Upgrade to Pro — share decks privately, control downloads, hide ads and more …

極小頂点被覆列挙問題を解く

kaityo256
February 01, 2018

 極小頂点被覆列挙問題を解く

逆探索アルゴリズムに基づいて極小頂点被覆(Minimal Hitting Set)を効率的に列挙する方法の紹介。

kaityo256

February 01, 2018
Tweet

More Decks by kaityo256

Other Decks in Programming

Transcript

  1. 3/30 数独と頂点被覆列挙問題 (2/4) 16ヒントの数独で解が一意になるものは存在しない There is no 16-Clue Sudoku [arXiv:1201.0749]

    数独の16ヒント定理 証明方法 ・数独の「答え」は有限個(自明な変換を除いて5,472,730,538個) ・それぞれの答えについて16ヒント問題を作る ・その全てについて解が一意でないことを示す 極小頂点被覆列挙問題 スパコンを使っても16ヒント問題を全て尽くすのは不可能 解が一意になる可能性がある問題を効率的に列挙したい (いわゆる「エレファントな証明」)
  2. 4/30 最小頂点被覆問題(1/3) 学校の開校問題 国語、算数、理科、社会、英語の五教科を教える学校を開校したい 教師候補は以下の五人 教師名 担当可能科目 給料(コスト) Alice 理科

    2 Bob 国語、社会 5 Carol 理科、社会、英語 10 Dave 国語、算数 6 Eve 算数、英語 8 教師候補を何人か雇って、五教科全てを教えられるようにしたい ただし、給料の総和は最小化したい
  3. 6/30 最小頂点被覆問題(3/3) Alice Bob Carol Dave Eve 国語 算数 理科

    社会 英語 Carol + Dave = 16 Bob + Carol + Eve = 23 Alice + Bob + Eve = 15 これが求める答え 極小頂点被覆 これを列挙したい
  4. 7/30 頂点被覆問題のグラフ表現 (1/2) Alice Bob Carol Dave Eve A B

    C D E Bob Carol Dave Eve Alice C A B E D 教師: 頂点(Vertex) 科目: 辺(Edge) グラフに書き直すことができる A: 国語 B: 数学 C: 理科 D: 社会 E: 英語
  5. 8/30 頂点被覆問題のグラフ表現 (2/2) Bob Carol Dave Eve Alice C A

    B E D Bob Carol Dave Eve Alice C A B E D Bob Carol Dave Eve Alice C A B E D 頂点被覆 全ての辺が選ばれた頂点のいずれかに所属するような頂点集合 極小頂点被覆 どの頂点が欠けても頂点被覆でなくなるような頂点集合
  6. 9/30 ヒッティングセット Simple Graph Hyper Graph Vertices Edges Vertices Hyper

    Edges 辺は必ず二点を繋ぐ 三点以上をつなぐ辺が存在 ヒッティングセット グラフにおける頂点被覆問題の拡張
  7. 10/30 頂点被覆列挙のビット表現 (1/3) 00100100 00011000 00010001 00110000 10000010 00000101 00010010

    00100001 00001001 87654321 グラフのビット表現 ≠ Adjacency matrix 各ビット列は辺を表現 その辺につながる頂点のビットが立っている
  8. 11/30 頂点被覆列挙のビット表現 (2/3) 00100100 00011000 00010001 00110000 10000010 00000101 00010010

    00100001 00001001 頂点被覆のビット表現 87654321 00010111 87654321 00010111 頂点被覆の条件 → 全ての辺のビット列と論理積(AND)をとってゼロではない 極小性の条件 → ひとつでもビットがかけたら頂点被覆でなくなる
  9. 12/30 頂点被覆列挙のビット表現 (3/3) 極小頂点被覆列挙とは 00100100 00011000 00010001 00110000 10000010 00000101

    00010010 00100001 00001001 00010111 00111110 10010101 10111100 00101011 00110011 10110001 グラフ Minimal Hitting Sets このビット列を入力とし このビット列を出力する問題 典型的なNP完全問題 ビット表現
  10. 13/30 ナイーブな実装 (1/2) 1 2 3 011 110 000 001

    010 101 011 010 ・入力のビット列をひとつずつチェック ・現在の状態と重なりがないビット列が出現したら、ビットのひとつを立てて再帰 入力グラフ ビット表現 1. 000からスタート 2. 000は011と重なりがない 3. 001を立てて次へ 4. 001と110は重なりがない 5. 110のうち、010を立てて次へ 6. 得られた011は極小でない 1 2 3 4 011 110 5 6 極小でない解や、重複解が出現してしまう 極小でない
  11. 14/30 ナイーブな実装 (2/2) 1 2 3 101 011 110 000

    100 001 110 101 001 101 011 101 011 110 101 110 左の入力からナイーブな再帰をすると 出力が重複する 重複
  12. 15/30 逆探索アルゴリズム(1/4) 極小頂点被覆列挙をナイーブな再帰で実装すると ・ 極小でないものが出現 ・ 重複する解が出現 これを解決するのが「逆探索アルゴリズム」 逆探索の考え方 1.

    解に階層を導入する 2. 異なる解に属す解に「親子関係」を定義する ・ ある子ノードの親は一意に決まるように定める ・ 自分自身が祖先に出現しないようにする 3. 階層を上に行くと答えが単純になり、自明な解が根(root)になるようにする 4. 根から親子木を逆にたどると答えを得る 親子関係が木になる 参考:宇野 毅明: 極小集合被覆を列挙する実用的高速アルゴリズム http://id.nii.ac.jp/1001/00031992
  13. 16/30 逆探索アルゴリズム(2/4) 部分被覆 ・入力のビット列がn個とする ・その1つ目からk個目までの部分集合を考える ・そのk個のビット列に対して極小頂点被覆であるものを k-極小頂点被覆(Minimal Hitting Set, MHS)と呼ぶ

    ・0-MHSからひとつずつ対応ビット列を増やして行く ・n-MHSが求める答え = {1 , 2 ,…, } 入力(辺)全体の集合 = {1 , 2 ,…, } 入力の部分集合 k-HS: k 頂点被覆 k-MHS: k 極小頂点被覆 についての頂点被覆 についての極小頂点被覆
  14. 17/30 逆探索アルゴリズム (3/4) いま、tがk-MHSであるとする時、tの親を生成する操作R(t)を 以下で定める R(t) = t ^ (t

    & e[k]) Reduction操作 t tが(k-1)-MHSの場合 そうでない場合(※) tは(k-1)-MHSではないので、あるビットを削っても、 はカバーできる tからビットを削って(k-1)-MHSにしたものをR(t)とする tはk-MHSであったから、ビットを削ったR(t)はk-MHSではない R(t)はk-MHSではないので、e[k]と交わりを持たせるにはビットを追加する必要があるが、 追加は1ビットで十分である したがって、tとR(t)の違いは1ビットであり、それはt&e[k]で求められる 以上からR(t) = t ^ (t & e[k])となる k-MHSの親が(k-1)-MHSとなるように定める あるノードの親を作る操作をReductionと呼ぶ −1 ※ tが(k-1)-MHSでないときのR(t)の求め方
  15. 18/30 逆探索アルゴリズム(4/4) 頂点被覆における親子木の例 000 100 001 110 001 101 011

    110 Reduction 自明な解 レベル0 レベル1 レベル2 レベル3 欲しい解 Enumeration 親 子 各レベルkではk-MHSが列挙されている
  16. 19/30 逆探索アルゴリズムの実装 (1/2) 1 2 3 011 110 000 001

    010 101 011 010 011 110 k-MHSの子供は必ず(k+1)-MHSでなければならない → 再帰してビットを追加したときに極小でなければ枝刈り 極小被覆でない解が取り除かれた 枝刈り
  17. 20/30 逆探索アルゴリズムの実装 (2/2) 1 2 3 101 011 110 000

    100 001 110 101 001 101 011 101 011 110 101 110 0-MHS 1-MHS 2-MHS 3-MHS k-MHSの子供は必ず(k+1)-MHSでなければならない 重複解が取り除かれた 2-MHSではない 枝刈り
  18. 21/30 極小性判定(1/6) 1. tから1-bit取り除いてみる 2. E_k 全てと重なりチェック 3. 全てのビットについて1.2.を繰り返す 4.

    1-bit削除したものがE_k全てと重なりを持てば極小でない 再帰してビットを追加したとき、極小性を満たさない場合は枝刈りする → t が k-MHSであるかチェックする必要がある(極小性判定) tに含まれるbit数がBの時、計算量はO(kB) bool check_minimal(mybit t, int k, mybits &e) { mybit v = t; while (v) { mybit t2 = v & -v;mybit t3 = t ^ t2; bool flag = true; for (int i = 0; i < k; i++) { flag &= ((e[i] & t3) != 0);if(!flag)break; } if (flag) return false; v = v ^ t2; } return true; } ナイーブな実装
  19. 22/30 極小性判定(2/6) Critical Hyperedge もしk-MHSのあるビットを削除した時に、ある辺との重なりがなくなったら、 その辺をそのビットのCritical hyperedge (CH)と呼ぶ 101 011

    110 Hypeedges 101 101 110 011 MHS Critical Hyperedge of this bit Critical Hyperedge of this bit tが極小頂点被覆であるなら、どのビットを削ってもカバーできない辺が出現する → tの全てのビットに最低ひとつはCHが存在する
  20. 23/30 極小性判定(3/6) 00010010 01100110 10110100 11011000 01000111 01010011 01100110 01010010

    01100110 10110100 11011000 01000111 01010011 01100110 minimal not-minimal 極小性条件 tを構成する全てのビットが、最低一つのCHを持つ時に限り、t はMHSとなる critical hyperedgeを持たないbitを持つ場合、極小ではない
  21. 24/30 極小性判定(4/6) 極小性条件判定 tを構成する全てのビットが最低一つの(CH)を持つ CHを持つビットにフラグを立てていく tを構成する全てのビットにフラグが立てばtは極小である ビット演算による実装 1. tと辺の論理積をとり、たっているビット数の数を数える 2.

    もし1ビットならその辺はCHであるので、そのビット位置を覚えておく 3. CHとtの重なりビット全ての論理和(OR)をとり、それをt’とする 4. もしt’==tなら、全てのビットがCHを持つのであるからtは極小である 5. そうでないならtは極小ではない
  22. 25/30 極小性判定(5/6) 00010010 01100110 10110100 11011000 01000111 01010011 01100110 00000010

    00010000 00010000 00000010 00000010 00010010 = 01010010 01100110 10110100 11011000 01000111 01010011 01100110 00000010 00010000 00010000 00000010 00000010 00010010 ≠ 極小性チェック 1. tと辺の論理積(AND)をとったとき、たっているビット数が1ビットな 2. その辺全ての論理和(OR)をとる 3. 結果がtに等しいとき、tは極小である 計算量がO(Bk)からO(k)に落ちる t’ t
  23. 26/30 極小性判定(6/6) bool check_minimal2(mybit t, int k, mybits &e) {

    mybit t2 = 0; for (int i = 0; i < k; i++) { if (popcnt(t & e[i]) == 1) { t2 = t2 | (t & e[i]); } } return (t2 == t); } bool check_minimal(mybit t, int k, mybits &e) { mybit v = t; while (v) { mybit t2 = v & -v;mybit t3 = t ^ t2; bool flag = true; for (int i = 0; i < k; i++) { flag &= ((e[i] & t3) != 0);if(!flag)break; } if (flag) return false; v = v ^ t2; } return true; } 最初の実装 改良された実装 tと1ビット重なりを持つe[i]全ての 論理和がtに一致するか調べる tから1ビット削ってみて、極小 性条件を満たすか調べる
  24. 27/30 実行時間 入力データ 32-bitのうち、ランダムに10bit 立っている 200行 全部でMHSは1352805個存在する これを列挙するのにかかった時間を計測 01010000100001111000000100001100 01000010010010010101010001000010

    10000000100100000100010011001011 01111010001000010000000101000010 00001110010010000100000100001110 10000100010001000010001011110000 10000010001010101011000000100010 10100100100111100010000000100000 ... 結果 Naïve way: Improved way: 3.621 [s] 2.396 [s] ちょっとだけ早くなった
  25. 28/30 UA sets (size 4) 不可避集合 (Unavoidable Sets, UA) UA

    sets (size 6) もし不可避集合に属すヒントを全て取り除いた場合、解が一意でなくなる集合 000000000000000000000000000000000000101000000000000000000000000000000000101000000 000000000000000000110000000000000000000000000000000000000000000000000000110000000 ... 100001001010001001000000000110000000000000000110000000110000000110000000000000000 100000001011000001010000100010000100001000001000000000111000000000000000000000000 000000001000001110001010110001001001010000100100100000001001001010010000100100000 UA sets Solution 解は必ず全ての不可避集合のビットと重なりを持つ (必要条件) 数独と頂点被覆列挙問題 (3/4) 5と9を入れ替えても数独として成立 → この4つを全て抜くと解が2つ出現
  26. 29/30 数独と頂点被覆列挙問題 (4/4) 不可避集合の活用 数独の解の一意性判定はコストが高い 不可避集合は、「答え」を与えると一意に決まる 全ての解は不可避集合と重なりを持っている 不可避集合を「解の一意性判定」の前処理に用いる 不可避集合と解候補 解が一意である場合、必ず全ての不可避集合と重なりを持つ

    不可避集合から、解の候補を列挙する 極小頂点被覆列挙 16ヒント定理証明の手続き 1. 数独の答えから、不可避集合を作成する 2. 不可避集合全てと重なりを持つ解候補を作成する(極小頂点被覆列挙) 3. ビット数が17以上なら枝刈り 4. 残った「解候補」についてまじめに解の一意性判定を行う 5. 以上を全ての「答え」について行う