Fluent Bit 集成指南:Ripser 高效 Vietoris–Rips 持续同调条形码计算库
2026/9/18 10:28:48 网站建设 项目流程

Fluent Bit 集成指南:Ripser 高效 Vietoris–Rips 持续同调条形码计算库

【免费下载链接】fluent-bitFast and Lightweight Logs, Metrics and Traces processor for Linux, BSD, OSX and Windows项目地址: https://gitcode.com/GitHub_Trending/fl/fluent-bit

导读

Ripser 是一个精简的 C++ 实现,专门用于计算 Vietoris–Rips 持续同调条形码(persistence barcodes),以"只做一件事但做到极致"著称。本文以仓库内 lib/ripser-1.2.1/README.md 为主线,完整讲解它的输入格式、命令行选项、编译期宏与核心算法原理,并结合 Fluent Bit 仓库中的实际集成(src/ripser/flb_ripser_wrapper.cppplugins/processor_tda插件)展示它如何被用于拓扑数据分析(TDA)。读完本文,你将掌握 Ripser 的独立构建、运行与参数调优方法,并理解它在 Fluent Bit 中如何驱动 TDA 处理器输出 Betti 数指标。

Ripser 是什么:定位与设计哲学

Ripser 由 Ulrich Bauer 开发(© 2015–2021),核心代码位于 lib/ripser-1.2.1/ripser.cpp(连同内部头文件 lib/ripser-1.2.1/ripser_internal.hpp 构成完整实现)。它的定位非常纯粹:只计算 Vietoris–Rips 持续同调条形码,但在这件事上做得非常出色

README 中列出的主要特性:

  • 时间与内存双高效:通过持续上同调(persistent cohomology)等技巧大幅降低资源占用;
  • 代码极简:整个核心实现仅约 1000 行代码,位于单个 C++ 文件中;
  • 支持素数有限域系数(编译期启用);
  • 无外部依赖(可选支持 Google sparsehash,或 Martin Ankerl 的 robin hood hashmap)。

说明:README 声称 Ripser 在计算时间上比其他实现(Dionysus、DIPHA、GUDHI、Perseus、PHAT)快一个数量级以上(>40 倍)、内存效率高 15 倍以上(针对 live.ripser.org 的示例),并特别注明 PHAT 本身不包含生成 Vietoris–Rips 过滤的代码。这是上游文档的陈述,具体到不同数据集上的表现仍需自行验证。

核心概念:Vietoris–Rips 复形与持续同调

要理解 Ripser 的输出,需要先厘清两个概念:

  • Vietoris–Rips 复形:给定一组点及两两距离,固定一个直径阈值t,当两个点距离 ≤t时连边,进而张成单纯复形。随着t从 0 增长到无穷,复形不断生长,形成一个过滤(filtration)。
  • 持续同调(persistent homology):跟踪该过滤过程中各维度的拓扑特征(连通分量、环、空洞等)何时"出生"(birth)与"消亡"(death),从而得到一系列区间(interval),即条形码(barcode)或持续对(persistence pair)。

Ripser 的输出正是这些持续对——(birth, death)二元组。当某个特征在阈值达到无穷时仍未消亡(即"本质同调类",essential homology class),其 death 记为无穷。

支持的输入格式与示例数据

Ripser 支持 7 种输入格式,仓库 lib/ripser-1.2.1/examples/ 提供了多种格式的实测样例数据:

格式说明仓库内示例
lower-distance下三角距离矩阵,逗号(或空白/其他非数字字符)分隔对角线下方的条目,按行索引、再列索引的字典序排列sphere_3_192.lower_distance_matrix、projective_plane.lower_distance_matrix、random16.lower_distance_matrix、random20.lower_distance_matrix
upper-distance上三角距离矩阵,适合 MATLABpdist/seqpdist导出到 CSV 的输出rp2_600.lower_distance_matrix.csv(CSV 类数据)
distance(默认)完整距离矩阵,每行对应矩阵的一行;实际只读取对角线以下部分可由 pointsCycloOctane.csv 等点云数据推算
diphaDIPHA 距离矩阵数据格式projective_plane.dipha
point-cloud点云,每行一个点,坐标为逗号(或空白等)分隔的欧氏空间坐标pointsCycloOctane.csv、projective_plane.csv、o3_1024.txt 等
binary二进制下三角距离矩阵,32 位浮点(IEEE 754 单精度、小端)序列
sparse稀疏三元组格式,每行一个条目i j d(i,j),表示点 i 与点 j 的距离;每对点至多出现一次

构建与运行

独立构建(Makefile)

Ripser 仅需支持 C++11 的编译器。仓库内 lib/ripser-1.2.1/Makefile 提供了三个构建目标:

make # 默认:带 -O3 -D NDEBUG 的 ripser make all # 依次构建 ripser、ripser-coeff(启用 USE_COEFFICIENTS)、ripser-debug(带 -g 调试符号) make clean # 清理三个产物

各目标的实际编译命令(见 Makefile):

c++ -std=c++11 -Wall ripser.cpp -o ripser -O3 -D NDEBUG c++ -std=c++11 -Wall ripser.cpp -o ripser-coeff -O3 -D NDEBUG -D USE_COEFFICIENTS c++ -std=c++11 -Wall ripser.cpp -o ripser-debug -g

构建后即可运行,输入既可以是命令行参数指定的文件,也可以通过 stdin 传入。README 中的标准示例(以球面点云距离矩阵为例):

./ripser examples/sphere_3_192.lower_distance_matrix

CMake 静态库构建

仓库还提供了 lib/ripser-1.2.1/CMakeLists.txt,将ripser.cpp编译为静态库ripser-static(同时指定 C++11 标准,并把仓库目录加入公共 include 路径,使ripser_internal.hpp可被外部引用)。Fluent Bit 正是通过这条路径把 Ripser 集成进构建系统的。

命令行选项详解

Ripser 支持以下命令行参数:

  • --format <fmt>:指定输入格式,取值与上文输入格式表格一一对应:
    • lower-distance:下三角距离矩阵;
    • upper-distance:上三角距离矩阵(MATLABpdist/seqpdist导出的 CSV);
    • distance未指定格式时的默认值):完整距离矩阵,只读取对角线以下部分;
    • dipha:DIPHA 距离矩阵;
    • point-cloud:欧氏空间点云,每行一个点;
    • binary:32 位浮点(IEEE 754 单精度、小端)下三角矩阵的二进制序列;
    • sparse:稀疏三元组格式i j d(i,j),每对点至多出现一次。
  • --dim k:计算最高至维数k的持续同调。
  • --threshold t:计算直径至t的 Rips 复形。若不指定阈值,Ripser 会选择外接半径(enclosing radius)作为阈值——在此阈值之后同调必然平凡(该思路由 Greg Henselman-Petrusek 提出,见其 Eirene.jl 项目)。
  • --modulus p:在素数域 Z/pZ 上计算系数同调(仅在编译时启用USE_COEFFICIENTS后可用)。
  • --ratio r:仅输出 death/birth 比值 >r的持续对。

编译期选项(预处理宏)

编译期宏在 lib/ripser-1.2.1/ripser.cpp 顶部以注释形式列出,通过#define或在编译命令行传入-D开关启用:

作用默认状态
USE_COEFFICIENTS启用素数有限域系数支持(配合--modulus注释关闭
INDICATE_PROGRESS在控制台指示当前计算进度注释关闭
PRINT_PERSISTENCE_PAIRS输出计算得到的持续对默认开启(注释掉以禁用)
USE_ROBINHOOD_HASHMAP启用 Martin Ankerl 的 robin hood hashmap,可进一步降低内存占用注释关闭

README 给出的手动编译示例(启用 robin hood hashmap):

c++ -std=c++11 ripser.cpp -o ripser -O3 -D NDEBUG -D USE_ROBINHOOD_HASHMAP

从源码看,哈希表的选择在 ripser.cpp 通过hash_map/hash模板别名统一抽象:启用USE_ROBINHOOD_HASHMAP时使用robin_hood::unordered_map,否则回退到std::unordered_map。此外,源码中还有num_coefficient_bits = 8max_simplex_index的设计(ripser.cpp),用于在启用系数时对单纯形索引做溢出检查——这也是USE_COEFFICIENTS会占用部分索引位宽的原因。

效率背后的四个关键原理

Ripser 的高效并非偶然,README 明确指出它建立在四项核心原理之上(均引用自计算拓扑领域的前人工作):

  1. 计算持续上同调(persistent cohomology):由 Vin de Silva、Dmitriy Morozov 与 Mikael Vejdemo-Johansson 提出,相比同调计算通常更节省内存;
  2. 利用"边界是圈"的链复形性质:采用clearing优化(又称 "persistence with a twist",由 Chao Chen 与 Michael Kerber 提出),避免重复消元;
  3. 默认阈值取外接半径:未指定--threshold时,选取保证同调平凡的外接半径作为阈值,避免无谓的过大过滤;
  4. 不存储可随时重算的信息:特别是原始矩阵与约简后的边界矩阵都不保留;
  5. 利用计算捷径apparentemergent persistence pairs的快速判定。

这些原理共同保证了时间和内存的双重高效。从实现结构看,核心计算逻辑被抽取到 ripser_internal.hpp,其中定义了compressed_lower_distance_matrix/compressed_upper_distance_matrix两种压缩距离矩阵类型(ripser_internal.hpp)、供调用方注册的interval_recorder回调结构(ripser_internal.hpp),以及统一的入口函数ripser_run_from_compressed_lower(ripser_internal.hpp)。距离矩阵的存取抽象与回调式的区间输出设计,为上层集成(如 Fluent Bit)提供了干净的调用接口。

Fluent Bit 中的集成:从 CLI 工具到处理器插件

Ripser 在 Fluent Bit 中并非以独立 CLI 形式存在,而是被封装为静态库并服务于processor_tda拓扑数据分析插件。整条集成链路清晰可循:

  1. 上游核心库:lib/ripser-1.2.1/CMakeLists.txt 把ripser.cpp编译为ripser-static
  2. C 桥接层:src/ripser/flb_ripser_wrapper.cpp 将 C++ 接口封装为 C ABI,src/ripser/CMakeLists.txt 将其编译为flb-ripser-wrapper-static并链接ripser-static。桥接层暴露两个核心 API:
    • flb_ripser_compute_betti_from_dense_distance(flb_ripser_wrapper.cpp):输入稠密距离矩阵,输出各维 Betti 数;
    • flb_ripser_compute_intervals_from_dense_distance(flb_ripser_wrapper.cpp):输入稠密距离矩阵,通过回调逐条输出持续区间(dim, birth, death)
    • 两者都把稠密矩阵转换为compressed_lower_distance_matrixmake_compressed_from_dense,flb_ripser_wrapper.cpp),然后调用ripser_run_from_compressed_lowerthreshold ≤ 0 时传入numeric_limits<value_t>::max(),等价于 README 所述的"外接半径自动模式"
  3. TDA 处理器插件:plugins/processor_tda/tda.c 中的tda_window_run_ripser(tda.c)把 cmetrics 指标快照做延迟嵌入(delay embedding)后构造成欧氏距离矩阵,再调用 wrapper 计算 Betti 数(betti0/betti1/betti2),并以 gauge 形式输出(ensure_betti_gauges,tda.c)。plugins/processor_tda/CMakeLists.txt 中可见target_link_libraries(flb-plugin-processor_tda ripser-static flb-ripser-wrapper-static),印证了这条依赖链。

从源码结构可以推断:Fluent Bit 复用了 Ripser 上游的ripser.cpp(含 2025 年 Fluent Bit Authors 的修改),将"计算持续同调"这一能力嵌入到指标处理器中,用于检测监控指标时间序列中的拓扑结构变化。

实验性特性(独立分支)

除主线功能外,README 还列出了三个实验性特性,它们以独立分支形式提供:

  • representative-cocycles:输出持续上同调的代表上闭链(representative cocycles);
  • representative-cycles:计算并输出持续同调的代表圈(representative cycles)——注意标准版本只计算圈(cocycles);
  • simple:精简版 Ripser,不支持稀疏距离矩阵与系数,可作为阅读源码的入门起点。

引用与许可证

如果你在研究中使用了 Ripser,README 提供了如下 BibTeX 条目:

@misc{1908.02518, Author = {Ulrich Bauer}, Title = {Ripser: efficient computation of Vietoris-Rips persistence barcodes}, Month = Feb, Year = {2021}, Eprint = {1908.02518v2}, Note = {Preprint} }

许可证方面,Ripser 采用 MIT 许可证(lib/ripser-1.2.1/COPYING.txt),并附加一条条款(lib/ripser-1.2.1/CONTRIBUTING.txt)说明:若无另行签署书面许可协议,对外发布的修改版本自动授予非独占、免版税、永久的安装、使用、修改、衍生、分发与再许可权利。Fluent Bit 集成的ripser.cpp头部同时保留了两者版权声明(Ulrich Bauer 2015–2021 与 The Fluent Bit Authors 2025)。如需在其他软件中以不同许可证使用 Ripser,请与作者联系。

小结

Ripser 以约千行代码实现了业界领先的 Vietoris–Rips 持续同调条形码计算:7 种输入格式、5 个命令行选项、4 个编译期宏,配合上同调、clearing、外接半径与 apparent/emergent pair 等算法原理,构成了一个"小而精"的计算几何利器。在 Fluent Bit 仓库中,它被桥接为 C API 并服务于 TDA 处理器插件,把持续同调能力从独立的 CLI 工具延伸到了实时的指标监控场景,这也是阅读 lib/ripser-1.2.1/README.md 之外、深入源码后最值得关注的集成路径。

【免费下载链接】fluent-bitFast and Lightweight Logs, Metrics and Traces processor for Linux, BSD, OSX and Windows项目地址: https://gitcode.com/GitHub_Trending/fl/fluent-bit

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询