量子コンピュータの勉強を続けており、Cirqの資料をひたすら読み進めている。
以下の資料を読みながら勉強中である。
- Cir: Tutorial
Tutorial — Cirq 0.1 documentation
一度チュートリアルを読んだのだが、意味が分からずに諦めてしまったのであった。リトライする。
上記のCirqの例では、イジングモデルを作成し、まずは量子ビット間の関係を示す$jr$, $jc$をランダムに決める。 その値に従って量子ビットに対してXゲートを適用している。
つまり、ランダムなので最初の量子回路の形は毎回異なるらしい。量子ビットの位相回転のパラメータを自由に設定しているということになる。
チュートリアルでは、3つの量子ビットの回転角度をそれぞれ$\alpha, \beta, \gamma$としている。 $\alpha=0.1, \beta=0.2, \gamma=0.3$として設定したときの量子回路は以下のようになった。
(0, 0): ───X^0.1───────────@───────────────────────────────────────────────────────────────────────────────────────────M('x')─── │ │ (0, 1): ───X^0.1───────────┼───────X───@───────X───────────────────────────────@───────────────────────────────────────M──────── │ │ │ │ (0, 2): ───X^0.1───────────┼───────────┼───────────@───────────────────────────@^0.3───────────────────────────────────M──────── │ │ │ │ (1, 0): ───X^0.1───Z^0.2───@^0.3───────┼───────────┼───────@───────────────────────────────────@───────────────────────M──────── │ │ │ │ │ (1, 1): ───X^0.1───────────X───────────@^0.3───X───┼───────┼───────X───@───────X───────────────@^0.3───@───────────────M──────── │ │ │ │ │ (1, 2): ───X^0.1───────────────────────────────────@^0.3───┼───────────┼───────────────@───────────────@^0.3───────────M──────── │ │ │ │ (2, 0): ───X^0.1───Z^0.2───────────────────────────────────@^0.3───────┼───────────────┼───────────────@───────────────M──────── │ │ │ │ (2, 1): ───X^0.1───Z^0.2───────────────────────────────────────────X───@^0.3───X───────┼───────────────@^0.3───@───────M──────── │ │ │ (2, 2): ───X^0.1───Z^0.2───────────────────────────────────────────────────────────────@^0.3───────────────────@^0.3───M────────
この時にシミュレーションを行った結果、最終的に9つの量子ビットはどのような状態になりうるだろうか。 それをシミュレーションしたのが以下の結果である。 100回シミュレーションを繰り返し、量子ビットの観測結果をヒストグラムで表示してある。
... circuit.append(one_step(h, jr, jc, 0.1, 0.2, 0.3)) circuit.append(cirq.measure(*qubits, key='x')) print(circuit) results = simulator.run(circuit, repetitions=100, qubit_order=qubits) ...
実行結果。
$ python3 cirq_tutorial.py Counter({0: 83, 4: 4, 32: 3, 256: 2, 64: 2, 128: 2, 8: 1, 2: 1, 144: 1, 320: 1})
この時の量子状態において、エネルギー関数を計算する。
このためにenergy_func()
という関数を定義する。
def energy_func(length, h, jr, jc): def energy(measurements): meas_list_of_lists = [measurements[i:i + length] for i in range(length)] pm_meas = 1 - 2 * np.array(meas_list_of_lists).astype(np.int32) tot_energy = np.sum(pm_meas * h) for i, jr_row in enumerate(jr): for j, jr_ij in enumerate(jr_row): tot_energy += jr_ij * pm_meas[i, j] * pm_meas[i + 1, j] for i, jc_row in enumerate(jc): for j, jc_ij in enumerate(jc_row): tot_energy += jc_ij * pm_meas[i, j] * pm_meas[i, j + 1] return tot_energy return energy def obj_func(result): energy_hist = result.histogram(key='x', fold_func=energy_func(3, h, jr, jc)) return np.sum(k * v for k,v in energy_hist.items()) / result.repetitions
この時のエネルギー関数は以下のようになった。
$ python3 cirq_tutorial.py [cirq.GridQubit(0, 0), cirq.GridQubit(0, 1), cirq.GridQubit(0, 2), cirq.GridQubit(1, 0), cirq.GridQubit(1, 1), cirq.GridQubit(1, 2), cirq.GridQubit(2, 0), cirq.GridQubit(2, 1), cirq.GridQubit(2, 2)] Counter({0: 81, 128: 5, 2: 3, 64: 3, 16: 2, 1: 1, 320: 1, 32: 1, 264: 1, 8: 1, 4: 1}) Value of the objective function -0.72
最後に、この3つのパラメータを0.0から1.0まで変化させていき、その時の最小値を求める。このためにはrun_sweep()
関数を用いて複数の条件を一気にシミュレーションする。
circuit = cirq.Circuit() alpha = cirq.Symbol('alpha') beta = cirq.Symbol('beta') gamma = cirq.Symbol('gamma') circuit.append(one_step(h, jr, jc, 0.1, 0.2, 0.3)) circuit.append(cirq.measure(*qubits, key='x')) results = simulator.run(circuit, repetitions=100, qubit_order=qubits) print(results.histogram(key='x')) print('Value of the objective function {}'.format(obj_func(results)))
$ python3 cirq_tutorial.py ... OrderedDict([('alpha', 1.0), ('beta', 1.0), ('gamma', 0.3333333333333333)]) -4.64 OrderedDict([('alpha', 1.0), ('beta', 1.0), ('gamma', 0.4444444444444444)]) -4.58 OrderedDict([('alpha', 1.0), ('beta', 1.0), ('gamma', 0.5555555555555556)]) -4.82 OrderedDict([('alpha', 1.0), ('beta', 1.0), ('gamma', 0.6666666666666666)]) -4.68 OrderedDict([('alpha', 1.0), ('beta', 1.0), ('gamma', 0.7777777777777778)]) -4.44 OrderedDict([('alpha', 1.0), ('beta', 1.0), ('gamma', 0.8888888888888888)]) -4.7 OrderedDict([('alpha', 1.0), ('beta', 1.0), ('gamma', 1.0)]) -4.5 Minimum objective value is -4.96.