Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GPU バックエンドテンプレート #352

Draft
wants to merge 15 commits into
base: main
Choose a base branch
from
Draft

Conversation

yasuhito
Copy link
Contributor

@yasuhito yasuhito commented Jun 8, 2023

これは何?

GPU で動く Cirq (on cuQuantum) をバックエンドとして組込むためのテンプレートです。http://localhost:3000/cirq/ にアクセスすると、標準とは異なるバックエンドで量子回路シミュレーションを行う Qni を起動できます。

(サンプルを実行した様子。でたらめな状態ベクトルを表示するだけ)
CleanShot 2023-06-08 at 11 02 34

サンプルの内容

サンプルバックエンド (apps/www/bin/cirq.py) は Qni で編集した量子回路を JSON で受け取り、ランダムな (でたらめな) 状態ベクトルを返します (上の gif 参照)。実際の量子計算はせず、あくまでサンプル実装です。cirq.py から Cirq (と Qsim, cuQuantum) を呼び出せば、正しい実行結果を Qni に表示することもできるはずです。

CleanShot 2023-06-12 at 13 44 04@2x

Qni から cirq.py への JSON

Qni から cirq.py へは Qni で構築した量子回路のデータが JSON として送られます。

CleanShot 2023-06-12 at 13 49 23@2x
{
  "circuit_id": "{\"cols\":[[\"H\"]]}",
  "qubit_count":1,
  "step_index":0,
  "steps":[[{"type":"H","targets":[0]}],[],[],[],[]],
  "targets":[0,1]
}

JSON の各プロパティの意味はこんな感じです

  • circuit_id: 回路を一意に表す ID 文字列
  • qubit_count: 回路で使用している量子ビット数
  • step_index: Qni で実行結果を表示中のステップ番号
  • steps: 回路データの各ステップの配列
  • targets: 必要な振幅のインデクス (通常は 0..qubit_count^2 の値)

cirq.py から Qni へ返す実行結果の JSON

cirq.py から Qni へ回路の実行結果 (状態ベクトル) を JSON で返します。回路が 5 ステップある場合には、次のように 5 要素の配列となり、それぞれがステップの実行結果になります。"amplitudes" は振幅を表していて、振幅を表す複素数が [実部, 虚部] の形で入ります。

[
  {"amplitudes": {"0": [0.14339366384416108, 0], "1": [0.652660119020844, 0]}},
  {"amplitudes": {}},
  {"amplitudes": {}}, 
  {"amplitudes": {}},
  {"amplitudes": {}}
]

cuQuantum とつなぐには

cirq.py の中で cuQuantum 入りでビルドした cirq を import すればできるはずです。実装は多少異なりますが、理研中田さんによる実装 #83 が参考になるかもしれません。

メモ

Cirq の Mac へのインストール方法
https://quantumai.google/cirq/start/install#installing_on_mac_os_x

TODO

measuredBits,
flags,
if (resultCache[circuitJson][i] === undefined) {
resultCache[circuitJson][i] = {}

Check warning

Code scanning / CodeQL

Prototype-polluting assignment

This assignment may alter Object.prototype if a malicious '__proto__' string is injected from [user controlled input](1).
const measuredBits = Object.assign({}, simulator.measuredBits)
const flags = Object.assign({}, simulator.flags)

resultCache[circuitJson][i] = {

Check warning

Code scanning / CodeQL

Prototype-polluting assignment

This assignment may alter Object.prototype if a malicious '__proto__' string is injected from [user controlled input](1).
@yasuhito yasuhito self-assigned this Jun 8, 2023
@yasuhito yasuhito added the enhancement New feature or request label Jun 8, 2023
@yasuhito yasuhito marked this pull request as draft June 8, 2023 08:32
@yasuhito
Copy link
Contributor Author

yasuhito commented Aug 24, 2023

状態ベクトルがおかしくなる現象ですが、以下の 2 点の修正が必要です。

  1. ゲートの配置を上下逆にする (Qni のリトルエンディアンから CIrq のビッグエンディアンへ)
  2. ゲートを置かない位置に I ゲート (= 単位行列) を置く。

以下、Cirq で X ゲートだけを使った簡単な回路を実行するためのコードです。まずはこちらで実験してみて、1, 2 の修正をすればノーマルな Qni の実行結果 (状態ベクトル) と同じになることを確認してみてください。

import cirq

circuit = cirq.Circuit()
qubits = cirq.LineQubit.range(4) # 0, 1, 2, 3 を連番で準備
simulator = cirq.Simulator()

# ゲートを置く
#
# - 上下を逆にすると Qni の結果と等しくなります。
# - 1, 2 行目をコメントアウトし I ゲートを置かないようにすると、X ゲートのない量子ビットは無視されるので、
#    1 量子ビットの回路になります (Cirq が勝手に圧縮する)。
circuit.append(cirq.I(qubits[0]))
circuit.append(cirq.I(qubits[1]))
circuit.append(cirq.X(qubits[2]))

print(circuit)
print()

# 回路をステップごとに表示
for index, step in enumerate(simulator.simulate_moment_steps(circuit)):
    print(index)
    print(step.state_vector())

参考

Cirq のドキュメント (Cirq はビッグエンディアン) https://quantumai.google/reference/python/cirq/SparseSimulatorStep#state_vector

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants