Quandoomはなぜ量子ビットでDOOMを動かせるのか
目次
Quandoomは、DOOMの1面を量子回路として書いたプロジェクトだ。
論文版では72,376量子ビット、少なくとも8,000万ゲート。画面は320x200の白黒ピクセルで、最後の64,000量子ビットを測定してそのまま表示する。
最初に引っかかったのは、「量子コンピュータって特定の計算だけ爆速になるやつでは」という点だった。
そこはだいたい合っている。Quandoomは「量子コンピュータだからDOOMが速くなる」話ではない。
古典的なゲーム処理を、量子回路で実行できる形に無理やり書き直したデモだ。
ゲームの状態を量子ビットのレジスタに置く
量子ビットは重ね合わせにできるが、普通の0/1としても使える。
Quandoomではまずその性質を使って、プレイヤーのHP、弾数、位置、角度、敵の状態、画面出力を量子ビット列のレジスタとして持つ。
論文に載っている例だと、health は9量子ビット、ammoBullets は8量子ビット、cosTheta は23量子ビット、outputPixels は64,000量子ビット。
この時点では「量子っぽい謎の表現」ではなく、符号付き整数や固定小数点をビット列で持っているだけに近い。
たとえばHP 100を9ビットで表す、プレイヤー角度に対応するcos値を23ビットで持つ、画面の各ピクセルに1量子ビットを割り当てる。
ここまでは普通のコンピュータのメモリと発想が変わらない。
Toffoliゲートで普通の計算を作る
Quandoomの基本演算は、足し算、引き算、比較、等値判定、掛け算、割り算などだ。
これらをToffoliゲート中心で組む。
Toffoliゲートは、2つの制御ビットが両方1のときだけターゲットビットを反転するゲートだ。
古典論理で言えば「条件付きNOT」に近い。ANDの条件を見て、別のビットを反転する。
このゲートを大量に組み合わせると、古典的なブール計算を可逆な形で作れる。
普通のCPUなら if hp <= 0 then dead = 1 みたいに書くところを、Quandoomでは「比較用のレジスタを用意し、引き算して符号を見て、条件に合ったらビットを反転する」という回路に展開する。
ゲーム演算そのものは特別ではない。
入力を受け取り、移動判定をし、敵の状態を更新し、壁やスプライトを描画する。
ただし実装先がCPU命令ではなく、QuandoomEngineが生成する巨大なQASM回路になっている。
量子回路は捨てる計算が苦手
普通のプログラムでは、いらない中間値をすぐ捨てる。
x = min(x + 1, 5) のような処理も平気で書く。
量子回路ではこれが問題になる。
量子ゲートは基本的に可逆で、出力から入力へ戻せる形でなければならない。
4 -> 5 と 5 -> 5 が同じ結果に潰れる処理は、前の値が4だったのか5だったのか復元できない。
Quandoomの見た目が妙にワイヤーフレームで、壁の向こうが透けるのもこの制約と関係している。
画面ピクセルは「黒にセットする」のではなく「反転する」。
線が重なるとまた反転して抜ける。Zバッファで前後関係をきれいに潰すような処理は、素直にやると可逆性と相性が悪い。
論文では、前面にある物だけを描くには各オブジェクトを事前描画し、見えるものだけ出力した後、中間結果をuncomputeしなければならないと説明している。
uncomputeは、作った中間値を逆向きの回路で消して元に戻す処理だ。
量子計算ではこの後片付けがかなり重い。
DOOMっぽさはかなり焼き込みで作っている
QuandoomはDOOMのソースコードを量子回路へ機械変換したものではない。
作者は、元のDOOMコードを使わず、可逆ゲートで動くレンダリングエンジンを作り直したと書いている。
しかも、何でもリアルタイムに計算しているわけではない。
スプライトの拡大縮小は、あらかじめ各サイズの描画回路を焼き込んでいる。
敵からプレイヤーが見えるかどうかのレイキャストも、部屋を10x10程度の粗いグリッドに分けて事前計算している。
これはゲーム開発で言うbakeに近い。
動的に計算すると回路が複雑になるところを、生成時に展開しておく。
結果としてQASMファイルは巨大になるが、実行時の回路は単純な条件付きビット反転の塊に寄せられる。
この割り切りがあるので、Quandoomは「DOOMエンジンが量子コンピュータに移植された」というより、「DOOMのE1M1を、量子回路として走る別エンジンで作り直した」に近い。
重ね合わせはランダム性にだけ薄く出てくる
一番気になるのは重ね合わせだろう。
全部のプレイヤー位置が同時に存在して、全ルートを並列に進んで、測定したら1つのDOOM画面になる、みたいな話ではない。
Quandoomのゲーム状態は基本的に1つの古典状態として進む。
重ね合わせが使われるのは、命中判定、敵の行動、スタン判定のようなランダム処理だ。
回路の最初で random レジスタにHadamardゲートをかけ、そこから確率的な分岐を作る。
Hadamardゲートは、0や1の量子ビットを0と1の重ね合わせにする。
ただしQuandoomでは、そのランダム用量子ビットが画面用レジスタの未使用部分に置かれていて、各フレームで測定・リセットされる。
ここが「量子コンピュータなのにノートPCで10〜20fpsでシミュレーションできる」理由になる。
HadamardとToffoliは一般には強力なゲートセットだが、Quandoomでは負の位相や干渉がほぼ出ないように作ってある。
干渉がないなら、巨大な状態ベクトルを全部持たずに、Hadamardに来たところで乱数を振るサンプラーとして処理できる。
量子コンピュータの速さは、単に「重ね合わせで全部試す」から出るわけではない。
重ね合わせの枝同士を干渉させ、間違った答えの振幅を消し、欲しい答えの振幅を増やすアルゴリズムが要る。
暗号の話で出てくるShorのアルゴリズムもその系統で、PQCの記事で触れたRSAや楕円曲線への量子攻撃は、DOOMを動かす話とはかなり別物だ。
Quandoomはこの干渉をほぼ使っていない。
だから量子優位性はない。
その代わり、量子回路としては成立していて、古典シミュレータでも動かせる。
本物の量子コンピュータではまだ動かない
GitHubのREADMEは「たった70,000量子ビットと8,000万ゲート」と冗談めかして書いているが、今の量子コンピュータにとってはまったく小さくない。
論文の正確な数字では72,376量子ビット。
しかもゲームとして動かすには、1フレームごとに巨大な回路を適用し、64,000量子ビットを測定して画面にする必要がある。
2026年時点の実機量子コンピュータで、これをエラー訂正込みで安定に走らせるのは現実的ではない。
Quandoomの配布版も、実際には150行程度のC++ QASMシミュレータで古典コンピュータ上から動かす。
READMEによると、起動時に5〜6GB程度のRAMを使い、大きな回路ファイルを読み込む。
真空揺らぎとシミュレーションの違い
量子コンピュータの量子ビットが壊れる理由をもう少し踏み込むと、真空揺らぎの話が出てくる。
量子場理論では、何もない真空でも仮想粒子と反粒子のペアが常に出現と消滅を繰り返している。
カシミール効果(2枚の金属板を真空中で極めて近づけると引力が生じる現象)は、この真空揺らぎが実在することを示す実験結果の一つだ。
「真の空っぽ」は量子の世界には存在しない。
この揺らぎは、量子ビットにとってノイズ源になる。
量子ビットが重ね合わせ状態を失う現象をデコヒーレンスと呼ぶが、その原因は熱雑音、電磁干渉、制御パルスの不完全さなど多岐にわたる。
真空揺らぎもその一つで、量子ビット周囲の電磁場がゼロ点エネルギーで揺れていることが量子ビットの状態を乱す。
超伝導方式の量子ビットだとコヒーレンス時間は数十〜数百マイクロ秒程度。
この間に計算を終えなければ結果が壊れる。
実機の量子コンピュータはこの問題を量子エラー訂正で扱う。
1つの論理量子ビットを大量の物理量子ビットで冗長に符号化し、壊れた部分を検出・修復しながら計算を進める。
代表的な表面符号では論理1量子ビットあたり物理量子ビットが約1,000個必要になるので、Quandoomの72,376論理量子ビットなら物理量子ビットは7,000万個以上。
2026年時点で最大級のプロセッサが1,000量子ビット台だから、桁が4つ足りない。
シミュレーションではこの問題がまるごと消える。
古典シミュレータは量子ビットを複素数の振幅として数学的に持っているだけだ。
物理的な媒体がないから真空揺らぎもデコヒーレンスも起きない。
エラー訂正も不要で、回路の定義通りの完璧な結果が出る。
QuandoomがノートPCで動く理由は、干渉を使わないから古典サンプリングできるという話に加えて、実機なら致命的になる量子ビットの崩壊がシミュレーションにはそもそも存在しない、という点もある。
まあ、こいつが実機で動かなくて困る人間はいないので、それはそれでいい。