开始的时候我们使用的Protégé运行的推理机发现
这里无法构建个体
然后转向用代码来实现效果上的对比。
FaCT++ vs HermiT 推理机对比测试报告 (Maven 版)
本报告基于 OWL API 5.1.20 + JFact 5.0.3 (FaCT++ 的纯 Java 移植版) + HermiT 1.4.3.517 在 Windows 10 (JDK 17) + Maven 3.9.9 下的实测结果。
项目通过 [pom.xml](file:///e:/ccks/reasoner/pom.xml) 管理依赖,测试代码: [src/main/java/Test.java](file:///e:/ccks/reasoner/src/main/java/Test.java),原始数据: [test_output.txt](file:///e:/ccks/reasoner/test_output.txt)。
1. 测试目的
验证两套 OWL 2 DL 推理机(JFact 替代原 FaCT++、HermiT)能否在本机 Maven 环境正常加载、初始化并完成推理;
在多种 OWL 2 特性与典型本体上,对比二者的功能正确性 与性能差异 ;
为本项目(CCKS 知识图谱推理)选定合适的推理机后端提供数据依据;
探索使用 Maven 替代手动 lib/ 依赖管理的可行性。
2. 测试环境
项目
版本/配置
操作系统
Windows 10 (64-bit)
JDK
OpenJDK 17.0.12 (64-bit, Microsoft)
构建工具
Apache Maven 3.9.9 (本地解压于 apache-maven-3.9.9/)
OWL API
5.1.20 (net.sourceforge.owlapi:owlapi-distribution:5.1.20)
JFact (FaCT++ 纯 Java 移植)
5.0.3 (net.sourceforge.owlapi:jfact:5.0.3)
HermiT
1.4.3.517 (net.sourceforge.owlapi:org.semanticweb.hermit:1.4.3.517)
测试本体
自构造 8 个小型 OWL 本体 + [pizza.owl (939 axioms)](file:///e:/ccks/reasoner/ontologies/pizza.owl) + [families.owl (9 axioms)](file:///e:/ccks/reasoner/ontologies/families.owl)
2.1 Maven 项目结构
1 2 3 4 5 6 7 8 9 10 11 12 reasoner/ ├── pom.xml # Maven 配置 (OWL API 5.1.20 + JFact 5.0.3 + HermiT 1.4.3.517) ├── src/main/java/Test.java # 8 组测试 (T1-T8) ├── ontologies/ │ ├── pizza.owl # 939 axioms (大本体基准) │ └── families.owl # 9 axioms (含实例的真实本体) ├── target/ │ ├── OWLReasonerTest-1.0-SNAPSHOT.jar # 构建产物 │ ├── classes/ # 编译输出 │ └── lib/ # maven-dependency-plugin 复制出来的所有依赖 ├── test_output.txt # 完整运行日志 (UTF-8) └── reasoner_comparison_report.md # 本报告
2.2 复现命令
1 2 3 4 5 mvn package -DskipTests java -Dfile.encoding=UTF-8 -cp "target\classes;target\lib\*" Test
Maven 版本调整说明 :原始 [pom.xml](file:///e:/ccks/reasoner/pom.xml) 中指定的 org.semanticweb.hermit:hermit:1.4.3.519 在 Maven Central 不存在,已替换为同 group 下 net.sourceforge.owlapi:org.semanticweb.hermit:1.4.3.517(OWL API 官方维护的坐标)。net.sourceforge.jfact:jfact:4.0.4 也已修正为 net.sourceforge.owlapi:jfact:5.0.3(更新、纯 Java、OWL API 5 兼容)。
3. 推理机简介
维度
JFact (原 FaCT++ 移植)
HermiT
实现语言
纯 Java (FaCT++ 的 1:1 移植)
纯 Java
作者
Ignazio Palmisano, Dmitry Tsarkov (Univ. of Manchester)
Boris Motik, Ian Horrocks (Univ. of Oxford)
支持语言
OWL 2 DL (SROIQ)
OWL 2 DL (SROIQ)
推理算法
Tableau + 优化 (内部缓存、可重用的分类结果)
Hypertableau + 多种 Blocking 策略 (Single/Pairwise/Direct)
部署依赖
无需 JNI ,单 jar 即可运行;跨平台 (Win/Linux/macOS)
无原生库,复制 jar 即可运行
性能
启动开销小,大本体分类显著更快
启动稍慢,JIT 预热后小任务也很快
许可
LGPL 2.1 (开源)
LGPL 3.0 (开源)
与 OWL API 集成
官方维护 (net.sourceforge.owlapi:jfact:5.0.3)
官方维护 (net.sourceforge.owlapi:org.semanticweb.hermit)
与原 FaCT++ 关系
共享内核设计,无 DIG 接口与命令行工具
与原 FaCT++ 是不同实现路径
关于 FaCT++ → JFact 的迁移 :原项目使用的 FaCTpp-OWLAPI-4.x-v1.6.5.jar + FaCTPlusPlusJNI.dll 需在每台目标机器上提供对应位数的 JNI 动态库,部署/打包/CI 都不友好。JFact 是 FaCT++ 的官方 Java 移植版 ,内核设计一致但用 Java 重写,无 JNI 依赖,OWL API 5 兼容性更好。本测试已完全迁移到 JFact。
4. 测试场景 (8 组)
场景 ID
名称
目的
T1
基础一致性 + 简单分类
验证 isConsistent() 与 getSubClasses 基础能力
T2
不一致本体处理
验证两个相互 disjoint 的类 + 同一实例时的检测
T3
实例检索 (Realization)
验证 getInstances 直接/间接/分层检索
T4
复杂 OWL 2 特性
嵌套等价类、逆属性、存在量化、子类蕴含
T5
性能基准 (小型)
同一任务单次执行耗时
T5b
性能基准 (5 次平均)
排除冷启动噪声的稳态耗时
T6
大本体 (pizza.owl)
939 axioms,分类/一致性耗时
T7
角色层次 + 传递性
hasParent ⊑ hasAncestor + Transitive(hasAncestor) 推断
T8
真实本体 (families.owl)
含实例的小型真实本体
5. 关键结论一览
维度
结论
功能正确性
✅ 两者在全部 8 个测试场景的逻辑结果完全一致 。一致性、分类、实例检索、蕴含、传递性全部相同。
性能 (小本体)
几乎无差异,均 < 1ms
性能 (大本体)
⚡ JFact 显著领先 。pizza.owl (939 公理) 分类耗时:HermiT ≈ 475ms vs JFact ≈ 222ms (≈ 2.1×)
启动开销
JFact 实例化更快(HermiT 单例含 Blocking 策略等额外初始化)
部署友好度
二者现在完全平手 (均为纯 Java + Maven 单坐标依赖);消除了旧版 FaCT++ 的 JNI 痛点
维护性
二者均被 OWL API 官方团队 (net.sourceforge.owlapi) 维护,版本号与 OWL API 主版本对齐
推荐场景
JFact 适合大批量/大本体分类;HermiT 在实例检索和反例生成场景同样成熟
6. 详细测试结果
T1 — 基础一致性 + 分类 (3 个类 A ⊑ B ⊑ C)
指标
HermiT
JFact
一致性
true
true
子类数 (直接)
1
1
分类耗时 ms
5
7
创建推理机耗时ms
97
38
✅ 两者结果一致,JFact 创建推理机更快。
T2 — 不一致本体 (Person ⊓ Dog, 同一实例 John)
指标
HermiT
JFact
一致性
false
false
错误
null
null
创建推理机耗时ms
4
1
✅ 两者均正确检测出本体不一致。
T3 — 实例检索 (8 个个体,4 个 Student、4 个 Teacher;Student ⊑ Person, Teacher ⊑ Person)
指标
HermiT
JFact
Person 间接实例数
8
8
Person 直接实例数
0 (均为 Student/Teacher 直接类型)
0
Student 实例数
4
4
Teacher 实例数
4
4
完整列表 (按名排序)
[Alice, Bob, Carol, Dave, Eve, Frank, Gina, Hank]
[Alice, Bob, Carol, Dave, Eve, Frank, Gina, Hank]
创建推理机耗时ms
2
0
✅ 两者结果完全一致。
T4 — 复杂 OWL 2 特性 (Animal ≡ Mammal ⊔ Pet,Pet ⊑ ∃hasOwner.Thing,hasOwner / hasPet 互逆)
指标
HermiT
JFact
一致性
true
true
Animal 等价类节点大小
1
1
Pet 等价类节点大小
1
1
Pet ⊑ ∃hasOwner.Thing 是否蕴含
true
true
创建推理机耗时ms
8
2
✅ 两者在嵌套等价类 + 逆属性 + 存在量化下结果完全一致。
T5 — 性能基准 (小型本体,单次)
指标
HermiT
JFact
创建推理机耗时ms
2
0
综合推理耗时ms
0
0
小本体下两者都 < 1ms,无法体现差距。详见 T5b 与 T6。
T5b — 性能基准 (小型本体,5 次平均)
指标
HermiT
JFact
创建推理机耗时ms
2
0
综合推理平均耗时ms
0
0
同样 < 1ms,无法体现差距。
T6 — 大本体 (pizza.owl, 939 axioms) ⭐ 最显著的差异
指标
HermiT
JFact
备注
一致性
true
true
一致
一致性耗时ms
1
83
HermiT 一致性检查更快
分类耗时ms
475
222
⚡ JFact 比 HermiT 分类快约 2.1 倍
类数
2
2
一致
加载 pizza.owl 耗时ms
322
322
(共享)
创建推理机耗时ms
110
33
JFact 实例化更快
这是本测试最关键的性能差异 :在 939 axioms 的 pizza 本体上,JFact 完成完整分类只需 ~222ms,而 HermiT 需要 ~475ms。一致性检查 则相反:HermiT 仅 1ms 而 JFact 用了 83ms (JFact 在 consistency 上内部多做了些工作),但 222ms 的总分类时间已包含了一致性 + 分类。
T7 — 角色层次 + 传递性 (hasParent ⊑ hasAncestor, Transitive(hasAncestor), Alice hasParent Bob)
指标
HermiT
JFact
Alice →hasAncestor→ Bob 是否蕴含
true
true
Alice →hasParent→ Bob 是否蕴含
true
true
创建推理机耗时ms
29
0
✅ 两者都通过传递性 + 角色层次推导出 hasAncestor 关系。
T8 — 真实本体 (families.owl, 9 axioms)
指标
HermiT
JFact
一致性
true
true
类数 (Top 下的直接子类)
1
1
实例数
2
2
一致性耗时ms
0
1
分类耗时ms
1
0
实例检索耗时ms
0
0
加载 families.owl 耗时ms
10
10
创建推理机耗时ms
2
0
✅ 结果完全一致;本体太小,性能差异无法体现。
7. 差异分析
7.1 性能差异来源
JFact 是在 FaCT++ 设计基础上的纯 Java 移植 :保留了 C++ 版本的高度优化算法,分类阶段直接调用 Java 实现,避开 JVM 解释/GC 压力优势(与原版 C++ JNI 相比差距缩小)。
HermiT 是纯 Java Hypertableau :策略更复杂、blocking 校验更多,在分类前要构造并维护完整的 hypertableau 数据结构,因此在中大本体上分类开销更明显。
小本体上差距消失 :当本体公理数 < 50 时,JVM 启动 + JIT 预热的开销会反过来让 JFact 看起来稍慢或相当。
pizza.owl 场景具体数据 :JFact 一致性耗时 83ms 反而比 HermiT 1ms 慢很多 (因为 JFact 内部需要先构建内部数据结构);但最终分类完成时间 JFact (222ms) 仍快于 HermiT (475ms)。
7.2 与原 FaCT++ JNI 版本对比 (历史数据)
维度
FaCT++ 1.6.5 + JNI (旧)
JFact 5.0.3 (新)
说明
pizza.owl 分类耗时
2ms
222ms
旧版 C++ JNI 大幅领先,Java 版被 JNI 拉开差距
pizza.owl 加载
100ms
322ms
旧版更快 (JNI 路径)
部署 JNI 依赖
必须 32/64-bit DLL
无
JFact 优势:跨平台、容器友好
代码可调试性
JNI 调用栈不友好
✅ 完整 Java 异常栈
调试更简单
商业/学术许可
学术免费
LGPL 2.1
JFact 更友好
推荐
仅 Windows + 性能极致要求
通用
JFact 已成为社区事实标准
7.3 部署差异 (JFact vs HermiT)
关注点
JFact
HermiT
跨平台
✅ 纯 Java,一次打包,到处运行
✅ 纯 Java,一次打包,到处运行
容器化
✅ 标准 JRE 即可
✅ 标准 JRE 即可
License
✅ LGPL 2.1 开源
✅ LGPL 3.0 开源
调试
✅ 完整 Java 异常栈
✅ 完整 Java 异常栈
Maven 坐标
net.sourceforge.owlapi:jfact
net.sourceforge.owlapi:org.semanticweb.hermit
维护方
OWL API 官方
OWL API 官方
7.4 接口差异
两者都实现了标准的 OWLReasoner 接口,因此调用代码完全相同 :
1 2 3 4 5 6 OWLReasoner r = factory.createReasoner(ontology);boolean consistent = r.isConsistent();r.getSubClasses(cls, true ); r.getInstances(cls, false ); r.isEntailed(axiom); r.dispose();
唯一区别在于工厂类:
1 2 3 4 5 6 7 import uk.ac.manchester.cs.jfact.JFactFactory;OWLReasonerFactory factory = new JFactFactory ();import org.semanticweb.HermiT.ReasonerFactory;OWLReasonerFactory factory = new ReasonerFactory ();
8. Maven 迁移经验总结
8.1 原始 lib/ 方式 vs 新 pom.xml 方式
维度
lib/ + 手动 classpath (旧)
pom.xml + mvn package (新)
依赖数量
23 个 jar (xz, trove, commons-io, slf4j, sesame-rio, …)
3 行 XML
冲突排查
手动逐个下 jar
Maven 自动解决传递依赖
跨平台
每个新机器都要找齐 jar
mvn package 即可
升级 OWL API
重新下一整套 jar
改一行版本号
编译入口
手动 javac -encoding UTF-8 test.java
mvn package -DskipTests
运行命令
java -cp lib\*;. Test
java -cp "target\classes;target\lib\*" Test
8.2 原始 pom.xml 的修正
原配置
修正后
原因
org.semanticweb.hermit:hermit:1.4.3.519
net.sourceforge.owlapi:org.semanticweb.hermit:1.4.3.517
该 groupId/version 在 Maven Central 不存在;OWL API 官方用新坐标维护
net.sourceforge.jfact:jfact:4.0.4
net.sourceforge.owlapi:jfact:5.0.3
该 groupId 4.0.4 在 Central 不存在;OWL API 维护的最新 JFact 5.0.3 在 net.sourceforge.owlapi
仓库 https://raw.githubusercontent.com/owlcs/jfact/master/mvn-repo/
https://repo1.maven.org/maven2/ (Maven Central)
旧仓库是历史 fallback,新坐标已迁回 Central
8.3 pom.xml 关键配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <properties > <maven.compiler.source > 11</maven.compiler.source > <maven.compiler.target > 11</maven.compiler.target > <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding > </properties > <dependencies > <dependency > <groupId > net.sourceforge.owlapi</groupId > <artifactId > owlapi-distribution</artifactId > <version > 5.1.20</version > </dependency > <dependency > <groupId > net.sourceforge.owlapi</groupId > <artifactId > org.semanticweb.hermit</artifactId > <version > 1.4.3.517</version > </dependency > <dependency > <groupId > net.sourceforge.owlapi</groupId > <artifactId > jfact</artifactId > <version > 5.0.3</version > </dependency > </dependencies >
8.4 历史 lib/ 依赖问题(已通过 Maven 解决)
历史错误
当前状态
NoClassDefFoundError: org/tukaani/xz/XZInputStream
✅ Maven 传递依赖自动引入
NoClassDefFoundError: gnu/trove/map/hash/THashMap
✅ Maven 传递依赖自动引入 (trove4j)
NoClassDefFoundError: org/apache/commons/io/input/BOMInputStream
✅ Maven 传递依赖自动引入
NoClassDefFoundError: org/slf4j/LoggerFactory
✅ Maven 传递依赖自动引入
NoClassDefFoundError: javax/inject/Inject
✅ Maven 传递依赖自动引入
NoClassDefFoundError: org/openrdf/rio/RDFFormat
✅ Maven 传递依赖自动引入 (openrdf-sesame-rio-*)
UnsatisfiedLinkError: no FaCTPlusPlusJNI in java.library.path
✅ 已彻底消除 — JFact 是纯 Java,无需 JNI 库
9. 结论与建议
功能层面可互换 :8 组测试中两台推理机的逻辑输出 100% 一致,可放心替换。
性能层面优先 JFact :在 CCKS 任务中若存在 1000+ axioms 的大本体,JFact 优势明显(pizza.owl 上 2.1×)。
部署层面两台均优 :Maven 迁移后,JFact 与 HermiT 都是"纯 Java + 单坐标依赖",部署难度彻底消失,也彻底摆脱了原 FaCT++ JNI 的多平台 / 容器 / 32/64-bit 痛点 。
混合策略 :可在本地用 JFact 跑离线批量推理;服务化部署时切到 HermiT,通过 OWLReasonerFactory 抽象,业务代码无需改动。
下一步 :
把 [Test.java](file:///e:/ccks/reasoner/src/main/java/Test.java) 接入 CCKS 真实语料(contest_data 中的多跳/图谱/表格题本体);
在 10+ 个真实 OWL 本体上重复 T6 风格的基准,统计 JFact vs HermiT 性能分布;
评估 ELK / Konclude / Openllet 等新一代推理机作为补充方案;
在 CI 中把 mvn package && java -cp ... Test 串成 smoke test 任务。
Maven 项目配置: [pom.xml](file:///e:/ccks/reasoner/pom.xml)
测试代码: [src/main/java/Test.java](file:///e:/ccks/reasoner/src/main/java/Test.java)
原始输出: [test_output.txt](file:///e:/ccks/reasoner/test_output.txt)
(ai参与撰写和润色)