Skip to main content
IBM Quantum Platform

SparseObservable

class qiskit.quantum_info.SparseObservable(data, /, num_qubits=None)

GitHub

ベース: object

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


数学

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

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

複素数 cic_i、制限されたアルファベット Ai(n)A^{(n)}_i からの量子ビット nn に作用する単一量子ビット演算子。 ii 上の和は個々の項の和であり、テンソル積は演算子文字列を生成する。

Ai(n)A^{(n)}_i、パウリ作用素とパウリ固有状態射影作用素のアルファベットから1量子ビットの作用素が選ばれる。 具体的には以下のようなものだ:

ラベル
オペレーター
数値
BitTerm 属性
"I"II (アイデンティティ)保管されていない。保管されていない。
"X"XX (パウリX)0b0010 (2)X
"Y"YY (パウリ・Y)0b0011 (3)Y
"Z"ZZ (パウリZ)0b0001 (1)Z
"+"++\lvert+\rangle\langle+\rvert (Xの正の固有状態への射影)0b1010 (10)PLUS
"-"\lvert-\rangle\langle-\rvert (Xの負の固有状態への射影)0b0110 (6)MINUS
"r"rr\lvert r\rangle\langle r\rvert (Yの正の固有状態への射影)0b1011 (11)RIGHT
"l"ll\lvert l\rangle\langle l\rvert (Yの負の固有状態への射影)0b0111 (7)LEFT
"0"00\lvert0\rangle\langle0\rvert (Zの正の固有状態への射影)0b1001 (9)ZERO
"1"11\lvert1\rangle\langle1\rvert (Zの負の固有状態への射影)0b0101 (5)ONE

許容されるアルファベットは演算子空間の過完備基底を形成する。 このことは、与えられた観測値を表す一意的な総和が存在しないことを意味する。 それに比べて SparsePauliOp は演算子空間の正確な基底を使うので、(同じパウリ文字列の項を組み合わせ、ゼロを取り除き、 ある正準順に並べ替えた後)どの演算子の表現も1つだけとなる。

SparseObservable は、「測定の効率性」を「表現の効率性」と同等にすることを目的に、その特殊な過完備基礎を使用している。 例えば、観測可能な 00n{\lvert0\rangle\langle0\rvert}^{\otimes n} は、ハードウェア上では単純な ZZ 測定で効率的に測定できるが、 でしか表現できない。 SparsePauliOp(I+Z)n/2n{(I + Z)}^{\otimes n}/2^n 2n2^n でしか表現できない。 SparseObservable これを保存するために必要な用語は1つだけである。

この欠点は、任意の行列または SparsePauliOp を取り出して*最良の *SparseObservable 表現することが現実的でないことである。 一般的には SparseObservable を直接作りたいだろう。


表現

の内部表現は SparseObservable の内部表現には、非同一量子ビット演算子のみが格納される。 これにより、 nqubitsZ(n)\sum_{n\in \text{qubits}} Z^{(n)} のような観測量を表現する効率が大幅に向上する; SparseObservable は総クビット数に線形なメモリ量を必要とするのに対し SparsePauliOp は2次関数的にスケールする。

項は圧縮されて保存され、これはスパース行列の圧縮されたスパース行フォーマットと同様の精神である。 このアナロジーでは、和の項が「行」で、量子ビットの項が「列」である。 より明確には、この表現は4つの連続した配列で構成されている:

属性
長さ
説明
coeffstt各項の複素スカラー倍率。
bit_termsssすべての演算子の非同一1量子ビット項を順番に並べる。 これらは、和の記述における非同一性 Ai(n)A^{(n)}_i に対応し、エントリーは、 ii の増加順に最初に格納され、各項目内では nn の増加順に格納される。
indicesssの各演算子に対応する量子ビット( nn )。 bit_terms. SparseObservable は、このリストが項ごとにソートされていることを必要とし、アルゴリズムはこの不変性が維持されていることを信頼することができる。
boundariest+1t+1を分割するインデックス bit_termsindices を完全な項に分割する。 項数 ii について、その複素係数は coeffs[i] であり、その非同一単一量子ビット演算子とそれに対応する量子ビットは、スライス boundaries[i] : boundaries[i+1] で次のようになる。 bit_termsindices である。 boundaries は常に最初の要素として明示的な0を持つ。

長さのパラメータ tt は和の項の数であり、パラメータ ss は非同一単一量子ビットの項の総数である。

実例として:

  • ゼロ演算子の場合 boundaries は長さ1(0が1つ)であり、他のすべてのベクトルは空である。
  • 完全に簡略化された恒等演算子の場合、 boundaries[0, 0]coeffs は単一のエントリを持ち bit_termsindices は空である。
  • 演算子 Z2Z0X3Y1Z_2 Z_0 - X_3 Y_1boundaries[0, 2, 4]coeffs[1.0, -1.0]bit_terms[BitTerm.Z, BitTerm.Z, BitTerm.Y, BitTerm.X] であり indices[0, 2, 1, 3]。 演算子は、パラメータによっては4つ以上の量子ビットに作用する。 num_qubits パラメータに依存する。 は整数値である。 bit_terms は整数値で、そのマジック・ナンバーは BitTerm 属性クラスでアクセスできます。 1ビットの項とインデックスは項ごとにソートされていることに注意。 これはクラスの必須条件である。

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

配列のスカラー項目は bit_terms 配列のスカラー項目は数値バイトとして格納される。 数値は、そのシンプレクティック・パウリ表現に関連している。 SparsePauliOp が使用するシンプレクティック・パウリ表現に関連しており、列挙による名前付きアクセスでアクセスできる:

BitTerm

class BitTerm

GitHub

への名前付きアクセスを提供する。 IntEnum Alphabet of single-qubit terms used in SparseObservable に列挙されている各シングル量子ビット・アルファベット項を表す数値への名前付きアクセスを提供する。

このクラスは SparseObservable. としてアクセスする。 SparseObservable.BitTerm. これでは入力が多すぎるし、 :class:¬SparseObservable` オブジェクトだけを扱っていて、 BitTerm の名前があいまいでない場合は、次のように短縮するとよいだろう:

>>> ops = SparseObservable.BitTerm
>>> assert ops.X is SparseObservable.BitTerm.X

列挙のすべての値には、すべて大文字のフルネームか、一文字のラベルでアクセスできる。 1文字のラベルは一般的に有効な Python 識別子ではないので、アクセスするには索引表記を使わなければならない:

>>> assert SparseObservable.BitTerm.ZERO is SparseObservable.BitTerm["0"]

これらの数値構造は、すべて4ビットの値であり、下位2ビットはオブジェクトに関連するパウリ演算子の(位相のない)シンプレクティック表現である。下位ビットは ZZ、2番目に低いビットは XX、上位2ビットはパウリ演算子の 00 、負固有状態プロジェクタの 01 、正固有状態プロジェクタの 10

X

デフォルト値: 2

Pauli XX 演算子。 一文字ラベル "X" を使用。

PLUS

デフォルト値: 10

XX 演算子の正固有状態へのプロジェクター: ++\lvert+\rangle\langle+\rvert.一文字ラベル "+" を使用。

MINUS

デフォルト値: 6

XX 演算子の負の固有状態へのプロジェクター: \lvert-\rangle\langle-\rvert.一文字ラベル "-" を使用。

Y

デフォルト値: 3

Pauli YY 演算子。 一文字ラベル "Y" を使用。

デフォルト値: 11

YY 演算子の正固有状態へのプロジェクター: rr\lvert r\rangle\langle r\rvert.一文字ラベル "r" を使用。

LEFT

デフォルト値: 7

YY 演算子の負の固有状態へのプロジェクター: ll\lvert l\rangle\langle l\rvert.一文字ラベル "l" を使用。

Z

デフォルト値: 1

Pauli ZZ 演算子。 一文字ラベル "Z" を使用。

ZERO

デフォルト値: 9

ZZ 演算子の正固有状態へのプロジェクター: 00\lvert0\rangle\langle0\rvert.一文字ラベル "0" を使用。

ONE

デフォルト値: 5

ZZ 演算子の負の固有状態へのプロジェクター: 11\lvert1\rangle\langle1\rvert.一文字ラベル "1" を使用。

属性

label

この用語をアルファベットで表すために使われる1文字の文字列ラベル。 SparseObservable アルファベット。

配列のような各属性は、 Python シーケンスのように振る舞う。 標準的な list-のようなセマンティクスで 属性をスライスすると、フィールドの自然な。 ndarray フィールドの自然な dtype 、関連するデータのコピーを含むNumpyを返します。 bit_terms. 各属性のインデックスやスライスに割り当てることができるが、その際にはデータ・コヒーレンス・ルールを守る必要がある。 例:

>>> obs = SparseObservable.from_list([("XZY", 1.5j), ("+1r", -0.5)])
>>> assert isinstance(obs.coeffs[:], np.ndarray)
>>> # Reduce all single-qubit terms to the relevant Pauli operator, if they are a projector.
>>> obs.bit_terms[:] = obs.bit_terms[:] & 0b00_11
>>> assert obs == SparseObservable.from_list([("XZY", 1.5j), ("XZY", -0.5)])

上記のパウリ塩基への漸化式は、次のようにすることもできる。 pauli_bases().

正則順序

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

これら2つの種類の表現の縮退により、演算 == 子は、同じ対象を表しているにもかかわらず、2つの観測量が等しくないとする結果になりかねない。 このような場合、観測量を構造的に比較できるようにするための標準形を定義しておくと便利である。

SparseObservable を正規形にすることができます。 simplify() メソッドを使う。 正準順序における用語の正確な順序は指定されておらず、Qiskitのバージョン間で変更される可能性がある。 しかし、同じバージョンのQiskitでは、2つのobservableを構造的に比較することができます。

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

def equivalent(left, right, tol):
    return (left - right).simplify(tol) == SparseObservable.zero(left.num_qubits)

によって生成される正準形式 simplify() によって生成される正準形式だけでは、過完備な基底アルファベットのために、等価なすべての観測量を普遍的に検出することはできない。 一意な式を得るには、まずパウリ項のみを用いて観測値を表すことができる。 as_paulis()その後に simplify(). プロジェクター展開(例えば +IX )に分割することは、スケール的に計算不可能である。

索引付け

SparseObservable は、 Python シーケンス (展開された collections.abc.Sequence). observableは整数でインデックスされ、反復して個々の項を得ることができる。

各用語は、自己完結したクラスのインスタンスとして表示される。 個々の項は基本観測値からコピーされるので、それらに変異があっても観測値には影響しない。

用語

class Term(num_qubits, coeff, bit_terms, indices)

GitHub

ベース: object

完全な SparseObservable.

これらは通常、インデックスを作成したり SparseObservable.

bit_labels

bit_labels()

用語のビット・ラベルを文字列として返す。

ビットラベルは、文字列のi番目の文字が term.indices[i] の量子ビットインデックスに適用されるように、 SparseTerm.indices の順序と一致する。

戻り値

非同一ビット項を連結した文字列。

bit_terms

個々の単一量子ビット項に関する読み取り専用ビュー。

配列の中で有効な値は、対応する BitTerm.

coeff

係数。

copy

copy()

今期のコピーを入手する

indices

各非同一シングル量子ビットの項のインデックスに関する読み取り専用ビュー。

インデックスは常にソート順となる。

num_qubits

その項が定義されている量子ビットの数。

pauli_base

pauli_base()

を取得する。 Pauli オブジェクトを取得する。

例えば、プロジェクター 0l+ は Pauli ZYX を返す。 その結果 Pauli は、明示的な同一性が格納されるという意味で、密である。 パウリ出力における同一性は、具体的な測定を必要としない。

戻り値: Pauli: 必要なパウリ演算子

測定基準。

関連資料

SparseObservable.pauli_bases()

同じような方法で、観測可能なもの全体を一度に観測することができます。

to_observable

to_observable()

この用語を完全に変換する SparseObservable.


建設

SparseObservable はいくつかのコンストラクタを定義している。 デフォルトのコンストラクタは、入力の型に基づいて、より特殊なコンストラクタのいずれかに委譲しようとする。 特定のコンストラクタを使用することで、よりコントロールしやすくなる。

メソッド
サマリー
from_label()密な文字列ラベルを単一項に変換する SparseObservable.
from_list()密な文字列ラベルと関連する係数のタプルのリストをobservableにまとめる。
from_sparse_list()疎な文字列ラベル、それらが適用される量子ビット、およびそれらの係数のタプルのリストをobservableにまとめる。
from_pauli()シングル Pauli を一項 SparseObservable.
from_sparse_pauli_op()SparsePauliOpSparseObservable.
from_terms()明示的な単一インスタンスの合計 Term インスタンスになります。
from_raw_parts()生のデータ配列から observableを構築する。

__new__

__new__(data, /, num_qubits=None)

のデフォルトコンストラクタは SparseObservable.

これは、 data の引数の型に基づいて、 明示的な変換コンストラクタ・メソッドのいずれかに委譲する。 num_qubits が与えられ、 data の型が暗示するコンストラクタが数値を受け付けない場合、与えられた整数は入力と一致しなければならない。

パラメーター

  • data - 入力のデータ型。 これは、別の SparseObservableこの場合、入力はコピーされる。 Pauli または SparsePauliOpであり、その場合は from_pauli() または from_sparse_pauli_op() が呼び出される。 from_list() または from_sparse_list().
  • num_qubits (int|None) – 演算子の量子ビット数(オプション)。 ほとんどのデータ入力では、これは推測できるので、渡す必要はない。 これは空リストかスパース・リスト形式でのみ必要である。 不必要に与えられる場合は、入力されたデータと一致しなければならない。

変換ベースのコンストラクタに加えて、特殊な形のobservableを構築するヘルパーメソッドもあります。

メソッド
サマリー
zero()与えられた数の量子ビットに対するゼロ演算子。
identity()与えられた数の量子ビットに対する恒等演算子。

変換

既存の SparseObservable は、他の quantum_info 演算子や汎用フォーマットに変換できる。 他のオブジェクトは、同じオブザーバブルを以下のように効率的に表現できない可能性があることに注意してください。 SparseObservableより多くのメモリを必要とする可能性がある。

メソッド
サマリー
as_paulis()新しい SparseObservableを作成する。
to_sparse_list()要素 (bit_terms, indices, coeff) を持つスパースリスト形式で観測値を表現する。

加えて SparsePauliOp.from_sparse_observable() はこのクラスから SparsePauliOp. このメソッドは、次のような指数関数的なメモリ使用量に悩まされることに注意してほしい。 as_paulis().


数学的操作

SparseObservable は、他の演算子と同様に、 Python の数学演算子の標準セットをサポートしている。 quantum_info 演算子をサポートしています。

基本的な算数では

  • を使用して2つのオブザーバブルを追加する。 +
  • を使って2つの観測値を差し引く。 -
  • で乗除する。 int, float または complex* を使う。 /
  • 観測値のすべての係数を単項演算子で否定する。 -

基本的な二項演算子には、それぞれ対応する特殊なインプレース・メソッドがあり、左辺をインプレースで変更する。 特にループの中でobservableを構築する場合には、これらの演算子を使う方がinfix演算子よりも効率的である。

テンソル積は tensor() (パウリ・ラベルの標準的な並置順序の場合) または expand() (逆順序の場合) で計算される。 ^ 演算子は、次のようにオーバーロードされます。 tensor().

二項演算子 ^ (tensor()) と & (compose())を使用する場合、 Python の演算子優先順位規則により、評価順序が予想と異なることがあるので注意すること。 特に、演算子 + は、 ^& よりも強く結合し、 *+ よりも強く結合する。

混合式で演算子を使用する場合、テンソル積のオペランドをグループ化するために括弧を使用するのが最も安全である。

A SparseObservable はよく定義された adjoint(). スカラー複素共役(conjugate())と実数値転置(transpose())はQiskitにおける他のPauli作用素の行列表現と同様に定義される。

効率に関する注記

内部的には SparseObservable はインプレース・ミュータブルであり、項数を拡張するためにオーバーアロケートされたグロウアブル・ベクターを使用することもできる。 これは、 += を使って観測値に追加するコストは、バイナリ + のような2次的な複雑さではなく、追加される用語の総数に対して線形に償却されることを意味する。

加算と減算は項を積み重ねる操作によって実行される。観測値を構築するための加算の大部分は少数の重複しか発生させず、同類項検出には追加コストがかかるため、自動的な「単純化」(同類項の合計)は行われない。 もしこれがあなたのユースケースに合わない場合は、定期的に simplify()を定期的に呼び出すか、observablesをより良く構築するためのさらなるAPIについて私たちと議論してください。


属性

bit_terms

単一量子ビット項のフラットリスト。 これは、より自然なリストのリストだが、メモリ使用量と局所性の理由から平坦に保存され、サブリストは境界で示される。

boundaries

分割するインデックス bit_termsindices を分割するインデックス。 boundaries[0] : boundaries[1] へのインデックスの範囲である。 bit_termsindices へのインデックスの範囲である。 すべての不特定の量子ビット・インデックスは暗黙的に同一である。 これは coeffsなぜなら、 boundaries[0] は常に明示的なゼロだからである(アルゴリズム的に簡単にするため)。

coeffs

各抽象項の係数は合計に含まれる。 これは和の項と同じ数の要素を持つ。

indices

の対応するエントリーが作用する量子ビット・インデックスのフラット・リスト。 bit_terms の対応するエントリが作用する量子ビットインデックスのフラットリスト。 このリストは常に項ごとにソートされなければならない。 boundaries.

警告

Python、この属性に書き込む場合は、用語順にソートされたインデックスのみを書き込むようにしなければならない

num_qubits

演算子が作用する量子ビットの数。

アイデンティティは明示的に保存されないため、これは他の形状や値からは推測できない。

num_terms

この演算子が追跡している和の項数。


方法

adjoint

adjoint()

この観測値の随伴点を計算する。

これは、抽象的な数学的な意味でうまく定義されている。 単一量子ビットのアルファベットの項はすべて自己合同なので、この演算の結果は、その係数がすべて複素共役であることを除けば、同じ観測値である。

>>> left = SparseObservable.from_list([("XY+-", 1j)])
>>> right = SparseObservable.from_list([("XY+-", -1j)])
>>> assert left.adjoint() == right

apply_layout

apply_layout(layout, num_qubits=None)

これにトランスパイラ・レイアウトを適用する。 SparseObservable.

通常、状態を準備するために使用する回路の仮想量子ビットの観点から観測可能なものを定義する。 トランスパイレーションの後、仮想量子ビットはデバイス上の特定の物理量子ビットにマッピングされる。 このマッピングは、サーキットの過程で変化することもある。 この方法は、仮想量子ビットの入力観測値を、完全にトランスパイルされた物理回路の直後に適用するのに適した観測値に変換する。

パラメーター

  • layout (TranspileLayout |list[int] | None) – レイアウトを適用する。 この関数のほとんどの用途は、ハードウェア用にトランスパイルされた回路から QuantumCircuit.layout フィールドを渡すべきである。 さらに、新しい量子ビット・インデックスのリストを渡すこともできる。 明示的に None、リマッピングは適用されない(ただし、 num_qubits 、observableを拡張することはできる)。
  • num_qubits (int | None) – 観測可能な量子ビットの数。 もし与えなければ、出力は与えられた TranspileLayoutと同じ幅になる。 layout が別の形式で与えられている場合は、入力と同じ幅になる。

戻り値

新しい SparseObservable を作成し、提供されたレイアウトを適用します。

as_paulis

as_paulis()

各投影をパウリ項の和として書くことにより、観測値をパウリ項のみで表す。

結果として得られるパウリ項の次数は保証されていないことに注意。 使用する SparseObservable.simplify() を加えて、正準表現を得る。

警告

nn シングル量子ビットプロジェクターが存在する場合、少なくとも 2n2^n、指数関数的な数の項を使うことになるので注意。

戻り値

同じ観測値だが、パウリ項のみで表現される。

パウリ作用素に射影することで、観測値を書き換える:

>>> obs = SparseObservable("+")
>>> obs.as_paulis()
<SparseObservable with 2 terms on 1 qubit: (0.5+0j)() + (0.5+0j)(X_0)>
>>> direct = SparseObservable.from_list([("I", 0.5), ("Z", 0.5)])
>>> assert direct.simplify() == obs.as_paulis().simplify()

小さな演算子の場合、これは simplify() をユニークな正準形式として使うことができる:

>>> left = SparseObservable.from_list([("+", 0.5), ("-", 0.5)])
>>> right = SparseObservable.from_list([("r", 0.5), ("l", 0.5)])
>>> assert left.as_paulis().simplify() == right.as_paulis().simplify()
関連資料

SparsePauliOp.from_sparse_observable()

のコンストラクタは SparsePauliOp のコンストラクタは SparseObservableSparsePauliOp 密なパウリ表現に変換できる。

clear

clear()

この演算子からすべての項を消去し、再びゼロ演算子と等しくする。

これにより内部の割り当て容量は変更されないため、その後の加算や減算の操作において再割り当てが必要なくなる場合があります。

>>> obs = SparseObservable.from_list([("IX+-rl", 2.0), ("01YZII", -1j)])
>>> obs.clear()
>>> assert obs == SparseObservable.zero(obs.py_num_qubits())

commutes

commutes(other, tol=1e-12)

ある観測可能量が別の観測可能量と可換であるかどうかを確認する。

パラメーター

  • other (SparseObservable) – 交換性を確認するためのもう一つの観測量。
  • tol (float) – 自己と他者の積における係数が許容値(絶対値)を下回る場合、それらの項は無視される。

戻り値

True 許容範囲内で条件が交換可能であれば、そうでなければ False

昇給

TypeError – が に強制変換できなかった other``SparseObservable 場合。

compose

compose(other, /, qargs=None, *, front=False)

この上に別の SparseObservable を作成する。

作用素代数の観点からは、合成は左掛け算に相当する。 c = a.compose(b) は、 $C = B A$ に相当する。つまり、 a.compose(b) は「 a を行い、その結果に b を行う」演算子を返す。 その代わり、 front=True

selfother は同じサイズでなければならない。ただし、 qargs が与えられている場合を除く。その場合、 otherself より小さくてもよい。ただし、 other の量子ビット数と qargs の長さが一致していることが条件である。 qargs は、 self に存在しない量子ビットの重複やインデックスを含むことはできない。

のアルファベットは合成の下では閉じていないので、この関数は観測可能なメモリ使用量を指数関数的に爆発させる可能性があることに注意してください。 SparseObservable のアルファベットは合成の下では閉じていないので、この関数は観測可能なメモリ使用量を指数関数的に爆発させる可能性があることに注意すること。 このメモリ使用量は、結果的なオブザーバブルに固有のものではないが、合計の効率的な再ファクタリゼーションを見つけることは、一般的に同様に計算が難しい。 後から単純化するのではなく、観測値の知識を利用して、存在する項の数を最小限にする方が良い。

パラメーター

  • other - self の左乗算に使われる観測値。

  • qargs

    もし与えられれば、 self の量子ビットが other の量子ビットに関連付けられる。 別の言い方をすれば、これが与えられれば、より効率的な実装に似ている:

    self.compose(other.apply_layout(qargs, self.num_qubits))

    というのも、 other のアプライドレイアウトフォームを保存するための一時的なオブザーバブルは作成されないからである。

  • front - True の場合、左掛けではなく other で右掛けする(デフォルトは False )。 qargs はまだ other に適用されている。 これは、 qargs が設定されている場合、あるいは、 other が、以下のように強制されなければならないオブジェクトである場合に最も便利である。 SparseObservable.

conjugate

conjugate()

この観測値の複素共役を計算する。

この演算はQiskitの標準的な行列規約の観点から定義され、行列の形が♪Z$計算基底にあるとみなされる。 X-関連項とZ-関連項は複素共役の影響を受けないが、Y-関連項はそのアルファベット項を修正する。 その通りだ:

  • YY に通じる。 Y-Y
  • rr\lvert r\rangle\langle r\rvert に結合する。 ll\lvert l\rangle\langle l\rvert
  • ll\lvert l\rangle\langle l\rvert に結合する。 rr\lvert r\rangle\langle r\rvert

さらに、すべての係数は共役である。

>>> obs = SparseObservable([("III", 1j), ("Yrl", 0.5)])
>>> assert obs.conjugate() == SparseObservable([("III", -1j), ("Ylr", -0.5)])

copy

copy()

このobservableのコピーを取得する。

>>> obs = SparseObservable.from_list([("IXZ+lr01", 2.5), ("ZXI-rl10", 0.5j)])
>>> assert obs == obs.copy()
>>> assert obs is not obs.copy()

evolve

evolve(other, /, qargs=None)

この観測量をパウリ項を用いて展開せよ。

観測可能量 OO のパウリ演算子 PP による演算は、 POPP^\dagger O P に対応する。

2つの完全な構成を用いた文字通りの実装とは異なり、この手法では固定のルックアップテーブルを用いて、単一量子ビットレベルで直接共役変換を行います。 これにより、中間状態の具体化を回避し、項を一度だけ SparseObservable 走査するだけで、進化後の観測量を計算することができる。 self また、 が qargs 指定されていない限り、両者の量子 other ビット数は同じでなければならない。ただし、 が指定されている場合は、 other と の量子ビット数が other 一致 qargs していれば、 は selfよりも小さくてもよい。 qargs は、のどの量子ビットがによって self 進化するかを other指定する。

現在、この手法は単項演算子による演化のみをサポートしており、つまり は で表される other パウリ演算子 Pauliでなければならない。

パラメーター

  • その他 – 共役化に用いられる selfパウリ演算子。
  • qargs – 指定された場合、関数 self によって進化させる量子 otherビット。 長さは、の量子ビット数と一致 otherしていなければなりません。

戻り値

新しい進化形 SparseObservable に、活用形が適用された。

昇給

  • TypeError – が型 Pauliでない other 場合。
  • ValueError – もし selfother の量子ビット数が異なる場合(かつ qargs が与えられていない場合)。
  • ValueError – length が量子ビットの数 qargsother 一致しない場合。
  • ValueError – 重複や範囲外のインデックスが含まれている qargs 場合。
  • ValueError – もし other に複数の項が含まれている場合。

expand

expand(other, /)

逆順テンソル積。

これは other.tensor(self) と等価であるが、 other が(デフォルトのコンストラクタを呼び出すことによって)まだ型キャストされていなければ、最初に型キャストされる。 SparseObservable に型キャストされる(デフォルトのコンストラクタが呼び出される)。

パラメーター

other - テンソル積の左辺に置く観測値。

これは tensor() と等価である:

>>> left = SparseObservable.from_label("XYZ")
>>> right = SparseObservable.from_label("+-IIrl")
>>> assert left.tensor(right) == right.expand(left)
関連資料

tensor()

同じ関数で、引数の順番を入れ替えたもの。 tensor() はより標準的な引数の順序であり、Qiskitの他の規約と一致しています。

from_label

static from_label(label, /)

密な文字列ラベルから単一項の観測値を構築する。

その結果、演算子の係数は1になる。 ラベルはアルファベット 'IXYZ+-rl01' の並びでなければならない。 ラベルはビット列と同様に解釈される。 つまり、一番右の文字が0番量子ビットに対応し、以下同様である。 のラベルと同じである。 PauliSparsePauliOp.

パラメーター

label (str) – 濃密なラベル。

>>> SparseObservable.from_label("IIII+ZI")
<SparseObservable with 1 term on 7 qubits: (1+0j)(+_2 Z_1)>
>>> label = "IYXZI"
>>> pauli = Pauli(label)
>>> assert SparseObservable.from_label(label) == SparseObservable.from_pauli(pauli)
関連資料

from_list()

複数のラベルとそれに対応する係数から和演算子を構成するこの方法の一般化。

from_list

static from_list(iter, /, *, num_qubits=None)

密なラベルと係数のリストからobservableを構築する。

と似ている。 SparsePauliOp.from_list()と似ているSparseObservable. この密なフォームでは、各ラベルにすべてのIDを明示的に与えなければならない。

ラベルはアルファベット 'IXYZ+-rl01' の並びでなければならない。 ラベルはビット列と同様に解釈される。 つまり、一番右の文字が0番量子ビットに対応し、以下同様である。 のラベルと同じである。 PauliSparsePauliOp.

パラメーター

  • iter (list[tuple[str, complex]]) – ラベルとその係数の和のペア。 ラベルの解釈は from_label().
  • num_qubits (int | None) – ラベルの長さから推測できるので、 iter が空の配列でないことが確かならば、これを指定する必要はない。 もし iter が空であれば、いくつの量子ビットの観測値であるかを明確にするためにこの引数を指定しなければなりません。 これが与えられ、 iter が空でない場合、値はラベルの長さと一致しなければならない。

同じ長さのラベルのリストからobservableを構築する:

>>> SparseObservable.from_list([
...     ("III++", 1.0),
...     ("II--I", 1.0j),
...     ("I++II", -0.5),
...     ("--III", -0.25j),
... ])
<SparseObservable with 4 terms on 5 qubits:
    (1+0j)(+_1 +_0) + (0+1j)(-_2 -_1) + (-0.5+0j)(+_3 +_2) + (-0-0.25j)(-_4 -_3)>

num_qubits を使って、空の可能性のある入力を曖昧さをなくす:

>>> SparseObservable.from_list([], num_qubits=10)
<SparseObservable with 0 terms on 10 qubits: 0.0>

このメソッドは from_sparse_list() を呼び出すのと同じである:

>>> labels = ["XY+Z", "rl01", "-lXZ"]
>>> coeffs = [1.5j, 2.0, -0.5]
>>> from_list = SparseObservable.from_list(list(zip(labels, coeffs)))
>>> from_sparse_list = SparseObservable.from_sparse_list([
...     (label, (3, 2, 1, 0), coeff)
...     for label, coeff in zip(labels, coeffs)
... ])
>>> assert from_list == from_sparse_list
関連資料

from_label()

似たようなコンストラクタだが、単一のラベルのみを取り、その係数は常に 1.0 に設定される。

from_sparse_list()

明示的な同一性を持たず、各単一量子ビット項が適用される量子ビットを明示的にリストしたラベルのリストから観測可能なものを構築する。

from_pauli

static from_pauli(pauli, /)

を構築する。 SparseObservable インスタンスから Pauli インスタンスから構築する。

出力観測値は、位相に依存するユニタリー係数を持つ単一の項を持つ。

パラメーター

pauli (Pauli) – コンバートするシングル・パウリ。

>>> label = "IYXZI"
>>> pauli = Pauli(label)
>>> SparseObservable.from_pauli(pauli)
<SparseObservable with 1 term on 5 qubits: (1+0j)(Y_3 X_2 Z_1)>
>>> assert SparseObservable.from_label(label) == SparseObservable.from_pauli(pauli)

from_raw_parts

static from_raw_parts(num_qubits, coeffs, bit_terms, indices, boundaries, check=True)

を構築する。 SparseObservable を、 クラスレベルのドキュメントに記述されている必要なデータ表現に一致する生のNumpy配列から構築します。

各配列のデータは、新しい、成長可能なRust-spaceアロケーションにコピーされる。

パラメーター

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

  • coeffs - 観測値の各項の複素係数。 これはd型のNumpy配列でなければならない。 complex128.

  • bit_terms - すべての完全項を含む単一量子ビット項の平坦化リスト。 のNumpy配列でなければならない。 uint8 (これは BitTerm).

  • indices - 各単一量子ビット項が対応する量子ビットを項ごとに平らにソートしたリスト。 これはd型のNumpy配列でなければならない。 uint32.

  • 境界 - bit_termsindices をタームに分割するインデックス。 これはd型のNumpy配列でなければならない。 uintp.

  • チェック

    True (デフォルト)の場合、データがすべてのコヒーレンス保証を満たしているかどうかを検証する。 False の場合、チェックは行われない。

    警告

    check=False の場合、 bit_terms はすべて有効な値でなければならないSparseObservable.BitTerm. そうでない場合、Rust-spaceの未定義動作が発生し、プログラムの実行が完全に無効になる可能性がある。

個々の量子ビットについて、 ZZ の和を構築する:

>>> num_qubits = 100
>>> terms = np.full((num_qubits,), SparseObservable.BitTerm.Z, dtype=np.uint8)
>>> indices = np.arange(num_qubits, dtype=np.uint32)
>>> coeffs = np.ones((num_qubits,), dtype=complex)
>>> boundaries = np.arange(num_qubits + 1, dtype=np.uintp)
>>> SparseObservable.from_raw_parts(num_qubits, coeffs, terms, indices, boundaries)
<SparseObservable with 100 terms on 100 qubits: (1+0j)(Z_0) + ... + (1+0j)(Z_99)>

from_sparse_list

static from_sparse_list(iter, /, num_qubits)

ラベルのリスト、各項目が適用される量子ビット、項全体の係数からobservableを構築する。

と似ている。 SparsePauliOp.from_sparse_list()と似ているSparseObservable.

トリプルの "labels "フィールドと "indices "フィールドは、ジップすることで関連付けられる。 たとえば、これは from_list() の呼び出しは、各トリプルの "indices" フィールドを (num_qubits-1, ..., 1, 0) に設定することで、このメソッドで使用される形式に変換できることを意味します。

パラメーター

  • iter (list[tuple[str, Sequence[int], complex]]) – ラベル、各単位量子ビットの項、項全体の係数の三つ組。
  • num_qubits (int) – 演算子の量子ビットの数。

単純な演算子を作る:

>>> SparseObservable.from_sparse_list(
...     [("ZX", (1, 4), 1.0), ("YY", (0, 3), 2j)],
...     num_qubits=5,
... )
<SparseObservable with 2 terms on 5 qubits: (1+0j)(X_4 Z_1) + (0+2j)(Y_3 Y_0)>

identityオブザーバブルを構築する(本当は identity()):

>>> SparseObservable.from_sparse_list([("", (), 1.0)], num_qubits=100)
<SparseObservable with 1 term on 100 qubits: (1+0j)()>

この方法は from_list()トリプルのqubit-argumentsフィールドが減少する整数に設定されている場合:

>>> labels = ["XY+Z", "rl01", "-lXZ"]
>>> coeffs = [1.5j, 2.0, -0.5]
>>> from_list = SparseObservable.from_list(list(zip(labels, coeffs)))
>>> from_sparse_list = SparseObservable.from_sparse_list([
...     (label, (3, 2, 1, 0), coeff)
...     for label, coeff in zip(labels, coeffs)
... ])
>>> assert from_list == from_sparse_list
関連資料

to_sparse_list()

この方法の逆。

from_sparse_pauli_op

static from_sparse_pauli_op(op, /)

から SparseObservable インスタンスから SparsePauliOp インスタンスを作成する。

これは SparsePauliOp特に、同じような項をその場で合計したり、パウリ項の合計を等価な射影演算子にリファクタライズする試みはない。

パラメーター

op (SparsePauliOp) – 変換する演算子。

>>> spo = SparsePauliOp.from_list([("III", 1.0), ("IIZ", 0.5), ("IZI", 0.5)])
>>> SparseObservable.from_sparse_pauli_op(spo)
<SparseObservable with 3 terms on 3 qubits: (1+0j)() + (0.5+0j)(Z_0) + (0.5+0j)(Z_1)>

from_terms

static from_terms(obj, /, num_qubits=None)

を構築する。 SparseObservable を構成する。

すべての項は同じ数の量子ビットを持たなければならない。 指定された場合、 num_qubits 引数は条件と一致しなければならない。

観測可能なものを作る過程で、単純化することはない。

パラメーター

  • obj (Iterable[Term]) – observableを構築する個々の用語の反復可能。
  • num_qubits (int | None) – 観測可能な量子ビットの数。 これは通常、入力から推測されるが、イテレート可能なものが空の場合に対処するために明示的に指定することもできる。

戻り値

対応する観測値。

identity

static identity(num_qubits)

指定された数の量子ビットに対する恒等演算子を取得します。

100量子ビットのID演算子を取得します:

>>> SparseObservable.identity(100)
<SparseObservable with 1 term on 100 qubits: (1+0j)()>

pauli_bases

pauli_bases()

を取得する。 PauliList このobservableの各項目(順番に)に必要な測定基底を表すオブジェクトを取得する。

例えば、プロジェクター 0l+ は Pauli ZXY を返す。 その結果 Pauli は、明示的な同一性が格納されるという意味で、密である。 パウリ出力における同一性は、具体的な測定を必要としない。

これは、和のすべての項について、パウリ・リストの項目を返す。

戻り値

必要な測定ベースを表すパウリ演算子リスト。

戻りの型

PauliList

simplify

simplify(tol=1e-08)

この演算子に含まれる同類の項をすべて合計し、その結果得られる複素係数の絶対値が許容範囲内のゼロであれば、それらを取り除く。

副次的な効果として、これは演算子を正準順にソートする。

これを等価比較に使用する際は、浮動小数点の丸め誤差や加算の非結合性により、和の各項の係数がゼロでない場合、それらが不等と判定される可能性があることに注意してください。 許容誤差の範囲内で2つの観測量を比較するには、それらの観測量の正規化された差を0と比較するのが最も確実である。

パラメーター

tol (float) – 同じような項を合計した後、絶対値が与えられた絶対許容誤差より小さい係数は、出力から抑制される。

を使用する。 simplify() を使うことで、同じ観測値を表す2つの演算子を比較することができますが、デフォルトでは構造検定のために不等間隔で比較されます:

>>> base = SparseObservable.from_sparse_list([
...     ("XZ", (2, 1), 1e-10),  # value too small
...     ("+-", (3, 1), 2j),
...     ("+-", (3, 1), 2j),     # can be combined with the above
...     ("01", (3, 1), 0.5),    # out of order compared to `expected`
... ], num_qubits=5)
>>> expected = SparseObservable.from_list([("I0I1I", 0.5), ("I+I-I", 4j)])
>>> assert base != expected  # non-canonical comparison
>>> assert base.simplify() == expected.simplify()

上記の例では、すべての浮動小数点計算が正確になるように係数が選択されており、中間的な丸めや連想性の懸念がないことに注意してください。 これが保証されない場合は、より安全な形がある:

>>> left = SparseObservable.from_list([("XYZ", 1.0/3.0)] * 3)   # sums to 1.0
>>> right = SparseObservable.from_list([("XYZ", 1.0/7.0)] * 7)  # doesn't sum to 1.0
>>> assert left.simplify() != right.simplify()
>>> assert (left - right).simplify() == SparseObservable.zero(left.num_qubits)

tensor

tensor(other, /)

2つの観測値のテンソル積。

ビットオーダーは、引数の量子ビットのインデックスが変わらないように定義され、 self のインデックスは other の量子ビットの数だけオフセットされる。 これはQiskitの他の quantum_info 演算子で使われているのと同じ規則です。

この関数は、 ^ の infix 演算子に使用される。 この演算子を使う場合、 Python 'の演算子優先順位規則によって、評価順序が期待したものと異なることがあるので注意すること。 特に、演算子 + は、 ^ よりも強く結合し、 * は、 + よりも強く結合する。 必要であれば、括弧を使って評価順序を固定する。

引数は SparseObservable にキャストされます。

パラメーター

その他 - テンソル積の右辺に置く観測値。

このビット順序は、1つのラベルから作られた2つの観測値のテンソル積が、2つの文字列を連結して作られた観測値の「ように見える」ようになっている:

>>> left = SparseObservable.from_label("XYZ")
>>> right = SparseObservable.from_label("+-IIrl")
>>> assert left.tensor(right) == SparseObservable.from_label("XYZ+-IIrl")

また、テンソル積には ^ という infix 演算子を使うこともできる。 SparseObservable:

>>> assert SparseObservable("rl") ^ Pauli("XYZ") == SparseObservable("rlXYZ")
関連資料

expand()

同じ関数だが、引数の順番が反転している。 これは、引数のキャスティング動作を使いたいが、既存の SparseObservable をテンソル順序の右辺にしたい場合に便利です。

to_sparse_list

to_sparse_list()

観測値をスパースリスト形式で表現する。

の逆演算と見なすことができる。 SparseObservable.from_sparse_list()しかし、スパース・リストへの往復の後では、項の順序が同じであることは保証されない。

>>> obs = SparseObservable.from_list([("IIXIZ", 2j), ("IIZIX", 2j)])
>>> reconstructed = SparseObservable.from_sparse_list(obs.to_sparse_list(), obs.num_qubits)
関連資料

from_sparse_list()

これらのリストを解釈できるコンストラクタ。

transpose

transpose()

この観測値の行列転置を計算する。

この演算はQiskitの標準的な行列規約の観点から定義され、行列の形が♪Z$計算基底にあるとみなされる。 X項とZ項は転置の影響を受けないが、Y項は転置の影響を受ける。 その通りだ:

  • YY に転化する。 Y-Y
  • rr\lvert r\rangle\langle r\rvert に転化する。 ll\lvert l\rangle\langle l\rvert
  • ll\lvert l\rangle\langle l\rvert に転化する。 rr\lvert r\rangle\langle r\rvert

>>> obs = SparseObservable([("III", 1j), ("Yrl", 0.5)])
>>> assert obs.transpose() == SparseObservable([("III", 1j), ("Ylr", -0.5)])

zero

static zero(num_qubits)

与えられた数の量子ビットのゼロ演算子を取得します。

ゼロ作用素は、すべての量子状態に対して期待値がゼロとなる作用素である。 条件はない。 これは、2つのインスタンスの加算のための同一要素である。 SparseObservable ゼロ演算子に追加されたものはそれ自身に等しい。

プロジェクターをオールゼロの状態にしたい場合は、次のようにする:

>>> num_qubits = 10
>>> all_zeros = SparseObservable.from_label("0" * num_qubits)

100量子ビットのゼロ演算子を取得します:

>>> SparseObservable.zero(100)
<SparseObservable with 0 terms on 100 qubits: 0.0>
このページは役に立ちましたか?
バグや誤字の報告、またはコンテンツの要求はGitHubで行ってください。