AtCoder Heuristic Contest 001

atcoder.jp

f:id:shuu0914:20210314195311p:plain

暫定7位

 アルゴリズムの流れ

  1. 解(=各企業の領域)を初期化する
  2. いくつかの企業の領域を変更する(突然変異)
  3. 全ての企業をある方向に寄せる(引力発生)
    その際、評価値が低い企業は引き伸ばす
    3. は方向を変えて4回繰り返す
  4. 2.3.の操作を近傍とみなして焼き鈍し
  5. 最後に、最良解について、微調整を行う

 

初期化

すべての企業の領域を、その基準点を囲う面積1の正方形とする

 

突然変異

ターゲット指定/範囲指定/ランダム の3種類から1つを行う

採用確率は

序盤から中盤 : 80%/14%/6%

終盤 : 20%/56%/24%

ターゲット指定

  1. 面積がr * max_per_r * 0.95より小さい企業からランダムにターゲット企業を選ぶ
    ※ max_per_r は時間経過につれて大きく
  2. ターゲット企業の新しい端点y1 y2 x1 x2を、
    世界の端(0または10000)と基準点の間からそれぞれ一様ランダムに選ぶ
  3. ターゲット企業の評価値が大きく悪化していたら2からやり直し
  4. 他の企業の基準点を内包していたら2からやり直し
    ※ 累積和でO(1)で判定
  5. ターゲット企業と接触している企業の領域を適切に縮小する
    ※ すべての企業について愚直に確認 O(n)
    ※ y1 y2 x1 x2のうち1つを変更することで縮小

範囲指定

  1. ある大きさの正方形を一様ランダムに配置
    ※ 1辺の長さは時間経過とともに短く
  2. 正方形と接触しているすべての企業の面積を1にする

ランダム

  1. すべての企業について、ある確率に基づいて面積を1にする
    ※ 確率は時間経過とともに小さく

 

引力発生

  1. 引力方向を決める
  2. 評価値を改善するターゲットとして「評価値の低い企業 + ランダムにいくつか」を選択
  3. 基準点が引力方向に近い企業から順に、引力をかける
    ・ターゲット→引力方向に、衝突するギリギリまで引き伸ばす。ただし、面積がr * max_per_r を超えないように調整
    ・非ターゲット→引力方向に、衝突するギリギリ/基準点が飛び出さないギリギリ まで平行移動
    ※ 区間をsetで管理する or 遅延セグ木を使う → 全体でO(nlogn)
    ※ 実際は区間vectorで管理したほうが早かったのでそうした

1~3を方向を変えて4回繰り返します。

 

微調整

  • 企業と企業の境界線を1マスずらしてみて、評価値が改善されるなら採用
  • 引力発生(ただし平行移動のみ)

これらをたくさんやる

 

何をしたら伸びた?

最初期は引力のみ

 

突然変異を導入

← それまでは領域の縮小が無かったので、当然伸びる

 

引力発生の3において max_per_rを導入

← 想像以上に伸びてびっくりした
    スペースに余裕のある企業は後でどうにでもなるので、

    評価値の低い企業にスペースを譲るのが大事?

 

突然変異にターゲット指定を追加

← これも結構伸びた

 

ターゲット指定においてターゲットと接触した企業の対処を、

面積を1にする にしていたが 適切に縮小する に変更

1回の突然変異に対して引力発生を30回行っていたが、

4回に減らしても改善解が発見されるようになった

← 近傍探索を行える回数が増えたので伸びた

 

微調整を導入

← 結構伸びる

    (焼き鈍しフェイズがざっくりしているから というのは要因としてありそう)

 

定数倍高速化は行う度に大きく伸びた

 

山登りと焼き鈍しはあまり変化が無かった気がする...?

 

困ったこと

点数の分散が大きく(同じコードをsubmitしても49599~49624のブレ)、

コードの変更が改良なのか改悪なのか判断できなくて困った。

どうすればいいのでしょうか。

 

次回の長期マラソンではやりたいこと

  • 解が改善されていく様子を確認するためのビジュアライザの作成
  • パラメータチューニング
  • 何をしたら何点伸びたのかメモしておく