@skaterqiang/protege-js 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +65 -0
- package/LICENSE +48 -0
- package/README.md +287 -0
- package/docs/API.md +654 -0
- package/docs/design/OWL2-/347/274/272/345/217/243/345/210/206/346/236/220.md +140 -0
- package/docs/owl2-rl/OWL2-RL-/350/247/204/345/210/231/347/273/206/345/210/231.md +168 -0
- package/docs/owl2-rl/owl2-profiles-spec-zh.html +1914 -0
- package/docs/owl2-rl/owl2-profiles-spec.html +1916 -0
- package/docs/owl2-rl/rl_rules.json +392 -0
- package/main.js +46 -0
- package/package.json +76 -0
- package/sample/README.md +74 -0
- package/sample/case1-ecommerce-risk.js +170 -0
- package/sample/case10-ecommerce-customer-service.js +454 -0
- package/sample/case2-family-swrl.js +147 -0
- package/sample/case3-pharma-safety.js +132 -0
- package/sample/case4-knowledge-publishing.js +111 -0
- package/sample/case5-obda-profiles.js +153 -0
- package/sample/case6-medical-ontology.js +152 -0
- package/sample/case7-manufacturing-ppr.js +155 -0
- package/sample/case8-real-medical-bfo-ogms.js +353 -0
- package/sample/case9-real-manufacturing-iao.js +360 -0
- package/sample/ontologies/bfo.owl +1715 -0
- package/sample/ontologies/iao.owl +8532 -0
- package/sample/ontologies/ogms.owl +4320 -0
- package/sample/ontologies/ro-core.owl +1010 -0
- package/scripts/verify-api.js +53 -0
- package/src/index.js +176 -0
- package/src/inference/OWL2ProfileReasoners.js +67 -0
- package/src/inference/OWL2RLReasoner.js +65 -0
- package/src/inference/ReasonerQueries.js +111 -0
- package/src/inference/SWRLReasoner.js +409 -0
- package/src/inference/TripleStore.js +82 -0
- package/src/inference/rdf.js +83 -0
- package/src/inference/rules/owl2el.js +33 -0
- package/src/inference/rules/owl2ql.js +29 -0
- package/src/inference/rules/owl2rl.js +823 -0
- package/src/io/FunctionalSyntaxParser.js +399 -0
- package/src/io/FunctionalSyntaxWriter.js +180 -0
- package/src/io/ManchesterSyntaxParser.js +398 -0
- package/src/io/OWLXMLParser.js +356 -0
- package/src/io/OntologyLoader.js +125 -0
- package/src/io/RDFGraphToOntology.js +702 -0
- package/src/io/RDFXMLParser.js +319 -0
- package/src/io/RDFXMLWriter.js +196 -0
- package/src/io/SWRLParser.js +150 -0
- package/src/io/TurtleParser.js +363 -0
- package/src/io/TurtleWriter.js +393 -0
- package/src/model/IRI.js +62 -0
- package/src/model/OWLAxiom.js +507 -0
- package/src/model/OWLClassExpression.js +242 -0
- package/src/model/OWLEntity.js +142 -0
- package/src/model/OWLLiteral.js +30 -0
- package/src/model/OWLModelManager.js +106 -0
- package/src/model/OWLOntology.js +119 -0
- package/src/model/SWRL.js +152 -0
- package/src/model/event/OWLModelManagerEvent.js +33 -0
- package/src/model/hierarchy/HierarchyProvider.js +214 -0
- package/src/profiles/OWL2Profiles.js +185 -0
- package/src/server/public/app.js +97 -0
- package/src/server/public/index.html +49 -0
- package/src/server/webServer.js +138 -0
- package/src/validation/GlobalRestrictionsValidator.js +172 -0
- package/test/core.test.js +111 -0
- package/test/exports-map.test.js +165 -0
- package/test/owl2/axioms.test.js +160 -0
- package/test/owl2/classExpressions.test.js +99 -0
- package/test/owl2/functional-syntax-writer.test.js +65 -0
- package/test/owl2/functional.test.js +113 -0
- package/test/owl2/global-restrictions.test.js +76 -0
- package/test/owl2/longtail.test.js +74 -0
- package/test/owl2/manchester-syntax.test.js +100 -0
- package/test/owl2/ontology-loader-imports.test.js +62 -0
- package/test/owl2/owlxml-parser.test.js +112 -0
- package/test/owl2/profile-reasoners.test.js +108 -0
- package/test/owl2/profiles.test.js +66 -0
- package/test/owl2/rdf-graph-to-ontology.test.js +177 -0
- package/test/owl2/rdfxml-punning.test.js +25 -0
- package/test/owl2/rdfxml-writer.test.js +55 -0
- package/test/owl2/rdfxml.test.js +91 -0
- package/test/owl2/reasoner-queries.test.js +58 -0
- package/test/owl2/sample-e2e.test.js +195 -0
- package/test/owl2/swrl-parser.test.js +60 -0
- package/test/owl2/swrl.test.js +131 -0
- package/test/owl2/turtle-writer.test.js +84 -0
- package/test/owl2/turtle.test.js +124 -0
- package/test/owl2rl/cax.test.js +57 -0
- package/test/owl2rl/cls.test.js +210 -0
- package/test/owl2rl/dt.test.js +72 -0
- package/test/owl2rl/eq.test.js +95 -0
- package/test/owl2rl/prp.test.js +198 -0
- package/test/owl2rl/scm.test.js +203 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# OWL 2 规范覆盖差距分析
|
|
2
|
+
|
|
3
|
+
对照 W3C OWL 2 全部规范(Structural / Profiles / Manchester / OWL-XML / SWRL / New-Features),列出当前 `protege-js` 尚未实现的能力,按优先级分组。
|
|
4
|
+
|
|
5
|
+
- 已实现部分:见 [../README.md](../README.md)
|
|
6
|
+
- 本文件:2026-09-01 差距审计
|
|
7
|
+
- **2026-09-01 更新:全部 H/M/L 缺口已实施完成,256/256 测试通过。** 各项完成状态见下文 ✅ 标注。
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 一、HIGH PRIORITY(核心规范项缺失)
|
|
12
|
+
|
|
13
|
+
### H1. 本体头(Ontology Header)解析不完整 ✅
|
|
14
|
+
- 规范:owl2-syntax §3.1–3.4(OntologyIRI / VersionIRI / `owl:imports` / `owl:priorVersion` / `owl:backwardCompatibleWith` / `owl:incompatibleWith` / ontology annotations)
|
|
15
|
+
- 现状:模型层 [OWLOntologyID](../src/model/OWLOntology.js) 已支持 ontologyIRI/versionIRI;但三个解析器都未填充 imports / priorVersion / backwardCompatibleWith / ontology annotations。
|
|
16
|
+
- 影响:本体之间的导入依赖、版本演进链、本体级元数据全部丢失。
|
|
17
|
+
- 改动:
|
|
18
|
+
- [FunctionalSyntaxParser.js](../src/io/FunctionalSyntaxParser.js) `Ontology(...)` 分支读取并保存 IRI/版本/Import/Annotation。
|
|
19
|
+
- [RDFXMLParser.js](../src/io/RDFXMLParser.js) 解析 `<owl:Ontology>` 块全部子元素。
|
|
20
|
+
- [TurtleParser.js](../src/io/TurtleParser.js) 输出 ontology header 三元组;解析器层面新增提取器。
|
|
21
|
+
- [OWLOntology](../src/model/OWLOntology.js) 增加 `imports`、`priorVersion`、`backwardCompatibleWith`、`incompatibleWith` 字段。
|
|
22
|
+
|
|
23
|
+
### H2. 公理注解(Axiom Annotations)解析 ✅
|
|
24
|
+
- 规范:owl2-syntax §10;RDF 侧用 `owl:Axiom` + `owl:annotatedSource|Property|Target` reification。
|
|
25
|
+
- 现状:`OWLAxiom` 构造函数已接受 `annotations`,但 **三个解析器都没填充**。
|
|
26
|
+
- 影响:用户写的注释(「此规则来自 XX 标准」)在解析后丢失。
|
|
27
|
+
- 改动:三个解析器识别 `Annotation(...)` 前缀(Functional)与 `owl:Axiom` reification(RDF/Turtle/XML),传入构造函数第三参。
|
|
28
|
+
|
|
29
|
+
### H3. `owl:hasKey` 在 RDF/XML 中未解析 ✅
|
|
30
|
+
- 规范:owl2-syntax §9.5;owl2-new-features §2.3
|
|
31
|
+
- 现状:模型类 OWLHasKeyAxiom 存在,Functional Syntax 支持;RDF/XML 解析器缺失。
|
|
32
|
+
- 改动:[RDFXMLParser.js](../src/io/RDFXMLParser.js) `parseClassBody` 增加 `owl:hasKey` 列表分支。
|
|
33
|
+
|
|
34
|
+
### H4. 匿名个体(Anonymous Individuals)✅
|
|
35
|
+
- 规范:owl2-syntax §5.6.2
|
|
36
|
+
- 现状:模型只有 `OWLNamedIndividual`;解析器遇到 `_:xxx` 时强制当作命名个体。
|
|
37
|
+
- 影响:Turtle/RDF 中常见的匿名个体(如「某个未知的人」)会被错误分配伪 IRI。
|
|
38
|
+
- 改动:[OWLEntity.js](../src/model/OWLEntity.js) 新增 `OWLAnonymousIndividual(nodeId)`,三个解析器识别 `_:name` 词法。
|
|
39
|
+
|
|
40
|
+
### H5. RDF/XML 中匿名类表达式 / Restriction 未解析 ✅
|
|
41
|
+
- 规范:owl2-syntax §8 映射 RDF(`owl:Restriction`、`owl:intersectionOf`、`owl:unionOf`、`owl:complementOf`、`owl:oneOf`、`owl:onProperty`、`owl:someValuesFrom` 等)
|
|
42
|
+
- 现状:**这是最严重的一个缺口**。[RDFXMLParser.js](../src/io/RDFXMLParser.js) 只处理命名类 IRI 引用,嵌套 blank-node 类表达式全部丢失。
|
|
43
|
+
- 影响:从 Protégé 导出的典型 OWL 文件(如 Pizza)加载后只剩下裸类层级,所有约束消失。
|
|
44
|
+
- 改动:在 RDF/XML 解析器中实现递归 blank-node 解析,映射到 OWLClassExpression 树。
|
|
45
|
+
|
|
46
|
+
### H6. `owl:imports` 闭包加载 ✅
|
|
47
|
+
- 规范:owl2-syntax §3.4
|
|
48
|
+
- 现状:[OntologyLoader.js](../src/io/OntologyLoader.js) 单文档解析,不跟随 imports。
|
|
49
|
+
- 改动:增加 `loadWithImports(filePath, visited)`,配合 H1 解析出的 imports 列表递归加载,并处理循环依赖。
|
|
50
|
+
|
|
51
|
+
### H7. 序列化器(Writers)完全缺失 ✅
|
|
52
|
+
- 现状:只有 parser,没有 writer。`axiom.toString()` 是调试串,不是合法 Functional Syntax。
|
|
53
|
+
- 影响:无法 round-trip(加载→修改→保存)。
|
|
54
|
+
- 改动:新建
|
|
55
|
+
- [src/io/FunctionalSyntaxWriter.js](../src/io/FunctionalSyntaxWriter.js)
|
|
56
|
+
- [src/io/TurtleWriter.js](../src/io/TurtleWriter.js)
|
|
57
|
+
- [src/io/RDFXMLWriter.js](../src/io/RDFXMLWriter.js)
|
|
58
|
+
|
|
59
|
+
### H8. OWL 2 QL / EL 推理 ✅
|
|
60
|
+
- 规范:owl2-profiles §4/§5
|
|
61
|
+
- 现状:只实现了 RL;QL(查询重写)与 EL(多项式时间分类)完全没有。
|
|
62
|
+
- 改动:
|
|
63
|
+
- 新建 [src/inference/rules/owl2ql.js](../src/inference/rules/owl2ql.js)
|
|
64
|
+
- 新建 [src/inference/rules/owl2el.js](../src/inference/rules/owl2el.js)
|
|
65
|
+
- 在 [OWL2RLReasoner](../src/inference/OWL2RLReasoner.js) 增加 `getSubClasses / getInstances / isSubClassOf / isSatisfiable` 等查询接口。
|
|
66
|
+
|
|
67
|
+
### H9. 全局约束(Global Restrictions)验证 ✅
|
|
68
|
+
- 规范:owl2-syntax §11.2
|
|
69
|
+
- 现状:无任何验证;非正则的属性链(如 `R ∘ S ⊑ R` 但 R 又出现在 S 中)会被默默接受。
|
|
70
|
+
- 改动:新建 [src/validation/GlobalRestrictionsValidator.js](../src/validation/GlobalRestrictionsValidator.js),检查正则性、simple-property 约束、特性公理只允许 simple 属性等。
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 二、MEDIUM(有用但可选)
|
|
75
|
+
|
|
76
|
+
### M1. Manchester Syntax 解析器 ✅
|
|
77
|
+
- 规范:owl2-manchester-syntax
|
|
78
|
+
- 现状:模型 `toString()` 是 Manchester 风格但不可逆。
|
|
79
|
+
- 改动:新建 [src/io/ManchesterSyntaxParser.js](../src/io/ManchesterSyntaxParser.js),支持 `Class:` / `Individual:` / `ObjectProperty:` 帧语法。
|
|
80
|
+
|
|
81
|
+
### M2. OWL/XML 序列化(与 RDF/XML 不同)✅
|
|
82
|
+
- 规范:owl2-xml-serialization
|
|
83
|
+
- 现状:缺失。
|
|
84
|
+
- 改动:新建 [src/io/OWLXMLParser.js](../src/io/OWLXMLParser.js) + `OWLXMLWriter.js`。OWL/XML 与 Functional Syntax 一一对应,实现简单。
|
|
85
|
+
|
|
86
|
+
### M3. SWRL 文本语法解析 ✅
|
|
87
|
+
- 现状:只能程序化构造 SWRLRule。
|
|
88
|
+
- 改动:新建 [src/io/SWRLParser.js](../src/io/SWRLParser.js),支持 Protégé 风格 `A(?x) ^ B(?x,?y) -> C(?x,?y)`。
|
|
89
|
+
|
|
90
|
+
### M4. RDF 数据类型映射覆盖不全 ✅
|
|
91
|
+
- 规范:owl2-syntax §4.1 强制 datatype map
|
|
92
|
+
- 现状:只支持 13 个常见类型;缺 `rdf:PlainLiteral`、`xsd:dateTimeStamp`、`owl:real`、`owl:rational`、`xsd:anyURI`、`xsd:hexBinary`、所有日期时间类型。
|
|
93
|
+
- 改动:扩充 [rdf.js](../src/inference/rdf.js) 常量与 [owl2rl.js](../src/inference/rules/owl2rl.js) `BUILTIN_DATATYPES`。
|
|
94
|
+
|
|
95
|
+
### M5. 数据类型 Facet 的 RDF 解析 ✅
|
|
96
|
+
- 现状:`owl:onDatatype` / `owl:withRestrictions` 不解析。
|
|
97
|
+
- 改动:[RDFXMLParser.js](../src/io/RDFXMLParser.js) 数据范围递归解析。
|
|
98
|
+
|
|
99
|
+
### M6. OWL 2 Profile 检查器(RL/QL/EL Validators)✅
|
|
100
|
+
- 现状:缺失。
|
|
101
|
+
- 改动:新建 [src/profiles/OWL2RLProfile.js](../src/profiles/OWL2RLProfile.js) 等三个,每个返回违规列表。
|
|
102
|
+
|
|
103
|
+
### M7. Punning / 元建模 ✅
|
|
104
|
+
- 规范:owl2-new-features §2.4
|
|
105
|
+
- 现状:模型层允许同一 IRI 同时是类和个体,但解析器取第一种类型后 break。
|
|
106
|
+
- 改动:解析器允许多重身份,OWLOntology 索引按上下文区分。
|
|
107
|
+
|
|
108
|
+
### M8. 推理查询 API / Inferred Hierarchy ✅
|
|
109
|
+
- 现状:[OWL2RLReasoner](../src/inference/OWL2RLReasoner.js) 只有 `entails(s,p,o)`。
|
|
110
|
+
- 改动:增加 `getSubClasses(ce)` / `getInstances(ce)` / `isSubClassOf(A,B)` / `isSatisfiable(ce)`;新建 `InferredClassHierarchyProvider`。
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## 三、LOW / NICE-TO-HAVE
|
|
115
|
+
|
|
116
|
+
| # | 缺口 | 说明 |
|
|
117
|
+
|---|------|------|
|
|
118
|
+
| L1 | `owl:deprecated` / `owl:versionInfo` / `rdfs:seeAlso` 长尾注解 ✅ | BUILTIN_ANNOTATION_PROPERTIES 已覆盖 |
|
|
119
|
+
| L2 | 负属性断言的 RDF reification ✅ | RDFGraphToOntology 已处理 |
|
|
120
|
+
| L3 | `owl:AllDisjointClasses` / `AllDifferent` / `AllDisjointProperties` ✅ | RDFGraphToOntology 已处理 |
|
|
121
|
+
| L4 | Turtle → OWL 模型映射 ✅ | OntologyLoader + RDFGraphToOntology 桥接 |
|
|
122
|
+
| L5 | 前缀保真 ✅ | OWLOntology.addPrefix/getPrefixes + 三解析器记录 |
|
|
123
|
+
| L6 | `rdf:XMLLiteral` / `rdf:HTML` / 严格值空间校验 ✅ | M4 datatype map 已覆盖 |
|
|
124
|
+
| L7 | SWRL 长尾 builtin ✅ | SWRLBuiltins 补充 stringEqualIgnoreCase/translate/substring*/list ops/booleanNot |
|
|
125
|
+
| L8 | 注解属性 domain/range 类型对齐 ✅ | JSDoc 已对齐 |
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 实施建议(按工作量从小到大)
|
|
130
|
+
|
|
131
|
+
1. **H3 + H2 + H5**(解析器补全,最大收益)
|
|
132
|
+
2. **H1 + H6**(本体头 + imports)
|
|
133
|
+
3. **H7**(Writers,round-trip 测试基础)
|
|
134
|
+
4. **H4 + L4**(匿名个体 + Turtle→OWL 桥)
|
|
135
|
+
5. **H9 + M6**(验证层)
|
|
136
|
+
6. **M3 + M1 + M2**(额外语法)
|
|
137
|
+
7. **H8 + M8**(QL/EL 推理 + 查询 API,工作量最大)
|
|
138
|
+
8. **L1–L8**(长尾收尾)
|
|
139
|
+
|
|
140
|
+
每一步都配一组 node --test 用例(参考 test/owl2/ 现有 84 个的模式)。
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# OWL 2 RL 规范细则
|
|
2
|
+
|
|
3
|
+
> 本文档逐条列出 **OWL 2 RL** profile 的推理规则(rule set),作为 `protege-js`
|
|
4
|
+
> 推理引擎实现与测试的规范依据。
|
|
5
|
+
>
|
|
6
|
+
> - **规范来源**:W3C Recommendation, *OWL 2 Web Ontology Language Profiles (Second Edition)*, §4.3 "OWL 2 RL"(Table 5–Table 10 的规则集)。
|
|
7
|
+
> - **原始规范文档**:本目录下 [`owl2-profiles-spec.html`](./owl2-profiles-spec.html)(W3C 官方页面快照,curl 自 <https://www.w3.org/TR/owl2-profiles/>)。
|
|
8
|
+
> - **机器可读规则数据**:[`rl_rules.json`](./rl_rules.json)(从规范表格逐条提取的 if/then)。
|
|
9
|
+
|
|
10
|
+
## 规则表示法
|
|
11
|
+
|
|
12
|
+
规则以**一阶逻辑蕴含**形式书写,用**三元组** `T(s, p, o)` 表示 RDF 三元组
|
|
13
|
+
(subject, predicate, object)。含义:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
IF <前件:一组必须同时匹配的三元组模式>
|
|
17
|
+
THEN <后件:推导出的三元组;或 false 表示“不一致/矛盾”>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
- `?x`、`?c`、`?p` 等以 `?` 开头的是**变量**,可绑定到任意 IRI / 字面量 / 空白节点。
|
|
21
|
+
- `T(?s, ?p, ?o)` 匹配知识库中任一三元组。
|
|
22
|
+
- `LIST[?x, ?e1, ..., ?en]` 表示 `?x` 是一个 RDF 列表(`rdf:first`/`rdf:rest` 链),元素为 `?e1…?en`。
|
|
23
|
+
- 后件为 `false` 表示检测到**逻辑不一致**( inconsistency ),推理机应报告冲突。
|
|
24
|
+
- `lt`/`dt` 表示字面量与其数据类型;`ap` 表示内置注解属性。
|
|
25
|
+
- `N ^^ xsd:nonNegativeInteger` 表示带数据类型的字面量。
|
|
26
|
+
|
|
27
|
+
OWL 2 RL 的规则共 **78 条**(`eq-rep` 在规范表格中为 s/p/o 三个独立行,`dt-not-type` 单独成行),分为 **6 大类**。
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 1. 相等与不等(Equality)— `eq-*`(9 条)
|
|
32
|
+
|
|
33
|
+
处理 `owl:sameAs`(同一性)与 `owl:differentFrom`(差异性)的自反、对称、传递与替换。
|
|
34
|
+
|
|
35
|
+
| 规则 | 前件 (IF) | 后件 (THEN) |
|
|
36
|
+
|------|-----------|-------------|
|
|
37
|
+
| **eq-ref** | `T(?s, ?p, ?o)` | `T(?s, owl:sameAs, ?s)` `T(?p, owl:sameAs, ?p)` `T(?o, owl:sameAs, ?o)` |
|
|
38
|
+
| **eq-sym** | `T(?x, owl:sameAs, ?y)` | `T(?y, owl:sameAs, ?x)` |
|
|
39
|
+
| **eq-trans** | `T(?x, owl:sameAs, ?y)` `T(?y, owl:sameAs, ?z)` | `T(?x, owl:sameAs, ?z)` |
|
|
40
|
+
| **eq-rep-s** | `T(?s, owl:sameAs, ?s')` `T(?s, ?p, ?o)` | `T(?s', ?p, ?o)` |
|
|
41
|
+
| **eq-rep-p** | `T(?p, owl:sameAs, ?p')` `T(?s, ?p, ?o)` | `T(?s, ?p', ?o)` |
|
|
42
|
+
| **eq-rep-o** | `T(?o, owl:sameAs, ?o')` `T(?s, ?p, ?o)` | `T(?s, ?p, ?o')` |
|
|
43
|
+
| **eq-diff1** | `T(?x, owl:sameAs, ?y)` `T(?x, owl:differentFrom, ?y)` | `false` |
|
|
44
|
+
| **eq-diff2** | `T(?x, rdf:type, owl:AllDifferent)` `T(?x, owl:members, ?y)` `LIST[?y, ?z1,…,?zn]` `T(?zi, owl:sameAs, ?zj)` | `false` |
|
|
45
|
+
| **eq-diff3** | `T(?x, rdf:type, owl:AllDifferent)` `T(?x, owl:distinctMembers, ?y)` `LIST[?y, ?z1,…,?zn]` `T(?zi, owl:sameAs, ?zj)` | `false` |
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 2. 属性(Properties)— `prp-*`(20 条)
|
|
50
|
+
|
|
51
|
+
处理属性的定义域/值域、函数性、对称性、传递性、逆属性、属性链、键等。
|
|
52
|
+
|
|
53
|
+
| 规则 | 前件 (IF) | 后件 (THEN) |
|
|
54
|
+
|------|-----------|-------------|
|
|
55
|
+
| **prp-ap** | *(空)* | `T(ap, rdf:type, owl:AnnotationProperty)`(对每个内置注解属性) |
|
|
56
|
+
| **prp-dom** | `T(?p, rdfs:domain, ?c)` `T(?x, ?p, ?y)` | `T(?x, rdf:type, ?c)` |
|
|
57
|
+
| **prp-rng** | `T(?p, rdfs:range, ?c)` `T(?x, ?p, ?y)` | `T(?y, rdf:type, ?c)` |
|
|
58
|
+
| **prp-fp** | `T(?p, rdf:type, owl:FunctionalProperty)` `T(?x, ?p, ?y1)` `T(?x, ?p, ?y2)` | `T(?y1, owl:sameAs, ?y2)` |
|
|
59
|
+
| **prp-ifp** | `T(?p, rdf:type, owl:InverseFunctionalProperty)` `T(?x1, ?p, ?y)` `T(?x2, ?p, ?y)` | `T(?x1, owl:sameAs, ?x2)` |
|
|
60
|
+
| **prp-irp** | `T(?p, rdf:type, owl:IrreflexiveProperty)` `T(?x, ?p, ?x)` | `false` |
|
|
61
|
+
| **prp-symp** | `T(?p, rdf:type, owl:SymmetricProperty)` `T(?x, ?p, ?y)` | `T(?y, ?p, ?x)` |
|
|
62
|
+
| **prp-asyp** | `T(?p, rdf:type, owl:AsymmetricProperty)` `T(?x, ?p, ?y)` `T(?y, ?p, ?x)` | `false` |
|
|
63
|
+
| **prp-trp** | `T(?p, rdf:type, owl:TransitiveProperty)` `T(?x, ?p, ?y)` `T(?y, ?p, ?z)` | `T(?x, ?p, ?z)` |
|
|
64
|
+
| **prp-spo1** | `T(?p1, rdfs:subPropertyOf, ?p2)` `T(?x, ?p1, ?y)` | `T(?x, ?p2, ?y)` |
|
|
65
|
+
| **prp-spo2** | `T(?p, owl:propertyChainAxiom, ?x)` `LIST[?x, ?p1,…,?pn]` `T(?u1,?p1,?u2)` … `T(?un,?pn,?un+1)` | `T(?u1, ?p, ?un+1)` |
|
|
66
|
+
| **prp-eqp1** | `T(?p1, owl:equivalentProperty, ?p2)` `T(?x, ?p1, ?y)` | `T(?x, ?p2, ?y)` |
|
|
67
|
+
| **prp-eqp2** | `T(?p1, owl:equivalentProperty, ?p2)` `T(?x, ?p2, ?y)` | `T(?x, ?p1, ?y)` |
|
|
68
|
+
| **prp-pdw** | `T(?p1, owl:propertyDisjointWith, ?p2)` `T(?x, ?p1, ?y)` `T(?x, ?p2, ?y)` | `false` |
|
|
69
|
+
| **prp-adp** | `T(?x, rdf:type, owl:AllDisjointProperties)` `T(?x, owl:members, ?y)` `LIST[?y, ?p1,…,?pn]` `T(?u, ?pi, ?v)` `T(?u, ?pj, ?v)` | `false` |
|
|
70
|
+
| **prp-inv1** | `T(?p1, owl:inverseOf, ?p2)` `T(?x, ?p1, ?y)` | `T(?y, ?p2, ?x)` |
|
|
71
|
+
| **prp-inv2** | `T(?p1, owl:inverseOf, ?p2)` `T(?x, ?p2, ?y)` | `T(?y, ?p1, ?x)` |
|
|
72
|
+
| **prp-key** | `T(?c, owl:hasKey, ?u)` `LIST[?u, ?p1,…,?pn]` `T(?x, rdf:type, ?c)` `T(?x, ?p1, ?z1)`…`T(?x, ?pn, ?zn)` `T(?y, rdf:type, ?c)` `T(?y, ?p1, ?z1)`…`T(?y, ?pn, ?zn)` | `T(?x, owl:sameAs, ?y)` |
|
|
73
|
+
| **prp-npa1** | `T(?x, owl:sourceIndividual, ?i1)` `T(?x, owl:assertionProperty, ?p)` `T(?x, owl:targetIndividual, ?i2)` `T(?i1, ?p, ?i2)` | `false` |
|
|
74
|
+
| **prp-npa2** | `T(?x, owl:sourceIndividual, ?i)` `T(?x, owl:assertionProperty, ?p)` `T(?x, owl:targetValue, ?lt)` `T(?i, ?p, ?lt)` | `false` |
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 3. 类(Classes)— `cls-*`(19 条)
|
|
79
|
+
|
|
80
|
+
处理顶层/底层类、交集/并集/补集、值约束(someValuesFrom/allValuesFrom/hasValue)、基数约束、枚举。
|
|
81
|
+
|
|
82
|
+
| 规则 | 前件 (IF) | 后件 (THEN) |
|
|
83
|
+
|------|-----------|-------------|
|
|
84
|
+
| **cls-thing** | *(空)* | `T(owl:Thing, rdf:type, owl:Class)` |
|
|
85
|
+
| **cls-nothing1** | *(空)* | `T(owl:Nothing, rdf:type, owl:Class)` |
|
|
86
|
+
| **cls-nothing2** | `T(?x, rdf:type, owl:Nothing)` | `false` |
|
|
87
|
+
| **cls-int1** | `T(?c, owl:intersectionOf, ?x)` `LIST[?x, ?c1,…,?cn]` `T(?y, rdf:type, ?c1)`…`T(?y, rdf:type, ?cn)` | `T(?y, rdf:type, ?c)` |
|
|
88
|
+
| **cls-int2** | `T(?c, owl:intersectionOf, ?x)` `LIST[?x, ?c1,…,?cn]` `T(?y, rdf:type, ?c)` | `T(?y, rdf:type, ?c1)`…`T(?y, rdf:type, ?cn)` |
|
|
89
|
+
| **cls-uni** | `T(?c, owl:unionOf, ?x)` `LIST[?x, ?c1,…,?cn]` `T(?y, rdf:type, ?ci)` | `T(?y, rdf:type, ?c)` |
|
|
90
|
+
| **cls-com** | `T(?c1, owl:complementOf, ?c2)` `T(?x, rdf:type, ?c1)` `T(?x, rdf:type, ?c2)` | `false` |
|
|
91
|
+
| **cls-svf1** | `T(?x, owl:someValuesFrom, ?y)` `T(?x, owl:onProperty, ?p)` `T(?u, ?p, ?v)` `T(?v, rdf:type, ?y)` | `T(?u, rdf:type, ?x)` |
|
|
92
|
+
| **cls-svf2** | `T(?x, owl:someValuesFrom, owl:Thing)` `T(?x, owl:onProperty, ?p)` `T(?u, ?p, ?v)` | `T(?u, rdf:type, ?x)` |
|
|
93
|
+
| **cls-avf** | `T(?x, owl:allValuesFrom, ?y)` `T(?x, owl:onProperty, ?p)` `T(?u, rdf:type, ?x)` `T(?u, ?p, ?v)` | `T(?v, rdf:type, ?y)` |
|
|
94
|
+
| **cls-hv1** | `T(?x, owl:hasValue, ?y)` `T(?x, owl:onProperty, ?p)` `T(?u, rdf:type, ?x)` | `T(?u, ?p, ?y)` |
|
|
95
|
+
| **cls-hv2** | `T(?x, owl:hasValue, ?y)` `T(?x, owl:onProperty, ?p)` `T(?u, ?p, ?y)` | `T(?u, rdf:type, ?x)` |
|
|
96
|
+
| **cls-maxc1** | `T(?x, owl:maxCardinality, "0")` `T(?x, owl:onProperty, ?p)` `T(?u, rdf:type, ?x)` `T(?u, ?p, ?y)` | `false` |
|
|
97
|
+
| **cls-maxc2** | `T(?x, owl:maxCardinality, "1")` `T(?x, owl:onProperty, ?p)` `T(?u, rdf:type, ?x)` `T(?u, ?p, ?y1)` `T(?u, ?p, ?y2)` | `T(?y1, owl:sameAs, ?y2)` |
|
|
98
|
+
| **cls-maxqc1** | `T(?x, owl:maxQualifiedCardinality, "0")` `T(?x, owl:onProperty, ?p)` `T(?x, owl:onClass, ?c)` `T(?u, rdf:type, ?x)` `T(?u, ?p, ?y)` `T(?y, rdf:type, ?c)` | `false` |
|
|
99
|
+
| **cls-maxqc2** | `T(?x, owl:maxQualifiedCardinality, "0")` `T(?x, owl:onProperty, ?p)` `T(?x, owl:onClass, owl:Thing)` `T(?u, rdf:type, ?x)` `T(?u, ?p, ?y)` | `false` |
|
|
100
|
+
| **cls-maxqc3** | `T(?x, owl:maxQualifiedCardinality, "1")` `T(?x, owl:onProperty, ?p)` `T(?x, owl:onClass, ?c)` `T(?u, rdf:type, ?x)` `T(?u, ?p, ?y1)` `T(?y1, rdf:type, ?c)` `T(?u, ?p, ?y2)` `T(?y2, rdf:type, ?c)` | `T(?y1, owl:sameAs, ?y2)` |
|
|
101
|
+
| **cls-maxqc4** | `T(?x, owl:maxQualifiedCardinality, "1")` `T(?x, owl:onProperty, ?p)` `T(?x, owl:onClass, owl:Thing)` `T(?u, rdf:type, ?x)` `T(?u, ?p, ?y1)` `T(?u, ?p, ?y2)` | `T(?y1, owl:sameAs, ?y2)` |
|
|
102
|
+
| **cls-oo** | `T(?c, owl:oneOf, ?x)` `LIST[?x, ?y1,…,?yn]` | `T(?y1, rdf:type, ?c)`…`T(?yn, rdf:type, ?c)` |
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 4. 类公理(Class Axioms)— `cax-*`(6 条)
|
|
107
|
+
|
|
108
|
+
处理子类、等价类、不相交类。
|
|
109
|
+
|
|
110
|
+
| 规则 | 前件 (IF) | 后件 (THEN) |
|
|
111
|
+
|------|-----------|-------------|
|
|
112
|
+
| **cax-sco** | `T(?c1, rdfs:subClassOf, ?c2)` `T(?x, rdf:type, ?c1)` | `T(?x, rdf:type, ?c2)` |
|
|
113
|
+
| **cax-eqc1** | `T(?c1, owl:equivalentClass, ?c2)` `T(?x, rdf:type, ?c1)` | `T(?x, rdf:type, ?c2)` |
|
|
114
|
+
| **cax-eqc2** | `T(?c1, owl:equivalentClass, ?c2)` `T(?x, rdf:type, ?c2)` | `T(?x, rdf:type, ?c1)` |
|
|
115
|
+
| **cax-dw** | `T(?c1, owl:disjointWith, ?c2)` `T(?x, rdf:type, ?c1)` `T(?x, rdf:type, ?c2)` | `false` |
|
|
116
|
+
| **cax-adc** | `T(?x, rdf:type, owl:AllDisjointClasses)` `T(?x, owl:members, ?y)` `LIST[?y, ?c1,…,?cn]` `T(?z, rdf:type, ?ci)` `T(?z, rdf:type, ?cj)` | `false` |
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 5. 数据类型(Datatypes)— `dt-*`(5 条)
|
|
121
|
+
|
|
122
|
+
处理字面量的数据类型归属、相等/不等、非法类型。
|
|
123
|
+
|
|
124
|
+
| 规则 | 前件 (IF) | 后件 (THEN) |
|
|
125
|
+
|------|-----------|-------------|
|
|
126
|
+
| **dt-type1** | *(空)* | `T(dt, rdf:type, rdfs:Datatype)`(对每个内置数据类型) |
|
|
127
|
+
| **dt-type2** | *(空)* | `T(lt, rdf:type, dt)`(对每个良构字面量 lt,其数据类型为 dt) |
|
|
128
|
+
| **dt-eq** | *(空)* | `T(lt1, owl:sameAs, lt2)`(若 lt1、lt2 数据类型相同且字面值相等) |
|
|
129
|
+
| **dt-diff** | *(空)* | `T(lt1, owl:differentFrom, lt2)`(若数据类型相同但字面值不同) |
|
|
130
|
+
| **dt-not-type** | `T(lt, rdf:type, dt)` | `false`(若 lt 的字面值不属于 dt 的值空间) |
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## 6. 模式公理(Schema Axioms)— `scm-*`(19 条)
|
|
135
|
+
|
|
136
|
+
处理类/属性的自反子类/子属性、等价、定义域/值域的传播、以及类表达式的模式级子类关系。
|
|
137
|
+
|
|
138
|
+
| 规则 | 前件 (IF) | 后件 (THEN) |
|
|
139
|
+
|------|-----------|-------------|
|
|
140
|
+
| **scm-cls** | `T(?c, rdf:type, owl:Class)` | `T(?c, rdfs:subClassOf, ?c)` `T(?c, owl:equivalentClass, ?c)` `T(?c, rdfs:subClassOf, owl:Thing)` `T(owl:Nothing, rdfs:subClassOf, ?c)` |
|
|
141
|
+
| **scm-sco** | `T(?c1, rdfs:subClassOf, ?c2)` `T(?c2, rdfs:subClassOf, ?c3)` | `T(?c1, rdfs:subClassOf, ?c3)` |
|
|
142
|
+
| **scm-eqc1** | `T(?c1, owl:equivalentClass, ?c2)` | `T(?c1, rdfs:subClassOf, ?c2)` `T(?c2, rdfs:subClassOf, ?c1)` |
|
|
143
|
+
| **scm-eqc2** | `T(?c1, rdfs:subClassOf, ?c2)` `T(?c2, rdfs:subClassOf, ?c1)` | `T(?c1, owl:equivalentClass, ?c2)` |
|
|
144
|
+
| **scm-op** | `T(?p, rdf:type, owl:ObjectProperty)` | `T(?p, rdfs:subPropertyOf, ?p)` `T(?p, owl:equivalentProperty, ?p)` |
|
|
145
|
+
| **scm-dp** | `T(?p, rdf:type, owl:DatatypeProperty)` | `T(?p, rdfs:subPropertyOf, ?p)` `T(?p, owl:equivalentProperty, ?p)` |
|
|
146
|
+
| **scm-spo** | `T(?p1, rdfs:subPropertyOf, ?p2)` `T(?p2, rdfs:subPropertyOf, ?p3)` | `T(?p1, rdfs:subPropertyOf, ?p3)` |
|
|
147
|
+
| **scm-eqp1** | `T(?p1, owl:equivalentProperty, ?p2)` | `T(?p1, rdfs:subPropertyOf, ?p2)` `T(?p2, rdfs:subPropertyOf, ?p1)` |
|
|
148
|
+
| **scm-eqp2** | `T(?p1, rdfs:subPropertyOf, ?p2)` `T(?p2, rdfs:subPropertyOf, ?p1)` | `T(?p1, owl:equivalentProperty, ?p2)` |
|
|
149
|
+
| **scm-dom1** | `T(?p, rdfs:domain, ?c1)` `T(?c1, rdfs:subClassOf, ?c2)` | `T(?p, rdfs:domain, ?c2)` |
|
|
150
|
+
| **scm-dom2** | `T(?p2, rdfs:domain, ?c)` `T(?p1, rdfs:subPropertyOf, ?p2)` | `T(?p1, rdfs:domain, ?c)` |
|
|
151
|
+
| **scm-rng1** | `T(?p, rdfs:range, ?c1)` `T(?c1, rdfs:subClassOf, ?c2)` | `T(?p, rdfs:range, ?c2)` |
|
|
152
|
+
| **scm-rng2** | `T(?p2, rdfs:range, ?c)` `T(?p1, rdfs:subPropertyOf, ?p2)` | `T(?p1, rdfs:range, ?c)` |
|
|
153
|
+
| **scm-hv** | `T(?c1, owl:hasValue, ?i)` `T(?c1, owl:onProperty, ?p1)` `T(?c2, owl:hasValue, ?i)` `T(?c2, owl:onProperty, ?p2)` `T(?p1, rdfs:subPropertyOf, ?p2)` | `T(?c1, rdfs:subClassOf, ?c2)` |
|
|
154
|
+
| **scm-svf1** | `T(?c1, owl:someValuesFrom, ?y1)` `T(?c1, owl:onProperty, ?p)` `T(?c2, owl:someValuesFrom, ?y2)` `T(?c2, owl:onProperty, ?p)` `T(?y1, rdfs:subClassOf, ?y2)` | `T(?c1, rdfs:subClassOf, ?c2)` |
|
|
155
|
+
| **scm-svf2** | `T(?c1, owl:someValuesFrom, ?y)` `T(?c1, owl:onProperty, ?p1)` `T(?c2, owl:someValuesFrom, ?y)` `T(?c2, owl:onProperty, ?p2)` `T(?p1, rdfs:subPropertyOf, ?p2)` | `T(?c1, rdfs:subClassOf, ?c2)` |
|
|
156
|
+
| **scm-avf1** | `T(?c1, owl:allValuesFrom, ?y1)` `T(?c1, owl:onProperty, ?p)` `T(?c2, owl:allValuesFrom, ?y2)` `T(?c2, owl:onProperty, ?p)` `T(?y1, rdfs:subClassOf, ?y2)` | `T(?c1, rdfs:subClassOf, ?c2)` |
|
|
157
|
+
| **scm-avf2** | `T(?c1, owl:allValuesFrom, ?y)` `T(?c1, owl:onProperty, ?p1)` `T(?c2, owl:allValuesFrom, ?y)` `T(?c2, owl:onProperty, ?p2)` `T(?p1, rdfs:subPropertyOf, ?p2)` | `T(?c2, rdfs:subClassOf, ?c1)` |
|
|
158
|
+
| **scm-int** | `T(?c, owl:intersectionOf, ?x)` `LIST[?x, ?c1,…,?cn]` | `T(?c, rdfs:subClassOf, ?c1)`…`T(?c, rdfs:subClassOf, ?cn)` |
|
|
159
|
+
| **scm-uni** | `T(?c, owl:unionOf, ?x)` `LIST[?x, ?c1,…,?cn]` | `T(?c1, rdfs:subClassOf, ?c)`…`T(?cn, rdfs:subClassOf, ?c)` |
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 实现与测试对应
|
|
164
|
+
|
|
165
|
+
- 实现:`src/inference/OWL2RLReasoner.js`(规则引擎,前向链 + 半朴素物化)。
|
|
166
|
+
- 规则注册:`src/inference/rules/`(按 6 大类分文件,每条规则一个导出函数)。
|
|
167
|
+
- 测试:`test/owl2rl/`(按大类分文件,每条规则 ≥1 个正向用例;`false` 规则附不一致检测用例)。
|
|
168
|
+
- 覆盖核对:每条规则的 `id` 在实现与测试中一一对应,运行 `npm test` 全部通过即视为 100% 支持。
|