4/15(火)~17(木) 第5回量子コンピューティングEXPO春(東京ビッグサイト)に共同出展します☆彡
量子アニーリング

New!! 量子アニーリング(QUBO)でプラレールを衝突回避させてみた②

AI要約

レールごとの長さを反映した上で、より大きなコースでQUBOアニーリングによる衝突回避の最適化に再挑戦しました。コース全体の物理的な距離を正確に扱うことで、より現実的な制御シミュレーションが可能になりました。

やること

前回、QUBOアニーリングで3台の衝突回避の最適化に挑戦しました。

これまでレールの長さはすべて同じにしていましたが、実際には直線レールが21.4cm、カーブレールが16.8cmのようです。今回はレールの長さの違いを反映させつつ、コースを拡張して4台の電車を衝突しないように走らせてみましょう。ここまでできれば実物のデモンストレーションは目の前です。

コースの拡張

前回までのコースを拡張しました。

IDも増えています。

パスと分岐も拡張しました。

#パスの定義
path = {0:1, 1:2, 2:3, 3:4, 4:5, 5:6, 6:7, 7:[8, 14], 8:[9, 20], 9:[22, 10], 10:11, 11:12, 12:13, 13:0,
        14:15, 15:16, 16:17, 17:[28, 18], 18:19, 19:6, 20:21, 21:13,
        22:23, 23:24, 24:25, 25:26, 26:27, 27:16, 28:29, 29:30, 30:5}

#分岐の状態
switch = {7:0, 8:0, 9:0, 17:0}

#線路の座標、可視化のため
xy_set = {0:[30, 0], 1:[20, 0], 2:[10, 0], 3:[5, 7], 4:[5, 13], 5:[10, 20], 6:[20, 20], 7:[30, 20],
          8:[40, 20], 9:[50, 20], 10:[55, 13], 11:[55, 7], 12:[50, 0], 13:[40, 0], 14:[35, 27],
          15:[35, 33], 16:[30, 40], 17:[20, 40], 18:[15, 33], 19:[15, 27], 20:[45, 13], 21:[45, 7],
          22:[60, 20], 23:[65, 27], 24:[65, 33], 25:[60, 40], 26:[50, 40], 27:[40, 40],
          28:[10, 40], 29:[5, 33], 30:[5, 27]}

さて、この後のために追加で2つ定義します。

#パスの長さ、単一長さのレールのみ
length = {0:21.4, 1:21.4, 26:21.4, 27:21.4,
          2:16.8, 3:16.8, 4:16.8, 5:16.8, 10:16.8, 11:16.8, 12:16.8, 14:16.8, 15:16.8, 18:16.8,
          19:16.8, 20:16.8, 21:16.8, 22:16.8, 23:16.8, 24:16.8, 25:16.8, 28:16.8, 29:16.8, 30:16.8}

#合流レール
join = {6:{5:21.4, 19:16.8}, 13:{12:21.4, 21:16.8}, 16:{27:21.4, 15:16.8}}

「length」はレールの長さ [cm] です。ただし、ターンアウトレールの長さは別で処理するのでここには含めていません。

「join」はターンアウトレールのうち合流となるレールで、どこから来たらどんな長さにするかを書き込みます。

なぜこんなにややこしいことをしているかというと・・・。分岐レールは分岐の状態によって長さが変わります。また、合流レールはどこから来たかによって長さが変わります。これを電車クラスの中でうまく反映させるのに頭を使いました。。

電車クラスの修正

クラス内で「self.len」(現在乗っているレールの長さ)を持つようにします。前回までは進行率が1.0を超えたら次のレールに遷移でしたが、修正後は進行長さがレール長(21.4や16.8)を超えたら遷移とします。よってスピードの意味も「1フレームあたり増やす進行率」から「1フレームあたり進む長さ」に変わっています。

#電車のクラス
class TrainClass:
    def __init__(self, name='a', speed=0.2, pos=0, color='yellow'):
        self.name = name
        self.speed = speed
        self.pos = pos
        self.color = color
        
        #レール長
        self.len = length[pos]
        
        #進行長さ
        self.progress = 0.0
    
    #1フレーム進める
    def move(self):
        
        #分岐にいる場合、ここでレール長を変更
        if self.pos in switch.keys():
            s = switch[self.pos]
            if s == 0:
                self.len = 21.4
            else:
                self.len = 16.8
        
        #進行長さを加算
        self.progress += self.speed
        
        #次のレールに移った場合
        if self.progress >= self.len:
            self.progress = self.progress - self.len
            #分岐からの遷移なら
            if self.pos in switch.keys():
                s = switch[self.pos]
                next_pos = path[self.pos][s]
            #そうでないなら
            else:
                next_pos = path[self.pos]
            
            #合流レールに遷移する場合、ここでレール長を変更
            if next_pos in join.keys():
                self.len = join[next_pos][self.pos]
            
            #更新
            self.pos = next_pos
            
        #まだこのレールにいる場合
        else:
            pass

move() の開始時に「分岐レールにいる場合は分岐状態によって(この分岐レールの)長さを設定」を差し込み、レール遷移前に「合流レールに行く場合は現在のレールによって(行き先の合流レールの)長さを設定」を差し込んでいます。

合ってるんかいなこれ?

電車を4台に増やして単純シミュレーションしてみましょう。初期位置はターンアウトレールにしないように注意。

#電車の作成
trains = []
trains.append(TrainClass(name='a', speed=0.17*20, pos=0, color='yellow'))
trains.append(TrainClass(name='b', speed=0.23*20, pos=4, color='orange'))
trains.append(TrainClass(name='c', speed=0.41*20, pos=19, color='green'))
trains.append(TrainClass(name='d', speed=0.37*20, pos=22, color='gray'))

レールの長さが反映されているか分からないですが、できていると信じましょう。

アニーリングで衝突回避

では、QUBOアニーリングで500フレームまで進めてみましょう。

最後まで衝突しませんでした!いやこれすごい。永久に行ける感じです。

ちなみに5台に増やしてみると、

trains.append(TrainClass(name='e', speed=0.29*20, pos=26, color='cyan'))

粘っていますが惜しくも238フレーム目で衝突しました。でもかなり頑張ってますよね!?

おわりに

シミュレーションは一旦ここまでにしましょう。実物のデモンストレーションにも挑戦しますので乞うご期待!

リアクションのお願い

「参考になった!」「刺激された!」と思ったらぜひリアクションをしましょう。エンジニアの世界はGive and Takeによって成り立っています。これからも無料で良質な情報にアクセスできるよう、Giveする人への感謝をリアクションで示しましょう!

この記事をシェアする

自身のブログ等で使用する場合は引用を忘れずに!

また、寄付も受け付けています。コーヒー1杯でとても喜びます(*˘︶˘*)

 Amazonでギフト券(アマギフ)を贈る

こちらのリンク から金額を指定してお贈りください。(デフォルトで10000円になっているのでご変更ください)

配送:Eメール
受取人:staffあっとvigne-cla.com
贈り主:あなたのお名前やニックネーム
メッセージ:◯◯の記事が参考になりました。など

のようにご入力ください。見返りはありませんのでご了承ください。

 Amazonで食事券(すかいらーく優待券)を贈る

500円 1000円 2000円 5000円 からお贈りください。

配送:Eメール
受取人:staffあっとvigne-cla.com
贈り主:あなたのお名前やニックネーム
メッセージ:◯◯の記事が参考になりました。など

のようにご入力ください。見返りはありませんのでご了承ください。

 その他、ギフト券やクーポン券をメールで贈る

デジタルのギフト券/クーポン券はメールアドレス(staffあっとvigne-cla.com)までお送りください。受領の返信をいたします。
紙のギフト券/クーポン券は 「郵便物はこちらへ」の住所 まで送付してください。名刺やメールアドレスを同封していただければ受領の連絡をいたします。
余った株主優待券等の処理におすすめです。
いずれも見返りはありませんのでご了承ください。

不明点はSNSでお気軽にご連絡ください

ビネクラのTwitter・Youtubeでコメントをください!


Slack・Discordの場合はこちらの公開グループに参加してShoya YasudaまでDMをください!


※当ブログに関することは何でもご相談・ご依頼可能です。

この記事を書いた人
Yasuda

博士(理学)。専門は免疫細胞、数理モデル、シミュレーション。米国、中国で研究に携わった。遺伝的アルゴリズム信者。物価上昇のため半額弁当とともに絶滅寸前。

タイトルとURLをコピーしました