コンテンツにスキップ

D-Waveマシン(QA)の使い方

「量子アニーリングって、本当に使えるの?」 そう思うかもしれません。実は、すでに様々な分野で実証実験や実用化が進んでいます。実用化されている例を簡単に示します。

分野課題の例量子アニーリングの効果
物流・交通トラックの配送ルート、渋滞解消走行距離の短縮、CO2削減、配送時間の短縮
金融投資ポートフォリオの作成リスクを最小限に抑えつつ、利益を最大化する組み合わせを発見
広告Web広告の配信どのユーザーにどの広告を出せばクリック率が最大になるか瞬時に判断

実践:巡回セールスマン問題と数式

Section titled “実践:巡回セールスマン問題と数式”

ここからは、実際に物流現場の課題 「巡回セールスマン問題(TSP)」 を解いてみます。 「4つの都市(0, 1, 2, 3)を1回ずつ回って、最短距離で帰ってくるルート」を見つける問題です。

コードを書く前に、ひとつだけ重要なルールがあります。 量子アニーリングマシンは、どんな複雑な問題でも 「QUBO(キューボ)」 と呼ばれる以下の数式形式に変換しないと理解できません。

QUBO: Quadratic Unconstrained Binary Optimization(二次制約なし二値最適化)

H=i,jQijxixjH = \sum_{i,j} Q_{ij} x_i x_j

難しい式に見えますが、要するに 「変数 xx 同士の掛け算(二次式)と足し算だけで書いてね」 というルールです。 (※ xx は 0 か 1 の値しか取れません)

例えば、「必ず1つ選ぶ」という制約を表すには (x1+x2+x31)2(x_1 + x_2 + x_3 - 1)^2 という式を使いますが、これをマシンに渡すには x12+x22++2x1x2x_1^2 + x_2^2 + \dots + 2x_1x_2 \dots のように展開して計算する必要があります。

📝 問題をどうやってビット(0/1)で表す?

Section titled “📝 問題をどうやってビット(0/1)で表す?”

「ルートの順番」のような複雑なものを、どうやって0と1だけで表すのでしょうか? ここでは 「都市 × 順番」の表(行列) を用意して考えます。 (※今回は4都市なので 4×4=164 \times 4 = 16 個の量子ビットを使います)

1番目2番目3番目
都市0x0,0x_{0,0}x0,1x_{0,1}x0,2x_{0,2}
都市1x1,0x_{1,0}x1,1x_{1,1}x1,2x_{1,2}
都市2x2,0x_{2,0}x2,1x_{2,1}x2,2x_{2,2}

もし「都市1 → 都市2 → 都市0 …」の順に進むなら、対応する場所を 1 にします。

1番目2番目3番目
都市0001
都市1100
都市2010

このように表現するとき、絶対に守らなければならない 2つの制約(One-hot制約) があります。

  1. 縦の制約: 「ある順番(例:1番目)に行ける都市は1つだけ
    • 縦に足し算して合計が1になればOK。
  2. 横の制約: 「ある都市(例:都市0)に行く回数は1回だけ
    • 横に足し算して合計が1になればOK。

📐 数式でルールを書く(QUBOの定式化)

Section titled “📐 数式でルールを書く(QUBOの定式化)”

表(ビット)の用意ができたら、次は「距離を短くしたい」「制約を守りたい」というルールを数式にします。

巡回セールスマン問題の定式化

Section titled “巡回セールスマン問題の定式化”

まず、巡回セールスマン問題を定式化していきます。 今回は距離を最小化するので目的関数は以下のようになります。

H距離=t=03i=03j=03dijxi,txj,t+1\begin{align*} H_{\text{距離}} = \sum_{t=0}^{3} \sum_{i=0}^{3} \sum_{j=0}^{3} d_{ij} x_{i,t} x_{j,t+1} \end{align*}

次に最適化する上での制約を示します。 今回は縦方向と横方向でそれぞれ選ぶ方向を1つにする制約です。制約式としては同じ構造のため、縦方向の制約のみ示します。

Pt=03i=03xi,t=1\begin{align*} P \sum_{t=0}^{3} \sum_{i=0}^{3} x_{i,t} = 1 \end{align*}

これが QUBO の中身であり、これから書くPythonコードの設計図になります。

ハミルトニアンは、以下の2つの足し算でできています。

H=H距離+H制約H = H_{\text{距離}} + H_{\text{制約}}

「隣り合う都市間の距離を足し合わせる」という式です。 「時刻 tt に都市 ii にいて、時刻 t+1t+1 に都市 jj にいる場合(つまり xi,tx_{i,t}xj,t+1x_{j,t+1} が共に 1 の時)」だけ、その距離 dijd_{ij} を足します。

H距離=t=03i=03j=03dijxi,txj,t+1\begin{align*} H_{\text{距離}} = \sum_{t=0}^{3} \sum_{i=0}^{3} \sum_{j=0}^{3} d_{ij} x_{i,t} x_{j,t+1} \end{align*}

この式が最小になる=総距離が最小になる、ということです。

2. 制約のルール(ペナルティ関数)

Section titled “2. 制約のルール(ペナルティ関数)”

ここが量子アニーリングの面白いところです。 「ルールを破ったら罰点(エネルギー)を増やす」という方法で、マシンにルールを教えます。これを ペナルティ法 と呼びます。 また、QUBOは2時である必要があります。

今回は「合計が必ず1になる」という制約なので、「(縦方向の合計 - 1) の2乗」 というテクニックを使います。横方向でも同様です。

  • 合計が 1 のとき: (11)2=0(1 - 1)^2 = 0 (ペナルティなし 👍)
  • 合計が 0 のとき: (01)2=1(0 - 1)^2 = 1 (ペナルティ発生 ⚠️)
  • 合計が 2 のとき: (21)2=1(2 - 1)^2 = 1 (ペナルティ発生 ⚠️)

これを「縦」と「横」の両方に適用します。

H制約=Pt=03(i=03xi,t1)2+Pi=03(t=03xi,t1)2\begin{align*} H_{\text{制約}} = P \sum_{t=0}^{3} \left( \sum_{i=0}^{3} x_{i,t} - 1 \right)^2 + P \sum_{i=0}^{3} \left( \sum_{t=0}^{3} x_{i,t} - 1 \right)^2 \end{align*}

PP は「ペナルティの重さ」です。この値を距離よりも十分大きく設定することで、マシンは「距離を短くするよりも、まずはルールを守ること(ペナルティを0にすること)」を最優先するようになります。

これをPythonで記述し、D-Waveの実機(QPU)で1000回実験してみましょう。

# 必要なライブラリ:
# pip install dwave-ocean-sdk numpy
import numpy as np
from dwave.system.samplers import DWaveSampler
from dwave.system.composites import EmbeddingComposite
# ==========================================
# 1. データの準備
# ==========================================
distance_matrix = np.array([
[0, 10, 20, 15],
[10, 0, 15, 30],
[20, 15, 0, 10],
[15, 30, 10, 0]
])
num_cities = 4
num_vars = 16 # 4x4
penalty_strength = 50.0
# ==========================================
# 2. QUBO行列の作成 (NumPyで直書き)
# ==========================================
Q_mat = np.zeros((num_vars, num_vars))
# --- 目的関数 (総距離) ---
for t in range(num_cities):
next_t = (t + 1) % num_cities # 次の時刻(最後は0に戻る)
for c1 in range(num_cities):
for c2 in range(num_cities):
if c1 != c2:
d = distance_matrix[c1][c2]
# インデックス計算
u = c1 * num_cities + t
v = c2 * num_cities + next_t
# ★重要: ここだけは u > v になる可能性があるので
# 小さい方を行(i)、大きい方を列(j)にして上三角に統一する
i, j = min(u, v), max(u, v)
Q_mat[i][j] += d
# --- 縦の制約 ---
# 「ある順番(t)には、1つの都市しか選べない」
for t in range(num_cities):
for c1 in range(num_cities):
# インデックス計算: 行番号 * 列数 + 列番号
idx1 = c1 * num_cities + t
# 対角成分: -P
Q_mat[idx1][idx1] -= penalty_strength
for c2 in range(c1 + 1, num_cities):
idx2 = c2 * num_cities + t
# 非対角成分: +2P
# ループの構造上、必ず idx1 < idx2 になるためそのまま代入
Q_mat[idx1][idx2] += 2 * penalty_strength
# --- 横の制約 ---
# 「ある都市(c)は、1回しか訪問できない」
for c in range(num_cities):
for t1 in range(num_cities):
idx1 = c * num_cities + t1
# 対角成分: -P
Q_mat[idx1][idx1] -= penalty_strength
for t2 in range(t1 + 1, num_cities):
idx2 = c * num_cities + t2
# 非対角成分: +2P
# ここもループ構造上 idx1 < idx2 なのでそのまま代入
Q_mat[idx1][idx2] += 2 * penalty_strength
# ==========================================
# 3. 辞書へ変換 & 実行
# ==========================================
# 行列(np.array) から D-Wave用の 辞書(dict) へ変換
# 0でない要素だけを取り出す
Q_dict = {
(i, j): Q_mat[i][j]
for i in range(num_vars)
for j in range(i, num_vars)
if Q_mat[i][j] != 0
}
# --- 実行設定 ---
token = 'xxxx' # ここはご自身のD-Wave APIトークンに置き換えてください
sampler = EmbeddingComposite(DWaveSampler(token=token))
print("量子アニーリングを実行中...")
sampleset = sampler.sample_qubo(Q_dict, num_reads=1000)
best_sample = sampleset.first.sample
# ==========================================
# 4. 結果表示
# ==========================================
print("\n--- 結果解析 ---")
active_vars = [k for k, v in best_sample.items() if v == 1]
# ルート復元
route = [-1] * num_cities
for idx in active_vars:
route[idx % num_cities] = idx // num_cities
# 結果チェック
if -1 not in route and len(set(route)) == num_cities:
print("制約OK! 最適ルート:", route)
total_dist = 0
for i in range(num_cities):
u, v = route[i], route[(i+1)%num_cities]
dist = distance_matrix[u][v]
total_dist += dist
print(f"{u} -> {v}: {dist}km")
print(f"総距離: {total_dist} km")
else:
print("制約違反あり。パラメータ調整が必要です。")

このコードを実行すると、16個の量子ビットが相互に作用し合い、ルール(制約)を守りつつ、最も距離が短いルートをマシンが導き出してくれます。

出力例:

量子プロセッサでアニーリングを実行中...
--- 結果解析 ---
制約OK! 最適ルート: [2, 3, 0, 1]
2 -> 3: 10km
3 -> 0: 15km
0 -> 1: 10km
1 -> 2: 15km
総距離: 50 km

※確率的な手法のため、実行するたびにルートの始点が異なる場合がありますが、総距離が最短であることは変わりません。


次世代の計算機は、もう手の中に!

Section titled “次世代の計算機は、もう手の中に!”

この記事を通して、量子アニーリングの正体が見えてきたでしょうか?

最後に、重要なポイントを3つだけ持ち帰ってください。

  1. QAは「計算」ではなく「自然現象」を使う。 コンピュータが必死に計算して山を登るのではなく、量子の力(トンネル効果)で壁をすり抜けて、自然と一番良い答え(谷底)に落ち着くのを待つ技術です。

  2. プログラミングは「地図作り」。 難しい命令を書く必要はありません。私たちがやるべきことは、「ここは相性がいい(谷)」「ここはダメ(山)」という 「地図(ルール)」を作ることだけ。あとは自然法則が勝手に答えを出してくれます。

  3. 「未来の話」ではなく「今日使える技術」。 かつて、大規模な最適化問題を解くには巨大な計算資源が必要でした。 しかし今は、たった数行のPythonコードで、この量子アニーリングの力をあなたのPCから呼び出せる時代です。

もし日常や仕事の中で「これ、組み合わせが多すぎて決められない!」という壁にぶつかったら。 その時こそ、量子アニーリングの出番かもしれません!


この記事のコードや解説は、以下の公式ドキュメントおよび研究を参考にしています。

  • Kadowaki, T., & Nishimori, H. (1998). “Quantum annealing in the transverse Ising model”
    • Phys. Rev. E, 58(5), 5355.
    • 量子アニーリングの概念を世界で初めて提唱した論文です。
  • J. Lucas (2014). “Ising formulations of many NP problems”
    • Frontiers in Physics, 2, 5.
    • TSPを含む様々な問題をどうやって定式化するかをまとめた論文です。