簡潔データ構造と情報理論sita/forum/article/2020/...簡潔データ構造と情報理論...
TRANSCRIPT
簡潔データ構造と情報理論
東京大学大学院情報理工学系研究科
定兼 邦彦
2019年11月26日情報理論研究会
簡潔データ構造とは• 情報理論的下界に「近い」領域量だけを使いつつ,(他の圧縮形式とは異なり)効率的に質問を受け付けることができるデータ構造を指す (wikipedia).
• 通常の圧縮形式 (LZ系)だとランダムアクセスできない.
• 大量データをディスクに格納すると読み込みが遅い.• SQLで読み込むとさらに遅い
• データを簡潔データ構造で表現し,メモリ内に格納することで高速処理を実現する.
2
目次
• 経験エントロピー
• 透過的データ圧縮
• ウェーブレット木
• 圧縮接尾辞配列
3
4
文字列の経験エントロピー
定義: 0 次の経験エントロピー H0
( )
=Ac c
cp
pTH1
log0(pc: 文字 cの出現確率)
定義: k次の経験エントロピー Hk
– Pr[T[i] = c] は T[i−k..i−1] (文脈) から決定する
– ns: 文脈が sである文字の数
– ps,c: 文脈 sでの文字 c の出現確率
– T(s)は Tの中の文字で長さ kの文脈が sであるもの全てからなる文字列
compress文脈
( ) ( )
==kk As
ss
As Ac cs
cssk THTp
pnTnH )(
0
)(
,
,
1log
5
LZ78(LZW)圧縮法
• 文字列を辞書中のパタンに分割
• 数字に置き換えて符号化
• 辞書を更新
• 文字列が長くなると圧縮率がエントロピーに収束
a b1 2
辞書
a a a b a
1 a
a3入力
出力 1 b
b 4a b
3 b b 5
a a b a
5 a
a6
6
LZ78の圧縮率長さ nの文字列 Sを分解したフレーズの数 cは
• 圧縮後のサイズ: bits
• Sが定常エルゴード情報源 (エントロピー H) から生成されるなら
• Sの k 次経験エントロピーHkに対し
)( log
→→ nHn
cc
( )loglog +cc
)(loglog ckcc
ncnHcc k +++
n
ncn
log ( : アルファベットサイズ)
S. Rao Kosaraju, Giovanni Manzini: Compression of Low Entropy Strings with
Lempel-Ziv Algorithms. SIAM J. Comput. 29(3): 893-911 (1999).
7
類似文字列のエントロピー
定理:
T, T’ : アルファベット[]上の長さn, n’ の文字列T と T’ の間の編集距離は 1 のとき, 任意のk0
に対して ( ))log)(log1(O)()( ++=− nkTHnTnH kk
T c n
T’ c’
T−
T+ c’’
n
n−1
n+1
n’ 置換
削除
挿入
Jesper Jansson, Kunihiko Sadakane, Wing-Kin Sung. Compressed random access
memory, Proceedings of ICALP, LNCS 7391, pp. 510-521, 2012.
8
補題:
T c n
T’ c’
T−
T− c’’
n
n−1
n+1
n’ 置換
削除
挿入
log4)1log(4)()1()(
log3log4)()1()(
log3log4)()(
00
00
00
+++−
+−−
+−
nTHnTnH
nTHnTnH
nTnHTnH
9
置換の場合: P とP’ をT とT’ の確率分布とする.
cが c’ に置き換わった時
nn
n
n
n
n
n
n
nPPPP cccc
A
211)()(
1=
−−+
−−=−=−
定理 [Cover, Thomas 91]
もし なら2
11− qp
1
100 log)()(qp
qpqHpH−
−−−
従って,もし2
1− PP
log2log4)()( 00 +− nTnHTnH
もし ならば n < 4であるため2
1− PP
log3)()( 00 − TnHTnH
他の場合も同様
10
定理の証明:
エントロピーの定義:
T = T1 c T2 と T’ = T1 c’ T2 とする
文脈 s0に対し, の文字が1つ置換される
T2[i] の文脈 siは s’i (i=1,…,k) に変わる
2k+1 個の文脈で 1 つの文字が変化
( ) ( )
=kAs
ss
k THTTnH )(
0
)(
T c
T’ c’
s0 s1 s2
sk
)( 0sT
T1 T2
( ))log)(log1(O)()( ++=− nkTHnTnH kk
11
透過的データ圧縮• 入力: 長さ nの配列 (文字列) S[0..n−1]
– S[i] A, アルファベットサイズ
• 問合せ
– S の指定された位置の部分文字列を返すS[i..i+w−1] (w = O(log n) つまり O(log n) bits)
– 語長 O(log n) bits の word RAM で O(1) 時間
• 索引サイズ: nHk(S) + o(n log ) bits
Kunihiko Sadakane, Roberto Grossi: Squeezing succinct data structures into entropy
bounds. Proc. SODA , pp. 1230-1239, 2006.
12
結果
• サイズ: LZ78 [Ziv, Lempel 78] と漸近的に同じ
• Sの i文字目からの連続する log n文字
(log n ビット) を定数時間で復元可能
• このアクセス時間は未圧縮の場合と同じ
– データは圧縮されていないと見なせる
++
n
nknSnH k
log
loglogloglogO)(
13
• k次エントロピーを達成するには,文字の符号をその直前の k文字から決める必要がある.
• 文字列のある部分を復元するにはその直前も復元する必要がある.
• でも実は・・・
部分復元の難しさ
14
• LZ78での圧縮サイズの 項は
1語 (log n bits) あたり O(k log ) bits の冗長度があることを表す.
• つまり,1語ごとに k文字をそのまま格納しても冗長度は漸近的には増えない
• 1語を復元するために必要な情報は k文字だけなので,他の部分は復元しなくていい
• ただし,k log < log nである必要がある
n
kn
log
loglogO
15
単純なデータ構造1 (S1)
• Sを w = ½ log n 文字ごとのブロックに分割
• 各ブロックの文字をハフマン符号で符号化
– n(1+H0(S)) bits
• ブロックへのポインタを格納
• ブロック内の文字の復号は表引きでO(1)時間
=
+
=
+
n
nn
w
n
nn
n
w
n
wn
n
log
logloglogO
O)log/log(O
)log(OlogO
/
)log(Olog
16
単純なデータ構造2 (S2)• Sを w = ½ log n 文字ごとのブロックに分割
• 各ブロックの先頭 k文字はそのまま格納
• 各ブロックの残りの w − k文字は,文脈から決まる確率に従い算術符号で符号化
• 全ブロックでの合計は
2
]1..[|][Pr
1log
)1(
1
+−−
+
++=
wj
kjwi ikiSiS
)(1
log
|Pr
1log|Pr
]1..[|][Pr
1log
,
,
1
SnHp
pn
scscn
ikiSiS
k
As Ac cs
css
As Ac
s
n
i
k
k
==
=−−
=
17
• 算術符号での誤差は2n/w = O(n log / log n)
• 各ブロックの符号を連結し, ポインタを格納
• 算術符号を定数時間で復号するための表
• 合計で
=
+
n
nn
w
n
wn
n
log
logloglogOO
/
loglog
)(o)log(O)log2(Olog
21
nnnn knk ==
( )
++ nk
n
nSnH k logloglog
log
logO)(
(k = o(log n) のとき)
Rodrigo González and Gonzalo Navarro. Statistical Encoding of Succinct
Data Structures. Proc. CPM'06, pages 295-306. LNCS 4009.
18
単純なデータ構造3 (S3)
• Sを w = ½ log n 文字ごとのブロックに分割
• 各ブロックを1つの文字だとみなし, 符号を割当てる
– 文字は 1 から の整数で表される
– 各文字の頻度を数える
– 頻度の多い順に符号 0, 1, 00, 01, 10, 11, 000, 001,...
を割当てる
• 各ブロックの符号を連結し, ポインタを格納
nw =
=
+
n
nn
w
n
wn
n
log
logloglogOO
/
loglog
P. Ferragina and R. Venturini. A simple storage scheme for strings achieving entropy
bounds. Theoretical Computer Science, 372(1):115–121, 2007.
19
サイズの解析
• ブロックへのポインタ: O(n log log log n/log n)
• ブロックの符号から文字列の復号
補題: ブロックの符号長の合計は次の値以下.
(S2のサイズ)
)(ologlogloglog21
21 nnnnnww ===
( )
++ nk
n
nSnH k logloglog
log
logO)(
20
証明:あるブロックの符号は
– S2: 最初の k文字をそのまま残りは算術符号
– S3: w文字をまとめて1つの符号
S3では多く出現するパタンに短い符号を割り当て
ている⇒符号長の合計はS2よりも長くない.
注:S3のサイズは kに依存しない
⇒全ての 0 k o(log n) について同時に成立
( )
++
nk
n
nSnH k
nklogloglog
log
logO)(minS3
)(logo0
21
動的な配列
• 入力: 長さ nの配列 (文字列) S[0..n−1]
– S[i] A, アルファベットサイズ
• 操作
– S の指定された位置の部分文字列を返すS[i..i+w−1] (w = O(log n) つまり O(log n) bits)
– Sの指定された位置の部分文字列を変更S[i..i+w−1]
• 索引サイズ: nHk(S) + o(n log ) bits
– Sが変更されると,エントロピーも変化する
– 索引サイズを現在の Sのエントロピーでおさえる
22
定理:
サイズ
Sの1語の読み込み: O(1) time
Sの1語の書き換え: O(1/) time
系:
サイズ(LZ78と同じ)
Sの1語の読み込み: O(1) time
Sの1語の書き換え: time
( )
+++
n
nknSnH k
log
loglogloglogO
( )
++
n
nknSnH k
log
loglogloglogO
n
nn
k loglog
log,log
1minO
23
• 1語の挿入・削除を許すと,読み書き・挿入削除の時間は O(log n /log log n) になる.
Jesper Jansson, Kunihiko Sadakane, Wing-Kin Sung. Compressed random access
memory, Proceedings of ICALP, LNCS 7391, pp. 510-521, 2012.
Roberto Grossi, Rajeev Raman, Srinivasa Rao Satti, Rossano Venturini:
Dynamic Compressed Strings with Random Access. ICALP (1) 2013: 504-515
定理:
サイズ
Sの1語の読み込み: O(1) time
Sの1語の書き換え: O(1) time
𝑛𝐻𝑘 𝑆 + O 𝑛 log 𝜎𝑘 log 𝜎 + loglog 𝑛
log 𝑛
24
• データのサイズが大きい
– 圧縮するとランダムアクセスができない (遅い)
– 検索を行うには索引を追加する必要がある
• 索引サイズが大きい
– メモリに載らない
– ディスクに置く→低速処理
– 索引の情報量を落としてサイズ削減→精度低下
従来のデータ構造の問題点
簡潔データ構造:100GBの日本語文書に対し
–従来の索引 (接尾辞配列) + データ 680.4G
–簡潔データ構造 (索引+データ) 21.6G
25
簡潔データ構造
• 簡潔データ構造=データの簡潔表現+簡潔索引
• 簡潔データ構造の例
– 集合
– 木,グラフ
– 文字列
– 順列,関数
26
簡潔表現
• サイズが情報理論的下限に(ほぼ)一致する表現
• 入力がL通りのとき,情報理論的下限はlog L bits
• 例1: 集合 S {1,2,...,n} のサイズの下限
– log 2n = n bits
n = 3
{1,2}
{1,2,3}
{1,3} {2,3}
{3}{2}{1}
log の底は 2
27
• 例2: n ノードの順序木
• 例3: n文字の文字列
– n log bits (: アルファベットサイズ)
( )bits log21
12
12
1log nn
n
n
n−=
−
−
−
n = 4
28
• どんなデータにも簡潔表現は存在
– 適当な順序で列挙し,符号を割り当てる
– log Lビットで表現可
– 効率的な演算ができるかどうかは分からない
• 表現法によって,演算操作の手間が変化
– 目的に適した表現を用いる必要あり
n = 4 bits 35log1
12
12
1log ==
−
−
− n
n
n
000 001 010 011 100
29
簡潔索引
• 決められた操作を実現するためのデータ構造
• サイズ: o(log L) bits
• 従来の表現と(ほぼ)同じ操作時間
• 計算モデル: word RAM
– 語長 w = log log L とする(従来のデータ構造と同じポインタサイズ)
30
ビットベクトル• B: 長さ nの 0,1 ベクトル B[0]B[1]…B[n−1]
• サイズの下限 = log 2n = n bits
• 操作
– rank(B, x): B[0..x] = B[0]B[1]…B[x] 内の 1 の数
– select(B, i): Bの先頭から i番目の 1 の位置 (i 1)
• 全ての簡潔データ構造の基本
• ナイーブなデータ構造
– 全ての答えを配列に格納
– 2n語 (2 n log n bits)
– O(1) 時間問合せ B = 10010100010000000 3 5 9
n = 16
31
定理:長さ nのビットベクトルでのrank, selectは
語長 (log n) bits のword RAM上で
n H0 + O(n log log n/log n) bits を用いて
O(1) 時間で求まる.
32
$ = 00
a = 01
c = 10
g = 11
ウェーブレット木• −1 個の0,1ベクトルから成る2分木
• 根のベクトル V[0..n−1]
– V[i] = 1 ⇔ S[i] の最上位ビットが 1
• 根の右(左)の部分木は,最上位ビットが 1(0) のS の文字だけからなる文字列のウェーブレット木
– 最上位ビットは取り除く
1 0 1 1 0 1 1 0 0
S: g $ c c a g g a a
V
0 1 1 1V0S0 0 0 1 11V1S1
33
rankの計算• b = (cの最上位ビット)
• c’ = (cの最上位ビットを除いたもの)
• r = rankb(V, x)
• rankc(S, x) = rankc’(Sb, r) (再帰的に計算)
• O(log ) 時間
• 木の深さ dのノードのベクトルの長さの合計は n
• 木の高さは log
• n log + O(n log log log n/log n)
= |S| + o(|S|) bits
34
accessの計算• b = access(V, x)
• r = rankb(V, x)
• access(S, x) = b : access(Sb, r) (再帰的に計算)
• O(log ) 時間
• b = (cの最上位ビット)
• c’ = (cの最上位ビットを除いたもの)
• selectc(S, x) = selectb(V, selectc’(S, x))
• O(log ) 時間
selectの計算
35
ベクトルの圧縮
• nc: 文字 cの頻度
• 圧縮された Vのサイズ
• 圧縮された V0 と V1のサイズ
1 0 1 1 0 1 1 0 0
0 1 1 1 0 0 1 11
S: g $ c c a g g a a
V0
V0
++++ −− 11021
21
log
nnnn
n
++++
+++
++++
++
−−
−
−−
−
11
1
110
10
43
43
21
21
21
41
41
21
log
log
nnnn
nn
nnnn
nn
V1
36
• 全てのレベルを合計すると
• まとめ
– access/rank/select: O(log ) 時間
– サイズ: nH0+O(n log log log n/log n)
• ウェーブレット木の形を完全2分木ではなくハフマン符号と同じにすれば,圧縮された文字列のランダムアクセスが可能になる(ただし定数時間ではない)
0
1
0120
log,,,
log nHn
nn
nnn
n
c c
c ==
−
=−
R. Grossi, A. Gupta, and J. S. Vitter. High-Order Entropy-Compressed Text
Indexes. In Proc. ACM-SIAM SODA, pages 841–850, 2003.
37
文字列用の標準的データ構造
• 操作
– パタンの出現回数,場所
– 共通部分文字列,極大パタン
– アラインメント
• 代表的データ構造
– 接尾辞木
– 接尾辞配列
• サイズ:文字列 + O(n log n) bits
– ヒトのDNA配列:30億文字 (750MB)
– 接尾辞木:40GB
38
接尾辞 (suffix)• 文字列 Tの先頭の何文字を除いたもの (n種類)
• Tの任意の部分文字列は,ある接尾辞の接頭辞
= T1 いるかいないかいないかいるかいるいるいるか2 るかいないかいないかいるかいるいるいるか3 かいないかいないかいるかいるいるいるか4 いないかいないかいるかいるいるいるか5 ないかいないかいるかいるいるいるか6 いかいないかいるかいるいるいるか7 かいないかいるかいるいるいるか8 いないかいるかいるいるいるか9 ないかいるかいるいるいるか10 いかいるかいるいるいるか11 かいるかいるいるいるか12 いるかいるいるいるか13 るかいるいるいるか14 かいるいるいるか15 いるいるいるか16 るいるいるか17 いるいるか18 るいるか19 いるか20 るか21 か
39
接尾辞配列
• 接尾辞のポインタを
辞書順にソートした配列
• サイズ
n log n + n log |A| bits
• パタン Pの検索
O(|P| log n) time
6 いかいないかいるかいるいるいるか10 いかいるかいるいるいるか4 いないかいないかいるかいるいるいるか8 いないかいるかいるいるいるか15 いるいるいるか17 いるいるか19 いるか1 いるかいないかいないかいるかいるいるいるか12 いるかいるいるいるか21 か3 かいないかいないかいるかいるいるいるか7 かいないかいるかいるいるいるか14 かいるいるいるか11 かいるかいるいるいるか5 ないかいないかいるかいるいるいるか9 ないかいるかいるいるいるか16 るいるいるか18 るいるか20 るか2 るかいないかいないかいるかいるいるいるか13 るかいるいるいるか
SA
40
圧縮接尾辞配列 (CSA)
• SAの代わりに[i] = SA-1[SA[i]+1] を格納
• サイズ: O(n log |A|) bits
• パタン Pの検索: O(|P| log n) time 0 1 7 $
5 2 1 ababac$
6 3 3 abac$
7 4 5 ac$
3 5 2 babac$
4 6 4 bac$
1 7 6 c$
SA i
41
なぜ圧縮できるのか
• 接尾辞は辞書順に格納される
• 先頭の1文字を消しても辞書順は同じ
6 いかいないかいるかいるいるいるか10 いかいるかいるいるいるか4 いないかいないかいるかいるいるいるか8 いないかいるかいるいるいるか15 いるいるいるか17 いるいるか19 いるか1 いるかいないかいないかいるかいるいるいるか12 いるかいるいるいるか21 か3 かいないかいないかいるかいるいるいるか7 かいないかいるかいるいるいるか14 かいるいるいるか11 かいるかいるいるいるか5 ないかいないかいるかいるいるいるか9 ないかいるかいるいるいるか16 るいるいるか18 るいるか20 るか2 るかいないかいないかいるかいるいるいるか13 るかいるいるいるか
SA12
14
15
16
17
18
19
20
21
0
3
4
5
9
1
2
6
7
10
11
13
42
CSA の性質• i < jのとき T[SA[i]] T[SA[j]]
• i < jかつ T[SA[i]] = T[SA[j]] のとき
[i] < [j]
証明:T[SA[i]] = T[SA[j]] のとき, この接尾辞の辞書順は2文字目以降で決まる.
i < j より T[SA[i]+1..n] < T[SA[j]+1..n]
SA[i’] = SA[i]+1, SA[j’] = SA[j]+1 とすると, i’ < j’
つまり i’ =SA-1[SA[i]+1]=[i]<[j]=j’
0 1 7 $
5 2 1 ababac$
6 3 3 abac$
7 4 5 ac$
3 5 2 babac$
4 6 4 bac$
1 7 6 c$
SA i
43
の圧縮
• [i]を T[SA[i]] で分割
• 各 S(c) を符号化:
• 全体で
• H0 log (等号は p1 = p2 = …のとき)
=Ac c
cp
pH1
log0 ( :文字 cの出現確率)
log1
log1
log0 == cAc
c
Ac c
cp
pp
pH
( ) )(,]][[| cSnciSATicS c ===
bits log2
+
c
cn
nn
n
np c
c =
( )3log2 0 +
+ Hn
n
nn
c c
c
44
要素 SA[i]のアクセス方法
• iが log nの倍数のときに
SA[i] を格納
• k = 0; w = log n;
• while (i % w != 0)
– i = [i]; k++;
• return SA2[i / w] - k;
0 8
0 1 7 $
5 2 1 ababac$
6 3 3 abac$
7 4 5 ac$
3 5 2 babac$
4 6 4 bac$
1 7 6 c$
SA i
0 8
1 3
2 4
SA2
n = 8
w = 3
アクセス時間: 平均 O(log n) 時間
45
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
T E B D E B D D A D D E B E B D C
A B B B B C D D D D D D E E E E
10 8 9 11 13 15 1 6 7 12 14 16 2 3 4 5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
SA 8 14 5 2 12 16 7 15 6 9 3 10 13 4 1 11
テキストの部分的な復元
T[9..13] = DDEBEを復元する場合1. i=SA-1[9]=10 を求める2. 辞書順で i 番目の接尾辞の先頭の文字を求める3. i=10からをたどる 1 2 3 4 5
C A B C D E
46
圧縮接尾辞配列の機能• lookup(i): SA[i] を返す (O(log n) 時間)
• inverse(i): SA-1[i] を返す (O(log n) 時間)
• [i]: SA-1[SA[i]+1] を返す(O(1) 時間)
• substring(i,l): T[SA[i]..SA[i]+l-1]を返す
– O(l) 時間
– (iからT[SA[i] は長さ nのベクトルのrankで求まる)
R. Grossi and J. S. Vitter. Compressed Suffix Arrays and Suffix Trees with
Applications to Text Indexing and String Matching. SIAM Journal on Computing,
35(2):378–407, 2005.
Kunihiko Sadakane: New text indexing functionalities of the compressed suffix
arrays. J. Algorithms 48(2): 294-313 (2003).