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

回路内では CircuitInstructionOperation (である。 Instruction, a Gateまたは他のサブクラス)とqubitオペランドとclbitオペランドで構成される。 ここで核となる基本クラスは以下の通りだ:

最小限の抽象的な Operation インターフェースの具体的なサブクラスは Instruction. 一方 Operation は抽象的な数学オブジェクトを含むことができるが Instruction は、ハードウェア上で直接実行することが考えられるものである。 によってサブクラス化されている。 Gate そして ControlledGate によってサブクラス化され、さらにその上に単位性と制御されたセマンティクスが追加される:

  • Instructionハードウェアベースの命令を表す
  • Gate単位であるハードウェア命令を表す
  • ControlledGate制御構造を持つゲートを表す。

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

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

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

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

  • Measureを測定する。 QubitClbit

  • Reset0\lvert0\rangle の状態に不可逆的にリセットする

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

  • ControlFlowOpこれは特定のサブクラスを持つ:

    • BreakLoopOp最も近いループから抜け出すために
    • ContinueLoopOpを含むループの次の反復にすぐに移る
    • BoxOp単純な命令群
    • ForLoopOp一定範囲の値をループする
    • IfElseOpの2つのサブサーキットのいずれかに条件付きで入る
    • SwitchCaseOp条件付きで多数のサブサーキットのいずれかに入る
    • WhileLoopOp条件が反証されるまでサブサーキットを繰り返す。

特定の命令にはメタデータを「注釈」することができる。このメタデータは通常、コンパイラ・パスによってローカルで、あるいは後のバックエンド処理で消費されることを意図している。 現在のところ、これは BoxOp. のカスタム・サブクラスで表現される。 Annotationサポート・インフラについては qiskit.circuit.annotation.

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

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

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

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

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

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


Qiskitにおける回路の表現

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

内部的には QuantumCircuit には、量子ビット、古典ビット、コンパイル時パラメータ、リアルタイム変数、その他、それが作用するデータとそれがどのようにパラメータ化されるかについての追跡情報が含まれている。 次に CircuitInstructionその中には特定の操作(ゲート、測定など)とオペランド(量子ビットと古典ビット)が含まれる。

ビットとレジスタ

キュービットと古典的なビットは、共有の基本型によって表現される。 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ではまだ古典的なビットをごく普通に使うでしょう。

命令コンテキスト

シーケンスのスカラー型は QuantumCircuit.data シーケンスのスカラー型は「命令コンテキスト」オブジェクトである、 CircuitInstruction. これは基本的に、実行されることの表現(その operation)、そしてそれが作用するデータ( qubitsclbits).

CircuitInstruction(操作[、量子ビット、クラビット] )の単一命令。 QuantumCircuitoperation 、さまざまなオペランドで構成される。

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

回路に QuantumCircuit 回路に命令を追加するメソッド(例えば append()およびすべてのヘルパー・スタンダード・ゲート・メソッド)は InstructionSetを返す。 CircuitInstructionを返す。

InstructionSet(*[, resource_requester] )指導集とその文脈

これは InstructionSet は現在、Qiskitではほとんど使われていない。 これは、(回路に伝搬される )命令に対してポスト・アペンド変異を実行するための非常に最小限のメソッド・セットを提供するが、現在ではこれらのメソッドは推奨されておらず、これらのメソッドに記載されている代替手段を使用すべきである。

操作、命令、ゲート

の中にある。 CircuitInstructionの中で、あらゆる操作が満たさなければならない最小のインターフェースは Operation. これは非常にハイレベルな見方で、抽象的な回路にしか使えない。 演算を Operation を抽象回路に直接追加できるようにするためである。 quantum_info.Operatorなど)を抽象回路に直接追加できるようにすることである。

Operation()量子操作インターフェース。

物理回路上のすべての操作を含め、ほとんどの操作は、より具体的に定義された Instruction. これは、いくつかのQPUがネイティブに実行できるかもしれない命令を表します。 Measure. Instruction である必要はない。 Measure )である必要はない。 Gate.

Instruction(name, num_qubits, num_clbits, params)一般的な量子指導。

Instructionにのみ作用するのであれば、任意に近いものでよい。 QubitClbitにのみ作用し、その params外側の回路レジスタを "クローズオーバー "しようとしたり、それ自身の内部で隠されたパラメータを使ったりしてはならない。 Instructionの属性を使用することで、他の回路に関連して分解を行うことができる。 Instruction.definition 属性を使って、他の回路に関連して分解を提供することができる。 これは、含まれるすべてのゲートの定義が何らかの位相的順序を持つ限り、あなたにとって最も便利な操作の基本セットであれば何でも構わない。 もし Instruction をオプティマイザにとってまったく不透明なものと考えるなら、その definitionNone。 詳しくはカスタム指示書の作成をご覧ください。

命令の params は技術的には任意であるが、一般的には可能な限り実数によるパラメトリゼーションにこだわるべきである。 Qiskit自身は多くの場所でこのルールを破っており、フィールドの中にあらゆる種類の変わった型を見つけることができます。 Instruction.params フィールドにはさまざまな変わった型がありますが、これらはしばしば型を意識した特殊なケーシングの必要性を示唆するため、バグの厄介な原因となっています。 命令を角度でパラメトリック化すれば、 コンパイル時のパラメトリック化を確実に使用することができます。 QuantumCircuit.assign_parameters().

しかし Instruction は必ずしもユニタリーではないが、そのサブクラス Gate は単位性を意味し to_matrix()control() メソッドを追加する。 Instruction.

Gate(name, num_qubits, params[, label] )ユニタリー・ゲート

Gate のすべてのメソッドを継承し Instruction のすべてのメソッドを継承し paramsdefinition フィールドに関するすべての同じ考察を継承する。 Gateは古典的なリソースには作用できない。

Gate インスタンスはベース definitionを使うことで、異なるベースに複数の異なる分解を指定することもできる。 EquivalenceLibrary.

サブクラス GateQiskitには特別な ControlledGate クラスもあります。 このクラスは、( CXGate のような)制御される多くの標準ライブラリ・ゲートのベースであり、最も遭遇しやすい場所である:

ControlledGate(name, num_qubits, params[,...] )制御されたユニタリーゲート。

それぞれ Instruction, GateControlledGate には対応するシングルトン型がある。 qiskit.circuit.singleton. モジュールレベルのドキュメントには、以下の説明とともに詳細が記載されています。 SingletonInstruction, SingletonGate および SingletonControlledGate. ユーザーから見れば、ベースクラスがシングルトンであるかどうかで変わることはほとんどない。 to_mutable() 命令の安全な所有コピーを取得する必要がある場合は、最初にこれを呼び出すべきであるという意図に変わりはない(任意の命令がミュータブルであると仮定することはできない)。 type 直接検査することは推奨されませんが、もし必要であれば、シングルトンである可能性のある命令の "ベース "型を見つける確実な方法は base_class.

ControlledGate は、 ゲートのサブクラス化と同じメカニズムを使って、自分自身のための固定された遅延合成を定義する。 これは当然ハードウェアを意識しておらず、コンパイラの合成ルーチンにフックするのも難しい。 Instruction としてよりよく機能する。 合成や抽象最適化がより重要な場合、Qiskitは AnnotatedOperationという合成可能なクラスがあります。 ControlModifier を追跡します。 base_op.

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 - この命令のオプションの文字列ラベル。

ハードウェアは、与えられた量子ビットにリアルタイムのアイドル期間を適用するよう指示することができる。 スケジュール回路( qiskit.transpilerを参照)は、量子ビットのすべてのアイドル時間をこの Delay. 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). を必要としないQubitClbit オペランドは取らないが、明示的に lvaluervalue.

例えば、ビット列 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 の結果は、ある特定の場所で直接使うことができる。 現在のところ、これは IfElseOpWhileLoopOpの条件に限定されています。 SwitchCaseOp. 結果は、型付けされた古典的な記憶場所に格納することもできます。 Store 命令(またはその QuantumCircuit.store() コンストラクタ)を使って expr.Var ノードでバッキングされる。

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

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

Qiskitのさまざまなパラメトリック Instruction Qiskitの様々なパラメータインスタンスは、コンパイル時に解決されるように設計された方法でパラメータ化することができます。 これらの特徴は ParameterParameterExpression クラスである。

Parameter(名前[, uuid] )コンパイル時のシンボリック・パラメーター。
ParameterExpression( [名前_マップ, 式] )パラメータ式。

これがリアルタイムの古典的な計算で使われる expr.Var 変数と異なる主な点は、次のとおりである。 ParameterExpression が数式を記号化したものであることだ。 この式の意味論は、連続実数(限られた場合には複素数)に対する正規数学のものである。 これに対して Var は、浮動小数点値や固定幅整数など、古典的なコンピュータに格納されている変数へのハンドルであり、これらは常に離散的である。

つまり ParameterExpression(x+yx)/y1(x + y - x) / y \to 1 を簡略化するなど、数学で有効な記号的簡略化が期待できる。このような単純化は、浮動小数点演算では有効ではない。 expr.Expr はこれを行わない。

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

互いに関連する多くのパラメーターを使いたい場合もあるだろう。 これを簡単にするために(そして多くの名前を考える必要がないように)、便利なコンストラクタ ParameterVector. ベクトルの要素はすべて Parameter インスタンスである。 ParameterVectorElement.

ParameterVector(名前[, 長さ] )多くの関連オブジェクトのコンテナ。 Parameter オブジェクト。
ParameterVectorElement(ベクトル, インデックス[, UUID] )の要素である。 ParameterVector.

回路における制御フロー

内では QuantumCircuit内では、古典的な制御フローは特定の Instructionのサブクラスである ControlFlowOp.

ControlFlowOp(*args, **kwargs)すべての制御フロー操作をカプセル化する抽象クラス。

便宜上 frozenset インスタンスがある。 Instruction.name インスタンスがある。

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 プロパティには進入可能なあらゆる異なるサブ回路ブロックが含まれている。

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

また SwitchCaseOp も特別な値を理解する:

qiskit.circuit.CASE_DEFAULT

デフォルト値: <default case>

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

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

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

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

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

サブクラスも ControlFlowOp サブクラスは Instruction サブクラスでもあるので CircuitInstruction インスタンスに格納される方法は、そのインスタンスの qubitsclbits 属性に「適用」される。 これは、微妙なデータ一貫性の問題につながる可能性があります。 QubitClbit オブジェクトは、コントロール・フロー・オペレーションのサブサーキット・ブロック内で使用されるオブジェクトと必ずしも同一ではない。 CircuitInstruction. Qiskitで制御フロー操作を消費するコードはすべて、このことを意識する必要がある。サブサーキット内では、 subcircuit.qubits[i] を本当に outer_instruction.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` ...

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

のすべてのサブサーキット・ブロックは ControlFlowOp には同じ数の QubitClbitsを含み、同じ外側のビットを同じ順序で参照し、上のコード・ブロックで与えられた zip ループが機能するようにする必要がある。 内部回路 Bit オブジェクトは文字通り同じオブジェクトである必要はない。 コントロール・フロー・ビルダー・インターフェースを使用する場合(これは、ユーザーにとって、いくら強調してもしきれないほど推奨される)、ビルダーは、内側のビット・オブジェクトが外側のビット・オブジェクトと同一であるようにアレンジする。上記のコード・ブロックの qubit_map は、常にマッピング {x: x}、ブロックを消費する場合は、マッピングが必要な場合に備えておく必要がある。

すべての ClassicalRegister制御フローのサブサーキットで使用されるレジスタは、それを含むすべてのブロック (すなわち、制御フロー演算を含むすべてのブロックと一番外側の回路)にも存在しなければならない。 ControlFlowOp は同じレジスタを含む必要がある。 繰り返しになるが、ビルダー・インターフェイスはこのようになるように手配する(できない場合はeagerエラーを出す)。

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

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

命令ローカル注釈

関連資料

qiskit.circuit.annotation

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

特定の回路命令には、命令ローカル注釈を "注釈 "することができる。 Qiskit 2.1.0 の時点では、次のように制限されている。 BoxOp. すべてのアノテーションは、1つの基本インターフェース定義オブジェクトのサブクラスだが、通常は完全にカスタム化された分析やコマンドを表す。

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.

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() に直接与えることができる。 これらのメソッドは Instruction または Gate インスタンスを生成します。 definition 属性を持つインスタンスを生成します。つまり、トランスパイラや、回路を分解しようとする他のQiskit関数から自動的にアクセスできるようになります。

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

命令サブクラスの作成

基本クラス Instruction, Gate および ControlledGate はすべてサブクラス化しても安全なように設計されており、サブクラスが実装するためのフックポイントを持っている。 カスタム・ゲートがパラメータレスでステートレスである場合、 の対応するシングルトン・クラスから派生させることもできます。 qiskit.circuit.singletonSingletonGateの対応するシングルトンクラスから派生させることもできます。 のドキュメントを参照されたい。 qiskit.circuit.singleton のドキュメントを参照してください。

サブクラスは、通常、命令の正しい引数で :classsuper コンストラクタを呼び出すデフォルト コンストラクタを定義する必要がある。 クラス内に余分なステートを持つことは許されていますが、サブクラスがQiskitの他の機械と最も確実に統合されるのは、あなたの Instruction.paramsにのみ依存し、これらのパラメータは純粋にゲートアングルである。

のサブクラス Instruction (のサブクラス(またはそのサブクラスの1つ)は、privateな Instruction._define()_definition メソッドを実装しなければなりません。 definition メソッドをバックアップする隠されたキャッシュに、遅延的にデータを投入する。

_define

Instruction._define()

GitHub

キャッシュされた _definition フィールドに値を入れる。 Instruction.

サブクラスはこのメソッドを実装して、パブリック属性 definition 属性の遅延構築を提供するために、このメソッドを実装する必要があります。 サブクラスはその params を使用することができます。 このメソッドは、 _definitionQuantumCircuit を入力し、値を返さないようにします。

のサブクラスでは ControlledGateのサブクラスでは _define() のサブクラスでは、オール・ワン制御状態に対してのみ分解を実装しなければならない。 機械は ControlledGate.definition マシンは、実際の制御状態を処理するためにこれを修正する。

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

のサブクラスもオーバーライドしたいだろう。 Gate のサブクラスもまた、 Numpyの配列プロトコルのインスタンスメソッド __array__ をオーバーライドしたいことでしょう。 これは Gate.to_matrix()というシグネチャを持つ:

__array__

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

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

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

カスタム・サブクラスが制御形または逆形の自然表現を持つ場合は inverse() メソッドと control() メソッドをオーバーライドすることもできます。

カスタム 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)

この例では、 RZXGate の観点からベース定義を行ったが、より高速にベースの範囲に分解できるようにするために、さらにいくつかの等価点を SessionEquivalenceLibrary. 翻訳検索は BasisTranslator の観点から等価性を与えれば、(例えば) XGate での分解も自動的に利用可能になる。 RXGate での分解も利用可能になる。

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

このための高レベル関数は transpile()抽象回路とハードウェア backend または target を受け取り、物理回路を返す。 実行されるパスのステージに対してより多くのアクセスとコントロールを得るには generate_preset_pass_manager() を使って StagedPassManager を作り、それを修正することができる。

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

回路のシミュレーション

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

ユニタリー回路では、 00\lvert0\dotsm0\rangle 状態への影響をシミュレートすることができます。 QuantumCircuit を直接 Statevector に直接渡すことで、状態への影響をシミュレートできます。 回路を演算子として表現するユニタリー行列も同様に、デフォルトのコンストラクタである Operator に渡すことで、演算子として回路を表すユニタリー行列を得ることができます。 物理的な回路がある場合は、代わりにそれを Operator.from_circuit() メソッドに渡して QuantumCircuit.layout 抽象 "量子ビット空間にマッピングする。

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

同値関係の定義

抽象的な回路を物理的なハードウェアにマッピングし、その結果を最適化する際の一般的なタスクは、ゲートを異なる基底セットにマッピングする等価関係を見つけることである。 Qiskit はこの情報を EquivalenceLibrary.

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

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

qiskit.circuit.StandardEquivalenceLibrary

A EquivalenceLibrary は、Qiskitに組み込まれている標準的なゲート関係をすべて保存しています。 これを変異させるのではなく、代わりに、これを使って独自の EquivalenceLibrarybase を作成するか、グローバルステート SessionEquivalenceLibrary.

Qiskit は共有グローバル状態オブジェクト SessionEquivalenceLibrary も定義しており、これは Qiskit のさまざまな場所、特に BasisTranslator トランスパイラパスで使用されるデフォルト等価物です。 このadd_equivalence() メソッドを使って、あなた自身の等価性を自由に追加してください。そうすれば、 BasisTranslator のデフォルトのインスタンスによって自動的にピックアップされます。

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 特に、ハードウェアベンダーが SamplerV2EstimatorV2 で実行インターフェースを実装している場合、これはあなたの回路にトワリングを適用する最良の方法ではない可能性が高いので、指定されたハードウェアベンダーの SamplerV2 および/または EstimatorV2 の実装を参照することをお勧めします。

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

パラメーター

  • circuit (QuantumCircuit) – 回転するサーキット
  • twirling_gate (None | str |Gate |list[str] | list[Gate]) – デフォルトはNoneで、デフォルトのすべてのゲートを回すことを意味する: CXGate, CZGate, ECRGateそして iSwapGate. 指定された場合、ゲート・オブジェクトまたは文字列名として、単一のゲートまたはゲートのリストを指定することができる。 現在のところ、"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 回路に追加されたpauliゲートを最適化し、指定されたターゲットにマップするために、Pauli twirlingの一部として単一量子ビット分解を実行するために使用するインスタンス。

戻り値

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

戻りの型

QuantumCircuit | リスト QuantumCircuit ]


例外

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

CircuitError

exception qiskit.circuit.CircuitError(*message)

GitHub

ベース: QiskitError

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

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


回路の慣例

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

Qiskitの規約は以下の通り:

  • ビット列表現では、ビットは、 00 と呼ばれる文字列の右端のビットと、 n1n - 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] == alphasv[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の慣例に一致していることを思い出してください。

のように、1つのゲートに複数の制御がある場合、 の引数は制御量子ビットのビット列値として解釈されます。 CCXGateのような複数のコントロールの場合、 ctrl_state の引数は、同じゼロベースのラベリング規則を使って、コントロールクビットのビット列値として解釈されます。 例えば、デフォルトの ctrl_state がオール・オンのビットストリングであることを考えると、 の行列の形は、オール・オンのコントロール・ステートと同じであることがわかる。 CCXGate の行列形式が ctrl_state = 1 と同じであることがわかる。 CCXGateを取るのと同じですが、上位のインデックスを持つ制御量子ビットの値を反転させ、ゲートに存在させます:

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)

どちらの場合も、 の CCXGatectrl_state = 1

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で行ってください。