概要
- Cirq の 理解を, さらに深めるため, シュミレーションに関するサンプルをいくつか動かしてみた.
- 動作環境は, Google Colaboratory で行った
感想
- Google社 の Simulation に 関する記事を少しずつ進めることが出来たと思う.
- 量子物理学に関する知識(用語, 数式の意味ほか)は, 徐々に身につけていく必要があると感じた.
- 時間を見つけて, 今後も, チュートリアルの残りの部分を進めていこうと思う.
Parameterized values and studies
cirq.ParamResolver の 使い方 を 確認
- cirq.ParamResolver を 使う サンプル
- cirq.ParamResolver を 使わない サンプル.
- cirq.ParamResolver を 使う サンプル
- cirq.ParamResolver を 使わない サンプル
- simulator.run_sweep を 使う サンプル
- simulator.run_sweep を 使わない サンプル
- cirq.DensityMatrixSimulator を 使う サンプル
- cirq.DensityMatrixSimulator を 使わない サンプル
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
[編集内容(cirq.ParamResolver)] import cirq from cirq import Simulator import numpy as np import sympy # Pick one qubit. q0 = cirq.GridQubit(0, 0) # Use Symbol value. rot_w_gate = cirq.X ** sympy.Symbol('x') circuit = cirq.Circuit() circuit.append([rot_w_gate(q0)]) simulator = Simulator() # Simulate 10 times. for y in range(10): resolver = cirq.ParamResolver({'x': y / 5.0}) result = simulator.simulate(circuit, resolver) print(np.round(result.final_state_vector, 3)) # 小数点以下3桁まで表示. |
1 2 3 4 5 6 7 8 9 10 11 |
[出力結果] [1.+0.j 0.+0.j] [0.905+0.294j 0.095-0.294j] [0.655+0.476j 0.345-0.476j] [0.345+0.476j 0.655-0.476j] [0.095+0.294j 0.905-0.294j] [0.+0.j 1.+0.j] [0.095-0.294j 0.905+0.294j] [0.345-0.476j 0.655+0.476j] [0.655-0.476j 0.345+0.476j] [0.905-0.294j 0.095+0.294j] |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
[編集内容(cirq.ParamResolver is not used)] import cirq from cirq import Simulator import numpy as np # Pick one qubit. q0 = cirq.GridQubit(0, 0) # Simulate 10 times. for y in range(10): circuit = cirq.Circuit() op = cirq.X(q0) ** (y / 5.0) circuit.append(op) simulator = cirq.Simulator() result = simulator.simulate(circuit) print(np.round(result.final_state_vector, 3)) # 小数点以下3桁まで表示. |
1 2 3 4 5 6 7 8 9 10 11 12 |
[出力結果] [1.+0.j 0.+0.j] [0.905+0.294j 0.095-0.294j] [0.655+0.476j 0.345-0.476j] [0.345+0.476j 0.655-0.476j] [0.095+0.294j 0.905-0.294j] [0.+0.j 1.+0.j] [0.095-0.294j 0.905+0.294j] [0.345-0.476j 0.655+0.476j] [0.655-0.476j 0.345+0.476j] [0.905-0.294j 0.095+0.294j] ※前項と同様の出力を確認出来た. |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
[編集内容(cirq.ParamResolver)] import cirq from cirq import Simulator import numpy as np import sympy # Pick two qubits. q0, q1 = cirq.GridQubit(0, 0), cirq.GridQubit(1, 0) # Use Symbol value. rot_w1_gate, rot_w2_gate = cirq.X ** sympy.Symbol('a'), cirq.X ** sympy.Symbol('b') circuit = cirq.Circuit() circuit.append([rot_w1_gate(q0), rot_w2_gate(q1)]) simulator = Simulator() # Simulate 7 times. for y in range(7): resolver = cirq.ParamResolver({'a': y / 3.0, 'b': y / 7.0}) result = simulator.simulate(circuit, resolver) print(np.round(result.final_state_vector, 1)) # 小数点以下1桁まで表示. |
1 2 3 4 5 6 7 8 |
[出力結果] [1.+0.j 0.+0.j 0.+0.j 0.+0.j] [ 0.6+0.6j 0.1-0.1j 0.3-0.4j -0.1-0.1j] [ 0. +0.4j 0.2-0.j 0.8-0.1j -0. -0.4j] [0. +0.j 0. +0.j 0.6+0.5j 0.4-0.5j] [ 0.3-0.j -0.1-0.4j 0.1+0.5j 0.7-0.1j] [ 0.3+0.2j 0.4-0.6j -0.1+0.2j 0.4+0.3j] [0.+0.2j 1.-0.2j 0.+0.j 0.+0.j ] |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
[編集内容(cirq.ParamResolver is not used)] import cirq from cirq import Simulator import numpy as np # Pick two qubits. q0, q1 = cirq.GridQubit(0, 0), cirq.GridQubit(1, 0) # Simulate 7 times. for y in range(7): circuit = cirq.Circuit() op_1, op_2 = cirq.X(q0) ** (y / 3.0), cirq.X(q1) ** (y / 7.0) circuit.append([op_1, op_2]) simulator = cirq.Simulator() result = simulator.simulate(circuit) print(np.round(result.final_state_vector, 1)) # 小数点以下1桁まで表示. |
1 2 3 4 5 6 7 8 9 |
[出力結果] [1.+0.j 0.+0.j 0.+0.j 0.+0.j] [ 0.6+0.6j 0.1-0.1j 0.3-0.4j -0.1-0.1j] [ 0. +0.4j 0.2-0.j 0.8-0.1j -0. -0.4j] [0. +0.j 0. +0.j 0.6+0.5j 0.4-0.5j] [ 0.3-0.j -0.1-0.4j 0.1+0.5j 0.7-0.1j] [ 0.3+0.2j 0.4-0.6j -0.1+0.2j 0.4+0.3j] [0.+0.2j 1.-0.2j 0.+0.j 0.+0.j ] ※前項と同様の出力を確認出来た. |
simulator.run_sweep の 使い方 を 確認
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
[編集内容(simulator.run_sweep)] import cirq from cirq import Simulator import numpy as np import sympy # Pick two qubits. q0, q1 = cirq.GridQubit(0, 0), cirq.GridQubit(1, 0) # Use Symbol value. rot_w_gate = cirq.X ** sympy.Symbol('x') # Use cirq.ParamResolver. resolvers = [cirq.ParamResolver({'x': y / 2.0}) for y in range(3)] circuit = cirq.Circuit() circuit.append([rot_w_gate(q0), rot_w_gate(q1)]) circuit.append([cirq.measure(q0, key='q0'), cirq.measure(q1, key='q1')]) results = simulator.run_sweep(program=circuit, params=resolvers, repetitions=2) # 以下のように理解. # 1. ↑↑(2量子ビット, 00 と見る) を 用意. # 2. 1量子ビット目に, X ゲート を 操作. # ※ 1量子ビット目が, ↑ もしくは ↓ に 変わるはず. # 3. 2量子ビット目に, X ゲート を 操作. # ※ 2量子ビット目が, ↑ もしくは ↓ に 変わるはず. # -> 1量子ビット目, 2量子ビット目の操作結果によって, # ↑↑(00, つまり, q0 = 0, q1 = 0), ↑↓(01, つまり, q0 = 0, q1 = 1), # ↓↑(10, つまり, q0 = 1, q1 = 0), ↓↓(11, つまり, q0 = 1, q1 = 1) の 4種類 の 出力結果があり得る. # Output result. for result in results: print(result) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
[出力結果] 測定を繰り返すと, 出力結果 も 変化. ※1回目. q0=00 q1=00 q0=00 q1=10 q0=11 q1=11 ※2回目. q0=00 q1=00 q0=10 q1=01 q0=11 q1=11 ※3回目. q0=00 q1=00 q0=10 q1=00 q0=11 q1=11 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
[編集内容(simulator.run_sweep is not used)] import cirq from cirq import Simulator import numpy as np # Pick two qubits. q0, q1 = cirq.GridQubit(0, 0), cirq.GridQubit(1, 0) # 以下のように理解. # 1. ↑↑(2量子ビット, 00 と見る) を 用意. # 2. 1量子ビット目に, X ゲート を 操作. # ※ 1量子ビット目が, ↑ もしくは ↓ に 変わるはず. # 3. 2量子ビット目に, X ゲート を 操作. # ※ 2量子ビット目が, ↑ もしくは ↓ に 変わるはず. # -> 1量子ビット目, 2量子ビット目の操作結果によって, # ↑↑(00, つまり, q0 = 0, q1 = 0), ↑↓(01, つまり, q0 = 0, q1 = 1), # ↓↑(10, つまり, q0 = 1, q1 = 0), ↓↓(11, つまり, q0 = 1, q1 = 1) の 4種類 の 出力結果があり得る. # Repeat 3 sets. for y in range(3): circuit = cirq.Circuit() op_1, op2 = cirq.X(q0) ** (y / 2.0), cirq.X(q1) ** (y / 2.0) circuit.append([op_1, op_2]) circuit.append([cirq.measure(q0, key='q0'), cirq.measure(q1, key='q1')]) # Simulate 2 times. simulator = cirq.Simulator() results = simulator.run(circuit, repetitions=2) # Output result. print(results) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
[出力結果] 測定を繰り返すと, 出力結果 も 変化. ※1回目. q0=00 q1=11 q0=00 q1=11 q0=11 q1=11 ※2回目. q0=00 q1=11 q0=10 q1=11 q0=11 q1=11 ※3回目. q0=00 q1=11 q0=11 q1=11 q0=11 q1=10 |
Mixed state simulations
cirq.DensityMatrixSimulator の 使い方 を 確認
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[編集内容(cirq.DensityMatrixSimulator)] import cirq from cirq import Simulator # Pick one qubit and Use Symbol value. q = cirq.NamedQubit('a') circuit = cirq.Circuit(cirq.H(q), cirq.amplitude_damp(0.2)(q), cirq.measure(q)) # Use cirq.DensityMatrixSimulator. simulator = cirq.DensityMatrixSimulator() result = simulator.run(circuit, repetitions=100) # Display histogram. print(result.histogram(key='a')) |
1 2 3 4 5 6 7 8 9 10 |
[出力結果] 測定を繰り返すと, 出力結果 も 変化. ※1回目. Counter({0: 62, 1: 38}) ※2回目. Counter({0: 59, 1: 41}) ※3回目. Counter({1: 51, 0: 49}) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[編集内容(cirq.DensityMatrixSimulator is not used)] import cirq from cirq import Simulator # Pick one qubit and Use Symbol value. q = cirq.NamedQubit('a') circuit = cirq.Circuit(cirq.H(q), cirq.amplitude_damp(0.2)(q), cirq.measure(q)) # Use cirq.Simulator. simulator = cirq.Simulator() result = simulator.run(circuit, repetitions=100) # Display histogram. print(result.histogram(key='a')) |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[出力結果] 測定を繰り返すと, 出力結果 も 変化. ※1回目. Counter({0: 70, 1: 30}) ※2回目. Counter({0: 67, 1: 33}) ※3回目. Counter({0: 58, 1: 42}) -> 本家サイトの以下のような説明から, 0: 60, 1: 40 が 期待される出力結果とのこと. We see that instead of about 50 percent of the timing being in 0, about 20 percent of the 1 has been converted into 0, so we end up with total around 60 percent in the 0 state. -> cirq.DensityMatrixSimulator を 使用した前項の方が, 期待される出力結果に近く, cirq.Simulatorを使用するよりも, 測定の精度が高くなると理解. |