量子アニーラや量子コンピュータではガチャを実装することができます。ある欲しいキャラクターの出現確率に対して量子コンピュータでは確率分布を操作することで実装ができます。早速やってみましょう。
D-Wave Ocean
今回は本物のマシンを利用するので、D-Wave Oceanを利用してみます。pythonから利用でき、pipでインストールは、
pip install dwave-ocean-sdk
で簡単にできます。
ガチャの仕組み
以前別のブログ記事でも紹介した気がしますが、D-Waveの量子アニーリングマシンや、量子コンピュータでは、任意の確率分布で答えを出現させることができます。D-Waveでは一つの式だけでそれを実現できます。あるキャラクターが出る確率は、p(x) = 1/Z * exp(-E)で計算でき、Eが式に相当します。実際には学習が大変なのですが、今回は学習が済んだこと前提でやってみます。
ツールの読み込み
今回はD-Waveの最新マシンであるAdvantage System 1.1を使ってみます。
import numpy as np
from dwave.system.samplers import DWaveSampler
from dwave.system.composites import EmbeddingComposite
数値ライブラリのnumpy、実機のサンプリングをするためのDWaveSamplerそして、問題を実機のQPUに埋め込むためのEmbeddingCompositeを利用します。
token = "ここにトークン"
qubo = np.array([[0,-2,10],[0,0,-1],[0,0,-0.5]])
bqm = dimod.BQM.from_numpy_matrix(qubo)
D-Waveから発行されるトークンを利用してみます。また、今回のガチャの肝となる数式はquboと呼ばれる行列の形で準備します。quboは上三角行列です。最後に、D-Waveに投げられる形式として、quboからBQMに変換します。
実際に投げてみる
早速投げてみましょう。今回は最新のAdvantage system 1.1に投げます。APIエンドポイントとtokenを設定します。今回は1000回やります。
response = EmbeddingComposite(DWaveSampler(endpoint='https://cloud.dwavesys.com/sapi', token=token, solver='Advantage_system1.1')).sample(bqm, num_reads=1000)
print(response)
これを実行すると、
0 1 2 energy num_oc. chain_.
0 1 1 0 -2.0 551 0.0
1 0 1 1 -1.5 375 0.0
2 0 0 1 -0.5 38 0.0
3 1 0 0 0.0 11 0.0
4 0 0 0 0.0 15 0.0
5 0 1 0 0.0 10 0.0
['BINARY', 6 rows, 1000 samples, 3 variables]
こうなりました。エネルギー値の小さい方が出やすく、エネルギー値が0.0のものは出現確率が低くなっています。これを利用することで、今回は1000回計算したので、確率分布が見えますので、これにキャラを設定すれば良くなります。
1回ガチャを回す
これを利用し、ガチャを1回回してみます。
response = EmbeddingComposite(DWaveSampler(endpoint='https://cloud.dwavesys.com/sapi', token=token, solver='Advantage_system1.1')).sample(bqm, num_reads=1)
a = list(response.first.sample.values())
if a == [1,0,0]:
print("SSR")
elif a == [1,1,0]:
print("N")
elif a == [0,0,0]:
print("HR")
else:
print("R")
num_read=1としました。サンプルを配列で取り出すには、response.first.sample.values()を使います。あとは、対応する配列にレア度を割り当てます。ガチャをボルツマンガチャと命名しましょう。
10連回す
たくさん回したいです。10連にします。
response = EmbeddingComposite(DWaveSampler(endpoint='https://cloud.dwavesys.com/sapi', token=token, solver='Advantage_system1.1')).sample(bqm, num_reads=10)
print(response.record)
arr = []
for item in response.record:
for _ in range(item[2]):
a = list(item[0])
if a == [1,0,0]:
b = "SSR"
elif a == [1,1,0]:
b = "N"
elif a == [0,0,0]:
b = "HR"
else:
b = "R"
arr.append(b)
random.shuffle(arr)
print(arr)
今回の肝はnum_read=10としました。結果はresponse.recordから取り出せます。計算結果と出現回数がセットでまとまっているので、それをバラします。また、最後にまとまった結果をシャッフルしてそれっぽく表示してみます。
[([1, 1, 0], -2. , 8, 0.) ([0, 1, 1], -1.5, 2, 0.)]
['R', 'N', 'R', 'N', 'N', 'N', 'N', 'N', 'N', 'N']
こんな感じです。上記では、110が8回、011が2回出たので、それを良い感じで出力しました。
魅惑の一万連
最後にD-Waveは一度に最大10000回の計算ができます。これを利用し、一万連を実行します。
bqm = dimod.BQM.from_numpy_matrix(qubo)
response = EmbeddingComposite(DWaveSampler(endpoint='https://cloud.dwavesys.com/sapi', token=token, solver='Advantage_system1.1')).sample(bqm, num_reads=10000)
print(response)
計算結果は、
0 1 2 energy num_oc. chain_.
0 1 1 0 -2.0 5836 0.0
1 0 1 1 -1.5 3427 0.0
2 0 0 1 -0.5 444 0.0
3 1 0 0 0.0 114 0.0
4 0 0 0 0.0 99 0.0
5 0 1 0 0.0 80 0.0
['BINARY', 6 rows, 10000 samples, 3 variables]
こうなりました。111はなかなか出ません。多分1万回に1度出るくらいかと思います。ちょっと整理してみます。
arr = []
ss = 0
for item in response.record:
a = list(item[0])
if a == [1,0,0]:
b = 4
elif a == [1,1,0]:
b = 1
elif a == [0,0,0]:
b = 3
elif a == [1,1,1]:
b = 5
else:
b = 2
if b !=2:
arr.append([b,item[2]])
ss = ss+item[2]
aa = 10000 - ss
arr.append([2,aa])
print(arr)
整理すると、
[[1, 5570], [4, 81], [3, 98], [5, 1], [2, 4250]]
こうなりました。配列の最初の数字がレア度で、後の数字が出現回数です。これをうまく表示させればガチャの完成です!
量子ガチャを回そう!
こちらは実際に超電導タイプの量子ビットを利用しています。ぜひ、本物を利用してガチャを体験してみてください。面白いですよ。以上です!