在实施"搜索窗口"对于C中的快速动态时间扭曲,我需要构建一个表示具有非常特殊结构的稀疏二进制矩阵的结构。
这个矩阵对它有一些强烈的结构约束:具体来说,只有一个"运行"每行非零数据,尽管该运行长度可变。随着行的增加,起始单元格的列索引和结束单元格列索引的值单调增加:
示例有效矩阵(* =已填充,。=未填充)
0 1 2 3 4 5
0 * * * . . .
1 . * * * . .
2 . * * * . .
3 . . * * * *
4 . . * * * *
0 1 2 3 4 5
0 * * * * . .
1 . * * * * .
2 . . * * * .
3 . . . . * *
4 . . . . . *
无效矩阵示例:
0 1 2 3 4 5
0 * * * . * * <-- more than one continuous run
1 . * * * . .
2 . * * * . .
3 . . * * * *
4 . . * * * *
0 1 2 3 4 5
0 * * * . . .
1 . * * * . .
2 . * * * . .
3 * * * * * * <-- start index not monotonically increasing
4 . . * * * *
0 1 2 3 4 5
0 * * * . . .
1 . * * * * .
2 . * * * . . <-- end index not monotonically increasing
3 . . * * * *
4 . . * * * *
这些稀疏矩阵主要填充在对角线上,但它们不方形,所以我不知道我是否应该使用&#34;锯齿状对角存储&#34;。
我目前的方法是为每行存储(开始,结束)列索引:即
0 1 2 3 4 5
0 * * * . . .
1 . * * * . .
2 . * * * . .
3 . . * * * *
4 . . * * * *
(逻辑上)存储为</ p>
(0, 0) --> (0, 2)
(1, 1) --> (1, 3)
(2, 1) --> (2, 3)
(3, 2) --> (3, 5)
(4, 2) --> (4, 5)
(虽然这些内部存储为ravelled指数,即。)
(0 * num_cols + 0) --> (0 * num_cols + 2)
(1 * num_cols + 1) --> (1 * num_cols + 3)
所以最终的结构看起来像
[0, 2, 7, 9, 13, 15, 20, 23, 26, 29]
然后,这个结构是delta编码的
[first_value, offset_1, offset_2, ...]
[0, 2, 5, 2, 4, 2, 5, 3, 3, 3]
因为这些delta值很小且正面,我们可以利用它们将它们打包成VARINT结构的一些风格。
第一个问题:这些矩阵有一个众所周知的名字吗?似乎在文献中找不到多少。
第二个问题:这种存储方案是否利用了矩阵的所有强大属性?我可以滥用约束来以某种方式存储更少的数据吗?
我已经阅读了一些描述一般稀疏矩阵的稀疏矩阵存储的文档,但是我觉得这种特殊情况结构可能具有特殊情况下的最佳存储/编码方案。
答案 0 :(得分:1)
我认为您考虑绝对索引值(然后使用delta编码)的方法已经产生了良好的结果,但它没有使用单调递增的开始/结束索引约束。
考虑存储的存储结构 - 相对于绝对开始和结束索引 - 只有开始和结束索引的增量应该 - 平均 - 产生具有较小范围的数字(因此表示较短)。
将您的第一个样本翻译成此结构将如下所示:
(0/2) - (1/1)(0/0)(1/2)(0/0)
其中第一对(0/2)
表示绝对开始/结束 - 索引,其他对代表每行的开始和结束的增量。
由于这些数字使用较小的范围,因此可变长度整数编码应该产生更好的压缩。
例如,考虑以下(简单)整数编码:
0 .. 00
1 .. 01
2 .. 100
3 .. 101
4 .. 1100
5 .. 1101
6 and higher: 111 + 16 bit integer
使用此编码,第一个样本转换为包含22位的以下比特流:
00 100 01 01 00 00 01 100 00 00
这种方法效果越好,增量越小;当逐行考虑增量时,如果矩阵的行数多于列数,则应该是这种情况。
只是想要优化具有更多列而不是行的矩阵:可以想到使用相同的存储方法逐列;我认为(但没有数学证明)单次运行的逐行单调递增也意味着单次运行也会逐列单调递增。