はじめに
量子コンピュータは、私たちの生活を大きく変える可能性を秘めた新しい技術です。しかし、その仕組みや応用方法は複雑で理解しづらいことも多いです。ここでは、QUBOやHOBOといった数理モデルから始めて、イジングモデルへの変換、そして量子回路への導入までを、少しずつ解説していきます。
今回は実際に量子ゼミナールという塾で、高校生向けの授業で疑問が出たところをブログとして公開しています。同じようなところで迷う人もいるかもしれません。
QUBOとHOBOとは?
**QUBO(Quadratic Unconstrained Binary Optimization)とHOBO(Higher-Order Binary Optimization)**は、組合せ最適化問題を解くための数学的な枠組みです。具体的には、バイナリ(0と1)の変数を用いて、目的関数を最適化します。
- QUBO: 2次の項までを含む最適化問題。例えば、
のように、変数の積が含まれます。f(x) = x_1x_2 + x_2x_3 + \dots - HOBO: それ以上の次数(3次以上)の項を含む最適化問題。
これらの問題は、多くの実世界の課題(スケジューリング、グラフの色付け、パターン認識など)に応用できます。
QUBO/HOBOからイジングモデルへの変換
イジングモデルは、物理学で磁性体のスピンの相互作用を表すために使われるモデルです。QUBOやHOBOをイジングモデルに変換することで、量子回路での計算が可能になります。
変換のステップ:
-
変数の変換:
-
QUBOやHOBOでは変数が0または1ですが、イジングモデルではスピンが+1または-1を取ります。
-
変数変換の例:
x_i = \frac{1 - z_i}{2} ここで、
はQUBO/HOBOの変数、x_i はイジングモデルのスピン変数です。QUBOをイジングに変換するときに、x=1をz=1に、x=0をz=-1に変換したくなりますが、実際に量子ビットでは|0>状態の時にzは期待値1を、|1>状態の時にzは期待値が-1になるので、上記のような式変形がいいです。z_i
-
-
目的関数の再構築:
- QUBOの目的関数をイジングモデルに適合させるために、変換した変数を用いて式を再構築します。
- これにより、イジングハミルトニアンとして表現できるようになります。
定数の除去
変換後のイジングハミルトニアンには、定数項が含まれることがあります。量子計算では、これらの定数はエネルギーの基準値としてのみ機能し、計算結果には影響しません。したがって、定数項を除去することで、計算を簡略化できます。
例:
ここで、
時間発展演算子と角度へのハミルトニアンの係数導入
量子回路では、ハミルトニアンを用いて量子ビットの状態を時間発展させます。具体的には、ハミルトニアンの係数を回転角度として導入します。
ステップ:
-
ハミルトニアンの分解:
- ハミルトニアン
をPauli行列に分解します。H
H = \sum_k \theta_k P_k ここで、
は係数、\theta_k は基底演算子です。P_k - ハミルトニアン
-
量子ゲートへの対応:
- 各基底演算子
に対応する量子ゲート(例えば、回転ゲート)を導入します。P_k - 係数
はゲートの回転角度として用いられます。\theta_k
- 各基底演算子
-
時間発展演算子の構築:
- 全てのゲートを組み合わせて、ハミルトニアンによる時間発展を表現します。
U(t) = e^{-iHt/\hbar} - これにより、量子ビットの状態がハミルトニアンに従って変化します。
時間発展演算子と任意回転ゲート
上記のハミルトニアンは時間発展計算では、RZやRZZゲートのような任意回転ゲートと呼ばれるものに変換されます。これらは角度を自分で決められ、ZやZZの量子ゲートの時間発展の形式になっています。もっと詳しく見るとトロッター展開などが出てきますが、今回は単にハミルトニアンからゲートへの導入の仕方だけを部分的に見てみます。
参考:
これを量子ゲートに直すと、RZ(-2at)やRZ(2at)のような形式になりますが、aが先ほどのハミルトニアンにおける項の係数に相当します。このようなルールで、QUBO/HOBOからイジングハミルトニアンに変換、それぞれの項の係数を時間発展演算子(今回はRZとかRZZとか)の角度に入れることによって計算ができます。
例題
実際にpythonを使って具体例を見てみます。
QUBOの例としては、
を適当に用意してみます。この式ではxは01のどちらかを取ります。2量子ビットの式で、最小値はおそらく00か01になりそうです。
import sympy as sp
# シンボルの定義
x0, x1 = sp.symbols('x0 x1')
# 式を作成
expr = 2*x0 + 3*x0*x1
# 式を表示
expr
こちらに最初にzに変換をします。
z0, z1 = sp.symbols('z0 z1')
expr_substituted = expr.subs({x0:(1 - z0)/2,x1:(1 - z1)/2})
expr_substituted.expand()
これで、
最後は定数なので、除外します。
次にこちらの係数をみます。
次にqisikitを使ってみます。
! pip install qiskit qiskit-optimization pylatexenc
from qiskit import QuantumCircuit, transpile
from qiskit.primitives import Sampler
from qiskit_algorithms.optimizers import COBYLA
from qiskit.quantum_info import SparsePauliOp
from qiskit_algorithms.minimum_eigensolvers import QAOA
initial_state_circuit = QuantumCircuit(2)
initial_state_circuit.h(0)
initial_state_circuit.h(1)
initial_state_circuit.barrier()
sampler = Sampler()
optimizer = COBYLA()
step = 1
# コストハミルトニアンの定義
cost = SparsePauliOp(["ZZ", "ZI", "IZ"], [3/4, -7/4, -3/4])
qaoa = QAOA(
sampler,
optimizer,
reps=step,
initial_state=initial_state_circuit,
)
result = qaoa.compute_minimum_eigenvalue(cost)
print(result)
display(result.optimal_circuit.draw('mpl'))
ちょっと回路表記が簡略化されています。
!pip install qiskit-aer
from qiskit_aer import AerSimulator
bound_circuit = result.optimal_circuit.assign_parameters(result.optimal_parameters)
sim = AerSimulator()
t_qc = transpile(bound_circuit, backend=sim)
counts = sim.run(t_qc).result().get_counts()
print(counts)
でみてみると、
{'10': 10, '00': 422, '01': 592}
答えは良さそうです。
回路表記が簡略化されてしまっています。
blueqat autoQAOAを使って確認してみます。最近改修しましたがまだちょっとバグがあるみたいでマイナス記号が使えませんでした。
3*ZZ+7*IZ+3ZI
を入れてみました。
雰囲気が伝わるでしょうか。角度が2倍されて入っています。ガンマやベータはQAOAでいう変分パラメータというもので、実際には時間発展のtを置き換えてパラメータにしています。今後FTQCではパラメータではなく、スケジュールと言って自分で決めることになるかもしれません。
まとめ
このように、QUBOやHOBOの定式化から始めてイジングモデルへの変換、定数の除去、そして量子回路への導入までを段階的に理解することで、量子コンピュータの基本的な仕組みをつかむことができます。高校生にも親しみやすい例や図を用いながら、具体的な応用例を紹介すると、さらに理解が深まるでしょう。