応用型の巡回セールスマン問題を最適化して解く!
- Naoaki Mochida
- 2月8日
- 読了時間: 5分
本記事では、量子コンピュータを活用して巡回セールスマン問題(TSP)を最適化する方法を解説します。具体的には、QUBO(Quadratic Unconstrained Binary Optimization)を用いた定式化を行い、最適な訪問順序を求めます。
1. 問題設定

巡回セールスマン問題(TSP)とは、複数の都市を一度ずつ訪問し、最短距離で巡回する順序を求める最適化問題です。本記事では、以下のルールに基づき問題を解きます。
4つの都市(A, B, C, D)を訪問する順序を最適化
各都市は1回ずつ訪問
移動距離の合計を最小化
Aを出発点とし、初めに入っている15km分のガソリンを切らさないように補充しながら、すべての都市に行く。
都市間の距離は以下のように設定します。

2. 定式化
QUBOを用いた定式化を行い、制約条件とコスト関数を構築します。
制約条件:
Aが出発点。
A, B, C, Dは1回ずつ通る。
n番目に通る都市は1つ。
Cは2地点以内に通る。(補充が必要なため)
コスト条件:
なるべく短い距離で行きたい。
なるべくガソリンを使わない。
問題の考え方
制約条件
(1) Aを出発点とする。
Hconst = 0
Hconst += (q[0][0] - 1)**2
(2) 各都市は1回ずつ訪れる。
Hconst += (q[0][1] + q[1][1] + q[2][1] + q[3][1] - 1)**2
Hconst += (q[0][2] + q[1][2] + q[2][2] + q[3][2] - 1)**2
Hconst += (q[0][3] + q[1][3] + q[2][3] + q[3][3] - 1)**2
(3) 各訪問順序において1都市のみ訪れる。
Hconst += (q[0][0] + q[0][1] + q[0][2] + q[0][3] - 1)**2
Hconst += (q[1][0] + q[1][1] + q[1][2] + q[1][3] - 1)**2
Hconst += (q[2][0] + q[2][1] + q[2][2] + q[2][3] - 1)**2
Hconst += (q[3][0] + q[3][1] + q[3][2] + q[3][3] - 1)**2
(4) Cは2地点以内に訪れる(補充が必要なため)。
Hconst += (q[1][2] + q[2][2] - 1)**2
コスト関数(なるべく少ないガソリンで達成したい)
(1) なるべく短い距離で達成したい。
Hcost = 0
Hcost += 8 * (q[0][0]*q[1][1])
Hcost += 14 * (q[0][0]*q[1][2])
Hcost += 13 * (q[0][0]*q[1][3])
...
(2) なるべく15kmを超えないように行きたい。
Hcost += (8 * q[1][1] + 8 * q[2][0] - 15)**2
Hcost += (8 * q[1][1] + 7 * q[2][2] - 15)**2
Hcost += (8 * q[1][1] + 9 * q[2][3] - 15)**2
Hcost += (14 * q[1][2] + 14 * q[2][0] - 15)**2
Hcost += (14 * q[1][2] + 7 * q[2][1] - 15)**2
Hcost += (14 * q[1][2] + 10 * q[2][3] - 15)**2
Hcost += (8 * q[2][1] + 8 * q[3][0] - 15)**2
Hcost += (8 * q[2][1] + 8 * q[3][2] - 15)**2
Hcost += (8 * q[2][1] + 9 * q[3][3] - 15)**2
Hcost += (14 * q[2][2] + 14 * q[3][0] - 15)**2
Hcost += (14 * q[2][2] + 7 * q[3][1] - 15)**2
Hcost += (14 * q[2][2] + 10 * q[3][3] - 15)**2
ハミルトニアンの構築
H = Hconst + 0.0001 * Hcost
全体のコード
from tytan import *
# 量子ビットの用意
q = symbols_list([4, 4], 'q{}_{}')
# 制約条件1(Aが出発点)
Hconst = 0
Hconst += (q[0][0] - 1)**2
# 制約条件2(A. B, C, Dは1地点ずつ通る)
Hconst += (q[0][1] + q[1][1] + q[2][1] + q[3][1] - 1)**2
Hconst += (q[0][2] + q[1][2] + q[2][2] + q[3][2] - 1)**2
Hconst += (q[0][3] + q[1][3] + q[2][3] + q[3][3] - 1)**2
#制約条件3(n番目に通る都市は1つ)
Hconst += (q[0][0] + q[0][1] + q[0][2] + q[0][3] - 1)**2
Hconst += (q[1][0] + q[1][1] + q[1][2] + q[1][3] - 1)**2
Hconst += (q[2][0] + q[2][1] + q[2][2] + q[2][3] - 1)**2
Hconst += (q[3][0] + q[3][1] + q[3][2] + q[3][3] - 1)**2
#制約条件4(Cは2地点以内に通る。A→B→CまたはA→C)
Hconst += (q[1][2] + q[2][2] - 1)**2
#コスト条件1(なるべく短い距離で行きたい)
Hcost = 0
Hcost += 0 * (q[0][0]*q[1][0])
Hcost += 8 * (q[0][0]*q[1][1])
Hcost += 14 * (q[0][0]*q[1][2])
Hcost += 13 * (q[0][0]*q[1][3])
Hcost += 8 * (q[0][1]*q[1][0])
Hcost += 0 * (q[0][1]*q[1][1])
Hcost += 7 * (q[0][1]*q[1][2])
Hcost += 9 * (q[0][1]*q[1][3])
Hcost += 14 * (q[0][2]*q[1][0])
Hcost += 7 * (q[0][2]*q[1][1])
Hcost += 0 * (q[0][2]*q[1][2])
Hcost += 10 * (q[0][2]*q[1][3])
Hcost += 13 * (q[0][3]*q[1][0])
Hcost += 9 * (q[0][3]*q[1][1])
Hcost += 10 * (q[0][3]*q[1][2])
Hcost += 0 * (q[0][3]*q[1][3])
Hcost += 0 * (q[1][0]*q[2][0])
Hcost += 8 * (q[1][0]*q[2][1])
Hcost += 14 * (q[1][0]*q[2][2])
Hcost += 13 * (q[1][0]*q[2][3])
Hcost += 8 * (q[1][1]*q[2][0])
Hcost += 0 * (q[1][1]*q[2][1])
Hcost += 7 * (q[1][1]*q[2][2])
Hcost += 9 * (q[1][1]*q[2][3])
Hcost += 14 * (q[1][2]*q[2][0])
Hcost += 7 * (q[1][2]*q[2][1])
Hcost += 0 * (q[1][2]*q[2][2])
Hcost += 10 * (q[1][2]*q[2][3])
Hcost += 13 * (q[1][3]*q[2][0])
Hcost += 9 * (q[1][3]*q[2][1])
Hcost += 10 * (q[1][3]*q[2][2])
Hcost += 0 * (q[1][3]*q[2][3])
Hcost += 0 * (q[2][0]*q[3][0])
Hcost += 8 * (q[2][0]*q[3][1])
Hcost += 14 * (q[2][0]*q[3][2])
Hcost += 13 * (q[2][0]*q[3][3])
Hcost += 8 * (q[2][1]*q[3][0])
Hcost += 0 * (q[2][1]*q[3][1])
Hcost += 7 * (q[2][1]*q[3][2])
Hcost += 9 * (q[2][1]*q[3][3])
Hcost += 14 * (q[2][2]*q[3][0])
Hcost += 7 * (q[2][2]*q[3][1])
Hcost += 0 * (q[2][2]*q[3][2])
Hcost += 10 * (q[2][2]*q[3][3])
Hcost += 13 * (q[2][3]*q[3][0])
Hcost += 9 * (q[2][3]*q[3][1])
Hcost += 10 * (q[2][3]*q[3][2])
Hcost += 0 * (q[2][3]*q[3][3])
Hcost += (8 * q[1][1] + 8 * q[2][0] - 15)**2
Hcost += (8 * q[1][1] + 7 * q[2][2] - 15)**2
Hcost += (8 * q[1][1] + 9 * q[2][3] - 15)**2
Hcost += (14 * q[1][2] + 14 * q[2][0] - 15)**2
Hcost += (14 * q[1][2] + 7 * q[2][1] - 15)**2
Hcost += (14 * q[1][2] + 10 * q[2][3] - 15)**2
Hcost += (8 * q[2][1] + 8 * q[3][0] - 15)**2
Hcost += (8 * q[2][1] + 8 * q[3][2] - 15)**2
Hcost += (8 * q[2][1] + 9 * q[3][3] - 15)**2
Hcost += (14 * q[2][2] + 14 * q[3][0] - 15)**2
Hcost += (14 * q[2][2] + 7 * q[3][1] - 15)**2
Hcost += (14 * q[2][2] + 10 * q[3][3] - 15)**2
H = Hconst + 0.0001*Hcost
# コンパイル・サンプリング
qubo, offset = Compile(H).get_qubo() # コンパイル
print(f'offset\n{offset}')
solver = sampler.SASampler() # サンプラー選択
result = solver.run(qubo, shots=100) # サンプリング
# 結果表示
for r in result[:5]:
print(f'Energy {r[1]}, Occurrence {r[2]}')
#配列に
arr, subs = Auto_array(r[0]).get_ndarray('q{}_{}')
print(arr)
5. 結果
以下のように最適な訪問順序は A → B → C → D であることが分かります。
offset
9.27
Energy -9.138, Occurrence 15
[[1 0 0 0]
[0 0 1 0]
[0 1 0 0]
[0 0 0 1]]
Energy -9.133299999999998, Occurrence 33
[[1 0 0 0]
[0 1 0 0]
[0 0 1 0]
[0 0 0 1]]
Energy -9.0909, Occurrence 9
[[1 0 0 0]
[0 0 1 0]
[0 0 0 1]
[0 1 0 0]]
Energy -9.076799999999999, Occurrence 19
[[1 0 0 0]
[0 0 0 1]
[0 0 1 0]
[0 1 0 0]]
Energy -8.1511, Occurrence 1
[[1 0 0 0]
[0 1 1 0]
[0 0 0 1]
[1 0 0 0]]
6. まとめ
本記事では、QUBOを用いた発展した巡回セールスマン問題の最適化を量子アニーリングを実施しました。QUBOの定式化によって制約条件を考慮しつつ、最適な経路を求めることが可能となります。
今後は、より多くの都市や追加の制約条件を考慮した拡張問題やHOBOで解いていきます。
お楽しみに!
Comments