Skip to main content
IBM Quantum Platform

QfFermionOperator

QfFermionOperator

struct QfFermionOperator

スピンを含まないフェルミオン演算子。

注

これは、C API からは内部構造が不透明なデータ構造であり、その内部は完全に Rust で実装されています。 このページの残りの部分では、この構造体を使用するための設計および関連する機能について説明します。



定義

この演算子は、スピンを持たないフェルミオンモードに作用するフェルミオン生成演算子および消滅演算子の積の線形結合によって定義される。 つまり、個々の項は以下の反交換関係を満たす: [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 は、それぞれが添字として付されているフェルミオンモードのスピン種を区別しない。

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

QfFermionOperator=∑ici⨂jAj^ ,\text{\texttt{QfFermionOperator}} = \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 みなされます。

注

これらの内部配列の読み取り専用コピー には、それぞれの関数を介してアクセスできます:

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

建設

上記で概説した対応する配列を指定することで、新しい演算子を直接構築することができます。 あるいは、空の を で初期化し qf_ferm_op_zero() 、 を通じて反復的に項を追加することもできます QfFermionOperatorqf_ferm_op_add_term() 。

コラム「 1 」
コラム「 2 」
qf_ferm_op_new()指定された配列から新しい演算子を構築します。
qf_ferm_op_zero()加法単位演算子を構築する。
qf_ferm_op_one()乗法単位演算子を構築します。
qf_ferm_op_add_term()既存の.に項を追加します QfFermionOperator。
注

A は を使って解放 QfFermionOperator できます qf_ferm_op_free()。

算数

以下の関数は、算術演算を行うためのものです:

コラム「 1 」
コラム「 2 」
qf_ferm_op_add()2つの演算子を足し合わせます。
qf_ferm_op_mul()演算子にスカラーを乗算します。
qf_ferm_op_compose()2つの演算子を互いに合成します。
qf_ferm_op_adjoint()エルミート共役演算子を返します。

操作

以下の関数は、演算子の操作ロジックを提供します:

コラム「 1 」
コラム「 2 」
qf_ferm_op_ichop()係数の絶対値が小さい項を除去します。
qf_ferm_op_simplify()同等だが簡略化された演算子を返します。
qf_ferm_op_normal_ordered()通常の順序を持つ項を持つ等価演算子を返します。
qf_ferm_op_relabel_modes()演算子のモードに新しいラベルを割り当てます。

プロパティ-

演算子の特定の性質を確認するために、以下の関数が用意されています。

コラム「 1 」
コラム「 2 」
qf_ferm_op_is_hermitian()演算子がエルミートであるかどうかを返します。
qf_ferm_op_max_rank()この演算子に含まれる項の最大ランクを返します。
qf_ferm_op_conserves_particle_number()演算子が粒子数保存であるかどうかを返します。

[ 1 ]

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


メンバー

qf_ferm_op_new

QfFermionOperator *qf_ferm_op_new(uint64_t num_terms, uint64_t num_actions, const QkComplex64 *coeffs, const bool *actions, const uint32_t *modes, const uint32_t *boundaries)

新しい演算子を構築します。

ポインタ引数のいずれかが となるのは、それに対応する長さがゼロである場合 NULL に限られる。

例

1uint64_t num_terms = 3;
2uint64_t num_actions = 4;
3bool actions[4] = {true, false, true, false};
4uint32_t modes[4] = {0, 1, 2, 3};
5QkComplex64 coeffs[3] = {{1.0, 0.0}, {-1.0, 0.0}, {0.0, -1.0}};
6uint32_t boundaries[4] = {0, 0, 2, 4};
7QfFermionOperator *op = qf_ferm_op_new(num_terms, num_actions, coeffs,
8                                       actions, modes, boundaries);

パラメーター

  • num_terms – 演算子に含まれる項の数。
  • num_actions – すべての項について合計したアクションの数。
  • coeffs – 項の係数の配列へのポインタ。 この配列の長さは であるべきです num_terms。
  • アクション – すべての項にわたるアクションの配列へのポインタ。 この配列の長さは であるべきです num_actions。
  • modes – すべての項にわたるアクションモードの配列へのポインタ。 この配列の長さは であるべきです num_actions。
  • 境界 – 項間の境界の配列へのポインタ。 この配列の長さは であるべきです num_terms + 1。

qf_ferm_op_free

void qf_ferm_op_free(QfFermionOperator *op)

既存の演算子を解放します。

例

1QfFermionOperator *op = qf_ferm_op_one();
2qf_ferm_op_free(op);

パラメーター

  • op – 解放対象のフェルミオン演算子へのポインタ。

qf_ferm_op_get_coeffs

void qf_ferm_op_get_coeffs(const QfFermionOperator *op, QkComplex64 **coeffs_out, uint64_t *coeffs_len)

演算子の係数に対して読み取り専用のアクセス権限を提供します。

関連資料

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

例

 1uint64_t num_terms = 2;
 2uint64_t num_actions = 0;
 3QkComplex64 coeffs[2] = {{1.0, 0.0}, {0.0, -1.0}};
 4uint32_t boundaries[3] = {0, 0, 0};
 5QfFermionOperator *op =
 6    qf_ferm_op_new(num_terms, num_actions, coeffs, NULL, NULL, boundaries);
 7
 8QkComplex64 *coeffs_out;
 9uint64_t *coeffs_len;
10
11qf_ferm_op_get_coeffs(op, &coeffs_out, &coeffs_len);
12
13assert(coeffs_len == 2);
注

この関数は、内部データのコピーを返します。

パラメーター

  • op – アクセスする係数を持つフェルミオン演算子へのポインタ。
  • coeffs_out – 係数を書き込む複素数の配列へのポインタ。
  • coeffs_len – 出力配列の長さを書き込む整数変数へのポインタ。

qf_ferm_op_get_actions

void qf_ferm_op_get_actions(const QfFermionOperator *op, bool **actions_out, uint64_t *actions_len)

オペレータの操作に対して読み取り専用のアクセス権限を提供します。

関連資料

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

例

 1uint64_t num_terms = 2;
 2uint64_t num_actions = 2;
 3bool actions[2] = {true, false};
 4uint32_t modes[2] = {0, 1};
 5QkComplex64 coeffs[2] = {{1.0, 0.0}, {0.0, -1.0}};
 6uint32_t boundaries[3] = {0, 0, 2};
 7QfFermionOperator *op =
 8    qf_ferm_op_new(num_terms, num_actions, coeffs, actions, modes, boundaries);
 9
10QkComplex64 *actions_out;
11uint64_t *actions_len;
12
13qf_ferm_op_get_actions(op, &actions_out, &actions_len);
14
15assert(actions_len == 2);
注

この関数は、内部データのコピーを返します。

パラメーター

  • op – アクセスする作用を持つフェルミオン演算子へのポインタ。
  • actions_out – アクションを書き込むブール値の配列へのポインタ。
  • actions_len – 出力配列の長さを書き込む整数変数へのポインタ。

qf_ferm_op_get_modes

void qf_ferm_op_get_modes(const QfFermionOperator *op, uint32_t **modes_out, uint64_t *modes_len)

オペレータの対象となるモードインデックスへの読み取り専用アクセスを提供します。

関連資料

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

例

 1uint64_t num_terms = 2;
 2uint64_t num_actions = 2;
 3bool actions[2] = {true, false};
 4uint32_t modes[2] = {0, 1};
 5QkComplex64 coeffs[2] = {{1.0, 0.0}, {0.0, -1.0}};
 6uint32_t boundaries[3] = {0, 0, 2};
 7QfFermionOperator *op =
 8    qf_ferm_op_new(num_terms, num_actions, coeffs, actions, modes, boundaries);
 9
10QkComplex64 *modes_out;
11uint64_t *modes_len;
12
13qf_ferm_op_get_modes(op, &modes_out, &modes_len);
14
15assert(modes_len == 2);
注

この関数は、内部データのコピーを返します。

パラメーター

  • op – アクセスするモードを持つフェルミオン演算子へのポインタ。
  • modes_out – モードを書き込むブール値の配列へのポインタ。
  • modes_len – 出力配列の長さを書き込む整数変数へのポインタ。

qf_ferm_op_get_boundaries

void qf_ferm_op_get_boundaries(const QfFermionOperator *op, size_t **boundaries_out, uint64_t *boundaries_len)

演算子の項間の境界を示すインデックスへの読み取り専用アクセスを提供します。

関連資料

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

例

 1uint64_t num_terms = 2;
 2uint64_t num_actions = 2;
 3bool actions[2] = {true, false};
 4uint32_t modes[2] = {0, 1};
 5QkComplex64 coeffs[2] = {{1.0, 0.0}, {0.0, -1.0}};
 6uint32_t boundaries[3] = {0, 0, 2};
 7QfFermionOperator *op =
 8    qf_ferm_op_new(num_terms, num_actions, coeffs, actions, modes, boundaries);
 9
10QkComplex64 *boundaries_out;
11uint64_t *boundaries_len;
12
13qf_ferm_op_get_boundaries(op, &boundaries_out, &boundaries_len);
14
15assert(boundaries_len == 3);
注

この関数は、内部データのコピーを返します。

パラメーター

  • op – アクセスする境界を持つフェルミオン演算子へのポインタ。
  • boundaries_out – 境界値を書き込むブール値の配列へのポインタ。
  • boundaries_len – 出力配列の長さを書き込む整数変数へのポインタ。

qf_ferm_op_num_support

uint32_t qf_ferm_op_num_support(const QfFermionOperator *op)

演算子の支持集合のサイズを取得します。

これを使用して qf_ferm_op_get_support()、独自の長さを報告しない の出力バッファのサイズを設定します。

例

1bool actions[3] = {true, false, true};
2uint32_t modes[3] = {2, 0, 2};
3QkComplex64 coeffs[2] = {{1.0, 0.0}, {1.0, 0.0}};
4uint32_t boundaries[3] = {0, 2, 3};
5QfFermionOperator *op = qf_ferm_op_new(2, 3, coeffs, actions, modes, boundaries);
6
7uint32_t num_support = qf_ferm_op_num_support(op);
8
9assert(num_support == 2);

パラメーター

  • op – サポートサイズを取得するフェルミオン演算子へのポインタ。

戻り値

演算子が作用する異なるモード指標の数。

qf_ferm_op_get_support

void qf_ferm_op_get_support(const QfFermionOperator *op, uint32_t *support_out)

演算子のサポート、すなわち、その演算子が作用するモードインデックスを取得します。

添字は昇順で記述され、その添字に作用する項がいくつあろうと、各添字は厳密に1回だけ現れます。

例

 1bool actions[3] = {true, false, true};
 2uint32_t modes[3] = {2, 0, 2};
 3QkComplex64 coeffs[2] = {{1.0, 0.0}, {1.0, 0.0}};
 4uint32_t boundaries[3] = {0, 2, 3};
 5QfFermionOperator *op = qf_ferm_op_new(2, 3, coeffs, actions, modes, boundaries);
 6
 7uint32_t num_support = qf_ferm_op_num_support(op);
 8uint32_t *support_out = malloc(num_support * sizeof(uint32_t));
 9
10qf_ferm_op_get_support(op, support_out);
11
12assert(support_out[0] == 0);
13assert(support_out[1] == 2);
14
15free(support_out);
注

他のゲッターとは異なり、このゲッターは演算子へのポインタを返しません。サポートは事前に保存されるのではなく、必要に応じて計算されるため、呼び出し側が出力バッファを用意する必要があります。 まず qf_ferm_op_num_support() 、その必要な長さを照会します。

パラメーター

  • op – 取得するサポートを持つフェルミオン演算子へのポインタ。
  • support_out – サポートを書き込む整数配列へのポインタ。 サイズは少なくとも :c:func:qf_ferm_op_num_support 個の要素になるように設定する必要があります。

qf_ferm_op_zero

QfFermionOperator *qf_ferm_op_zero(void)

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

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

例

1QfFermionOperator *zero = qf_ferm_op_zero();
2
3QfFermionOperator *op_plus_zero = qf_ferm_op_add(op, zero);
4
5assert(qf_ferm_op_equal(op, op_plus_zero));

戻り値

作成された演算子へのポインタ。

qf_ferm_op_one

QfFermionOperator *qf_ferm_op_one(void)

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

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

例

1QfFermionOperator *one = qf_ferm_op_one();
2
3QfFermionOperator *op_times_one = qf_ferm_op_compose(op, one);
4
5assert(qf_ferm_op_equal(op, op_times_one));

戻り値

作成された演算子へのポインタ。

qf_ferm_op_has_groups

bool qf_ferm_op_has_groups(const QfFermionOperator *op)

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

関連資料

グループ演算子の用語に関する説明:演算子の構造を使用してください。

例

1QfFCIDump *fcidump = NULL;
2qf_fcidump_from_file("molecule.fcidump", &fcidump);
3QfFermionOperator *op = qf_ferm_op_from_fcidump(fcidump);
4
5bool has_groups = qf_ferm_op_has_groups(op);
6
7assert(!has_groups);

パラメーター

  • op – チェック対象のフェルミオン演算子へのポインタ。

戻り値

指定された演算子に 属性 groups があるかどうか。

qf_ferm_op_num_groups

uint32_t qf_ferm_op_num_groups(const QfFermionOperator *op)

演算子からグループ数を取得します。

関連資料

グループ演算子の用語に関する説明:演算子の構造を使用してください。

例

1QfFCIDump *fcidump = NULL;
2qf_fcidump_from_file("molecule.fcidump", &fcidump);
3QfFermionOperator *op = qf_ferm_op_from_fcidump(fcidump);
4
5uint32_t num_groups = qf_ferm_op_num_groups(op);
注

グループの数は、出現する最大のグループインデックスに1を加えた値として、遅延評価されます。

パラメーター

  • op – 取得する群の数を持つフェルミオン演算子へのポインタ。

戻り値

演算子の属性 groups に基づくグループインデックスの数。

qf_ferm_op_get_groups

void qf_ferm_op_get_groups(const QfFermionOperator *op, uint32_t **groups_out, uint64_t *groups_len)

すべての演算子項のグループインデックスを取得します。

関連資料

グループ演算子の用語に関する説明:演算子の構造を使用してください。

例

1QfFermionOperator *op = ...;
2uint32_t *groups_out;
3uint32_t groups_len;
4
5qf_ferm_op_get_groups(op, &groups_out, &groups_len);

パラメーター

  • op – グループのインデックスを取得するフェルミオン演算子へのポインタ。
  • groups_out – グループインデックスを書き込む整数配列へのポインタ。
  • groups_len – 出力配列の長さを書き込む整数変数へのポインタ。

qf_ferm_op_set_groups

QfExitCode qf_ferm_op_set_groups(QfFermionOperator *op, const uint32_t *groups_in, uint64_t groups_len)

指定された演算子の属 groups 性を設定します。

この長さの検証はここで行われます。なぜなら、下流の処理で再検証される箇所がないからです。インデックスの数が少なすぎると、項とそのグループが一緒に反復処理される際に、末尾の項が黙って除外されてしまいます。一方、多すぎると、どの項にも含まれていないグループが報告 qf_ferm_op_num_groups() されてしまうことになります。

関連資料

グループ演算子の用語に関する説明:演算子の構造を使用してください。

例

1QfFermionOperator *op = ...;
2
3uint32_t num_terms = 4;
4uint32_t groups_in[4] = {0, 1, 0, 1};
5qf_ferm_op_set_groups(op, groups_in, num_terms);

パラメーター

  • op – 書き込む属性 groups を持つフェルミオン演算子へのポインタ。
  • groups_in – 演算子に書き込む整数 groups 配列へのポインタ。
  • groups_len – 配列 groups_in に含まれる項の数。

戻り値

終了コード。

  • QfExitCode_Success 成功した際に
  • QfExitCode_ValueError もし が演算子の項の数と異なる groups_len 場合

qf_ferm_op_del_groups

void qf_ferm_op_del_groups(QfFermionOperator *op)

指定された演算子から 属 groups 性を削除します。

関連資料

グループ演算子の用語に関する説明:演算子の構造を使用してください。

例

1QfFermionOperator *op = ...;
2
3qf_ferm_op_del_groups(op);

パラメーター

  • op – 削除する groups 属性を持つフェルミオン演算子へのポインタ。

qf_ferm_op_split_out_groups

void qf_ferm_op_split_out_groups(const QfFermionOperator *op, const uint32_t *group_indices, uint64_t num_indices, QfFermionOperator **group_ops_out)

この演算子を、その属性 groups に基づいて新しい演算子のリストに分割します。

における重複インデックスは、における出現回数ごとに1回書き込まれます group_indices``group_ops_out 。 総数に比べてごく少数のグループのみをリクエストする場合、すべてのグループをリクエストする場合に比べて大幅にコストが抑えられます。これは、リクエスト対象外のグループに属する用語は、どこにも追加されることなくスキップされるためです。

関連資料

グループ演算子の用語に関する説明:演算子の構造を使用してください。

例

 1uint64_t num_terms = 4;
 2uint64_t num_actions = 8;
 3bool actions[8] = {true, false, true, false, true, false, true, false};
 4uint32_t modes[8] = {0, 1, 2, 3, 1, 0, 3, 2};
 5QkComplex64 coeffs[4] = {{1.0, 0.0}, {1.0, 0.0}, {1.0, 0.0}, {1.0, 0.0}};
 6uint32_t boundaries[5] = {0, 2, 4, 6, 8};
 7QfFermionOperator *op =
 8    qf_ferm_op_new(num_terms, num_actions, coeffs, actions, modes, boundaries);
 9
10uint32_t groups_in[4] = {0, 1, 0, 1};
11qf_ferm_op_set_groups(op, groups_in, num_terms);
12
13// build every group, in index order
14QfFermionOperator *group_ops[2];
15qf_ferm_op_split_out_groups(op, NULL, 0, group_ops);
16
17// build only group 1
18uint32_t group_indices[1] = {1};
19QfFermionOperator *group_op[1];
20qf_ferm_op_split_out_groups(op, group_indices, 1, group_op);

パラメーター

  • op – 分離対象 groups となるフェルミオン演算子へのポインタ。
  • group_indices – 演算子を構築するグループインデックスの配列へのポインタ。出力順序は指定された順序に従う。 そうかもしれません NULL。その場合、すべてのグループはインデックスの順に構築されます(これは、すべてのインデックスを から :c:func:qf_ferm_op_num_groups 0 へ渡すことと同等です - 1)。
  • num_indices – 配列 group_indices に含まれるインデックスの数。 が group_indices の場合、無視される NULL。
  • group_ops_out – 要求された各グループの演算子を書き込む :c:struct:QfFermionOperator の配列へのポインタ。 が group_indices 非の num_indices ときは にNULL、が のときは :c:func:qf_ferm_op_num_groups にサイズ設定する必要があります NULL。

qf_ferm_op_add_term

void qf_ferm_op_add_term(QfFermionOperator *op, uint64_t num_actions, const bool *actions, const uint32_t *modes, const QkComplex64 *coeff)

既存の演算子に項を追加します。

ポインタ引数のいずれかが となるのは、それに対応する長さがゼロである場合 NULL に限られる。

警告

この関数は、演算子の属 groups 性を にリセットします NULL。

例

 1QfFermionOperator *one = qf_ferm_op_one();
 2
 3QfFermionOperator *op = qf_ferm_op_zero();
 4bool actions[0] = {};
 5uint32_t modes[0] = {};
 6QkComplex64 coeff = {1.0, 0.0};
 7
 8qf_ferm_op_add_term(op, 0, actions, modes, &coeff);
 9
10assert(qf_ferm_op_equal(op, one));

パラメーター

  • op – 変更対象のフェルミオン演算子へのポインタ。
  • num_actions – actions 配列の長さ。
  • アクション – アクションの配列へのポインタ。 この配列の長さは であるべきです num_actions。
  • modes – アクションモードの配列へのポインタ。 この配列の長さは であるべきです num_actions。
  • coeff – 複素係数を指すポインタ。

qf_ferm_op_add

QfFermionOperator *qf_ferm_op_add(const QfFermionOperator *left, const QfFermionOperator *right)

2つの演算子を足し合わせます。

例

1QfFermionOperator *one = qf_ferm_op_one();
2QfFermionOperator *zero = qf_ferm_op_zero();
3
4QfFermionOperator *result = qf_ferm_op_add(one, zero);
5
6assert(qf_ferm_op_equal(result, one));

パラメーター

  • left – 左演算子へのポインタ。
  • right – right 演算子へのポインタ。

戻り値

結果となる演算子へのポインタ。

qf_ferm_op_scaled_add

QfFermionOperator *qf_ferm_op_scaled_add(const QfFermionOperator *left, const QfFermionOperator *right, const QkComplex64 *factor)

2つの演算子を足し合わせ、右側の演算子の係数をスケーリングします。

これにより、スケーリングが加算処理に統合されるため、単に right 追加するためだけに完全にスケーリングされたコピーを作成する必要がなくなります。 係数を乗じると、結果 -1 として引き算が行われることになるため、個別の引き算関数は用意されていません。

例

1QfFermionOperator *one = qf_ferm_op_one();
2QfFermionOperator *other = qf_ferm_op_one();
3
4// Subtracting via a factor of -1 leaves the two terms cancelling each other out.
5QkComplex64 factor = {-1.0, 0.0};
6QfFermionOperator *result = qf_ferm_op_scaled_add(one, other, &factor);
7
8QfFermionOperator *simplified = qf_ferm_op_simplify(result, 1e-10);
9assert(qf_ferm_op_len(simplified) == 0);
注

つまり qf_ferm_op_add()、これは の項を追加するだけで、 の項と組み合わせるわけではない right ため left、結果にはグループインデックスは含まれません。 後で同等の条件 qf_ferm_op_simplify() で着信料負担の電話をかけてください。

パラメーター

  • left – 左演算子へのポインタ。
  • right – right 演算子へのポインタ。
  • 因子 – 右辺演算子の係数をスケーリングするための因子へのポインタ。

戻り値

結果として得られる演算子へのポインタ、 left + factor * right。

qf_ferm_op_add_inplace

void qf_ferm_op_add_inplace(QfFermionOperator *left, const QfFermionOperator *right)

ある演算子を別の演算子に、その場で追加します。

のインプレース版であり qf_ferm_op_add()、新しく割り当てられた結果変数 left へのコピーを省略します。

警告

この関数は、演算子の属 groups 性を にリセットします NULL。

例

1QfFermionOperator *left = qf_ferm_op_one();
2QfFermionOperator *right = qf_ferm_op_one();
3
4qf_ferm_op_add_inplace(left, right);
5
6assert(qf_ferm_op_len(left) == 2);

パラメーター

  • left – 追加先の演算子へのポインタ。
  • right – 加算する演算子へのポインタ。

qf_ferm_op_scaled_add_inplace

void qf_ferm_op_scaled_add_inplace(QfFermionOperator *left, const QfFermionOperator *right, const QkComplex64 *factor)

ある演算子を別の演算子にその場で追加し、右側の演算子の係数をスケーリングします。

のインプレース版であり qf_ferm_op_scaled_add()、結果を割り当て left + factor * right ずに を計算する。 そこで、ある係数が差し引かれます -1 。

警告

この関数は、演算子の属 groups 性を にリセットします NULL。

例

1QfFermionOperator *left = qf_ferm_op_one();
2QfFermionOperator *right = qf_ferm_op_one();
3
4// Subtract, leaving two terms that cancel each other out.
5QkComplex64 factor = {-1.0, 0.0};
6qf_ferm_op_scaled_add_inplace(left, right, &factor);
7
8QfFermionOperator *simplified = qf_ferm_op_simplify(left, 1e-10);
9assert(qf_ferm_op_len(simplified) == 0);

パラメーター

  • left – 追加先の演算子へのポインタ。
  • right – 加算する演算子へのポインタ。
  • 因子 – 右辺演算子の係数をスケーリングするための因子へのポインタ。

qf_ferm_op_mul_inplace

void qf_ferm_op_mul_inplace(QfFermionOperator *op, const QkComplex64 *scalar)

演算子にスカラーを掛け合わせ、その場で結果を更新します。

のインプレース版であり qf_ferm_op_mul()、演算子を新たに割り当てられた結果変数にコピーする手間を省くことができます。

例

1QfFermionOperator *op = qf_ferm_op_one();
2QkComplex64 scalar = {2.0, 0.0};
3
4qf_ferm_op_mul_inplace(op, &scalar);
注

上記の2つのインプレース追加とは異なり、この方法では 属性 groups が保持されます。係数をスケーリングしても、項の数は変わらず、したがって「1項あたり1インデックス」という不変性も損なわれません。

パラメーター

  • op – 拡大・縮小を行う演算子へのポインタ。
  • スカラー – スカラーへのポインタ。

qf_ferm_op_mul

QfFermionOperator *qf_ferm_op_mul(const QfFermionOperator *op, const QkComplex64 *scalar)

演算子にスカラーを乗算します。

例

 1QfFermionOperator *one = qf_ferm_op_one();
 2QkComplex64 coeff = {2.0, 0.0};
 3QfFermionOperator *result = qf_ferm_op_mul(one, &coeff);
 4
 5QfFermionOperator *expected = qf_ferm_op_zero();
 6bool actions[0] = {};
 7uint32_t modes[0] = {};
 8qf_ferm_op_add_term(expected, 0, actions, modes, &coeff);
 9
10assert(qf_ferm_op_equal(result, expected));

パラメーター

  • op – 演算子へのポインタ。
  • スカラー – スカラーへのポインタ。

戻り値

結果となる演算子へのポインタ。

qf_ferm_op_compose

QfFermionOperator *qf_ferm_op_compose(const QfFermionOperator *left, const QfFermionOperator *right)

2つの演算子を互いに合成します。

例

1QfFermionOperator *one = qf_ferm_op_one();
2QfFermionOperator *zero = qf_ferm_op_zero();
3
4QfFermionOperator *result = qf_ferm_op_compose(one, zero);
5
6assert(qf_ferm_op_equal(result, zero));
注

2つの演算子からなる式は、たとえ両方のオペランドがグループ化されていても、グループを追跡することはありません。

パラメーター

  • left – 左演算子へのポインタ。
  • right – right 演算子へのポインタ。

戻り値

へのポインタ left.compose(right)。これは、行列乗算 を用いて result = right @ left 、演算子 と等しくなる @。 つまり、 が先に適用される right 。 を得るには left @ right、引数の順序を入れ替えます。

qf_ferm_op_adjoint

QfFermionOperator *qf_ferm_op_adjoint(const QfFermionOperator *op)

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

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

  • 各項における作用は順序が逆転し、生成と消滅が交互に繰り返される
  • 係数は複素共役である

例

 1QfFermionOperator *op = qf_ferm_op_zero();
 2bool actions[0] = {};
 3uint32_t modes[0] = {};
 4QkComplex64 coeff = {0.0, 1.0};
 5qf_ferm_op_add_term(op, 0, actions, modes, &coeff);
 6
 7QfFermionOperator *adjoint = qf_ferm_op_adjoint(op);
 8
 9QfFermionOperator *expected = qf_ferm_op_zero();
10QkComplex64 coeff_adj = {0.0, -1.0};
11qf_ferm_op_add_term(expected, 0, actions, modes, &coeff_adj);
12
13assert(qf_ferm_op_equal(adjoint, expected));

パラメーター

  • op – 演算子へのポインタ。

戻り値

作成された演算子へのポインタ。

qf_ferm_op_ichop

void qf_ferm_op_ichop(QfFermionOperator *op, double atol)

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

警告

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

例

 1QfFermionOperator *op = qf_ferm_op_zero();
 2bool actions[0] = {};
 3uint32_t modes[0] = {};
 4QkComplex64 coeff = {1e-8};
 5qf_ferm_op_add_term(op, 0, actions, modes, &coeff);
 6
 7qf_ferm_op_ichop(op, 1e-6);
 8
 9QfFermionOperator *expected = qf_ferm_op_zero();
10
11assert(qf_ferm_op_equal(op, expected));

パラメーター

  • op – 演算子へのポインタ。
  • atol – 係数の切り捨てに対する絶対許容誤差。

qf_ferm_op_simplify

QfFermionOperator *qf_ferm_op_simplify(const QfFermionOperator *op, double atol)

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

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

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

 1uint64_t num_terms = 100000;
 2uint64_t num_actions = 0;
 3bool actions[0] = {};
 4uint32_t modes[0] = {};
 5QkComplex64 coeffs[100000];
 6uint32_t boundaries[100001];
 7for (int i = 0; i < 100000; i++) {
 8  coeffs[i].re = 1e-5;
 9  coeffs[i].im = 0.0;
10  boundaries[i] = 0;
11}
12boundaries[100000] = 0;
13QfFermionOperator *op = qf_ferm_op_new(num_terms, num_actions, coeffs,
14                                       actions, modes, boundaries);
15
16QfFermionOperator *canon = qf_ferm_op_simplify(op, 1e-4);
17
18QfFermionOperator *one = qf_ferm_op_one();
19bool canon_is_equal = qf_ferm_op_equiv(canon, one, 1e-6);
20
21qf_ferm_op_ichop(op, 1e-4);
22
23QfFermionOperator *zero = qf_ferm_op_zero();
24bool ichop_is_equal = qf_ferm_op_equiv(op, zero, 1e-6);

パラメーター

  • op – 簡略化するフェルミオン演算子へのポインタ。
  • atol – 係数の切り捨てに対する絶対許容誤差。

戻り値

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

qf_ferm_op_normal_ordered

QfFermionOperator *qf_ferm_op_normal_ordered(const QfFermionOperator *op, const bool *sandwich)

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

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

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

例

 1QfFermionOperator *op = qf_ferm_op_zero();
 2bool actions[4] = {false, true, false, true};
 3uint32_t modes[4] = {1, 1, 0, 0};
 4QkComplex64 coeff = {1.0, 0.0};
 5qf_ferm_op_add_term(op, 4, actions, modes, &coeff);
 6
 7QfFermionOperator *normal_ordered = qf_ferm_op_normal_ordered(op, NULL);
 8
 9uint64_t num_terms = 4;
10uint64_t num_actions = 8;
11bool actions_exp[8] = {true, false, true, false, true, true, false, false};
12uint32_t modes_exp[8] = {0, 0, 1, 1, 1, 0, 1, 0};
13QkComplex64 coeffs_exp[4] = {
14    {1.0, 0.0}, {-1.0, 0.0}, {-1.0, 0.0}, {-1.0, 0.0}};
15uint32_t boundaries_exp[5] = {0, 0, 2, 4, 8};
16QfFermionOperator *expected =
17    qf_ferm_op_new(num_terms, num_actions, coeffs_exp, actions_exp,
18                   modes_exp, boundaries_exp);
19
20assert(qf_ferm_op_equal(normal_ordered, expected));
注

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

パラメーター

  • op – 演算子へのポインタ。
  • sandwich – ブール値へのポインタ。 このポインタは…である可能性があります NULL。

戻り値

作成された演算子へのポインタ。

qf_ferm_op_is_hermitian

bool qf_ferm_op_is_hermitian(const QfFermionOperator *op, double atol)

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

例

 1QfFermionOperator *op = qf_ferm_op_zero();
 2bool actions1[2] = {true, false};
 3uint32_t modes1[2] = {0, 1};
 4QkComplex64 coeff1 = {0.0, 1.00001};
 5qf_ferm_op_add_term(op, 2, actions1, modes1, &coeff1);
 6bool actions2[2] = {true, false};
 7uint32_t modes2[2] = {1, 0};
 8QkComplex64 coeff2 = {0.0, -1};
 9qf_ferm_op_add_term(op, 2, actions2, modes2, &coeff2);
10
11assert(qf_ferm_op_is_hermitian(op, 1e-4));
12assert(!qf_ferm_op_is_hermitian(op, 1e-8));
注

このチェックは、と op 、その、 qf_ferm_op_adjoint() およびの qf_ferm_op_normal_ordered() 差 qf_ferm_op_equiv() を用いて実装されています qf_ferm_op_zero()。

パラメーター

  • op – チェック対象のフェルミオン演算子へのポインタ。
  • atol – 係数が等しいとみなされる絶対許容誤差。

戻り値

指定された演算子がエルミート演算子であるかどうか。

qf_ferm_op_max_rank

uint32_t qf_ferm_op_max_rank(const QfFermionOperator *op)

演算子の最大位数を確認します。

例

1QfFermionOperator *op = qf_ferm_op_zero();
2bool actions[4] = {true, false, true, false};
3uint32_t modes[4] = {0, 1, 2, 3};
4QkComplex64 coeff = {1.0, 0.0};
5qf_ferm_op_add_term(op, 4, actions, modes, &coeff);
6
7assert(qf_ferm_op_max_rank(op), 4);
注

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

パラメーター

  • op – チェック対象のフェルミオン演算子へのポインタ。

戻り値

演算子の最大ランク。

qf_ferm_op_conserves_particle_number

bool qf_ferm_op_conserves_particle_number(const QfFermionOperator *op)

演算子が粒子数保存であるかどうかを調べます。

これは、すべてのモードを単一のブロックとして扱うという qf_ferm_op_conserves_sector() 、その特殊なケースです。 その関数を使用することで、モードブロック内でも保存則を満たすことを追加で要求できます。例えば、粒子数に加えてスピンのz成分の保存則が満たされているかを確認する場合などが挙げられます。

例

 1// A hopping term conserves the particle number, ...
 2QfFermionOperator *op = qf_ferm_op_zero();
 3bool actions[2] = {true, false};
 4uint32_t modes[2] = {0, 2};
 5QkComplex64 coeff = {1.0, 0.0};
 6qf_ferm_op_add_term(op, 2, actions, modes, &coeff);
 7
 8assert(qf_ferm_op_conserves_particle_number(op));
 9
10// ... whereas a bare creation operator does not.
11QfFermionOperator *cre = qf_ferm_op_zero();
12bool cre_actions[1] = {true};
13uint32_t cre_modes[1] = {0};
14qf_ferm_op_add_term(cre, 1, cre_actions, cre_modes, &coeff);
15
16assert(!qf_ferm_op_conserves_particle_number(cre));

パラメーター

  • op – チェック対象のフェルミオン演算子へのポインタ。

戻り値

与えられた演算子が粒子数の保存を満たすかどうか。

qf_ferm_op_conserves_sector

bool qf_ferm_op_conserves_sector(const QfFermionOperator *op, const uint32_t *block_sizes, uint64_t num_blocks)

演算子が各モードブロック内で粒子数を保存しているかどうかを確認します。

モード範囲を、連続し、互いに重ならないブロックに分割 block_sizes する。ブロック はモード から までを網羅 b し、 [start_b, start_b + block_sizes[b]) ここで はそれ以前のすべてのブロックのサイズの合計である start_b 。 ある項がセクターを保つのは、 すべてのブロックにおいて、その生成演算子の数が消滅演算子の数と等しい場合に限られる。 最後のブロックを超えるモードに作用する項は、そのカウントを相殺できるブロックが存在しないため、セクターを保存することは決してありません。

空間 norb 軌道がスピン軌道配置をとる場合、 はスピンを持たない系の粒子数を検証 [norb] するのに対し、 はアルファブロック と [0, norb) ベータブロック がそれぞれ個別に保存される [norb, 2 * norb) ことを要求 [norb, norb] する。すなわち、粒子数とスピンの z 成分の両方が厳密に保存されることを要求する。

例

 1// This term hops an electron from the beta block into the alpha block.
 2QfFermionOperator *op = qf_ferm_op_zero();
 3bool actions[2] = {true, false};
 4uint32_t modes[2] = {0, 2};
 5QkComplex64 coeff = {1.0, 0.0};
 6qf_ferm_op_add_term(op, 2, actions, modes, &coeff);
 7
 8// The total particle number is conserved, ...
 9uint32_t one_block[1] = {4};
10assert(qf_ferm_op_conserves_sector(op, one_block, 1));
11assert(qf_ferm_op_conserves_sector(op, NULL, 0));
12
13// ... but the two spin sectors are not conserved individually.
14uint32_t spin_blocks[2] = {2, 2};
15assert(!qf_ferm_op_conserves_sector(op, spin_blocks, 2));
注

passing NULL (set を に設定 num_blocks した場合 0)では、すべてのモードが 1 つの境界のないブロックとして扱われるため、これは と同等になります qf_ferm_op_conserves_particle_number()。

パラメーター

  • op – チェック対象のフェルミオン演算子へのポインタ。
  • block_sizes – モード範囲を分割するブロックサイズの配列へのポインタ。 すべてのモードを単一のブロックとして扱う NULL ことも考えられます。
  • num_blocks – 配列 block_sizes 内の要素数。

戻り値

指定された演算子が、各ブロック内で粒子数を保存するかどうか。

qf_ferm_op_equal

bool qf_ferm_op_equal(const QfFermionOperator *left, const QfFermionOperator *right)

2つの演算子の等価性を比較する。

例

1QfFermionOperator *one = qf_ferm_op_one();
2QfFermionOperator *zero = qf_ferm_op_zero();
3
4assert(qf_ferm_op_equal(one, one));
5assert(!qf_ferm_op_equal(one, zero));

パラメーター

  • left – 左演算子へのポインタ。
  • right – right 演算子へのポインタ。

戻り値

2つの演算子が等しいかどうか。

qf_ferm_op_equiv

bool qf_ferm_op_equiv(const QfFermionOperator *left, const QfFermionOperator *right, double atol)

2つの演算子の等価性を比較する。

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

例

 1QfFermionOperator *zero = qf_ferm_op_zero();
 2
 3QfFermionOperator *op = qf_ferm_op_zero();
 4bool actions[0] = {};
 5uint32_t modes[0] = {};
 6QkComplex64 coeff = {1e-7, 0.0};
 7qf_ferm_op_add_term(op, 0, actions, modes, &coeff);
 8
 9assert(qf_ferm_op_equiv(op, zero, 1e-6));
10assert(!qf_ferm_op_equiv(op, zero, 1e-8));

パラメーター

  • left – 左演算子へのポインタ。
  • right – right 演算子へのポインタ。
  • atol – 係数等価性の絶対許容誤差。

戻り値

この2つの演算子が等価であるかどうか。

qf_ferm_op_len

size_t qf_ferm_op_len(const QfFermionOperator *op)

指定された演算子の長さ(または項の数)を返します。

例

1QfFermionOperator *op = qf_ferm_op_zero();
2bool actions[4] = {true, false, true, false};
3uint32_t modes[4] = {0, 1, 2, 3};
4QkComplex64 coeff = {1.0, 0.0};
5qf_ferm_op_add_term(op, 4, actions, modes, &coeff);
6
7assert(qf_ferm_op_len(op) == 1);

パラメーター

  • op – フェルミオン演算子へのポインタ。

戻り値

演算子の長さ(または項の数)。

qf_ferm_op_relabel_modes

QfExitCode qf_ferm_op_relabel_modes(QfFermionOperator *op, uint64_t num_modes, const uint32_t *permutation)

指定された演算子のインデックスに新しいラベルを割り当てます。

例

 1QfFermionOperator *op = qf_ferm_op_zero();
 2bool actions[4] = {true, false, true, false};
 3uint32_t indices[4] = {0, 1, 2, 3};
 4QkComplex64 coeff = {1.0, 0.0};
 5qf_ferm_op_add_term(op, 4, actions, indices, &coeff);
 6
 7uint32_t permutation[4] = {3, 2, 1, 0};
 8
 9QfExitCode exit = qf_ferm_op_relabel_modes(op, 4, permutation);
10
11assert(exit == QfExitCode_Success);

パラメーター

  • op – フェルミオン演算子へのポインタ。
  • num_modes – 指定された順列リストに含まれるモードインデックスの数。
  • 順列 – インデックスの順列リスト。

戻り値

終了コード。

  • QfExitCode_Success 成功した際に
  • QfExitCode_DuplicateIndexError 順列の中に重複するインデックスが見つかった場合
  • QfExitCode_IndexError 無効なインデックスなど、その他のインデックスに関するエラーについては。
このページは役に立ちましたか?
バグや誤字の報告、またはコンテンツの要求はGitHubで行ってください。