Skip to main content
IBM Quantum Platform

QkObs

typedef struct QkObs QkObs

qubit-sparseフォーマットでデータを保存するパウリ基底上の観測可能。


数学

この観測値は、パウリ作用素とパウリ固有状態射影体の文字列上の和を表し、各項はある複素数で重み付けされている。 つまり、完全な観測値は

QkObs=icinAi(n)\text{\texttt{QkObs}} = \sum_i c_i \bigotimes_n A^{(n)}_i

複素数 cic_i、制限されたアルファベット Ai(n)A^{(n)}_i からの量子ビット nn に作用する単一量子ビット演算子。 ii 上の和は個々の項の和であり、テンソル積は演算子文字列を生成する。 Ai(n)A^{(n)}_i、パウリ作用素とパウリ固有状態射影作用素のアルファベットから1量子ビットの作用素を選ぶ。 具体的には以下のようなものだ:

オペレーター
QkBitTerm
数値
II (アイデンティティ)保管されていない。保管されていない。
XX (パウリX)QkBitTerm_X0b0010 (2)
YY (パウリ・Y)QkBitTerm_Y0b0011 (3)
ZZ (パウリZ)QkBitTerm_Z0b0001 (1)
++\lvert+\rangle\langle+\rvert (Xの正の固有状態への射影)QkBitTerm_Plus0b1010 (10)
\lvert-\rangle\langle-\rvert (Xの負の固有状態への射影)QkBitTerm_Minus0b0110 (6)
rr\lvert r\rangle\langle r\rvert (Yの正の固有状態への射影)QkBitTerm_Right0b1011 (11)
ll\lvert l\rangle\langle l\rvert (Yの負の固有状態への射影)QkBitTerm_Left0b0111 (7)
00\lvert0\rangle\langle0\rvert (Zの正の固有状態への射影)QkBitTerm_Zero0b1001 (9)
11\lvert1\rangle\langle1\rvert (Zの負の固有状態への射影)QkBitTerm_One0b0101 (5)

ポーリスとその射影の両方を許容することにより、許容されるアルファベットは作用素空間の過完備な基底を形成する。 これは、与えられた観測値を表す一意的な和が存在しないことを意味する。 結果として、比較にはさらなる注意が必要であり、2つの数学的に等価な観測値に対して qk_obs_canonicalize

QkObs は、「測定の効率性」を「表現の効率性」と同等にすることを目的に、その特殊な過完備基礎を使用している。 例えば、観測可能な 00n{\lvert0\rangle\langle0\rvert}^{\otimes n} は、ハードウェア上では単純な ZZ 測定で効率的に測定できるが、ポーリスの項では (I+Z)n/2n{(I + Z)}^{\otimes n}/2^n のようにしか表現できない。これは 2n2^n 保存された項を必要とする。 QkObs これを保存するために必要な用語は1つだけである。 この欠点は、任意の行列を取り出して最良の QkObs 表現を見つけることが現実的でないことである。 通常、 QkObs 、分解するのではなく、直接構築することを望むだろう。


表現

QkObs の内部表現には、非同一量子ビット演算子のみが格納される。 QkObs このため、 nqubitsZ(n)\sum_{n\in \text{qubits}} Z^{(n)} のような観測値を表現するのに必要なメモリの量は、量子ビットの総数に比例する。 項は圧縮されて保存され、これはスパース行列の圧縮されたスパース行の形式と同じである。 このアナロジーでは、和の項が「行」で、量子ビットの項が「列」である。 より明確には、この表現は4つの連続した配列で構成されている:

アクセス可能な属性
長さ
説明
qk_obs_coeffstt各項の複素スカラー倍率。
qk_obs_bit_termsssすべての演算子の非同一1量子ビット項を順番に並べる。 これらは、和の記述における非同一性 Ai(n)A^{(n)}_i に対応し、エントリーは ii の増加順に最初に格納され、各項目内では nn の増加順に格納される。
qk_obs_indicesss各ビット項の対応する量子ビット( nn )。 QkObs は、このリストが項ごとにソートされていることを必要とし、アルゴリズムはこの不変性が維持されていることを信頼することができる。
qk_obs_boundariest+1t+1ビット項とインデックスを完全な項に分割するインデックス。 項番 ii、その複素係数はインデックス i に格納され、その非同一シングル量子ビット演算子と対応する量子ビットは、それぞれビット項とインデックスの範囲 [boundaries[i], boundaries[i+1]) にある。 境界線は常に最初の要素として明示的な0を持つ。

長さパラメータ tt は、合計の項数であり、 qk_obs_num_terms を使って問い合わせることができる。 パラメータ ss は、非同一シングル量子ビットの項の総数であり、 qk_obs_len を使って問い合わせることができる。

実例として:

  • ゼロ演算子の場合、境界は長さ1(0が1つ)で、それ以外のベクトルは空である。
  • 完全に簡略化された恒等演算子の場合、境界は {0, 0}、係数はシングル・エントリで、ビット項もインデックスも空である。
  • 演算子 Z2Z0X3Y1Z_2 Z_0 - X_3 Y_1、境界は {0, 2, 4}、係数は {1.0, -1.0}、ビット項は {QkBitTerm_Z, QkBitTerm_Z, QkBitTerm_Y, QkBitTerm_X} 、インデックスは {0, 2, 1, 3}。 演算子は、量子ビットの数に応じて、4つ以上の量子ビットに作用する可能性がある( qk_obs_num_qubits 参照)。 1ビットの項とインデックスは項ごとにソートされていることに注意。

これらのケースは特別なものではなく、ルールに完全に合致しており、特別な扱いをする必要はないはずだ。

正則順序

任意の数学的可観測量について、それを QkObs で表現する方法はいくつかある。 例えば、同じ1ビットの項とそれに対応するインデックスは、観測可能な中に複数回現れるかもしれない。 数学的には、これはすべての係数を合計した単一の項だけを持つことと同じである。 同様に、 QkObs の和の項は、加算が可換であるため、同じ観測値を表しながら、どのような順序であってもよい(ただし、浮動小数点数の加算は可換ではないため、 QkObs は和の順序を保証しない)。

これら2つのカテゴリーに分類される表現縮退は、演算子の等式( qk_obs_equal )により、同じ対象を表現しているにもかかわらず、2つの観測値が等しくないという主張を引き起こす可能性がある。 このような場合、観測値を構造的に比較できるような正準形式を定義しておくと便利である。 qk_obs_canonicalize 関数を使えば、 QkObs を正準形式にすることができる。 正準順序における用語の正確な順序は指定されておらず、Qiskitのバージョン間で変更される可能性がある。 しかし、同じバージョンのQiskitでは、2つのobservableを構造的に比較することができます。

比較の際に浮動小数点数の許容誤差を考慮したい場合は、次のようなレシピを使うのが最も安全である:

bool equivalent(QkObs *left, QkObs *right, double tol) {
  // compare a canonicalized version of left - right to the zero observable
  QkObs *neg_right = qk_obs_multiply(right, &(QkComplex64){-1, 0});
  QkObs *diff = qk_obs_add(left, neg_right);
  QkObs *canonical = qk_obs_canonicalize(diff, tol);

  QkObs *zero = qk_obs_zero(qk_obs_num_qubits(left));
  bool equiv = qk_obs_equal(diff, zero);
  // free all temporary variables
  qk_obs_free(neg_right);
  qk_obs_free(diff);
  qk_obs_free(canonical);
  qk_obs_free(zero);
  return equiv;
}

qk_obs_canonicalize によって生成される正準形式だけでは、過完備な基底アルファベットのために、等価なすべての観測量を普遍的に検出することはできない。

索引付け

QkObs の個々の観測可能な和項は、 qk_obs_term を介してアクセスでき、 QkObsTerm 型のオブジェクトを返す。 これらの項には、項の係数、ビット項、インデックス、定義されている量子ビット数を示すフィールドが含まれる。 項数の情報と合わせて、次のようにすべての観測項を反復処理することができる

size_t num_terms = qk_obs_num_terms(obs);  // obs is QkObs*
for (size_t i = 0; i < num_terms; i++) {
    QkObsTerm term;  // allocate term on stack
    int exit = qk_obs_term(obs, i, &term);  // get the term (exit > 0 upon index errors)
    // do something with the term...
}
警告

qk_obs_term 経由で QkObsTerm にデータを入力すると、元の QkObs のデータが参照される。 ビット項やインデックスを変更すると、観測値が変化し、インコヒーレントな状態になる可能性がある。


建設

QkObs は、空の観測値( qk_obs_zero )を初期化し、項( qk_obs_add_term )を繰り返し追加することで構築できる。 あるいは、すべての内部データが指定されていれば、"生 "データ( qk_obs_new )から観測値を構築することもできる。 そのためには、データが首尾一貫したものであり、有効な観測結果をもたらすように注意する必要がある。

関数
サマリー
qk_obs_zero与えられた数の量子ビットで空の観測値を構築する。
qk_obs_identity指定された数の量子ビットでID観測可能を構築する。
qk_obs_new生のデータ配列から observable を構築する。

数学的操作

QkObs は、観測値間やスカラーを使った基本的な算術演算をサポートしている。 できること:

  • qk_obs_add を使用して2つのオブザーバブルを追加する qk_obs_add_inplace
  • 複素数で乗算する qk_obs_multiply qk_obs_multiply_inplace
  • qk_obs_compose 、2つの観測値を合成(乗算)する。 qk_obs_compose_map
  • 2つの観測量と複素スカラー left + scalar * right について、 qk_obs_scaled_add および qk_obs_scaled_add_inplace

関数

qk_obs_zero

QkObs *qk_obs_zero(uint32_t num_qubits)

項のない)ゼロの観測値を構築する。

QkObs *zero = qk_obs_zero(100);

パラメーター

  • num_qubits - 観測可能な量子ビットの数。

戻り値

作成されたobservableへのポインタ。

qk_obs_identity

QkObs *qk_obs_identity(uint32_t num_qubits)

ID観測器を構築する。

QkObs *identity = qk_obs_identity(100);

パラメーター

  • num_qubits - 観測可能な量子ビットの数。

戻り値

作成されたobservableへのポインタ。

qk_obs_new

QkObs *qk_obs_new(uint32_t num_qubits, uint64_t num_terms, uint64_t num_bits, QkComplex64 *coeffs, QkBitTerm *bit_terms, uint32_t *indices, size_t *boundaries)

生データから新しい観測値を構築する。

ポインタ引数のいずれかについて、その対応する長さがゼロである場合に限り、その引 NULL 数はNULLである可能性があります。

// define the raw data for the 100-qubit observable |01><01|_{0, 1} - |+-><+-|_{98, 99}
uint32_t num_qubits = 100;
uint64_t num_terms = 2;  // we have 2 terms: |01><01|, -1 * |+-><+-|
uint64_t num_bits = 4; // we have 4 non-identity bits: 0, 1, +, -
QkComplex64 coeffs = {1, -1};
QkBitTerm bits[4] = {QkBitTerm_Zero, QkBitTerm_One, QkBitTerm_Plus, QkBitTerm_Minus};

uint32_t indices[4] = {0, 1, 98, 99};  // <-- e.g. {1, 0, 99, 98} would be invalid
size_t boundaries[3] = {0, 2, 4};
QkObs *obs = qk_obs_new(
    num_qubits, num_terms, num_bits, &coeffs, bits, indices, boundaries
);

安全

以下の条件のいずれかに違反した場合、動作は未定義となる:

  • coeffs QkComplex64 へのポインタである。 num_terms
  • bit_terms は、有効な QkBitTerm 要素の配列へのポインタである。 num_bits
  • indices は長さ num_bitsuint32_t 配列へのポインタであり、この配列は厳密な昇順でソートされている。 num_qubits
  • boundaries は長さ num_terms + 1size_t 配列へのポインタであり、昇順にソートされている。 num_terms

パラメーター

  • num_qubits - 観測可能な量子ビットの数。
  • num_terms - 項目の数。
  • num_bits - 非同一ビット項の総数。
  • num_termsc oeffs - 係数配列の最初の要素へのポインタ.
  • bit_terms - ビット項配列の最初の要素へのポインタ。長さは num_bits である。
  • index - index 配列の最初の要素へのポインタ.長さは num_bits である. 用語ごとに、段階的に並べ替えなければならないことに注意。
  • boundaries - boundaries 配列の最初の要素へのポインタ.長さは num_terms + 1 です.

戻り値

入力データが首尾一貫しており、構築に成功した場合、結果はobservableへのポインタとなる。 そうでない場合はNULLポインタが返される。

qk_obs_free

void qk_obs_free(QkObs *obs)

観察可能なものを解放する。

QkObs *obs = qk_obs_zero(100);
qk_obs_free(obs);

安全

obs が NULL または QkObs への有効なポインタでない場合、動作は未定義となる。

パラメーター

  • obs - 解放する observable へのポインタ.

qk_obs_add_term

QkExitCode qk_obs_add_term(QkObs *obs, const QkObsTerm *cterm)

observableに用語を追加する。

uint32_t num_qubits = 100;
QkObs *obs = qk_obs_zero(num_qubits);

QkComplex64 coeff = {1, 0};
QkBitTerm bit_terms[3] = {QkBitTerm_X, QkBitTerm_Y, QkBitTerm_Z};
uint32_t indices[3] = {0, 1, 2};
QkObsTerm term = {coeff, 3, bit_terms, indices, num_qubits};

QkExitCode exit_code = qk_obs_add_term(obs, &term);

安全

以下のいずれかに違反した場合、動作は未定義となる:

  • obs への有効な非NULLポインタである。 QkObs
  • cterm への有効な非NULLポインタである。 QkObsTerm

パラメーター

  • obs - observableへのポインタ.
  • cterm - 追加する用語へのポインタ。

戻り値

終了コード。 これは、用語が支離滅裂であったり、用語の追加に失敗した場合に >0

qk_obs_term

QkExitCode qk_obs_term(QkObs *obs, uint64_t index, QkObsTerm *out)

参照によって観測可能な用語を取得する。

QkObsTerm は、observableの内部データを変更するために使用することができる用語のインデックスとビット項へのポインタを含んでいます。 このようなことは、観測対象を支離滅裂な状態にする可能性があるので、細心の注意を払わない限り避けるべきである。 一般的には、インプレースで変更を試みるのではなく、新しいobservableを構築する方が安全です。

QkObs *obs = qk_obs_identity(100);
QkObsTerm term;
QkExitCode exit_code = qk_obs_term(obs, 0, &term);
// out-of-bounds indices return an error code
// QkExitCode error = qk_obs_term(obs, 12, &term);

安全

以下のいずれかに違反した場合、動作は未定義となる

  • obs への有効な非NULLポインタである。 QkObs
  • out への有効な非NULLポインタである。 QkObsTerm

パラメーター

  • obs - observableへのポインタ.
  • index - 取得する用語のインデックス。
  • out - 観測項を返すための QkObsTerm へのポインタ。

戻り値

終了コード。

qk_obs_num_terms

size_t qk_obs_num_terms(const QkObs *obs)

observableの項の数を得る。

QkObs *obs = qk_obs_identity(100);
size_t num_terms = qk_obs_num_terms(obs);  // num_terms==1

安全

動作は未定義 obs は有効な、 QkObs への NULL ではないポインタではない。

パラメーター

  • obs - observableへのポインタ.

戻り値

観測値の項数。

qk_obs_num_qubits

uint32_t qk_obs_num_qubits(const QkObs *obs)

observableが定義されている量子ビットの数を取得します。

QkObs *obs = qk_obs_identity(100);
uint32_t num_qubits = qk_obs_num_qubits(obs);  // num_qubits==100

安全

動作は未定義 obs は有効な、 QkObs への NULL ではないポインタではない。

パラメーター

  • obs - observableへのポインタ.

戻り値

観測可能な量子ビットの数。

qk_obs_len

size_t qk_obs_len(const QkObs *obs)

observableのビット項/インデックスの数を取得します。

QkObs *obs = qk_obs_identity(100);
size_t len = qk_obs_len(obs);  // len==0, as there are no non-trivial bit terms

安全

動作は未定義 obs は有効な、 QkObs への NULL ではないポインタではない。

パラメーター

  • obs - observableへのポインタ.

戻り値

観測値の項数。

qk_obs_coeffs

QkComplex64 *qk_obs_coeffs(QkObs *obs)

係数へのポインタを取得する。

これはobservableの係数を読んだり変更したりするのに使われる。 結果として得られるポインタは、 QkComplex64qk_obs_num_terms(obs) 要素に対して有効である。

QkObs *obs = qk_obs_identity(100);
size_t num_terms = qk_obs_num_terms(obs);
QkComplex64 *coeffs = qk_obs_coeffs(obs);

for (size_t i = 0; i < num_terms; i++) {
    printf("%f + i%f\n", coeffs[i].re, coeffs[i].im);
}

安全

動作は未定義 obs は有効な、 QkObs への NULL ではないポインタではない。

パラメーター

  • obs - observableへのポインタ.

戻り値

係数へのポインタ。

qk_obs_indices

uint32_t *qk_obs_indices(QkObs *obs)

インデックスへのポインタを取得する。

これはobservableのインデックスを読んだり変更したりするのに使われます。 結果として得られるポインタは、サイズ uint32_tqk_obs_len(obs) 要素を読み出すのに有効である。

uint32_t num_qubits = 100;
QkObs *obs = qk_obs_zero(num_qubits);

QkComplex64 coeff = {1, 0};
QkBitTerm bit_terms[3] = {QkBitTerm_X, QkBitTerm_Y, QkBitTerm_Z};
uint32_t term_indices[3] = {0, 1, 2};
QkObsTerm term = {coeff, 3, bit_terms, term_indices, num_qubits};
qk_obs_add_term(obs, &term);

size_t len = qk_obs_len(obs);
uint32_t *indices = qk_obs_indices(obs);

for (size_t i = 0; i < len; i++) {
    printf("index %i: %i\n", i, indices[i]);
}

qk_obs_free(obs);

安全

動作は未定義 obs は有効な、 QkObs への NULL ではないポインタではない。

パラメーター

  • obs - observableへのポインタ.

戻り値

インデックスへのポインタ。

qk_obs_boundaries

size_t *qk_obs_boundaries(QkObs *obs)

用語境界へのポインタを取得する。

これはobservableの項境界を読んだり変更したりするのに使われます。 結果として得られるポインタは、サイズ size_tqk_obs_num_terms(obs) + 1 要素を読み出すのに有効である。

uint32_t num_qubits = 100;
QkObs *obs = qk_obs_zero(num_qubits);

QkComplex64 coeff = {1, 0};
QkBitTerm bit_terms[3] = {QkBitTerm_X, QkBitTerm_Y, QkBitTerm_Z};
uint32_t indices[3] = {0, 1, 2};
QkObsTerm term = {coeff, 3, bit_terms, indices, num_qubits};
qk_obs_add_term(obs, &term);

size_t num_terms = qk_obs_num_terms(obs);
size_t *boundaries = qk_obs_boundaries(obs);

for (size_t i = 0; i < num_terms + 1; i++) {
    printf("boundary %i: %i\n", i, boundaries[i]);
}

安全

動作は未定義 obs は有効な、 QkObs への NULL ではないポインタではない。

パラメーター

  • obs - observableへのポインタ.

戻り値

境界線へのポインタ。

qk_obs_bit_terms

QkBitTerm *qk_obs_bit_terms(QkObs *obs)

ビット項へのポインタを取得する。

これはobservableのビット項を読んだり変更したりするのに使われる。 結果として得られるポインタは、サイズ uint8_tqk_obs_len(obs) 要素を読み出すのに有効である。

uint32_t num_qubits = 100;
QkObs *obs = qk_obs_zero(num_qubits);

QkComplex64 coeff = {1, 0};
QkBitTerm bit_terms[3] = {QkBitTerm_X, QkBitTerm_Y, QkBitTerm_Z};
uint32_t indices[3] = {0, 1, 2};
QkObsTerm term = {coeff, 3, bit_terms, indices, num_qubits};
qk_obs_add_term(obs, &term);

size_t len = qk_obs_len(obs);
QkBitTerm *bits = qk_obs_bit_terms(obs);

for (size_t i = 0; i < len; i++) {
    printf("bit term %i: %i\n", i, bits[i]);
}

qk_obs_free(obs);

安全

「動作は未定義 obs 」とは、 QkObsが有効な、NULL以外のポインタでない場合、または結果として QkBitTerm 得られるポインタに無効な値が書き込まれる場合を指します。

パラメーター

  • obs - observableへのポインタ.

戻り値

ビット項へのポインタ。

qk_obs_multiply

QkObs *qk_obs_multiply(const QkObs *obs, const QkComplex64 *coeff)

観測値に複素係数を掛ける。

QkObs *obs = qk_obs_identity(100);
QkComplex64 coeff = {2, 0};
QkObs *result = qk_obs_multiply(obs, &coeff);

安全

以下のいずれかに違反した場合、動作は未定義となる

  • obs への有効な非NULLポインタである。 QkObs
  • coeff への有効な非NULLポインタである。 QkComplex64

パラメーター

  • obs - observableへのポインタ.
  • coeff - 観測値に乗じる係数.

戻り値

結果へのポインタ obs * coeff

qk_obs_multiply_inplace

void qk_obs_multiply_inplace(QkObs *obs, const QkComplex64 *coeff)

その場にある観測量を複素係数で乗算する。

QkObs *obs = qk_obs_identity(100);
QkComplex64 coeff = {2, 0};
qk_obs_multiply_inplace(obs, &coeff);

安全

以下のいずれかに違反した場合、動作は未定義となる

  • obs への有効な非NULLポインタである。 QkObs
  • coeff への有効な非NULLポインタである。 QkComplex64

パラメーター

  • obs - observableへのポインタ.
  • coeff - 観測値に乗じる係数.

qk_obs_add

QkObs *qk_obs_add(const QkObs *left, const QkObs *right)

2つのオブザーバブルを追加する。

QkObs *left = qk_obs_identity(100);
QkObs *right = qk_obs_zero(100);
QkObs *result = qk_obs_add(left, right);

安全

left QkObs または が有効でない場合、動作は未定義である。 right

パラメーター

  • left - 左側の観測値へのポインタ.
  • right - 右の観測値へのポインタ.

戻り値

結果へのポインタ left + right

qk_obs_add_inplace

void qk_obs_add_inplace(QkObs *left, const QkObs *right)

既存のオブザーバブルに新しいオブザーバブルを追加します。

QkObs *left = qk_obs_identity(100);
QkObs *right = qk_obs_zero(100);
qk_obs_add_inplace(left, right);

安全

left QkObs または が有効でない場合、動作は未定義である。 right

パラメーター

  • left - 左側の観測値へのポインタ.
  • right - 右の観測値へのポインタ.

qk_obs_scaled_add

QkObs *qk_obs_scaled_add(const QkObs *left, const QkObs *right, const QkComplex64 *factor)

2つのオブザーバブルを追加し、右側の係数をスケーリングします。

QkObs *left = qk_obs_zero(100);
QkObs *right = qk_obs_identity(100);
QkComplex64 factor = {2, 0};
QkObs *result = qk_obs_scaled_add(left, right, &factor);

安全

left QkObs または が有効でない場合、動作は未定義である。 right

パラメーター

  • left - 左側の観測値へのポインタ.
  • right - 右の観測値へのポインタ.
  • 係数 – 係数に掛ける係数。

戻り値

結果への所有 left + factor * rightポインタ。

qk_obs_scaled_add_inplace

void qk_obs_scaled_add_inplace(QkObs *left, const QkObs *right, const QkComplex64 *factor)

既存のオブザーバブルにスケーリングされたオブザーバブルを追加します。

QkObs *left = qk_obs_zero(100);
QkObs *right = qk_obs_identity(100);
QkComplex64 factor = {2, 0};
qk_obs_scaled_add_inplace(left, right, &factor);

安全

left QkObs または が有効でない場合、動作は未定義である。 right

パラメーター

  • left - 左側の観測値へのポインタ.
  • right - 右の観測値へのポインタ.
  • 係数 – 係数に掛ける係数。

qk_obs_compose

QkObs *qk_obs_compose(const QkObs *first, const QkObs *second)

2つの観測値を合成(乗算)する。

QkObs *first = qk_obs_zero(100);
QkObs *second = qk_obs_identity(100);
QkObs *result = qk_obs_compose(first, second);

安全

first QkObs または が有効でない場合、動作は未定義である。 second

パラメーター

  • first - 観測可能な1つ。
  • second - もう一つの観測可能なもの。

戻り値

first.compose(second) これは、観測可能な result = second @ first、行列の乗算 @ に等しい。

qk_obs_compose_map

QkObs *qk_obs_compose_map(const QkObs *first, const QkObs *second, const uint32_t *qargs)

カスタム量子ビットの順序に従って2つの観測値を合成(乗算)する。

注目すべきは、これによって大きさの異なる2つの観測値を合成できることだ。

QkObs *first = qk_obs_zero(100);
QkObs *second = qk_obs_identity(100);
QkObs *result = qk_obs_compose(first, second);

安全

この関数を安全に呼び出すには

  • first および second は、 QkObs ㊟への有効な非 NULL ポインタでなければならない
  • qargs は、 qk_obs_num_qubits(second) の要素( second の量子ビット数を意味する)に対して読み取り可能な、 uint32_t の配列を指す必要がある

パラメーター

  • first - 観測可能な1つ。
  • second - もう一つの観測可能なもの。 量子ビットの数は、 qargs の長さと一致しなければならない。
  • qargs - first のどのインデックスを second のインデックスと関連付けるかを指定する量子ビット引数。

戻り値

first.compose(second) これは、観測可能な result = second @ first、行列の乗算 @ に等しい。

qk_obs_apply_layout

QkExitCode qk_obs_apply_layout(QkObs *obs, const uint32_t *layout, uint32_t num_qubits)

新しい量子ビットレイアウトを観測値に適用する。

レイアウトは新しいインデックスの配列 layout によって設定され、現在のインデックス i にある量子ビットがインデックス layout[i] に再ラベル化されることを指定する。 観測可能な量子ビットの数は、現在の観測可能な量子ビット数より大きな num_qubits

このインターフェースにより、量子ビットのインデックスを再ラベル化し、拡張することができる:

QkObs *obs = qk_obs_zero(4);

// add a term to the observable
QkBitTerm bit_terms[3] = {QkBitTerm_X, QkBitTerm_Y, QkBitTerm_Z};
uint32_t qubits[3] = {1, 2, 3};
complex double coeff = 1;
QkObsTerm term = {coeff, 3, bit_terms, qubits, 4};
qk_obs_add_term(obs, &term);

uint32_t layout[3] = {0, 10, 9};  // qubit mapping is: 0->0, 1->10, 2->9
uint32_t num_output_qubits = 11;
QkExitCode exit = qk_obs_apply_layout(obs, layout, num_output_qubits);

コンパイラのワークフローでは、この関数をトランスパイラパスから得られた QkTranspileLayout* (次の例では transpile_layout )を適用するのに使うと便利です:

// get the number of output qubits
uint32_t num_output_qubits = qk_transpile_layout_num_output_qubits(transpile_layout);

// get the layout including the ancillas (hence the ``false`` in the function call)
uint32_t *layout = malloc(sizeof(uint32_t) * num_output_qubits);
qk_transpile_layout_final_layout(transpile_layout, false, layout);

// apply the layout
QkExitCode exit = qk_obs_apply_layout(obs, layout, num_output_qubits);

// free the layout array
free(layout);

安全

obsQkObs への有効な非NULLポインタでない場合、または layoutqk_obs_num_qubits(obs) の連続する要素 uint32_t への有効な非NULLポインタでない場合、動作は未定義となる。

パラメーター

  • obs - observableへのポインタ。このobservableは成功するとその場で変更されます。 終了コードをチェックし、レイアウトが正しく適用されていることを確認する。
  • layout - レイアウトへのポインタ. ポインタは、 uint32_t 型の qk_obs_num_qubits(obs) 要素の配列を指していなければならない。 各要素は [0, num_qubits) の値を持たなければならない。
  • num_qubits - 出力量子ビットの数。

戻り値

終了コード。

  • QkExitCode_Success 成功すれば
  • QkExitCode_DuplicteIndexError 重複した量子ビットインデックスが見つかった場合
  • QkExitCode_MismatchedQubits num_qubits が観測可能な量子ビット数より小さい場合
  • QkExitCode_IndexError layout の無効な値など、その他のインデックス・エラーについて。

qk_obs_canonicalize

QkObs *qk_obs_canonicalize(const QkObs *obs, double tol)

観測値の正準表現を計算する。

QkObs *iden = qk_obs_identity(100);
QkObs *two = qk_obs_add(iden, iden);

double tol = 1e-6;
QkObs *canonical = qk_obs_canonicalize(two, tol);

安全

動作は未定義 obs は有効な、 QkObs への NULL ではないポインタではない。

パラメーター

  • obs - observableへのポインタ.
  • tol - 係数がゼロとみなされる許容誤差。

戻り値

観測値の正準表現。

qk_obs_copy

QkObs *qk_obs_copy(const QkObs *obs)

observableをコピーする。

QkObs *original = qk_obs_identity(100);
QkObs *copied = qk_obs_copy(original);

安全

動作は未定義 obs は有効な、 QkObs への NULL ではないポインタではない。

パラメーター

  • obs - observableへのポインタ.

戻り値

observableのコピーへのポインタ。

qk_obs_equal

bool qk_obs_equal(const QkObs *obs, const QkObs *other)

2つの観測値が等しいかどうかを比較する。

これは数学的な等しさを比較するのではなく、データの等しさを比較するものであることに注意してほしい。 これは、2つの観測値が同じ観測値を表していても、同じ観測値として比較されないことを意味します。

QkObs *observable = qk_obs_identity(100);
QkObs *other = qk_obs_identity(100);
bool are_equal = qk_obs_equal(observable, other);

安全

obs QkObs または が有効でない場合、動作は未定義である。 other

パラメーター

  • obs - 1つの観測値へのポインタ.
  • other - 他の観測値へのポインタ.

戻り値

true 観測値が等しい場合は false

qk_obs_str

char *qk_obs_str(const QkObs *obs)

QkObs の文字列表現を返す。

QkObs *obs = qk_obs_identity(100);
char *string = qk_obs_str(obs);
qk_str_free(string);

安全

動作は未定義 obs は有効な、 QkObs への NULL ではないポインタではない。

文字列は通常のCのfreeで解放してはならない。 qk_str_free 、文字列が消費したメモリを解放しなければならない。 qk_str_free を呼び出さないとメモリー・リークにつながる。

値を変更することはできるが、(文字列内部のどこかにnulバイトを書くか、最後の1バイトを削除することによって)返された後の文字列の長さを変更してはならない。

パラメーター

  • obs - 文字列を取得する QkObs へのポインタ。

戻り値

の文字列表現のヌル終端文字配列へのポインタ。 obs

qk_str_free

void qk_str_free(char *string)

文字列表現を解放する。

安全

strqk_obs_str または qk_obsterm_str によって返されたポインタでない場合の動作は未定義である。

パラメーター

  • string - qk_obs_str または qk_obsterm_str から返される文字列表現へのポインタ.

qk_obs_to_python

PyObject *qk_obs_to_python(QkObs *obs)

オブジェクトの QkObs 所有権を Python に渡す。

この関数を呼び出した後、ポインタ QkObs を使用することは安全ではありません。 特に、これを消去したり解放したりしようとしないでください。 呼び出し元は、 QkObsそのオブジェクトを所有していなければならず、借用した参照を保持しているだけではいけません(たとえば、から取得 QkObs * した qk_obs_borrow_from_python は所有されていません)。

安全

呼び出し元は、 Python のインタプリタに接続されている必要があります。 が、初期化済みかつ所有権が保持されているへの有効な( QkObsNULLでない)ポインタでない obs 場合、動作は未定義となる。

パラメーター

  • obs – 所有されているオブジェクト。

戻り値

そのオブジェクトへの Python 参照。

qk_obs_borrow_from_python

QkObs *qk_obs_borrow_from_python(PyObject *ob)

PythonQkObs オブジェクトからポインタを取得します。

これは Python への参照を取得し、その型が正しい場合、その QkObs ポインタを抽出します。 返されるポインタは、その ob ポインタから借用されたものです。 が PyObject 正しい型でない場合、戻り値は NULL となり、 Python インタプリタの例外状態が設定されます。

この関数を呼び出すには、 Python のインタプリタに接続されている必要があります。

また、 qk_obs_convert_from_pythonを使用することもできます。これは論理的にはこの関数と全く同じですが、 Python コンバータ PyArg_Parse* 関数のファミリー向けの「コンバータ」関数として直接使用することができます。

安全

呼び出し元は、 Python のインタプリタに接続されている必要があります。 が、 Python オブジェクトへの有効な(NULLではない)ポインタでない ob 場合、動作は未定義となります。

パラメーター

  • ob – Python から借用したオブジェクト。

戻り値

ネイティブオブジェクトへのポインタ、あるいは NULLPython オブジェクトの型が正しくない場合。

qk_obs_convert_from_python

int qk_obs_convert_from_python(PyObject *object, void *address)

PythonQkObs オブジェクトからポインタを取得します。

これは Python への参照を受け取り、その QkObs ポインタが正しい型であれば、 addressそれをに抽出します。 返されるポインタは、その object ポインタから借用されたものです。 が正しい PyObject 型でない場合、戻り値は 1 となり、 Python インタプリタの例外状態が設定され、 address は変更されません。

この関数を呼び出すには、 Python のインタプリタに接続されている必要があります。

また、 qk_obs_borrow_from_pythonを使用することもできます。これは論理的にはこれと全く同じですが、直接使用する際のシグネチャがより自然になっています。

安全

呼び出し元は、 Python のインタプリタに接続されている必要があります。 が Python オブジェクトへの有効な(NULLではない)ポインタでない object 場合、またはが正しい型の書き込み可能なデータへのポインタでない address 場合、動作は未定義となります。

パラメーター

  • object – 借用された Python オブジェクト。
  • アドレス – 出力を書き込む場所。

戻り値

成功時は1、失敗時は0。

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