common.title

Docs
Quantum Circuit
TYTAN CLOUD

QUANTUM GAMING


Overview
Contact
Event
Project
Research

Terms of service (Web service)

Terms of service (Quantum and ML Cloud service)

Privacy policy


Sign in
Sign up
common.title

blueqat cloud経由でのD-Waveでのクラスタリング問題

Yuichiro Minato

2021/04/16 01:37

#量子アニーリング #blueqat cloud

こんにちは、今日はblueqat cloudを利用して簡単なクラスタリングを実行したいと思います。こちらはまだAPIを作ったばかりなので、フロントエンドのツール類はこれから少しずつ提供される予定なので、現時点ではちょっと煩雑かもしれませんが、楽しめる方は見ていただけると幸いです。
このファイルは、記事ページから直接blueqat cloudの自分のアカウントにimportできる機能が付いています。クラウドのダウンロードマークを押すと自分のblueqat cloudのフォルダにimportされます。
API関連整備
まずはツール類を読み込み関数を作ります。ポイントはタスクを投げるところ、回収するところです。APIのキーは事前に.passというテキストファイルに記述しておいてあり、そっから読み込んでます。

import json
import urllib.request

import numpy as np
import pandas as pd
import networkx as nx
from blueqat.wq import *
import matplotlib.pyplot as plt

%matplotlib inline


f = open('.pass', 'r', encoding='UTF-8')
API_KEY = f.read()[:-1]
f.close()

API_ENDPOINT = "https://cloudapi.blueqat.com/v1/"

def post_request(path, body):
    headers = {
        'Content-Type': 'application/json',
        'X-Api-Key': API_KEY,
    }
    req = urllib.request.Request(
        API_ENDPOINT + path, json.dumps(body).encode(), headers)
    with urllib.request.urlopen(req) as res:
        body = res.read()
    return json.loads(body)


def get_quantum_tasks(index):
    path = "quantum-tasks/list"
    body = {
        "index": index,
    }
    return post_request(path, body)


def get_quantum_task(id):
    path = "quantum-tasks/get"
    body = {
        "id": id,
    }
    return post_request(path, body)


def create_quantum_task(qubo, num_reads, chain_strength=8):
    path = "quantum-tasks/create"
    body = {
        "qubo": qubo,
        "num_reads": num_reads,
        "chain_strength": chain_strength
    }
    return post_request(path, body)


def get_credit():
    path = "credit/get"
    return post_request(path, {})

次に、クラスタリングを進めます。こちらは以前行った記事をベースに組み立てます。
https://blueqat.com/yuichiro_minato2/af8fa7e9-d020-4a92-a3e1-fecf43bafb0a

今回は20ノードを2つのクラスタに分けます。全部で40量子ビット必要です。

n_node = 20
n_cluster = 2
N = n_node*n_cluster

print(N)
40

適当にデータを作ります。

x = np.random.normal(0, 1.5, int(n_node/2))
y = np.random.normal(0, 1.5, int(n_node/2)) 

x = np.append(x, np.random.normal(5, 1.5, int(n_node/2)))
y = np.append(y, np.random.normal(5, 1.5, int(n_node/2)))
 
# 散布図を描画
plt.scatter(x, y)
<matplotlib.collections.PathCollection at 0x7fd0d75df3d0>
<Figure size 432x288 with 1 Axes>

image

次にqubo matrixと呼ばれる問題設定をします。

#initialize distance
d = np.zeros((n_node,n_node))

for i in range(0, n_node-1):
    for j in range(i+1, n_node):
        a = np.array([x[i],y[i]])
        b = np.array([x[j],y[j]])
        d[i][j] = np.linalg.norm(a-b)

#map distance to qubo
A = np.zeros((N,N))

for i in range(0, n_node-1):
    for j in range(i+1, n_node):
        A[i*2][j*2] = A[i*2+1][j*2+1] = d[i][j]
        
#initialize constraint
B = np.zeros((N,N))

for i in range(N):
    B[i][i] = -1

for i in range(n_node):
    B[i*2][i*2+1] = 2

きちんとできているかどうか確認します。まずはネットワークグラフでの確認。

#set a QUBO
M = 1
qubo = A+B*M

#show as network
G = nx.from_numpy_matrix(qubo)
nx.draw_networkx(G)
plt.show()
<Figure size 432x288 with 1 Axes>

image

次は行列自体を可視化してみます。

plt.imshow(qubo)
plt.colorbar()
plt.show()
<Figure size 432x288 with 2 Axes>

image

早速解いてみますが、シミュレータでやってみます。調整変数Mを導入して50にしてみます。そして、先ほどの散布図に色として導入します。

#to simulator
M = 50
qubo = A+B*M

a = Opt()
a.qubo = qubo
res = a.run()

print(sum(res))

plt.scatter(x, y, c=res[::2])
20
<matplotlib.collections.PathCollection at 0x7fd0d72901f0>
<Figure size 432x288 with 1 Axes>

image

きちんとイジングとしてクラスタリングができています。上の20という数字は0が20こ、1が20こ、合計20となっているので、クラスタリングできている目安として使っています。続いてblueqat cloudを利用して実機のD-Wave Advantageを利用してみます。今回はquboを作ると、自動的にサーバーサイドで実機の接続に直して埋め込んでくれます。1000回の実行となっています。

num_reads = 10000

#to D-Wave Advantage
M = 100
qubo = (A+B*M).tolist()

result = create_quantum_task(qubo, num_reads)
table = pd.read_json(result["task"]["dataframe"]).sort_values('energy')
result2 = table.loc[0][0:N].astype('int').to_list()

print(sum(result2))

plt.scatter(x, y, c=result2[::2])
16
<matplotlib.collections.PathCollection at 0x7fd0d6fd3f40>
<Figure size 432x288 with 1 Axes>

image

データは1000回計算した結果が、表として得られました。今回はそれをさらにエネルギー値でソートし、一番低いエネルギーの解が一番正解に近いということで取り出しました。チェーンの接続強さとかを調整するともっと良い解が得られますが、今回はデフォルトでやってみました。テーブルは参考に下記のようになりました。

table
      0  1  2  3  4  5  6  7  8  9  ...  33  34  35  36  37  38  39  \
27    1  0  0  1  0  1  0  1  0  1  ...   0   1   0   1   0   1   0   
625   0  1  1  0  1  0  1  0  0  1  ...   1   0   1   0   1   1   0   
2050  1  0  0  1  0  1  0  1  0  1  ...   1   1   0   1   0   1   0   
4971  1  0  0  1  0  1  0  1  1  0  ...   1   1   0   1   0   0   1   
4174  0  1  0  1  0  1  0  0  0  1  ...   0   1   0   1   0   0   1   
...  .. .. .. .. .. .. .. .. .. ..  ...  ..  ..  ..  ..  ..  ..  ..   
9104  1  0  0  1  1  0  0  1  0  0  ...   0   0   0   0   1   0   1   
3233  1  0  1  0  0  1  1  0  1  1  ...   0   0   0   0   0   0   0   
9797  0  1  1  0  0  0  1  1  0  0  ...   1   0   0   1   0   0   0   
9958  0  1  1  1  1  1  0  0  0  1  ...   0   0   1   0   1   1   1   
8870  1  0  1  1  0  0  0  0  0  1  ...   0   1   1   1   1   1   1   

      chain_break_fraction       energy  num_occurrences  
27                   0.200 -1668.444513                1  
625                  0.225 -1658.498630                1  
2050                 0.250 -1655.938749                1  
4971                 0.250 -1624.865138                1  
4174                 0.275 -1609.859855                1  
...                    ...          ...              ...  
9104                 0.475  -587.514587                1  
3233                 0.425  -538.120855                1  
9797                 0.475  -499.884221                1  
9958                 0.475  -472.141642                1  
8870                 0.475  -337.330693                1  

[10000 rows x 43 columns]

調整変数の調整などで多少改善しますが、今回はランダムで作成した座標データの係数が細かいと実機への搭載時にやはり課題となりそうです。今回は以上です。

© 2025, blueqat Inc. All rights reserved