通过实验,掌握索引压缩的可变字节码VB的编码和解码算法。
检索系统中的倒排记录表所占空间巨大,因此索引压缩非常关键,可变字节码VB编码利用整数个字节对间距编码和解码,能够在时间和空间上达到一个非常好的平衡点。本实验通过编程实现这个VB的编码和解码过程。
通过编写编码辅助函数、编码函数、解码函数、间距计算函数和计算倒排记录表函数实现VB的编码和解码过程。当用户输入原始倒排记录表后,系统可以计算输出间距记录表、可变字节码,并通过解码函数对可变字节码进行解码得到原始倒排记录表。
分为编码模块与解码模块两个功能模块。
VBEncodeNumber是编码辅助函数,主要用于倒排记录表的切分与二进制的转换,通过bin函数实现十进制到二进制转换,然后通过字符串的replace函数实现可变字节码末位前缀与其它位的不同。
def VBEncodeNumber(n):
by, byte = '', []
while True:
byte.insert(0, n % 128 + 128)
if n < 128:
break
n = n // 128
for i in range(len(byte)):
if i < len(byte) - 1:
by += bin(byte[i]).replace('0b1', '0') + ' '
else:
by += bin(byte[i]).replace('0b', '')
return by
VBEncode实现倒排记录表的循环与VBEncodeNumber的调用。
def VBEncode(numbers):
bytestream = []
for n in numbers:
byte = VBEncodeNumber(n)
bytestream.append(byte)
return bytestream
VBDecode是解码模块。用于通过可变字节码计算间距表,计算过程中需注意可变字节码末尾前缀的不同,计算结束后通过Countdaopai函数得到原始倒排记录表。
def VBDecode(bytestream):
numbers = []
n = 0
for i in range(len(bytestream)):
byte = bytestream[i].split(' ')
l = len(byte)
for j in range(l):
if j < 1 - 1:
by = int('0b1' + byte[j][1: len(byte[j])], 2)
else:
by = int('0b' + byte[j], 2)
n = 128*n + by if by < 128 else 128*(n - 1) + by
numbers.append(n)
n = 0
return numbers
Countdaopaidis是倒排记录表间距函数,用于计算原始倒排记录表的间距表。
def countdaopaidis(daopai):
daopaidis = daopai.copy()
for i in range(len(daopai)):
if i == 0:
daopaidis[i] = daopai[i]
else:
daopaidis[i] = daopai[i] - daopai[i - 1]
return daopaidis
Countdaopai为计算倒排记录表函数,用于通过间距表计算得到倒排记录表。
def countdaopai(daopaidis):
daopai = daopaidis.copy()
for i in range(len(daopaidis)):
daopai[i] = sum(daopaidis[0: i + 1])
return daopai
daopai = [777, 17743, 294068, 31251336]
print('原始倒排记录表为:\n', daopai, '\n')
daopaidis = countdaopaidis(daopai)
print('间距记录表为:\n', daopaidis, '\n')
bytestream = VBEncode(daopaidis)
print('可变字节码为:\n', bytestream, '\n')
daopaidis = VBDecode(bytestream)
daopai = countdaopai(daopaidis)
print('解码得到的倒排记录表为:\n', daopai, '\n')
运行程序,原始倒排记录表为[777,17743,294068,31251336],得到结果如下图。
通过结果图可以看出解码得到的倒排记录表与原始倒排记录表相同,观察可变字节码,最后一位首位数字为1,其它位首位数字为0。
在程序调试过程中,设置原始倒排记录表为[121, 456, 728, 879]。