Eliminating Amortizations PurelyFunctionalDataStrctures 輪講 第6回

Slides:



Advertisements
Similar presentations
G ゼミ 2010/5/14 渡辺健人. パフォーマンスの測定 CUDA Visual Profiler CUDA の SDK に標準でついているパフォーマン ス測定用のツール 使い方: exe ファイルのパスと作業ディレクトリ指定して実 行するだけ 注意点 : GPU のコード実行後にプログラム終了前に,
Advertisements

Lecture02-Binary Search Trees 通信情報システム専攻 岩間伊藤研究室 M1 前田圭介.
プログラミング言語論 第10回(演習) 情報工学科 木村昌臣   篠埜 功.
4.3 マージソート.
プログラミング演習II 2004年11月 30日(第6回) 理学部数学科・木村巌.
プログラムのパタン演習 解説.
離散システム特論 整列(sorting)アルゴリズム 2.
情報・知能工学系 山本一公 プログラミング演習Ⅱ 第4回 配列(2) 情報・知能工学系 山本一公
20分でわかる Purely Functional Data Structures
2 分探索木 Binary Search Tree 実行可能な操作 計算量 木の高さは,最悪 O(n) n = |A| : 要素の個数
アルゴリズムとデータ構造 第8回 ソート(3).
近似アルゴリズム 第10章 終了時刻最小化スケジューリング
第11回 整列 ~ シェルソート,クイックソート ~
基礎プログラミングおよび演習 第9回
プログラミング演習Ⅱ 第12回 文字列とポインタ(1)
アルゴリズムイントロダクション第5章( ) 確率論的解析
アルゴリズムとデータ構造 第6回演習解答 2015/11/18実施 アルゴリズムとデータ構造 2015.
2009/10/9 良いアルゴリズムとは 第2講: 平成21年10月9日 (金) 4限 E252教室 コンピュータアルゴリズム.
第10回 ソート(1):単純なソートアルゴリズム
情報工学概論 (アルゴリズムとデータ構造)
プログラミング言語論 第4回 式の構文、式の評価
アルゴリズムイントロダクション18章 D3照山順一.
全体ミーティング (6/13) 村田雅之.
Natural Semantics 実行過程の、最初と最後の状態(state)の関係を考える。
アルゴリズムとデータ構造 第3回基本的なデータ構造(リスト) 2015/10/28 アルゴリズムとデータ構造 2015.
条件式 (Conditional Expressions)
プログラミング演習II 2004年12月 21日(第8回) 理学部数学科・木村巌.
岩井 儀雄 コンピュータ基礎演習  ー探索、整列ー 岩井 儀雄
プログラミング論 II 電卓,逆ポーランド記法電卓
第3回:ボールを上下に動かそう! (オブジェクトの移動、一次元)
データ構造と アルゴリズム 第八回 知能情報学部 新田直也.
ML 演習 第 7 回 新井淳也、中村宇佑、前田俊行 2011/05/31.
関数 関数とスタック.
データ構造と アルゴリズム 第十一回 理工学部 情報システム工学科 新田直也.
第11回 整列 ~ シェルソート,クイックソート ~
7-3.高度な木 (平衡木) AVL木 平衡2分木。回転操作に基づくバランス回復機構により平衡を保つ。 B木
データ構造とアルゴリズム 第4回 リスト ~ データ構造(1)~.
PROGRAMMING IN HASKELL
“Purely Functional Data Structures” セミナー
PROGRAMMING IN HASKELL
関数の定義.
プログラミング 4 記憶の割り付け.
アルゴリズムとデータ構造 補足資料11-1 「mallocとfree」
7.4 Two General Settings D3 杉原堅也.
情報工学概論 (アルゴリズムとデータ構造)
逐次プログラムの正当性(2) 帰納的アサーション法(フロイド法)
第9回 優先度つき待ち行列,ヒープ,二分探索木
アルゴリズムとデータ構造1 2005年7月1日
25. Randomized Algorithms
Cプログラミング演習 第10回 二分探索木.
プログラミング 4 整列アルゴリズム.
プログラミング 4 探索と計算量.
プログラムの基本構造と 構造化チャート(PAD)
15.cons と種々のデータ構造.
アルゴリズムとデータ構造 第3章 ヒープ 5月31日分
データ構造とアルゴリズム (第5回) 静岡大学工学部 安藤和敏
第16章 動的計画法 アルゴリズムイントロダクション.
第9回 優先度つき待ち行列,ヒープ,二分探索木
ポインタとポインタを用いた関数定義.
情報工学概論 (アルゴリズムとデータ構造)
Post-Kona paper 解説 P0083R1: Splicing Maps and Sets (Rev.3) 稲葉 一浩
ヒープソート.
2008年6月5日 非線形方程式の近似解 2分法,はさみうち法,Newton-Raphson法)
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
参考:大きい要素の処理.
プログラミング演習I 2003年6月11日(第9回) 木村巌.
データ構造と アルゴリズムI 第三回 知能情報学部 新田直也.
プログラミング演習II 2003年12月10日(第7回) 木村巌.
情報処理Ⅱ 第3回 2004年10月19日(火).
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
Presentation transcript:

Eliminating Amortizations PurelyFunctionalDataStrctures 輪講 第6回 2006/06/23 いなば

ここまでの流れ (1) Imperative Queue (Ch2) 1 2 3 ・ 4 ・ リスト末尾を指すポインタをもっておきsnoc時に書換 Persistent でない head, tail, snoc の最悪実行時間が O(1) 1 2 3 ・ 4 ・

ここまでの流れ (2) 1 2 3 ・ 5 4 ・ Functional Queue (Ch5) Front側とRear側の2つのリストで表現 |Front| == 0 になったら Rear を reverse Persistent である 最悪実行時間は、reverseが発生するとき O(n) 償却実行時間は (persistencyを必要としない使い方なら) O(1) 1 2 3 ・ 5 4 ・

ここまでの流れ (3) 1 2 3 ・ 5 4 ・ Functional Queue via Lazy Evaluation (Ch6) Front側とRear側の2つのリストで表現 |Front|+1 == |Rear| になったら遅延 reverse Persistent である 最悪実行時間は、reverseが発生するとき O(n) 償却実行時間は (persistencyを必要とする使い方でも) O(1) 1 2 3 ・ 5 4 ・

? 今日の話 Functional Real-Time Queue (Ch7) Persistent である 最悪実行時間は、O(1)

Real-Time Queues: 基本的考え 「借金」 = 「suspensionをほどく計算のコスト」 “reverse” の suspension に仮想的な「借金」を割当 借金額 =非共有コスト = そのsuspensionをforceした時実行される計算時間 = reverse時点のRearの長さ 実際にsuspensionがforceされるに至るまでの各演算に、仮想的に借金を定数額ずつ「返済」させる reveseは|Front| = |Rear| のとき行われるので、 |Front| 回 tail した後にforceされる。よって、1回のtailで 1ずつ借金を返済

Real-Time Queues: 基本的考え 「借金」 = 「suspensionをほどく計算のコスト」 各 tail 演算で、実際に「借金」を「返済」する つまり、tailのたびに、reverseのsuspensionを 少しずつ(定数時間ずつ)実行しておく

Real-Time Queues OCaml で実装してみました ポイント MyRTQ.ml 「|Front|+1 == |Rear| になったらreverse」になってるか 全てのsuspensionは定数時間でforce可能か

Amortization除去 6章のQueueとの差 Rearの逆転処理 f @ rev r rev は incremental でない(forceすると全体を計算してしまう)ので、「実際に少しずつ借金を返す」ができない rotate f r [] incremental。少しずつ計算できる。 Schedule, exec 「実際に少しずつ計算」するための「次やる計算」のリストと、それを実際に少し実行する処理

Amortization除去 一般的なステップ (1) Monolithic な suspension を、工夫してincremental なものに置き換える 各 suspension の「内部コスト」を、許される計算量制限の範囲におさえる 例 : @rev → rotate, 内部コスト=O(1) 内部コスト(internal cost) suspension の内部コストとは、「依存している他の全ての suspension が既に評価済みで値をO(1)で取り出せる」と仮定した時にかかる計算コストのこと (「suspendされている計算の非共有コスト」と同義?)

Amortization除去 一般的なステップ (2) 各suspensionが評価されるよりも前に、そのsuspensionが依存する他のsuspensionが評価済みとなることを保証する 例 : schedule変数

Exercise 7.1 6章の @rev を rotate に置き換えると(Schedulingを行わなくても)、snoc, head, tail の最悪実行時間はO(n) から O(log n) に減る。これを示せ Ans Scheduleが関与したのはrotateの第一引数のforce。 このsuspensionの依存の深さは、連続でsnocし続けた時最大になるが、たかだかO(log n)

Exercise 7.2 Real-time Queue の要素数を求めたい。 ただし、|f| + |r| で求めるよりも、|r| と |s| を使う方が効率がよい。求め方と効率について考察せよ Ans. |s| = 前回のrotate時の要素数 – tail回数 – snoc回数 |r| = snoc回数 ∴要素数 =前回のrotate時の要素数 - tail回数 + snoc回数 = |s| + 2 |r| |f|+|r| > |r|+|s| なのでその分だけ速い? それだけだろうか? 

今日の話その2 Binomial Heaps (Ch3) Binomial Heaps (Ch5) insert, deleteMin, findMin, merge : 最悪 O(log n) Binomial Heaps (Ch5) Physicist’s Method で、 persistencyを必要としない使い方なら insert : 償却 O(1) が示せる Lazy Binomial Heaps (Ch6) リストを遅延リストに変えれば、persistency を使う場合でも insert : 償却 O(1) にできる Amortizationの除去 (Ch7) insert を 最悪 O(1) にできる

Binomial Heaps: おさらい 自然数の「2進数表現」に類似したデータ構造 サイズ 2a1+2a2+...+2an のHeapは、 [サイズ2a1の木、サイズ2a2の木、…、サイズ2anの木] のリストで表現

Binomial Heaps: おさらい type tree = T of int * Elt.t * tree list type heap = tree list insert e h = insTree (T(0,e,[])) h insTree t h = match h with | [] -> [t] | hd::tl -> if rank t < rank hd then t::h else insTree (link t hd) tl

やるべきこと 「少しずつ実行したいsuspension」 がmonolithicなら incremental に書き換える 内部コストが欲しい計算量におさまるように monolithic な insTree を incremental, O(1) に Scheduling insert e h = insTree (T(0,e,[])) h insTree t h = match h with | [] -> [t] | hd::tl -> if rank t < rank hd then t::h else insTree (link t hd) tl

[ ] [ , ] , , , 1: Incremental 化 もっと2進数に近い表現を type tree = T of Elt.t * tree list type bit = Zero | One of tree type heap = bit list [ , ] [ ] , , ,

1: Incremental 化 もっと2進数に近い表現を insTree t h = match h with | [] -> [One t] | Zero::tl -> (One t) :: tl | (One hd)::tl -> Zero :: insTree (link t hd) tl

1: Incremental 化 もっと2進数に近い表現を Lazy版 insTree t h = match force h with | SNil -> lazy (SCons(One t, lazy(SNil))) | SCons(Zero, tl) -> lazy (SCons(One t, tl)) | SCons(One hd, tl) -> lazy (SCons(Zero, insTree (link t hd) tl))

2: Scheduling 「insTreeの作るsuspensionは全て、 評価される前にその依存するsuspensionが評価済みになっているようにする」 insTree t h = match force h with | SNil -> lazy (SCons(One t, lazy(SNil))) | SCons(Zero, tl) -> lazy (SCons(One t, tl)) | SCons(One hd, tl) -> lazy (SCons(Zero, insTree (link t hd) tl))

2: Scheduling insert のみで考える(他の演算はあとで) 作られるsuspension 満たすべき条件 左図の黄色の部分 1 作られるsuspension 左図の黄色の部分 満たすべき条件 「ある bit が0に評価される時点までには、その右上のマスの bit は評価済み」 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

2: Scheduling insert のみで考える(他の演算はあとで) type schd = bit stream list 1 type schd = bit stream list type heap = bit stream * schd let exec (bs::bsl) = match force bs with | SCons(Zero, t) -> t::bsl | SCons(One _,_) -> bsl let insert x (bs,sc) = let bs = insTree ... bs in (bs, exec (exec (bs::sc))) 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

2: Scheduling Q: なぜ2回execするのか A: 6章での解析によれば、 Amortized Costは2だったので。

2: Scheduling (Thm7.1) … … 1回のinsertにつき2回execすれば 常に次が満たされる Schedule 1回のinsertにつき2回execすれば 常に次が満たされる Schedule内で未評価rangeに重なりはない 隣り合う未評価rangeの間には必ず評価済のZeroが1個はある 最左の未評価rangeの左には必ず評価済のZeroが2個はある 1 1 1 … 1 1 … 1 1 1 1 1 1 現在のHeap

2: Scheduling (Thm7.1) 証明 帰納法による 初期状態 (empty) は条件を満たす → 自明 条件を満たす状態で insert を1回実行しても条件を満たす insert すると最左のZeroがOneに変わる 場合分け(4通り)

証明:場合分け4通り [1] が入る ケースB [1] が入る ケースA 1 1 insert 1 1 1 1 insert 1 1 1 1 1 insert 1 1 1 1 insert 1 1 1 exec × 2 1 1 1 1 exec × 2 [0,1] が入る ケース 1 1 1 insert 1 1 insert 1 1 1 exec × 2 1 1 exec × 2 1 1 1 [0,...,0,1] が入る ケース

その他の演算 deleteMin, findMin, merge O(log n) で十分なので、全ての未消化 schedule を実行して、普通のリストとして操作すればよい insert での解析から、未消化 schedule はたかだか O(log n) 個である MyBinHeap2.ml

まとめ “Lazy” “Amortized” “Persistent” データ構造を、 “Lazy” “WorstCase” “Persistent” に変える手法 遅延評価する部分を incremental にする 小分けにした suspension を “Schedule” として管理 各演算ごとに、解析された償却計算量に従った回数分 Schedule を実行