# succinct # rank # unsigned-integer # select # constant-time

wavelet-matrix

小波矩阵实现。支持对大量符号或整数进行各种近似 O(1) 查询。

9 个不稳定版本 (3 个破坏性更新)

使用旧的 Rust 2015

0.4.7 2017年12月21日
0.4.6 2017年12月21日
0.4.3 2017年11月16日
0.3.0 2017年10月31日
0.1.0 2017年10月29日

#1078 in 数据结构


3 个crate中使用(通过 kmerutils

MIT 许可证

70KB
1K SLoC

Rust 语言的小波矩阵

Build Status

它在常数时间内提供了对非常大的无符号整数序列的各种分析。

使用方法

在Cargo.toml中添加后,将此行添加到lib.rs或main.rs中。

extern crate wavelet_matrix;

查看crate文档顶部以获取更多示例。

基准测试

功能

给定一个无符号整数序列 T,它提供以下查询。

基本操作

  • .len():
    • 返回 T 的长度。
    • 几乎没有开销,只是返回存储的值。
  • .lookup(pos):
    • 返回 T 位置处的值,T[pos]
    • 比数组查找慢,但仍然是 O(1)。您可能想保存原始 Vector 以加快查找速度。

计数

计数在 O(1) 内完成。

  • .count(start..end,value):
    • 返回满足 e == value 且包含在 T[start..end] 的元素 e 的数量
  • .count_prefix(start..end,value,ignore_bit):
    • 返回满足 e >> ignore_bit == value >> ignore_bit 且包含在 T[start..end] 的元素 e 的数量
    • 这可以用来统计满足诸如 192.168.10.0/24 这样的 IPv4 前缀的 IPv4 地址的数量。在这种情况下,ignore_bit 将是 8。
  • .count_lt(start..end,value):
    • 返回满足条件 e < value 的元素 e 的数量,该条件包含在 T[start..end] 中。
  • .count_gt(start..end,value):
    • 返回满足条件 e > value 的元素 e 的数量,该条件包含在 T[start..end] 中。
  • .count_range(start..end,val_start..val_end):
    • 返回满足条件 val_start <= e < val_end 的元素 e 的数量,该条件包含在 T[start..end] 中。

搜索

每次搜索的索引的时间复杂度为 O(1)。

  • .search(start..end,value):
    • 返回一个迭代器,该迭代器找到满足条件 e == value 的元素 e 的索引,该条件包含在 T[start..end] 中。
  • .search_prefix(start..end,value,ignore_bit):
    • 返回一个迭代器,该迭代器找到满足条件 e >> ignore_bit == value >> ignore_bit 的元素 e 的索引,该条件包含在 T[start..end] 中。
  • [待办] 实现除等于之外的各种条件。

排名

与元素数量 n 相关的排名操作大致为 O(1)。

  • .max_k(start..end,val_start..val_end,k):
    • 按降序列出 (value, count) 对。
    • 值被限制在范围 val_start..val_end 内。
  • .min_k(start..end,val_start..val_end,k):
    • 按升序列出 (value, count) 对。
    • 值被限制在范围 val_start..val_end 内。

.top_k() 在最佳情况下也以 O(1) 的速度执行,但在最坏情况下(每个值只出现一次)可能需要 O(n)!

  • .top_k(start..end,val_start..val_end,k):
    • 按最频繁出现顺序列出 (value, count) 对。
    • 值被限制在范围 val_start..val_end 内。
    • [待办] 明确相同计数的顺序。

为了在不考虑唯一值数量的情况下实现 O(1) 性能,请使用 .top_k_ranges()

  • [实验性] .top_k_ranges(start..end, val_start..val_end, k)
    • 按最频繁出现顺序列出 (v_start..v_end, count) 对。
    • .top_k() 不同,.top_k_ranges() 返回包含所有值的完整范围集。
    • 值被限制在范围 val_start..val_end 内。
    • [待办] 明确相同计数的顺序。

统计

O(1) 中位数 / O(1) 分位数

  • .median(start..end):
    • T[start..end] 返回中位数。
    • .quantile(start..end, start + (end - start) / 2) 相同。
  • .quantile(start..end,k):
    • T[start..end] 返回第 (k+1) 个最小值。

O(1) 求和 / O(1) 平均值 / O(1) 方差

实验 1

这些方法使用 .top_k_ranges() 来枚举最相关的值范围。

它们不如实验 2 中的方法准确。

  • [实验性] .sum_experiment1(start..end, val_start..val_end, k)
    • 使用最多 k 个小波树节点来近似计算 T[start..end] 的总和。
    • 仅处理包含在范围 val_start..val_end 内的值。
    • 要得到精确结果,指定 k = m + 1,其中 m 是唯一值的数量。
  • [实验性] .mean_experiment1(start..end, val_start..val_end, k)
    • 使用最多 k 个小波树节点来近似计算 T[start..end] 的平均值。
    • 仅处理包含在范围 val_start..val_end 内的值。
    • 要得到精确结果,指定 k = m + 1,其中 m 是唯一值的数量。
  • [实验性] .variance_experiment1(start..end, val_start..val_end, k)
    • 使用最多 k 个小波树节点来近似计算 T[start..end] 的方差。
    • 仅处理包含在范围 val_start..val_end 内的值。
    • 要得到精确结果,指定 k = m + 1,其中 m 是唯一值的数量。
实验 2

比实验 1 有所改进。它们使用自定义节点枚举器来最小化误差。

  • [实验性] .sum_experiment2(start..end, val_start..val_end, k)
实验 3

比实验 2 有所改进。它们使用 Range<u64> 来表示计算值的精确度。

  • [实验性] .sum_experiment3(start..end, val_start..val_end, k)

经典小波矩阵操作

  • .rank(pos, value):计算包含在 T[0..pos] 中的值数量。
    • 注意:pos是排他的。当pos为0时,.rank()总是返回0。
  • .select(rank, value):返回第(rank+1)个值的索引
    • 注意:如果没有找到,则返回.len()而不是None。

版本发布

v0.4.7

  • 修复测试错误#4
  • 修复测试错误#3

v0.4.6

  • 添加对.median().quantile()的测试。
  • 添加索引范围检查。

v0.4.5

  • 修复依赖项错误。

v0.4.4

  • 添加.median().quantile()。它们非常快,在16位值上只需3-5微秒。
  • 添加.top_k_ranges(),它在最坏情况下比.top_k()更快。
  • 添加.sum_experiment1().mean_experiment1().variance_experiment1()
  • 添加.sum_experiment2()
  • 添加.sum_experiment3()
  • 添加BENCH.md基准测试报告。
  • 添加BENCH_SUM.md基准测试报告。

v0.4.3

  • 添加.bit_len()
  • 添加.dim()
  • 将示例移动到crate文档顶部。
  • 添加对.top_k().max_k()min_k()的测试。
  • 抑制警告。

v0.4.2

  • 添加.top_k().max_k()min_k()

v0.4.1

  • 添加 .search().search_prefix()

v0.4.0

  • 添加 .count().count_prefix().count_lt().count_gt().count_range()
  • [不兼容] WaveletMatrix::new() 现在接受 &Vec<u64>,而不是 Vec<u64>

v0.3.0

  • [不兼容] .select() 现在返回 .len() 而不是 None。

待办事项

  • 添加基准测试。

    • 使用简单算法实现相同的查询。
    • 比较 wm 的查询与简单算法的查询。
    • 制作一个漂亮的图表。
  • 性能分析

  • 优化底层的 rsdic 结构。

  • 添加 travis CI。

  • 添加 u128 支持或任意长度整数支持

  • 地球上最快的实现

致谢

依赖项

~445KB