Slide 1

Slide 1 text

Toyota Programming Contest 2023 Summer Final Transit Warehouse 解説 TOYOTA AHC 至高のアルゴリズム解説会 松尾 充 (@terry_u16)

Slide 2

Slide 2 text

松尾 充 株式会社ALGO ARTIS まつお あたる (世界5位) 2196 アルゴリズム ヒューリスティック 最高 3028 @terry_u16 terry_u16 1992年 福岡県生まれ 九州大学に入学して機械工学を勉強 九州大学大学院の修士課程に進学 2010年 2014年 株式会社IHIに入社し戦闘機用ジェットエンジンを開発 うっかり競技プログラミングにハマってしまう 株式会社ALGO ARTISに入社 2016年 2020年 2022年

Slide 3

Slide 3 text

問題説明

Slide 4

Slide 4 text

Transit Warehouse 問題文(要約) 𝐷 × 𝐷 マスの倉庫があります。この倉庫に 𝑀 個の コンテナが運び込まれ、その後運び出されます。 運び込みと運び出しは、入口から空きマスを経由 して到達可能なマスにしか行えません。 各コンテナには番号が振られていますが、 運び込まれる順番は不明です。 できるだけ番号の昇順で運び出せるような 運び込み・運び出しの操作列を求めてください。 出典: Transit Warehouse ( https://atcoder.jp/contests/toyota2023summer-final/tasks/toyota2023summer_final_a )

Slide 5

Slide 5 text

ビジュアライザ 運び込みパート 運び出しパート 運び込み + 運び出し

Slide 6

Slide 6 text

解説

Slide 7

Slide 7 text

本番1位を超えるために Q. 本番1位を超えるためにやっておくとよいことは? A. 本番1位を取っておくとよいです。

Slide 8

Slide 8 text

本番1位を超えるために 乱数シードを変更して提出し直すと、1位のスコアを超えることができます。

Slide 9

Slide 9 text

完 TOYOTA AHC 至高のアルゴリズム解説会

Slide 10

Slide 10 text

……ではなくて、 今回のための新しい解法を用意してきました。

Slide 11

Slide 11 text

コード提出 早速ですが、 今回書いたコードを この場で初提出してみます! 何点取れるかお楽しみに! 同僚にやれと言われたので……

Slide 12

Slide 12 text

本番解法の解説

Slide 13

Slide 13 text

解法の概要 運び込みパート 運び出しパート 運び込み順がランダムなので、 ランダムシミュレーションを行い 得点の期待値を求める。 シミュレーション中は いい感じの貪欲を行う。 モンテカルロ法 + 貪欲プレイアウト なるべく小さい番号のコンテナを 運び出す貪欲を行う。 この貪欲を焼きなましで さらに改善する。 貪欲法 + 焼きなましで改善

Slide 14

Slide 14 text

運び込みパート 運び込みパート 運び出しパート 運び込み順がランダムなので、 ランダムシミュレーションを行い 得点の期待値を求める。 シミュレーション中は いい感じの貪欲を行う。 モンテカルロ法 + 貪欲プレイアウト なるべく小さい番号のコンテナを 運び出す貪欲を行う。 この貪欲を焼きなましで さらに改善する。 貪欲法 + 焼きなましで改善

Slide 15

Slide 15 text

運び込みパート概要 モンテカルロ法 + 貪欲プレイアウトでコンテナを置いていく。 1. コンテナを置いても空きマスが連結となるマス (非関節点)を列挙する。 関節点はLowLinkで 𝑂 𝐷2 で列挙可能。 2. 各マスをある評価関数で評価し、 評価値の高いマスをいくつかピックアップする。 3. 各候補マスに置いたときのスコアの期待値を 貪欲プレイアウトにより求め、 最も期待値の高いマスを選ぶ。

Slide 16

Slide 16 text

評価関数 質の高いプレイアウトを行うため、賢い貪欲が非常に重要。 2 1 1 3 2 1 5 4 3 2 3 4 5 3 4 5 6 5 4 5 6 コンテナ 𝒌 𝑫𝒌 0~2 1 3~5 2 6~9 3 10~13 4 14~18 5 19~20 6 お気持ち IDの小さいコンテナは入口の近くに、 IDの大きいコンテナは入口から遠くに置きたい。 IDの大きいコンテナを入口の近くに置くのは特に避けたい。 BFSを行い、コンテナIDごとに置きたい距離 𝑫𝒌 を決める。 入口からの距離 𝑑𝑖,𝑗 のマス 𝑖, 𝑗 の評価値 𝑓 𝑖, 𝑗, 𝑘 は以下。 𝑓 𝑖, 𝑗, 𝑘 = ൝ 4 𝑫𝒌 − 𝑑𝑖,𝑗 𝑑𝑖,𝑗 < 𝑫𝒌 𝑑𝑖,𝑗 − 𝑫𝒌 𝑫𝒌 ≤ 𝑑𝑖,𝑗

Slide 17

Slide 17 text

運び出しパート 運び込みパート 運び出しパート 運び込み順がランダムなので、 ランダムシミュレーションを行い 得点の期待値を求める。 シミュレーション中は いい感じの貪欲を行う。 モンテカルロ法 + 貪欲プレイアウト なるべく小さい番号のコンテナを 運び出す貪欲を行う。 この貪欲を焼きなましで さらに改善する。 貪欲法 + 焼きなましで改善

Slide 18

Slide 18 text

運び出しパート概要 基本的に貪欲法でコンテナを運び出していく。 1. 入口から到達可能なコンテナをDFSで列挙する。 2. 列挙したコンテナのうち、 最もIDの小さいものを運び出す。 以上!

Slide 19

Slide 19 text

焼きなましによる改善 この貪欲法を焼きなましで改善する。 各コンテナについて優先度という概念を考え、 これを用いて以下の貪欲を行う。 1. 入口から到達可能なコンテナを列挙する。 2. 列挙したコンテナのうち、 最も優先度の高いものを運び出す。 この貪欲によるスコアが大きくなるように 焼きなましで優先度を決める。 5 6 12 34 18 8

Slide 20

Slide 20 text

本番の提出 ここまで実装したものが本番1位解法(2960億点)。

Slide 21

Slide 21 text

延長戦順位表 ……なのですが、その後色々な人が延長戦に参加して魔境に……。

Slide 22

Slide 22 text

解法のブラッシュアップ

Slide 23

Slide 23 text

高速化 解法のブラッシュアップ 1/3

Slide 24

Slide 24 text

高速化 モンテカルロ法はプレイアウト回数が命。 プレイアウト結果のばらつきは、試行回数を 𝑵 として 𝟏/ 𝑵 に比例する(はず) 。 高速化を頑張ることで、より精度高く期待値を求められるようになる。 𝑁 = 10 𝑁 = 40 𝑁 = 160 𝑁 = 640 標準偏差 0.55 標準偏差 0.28 標準偏差 0.14 標準偏差 0.07 「サイコロの出る目の期待値を試行回数 𝑁 回のプレイアウトで求めた結果」のばらつき

Slide 25

Slide 25 text

運び出し時の計算量改善 入口から到達可能なコンテナの列挙の計算量を改善する。 Before 入口からDFSを行い、愚直にコンテナを列挙する。 計算量は 𝑶 𝑫𝟐 。 After 運び出したコンテナの周囲だけ差分更新する。 最小のIDのコンテナは優先度付きキューで求める(Prim法と同じ)。 計算量は 𝑶 𝐥𝐨𝐠 𝑫 。

Slide 26

Slide 26 text

運び出し時の計算量改善 Q. 何で本番中にやらなかったんですか? A. 何ででしょうね……。 コンテスト序盤に思い付いてはいて、 どうせLowLinkに 𝑂 𝐷2 かかるし、まずは愚直に実装して後で改善しようと思っていたのですが、 いつの間にか忘れていました……。

Slide 27

Slide 27 text

その他の高速化 その他にも諸々の高速化を実施。 • 優先度付きキューの代わりにbit演算を使う • グリッドグラフの隣接4マスを前計算で求めておく • ひたすら動的メモリ確保を避ける • 関数のインライン化 などなど…… プレイアウト数 毎ターン 約 250 回 約 1000 回 →

Slide 28

Slide 28 text

プレイアウトの効率化 解法のブラッシュアップ 2/3

Slide 29

Slide 29 text

プレイアウトの効率化 プレイアウトを行う際、各候補について同じ計算コストを払うのは無駄。 見込みのない候補は早めに捨てて、有望な候補のプレイアウト回数を稼ぎたい。 候補名 計算時間 確定 候補A 候補B ★ 候補C 候補D 100回 100回 100回 100回

Slide 30

Slide 30 text

プレイアウトの効率化 Successive Halving という手法を用いて枝刈りする。 • 一定時間ごとに解を半分に絞り込む手法 (下図では4個→2個→1個) • 機械学習におけるハイパーパラメータ最適化でよく用いられる 候補名 計算時間 確定 候補A 候補B ★ 候補C 候補D 100回 50回 100回 50回 50回 50回

Slide 31

Slide 31 text

貪欲の改善 解法のブラッシュアップ 3/3

Slide 32

Slide 32 text

貪欲の改善 運び込み時の貪欲をより賢くすればスコアが上がるはず。 以下の概念を導入して、貪欲の改善を行う。 空きマスコスト 端の方から詰めて置く 距離マップ 運び出す順番を工夫する ターゲットID 気持ち遠めのマスに置く コストマップ 中央スペースを空けておく

Slide 33

Slide 33 text

空きマスコスト 周囲4マスの空きマス数 𝒆 に対してコスト 𝐶𝐸,𝑒 をかける。 お気持ち: できるだけ端の方から詰めて置いていきたい。 空きマス数 1 空きマス数 2 空きマス数 3 空きマス数 4 コスト小 コスト大

Slide 34

Slide 34 text

ターゲットID コンテナ 𝑘 を距離 𝐷𝑘 ではなく距離 𝑫𝑻𝒌 の場所に置くことを目指す。 お気持ち: 少し遠めのマスに置いていき、近くのマスを空けておきたい。 2 1 1 3 2 1 5 4 3 2 3 4 5 3 4 5 6 5 4 5 6 2 13 2 1 1 3 2 1 5 4 3 2 3 4 5 3 4 5 6 5 4 5 6 2 13 距離の近い順に置いていく 少し遠めの場所に置いていく Before After

Slide 35

Slide 35 text

距離マップ 入口からの距離を 𝑑𝑖,𝑗 ではなく 𝒅𝒊,𝒋 ′ = 𝒅𝒊,𝒋 + 𝑬𝒊,𝒋 と見なして配置する。 お気持ち: 運び出す順番を工夫することでスムーズに運び出したい。 2 1 1 3 2 1 5 4 3 2 3 4 5 3 4 5 6 5 4 5 6 2 1 1 3 3 1 5 4 4 5 4 4 5 6 5 5 6 6 7 6 6 Before After 入口からの距離を素直に使う 見かけ上の距離を変化させる

Slide 36

Slide 36 text

コストマップ マス 𝑖, 𝑗 のコストを 𝑪𝑴,𝒊,𝒋 だけ上乗せする。 お気持ち: 運び込むときに中央スペースは最後まで空けておきたい。 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 4 6 0 1 3 7 3 1 1 6 5 1 0 2 3 2 0 Before After 特に追加コストなし 場所によって追加コストが発生

Slide 37

Slide 37 text

評価関数 最終的な評価関数 𝑓 𝑖, 𝑗, 𝑘 は以下のような形となる。 𝑓 𝑖, 𝑗, 𝑘 = ቐ 𝜶 𝐷𝑻𝒌 − 𝑑𝑖,𝑗 ′ + 𝑪𝑬,𝒆 + 𝑪𝑴,𝒊,𝒋 𝑑𝑖,𝑗 ′ < 𝐷𝑘 𝑑𝑖,𝑗 ′ − 𝐷𝑻𝒌 + 𝑪𝑬,𝒆 + 𝑪𝑴,𝒊,𝒋 𝐷𝑘 ≤ 𝑑𝑖,𝑗 ′ 𝑑𝑖,𝑗 ′ = 𝑑𝑖,𝑗 + 𝑬𝒊,𝒋 距離マップ 空きマスコスト コストマップ ターゲットID ハイパーパラメータ: 𝛼, 𝐶𝐸,𝑒 , 𝐶𝑀,𝑖,𝑗 , 𝑇𝑘 , 𝐸𝑖,𝑗 (250パラメータ程度)

Slide 38

Slide 38 text

ハイパーパラメータチューニング Q. 面倒なパラメータチューニングを自動でやってくれるものといえば? 焼きなまし A.

Slide 39

Slide 39 text

Optunaとかじゃないの? 焼けそうなので焼きました。 もう少し詳しく説明すると、以下の理由から選定しました。 • 貪欲であればスコア計算が軽く、試行回数が十分稼げる • 探索空間が比較的滑らかと思われる • パラメータ数が非常に多くても動作する • 慣れている

Slide 40

Slide 40 text

貪欲Before/After 数時間じっくり焼いた結果、貪欲だけで本番1位を超えるスコアに。 Before: 2,901億点 After: 2,967億点 ※手元300ケースのスコア

Slide 41

Slide 41 text

実装結果

Slide 42

Slide 42 text

seed=0 実行結果 seed=0ではそこそこの確率で満点が取れるようになった。 ※ 満点の確率が高い操作と得点の期待値が高い操作は 必ずしも一致しないことに注意。

Slide 43

Slide 43 text

運 び 出 し 運 び 込 み 最適化結果の考察 焼きなましくんがどのような戦略を編みだしたのか考察してみる。 • マップの外周部分から順に埋めていっている • 細長い通路ができないようにしている • 小さいIDのコンテナ置き場を横に空けている • 両サイドから先に運び出している • 運び込み終盤にどの順番でコンテナが来ても 両サイドのコンテナは既に配置済みのため 安定して運び出しを行うことができている

Slide 44

Slide 44 text

提出結果

Slide 45

Slide 45 text

おわりに

Slide 46

Slide 46 text

謝辞 今回の解法を作るにあたり、以下の方の解法を参考にさせて頂きました。 • eijirouさん: 空きマスコスト・ターゲットID的な考え方 • simanさん: 距離マップ的な考え方

Slide 47

Slide 47 text

おわりに 今回は私の作った解法例をご紹介しましたが、 まだまだ伸ばす余地はあると思われます。 是非とも皆さんもチャレンジして あなただけの至高のアルゴリズムを 作り上げてみてください!

Slide 48

Slide 48 text

ご清聴ありがとうございました!

Slide 49

Slide 49 text

補足スライド

Slide 50

Slide 50 text

パラメータ焼きなましの詳細 • 𝜶, 𝑪𝑬,𝒆 , 𝑪𝑴,𝒊,𝒋 , 𝑻𝒌 , 𝑬𝒊,𝒋 の組を最適化する • 焼きなましの評価関数は 「1000ケースに対して以下の解法で解いたときのスコアの総和」とする • 運び込みパート: 評価関数 𝑓 𝑖, 𝑗, 𝑘 が最小となるマスを選ぶ貪欲 • 運び出しパート: IDが最小のコンテナを運び出す貪欲 • ローカルだと並列計算可能で、焼きなましのループが100万/hくらい回る • 過学習していないか最後に別の1000ケースでバリデーションしておく

Slide 51

Slide 51 text

スコアのヒストグラム 手元1000ケースでの実行結果 満点: 159ケース 平均: 0.9973×109

Slide 52

Slide 52 text

距離マップ・コストマップ

Slide 53

Slide 53 text

この解法の弱点 障害物が多いとパラメータの埋め込みが効かず、スコアが悪化しがち。 seed=265 (972,602,740点)

Slide 54

Slide 54 text

弱点の改善案 障害物マップを入力、距離マップ・コストマップを出力とするCNNを考え、 動的に距離マップ・コストマップを生成させると改善できる? 2 1 1 3 3 1 5 4 4 5 4 4 5 6 5 5 6 6 7 6 6 0 2 2 0 4 6 0 1 3 7 3 1 1 6 5 1 0 2 3 2 0 CNN 距離マップ コストマップ 障害物マップ 力尽きたので誰かやって

Slide 55

Slide 55 text

強化学習 延長戦2位のsaitodevel01さんは強化学習っぽいコード? 軽いCNNで強化学習でプレイアウトしたら強そうと思って試していたのですが 上手く行きませんでした……。誰かやって