逆转霍夫曼编码

时间:2015-07-22 07:03:58

标签: algorithm math

假设我有一组带有预定义二进制前缀代码的单词。给定一个非常大的随机二进制数据块,我可以使用前缀代码将这个块解析为单词。

我想确定,至少近似(对于非常大的长度的随机块)每个单词的命中数的期望值(在解码文本中提到的次数)。

乍一看,问题显得微不足道 - 每个字从随机比特池中扫描的概率完全取决于其长度(因为每个比特可以是0或1)。但我怀疑这是对上述问题的错误答案,因为单词的长度不同,因此这个概率与预期的命中数(除以数据块的长度)不一样。

UPD:有人问我(在下面的评论中)以数学方式陈述这个问题,所以就这样了。

w 成为仅使用0和1编写的单词列表(我们的字母只包含两个字母)。此外, w 中的任何字词都不是任何其他字词的前缀。因此, w 形成合法的二进制前缀代码。我想知道(至少近似)点击的平均值,对于 w 中的每个单词,对固定大小 n 的所有可能的二进制数据块进行平均。 n 可以非常大,比我们的任何长度都大得多。但是,单词的长度不同,这是不可忽视的。

我很感激任何试图解决这个问题的提法。

2 个答案:

答案 0 :(得分:1)

我的简短回答:可以为每个给定的单词列表计算预期的命中数(或者更确切地说是预期的命中比例)。

我不会描述完整的算法,但只是详细说明以下示例:让我们修复以下三个单词的非常简单的列表:010,{{1} }。

对于每个11,有n个不同的数据块,长度为2^n(我的意思是n位),每个数据块的概率相同n

第一个观察结果是,并非所有数据块都可以被精确解码 - 例如数据2^(-n),当您解码时,最终会保留一个0101

让我们写1表示可以精确解码的U(n)个数据块的数量,然后为其他数据写入n(即那些额外V(n)的数据块到底)。以下重现关系很明确:

  1. 1

  2. U(n) + V(n) = 2^n

  3. 初始值为V(n) = U(n - 1) = 1和U(0)

    然后一个简单的计算得出:

    V(0) = 0

    现在让U(n) = (2^(n + 1) + (- 1)^n) / 3(分别为A(n)B(n))为单词C(n)(resp。0上的点击次数总和, 10所有11个确切数据块的U(n)},a(n)(resp。b(n)c(n))与所有{{1}的总和相同不精确的数据块(在这种情况下,最后V(n)不计算)。

    然后我们有以下关系:

    1. 1a(n) = A(n - 1)b(n) = B(n - 1)
    2. c(n) = C(n - 1)
    3. A(n) = A(n - 1) + U(n - 1) + A(n - 2) + A(n - 2)
    4. B(n) = B(n - 1) + B(n - 2) + U(n - 2) + B(n - 2)
    5. 关系解释2 3 4:

      如果C(n) = C(n - 1) + C(n - 2) + C(n - 2) + U(n - 2)是长度为D的确切数据块,则有三种可能性:

      • nD结尾,删除此0会产生一个长度为0的确切数据块;

      • n - 1D结尾,删除此10会产生一个长度为10的确切数据块;

      • n - 2D结尾,删除此11会产生一个长度为11的确切数据块。

      因此,例如,当我们在n - 2的所有精确数据块中总结0的所有命中数时,这三种情况的贡献分别为n,{ {1}},A(n - 1) + U(n - 1)。同样,对于其他两个平等。

      现在,解决这些递归关系,我们得到:

      • A(n - 2)

      • A(n - 2)

      A(n) = 2/9 * n * 2^n + (smaller terms)以来,我们得出的结论是B(n) = C(n) = 1/9 * n * 2^n + (smaller terms)点击U(n) = 2/3 * 2^n + (smaller terms)次点击,n/3点击0次点击,n/6点击10

      请注意,如果我们同时考虑n/6不精确的数据块,则会保持相同的比例,因为11V(n)A(n),{{之间的关系1}}和B(n)C(n)U(n)a(n)

      此方法适用于任何单词列表。它与您使用动态编程解决此问题的想法相同 - 创建状态,查找递归关系,并建立转换矩阵。

      进一步

      我认为以下情况也可能如此,这将进一步简化答案。

      b(n),...,c(n)成为列表中的字词,让V(n),...,w_1成为他们的长度。

      对于每个w_k,让l_1成为l_k点击的比例,即i = 1, ..., k个数据块,a_i的预期点击次数是w_i

      然后,我的感觉(猜想)是n对于所有w_i是相同的,即如果一个单词比另一个单词长一点,则其命中数是该单词的一半。其他

      这个猜想,如果正确,可能不是很难证明。但我现在懒得思考......

      如果这是真的,那么我们可以很容易地计算出a_i * n + (smaller terms),因为我们有这样的身份:

      a_i * 2^(l_i)

      让我用上面的例子说明这一点。

      我们有ia_isum (a_i * l_i) = 1,因此w_1 = 0w_2 = 10

      根据猜想,我们应该w_3 = 11。因此l_1 = 1l_2 = l_3 = 2。上述平等成为:

      a_1 = 2 * a_2 = 2 * a_3

      因此a_2 = a_3 = x,我们有a_1 = 2x2x * 1 + x * 2 + x * 2 = 1,可以通过上述计算进行验证。

答案 1 :(得分:0)

让我们制作一个可以识别单词的简单机器:每个单词具有接受状态的DFA。要构造此DFA,请从二叉树开始,每个左子边标记为0,每个右子边标记为1.每个叶子都是一个单词接受者(如果到树下的那条叶子的路径是单词& #39; s拼写)或垃圾(一串字母不是任何有效单词的前缀)。我们连线"重启"叶子的边缘回到树的根部*。

如果我们有一个无限长度的字符串,让我们找出匹配每个单词的频率。为此,将DFA的图形视为马尔可夫状态转换图,将起始状态初始化为概率为1的根并且所有其他状态为0,并找到稳态分布(通过查找转换的主要特征向量)图表的相应矩阵)。

我们的字符串不是无限长。但由于n很大,我期待"边缘效应"无所谓。我们可以通过逐字取匹配并乘以n来近似匹配频率。如果我们想要更精确,而不是采用特征向量,我们可以将转移矩阵转换为 n 次幂并将其与起始分布相乘以得到n个字母后的结果分布。

*这不是很精确,因为这个马尔可夫系统会在根部花费一些非零的时间,当识别一个单词或跳过垃圾后,它应该立即转到0孩子或1个孩子,这取决于。所以我们实际上并没有连接我们的'#34;重启"到根的边:从接受字的节点,我们连接两个重启边(一个到0子,一个到子的1子);我们将具有边缘的左子节点的垃圾节点替换为0子节点;并且我们将具有边缘的右边儿童的垃圾节点替换为1个孩子。事实上,如果我们将初始状态设置为0,概率为0.5,概率为0.5,则我们甚至不需要根。

编辑:要使用@ WhatsUp的示例,我们从DFA开始,如下所示:

DFA for WhatsUp example set of words

在接受一个单词并取消根节点后,我们重新启动它以重新启动:

enter image description here

相应的马尔可夫转移矩阵是:

0.5    0  0.5  0.5
0.5    0  0.5  0.5
  0  0.5    0    0
  0  0.5    0    0

其第一个特征向量是:

0.333
0.333
0.167
0.167

也就是说它在0节点中占1/3,在10中占1/3,在10中占1/6,在1/6中占用1/6。这与@ WhatsUp'这个例子的结果。