教室でQiskitを使ってみよう
このQiskit in Classroomsモジュールでは、以下のパッケージをインストールした動作するPython環境が必要です:
qiskitv2.1.0以降qiskit-ibm-runtimev0.40.1以降qiskit-aerv0.17.0以降qiskit.visualizationnumpypylatexenc
上記パッケージのセットアップとインストールについては、Qiskitのインストールガイドを参照してください。 実際の量子コンピューターでジョブを実行するには、IBM Cloud®アカウントの設定ガイドの手順に従ってIBM Quantum®のアカウントを作成する必要があります。
このモジュールはHeron v2プロセッサー上でテストされ、2秒のQPU時間を使用しました。これはあくまで推定値であり、実際の使用量は異なる場合があります。
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-aer qiskit-ibm-runtime
# Uncomment and modify this line as needed to install dependencies
#!pip install 'qiskit>=2.1.0' 'qiskit-ibm-runtime>=0.40.1' 'qiskit-aer>=0.17.0' 'numpy' 'pylatexenc'
はじめに
Qiskit in the Classroomモジュールでは、量子コンピューターを使って、量子力学・コンピューターサイエンス・化学などの量子コンピューティングに関連する様々な分野の概念を探求する機会があります。このモジュールは他のモジュールの前提条件として機能しており、量子コンピューティングの基礎と、Qiskitを使って量子Circuit(回路)を実行する方法を紹介します。
まず古典的なコンピューターの仕組みについて簡単に説明し、次にこれらの概念が量子コンピューティングのパラダイムにどのように適用されるかを示します。最後に、これらの概念をまとめて最初の量子Circuit(回路)を構築・実行する方法をお見せします。
古典的なコンピューター
古典的なコンピューターの仕組みの基礎はすでにご存知かもしれませんが、ここでは量子コンピューターとの比較ができるよう、主要な特徴をいくつか取り上げます。
情報の基本単位:ビット
古典的なコンピューターは古典的な情報を処理しており、古典的な情報の基本単位はビットです。1つのビットは「はい/いいえ」という1つの問いへの答えを格納できます。ビットの2つの二進状態は通常「0」と「1」で表されます。
二進数の復習
ビットを組み合わせることで、より多くの情報を格納できます。例えば、0から15の数値を格納したい場合、次のように4ビットで表現できます:
| 0 = 0000 | 4 = 0100 | 8 = 1000 | 12 = 1100 |
| 1 = 0001 | 5 = 0101 | 9 = 1001 | 13 = 1101 |
| 2 = 0010 | 6 = 0110 | 10 = 1010 | 14 = 1110 |
| 3 = 0011 | 7 = 0111 | 11 = 1011 | 15 = 1111 |
一般に、ビットの二進数を馴染みのある10進数に変換するには、最下位(最右端)のビットをで乗算し、その左のビットをで、次のビットをで乗算し、最上位(最左端)のビットに達するまでで乗算するまで続けます。
つまり、ビットは通りの異なる状態のうちの1つになり得ます。
理解度チェック
以下の問いを読み、答えを考えてから、三角形をクリックして解答を確認してください。
86という数を表すには何ビット必要ですか?この数を二進数でエンコードするビット列を書き出してください。
答え:
ビットではからまでの数を表せることを思い出してください。6ビットでは最大です。それでは足りません。もう1ビット追加してまで表せるようにします。では86を2の冪乗に分解しましょう:
基本演算:Gate(ゲート)
コンピューターは、計算を行うためにビットに対して何らかの操作を実行できる必要があります。二進Gate(ゲート)は、より複雑なアルゴリズムやコードすべての基本的な構成要素となる演算です。
1ビットGate(ゲート):
NOT
1つのビットしかない場合、その状態を変換する方法は1つだけです:状態を0から1へ、または1から0へ反転させます。これを「NOT」Gate(ゲート)と呼びます。このGate(ゲート)の効果——および以下で説明する他のGate(ゲート)の効果——は、いわゆる「真理値表」で表すことができます。真理値表には、Qubitの入力状態と出力状態の列があります。NOT Gate(ゲート)の真理値表は以下のとおりです:
| 入力 | 出力 |
|---|---|
| 0 | 1 |
| 1 | 0 |
複数ビットGate(ゲート):
AND
ANDは2つの入力ビットを受け取り、1つのビットを出力する2ビットGate(ゲート)です。両方の入力ビットが1の場合に1を出力し、それ以外は0を出力します:
| 入力 | 出力 |
|---|---|
| 00 | 0 |
| 01 | 0 |
| 10 | 0 |
| 11 | 1 |
OR
ORも単一の出力ビットを持つ2ビットGate(ゲート)です。どちらかのビットが1であれば1を出力します:
| 入力 | 出力 |
|---|---|
| 00 | 0 |
| 01 | 1 |
| 10 | 1 |
| 11 | 1 |
XOR
XORは「排他的論理和(exclusive OR)」の略で、OR Gate(ゲート)に似ていますが、入力ビットのうちの1つだけが1の場合に1を出力します。両方が1または両方が0の場合は0を出力します:
| 入力 | 出力 |
|---|---|
| 00 | 0 |
| 01 | 1 |
| 10 | 1 |
| 11 | 0 |
測定:
古典的なコンピューティングを学ぶ際、ビットの状態を読み出すプロセスにはあまり注意が払われません。これは、概念的な観点から見るとそれほど複雑ではないためです。ビットは計算の前後いつでも測定でき、結果に影響を与えません。これは量子コンピューティングには当てはまらず、以下で説明します。
Circuit(回路):
上記のGate(ゲート)を組み合わせることで、コンピューター上で任意の操作を実行できます。簡単な例として、ANDとXOR Gate(ゲート)を使って、2ビットの和を計算する半加算器Circuit(回路)を構成できます。これは論理Circuit(回路)図で表され、ワイヤーがビットを表し、各ビットに作用するGate(ゲート)が対応するワイヤー上のシンボルとして示されます:
つまり、2つのビットがコピーされ、AND Gate(ゲート)とXOR Gate(ゲート)の両方に入力されます。XOR Gate(ゲート)の結果は「和ビット」(S)で、二進数の1の位の値を表し、AND Gate(ゲート)の結果は「桁上げビット」(C)で、二進数の次の上位桁の値を表します。真理値表は以下のとおりです:
| 和 () | 桁上げ () | ||
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 1 | 1 | 0 |
| 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 1 |
理解度チェック
以下の問いを読み、答えを考えてから、三角形をクリックして解答を確認してください。
上記の真理値表が加算器Circuit(回路)の正しい解を与えることを確認してください。つまり、AとBの4つの選択肢それぞれについて、が成り立つことを確認してください。
答え:
量子コンピューター
ビット qubit
ビットが古典的な情報の基本単位であるように、量子ビット(qubit)は量子情報の基本単位です。古典的なビットと同様に、Qubitの状態は0または1のいずれかで、通常およびと表記します。しかし古典的なビットとは異なり、量子ビットは状態と状態の両方の重ね合わせに同時になることができます。一般に、Qubitは以下の形式の任意の状態になれます:
ここでおよびはを満たす複素振幅です。
量子位相
とは複素数であるため、それぞれと書けます。ここでは位相と呼ばれます。状態全体に同じ全体位相因子を乗算しても、物理的には何も変わりません——これをグローバル位相と呼び、観測可能な影響はありません。
そのため、を「括り出す」ことが慣例となっており、次のように書けます:
ここでは量子状態の相対位相であり、これは観測可能な影響を持ちます。
この位相は量子コンピューティングにおいて非常に重要な役割を果たしており、続くQiskit in the Classroomモジュールでその様々な影響を探求していきます。
複数のQubit
複数のビットの状態は単純に0と1の文字列で表せますが、複数のQubitの状態は重ね合わせとエンタングルメントの原理により、少し複雑になります。
ビットは二進数の000...000から111...111までの通りの可能な状態のうちの1つになれることを思い出してください。しかし今度は重ね合わせの原理により、個のqubitはこれらすべての状態の重ね合わせに同時になることができます!
これは次のように表現できます:
ここで古典的な場合と同様に、状態は各Qubitが0と1の適切な組み合わせになって二進数を生成する状態に対応します。これらは量子系の「計算基底状態」として知られています。例えば、3Qubit状態はその8つの計算基底状態の重ね合わせとして書けます:
系の各Qubitはインデックスからで示されます。慣例として、Qubitの状態は右から左に読みます。つまりQubit の状態が最右端で、qubit の状態が最左端になります。これは「リトルエンディアン」記法として知られており、左から右に読むことに慣れているため、最初は直感に反して感じるかもしれません。
理解度チェック
以下の問いを読み、答えを考えてから、三角形をクリックして解答を確認してください。
一見すると、リトルエンディアン記法のようにQubitを右から左に並べることは直感に反するように思えるかもしれませんが、実は非常に論理的なことです!その理由を説明してください。(上記の二進数から10進数への変換の話を思い出してください。)
答え:
Qubitを右から左に並べ、qubit 0が最右端でQubit N-1が最左端になるようにすると、qubit をで乗算される最下位ビットに対応させ、qubit をで乗算される最上位ビットに対応させることが論理的です。
エンタングルメント
先ほど述べたように、Qubitのもう1つの重要な特徴は、互いにエンタングルできることです。、の2Qubit状態の例を見てみましょう:
つまり、qubit 0の状態は等しい確率でまたはになり得て、qubit 1も同様です。しかし、これらの確率はもはや互いに独立ではありません。qubit 0の状態がとわかれば、qubit 1もにあることがわかります。これは互いにどれだけ離れていても成り立つため、エンタングルした状態を測定する行為はときに「不気味な遠隔作用」と呼ばれます。
エンタングルメントは他の形でも現れます。例えば、状態
は常に反対の結果をもたらします:一方のQubitがと測定されれば、もう一方は必ずの状態で見つかります。
理解度チェック
以下の問いを読み、答えを考えてから、三角形をクリックして解答を確認してください。
状態はエンタングルしていますか?その理由を答えてください。
答え:
エンタングルしていません。両方のQubitを測定すると結果が常に同じになりますが、これは各Qubitが常にの状態に固定されているためです。一方のQubitを測定した結果は実際にはもう一方に依存しておらず、どちらも常になのです。
一般に、各Qubitの状態を個別に記述してから次のように積を取ることができる場合:
これは「積状態」として知られており、エンタングルしていません。
ベクトル記法
量子状態が異なる演算の下でどのように変換されるかを確認するには、ベクトルと行列を使用すると便利です。この表現では、量子状態はベクトルであり、量子Gate(ゲート)(次のセクションで説明)はベクトルを変換する行列となります。
1つのQubitについて、各状態のベクトル形式は次のように選ばれます: このようにして、任意の状態は次のように書けます:
一般的なQubit状態では、次元のベクトルが必要であり、基底状態は二進数の値の昇順に並べられます:
このベクトル記法を念頭に置いて、必要な量子Gate(ゲート)、量子状態への作用、および行列形式を紹介します。
理解度チェック
以下の問いを読み、答えを考えてから、三角形をクリックして解答を確認してください。
2Qubit系には4つの計算基底状態があります。それぞれをケット記法とベクトル記法の両方で書き出してください。
答え:
Gate(ゲート) 量子Gate(ゲート)
NOT、AND、OR、XORなどの古典的なGate(ゲート)を組み合わせて任意の古典Circuit(回路)を構築できるように、量子Gate(ゲート)は量子コンピューティングにおいて同じ役割を果たします。Qubitには量子力学的な追加的特徴があるため、量子Gate(ゲート)はそれに対応してより豊富です。基底状態とへの作用は真理値表で記述できますが、それでは全体像を捉えきれません。量子Gate(ゲート)では、基底状態の重ね合わせにも作用するため、行列表現を使用する方が自然なことが多いです。
以下では、最も一般的な量子Gate(ゲート)と、それらが相互作用するQubitをどのように変換するかを紹介します。該当する場合は、馴染みのある古典的なGate(ゲート)と結び付けて説明します。
1量子ビットゲート
ゲート: 量子版のNOT演算です。真理値表は古典的なNOTゲートとまったく同じです。
| 入力 | 出力 |
|---|---|
行列表現は次のとおりです。
Qiskitで ゲートを含むCircuitを作成するには次のようにします。
from qiskit import QuantumCircuit
qc = QuantumCircuit(1)
qc.x(0)
qc.draw("mpl")
この非常にシンプルなCircuit図では、Qubitはワイヤー(黒い水平線)で表されており、ゲートはそのワイヤー上のボックスとして表示されます。
Hadamardゲート: 重ね合わせ状態を生成します。真理値表:
| 入力 | 出力 |
|---|---|
行列表現:
HadamardゲートをもつCircuitは次のように作成します。
from qiskit import QuantumCircuit
qc = QuantumCircuit(1)
qc.h(0)
qc.draw("mpl")
ゲート: 状態に の位相シフトを加えます。
| 入力 | 出力 |
|---|---|
Qiskitで ゲートを含むCircuitを作成するには次のようにします。
qc = QuantumCircuit(1)
qc.z(0)
qc.draw("mpl")
ゲート: 状態に の位相シフトを加えます。
| 入力 | 出力 |
|---|---|
Qiskitで ゲートを含むCircuitを作成するには次のようにします。
qc = QuantumCircuit(1)
qc.t(0)
qc.draw("mpl")
複数Qubitゲート
2Qubitゲートは古典的な2ビットゲートに似ていますが、重要な違いが一つあります。すべての量子ゲートは可逆でなければならないという点です。線形代数の観点では、これはゲートがユニタリ行列で表されることを意味します。したがって、2つの入力Qubitは常に2つの出力Qubitに対応し、原理的に操作を元に戻すことができます。これは、ANDやORなどの古典ゲートとは対照的です。古典ゲートは情報を失うため不可逆であり、出力から入力を一意に特定することができません。
CNOT(制御NOTゲート): 2つの入力Qubitは「制御」と「ターゲット」Qubitと呼ばれます。制御Qubitは変化しませんが、その状態がターゲットQubitへの作用を決定します。制御Qubitが の状態にある場合、ターゲットに ゲートが適用されます。制御Qubitが の場合は何も変化しません。以下の表記では、qubit (最右端のQubit)が制御、qubit (最左端のQubit)がターゲットとします。使用する表記は です。
| 入力 | 出力 |
|---|---|
この操作を表す行列は次のとおりです。
qc = QuantumCircuit(2)
qc.cx(0, 1)
qc.draw("mpl")
これは2つのQubitを持つ最初のCircuit図です。2本のワイヤーがそれぞれのQubitを表しています。CNOTゲートは2つのQubit間に実装されており、 が制御、 がターゲットです。
理解度チェック
以下の問いを読んで答えを考えてから、三角形をクリックして解答を確認してください。
ほとんどのゲートはQiskitでも他の場所でも同じ行列形式を持ちます。しかし、CNOTゲートは2つのQubitに作用するため、Qubitの順序の規則が問題になります。Qubitを の順に並べるテキストでは、CNOTゲートの行列形式が異なります。上記のCNOT行列が 状態に対して正しい作用をもつことを、行列の明示的な掛け算によって確認してください。
解答:
SWAPゲート: このゲートは2つのQubitの状態を入れ替えます。真理値表:
| 入力 | 出力 |
|---|---|
この操作を表す行列は次のとおりです。
qc = QuantumCircuit(2)
qc.swap(0, 1)
qc.draw("mpl")
SWAPゲートは実際には3つのCNOTから構成できます。その方法を確認するには、Qiskitの decompose() でゲートを分解します。
qc = QuantumCircuit(2)
qc.swap(0, 1)
qc.decompose().draw("mpl")
ここで初めて、Circuit図に複数のゲートがどのように表示されるかを確認できます。左から右に読むため、一番左のゲートが最初に適用されます。
理解度チェック
以下の問いを読んで答えを考えてから、三角形をクリックして解答を確認してください。
上記のCNOTの組み合わせがSWAPゲートになることを確認してください。行列の掛け算またはその他の方法で確かめられます。
解答:
行列の掛け算を用いると:
真理値表を使用して、各CNOTで状態がどのように変化するかを確認します。最後の列は、SWAPの真理値表の「出力」列と一致するはずです。
| 入力 | CNOT(A,B) | CNOT(B,A) | CNOT(A,B) |
|---|---|---|---|
Toffoliゲート(または「制御制御NOT」(CCNOT)): これは 3 QubitのGateです。「制御制御NOT」という名称から動作が推測できます。2つの制御Qubitと1つのターゲットQubitがあり、両方 の制御Qubitが の状態にある場合にのみ、ターゲットQubitの状態が反転します。CNOTで用いた順序規則を引き続き使用します。
真理値表は次のとおりです。
| 入力 | 出力 |
|---|---|
この操作を表す行列は次のとおりです。
qc = QuantumCircuit(3)
qc.ccx(0, 1, 2)
qc.draw("mpl")
Toffoliゲートも、いくつかのゲートとともにCNOTに分解できます。ただし、SWAPゲートの分解よりもはるかに複雑であるため、この分解の確認はモジュール末尾の任意課題として残しておきます。
測定
測定は量子計算において特別な役割を果たしており、古典計算には対応するものがありません。古典計算ではアルゴリズムの任意のタイミングでビットを確認できますが、量子計算ではQubitを観測するタイミングを慎重に選ぶ必要があります。測定によって状態が崩壊し、Qubitの計算上の複雑性を生み出す重ね合わせが破壊されてしまうからです。
具体的には、 ビットの量子状態 が与えられた場合、測定によって状態は基底 のいずれかに崩壊し、その確率は に等しくなります。
しかし、測定のこの破壊的な効果が常に障害になるわけではありません。実際、量子テレポーテーションや量子鍵配送などの特定のアルゴリズムやプロトコルでは、重要なリソースとなっています。
Qiskitでは、測定を行うと結果は古典レジスタに送られ、古典ビットとして保存されます。測定を含むCircuitを作成するには次のようにします。
qc = QuantumCircuit(
1, 1
) # the second number is the number of classical bits in the circuit
qc.measure(0, 0)
qc.draw("mpl")
Circuit
Qubit、Gate、測定の仕組みを理解したところで、実際に量子Circuitを作成して実行してみましょう。そのために、Qiskitパターンと呼ばれる便利なワークフローを紹介します。
Qiskitパターンフレームワーク
Qiskitパターンフレームワークは、量子コンピューターを使って問題にアプローチし解決するための一般的な手順です。4つのステップで構成されています。
- マッピング: 問題を量子CircuitおよびOperatorに対応付ける
- 最適化: ターゲットハードウェア向けにCircuitを最適化する
- 実行: ターゲットハードウェア上で実行する
- 後処理: 結果を後処理する
これらのステップを説明するために、上で紹介した半加算器Circuitの量子バージョンを実装します。
1. マッピング
古典の半加算器Circuitは、XORゲートとANDゲートを使って、それぞれ和ビットとキャリービットを計算します。これらのゲートを量子の文脈に適用して量子半加算器を作ります。量子ゲートは可逆であるため、入力をそのまま上書きすることはできません。その代わりに、和とキャリーの出力を格納するための補助Qubit2つを で初期化して導入します。したがって、完全な量子状態はQubit と 、および和とキャリーのQubit(それぞれ と とラベル付け)で構成されます。
次に、古典回路のXORゲートとANDゲートに相当する量子ゲートが必要です。
和:
XORに対しては、制御Qubitをそれぞれ と 、ターゲットQubitを両方とも とする2つのCNOTを適用します。 と が異なる場合、どちらか一方のCNOTゲートが を 状態に反転させます。 と が両方 の場合、 には何も作用しないため 状態のままです。 と が両方 の場合、 の状態は2回反転し、 状態に戻ります。
キャリー:
キャリービットには、古典のANDゲートと同様に機能するものが必要です。
理解度チェック
以下の問いを読んで答えを考えてから、三角形をクリックして解答を確認してください。
これまでに説明したゲートを振り返り、古典のANDゲートの代わりにどの量子ゲートを使うか考えてみてください。
解答:
Toffoliゲートです。Toffoli(制御制御NOTゲート)は、制御Qubit0と制御Qubit1の両方が の場合にのみターゲット状態を反転させます。そのため、ターゲットQubitが から始まる場合、ANDゲートと同じ動作をします。
これで量子Circuitを作成するために必要な材料がそろいました。
# qubits: a, b, sum, carry
qc = QuantumCircuit(4)
# Choose values for A and B:
a = 0
b = 0
# Prepare A and B qubits according to selected values:
if a:
qc.x(0)
if b:
qc.x(1)
# XOR (sum) into qubit 2
qc.cx(0, 2)
qc.cx(1, 2)
# AND (carry) into qubit 3
qc.ccx(0, 1, 3) # a AND b
# measure
qc.measure_all()
qc.draw("mpl")
上図は量子半加算器CircuitのCircuit図です。前述のように、ワイヤーは上から下に順にQubit から を表しており、古典ビットレジスタは一番下の二重線のワイヤーです。左から右に読むことで、対応するワイヤー上のボックスの位置から各Qubitへのゲートの適用を確認できます。最後に測定が示されています。測定によってQubitの状態は確定的な または の値に崩壊し、結果は古典レジスタに送られます。
ひとつ注意点があります。Circuit図は左から右に描かれていますが、対応する行列式を書く際は右から左に読む必要があります。これは、行列の掛け算では状態ベクトルに最も近い演算子が最初に作用するためです。たとえば、上記のCircuit(測定を除く)は次のように表されます。
2. 最適化
次に、量子ハードウェア上で実行できるようCircuitを最適化する必要があります。この最適化はTranspilerによって行われます。Transpilerは上記の抽象的なCircuitを量子コンピューターが理解できる命令に変換します。論理Qubitをプロセッサ上の実際の物理Qubitに割り当て、量子コンピューターに最適化されたネイティブなゲートセットでゲートを書き直します。さらにTranspilerは、エラーの影響を最小化するための「誤り抑制と軽減」も実装します。今回の非常にシンプルなCircuitにはそれほど重要ではありませんが、量子計算の学習を進めてより複雑なCircuitを実行するようになれば、誤り抑制と軽減の価値がすぐに実感できるでしょう。詳しくは、Olivia Laneのコース「実践的な量子計算」を参照してください。
まず、IBM®量子コンピューターと通信するために必要なパッケージを読み込み、実行するBackendを選択します。最も空いているBackendを選ぶか、特性がわかっている特定のBackendを選択できます。
初回使用時に認証情報を保存するためのコードを以下に示します。ノートブックを共有する際に認証情報が誤って共有されないよう、環境に保存した後はノートブックからこの情報を削除してください。詳しくは「IBM Cloudアカウントのセットアップ」および「信頼できない環境でのサービス初期化」を参照してください。
# Load the Qiskit Runtime service
from qiskit_ibm_runtime import QiskitRuntimeService
# Load the Qiskit Runtime service
# Syntax for first saving your token. Delete these lines after saving your credentials.
# QiskitRuntimeService.save_account(channel='ibm_quantum_platform',
# instance = '<YOUR_IBM_INSTANCE_CRN>', token='<YOUR-API_KEY>', overwrite=True, set_as_default=True)
# service = QiskitRuntimeService(channel='ibm_quantum_platform')
# Load saved credentials
service = QiskitRuntimeService()
# Use the least busy backend, or uncomment the loading of a specific backend like "ibm_brisbane".
backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
# backend = service.backend("ibm_brisbane")
print(backend.name)
ibm_fez
次に、TranspilerでCircuitを最適化します。最適化レベルは0(最適化なし)から3(最高の最適化)まで選択できます。各レベルの詳細については、「Transpilerの最適化レベルの設定」ガイドを参照してください。結果のCircuitは、マッピングステップで作成した論理的なCircuitとは大きく異なって見えるでしょう。
# Transpile the circuit and optimize for running on the quantum computer selected
# Step 2: Transpile
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
qc_isa.draw("mpl")
「Sampler」とは、量子Circuitから生じる可能性のある状態をサンプリングし、どの状態がどの確率で測定されるかの統計を収集するためのプリミティブです。ここでQiskit RuntimeのSamplerをインポートします。
# Load the Runtime primitive and session
from qiskit_ibm_runtime import SamplerV2 as Sampler
sampler = Sampler(mode=backend)
実際の量子コンピューターの利用可能時間を使い切った場合、またはインターネット接続がない場合は、シミュレーターを使用することもできます。その場合は以下のセルを実行し、「実行」ステップの対応する行のコメントを外してください。
# Load the backend sampler
from qiskit.primitives import BackendSamplerV2
# Load the Aer simulator and generate a noise model based on the currently-selected backend.
from qiskit_aer import AerSimulator
from qiskit_aer.noise import NoiseModel
noise_model = NoiseModel.from_backend(backend)
# Define a simulator using Aer, and use it in Sampler.
backend_sim = AerSimulator(noise_model=noise_model)
sampler_sim = BackendSamplerV2(backend=backend_sim)
# Alternatively, load a fake backend with generic properties and define a simulator.
# backend_gen = GenericBackendV2(num_qubits=18)
# sampler_gen = BackendSamplerV2(backend=backend_gen)
3. 実行
Circuitの準備ができたので、量子コンピューターで実行しましょう!
job = sampler.run([qc_isa], shots=100)
# job = sampler_sim.run([qc_isa]) # uncomment if you want to run on a simulator
res = job.result()
counts = res[0].data.meas.get_counts()
4. 後処理
いよいよ結果を確認します。Circuitの100回サンプルのヒストグラムを表示します。
from qiskit.visualization import plot_histogram
print("counts = ", counts)
plot_histogram(counts)
counts = {'0000': 90, '0100': 4, '1100': 3, '0010': 3}
上のヒストグラムは、Circuit終了時の全4つのQubitの測定結果を示しています。ノイズがまったくない理想的な量子コンピューターであれば毎回同じ値が測定されますが、実際にはノイズによって一部の実行でエラーが発生することがあります。
理解度チェック
以下の問いを読んで答えを考えてから、三角をクリックして解答を確認しましょう。
最も多いカウントを示すビット文字列を 、、、 の値として使用し、量子加算器 Circuit が正しく動作したことを確認してください。
解答:
が成り立つことを確認する必要があります。ビット文字列はリトルエンディアン記法に従っているため、CSBA の順で読むことに注意してください。
上のヒストグラムから、0000 のビット文字列が最も多いことがわかります。
と の値を 、 に変更し、Qiskit パターンのステップをもう一度実行して Circuit を再実行してください。加算器 Circuit が再び正しく動作したことを確認してください。
解答:
最も多いビット文字列が 1011 となるヒストグラムが得られるはずです:
量子ハーフ加算器が古典的なハーフ加算器に対して持つ付加的な特徴の一つは、量子入力で動作できることです。つまり、qubit と が重ね合わせ状態にあっても「加算」を行えます。以下のチャレンジ問題のセクションでは、qubit を重ね合わせ状態に準備して、何が起こるかを確かめるよう問われます。
まとめ
このモジュールは、量子コンピューティングの基本原理を古典コンピューティングと比較することで、しっかりとした基礎的理解を得ることを目的として設計されました。古典的なハーフ加算器 Circuit を検討し、それを量子コンピュータ上の qubit で動作するように適応させる方法を示しました。これで、他の「Qiskit in the Classroom」モジュールを探索する準備が整いました!
重要な概念
- 0 と 1 の値しか取れない古典ビットとは対照的に、qubit は 0 と 1 の両方の重ね合わせ状態を取ることもできます。
- 複数の qubit は、古典的に許容されるビット文字列(計算基底状態と呼ばれます)の重ね合わせになることができます。
- 複数の qubit はエンタングル(量子もつれ)状態になることができ、一方の状態が他方の状態に依存します。
- Qiskit の規約ではリトルエンディアン記法を使用しており、最下位 qubit を最右端に、最上位 qubit を最左端に配置します。
- 量子 Gate は、量子状態ベクトルに作用するユニタリ行列で表される可逆的な演算です。この記法では、ベクトルに最も近い(最右端の)行列が最初に作用します。
- 測定は量子重ね合わせ状態を古典的に許容される状態の一つに崩壊させます。その確率は、重ね合わせにおける対応する計算基底状態の振幅の二乗に等しくなります。
- 量子 Circuit は量子回路図を用いて表されることが多く、qubit は水平な線として描かれ、量子 Gate はこれらの線に沿って左から右へと配置されます。
- 量子 Circuit を実行するには、Qiskit パターンワークフローの4つのステップ、すなわちマップ、最適化、実行、後処理を使用します。
問題
正誤問題
-
古典コンピュータの1ビットは、0 または 1 の値しか保持できない。
-
エンタングルメントとは、ある qubit の状態が別の qubit の状態と無関係であることを意味する。
-
量子 Gate は一般に不可逆な演算である。
-
Qiskit の規約では、最下位 qubit を最左端の位置に配置する。
-
量子状態を測定すると、何度繰り返しても常にまったく同じ結果が得られる。
-
Hadamard Gate は単一の qubit に重ね合わせを生成する。
-
量子 Circuit には、重ね合わせ状態を古典的に許容される状態の一つに崩壊させる測定演算が含まれることがある。
-
ビットに対して取り得る古典状態の数は である。
-
量子測定の結果確率は、古典的に測定可能な基底状態の振幅の二乗によって与えられる。
短答問題
-
ビットと qubit の主な違いは何ですか?
-
量子状態を測定すると何が起こりますか?
-
Qiskit でリトルエンディアン記法を使用するのはなぜですか?
-
Qiskit パターンワークフローの4つのステップは何ですか?
チャレンジ問題
-
このモジュールでは、加算器を使って と の古典的に許容された状態のみを加算しました。しかし、 と を重ね合わせ状態に準備することもできます!各 qubit を 0 と 1 の等しい重ね合わせに準備するようコードを変更し、新しい Circuit を実行して新しいヒストグラムを取得してください。何が見えますか?何が起きているのか説明してください。
-
Toffoli Gate の分解。
decompose()を使用して、Toffoli Gate がどのように単一 qubit および2 qubit の Gate に分解されるかを示し、行列の積でこの構成を検証してください。Circuit 図は左から右へ読みますが、行列は量子状態に対して右から左へ適用されることに注意してください!