Skip to main content
IBM Quantum Platform

量子回路モデル

qiskit.circuit

量子コンピューティングの基本要素は量子回路である。 これは、量子プロセッシング・ユニット(QPU)上で一度に1ショットずつ実行できる計算ルーチンである。 回路は、あらかじめ定義された量の量子データ(Qiskitでは、量子ビットのみを直接サポートしている)に対して、ユニタリー演算(ゲート)、測定、リセットを用いて動作する。 さらに、量子回路は、QPUのコントローラによって実行されるリアルタイム計算や制御フロー構成など、古典データに対する演算を含むことができる。

量子プログラムを構築する際、回路は抽象度が低い。 これらは、 量子計算のプリミティブなどのより高い抽象レベルを構築するために使用される構造であり、量子回路実行の多数のショットからのデータを、高度なエラー軽減技術および測定最適化とともに、適切に型付けされた古典的なデータとエラー統計に蓄積します。

Qiskitでは、回路は 2つの体制のいずれかで定義できる:

  • 抽象回路。 仮想量子ビットと、カプセル化アルゴリズムやユーザー定義ゲートのような任意の高レベル演算で定義される。
  • 物理回路は、ある特定のバックエンドのハードウェア量子ビットの観点から定義され、そのバックエンドがネイティブにサポートする演算のみを含む。 このコンセプトは ISA回路と呼ばれることもある。

抽象回路から物理回路への変換には、 Qiskitのトランスパイルパッケージを使用します。 transpile(). 量子ビットインデックスが物理量子ビットを参照するような回路を定義する場合、Qiskitが回路を物理回路として認識するように回路のメタデータを書き換えるために QuantumCircuit.ensure_physical() を使って回路のメタデータを書き換え、Qiskitが回路を物理回路として認識するようにします。

Qiskitでは、量子回路は QuantumCircuit クラスで表されます。 以下は、3量子ビットのGHZ(Greenberger-Horne-Zeilinger)状態を作る量子回路の例である:

∣ψ⟩=(∣000⟩+∣111⟩)/2|\psi\rangle = \left( |000\rangle + |111\rangle \right) / \sqrt{2}
from qiskit import QuantumCircuit

# Create a circuit with a register of three qubits
circ = QuantumCircuit(3)
# H gate on qubit 0, putting this qubit in a superposition of |0> + |1>.
circ.h(0)
# A CX (CNOT) gate on control qubit 0 and target qubit 1 generating a Bell state.
circ.cx(0, 1)
# CX (CNOT) gate on control qubit 0 and target qubit 2 resulting in a GHZ state.
circ.cx(0, 2)
# Draw the circuit
circ.draw('mpl')
先のコードで出力された回路図。

回路の概念と定義

量子回路には多くの専門用語がある。 その多くは量子コンピュータの文献によく見られるものだが、量子ソフトウェア・パッケージに特化したものもあり、Qiskitに特化したものも少しある。 これは、クイックリファレンスとして重要なコンセプトのいくつかをアルファベット順に列挙したもので、基本的なコンセプトの詳細には触れていない。 最初から始めたい場合は、 IBM クォンタム・ラーニング・プラットフォームの利用をご検討ください。

抽象回路

抽象的な数学演算と仮想量子ビットで定義される回路。 抽象的な回路は、完全に任意の単位演算、測定、そして潜在的にリアルタイムの古典的な計算で構成することができ、どの量子ビットが互いに相互作用できるかについての制限はない。

Qiskitのトランスパイルパッケージを使用することで、抽象回路を物理回路に変換します。

アンシラ量子ビット

他の量子ビットに対する演算の実装を助けるために使用されるが、その最終状態はプログラムにとって重要ではない。

回路

QPUで実行される1回の実行を定義する計算ルーチン。 これは抽象的な回路でも 物理的な回路でも構わない。

クリビット

Qiskit特有の略語で、古典的な1ビットのデータを意味する。

ゲート

1つまたは複数の量子ビットに対するユニタリー演算。

ハードウェア量子ビット

特定の QPU 上の単一量子ビットの表現。 ハードウェア量子ビットは、超伝導回路のような物理的な量子力学的システムを持つ。 仮想量子ビットとは異なり、特定の結合制約があり、特定のハードウェア量子ビット群には特定のゲートしか適用できない。

Qiskitは、ハードウェア量子ビットについて話すとき、 論理量子ビットを個々の物理量子ビットと区別しません。 QPUは、そのハードウェア量子ビットを論理量子ビットとして実装することができ、各ハードウェア量子ビットは、制御エレクトロニクスによってQiskitに対して不透明な状態で制御されエラー訂正される多数の物理量子ビットから構成される。 より可能性が高いのは、近い将来のアプリケーションでは、QPUはその物理量子ビットをQiskitが推論するためのハードウェア量子ビットとして直接公開することだろう。

物理的量子ビットと論理的量子ビットの両方が、それらの間に結合制約を持ち、特定の量子演算しか許可されず、それらの間にスケジューリング上の懸念がある。 Qiskitは、ハードウェア量子ビットの概念において、これらの懸念を一緒に抽象化する。 量子エラー訂正の初期には、特定のバックエンドが、その量子ビット・リソースに、高レベルの論理量子ビットとして、あるいはQiskitを通じて低レベルの物理量子ビットとしてアクセスすることができる。

命令セットアーキテクチャ

ある特定の QPUにおいて、どのハードウェア量子ビットのセットでどの演算が可能かを示す抽象モデル。 例えば、あるQPUは、すべての単一ハードウェア量子ビットに対して X\sqrt X と RZR_Z 操作を許可し、特定のハードウェア量子ビットのペアに対して CXCX 操作を許可することができる。

論理量子ビット

複数の物理量子ビットの集合体で、QPUによって(ユーザーの視点から)一緒に制御され、リアルタイムの量子エラー訂正を適用する。 論理量子ビットはQiskitのハードウェア量子ビットの一種。

計算

1つの量子ビットの状態から古典的な1ビットのデータを取り出すこと。 これは不可逆的な操作であり、通常はターゲット量子ビットとシステムの残りの部分との間のもつれや位相コヒーレンスを破壊する。

物理回線

ハードウェア量子ビットと、特定の QPUの ISAで利用可能な量子演算のみで定義された回路。 物理回路は特定のQPUアーキテクチャに縛られており、互換性のない他のアーキテクチャでは動作しない。 ISA回路と呼ばれることもある。

通常、 Qiskitのトランスピレーション・ルーチンを使って 抽象回路を構築すると、物理回路が得られます。

物理量子ビット

制御可能な2レベル量子システム。 これは文字通り、トランスモンやトラップされたイオンの電子状態のような、1つの「物理」量子ビットである。 QPUはこれをハードウェア量子ビットとして直接公開することもできるし、複数の物理量子ビットを組み合わせて論理量子ビットにすることもできる。

量子プロセッシング・ユニット(QPU)

古典的なコンピューティングにおけるCPUやグラフィック処理におけるGPUに似ているが、QPUは量子データに対して量子演算を実行するハードウェアである。 計算の回路モデルを使用するQPUは、 ゲートと 測定演算のセットを実行できることを常に期待できる。 特定の技術によっては、古典的な制御フローや古典的なデータに対するビット演算など、古典的な計算をリアルタイムで実行することもできる。

qubit

量子情報の基本単位。

リアルタイム古典計算

回路のシングルショットの実行中に起こりうる古典的計算で、古典的計算の結果が後の回路の実行に影響を与える可能性があるもの。 特定の QPUで利用可能なリアルタイムの古典的計算量は、制御電子機器や使用されている量子ビット技術など、多くの要因によって大きく異なる。 これについては、ハードウェアベンダーのマニュアルを参照してください。

単体動作

量子状態に対する可逆的な操作。 すべての量子ゲートは (定義上)ユニタリー演算である。

仮想量子ビット

抽象的な回路を構築するために使用される抽象的で数学的な量子ビット。 全ての量子ゲートは全ての仮想量子ビット上で有効であり、全ての仮想量子ビットは常に他の全ての仮想量子ビットに接続されていると仮定する。

ハードウェアにマッピングする場合、仮想量子ビットはハードウェア量子ビットに割り当てなければならない。 この対応付けは一対一である必要はない。 通常、QPUの結合制約を満たすために、回路実行中に1つの仮想量子ビットを1つのハードウェア量子ビットから別のハードウェア量子ビットにスワップする必要がある。 回路で使用されるすべての仮想量子ビットが、 物理回路内の任意の時点で物理量子ビットにマッピングされる必要はない。 これらの条件を評価して仮想回路を物理回路にマッピングするのが Qiskitのトランスパイルパッケージの仕事だ。


qiskit.circuit の API 概要

ここにあるすべてのオブジェクトは、次のセクションでより詳細に、より大きな文脈で説明される。 このセクションでは、ここで文書化されているAPIエレメントの概要を説明する。

主要なクラスは QuantumCircuitであり、回路の構築に関する詳細なセクションを含む独自のドキュメント・ページがある。 量子データと最も単純な古典データは「ビット」と「レジスタ」で表される:

Gate回路内では、各完全な CircuitInstruction は、 Operation (これは、 Instruction、あるいはその他のサブクラスである場合もある)と、量子ビットおよびCLビットのオペランドから構成される。 ここでの主要な基底クラスは以下の通りです:

Instructionこの最小限の抽象 Operation インターフェースの最も一般的な具体的なサブクラスは、です。 は抽象的な数学的対象を含むこともありますが Operation 、とは Instruction 、ハードウェア上で直接実行される可能性のあるものです。 これには、さらにその上にユニタリティと制御されたセマンティクスを追加する および ControlledGate というサブクラスが Gate 派生しています:

  • Instruction、ハードウェアベースの命令を表す
  • Gate, ユニタリなハードウェア命令を表す
  • ControlledGate、制御構造を備えたゲートを表す。

Qiskitには、標準的なゲートと回路の大規模なライブラリが含まれており、そのドキュメントは qiskit.circuit.library. これらの多くは、 Python -オブジェクトのシングルトンとして宣言されている。 そのための仕組みは qiskit.circuit.singletonで詳しく説明されているが、主要なクラスはそれぞれ標準的な命令ゲート階層のシングルトン形式である:

いくつかの命令は、回路の制御フローやデータフローに影響を与えるという点で、特に特殊である。 トップレベルのものは以下の通りだ:

  • Barrier独立して最適化されるべき回路の部分をマークする

  • Delayリアルタイムの待ち時間を挿入する

  • Measureを測定する。 Qubit を Clbit

  • Reset∣0⟩\lvert0\rangle の状態に不可逆的にリセットする

  • Storeリアルタイムで古典的な式をストレージに書き込む

  • ControlFlowOp、これには特定のサブクラスがあります:

    • BreakLoopOp, 最も近い包含ループから抜け出すために
    • ContinueLoopOp, 包含ループの次の反復に直ちに移行する
    • BoxOp、単純な命令の集合
    • ForLoopOp, 特定の値の範囲を繰り返し処理するために
    • IfElseOp、2つのサブ回路のうちいずれか一方に条件付きで分岐するため
    • SwitchCaseOp、複数のサブ回路のうちの1つを条件に応じて選択して入力するため
    • WhileLoopOp、ある条件が偽となるまでサブ回路を繰り返す。

特定の命令にはメタデータによる「注釈」を付けることができ、これは通常、コンパイラのパスによって、その場か、あるいはその後のバックエンド処理のいずれかで利用されることを意図しています。 BoxOp現在、これは.に限定されています。 qiskit.circuit.annotationAnnotationこれらの注釈はのカスタムサブクラスによって表現されており、サポートインフラストラクチャに関するさらなる説明はに記載されています。

回路には、QPU が回路の単一ショットを実行している間にリアルタイムで評価される従来の式を含めることができます。 これらは主に、以下のモジュールのドキュメントに記載されている。 qiskit.circuit.classical. 特にベース・クラス(ルートからは公開されない)に興味があるかもしれない。 qiskit.circuit ルートからは公開されない):

  • Var回路内の型付けされた古典的な記憶場所
  • Expr実時間評価式
  • Type式の古典的な型。

古典的なハードウェアのデータ表現によって制限されるこのリアルタイム式評価に加えて、Qiskitには抽象記号代数で行われる「コンパイル時」パラメトリゼーションの概念がある。 これらは通常、数値微分を実行したいような高レベルアルゴリズムでゲート角を表現するために使用されますが、リアルタイム評価よりもQiskitの古い部分であるため、一般的なパラメトリゼーションを行うためにまだいくつかの場所で使用されています。 主な関連クラスは以下の通り:

この qiskit.circuit モジュールはまた、コンパイルのワークフローを支援するために、回路を扱ういくつかの計算クラスも公開している。 次のものが含まれます。

ランダム回路を生成するユーティリティもある:

最後に、回路モジュールには独自の例外クラスがあり、回路固有のマナーで問題が発生した場合にそれを示す:


Qiskitにおける回路の表現

回路を表現するためのユーザー向けの主なクラスは次のとおりです。 QuantumCircuit. これは抽象的な回路でも物理的な回路でも構わない。 クラスそのものと QuantumCircuit クラスそのものと、そのクラスで利用可能な多数のメソッドについては、クラス・ドキュメントに多くの情報があります。

内部的には、a には QuantumCircuit 、量子ビット、古典ビット、コンパイル時パラメータ、リアルタイム変数、およびそれが作用するデータやそのパラメータ設定方法に関するその他の追跡情報が含まれています。 CircuitInstructionそこには、特定の演算(ゲート、測定など)とそのオペランド(量子ビットおよび古典ビット)を含む一連の「s」が含まれています。

ビットとレジスタ

キュービットと古典的なビットは、共有の基本型によって表現される。 Bit これは単なる「型タグ」であり、クラスには不変オブジェクトであること以外の動作はない:

ビット

class qiskit.circuit.Bit

GitHub

ベース: object

汎用ビットを実装する。

注

このクラスは直接インスタンス化できない。 の汎用型チェックを可能にすることだけが目的です。 Clbit そして Qubit.

量子ビット

class qiskit.circuit.Qubit(register=None, index=None)

GitHub

ベース: Bit

異なる回路間で比較できる量子ビット。

Clbit

class qiskit.circuit.Clbit(register=None, index=None)

GitHub

ベース: Bit

異なる回路間で比較できるビット。

Qubitsとclbitsは、 Qubit() のように、引数なしでユーザーによってインスタンス化される。 ビットは、同じ Python オブジェクトであるか、同じ名前とサイズのレジスタによって作成され、そのレジスタ内の同じインデックスを参照している場合、等しく比較される。 アンシラ "量子ビット用の特別なタイプタグもあるが、Qiskitの現状ではほとんど使われていない:

AncillaQubit

class qiskit.circuit.AncillaQubit

GitHub

ベース: Qubit

アンシラとして使用される量子ビット。

同じ型のコレクション・ビットは、一致する型のレジスタにカプセル化することができる。 ベースとなる機能は、直接インスタンス化されないベース・クラスにある:

レジスター

class qiskit.circuit.Register

GitHub

ベース: object

汎用レジスタを実装する。

注

このクラスは直接インスタンス化できない。 の汎用型チェックを可能にすることだけが目的です。 ClassicalRegister そして QuantumRegister.

定義されたビット・サブタイプにはそれぞれ関連するレジスタがあり、それらは基本クラスと同じコンストラクタのシグネチャ、メソッド、プロパティを持つ:

QuantumRegister

class qiskit.circuit.QuantumRegister(size=None, name=None, bits=None)

GitHub

ベース: Register

レジスターを導入する。

ClassicalRegister

class qiskit.circuit.ClassicalRegister(size=None, name=None, bits=None)

GitHub

ベース: Register

レジスターを導入する。

AncillaRegister

class qiskit.circuit.AncillaRegister(size=None, name=None, bits=None)

GitHub

ベース: QuantumRegister

アンシラレジスターを導入する。

一度に複数のビットをインスタンス化する一般的な方法は、 QuantumRegister("my_qreg", 5) のようにレジスタを作成することである。 これには、ビットの集まりに名前をつけることができるという利点がある。QuantumCircuit.draw())や交換言語( qasm2 および qasm3). 名前とあらかじめ構成されたビットのリストを渡すこともできるが、これは「エイリアシング・レジスタ」を作成することになり、ハードウェアでのサポートが非常に悪い。

回路はレジスタを追跡するが、レジスタ自体は回路にほとんど動作の違いを与えない。 唯一の例外は ClassicalRegistersは、 制御フロー操作の条件付き比較で使用するために、暗黙的に符号なし整数にキャストすることができる。

古典的なレジスタとビットは、Qiskitで古典的なデータを表現する最初の方法であり、現在も最もサポートされています。 長期的には、データモデルはより完全で強く型付けされた様々な古典的データの表現に向かっていますが( リアルタイム古典的計算を参照)、現在のQiskitではまだ古典的なビットをごく普通に使うでしょう。

命令コンテキスト

CircuitInstructionシーケンス QuantumCircuit.data のスカラー型は、「命令コンテキスト」オブジェクトである。 これは本質的に、実行すべき処理(その operation)と、その処理の対象となるデータ( と qubits clbits)を格納する単なるデータクラスに過ぎません。

コラム「 1 」
コラム「 2 」
CircuitInstruction(演算[、量子ビット、CLビット] )の単一命令。 QuantumCircuitoperation 、さまざまなオペランドで構成される。

プログラム上、このクラスは実際にはRustで実装されており、Rust空間内の内部データへのハンドルとして構築されたものです。 このクラスのインスタンスに対する変更は、回路には反映されません。 一般的に、回路内にすでに存在する命令コンテキストを直接変更することはできません。この QuantumCircuit インターフェースは回路の保存や構築を目的として設計されていますが、回路を変更するためのインターフェースについては、 トランスパイラーとその各パス、および中間 DAGCircuit 表現を参照する必要があります。

CircuitInstructionInstructionSetappend()回路に命令を追加するメソッド(や、およびすべてのヘルパー標準ゲートメソッドなど)は QuantumCircuit 、複数のを同時に参照するハンドルである を返します。

コラム「 1 」
コラム「 2 」
InstructionSet(*[, resource_requester] )指導集とその文脈

これは InstructionSet 現在、Qiskitではほとんど使われていません。 この機能は、命令に対して追加後の変更を行うためのごく最小限のメソッドセットを提供していますが(変更内容は回路に反映されます )、これらは現在推奨されていません。代わりに、それらのメソッドに記載されている代替手段を使用してください。

操作、命令、ゲート

OperationCircuitInstructionにおいて、あらゆる操作が満たさなければならない最小限のインターフェースは である。 これは非常に大まかな概要であり、抽象的な回路にのみ適用可能です。 演算を として Operation 扱う主な目的は、任意の数学的対象(例えば quantum_info.Operator)を抽象回路に直接加えることを可能にすることである。

コラム「 1 」
コラム「 2 」
Operation()量子操作インターフェース。

Instruction物理回路に対するすべての操作を含め、ほとんどの操作は、より具体的に定義されたものの具体例である。 Measureこれは、あるQPUがネイティブに実行できる可能性のあるあらゆる命令を表しており、例えば……などです。 GateInstruction ユニタリである必要はない(がそうではないのと同様に Measure );ある命令が、である場合、それは特にユニタリである。

コラム「 1 」
コラム「 2 」
Instruction(name, num_qubits, num_clbits, params)一般的な量子指導。

paramsQubitInstructions は、s と Clbits のみに作用し、その によってパラメータ化されている限り、ほぼ任意のものであってもよい。ただし、外側の回路レジスタを「閉じ込める」ようなことはせず、また、その内部で隠れたパラメータを使用してはならない。 Instructions は他の回路と関連付けることで、その Instruction.definition 属性を利用して分解を行うことができ、これにより局所的かつ一回限りの分解が実現される。 これは、含まれるすべてのゲートの定義に何らかの位相順序が存在する限り、ご自身にとって最も都合の良い演算の基底セットであればどれでも構いません。つまり、そのゲートの定義自体が親ゲートに依存している場合、そのゲートを定義に使用することはできません。 Noneもし が Instruction 最適化ツールに対して完全に不透明であると見なされるのであれば、その は definition とすることができる。 詳細については、「カスタム手順の作成」 を参照してください。

命令の は params 、技術的には任意に設定できますが、一般的には、可能な限り実数を用いたパラメータ化に留めるよう努めるべきです。 Qiskit自体、このルールを多くの箇所で破っており、フィールドには Instruction.params あらゆる種類の珍しい型が見られますが、これらはしばしば型に応じた特別な処理が必要になることを意味するため、厄介なバグの原因となります。 QuantumCircuit.assign_parameters()命令が角度をパラメータとして定義されている場合、 その命令内でコンパイル時のパラメータ化を確実に利用でき、. とシームレスに連携します。

Instructionは Instruction 必ずしもユニタリであるとは限りませんが、そのサブクラスである Gate はユニタリ性を保証し、から継承されたすべてのメソッドに および to_matrix()control() メソッドを追加します。

コラム「 1 」
コラム「 2 」
Gate(名前, 量子ビット数, パラメータ[, ラベル] )ユニタリー・ゲート

GateGate は、の Instruction すべてのメソッドを継承し、その params および definition フィールドに関する考慮事項もすべて同様である。もっとも、sは当然ながら、いかなる古典的なリソースに対しても作用することはできない。

EquivalenceLibrarydefinitionGate インスタンスには基底を指定することも(また、そうすべきですが)できますが、を使用することで、異なる基底を用いた複数の異なる分解を指定することも可能です。

Gateサブクラス化に関しては、Qiskitにも専用の ControlledGate クラスが用意されています。 CXGateこのクラスは、制御される多くの標準ライブラリのゲート(例:)の基盤となっており、実際にこのクラスに出くわすのは、こうした場面が最も多いでしょう:

コラム「 1 」
コラム「 2 」
ControlledGate(名前, 量子ビット数, パラメータ[,...] )制御されたユニタリーゲート。

qiskit.circuit.singleton、 Instruction、 Gate および ControlledGate にはそれぞれ、で説明されている仕組みを用いて構築された、対応するシングルトン型があります。 SingletonControlledGateSingletonInstructionモジュールレベルのドキュメントには、および、 SingletonGate ならびにに関する説明とともに、詳細な情報が記載されています。 base_classユーザーの視点から見ると、基底クラスがシングルトンであるかどうかにかかわらず、ほとんど変化はありません。意図としては、変更しても安全な命令の所有コピーを取得する必要がある場合は、常にまず を to_mutable() 呼び出すべきであるという点に変わりはありません(任意の命令が変更可能であると仮定することはできません)。また、直接的な type 検査は推奨されませんが、どうしても必要な場合は、シングルトンである可能性のある命令の「基底」型を特定する確実な方法として、 を使用します。

ControlledGate サブクラス化ゲートと同じ仕組みを用いて、それ自体に対して固定の遅延合成を定義する。 当然ながら、これはハードウェアを意識したものではなく、コンパイラの合成ルーチンに組み込むのは難しいですが、ハードウェア上でネイティブに実行できる可能性のある具体的な Instruction 実装としては、よりうまく機能します。 base_opAnnotatedOperation合成や抽象的な最適化がより重要となるケースでは、Qiskit は「gate modifiers」(その ControlModifier 一つが )を追跡し、内部の に適用する、という名前のコンポーザブルクラスを提供しています。

コラム「 1 」
コラム「 2 」
AnnotatedOperation(base_op, modifiers)注釈付き操作。

で AnnotatedOperation 利用可能な修飾子は以下の通りです:

InverseModifier

class qiskit.circuit.InverseModifier

GitHub

ベース: Modifier

Inverse修飾子:操作が反転することを指定する。

ControlModifier

class qiskit.circuit.ControlModifier(num_ctrl_qubits=0, ctrl_state=None)

GitHub

ベース: Modifier

制御修飾子:操作が num_ctrl_qubits によって制御され、制御状態 ctrl_state を持つことを指定する。

パラメーター

  • num_ctrl_qubits (int)
  • ctrl_state (int |str | None)

PowerModifier

class qiskit.circuit.PowerModifier(power)

GitHub

ベース: Modifier

べき乗修飾子:操作のべき乗を指定 power。

パラメーター

power (float)

カスタム・ゲートやカスタム・インストラクションを作成する方法については、1つだけのオブジェクトを作成する方法や、サブクラス化による再利用可能なパラメトリック・ゲートを作成する方法を含めて、以下のカスタム・インストラクションの作成を参照してください。 のQiskit 回路ライブラリには qiskit.circuit.library には多くの定義済みゲートと回路が含まれています。

内蔵の特殊命令

Qiskit には、ある意味で「特別な」クラスがいくつか Instruction 含まれています。 これらは通常、回路コード、トランスパイラ、あるいはハードウェアのモデルにおいて、特別な処理が行われます。 これらは、概して、皆さんもすでにご存じかもしれない手順です。

Qiskitでの測定は、単一の Qubit を単一の Clbit. この2つが指導の対象となる。 測定は計算ベースである。

測定

class qiskit.circuit.Measure(label=None)

GitHub

ベース: SingletonInstruction

計算基礎における量子測定。

パラメーター

label - この命令のオプションの文字列ラベル。

測定に関連して Reset これは古典的なデータを生成しないが、ハードウェアに量子ビットを ∣0⟩\lvert0\rangle の状態に戻すよう指示する。 これは支離滅裂に起こり、あらゆるもつれを崩壊させると仮定されている。

リセット

class qiskit.circuit.Reset(label=None)

GitHub

ベース: SingletonInstruction

∣0⟩\lvert0\rangle、量子ビットをインコヒーレントにリセットする。

パラメーター

label - この命令のオプションの文字列ラベル。

ハードウェアに対して、特定の量子ビットにリアルタイムのアイドル期間を適用するよう指示することができます。 Delayqiskit.transpiler予定回路(参照)には、この を用いて、量子ビットのすべてのアイドル時間が明示的に含まれる。 BoxOp また、その BoxOp.duration フィールドに明示的な継続時間が指定されることもあります。

遅延

class qiskit.circuit.Delay(duration, unit=None)

GitHub

ベース: Instruction

何もせず、指定された時間だけ遅延/待機/アイドルする。

パラメーター

  • duration - 継続時間の長さ。 これが Exprの定数式でなければならない。 Duration でなければならず、 unit パラメータは省略されなければならない(指定された場合は "expr "でなければならない)。
  • unit - 持続時間の単位。 duration が数値の場合。 "dt"、SI接頭辞付きの秒単位、または "expr "でなければならない。

レイズ

CircuitError - duration 、タイミングベースではない解決された型が指定されたか、 unit の指定が不適切であった。

遅延時間は、具体的な一定の時間で指定することもできるし、オブジェクトから作られた遅延解決の "継続時間式 "で指定することもできる。 expr.Stretch オブジェクトから作られる 詳しくは「 遅延解決スケジューリング 」を参照。

この Barrier 命令は任意の数のqubitsとclbitsにまたがることができ、ハードウェアではno-opである。 しかし、トランスパイルと最適化の間は、最適化がバリアを "越える "のをブロックする:

from qiskit.circuit import QuantumCircuit

qc = QuantumCircuit(1)
qc.x(0)
qc.barrier()
qc.x(0)

オプティマイザが2つの命令( XX )を打ち消すことは禁じられている。

障壁

class qiskit.circuit.Barrier(num_qubits, label=None)

GitHub

ベース: Instruction

最適化や再書き込みがバリア間でのみ行われるように、回路の断片を分離する回路コンパイルの指示。

これはビジュアライゼーションでもビジュアルマーカーとして表示される。

パラメーター

  • num_qubits (int) – バリアの量子ビット数。
  • label (str | None) – このバリアのオプションのラベル。

この Store 命令は特に特殊で、 リアルタイム古典計算式の結果(an expr.Expr)をローカル古典変数(a expr.Var). を必要としない。 Qubit も Clbit オペランドは取らないが、明示的に lvalue と rvalue.

例えば、ビット列 cr のパリティを決定し、それを別のレジスタ creg に格納するには、次のように命令を使用することができる。 Store 命令は次のように使用できる:

parity = expr.lift(cr[0])
for i in range(1,n):
    parity = expr.bit_xor(cr[i], parity)
qc.store(creg[0], parity)

ストア

class qiskit.circuit.Store(lvalue, rvalue)

GitHub

ベース: Instruction

古典的なメモリ位置に古典的な値を手動で保存すること。

これは古典式処理の低レベルプリミティブであり(量子測定のプリミティブである Measure 量子測定のプリミティブに似ている)、サブクラス化するのは危険である。

パラメーター

  • lvalue (expr.Expr) – 保存されるメモリー位置。
  • rvalue (expr.Expr) – 式の結果が格納される。
lvalue

L値を取得する Expr ノードを取得する。

rvalue

l値に書き込まれているr値 Expr ノードを取得する。

リアルタイム古典計算

関連資料

qiskit.circuit.classical

変数、式、型システムの仕組み、それらを表現するためのオブジェクト、利用可能な古典的操作について、モジュール・レベルのドキュメント。

リアルタイムでタイプされたクラシック・データを扱う

これらの変数を QuantumCircuit これらの変数を1つの回路の中で扱う方法。

Qiskitは、QPUの実行中に起こり、結果に影響を与えるリアルタイムの古典的な計算を表現するための初歩的な低レベルのサポートを持っています。 このようなコンセプトのハードウェア・サポートはまだ比較的初期段階にあるので、リアルタイム・クラシカル計算を最大限に活用するためには、ハードウェア・プロバイダのドキュメントと密接に連携する必要がある。

これらのリアルタイム計算は、以下の式と型システムで表現される。 qiskit.circuit.classical. 高いレベルでは、すべてのリアルタイム式は、式の「ツリー」表現の一部である Expr ノードで表現される。このノードは、式の「ツリー」表現の一部であり、各レベルで明確に定義された Type 。 これらのクラスの内部表現の詳細については、モジュール・レベルのドキュメントを参照のこと。

リアルタイム Expr 処理の結果は、特定の場面で直接利用することができます。 SwitchCaseOpWhileLoopOp現在、これは および の IfElseOp 条件、ならびに のターゲットに限定されています。 結果は、ノードを expr.Var バックエンドとする命令 Store (またはその QuantumCircuit.store() コンストラクタ)を使用して、型付き従来の格納場所に格納することもできます。

回路は、古典的な手動記憶場所を含むことができる。 Var ツリーの Expr ツリーで表現される。 これらは、(他の式と同様に)付属の古典型を持っています。 これらは回路の各実行で宣言され、初期化される (add_var())、または回路への入力(add_input()).

コンパイル時パラメータ化

Qiskit のさまざまな Instruction パラメトリックインスタンスは、コンパイル時に解決されるように設計された方法でパラメータ化することができます。 これらは、 および ParameterExpression クラスの Parameter 使用を特徴としています。

コラム「 1 」
コラム「 2 」
Parameter(名前[, UUID] )コンパイル時のシンボリック・パラメーター。
ParameterExpression(name_map, expr)パラメータ式。

これが、リアルタイムの古典的計算で使用される変数と異なる主な点は、が expr.Var 数学式の記号表現であるという点 ParameterExpression です。 この式の意味論は、連続実数(および、限られた場合において、複素数)上の通常の数学におけるものと同じである。 対照的に、 Var は、浮動小数点値や固定幅の整数など、常に離散的な値をとる、従来のコンピュータ上に格納された変数へのハンドルである。

つまり、 (x+y−x)/y→1(x + y - x) / y \to 1 を簡略化するなど、数学的には有効な記号的な簡略化を行うことが期待 ParameterExpression されます。このような簡略化は浮動小数点演算では有効ではなく、この処理は行われません。 expr.Expr

これらのパラメーターの "コンパイル時 "の部分は、通常、回路を実行するために送信する前に、パラメーターに値を "割り当てる "ことを意味する。 これらのパラメーターは通常、数学的な角度を期待するところ(回転ゲートのパラメーターのような)ならどこでも使うことができるが、ハードウェアは通常、実行前に適切な古典的型付け値に代入することを要求するという注意点がある。 この課題は QuantumCircuit.assign_parameters().

互いに関連し合う多くのパラメータを使用したい場合もあるでしょう。 ParameterVectorこれを簡単にするため(そして、たくさんの名前を考えなくて済むようにするため)、便利なコンストラクタを使用することができます。 ParameterVectorElementベクトルの各要素は、すべてある特別なサブクラスの有効 Parameter なインスタンスである。

コラム「 1 」
コラム「 2 」
ParameterVector(名前[、長さ、UUID] )関連 Parameter する多くのオブジェクトを格納するコンテナ。
ParameterVectorElement(ベクトル, インデックス[, UUID] )ParameterVector. の要素。

回路における制御フロー

ControlFlowOpInstructionQuantumCircuitにおいて、古典的な制御フローは、のサブクラスである特定のsによって表現される。

コラム「 1 」
コラム「 2 」
ControlFlowOp(name, num_qubits, num_clbits,...)すべての制御フロー操作をカプセル化する抽象クラス。

便宜上、各制御フロー操作の属 Instruction.name 性を格納したインスタンス frozenset が用意されています。

qiskit.circuit.CONTROL_FLOW_OP_NAMES

Qiskitの既知のコントロールフロー操作の命令名のセット。

この get_control_flow_name_mapping() 関数を使うと、それぞれの名前に関連づけられたコントロール・フロー・オペレーション・クラスにアクセスすることができる。

get_control_flow_name_mapping

qiskit.circuit.get_control_flow_name_mapping()

GitHub

コントロール・フロー操作の名前を、対応するクラスにマッピングした辞書を返す。"

例

from qiskit.circuit import get_control_flow_name_mapping

ctrl_flow_name_map = get_control_flow_name_mapping()
if_else_object = ctrl_flow_name_map["if_else"]

print(if_else_object)
<class 'qiskit.circuit.controlflow.if_else.IfElseOp'>

これらの制御フロー演算(IfElseOp, WhileLoopOp, SwitchCaseOp, ForLoopOp, および BoxOp)はすべて、分岐条件や分岐戦略を定義する固有の状態を持っていますが、その blocks property には、実行される可能性のあるあらゆる種類のサブ回路ブロックが含まれています。

コラム「 1 」
コラム「 2 」
IfElseOp(条件, true_body[, false_body,...] )提供された条件(condition)が真と評価された場合にプログラム(true_body)を実行し、オプションでそれ以外の場合に別のプログラム(false_body)を評価する回路操作。
WhileLoopOp(条件、本体[、ラベル] )条件(condition)が偽と評価されるまで、サブ回路(body)を繰り返し実行する回路操作。
SwitchCaseOp(ターゲット, ケース, *[, ラベル] )与えられた target と、 values の順序付きリストとのマッチングに基づいて、ある特定の回路ブロックを実行する回路操作。
ForLoopOp(インデックスセット, ループパラメータ, 本体[,...] )パラメータ loop_parameter でパラメタライズされたサブサーキット(body)を、 indexset で指定された整数値の集合を通して繰り返し実行する回路操作。
BoxOp(本体[、期間、単位、ラベル、注釈] )より大きなコンテキストの中でアトミックに扱われる、回路上の操作のスコープ付き「ボックス」。

また、この SwitchCaseOp 関数は特別な値も認識します:

qiskit.circuit.CASE_DEFAULT

デフォルト値: <default case>

switch文の「デフォルト」ケースを表す特別なオブジェクト。 これをケース・ターゲットとして使う場合は、最後のケースでなければならず、まだマッチしていないものすべてにマッチする。 のビルダー・インターフェースを使用する場合、これは QuantumCircuit.switch()のビルダー・インターフェースを使う場合,これはバインドされたケース・ビルダー・オブジェクトの DEFAULT 属性としてアクセスすることもできます.

ブロック構造の制御フロー操作に加えて、ループ内の制御フローに影響を与える特別な命令が2つある。 これらは、古典的なプログラミング言語における break と continue ステートメントの典型的な使い方に相当する。

コラム「 1 」
コラム「 2 」
BreakLoopOp(num_qubits, num_clbits[, label] )最も近いループの終わりにジャンプする回路操作。
ContinueLoopOp(num_qubits, num_clbits[, label] )最も近いループの次の反復に移る回路操作。
注

各クラスの表現方法については、ここに文書化されているが、手作業でこれらのクラスを構築するのは低レベルの作業であり、ユーザーが頻繁に行う必要はないと思われることに注意してほしい。

コントロール・フロー対応の回路を構築するための推奨ワークフローについては、「 回路にコントロール・フローを追加する 」をお読みください。

サブクラスもまた Instruction サブクラスであるため ControlFlowOp 、インスタンス内に CircuitInstruction 格納されるその仕組み上、それらの属性である clbitsqubits と には、一連の量子ビット(qubit)およびクラビット(clbit)が「適用」されていることになる。 CircuitInstructionこれにより、微妙なデータ一貫性の問題が生じる可能性があります。つまり、制御フロー演算子のサブ回路ブロック内で使用される および Clbit オブジェクトは Qubit 、必ずしも 内の対応するオブジェクトと同一であるとは限りません。 outer_instruction.qubits[i]Qiskit で制御フロー操作を利用するコードは、この点を考慮する必要があります。サブ回路内では、 をあたかも であるかのように扱う subcircuit.qubits[i] 必要があります。以下同様です。 次のようにすれば、このための簡単な参照テーブルを作成できます:

cf_instruction: CircuitInstruction = ...
cf_operation: ControlFlowOp = cf_instruction.operation
for block in blocks:
    # Mappings of "inner" qubits/clbits to the outer ones.
    qubit_map = dict(zip(block.qubits, cf_instruction.qubits))
    clbit_map = dict(zip(block.clbits, cf_instruction.clbits))

    # ... do something with `block` ...

コントロール・フロー操作のサブブロックに再帰する場合は、この情報を伝播する必要があることを覚えておいてほしい。

a ControlFlowOp 内のすべてのサブ回路ブロックは、上記のコードブロックに示されたループが zip 正しく動作するように、同じ数の Qubits と Clbits を含み、かつ同じ順序で同じ外側のビットを参照している必要があります。 内部 Bit 回路のオブジェクトは、文字通り同じオブジェクトである必要はありません。 {x: x}制御フロービルダーのインターフェースを使用する場合(これは、いくら強調してもしすぎることはないほど、ユーザーに強く推奨されます)、ビルダーは内部のビットオブジェクトが外部のビットオブジェクトと同一になるように調整します。上記のコードブロック内の qubit_map は常にマッピング になりますが、ブロックを利用する場合は、マッピングが必要となるケースに備えておく必要があります。

ClassicalRegister制御フローサブ回路で使用されるsは、それを含むすべてのブロック( すなわち、それを含むすべての制御フロー演算および最外側の回路)にも存在していなければならず、また、同じ ControlFlowOp 制御フローサブ回路内のすべてのブロックには、同じレジスタが含まれている必要があります。 繰り返しになりますが、ビルダーインターフェースがこれを自動的に処理します(処理できない場合は、即座にエラーを発生させます)。

低レベル構造が使用されている場合 QuantumCircuit ブロックが使用するアウター・スコープ・リアルタイム古典計算変数を手動でクローズしなければならない。 これは iter_captured_vars() イテレータの中にある。 これらのブロックを手動で構築するライブラリは、制御フロー回路ブロックを構築する際に、これらのキャプチャを追跡し、ブロックに追加する必要があります。 add_capture() (またはコンストラクタの引数 captures )を使用してブロックに追加する必要があるが、ユーザーコードは通常、自動的にこれを処理するコントロール・フロー・ビルダー・インターフェースを使用する。

コントロール・フローを使った回路の作り方の詳細については、 コントロール・フロー・コンストラクションのドキュメントを参照してください。

命令ローカル注釈

関連資料

qiskit.circuit.annotation

カスタムアノテーションの定義方法や、システムがコンパイラーや他のフォーマットへのシリアライゼーションとどのように相互作用するかを含む、アノテーションフレームワークのモジュールレベルの議論。

特定の回路命令には、命令ローカルなアノテーションを「付与」することができます。 BoxOpQiskit 2.1.0 の時点では、これは に限定されています。 すべてのアノテーションは、1つの基底インターフェース定義オブジェクトのサブクラスですが、通常は完全に独自に定義された分析やコマンドを表しています。

コラム「 1 」
コラム「 2 」
Annotation(*args, **kwargs)命令に対する任意の注釈。

可換関係式の研究

回路内の2つの演算が互いに競合する場合、その演算を適用する順番を入れ替えることができる。 これにより、例えばゲートのマージやキャンセルが可能になれば、最適化や簡略化が可能になる:

     ┌─────────┐     ┌─────────┐               ┌─────────┐
q_0: ┤ Rz(0.5) ├──■──┤ Rz(1.2) ├──■──     q_0: ┤ Rz(1.7) ├
     └─────────┘┌─┴─┐└──┬───┬──┘┌─┴─┐  =       └──┬───┬──┘
q_1: ───────────┤ X ├───┤ X ├───┤ X ├     q_1: ───┤ X ├───
                └───┘   └───┘   └───┘             └───┘

CommutationCheckerこれらの最適化の処理はトランスパイラーの一部ですが、交換を調査するためのツールは. に用意されています。

コラム「 1 」
コラム「 2 」
CommutationChecker([...])2つの操作のコミュテーションをチェックする。

遅延解決スケジューリング

通常、Qiskitのコンパイラによる出力は、QPU上で直接実行することはできません。 まず、ベンダー固有のパルスレベルコンパイラを経由する可能性が高い。このコンパイラは、ゲートや測定値を、QPUの制御用電子回路への信号に変換する。 Qiskit Target では、これらのパルスが持つタイミング制約の一部を表現することはできますが、一般的に完全とは言えません。 これは、動的回路(フィードフォワード演算)が関与する場合に特に当てはまります。従来のコンポーネントによって生じる遅延は、多くの場合、バックエンドコンパイラの最適化後の低レベルの詳細に依存しており、Qiskitでは把握することができません。

このような状況でも、ユーザーは "ストレッチ "デュレーションを使用することで、ダイナミック・デカップリングのようにパルスの相対的なスケジューリングをコントロールすることができる。 これらは QuantumCircuit.add_stretch()で説明されている古典的表現システムと相互作用する。 qiskit.circuit.classicalで説明されている古典的表現システムと相互作用する。

例えば、ストレッチとボックスを追加することで、同じ量子ビットに2つの異なる動的切り離しシーケンスが適用され、他の量子ビットが未知の遅延を受けるようなシステムを構築することができる。 内部的には具体的なDDパルスの長さが異なっていても、2つのシーケンスは同じ長さになるように制約されている。

from qiskit import QuantumCircuit
from qiskit.circuit.classical import expr

qc = QuantumCircuit(3, 3)
# This sets up three duration "degrees of freedom" that will
# be resolved later by a backend compiler.
a = qc.add_stretch("a")
b = qc.add_stretch("b")
c = qc.add_stretch("c")

# This set of operations involves feed-forward operations that
# Qiskit cannot know the length of.
with qc.box():
    qc.h(1)
    qc.cx(1, 2)
    qc.measure([1, 2], [1, 2])
    with qc.if_test(expr.equal(qc.clbits[1], qc.clbits[2])):
        qc.h(1)

# While that stuff is happening to qubits (1, 2), we want
# qubit 0 to do two different DD sequences.  The two DD
# sequences are fixed to be the same length as each other,
# even though they're both internally stretchy.
with qc.box(duration=a):
    # Textbook NMRish XX DD.
    qc.delay(b, 0)
    qc.x(0)
    qc.delay(expr.mul(2, b), 0)
    qc.x(0)
    qc.delay(b, 0)
with qc.box(duration=a):
    # XY4-like DD.
    for _ in range(2):
        qc.delay(c, 0)
        qc.y(0)
        qc.delay(expr.mul(2, c), 0)
        qc.x(0)
        qc.delay(c, 0)

カスタム指示の作成

QuantumCircuit回路に追加する単純な単発の命令やゲートを作成したい場合、かつブロックが単に可視化やグループ化の目的で利用されるだけであるならば、カスタム命令やゲートを作成する最も簡単な方法は、その定義をとして構築し、必要に応じてその to_instruction() または to_gate() メソッドを使用することです。 結果は、より大きな回路上で直接 に QuantumCircuit.append() 与えることができます。 これらのメソッドは、属性として指定された回路を持つ definition ベース Instruction または Gate インスタンスを作成します。つまり、その属性はトランスパイラーや、回路を分解しようとするその他のQiskit関数から自動的にアクセス可能になります。

複雑な制御フローを使用する必要がある命令は、compose()を使用して、 QuantumCircuit にインライン化する必要があります。

命令サブクラスの作成

基底クラス Instruction、 Gate 、 ControlledGate はいずれも、サブクラス化しても安全になるように設計されており、サブクラスが実装するためのフックポイントが用意されています。 SingletonGateqiskit.circuit.singletonカスタムゲートがパラメータを持たず、ステートレスである場合は、 内の対応するシングルトンクラス(例:)を継承することも検討するとよいでしょう。 シングルトン機構に関するその他のメソッドやフックポイントについては、の qiskit.circuit.singleton ドキュメントを参照してください。

サブクラスでは通常、その指示に適した引数を指定して :class\super` コンストラクタを呼び出すデフォルトコンストラクタを定義する必要があります。 Instruction.paramsクラスに余分な状態を含めることは可能ですが、サブクラスがQiskitの他の仕組みと最も確実に連携するためには、自身のパラメータのみに依存し、それらのパラメータが純粋にゲート角度であるようにすることが望ましいです。

(またはそのサブクラスのいずれか)の Instruction サブクラスは、プライベート Instruction._define() メソッドを実装する必要があります。このメソッドは、パブリック definition メソッドの基盤となる非表示 _definition のキャッシュを遅延的に初期化します。

_define

Instruction._define()

GitHub

Instructionこの の「キャッシュ _definition 」フィールドに値を設定してください。

サブクラスは、パブリック definition 属性の遅延生成を実現するために、このメソッドを実装する必要があります。 サブクラスは、呼び出し時にその params 機能を使用することができます。 このメソッドは、 に を QuantumCircuit 代入 _definition し、値を返してはならない。

ControlledGateのサブクラスでは、この _define() メソッドは、すべてのビットが1の制御状態の場合にのみ、分解を実装すべきである。 この処理は、実際の制御状態に対応できるよう、システムによって ControlledGate.definition 修正されます。

サブクラスがシングルトン機構を使用している場合、クラス本体文が実行された直後に _define() は、正規のシングルトン・オブジェクトの定義オブジェクトを生成するために、クラス本体文が実行された直後に熱心に呼び出されることに注意してください。 つまり、あなたの定義では、すでに定義されているゲートのみを使用しなければならない。多くのシングルトン・ゲートを持つライブラリを書く場合は、これが可能になるようにファイルやインポートの順序を決めなければならない。

__array__の Gate サブクラスも、 Numpyの配列プロトコルインスタンスメソッドである をオーバーライドしたい場合が多いでしょう。 Gate.to_matrix()これは によって使用され、シグネチャは次のとおりです:

__array__

object.__array__(dtype=None, copy=None)

ゲートを表すNumPy配列を返す。 これにより、ゲ params ートのフィールドを利用することができ、これらは数値(サブクラスがそれを想定している場合)であり、 コンパイル時のパラメータではないとみなすことができます。

最大の効率を得るためには、返される配列のデフォルトのd型は complex.

カスタムサブクラスに、制御形や逆形の自然な表現がある場合は、 および control() メソッドも inverse() オーバーライドするとよいでしょう。

カスタム RxzR_{xz} ゲート、つまり XZXZ 軸を中心とした単一角度の回転を定義する例として。 RZXGateこれは本質的に、量子ビットの向きが逆だった場合と同じことなので、そのことを踏まえて定義を記述することにします。 Gate我々はパラメトリックであるため、シングルトンにはなり得ないが、ユニタリであるため、以下であるはずだ:

import math
import numpy as np
from qiskit.circuit import Gate, QuantumCircuit

class RXZGate(Gate):
    def __init__(self, theta):
        # Initialize with our name, number of qubits and parameters.
        super().__init__("rxz", 2, [theta])

    def _define(self):
        # Our base definition is an RZXGate, applied "backwards".
        defn = QuantumCircuit(2)
        defn.rzx(1, 0)
        self._definition = defn

    def inverse(self, annotated = False):
        # We have an efficient representation of our inverse,
        # so we'll override this method.
        return RXZGate(-self.params[0])

    def power(self, exponent: float):
        # Also we have an efficient representation of power.
        return RXZGate(exponent * self.params[0])

    def __array__(self, dtype=None, copy=None):
        if copy is False:
            raise ValueError("unable to avoid copy while creating an array as requested")
        cos = math.cos(0.5 * self.params[0])
        isin = 1j * math.sin(0.5 * self.params[0])
        return np.array([
            [cos, -isin, 0, 0],
            [-isin, cos, 0, 0],
            [0, 0, cos, isin],
            [0, 0, isin, cos],
        ], dtype=dtype)

SessionEquivalenceLibraryRZXGateこの例では、を基底として基底定義を定義しましたが、さまざまな基底への分解をより高速に行うためには、にさらにいくつかの同値関係を追加したくなるかもしれません。 なお、翻訳検索では BasisTranslator 、あらゆる深さにおけるすべての可能な等価関係が検索対象となるため、(例えば) XGate を用いて等価関係を指定すると、自動的に を用いた RXGate 分解も利用可能になります。

任意の記号パラメータについて、 HH、 CXCX、 RzR_z の観点から同値性を追加してみよう:

from qiskit.circuit import SessionEquivalenceLibrary, Parameter

theta = Parameter("theta")

equiv = QuantumCircuit(2)
equiv.h(0)
equiv.cx(1, 0)
equiv.rz(theta, 0)
equiv.cx(1, 0)
equiv.h(0)

SessionEquivalenceLibrary.add_equivalence(RZXGate(theta), equiv)

これ以降、 Python のインタプリタセッションが継続している間、のような BasisTranslator 翻訳ツールは、検索時にこの新しい定義を参照できるようになります。


回路レベルのオブジェクトを扱う

抽象回路を物理回路へ変換する

抽象的な QuantumCircuit はハードウェア上で確実に実行することはできない。 小規模な回路であれば、『 回路をシミュレートする 』にリンクされているハイレベル・シミュレータのいくつかを使って素早く結果を出すことができるかもしれないが、ユーティリティ・スケールの回路を動かすには、実際のハードウェアを使う必要があり、それには物理的な回路にコンパイルする必要がある。

targettranspile()これを行うための高レベル関数は です。この関数は、抽象回路とハードウェア backend または を受け取り、物理回路を返します。 実行されるパスの各段階に対して、より詳細なアクセスや制御を行いたい場合は、まず を使用して generate_preset_pass_manager() を作成 StagedPassManager し、それを後で変更してください。

完全なトランスパイルとコンパイルの仕組みについては qiskit.transpiler モジュールのドキュメントに、そしてQiskitに組み込まれたすべてのパスの詳細は qiskit.transpiler.passes.

回路のシミュレーション

インターフェースの一部ではありませんが qiskit.circuit インターフェイスの一部ではありませんが、最も一般的なニーズの1つは、オブジェクトのシミュレーション結果を素早く得ることです。 QuantumCircuit オブジェクトのシミュレーション結果を素早く得ることです。 このセクションでは、関連する情報を見つけるために、ドキュメントの他の場所への迅速なジャンプオフポイントを提供します。

Statevector ユニタリー回路の場合、 ∣0⋯0⟩\lvert0\dotsm0\rangle の状態への影響をシミュレートするには、をデフォルトコンストラクタに直接渡します QuantumCircuit 。 同様に、回路を表す単位行列をオペレータとして取得するには、それをデフォルトコンストラクタ Operator に渡せばよい。 物理回路がある場合は、代わりにそれをメソッドに渡して Operator.from_circuit() 、からの変換を QuantumCircuit.layout 適用し、「抽象的な」量子ビット空間にマッピングし直すことを検討するとよいでしょう。

よりバックエンドに近いシミュレーション体験のために、すべてのQiskitハードウェアインターフェースのシミュレータバック実装があります。 特にご興味があるのは

同値関係の定義

抽象的な回路を物理的なハードウェアにマッピングし、その結果を最適化する際によく行われる作業の一つは、あるゲートを別の基底集合にマッピングする同値関係を見つけることである。 EquivalenceLibraryQiskit は、この情報を「」という名前のデータベースクラスに保存します。

コラム「 1 」
コラム「 2 」
EquivalenceLibrary( [ベース] )ゲートの一方向マッピングを提供するライブラリで、 QuantumCircuits として同等の実装を提供する。

Qiskitは、すべての標準ゲートについて、事前に定義された等価関係の大規模なセットを同梱しています。 この基本ライブラリーは StandardEquivalenceLibraryと呼ばれ、不変のものとして扱われるべきである。

qiskit.circuit.StandardEquivalenceLibrary

Qiskitに組み込まれているすべての標準ゲートの関係性を格納するA EquivalenceLibrary 。 SessionEquivalenceLibrarybaseこれを直接変更してはいけません。代わりに、これをテンプレートとして独自の EquivalenceLibrary インスタンスを作成するか、グローバル状態を変更してください。

SessionEquivalenceLibraryQiskit では、共有グローバル状態オブジェクトも定義されています。これは、Qiskit のさまざまな箇所、とりわけトランパイラ・パス BasisTranslator で使用されるデフォルトの等価関係です。 BasisTranslatorこの add_equivalence() メソッドを使用して、ご自身で対応関係を自由に追加してください。追加された対応関係は、のデフォルトインスタンスによって自動的に認識されます。

qiskit.circuit.SessionEquivalenceLibrary

EquivalenceLibraryのデフォルトインスタンス。ライブラリを手動で指定しない場合、ほとんどのQiskitオブジェクトでこれを使用します。 add_equivalence(). を使って、これに等価な式を自由に追加しても構いません。 StandardEquivalenceLibraryこれは、のすべての組み込みルールを継承しています。

回路にパウリ・スピンを適用する

量子回路の実行時に発生するノイズには、主に2種類ある。 ひとつは、量子プロセッサーと外部環境との不要な相互作用に起因する確率的ノイズ、つまりインコヒーレントなノイズである。 もうひとつはコヒーレントエラーと呼ばれるもので、量子系の制御が不完全なために生じるエラーである。 これは、システムのハミルトニアンに含まれる不要な項、すなわち誤ったユニタリー進化であったり、量子システムの誤った時間制御によるエラーであったりする。

パウリ・ツワーリングは量子エラー抑制技術であり、ランダム化を用いてコヒーレントなエラーを確率的エラーに変換する。 Qiskitは、標準的な2量子ビットゲートに対して、与えられた回路にパウリ・ツワーリングを適用する関数を提供します。 詳細については、以下の関数のドキュメントを参照してください:

pauli_twirl_2q_gates

qiskit.circuit.pauli_twirl_2q_gates(circuit, twirling_gate=None, seed=None, num_twirls=None, target=None)

GitHub

指定された2つの量子ビットゲートの周りにパウリ回転を適用した回路のコピーを作成する。

この関数を、ハードウェア上で動作する回路をトワリングする目的で実行する場合、トワリングを実行する最も効率的な方法ではないかもしれない。 特にハードウェアベンダーが primitives 特に、ハードウェアベンダーが SamplerV2 と EstimatorV2 で実行インターフェースを実装している場合、これはあなたの回路にトワリングを適用する最良の方法ではない可能性が高いので、指定されたハードウェアベンダーの SamplerV2 および/または EstimatorV2 の実装を参照することをお勧めします。

この関数が または PassManager.run() の transpile() 後に実行されることを意図している場合、オプションの target 引数を使用することで、挿入される 1 量子ビットのパウリゲートが、指定 Target された と互換性があるように合成され、出力回路の互換性が維持されるようにすることができます。

パラメーター

  • circuit (QuantumCircuit) – 回転するサーキット
  • twirling_gate (None | str |Gate |list[str] | list[Gate]) – 「twirl」のゲートは、デフォルトで「None」に設定されています。これは、すべてのデフォルトゲート( CXGate, CZGate, ECRGate, および iSwapGate)をtwirlすることを意味します。 指定された場合、単一のゲート、またはゲートオブジェクトもしくはその文字列名として表されるゲートのリストのいずれかになります。 現在、「cx」、「cz」、「ecr」、「iswap」という名前のみがサポートされています。 デフォルトのゲートの外側にゲートオブジェクトが配置される場合、そのゲートがツイールされる可能性があるように、その to_matrix メソッドから行列が定義されている必要があります。 有効なツイール設定を計算できない場合、その特定のゲートは黙って無視され、ツイール処理は行われません。
  • seed (int | None) – この関数が内部的に使用する乱数生成器の整数シード。 指定する場合は、0から18,446,744,073,709,551,615の間でなければならない。
  • num_twirls (int | None) – 作るクルクル回路の数。 デフォルトは None 、単一の回路を返す。 整数であれば、num_twirls 回路のリストが返される。
  • target (Target | None) – 指定された場合、回路に追加されたパウリゲートを最適化し、指定されたターゲットにマッピングするためのパウリ・トゥワーリングの一環として、単一量子ビットの分解を実行するために使用するインスタンス Target 。

戻り値

指定されたトワーリングゲートの各インスタンスにパウリトワーリングを適用した、指定された回路のコピー。

戻りの型

QuantumCircuit | リスト QuantumCircuit ]


例外

ほとんどすべての回路関数とメソッドは、Qiskitの使用法特有のエラーに遭遇したときに CircuitError を送出します (通常の型付けやインデックスの問題とは異なり、通常は対応する標準の Python エラーが送出されます)。

CircuitError

exception qiskit.circuit.CircuitError(*message)

GitHub

ベース: QiskitError

回路の処理中に発生したエラーの基本クラス。

エラーメッセージを設定する。


回路の慣例

抽象的なオブジェクトと、より具体的な行列から回路を構成する場合、ビットラベル、ビット順序、抽象的なテンソル積を具体的な行列代数でどのように実現するかなど、いくつかの規約が考えられる。

Qiskitの規約は以下の通り:

  • ビット列表現では、ビットは、 00 と呼ばれる文字列の右端のビットと、 n−1n - 1 と呼ばれる nn ビットの文字列の左端のビットでラベル付けされる。
  • 回路構成関数でビット指定子のインデックスとして整数を使用する場合、整数は次のインデックスとして扱われます。 QuantumCircuit.qubits (または clbits).
  • 回路を描くときは、インデックスの低いビットを上に置く。
  • 状態ベクトル表現では、抽象的なテンソル積をクロネッカー積として実現し、計算基底状態 ∣x⟩\lvert x\rangle の振幅が、 xx を整数として解釈したビット列の位置 statevector[x] になるように、この引数を順番に並べる。
  • ゲートを制御する場合、制御量子ビットは引数リストの最初に置かれる。 例えば、 qc.cx(0, 1) の呼び出しでは、量子ビット0が制御となり、量子ビット1がターゲットとなる。 同様に、マニュアルコール( qc.append(CXGate(), [0, 1]) )では、量子ビット0がコントロール、量子ビット1がターゲットとなる。

これらの慣例をいくつかの例で説明しよう。

ビットラベリング

サーキットを走る:

from qiskit import QuantumCircuit

qc = QuantumCircuit(5, 5)
qc.x(0)
qc.x(1)
qc.x(4)
qc.measure(range(5), range(5))

これは、量子ビット0、1、4の状態を ∣0⟩\lvert0\rangle から ∣1⟩\lvert1\rangle に反転させ、計算( ZZ )基底を使用して、すべての量子ビット nn を対応する clbit nn に測定する。 ノイズレスでシミュレーションした場合、この回路から出力されるビット列は毎回 1001110011。量子ビット0、1、4は反転し、ビット列の「1」の値は右から 0桁目、1桁目、4桁目になる。

Qiskitでは、測定直前の量子ビットの状態をケット表記略記で ∣10011⟩\lvert10011\rangle と書きます。ketラベルは古典的なビット列と一致し、2進数で19であることに注意してください。

この回路を描いてみると、Qiskitは0番目の量子ビットを回路図の一番上に配置していることがわかる:

qc.draw("mpl")
先のコードで出力された回路図。

行列表現

状態ベクトルは、2レベルシステムにおいて、抽象表現と行列表現の関係が次のようになるように定義される

α∣0⟩+β∣1⟩↔(αβ)\alpha\lvert0\rangle + \beta\lvert1\rangle \leftrightarrow \begin{pmatrix} \alpha \\ \beta \end{pmatrix}

ここで、 α\alpha と β\beta は複素数である。 状態ベクトルは、 1D Numpy ndarraysv = [alpha, beta] として格納する*。* sv[0] == alpha と sv[1] == beta;状態ベクトルへのインデックスがケットのラベルと一致していることに注意。

ZZ (ここで xx はビット列の整数解釈である)の基底状態 ∣x⟩\lvert x\rangle が、状態ベクトル sv の非ゼロ項を sv[x] に持つように、 クロネッカー積を用いて 2つの量子ビット状態のテンソル積を行列代数で構成する:

import numpy
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector

state_0 = [1, 0]  # defined representation of |0>
state_1 = [0, 1]  # defined representation of |1>

# Circuit that creates basis state |10011>, where
# binary 10011 has the decimal value 19.
qc = QuantumCircuit(5)
qc.x(0)
qc.x(1)
qc.x(4)
qiskit_sv = Statevector(qc)

# List index 'n' corresponds to qubit 'n'.
individual_states = [
    state_1,
    state_1,
    state_0,
    state_0,
    state_1,
]
# Start from a scalar.
manual_sv = [1]
for qubit_state in individual_states:
    # Each new qubit goes "on the left".
    manual_sv = numpy.kron(qubit_state, manual_sv)

# Now `qiskit_sv` and `manual_sv` are the same, and:
assert manual_sv[19] == 1
assert qiskit_sv[19] == 1

これは演算子の行列表現にも反映され、制御対象の演算子に関するビット順の規則と結びつきます。 例えば、 の CXGate 行列形は次のようになります:

import numpy
from qiskit.circuit.library import CXGate

numpy.array(CXGate())
array⁡(CX)=(1000000100100100)\operatorname{array}(CX) = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \end{pmatrix}

これは、あなたが CXCX で見たことのある他の行列表現とは異なるかもしれませんが、行列表現の選択は従来のものであり、この形式は制御量子ビットが最初に来て、 テンソル積は「1振幅」のインデックスと状態のビット列値の間に対応関係があるように表現されるというQiskitの慣例に一致していることを思い出してください。

CCXGateゲートに対して複数の制御クビットが存在する場合(例えば、の場合など)、argument は ctrl_state 、同じ 0 を起点とするラベル付け規則を用いて、制御クビットのビット列値として解釈されます。 CCXGate例えば、デフォルト ctrl_state が「すべて1」のビット列であることを踏まえると、 における ctrl_state = 1 の CCXGate 行列形式は、制御状態が「すべて1」の状態 をとった場合と同じであることがわかりますが、ゲートへの入力時および出力時に、インデックスの大きい制御量子ビットの値を反転させたものとなります:

from qiskit import QuantumCircuit
from qiskit.quantum_info import Operator

# Build the natural representation of `CCX` with the
# control qubits being `[0, 1]`, relative to the
# bitstring state "01", such that qubit 0 must be in |1>
# and qubit 1 must be in |0>.  The target qubit is 2.
ccx_natural = QuantumCircuit(3)
ccx_natural.ccx(0, 1, 2, ctrl_state=1)

# Build the same circuit in terms of the all-ones CCX.
# Note that we flip _qubit 1_, because that's the one
# that differs from the all-ones state.
ccx_relative = QuantumCircuit(3)
ccx_relative.x(1)
ccx_relative.ccx(0, 1, 2)
ccx_relative.x(1)

assert Operator(ccx_relative) == Operator(ccx_natural)

これら2つのケースにおいて、における ctrl_state = 1 の CCXGate 行列形式は次のとおりである:

array⁡(CCX(ctrl_state=1))=(1000000000000100001000000001000000001000010000000000001000000001)\operatorname{array}\bigl(CCX(\text{ctrl\_state}=1)\bigr) = \begin{pmatrix} 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \end{pmatrix}
このページは役に立ちましたか?
バグや誤字の報告、またはコンテンツの要求はGitHubで行ってください。