Transcript 計算幾何学
計算幾何学 ・ 線分交差列挙 ・ 凸包 ・ アレンジメント ・ ボロノイ図 線分交差判定 ・ 線分交差列挙 計算幾何学とは ・ 幾何学的な問題を計算で解く方法 ・ 人間の場合、補助線を引く、定規・コンパスを使う、といった 紙を使う解法が多いが、コンピュータではこれらは使えない ・ 目で見て大観を得るようなこともできない ・ 全てを、数値データとして扱わなければならないのがポイント 線分交差判定 ・ 例えば、2つの線分が交わるかどうか判定する 人間は、図があればぱっと答えられる ・ 数値で与えられる場合、線分の端点の座標が与えられる ・ ここから何かを計算して、代数的に判定しなければいけない ・ 赤い線・青い線が乗っている直線の方程式を計算して、 端点が直線のどちら側にあるか判定(これは代入して大小比較) ・ 相手の端点が両側にある、 という条件が、両方に 成り立つときのみ交わる 線分交差列挙問題 ・ n 本の線分があるとき、どれとどれがどこで交わっているの か知りたい 人間ならば、図を書いて端からチェックして、簡単 先の交差判定を用いれば、O(n2) 時間でできる ・ 全部交わっていたらO(n2) 時間はしかたないが、交わってい るものが少ないときに、もう少し速くできないだろうか ・ 人間と同じように、 端からチェックしてみよう 同一要素判定問題の帰着 ・ 線分交差列挙問題には、同一要素判定問題が帰着できる ・ 同一要素判定問題を解くには、少なくとも n log n 時間かかるこ とが知られている 線分交差列挙問題を解くには少なくとも n log n 時間かかる 同一要素判定問題: 入力した数 a1,…, an の中に、同じ値のものがあるか 各 ai に対して、 x 座標が ai である 場所に縦線を置く(わずかに垂直 から異なる角度ずらす) ・ 交点がある 同一要素がある a1 a4 a3 a2 a5 線分交差判定問題 ・ まず、一番左に垂直な線を立て、それを右に動かしていく ほんとに書くのではなくて、仮想的に考えるだけ 1. 垂直線と各線分の交点を見つけ、垂直方向にソートする 2. 各線分の右端、新しい線分の左端、上下に隣り合う線分の 交点(これらをイベントという)をヒープに入れる 3. ヒープから最小のものを取り出し、そこに移動 線分交差判定問題 2. 各線分の右端、新しい線分の左端、上下に隣り合う線分の交 点(これらをイベントという)をヒープに入れる 3. ヒープから最小のものを取り出し、そこに移動 ・ 交点 出力。線の順番を入替え、新たな交点をヒープに挿入 ・ 線の右端 線を消し、線の交点をヒープから消し、隣り合う 線の交点を挿入 ・ 線の左端 線を挿入し、 隣の線との交点をヒープに挿入 一回の操作は O(log n) 時間 全部で O((n+K)logn) 時間 交点の数 凸包構成 ・ 行進法 ・ グラハムスキャン ・ マージハル ・ クイックハル 凸包構成問題 ・ 平面上にある n 点を包む極小な領域を考える (ただし、へこみはつくらない)こういうものを凸包という ・凸包の辺を求める問題を凸包構成問題という 凸包の難しさ ・ 凸包の計算を使って n 個の数値のソートができる O(n log n) 時間はかかる -a1,…,an をソートしたい -点集合 (a1, a12), (a2, a22),…, (an, an2) の凸包を求める -ソートした順番に (a1, a12), (a2, a22),…, (an, an2) に枝が張られる 行進法 ・ 品物をくるむときのように、1つずつ枝を張って端からくるもう 1.一番 x 座標が小さい点 v を見つける。複数あったら、 y が最 小のものを選ぶ。凸包の内側の方向を見つける 2. v から見て時計回り順で一番大きい頂点 v' を見つける (凸包の内側の中で) 3. v と v' の間に枝をはる。 v' が最初の点でなければ、 v= v' として2 に戻る 一回の操作は O(n) 時間 全部で O(K n) 時間 辺の数 グラハムスキャン法 ・ くるむときに、効率良く接線を求める方法 1.凸包の中の点 o を見つける 2. o から見た時計回り順で全ての点をソートする 3. 時計回り順に v と、今までの点の間に接線を張る。接線を作 る頂点を2分探索で見つける 1つ消すと O(log n) 時間 全部で O(nlogn) 時間 ソートとの関連 ・ 凸包はソートが帰着できることもあり、ソート的な要因を持って いる ・ そのためか、ソート用のアイディアがけっこう使える 行進法は挿入ソート グラハムスキャンは角度順の挿入ソート+2分探索 ・ マージソートや、クイックソートのアイディアも使える - マージソート マージハル、分割法 - クイックソート クイックハル 分割法 ・ 点集合を x 軸に平行な直線でほぼ2つにわけ、それぞれの凸 法を再帰的に求めた後、全体の凸法を求める 1.点集合 P を x 座標の小さい順にソートする 2.P を x 座標で P0 と P1 、ほぼ同じ大きさの2つに分割 3.P0、P1 のについて再帰呼び出しし、P0 と P1 の凸法を求める 4.P1 と P0 の凸法の接線2つを求め、全体の凸法を作る ・ 接線は2つ求める だけでいいことに注意 分割法の計算時間 1.点集合 P を x 座標の小さい順にソート O(log n) 2.P を x 座標で P0 と P1 に分割 O(1) 4.P1 と P0 の凸法の接線2つを求め、全体の凸法を作る - 接線を求める時間は O(logn) - 頂点・枝リストのつげ替えは O(1) ・ 1反復の計算時間は O(logn) ・ 結局、ソートの時間が一番 長く、全体の計算時間は O(n logn) マージハル ・ 点集合を分割してそれぞれの凸法を再帰的に求めるところは分 割法と同じだが、分割する際に、適当な2つの点集合に分割す る (ソートしない) 2.P を P0 と P1 、ほぼ同じ大きさの2つに分割 3.P0、P1 のについて再帰呼び出しし、P0 と P1 の凸法を求める 4.P1 と P0 の凸法の接線を求め、全体の凸法を作る ・ ソートが必要なく なったが、接線を2つ 以上見つけなければ ならない 接線の求め方 ・ 接線は2分探索で1つ求められるが、最悪接線は n 本になる ざっくりいって、O(n log n) の時間が必要 ・ 工夫すると線形時間でできる 1.P0 の凸包と P1 の凸包、両者に含まれる点 o を見つける 2.そのような点がなければ、接線は2つしかない。それを求める 3. o から見て時計回り順に P0、P1 の点を見て、凸包を作る (グラハムスキャンと同じ) ・ 1つの点は2回しかアクセス されず、線形時間となる 全体で O(n log n) 時間 クイックハル ・ クイックソートのように、最悪の場合は悪くとも、もっとざっくりと 平均的に速く計算できるようデザインしたアルゴリズムもある 1. 最も右、最も左にある点を線で結び、点集合を2つに分ける 2. 各領域について、分割線の法線方向に最も遠い点を見つける 点が1つもなかったら、その分割線は凸包の辺 3. その点と分割線の両端点を結び、2つの分割線と領域を作成、 再帰的に分割線を求める ・ 平均的には、凸包 内部の点がざっくり 消えるので高速 ・ 最悪は O(n2) 時間 多次元の場合 ・ 3次元以上の高次の次元で、凸包アルゴリズムはどうなるか? ・ まず、接線が接平面になる 2つの凸包の接平面は、2つとは限らない ・ グラハムスキャンや行進法で使う「時計回り」という概念がない ・ 点を逐次追加し、その点を含む接平面を追加する ・ 3次元なら、2つの凸包の接平面をくるむように求められるので、 分割法は動く ボロノイ図 ・ 逐次追加 ・ 分割統治 ボロノイ図 ・ 平面に点(母点)がちらばっているとき、平面を、一番近い点が どこか、で領域分割したのがボロノイ図 ・ ボロノイ図にはいろいろな性質がある - ボロノイ図の各辺は、どれか2点の垂直二等分線 - 垂直二等分線の、ボロノイ図の辺になる部分は連続してる - ボロノイ図の各領域は凸多角形 - 各領域は母点を1つだけ含む - 各領域の辺は、含む 母点 と他の点の垂直二等分線 ・ 与えられた点からどこの点が 一番近いか調べるときなどに使う ボロノイ図の作り方 ・ 点が2個しか無ければ簡単 単に垂直二等分線を引けばよい ・ ここに1点追加すると、単なる直線ではなくなる 3本の垂直二等分線の一部からなる図形 ・ 交点は、3点から等距離にあるところ ・ 4点目以降はどうなるだろうか? 1点追加すると ・ 一般に、母点を1つ追加すると、その点を含む領域が新しくできる ・ それ以外の領域の形は変化しない できる領域の形かわかれば、ボロノイ図を更新できる ・ 追加した母点を v、v が入る領域にある母点を u とする v を含む領域が新たにできる 領域の辺の1つは、u と v の 垂直二等分線を含む ・ この二等分線は、他の辺と 交わるところまで伸びる 領域の端点は必ず二等分線の交点 垂直二等分線が交わると ・ 垂直二等分線を、領域の辺にくるまで伸ばす ・ 領域の辺は、領域の母点と他の点 w の垂直二等分線なので、そ こから向こう側は他の点が一番近い母点になる 垂直二等分線が作る辺はそこでおしまい ・ 新しくできる領域の辺は、そこから v と w の垂直二等分線になる また、 w の領域の他の辺にぶつかるまで進む そこで、その向こう側の 領域の母点との垂直二等 分線を求める...と進む ・ いつか、最初の二等分線と ぶつかるので、そこで終了 計算量の解析 ・ アルゴリズムは、以下の計算の反復 - 現在いる領域の母点と追加した母点の垂直二等分線を求める - その垂直二等分線と領域がもう一回交わる点を見つける ・ 垂直二等分線の計算は O(1) 時間 ・ 領域との交点を見つけるのには 二分探索が使える O(log n) 時間 ・ 領域は n の定数倍の辺を 持ちうるので、O(nlog n) 時間 ・ 全領域合計で O(n2log n) 時間 分割統治法 ・ ボロノイ図の構成法、実際のところは領域がそれほど多くの辺を 含むことはないので、実用上は短時間。O(n log n) 時間程度 ・ しかし、分割統治法を使えば、最悪 O(n log n) 時間にできる ・ 母点を、x 座標の小さいものと大きなもの、およそ半分に分割 ・ 分割した母点のボロノイ図を、再帰的に求める 分割統治法 ・ ボロノイ図の構成法、実際のところは領域がそれほど多くの辺を 含むことはないので、実用上は短時間。O(n log n) 時間程度 ・ しかし、分割統治法を使えば、最悪 O(n log n) 時間にできる ・ 母点を、x 座標の小さいものと大きなもの、およそ半分に分割 ・ 分割した母点のボロノイ図を、再帰的に求める 分割統治法 ・ 母点を、x 座標の小さいものと大きなもの、およそ半分に分割 ・ 分割した母点のボロノイ図を、再帰的に求める ・ できたボロノイ図を合わせて一つのボロノイ図を作る ・ まず、右の領域と左の領域、それぞれの中でもっとも下にある母 点を求める。無限遠では、この2点の垂直二等分線が辺になる ・ 次に、それが交わる辺を見つける。 交わった辺により、どちらかの 母点を捨て、次の領域の母点と の垂直二等分線を求める 計算量の解析 ・ n 点のボロノイ図を求めるのに、n/2 の大きさの問題を2つ解く ・ 計算結果をマージするのには、O(n) 時間 二等分線と領域の交点を見つけるときに、領域の全ての辺と の交わりをチェックするようにする ・ n 点のボロノイ図の辺は O(n) 本であることを使うと、こういう単 純なやり方でも O(n) 時間ですむ ・ よって、再帰式を作ると、 T(n) = cn + 2T(n/2) となり、計算時間は O(n log n) となる 多次元の場合 ・ 3次元以上の高次の次元で、凸包アルゴリズムはどうなるか? ・ ボロノイ領域は凸多面体になる ・ やはり「時計回り」という概念がない ・ 点を逐次追加し、その点を含む領域を構成するには、凸多面体 領域の面を求める問題になる まとめ ・ 線分交差列挙 - 端から走査線をスイープし、線分の上下関係を更新 ・ 凸包 - ソートに使うアイディアが有効 - 分割統治法がうまく働く - 行進法、グラハムスキャン、マージハル、クイックハル ・ ボロノイ図 - 逐次追加 - 分割法