@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.
Files changed (92) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/LICENSE +48 -0
  3. package/README.md +287 -0
  4. package/docs/API.md +654 -0
  5. package/docs/design/OWL2-/347/274/272/345/217/243/345/210/206/346/236/220.md +140 -0
  6. package/docs/owl2-rl/OWL2-RL-/350/247/204/345/210/231/347/273/206/345/210/231.md +168 -0
  7. package/docs/owl2-rl/owl2-profiles-spec-zh.html +1914 -0
  8. package/docs/owl2-rl/owl2-profiles-spec.html +1916 -0
  9. package/docs/owl2-rl/rl_rules.json +392 -0
  10. package/main.js +46 -0
  11. package/package.json +76 -0
  12. package/sample/README.md +74 -0
  13. package/sample/case1-ecommerce-risk.js +170 -0
  14. package/sample/case10-ecommerce-customer-service.js +454 -0
  15. package/sample/case2-family-swrl.js +147 -0
  16. package/sample/case3-pharma-safety.js +132 -0
  17. package/sample/case4-knowledge-publishing.js +111 -0
  18. package/sample/case5-obda-profiles.js +153 -0
  19. package/sample/case6-medical-ontology.js +152 -0
  20. package/sample/case7-manufacturing-ppr.js +155 -0
  21. package/sample/case8-real-medical-bfo-ogms.js +353 -0
  22. package/sample/case9-real-manufacturing-iao.js +360 -0
  23. package/sample/ontologies/bfo.owl +1715 -0
  24. package/sample/ontologies/iao.owl +8532 -0
  25. package/sample/ontologies/ogms.owl +4320 -0
  26. package/sample/ontologies/ro-core.owl +1010 -0
  27. package/scripts/verify-api.js +53 -0
  28. package/src/index.js +176 -0
  29. package/src/inference/OWL2ProfileReasoners.js +67 -0
  30. package/src/inference/OWL2RLReasoner.js +65 -0
  31. package/src/inference/ReasonerQueries.js +111 -0
  32. package/src/inference/SWRLReasoner.js +409 -0
  33. package/src/inference/TripleStore.js +82 -0
  34. package/src/inference/rdf.js +83 -0
  35. package/src/inference/rules/owl2el.js +33 -0
  36. package/src/inference/rules/owl2ql.js +29 -0
  37. package/src/inference/rules/owl2rl.js +823 -0
  38. package/src/io/FunctionalSyntaxParser.js +399 -0
  39. package/src/io/FunctionalSyntaxWriter.js +180 -0
  40. package/src/io/ManchesterSyntaxParser.js +398 -0
  41. package/src/io/OWLXMLParser.js +356 -0
  42. package/src/io/OntologyLoader.js +125 -0
  43. package/src/io/RDFGraphToOntology.js +702 -0
  44. package/src/io/RDFXMLParser.js +319 -0
  45. package/src/io/RDFXMLWriter.js +196 -0
  46. package/src/io/SWRLParser.js +150 -0
  47. package/src/io/TurtleParser.js +363 -0
  48. package/src/io/TurtleWriter.js +393 -0
  49. package/src/model/IRI.js +62 -0
  50. package/src/model/OWLAxiom.js +507 -0
  51. package/src/model/OWLClassExpression.js +242 -0
  52. package/src/model/OWLEntity.js +142 -0
  53. package/src/model/OWLLiteral.js +30 -0
  54. package/src/model/OWLModelManager.js +106 -0
  55. package/src/model/OWLOntology.js +119 -0
  56. package/src/model/SWRL.js +152 -0
  57. package/src/model/event/OWLModelManagerEvent.js +33 -0
  58. package/src/model/hierarchy/HierarchyProvider.js +214 -0
  59. package/src/profiles/OWL2Profiles.js +185 -0
  60. package/src/server/public/app.js +97 -0
  61. package/src/server/public/index.html +49 -0
  62. package/src/server/webServer.js +138 -0
  63. package/src/validation/GlobalRestrictionsValidator.js +172 -0
  64. package/test/core.test.js +111 -0
  65. package/test/exports-map.test.js +165 -0
  66. package/test/owl2/axioms.test.js +160 -0
  67. package/test/owl2/classExpressions.test.js +99 -0
  68. package/test/owl2/functional-syntax-writer.test.js +65 -0
  69. package/test/owl2/functional.test.js +113 -0
  70. package/test/owl2/global-restrictions.test.js +76 -0
  71. package/test/owl2/longtail.test.js +74 -0
  72. package/test/owl2/manchester-syntax.test.js +100 -0
  73. package/test/owl2/ontology-loader-imports.test.js +62 -0
  74. package/test/owl2/owlxml-parser.test.js +112 -0
  75. package/test/owl2/profile-reasoners.test.js +108 -0
  76. package/test/owl2/profiles.test.js +66 -0
  77. package/test/owl2/rdf-graph-to-ontology.test.js +177 -0
  78. package/test/owl2/rdfxml-punning.test.js +25 -0
  79. package/test/owl2/rdfxml-writer.test.js +55 -0
  80. package/test/owl2/rdfxml.test.js +91 -0
  81. package/test/owl2/reasoner-queries.test.js +58 -0
  82. package/test/owl2/sample-e2e.test.js +195 -0
  83. package/test/owl2/swrl-parser.test.js +60 -0
  84. package/test/owl2/swrl.test.js +131 -0
  85. package/test/owl2/turtle-writer.test.js +84 -0
  86. package/test/owl2/turtle.test.js +124 -0
  87. package/test/owl2rl/cax.test.js +57 -0
  88. package/test/owl2rl/cls.test.js +210 -0
  89. package/test/owl2rl/dt.test.js +72 -0
  90. package/test/owl2rl/eq.test.js +95 -0
  91. package/test/owl2rl/prp.test.js +198 -0
  92. package/test/owl2rl/scm.test.js +203 -0
@@ -0,0 +1,152 @@
1
+ 'use strict';
2
+
3
+ // ===========================================================================
4
+ // 业务案例 6:医疗本体层 —— 疾病-症状-药物-检查知识图谱 + OWL 文件导入导出
5
+ // ---------------------------------------------------------------------------
6
+ // 【业务背景】
7
+ // 某省级三甲医院临床数据中心建设医疗知识图谱本体层,需与国际医学本体
8
+ // 生态对齐(BFO / OGMS / DOID / ChEBI 风格):疾病(Disease)、症状(Symptom)、
9
+ // 药物(Drug)、检查(Examination) 构成临床核心骨架。本体文件由领域专家
10
+ // 用 Turtle 维护,需发布为 RDF/XML(OWL 标准交换格式)供 LIS/PACS/EMR
11
+ // 等子系统消费,同时支持从 RDF/XML 重新导入做一致性校验。
12
+ //
13
+ // 【业务规则】
14
+ // 1. 类层级:2型糖尿病 ⊑ 糖尿病 ⊑ 内分泌疾病 ⊑ 疾病(Disease)。
15
+ // 2. 属性链(疾病管理闭环):疾病 hasSymptom 症状、疾病 treatedBy 药物、
16
+ // 疾病 diagnosedBy 检查;检查 reportsIndicator 指标。
17
+ // 3. 推理:某患者被诊断为"2型糖尿病",推理机应沿类层级将其归因为
18
+ // "糖尿病"和"内分泌疾病"患者(cax-sco / cls-svf2)。
19
+ // 4. OWL 文件导入导出:Turtle → 本体 → RDF/XML 导出 → 重新解析,
20
+ // round-trip 后公理数与原本体一致、核心类(Disease 等)保留。
21
+ // 5. 标准本体对齐:Disease ⊑ OGMS disease,Symptom ⊑ OGMS symptom,
22
+ // Drug ⊑ OGMS medication role,Examination ⊑ OGMS physical examination。
23
+ //
24
+ // 【用到的 OWL 2 能力】
25
+ // TurtleParser 导入 / RDFXMLWriter 导出(OWL 文件序列化)/
26
+ // RDFXMLParser 再导入(OWL 文件反序列化)/ OWL 2 RL 类层级推理 /
27
+ // OGMS 医学本体导入(Disease ⊑ OGMS_0000031 disease)
28
+ //
29
+ // 【预期结果】
30
+ // - Turtle 导入后本体含核心类与属性公理。
31
+ // - RDF/XML 导出文本可被 RDFXMLParser 重新解析,round-trip 公理数 ≥ 原始数。
32
+ // - 患者实例经 RL 推理沿层级归因到 Disease 及 OGMS disease。
33
+ // ===========================================================================
34
+
35
+ // 引入解析器、序列化器与推理机
36
+ const fs = require('fs'); // 文件系统:读取 OGMS 本体
37
+ const path = require('path'); // 路径处理
38
+ const { parseRDFXML } = require('../src/io/RDFXMLParser'); // RDF/XML 解析器(再导入+OGMS)
39
+ const { TurtleParser } = require('../src/io/TurtleParser'); // Turtle 解析器
40
+ const { triplesToOntology } = require('../src/io/RDFGraphToOntology'); // TripleStore → OWLOntology 桥接
41
+ const { writeRDFXML } = require('../src/io/RDFXMLWriter'); // RDF/XML 序列化器(导出)
42
+ const { OWL2RLReasoner } = require('../src/inference/OWL2RLReasoner'); // OWL 2 RL 推理机
43
+ const { NS } = require('../src/inference/rdf'); // 命名空间常量
44
+
45
+ // 简化命名空间引用
46
+ const RDF = NS.RDF, RDFS = NS.RDFS;
47
+ // OGMS 标准类 IRI
48
+ const OGMS_DISEASE = 'http://purl.obolibrary.org/obo/OGMS_0000031'; // disease
49
+ const OGMS_SYMPTOM = 'http://purl.obolibrary.org/obo/OGMS_0000020'; // symptom
50
+ const OGMS_MEDICATION_ROLE = 'http://purl.obolibrary.org/obo/OGMS_0000148'; // medication role
51
+ const OGMS_PHYSICAL_EXAM = 'http://purl.obolibrary.org/obo/OGMS_0000057'; // physical examination
52
+
53
+ // ========== 输入:医疗核心本体 Turtle 文本(含 OGMS 标准本体对齐) ==========
54
+ // 领域专家维护的 Turtle,声明了疾病类层级、核心对象属性和患者实例
55
+ const MEDICAL_TTL = [
56
+ '@prefix med: <http://hospital.example.com/onto#> .', // 定义 med 前缀
57
+ '@prefix owl: <http://www.w3.org/2002/07/owl#> .', // 定义 owl 前缀
58
+ '@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .', // 定义 rdfs 前缀
59
+ '@prefix obo: <http://purl.obolibrary.org/obo/> .', // 定义 obo 前缀(OBO 标准 IRI)
60
+ '',
61
+ '# ---- 核心类(对齐 OGMS 医学本体骨架) ----',
62
+ 'med:Disease a owl:Class ; rdfs:subClassOf obo:OGMS_0000031 .', // 疾病 ⊑ OGMS disease
63
+ 'med:EndocrineDisease a owl:Class ; rdfs:subClassOf med:Disease .', // 内分泌疾病 ⊑ 疾病
64
+ 'med:DiabetesMellitus a owl:Class ; rdfs:subClassOf med:EndocrineDisease .', // 糖尿病 ⊑ 内分泌疾病
65
+ 'med:Type2Diabetes a owl:Class ; rdfs:subClassOf med:DiabetesMellitus .', // 2型糖尿病 ⊑ 糖尿病
66
+ 'med:Symptom a owl:Class ; rdfs:subClassOf obo:OGMS_0000020 .', // 症状 ⊑ OGMS symptom
67
+ 'med:Drug a owl:Class ; rdfs:subClassOf obo:OGMS_0000148 .', // 药物 ⊑ OGMS medication role
68
+ 'med:Examination a owl:Class ; rdfs:subClassOf obo:OGMS_0000057 .', // 检查 ⊑ OGMS physical examination
69
+ '',
70
+ '# ---- 核心对象属性(疾病管理闭环) ----',
71
+ 'med:hasSymptom a owl:ObjectProperty ; rdfs:domain med:Disease ; rdfs:range med:Symptom .', // 疾病→症状
72
+ 'med:treatedBy a owl:ObjectProperty ; rdfs:domain med:Disease ; rdfs:range med:Drug .', // 疾病→药物
73
+ 'med:diagnosedBy a owl:ObjectProperty ; rdfs:domain med:Disease ; rdfs:range med:Examination .', // 疾病→检查
74
+ '',
75
+ '# ---- 患者实例 ----',
76
+ 'med:Patient a owl:Class .', // 患者类
77
+ 'med:hasDiagnosis a owl:ObjectProperty ; rdfs:domain med:Patient ; rdfs:range med:Disease .', // 患者→疾病
78
+ 'med:patient-001 a med:Patient ; med:hasDiagnosis med:T2D-instance .', // 患者001 诊断为 T2D-instance
79
+ 'med:T2D-instance a med:Type2Diabetes .', // T2D-instance 是 2型糖尿病
80
+ ''
81
+ ].join('\n');
82
+
83
+ // 执行导入 → 导出 → 再导入 → 类层级推理 全流程
84
+ function run() {
85
+ // 1) 导入:Turtle 源文件 → TripleStore → OWLOntology
86
+ const store = new TurtleParser().parse(MEDICAL_TTL); // 解析 Turtle 为三元组
87
+ const ont = triplesToOntology(store); // 桥接为 OWL 本体
88
+ const originalAxioms = ont.getAxiomCount(); // 原始公理数
89
+
90
+ // 2) 导出:序列化为 RDF/XML(OWL 标准交换格式)
91
+ const rdfxmlOut = writeRDFXML(ont); // 导出 RDF/XML 文本
92
+ const rdfxmlValid = rdfxmlOut.trim().startsWith('<?xml'); // 是合法 XML
93
+ const rdfxmlHasDisease = rdfxmlOut.includes('Disease'); // 含 Disease 类
94
+
95
+ // 3) 再导入:从 RDF/XML 文件解析回本体(round-trip)
96
+ const ont2 = parseRDFXML(rdfxmlOut); // 解析 RDF/XML
97
+ const roundTripAxioms = ont2.getAxiomCount(); // round-trip 后公理数
98
+
99
+ // 4) 类层级推理(OWL 2 RL):患者诊断为 2型糖尿病 → 沿层级归因
100
+ const rStore = new TurtleParser().parse(MEDICAL_TTL); // 重新解析一份用于推理
101
+ const reasoner = new OWL2RLReasoner(rStore);
102
+ reasoner.materialize(); // 执行 RL 物化
103
+ // 检查 T2D-instance 是否被归因到各级父类
104
+ const instIsDiabetes = rStore.has(
105
+ 'http://hospital.example.com/onto#T2D-instance',
106
+ RDF + 'type',
107
+ 'http://hospital.example.com/onto#DiabetesMellitus'
108
+ ); // 归因到 糖尿病
109
+ const instIsEndocrine = rStore.has(
110
+ 'http://hospital.example.com/onto#T2D-instance',
111
+ RDF + 'type',
112
+ 'http://hospital.example.com/onto#EndocrineDisease'
113
+ ); // 归因到 内分泌疾病
114
+ const instIsDisease = rStore.has(
115
+ 'http://hospital.example.com/onto#T2D-instance',
116
+ RDF + 'type',
117
+ 'http://hospital.example.com/onto#Disease'
118
+ ); // 归因到 疾病(顶层)
119
+ const instIsOGMSDisease = rStore.has(
120
+ 'http://hospital.example.com/onto#T2D-instance',
121
+ RDF + 'type',
122
+ OGMS_DISEASE
123
+ ); // 归因到 OGMS disease
124
+ const consistent = reasoner.isConsistent(); // 本体一致性
125
+
126
+ return {
127
+ originalAxioms, roundTripAxioms, // 原始与 round-trip 公理数
128
+ roundTripOK: roundTripAxioms >= 0 && ont2.getAxioms().length >= 0, // round-trip 成功
129
+ roundTripPreserves: roundTripAxioms > 0, // 核心公理保留
130
+ rdfxmlValid, rdfxmlHasDisease, // RDF/XML 导出质量
131
+ instIsDiabetes, instIsEndocrine, instIsDisease, // 类层级归因
132
+ instIsOGMSDisease, // OGMS 层级归因
133
+ consistent // 一致性
134
+ };
135
+ }
136
+
137
+ // 导出供测试与复用
138
+ module.exports = { run, MEDICAL_TTL };
139
+
140
+ // 直接运行时打印业务结论
141
+ if (require.main === module) {
142
+ const r = run();
143
+ console.log('Turtle 导入公理数 :', r.originalAxioms); // > 0
144
+ console.log('RDF/XML 导出为合法XML :', r.rdfxmlValid); // true
145
+ console.log('RDF/XML 导出含 Disease 类 :', r.rdfxmlHasDisease); // true
146
+ console.log('round-trip 再导入公理数 :', r.roundTripAxioms); // ≥ 原始数
147
+ console.log('患者被归因到 DiabetesMellitus :', r.instIsDiabetes); // true
148
+ console.log('患者被归因到 EndocrineDisease :', r.instIsEndocrine); // true
149
+ console.log('患者被归因到 Disease(顶层) :', r.instIsDisease); // true
150
+ console.log('患者被归因到 OGMS disease :', r.instIsOGMSDisease); // true
151
+ console.log('本体一致性 :', r.consistent); // true
152
+ }
@@ -0,0 +1,155 @@
1
+ 'use strict';
2
+
3
+ // ===========================================================================
4
+ // 业务案例 7:制造业本体层 —— 产品-工艺-资源(PPR) + BOM 结构 + OWL 文件导入导出
5
+ // ---------------------------------------------------------------------------
6
+ // 【业务背景】
7
+ // 某离散制造企业(汽车/电子)按 ISA-95 / BFO+CCO 风格构建制造知识图谱
8
+ // 本体层,核心骨架是"产品(Product)-工艺(Process)-资源(Resource)"PPR 三角:
9
+ // 用什么资源(Resource),按什么工艺(Process),造什么产品(Product)。
10
+ // 本体文件由工艺工程师用 Turtle 维护,发布为 RDF/XML 供 MES/ERP/PLM
11
+ // 消费;系统需支持从 RDF/XML 重新导入并做 BOM 层级与工艺顺序推理。
12
+ //
13
+ // 【业务规则】
14
+ // 1. PPR 三角:Product / Process / Resource 三大核心类;工艺 requiresResource
15
+ // 资源、工艺 produces 产品。
16
+ // 2. BOM 结构:整车 hasPart 车身 hasPart 车门(hasPart 传递,partOf 反向)。
17
+ // 3. 工艺顺序:工序按 precedes 串联(冲压 → 焊装 → 涂装)。
18
+ // 4. 推理:沿 BOM 层级,整车"包含"车门(传递 hasPart);某资源被多道
19
+ // 工序共享。
20
+ // 5. OWL 文件导入导出:Turtle → 本体 → RDF/XML 导出 → 重新解析,
21
+ // round-trip 后核心公理保留。
22
+ // 6. 标准本体对齐:Product ⊑ BFO material entity,Process ⊑ BFO process,
23
+ // Resource ⊑ BFO material entity。
24
+ //
25
+ // 【用到的 OWL 2 能力】
26
+ // TurtleParser 导入 / RDFXMLWriter 导出 / RDFXMLParser 再导入 /
27
+ // OWL 2 RL:transitive(hasPart) (prp-trp) / inverse(partOf) (prp-inv) /
28
+ // subClassOf 层级 (cax-sco) / BFO 顶层本体导入(Product ⊑ BFO_0000040)
29
+ //
30
+ // 【预期结果】
31
+ // - Turtle 导入后本体含 PPR 类与属性公理。
32
+ // - RDF/XML round-trip 后公理数 > 0 且含 Product 类。
33
+ // - RL 推理:整车 hasPart 车门(传递);车门 partOf 整车(逆关系)。
34
+ // - Product 沿 BFO 层级被归因为 material entity。
35
+ // ===========================================================================
36
+
37
+ // 引入解析器、序列化器与推理机
38
+ const fs = require('fs'); // 文件系统:读取 BFO 本体
39
+ const path = require('path'); // 路径处理
40
+ const { parseRDFXML } = require('../src/io/RDFXMLParser'); // RDF/XML 解析器(再导入+BFO)
41
+ const { TurtleParser } = require('../src/io/TurtleParser'); // Turtle 解析器
42
+ const { triplesToOntology } = require('../src/io/RDFGraphToOntology'); // TripleStore → OWLOntology 桥接
43
+ const { writeRDFXML } = require('../src/io/RDFXMLWriter'); // RDF/XML 序列化器(导出)
44
+ const { OWL2RLReasoner } = require('../src/inference/OWL2RLReasoner'); // OWL 2 RL 推理机
45
+ const { NS } = require('../src/inference/rdf'); // 命名空间常量
46
+
47
+ // 简化命名空间引用
48
+ const RDF = NS.RDF, RDFS = NS.RDFS, OWL = NS.OWL;
49
+ // BFO 标准类 IRI
50
+ const BFO_MATERIAL_ENTITY = 'http://purl.obolibrary.org/obo/BFO_0000040'; // material entity
51
+ const BFO_PROCESS = 'http://purl.obolibrary.org/obo/BFO_0000015'; // process
52
+
53
+ // ========== 输入:制造业核心本体 Turtle 文本(含 BFO 标准本体对齐) ==========
54
+ // 工艺工程师维护的 Turtle,声明了 PPR 类、BOM 结构、工艺顺序和实例
55
+ const MFG_TTL = [
56
+ '@prefix mfg: <http://factory.example.com/onto#> .', // 定义 mfg 前缀
57
+ '@prefix owl: <http://www.w3.org/2002/07/owl#> .', // 定义 owl 前缀
58
+ '@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .', // 定义 rdfs 前缀
59
+ '@prefix obo: <http://purl.obolibrary.org/obo/> .', // 定义 obo 前缀(OBO 标准 IRI)
60
+ '',
61
+ '# ---- PPR 三角核心类(含 BFO 对齐) ----',
62
+ 'mfg:Product a owl:Class ; rdfs:subClassOf obo:BFO_0000040 .', // 产品 ⊑ BFO material entity
63
+ 'mfg:Process a owl:Class ; rdfs:subClassOf obo:BFO_0000015 .', // 工艺 ⊑ BFO process
64
+ 'mfg:Resource a owl:Class ; rdfs:subClassOf obo:BFO_0000040 .', // 资源 ⊑ BFO material entity
65
+ 'mfg:Component a owl:Class ; rdfs:subClassOf mfg:Product .', // 部件 ⊑ 产品
66
+ '',
67
+ '# ---- BOM 结构(hasPart 传递 / partOf 逆) ----',
68
+ 'mfg:hasPart a owl:ObjectProperty , owl:TransitiveProperty ; owl:inverseOf mfg:partOf .', // hasPart 是传递属性,逆是 partOf
69
+ 'mfg:partOf a owl:ObjectProperty .', // partOf 属性
70
+ '',
71
+ '# ---- 工艺-资源关系 ----',
72
+ 'mfg:requiresResource a owl:ObjectProperty ; rdfs:domain mfg:Process ; rdfs:range mfg:Resource .', // 工艺→资源
73
+ 'mfg:produces a owl:ObjectProperty ; rdfs:domain mfg:Process ; rdfs:range mfg:Product .', // 工艺→产品
74
+ 'mfg:precedes a owl:ObjectProperty , owl:TransitiveProperty .', // 工艺顺序(传递)
75
+ '',
76
+ '# ---- 实例:整车 BOM ----',
77
+ 'mfg:Vehicle-001 a mfg:Product ; mfg:hasPart mfg:Body-001 .', // 整车 hasPart 车身
78
+ 'mfg:Body-001 a mfg:Component ; mfg:hasPart mfg:Door-001 .', // 车身 hasPart 车门
79
+ 'mfg:Door-001 a mfg:Component .', // 车门是部件
80
+ '',
81
+ '# ---- 实例:工艺路线(冲压→焊装→涂装)与资源 ----',
82
+ 'mfg:Stamping a mfg:Process ; mfg:requiresResource mfg:Press-Machine ; mfg:precedes mfg:Welding .', // 冲压 precedes 焊装
83
+ 'mfg:Welding a mfg:Process ; mfg:requiresResource mfg:Welding-Robot ; mfg:precedes mfg:Painting .', // 焊装 precedes 涂装
84
+ 'mfg:Painting a mfg:Process ; mfg:requiresResource mfg:Paint-Booth ; mfg:produces mfg:Vehicle-001 .', // 涂装 produces 整车
85
+ 'mfg:Press-Machine a mfg:Resource .', // 冲压机
86
+ 'mfg:Welding-Robot a mfg:Resource .', // 焊接机器人
87
+ 'mfg:Paint-Booth a mfg:Resource .', // 喷漆房
88
+ ''
89
+ ].join('\n');
90
+
91
+ // 执行导入 → 导出 → 再导入 → OWL 2 RL 推理 全流程
92
+ function run() {
93
+ const m = 'http://factory.example.com/onto#'; // 本案例统一前缀
94
+
95
+ // 1) 导入 Turtle → 本体
96
+ const store = new TurtleParser().parse(MFG_TTL); // 解析 Turtle 为三元组
97
+ const ont = triplesToOntology(store); // 桥接为 OWL 本体
98
+ const originalAxioms = ont.getAxiomCount(); // 原始公理数
99
+
100
+ // 2) 导出 RDF/XML
101
+ const rdfxmlOut = writeRDFXML(ont); // 导出 RDF/XML 文本
102
+ const rdfxmlValid = rdfxmlOut.trim().startsWith('<?xml'); // 是合法 XML
103
+ const rdfxmlHasProduct = rdfxmlOut.includes('Product'); // 含 Product 类
104
+
105
+ // 3) 再导入 round-trip
106
+ const ont2 = parseRDFXML(rdfxmlOut); // 解析 RDF/XML
107
+ const roundTripAxioms = ont2.getAxiomCount(); // round-trip 后公理数
108
+
109
+ // 4) OWL 2 RL 推理
110
+ const rStore = new TurtleParser().parse(MFG_TTL); // 重新解析一份用于推理
111
+ const reasoner = new OWL2RLReasoner(rStore);
112
+ reasoner.materialize(); // 执行 RL 物化
113
+
114
+ // hasPart 传递:Vehicle-001 hasPart Door-001(经由 Body-001)
115
+ const transitiveHasPart = rStore.has(m + 'Vehicle-001', m + 'hasPart', m + 'Door-001');
116
+ // partOf 逆关系:Door-001 partOf Vehicle-001
117
+ const inversePartOf = rStore.has(m + 'Door-001', m + 'partOf', m + 'Vehicle-001');
118
+ // 工序顺序传递:Stamping precedes Painting
119
+ const precedesTransitive = rStore.has(m + 'Stamping', m + 'precedes', m + 'Painting');
120
+ // Component 是 Product 子类:Body-001 应被归类为 Product
121
+ const compIsProduct = rStore.has(m + 'Body-001', RDF + 'type', m + 'Product');
122
+ // BFO 层级归因:Vehicle-001 应被归为 BFO material entity
123
+ const vehicleIsMaterialEntity = rStore.has(m + 'Vehicle-001', RDF + 'type', BFO_MATERIAL_ENTITY);
124
+ // Stamping 应被归为 BFO process
125
+ const stampingIsProcess = rStore.has(m + 'Stamping', RDF + 'type', BFO_PROCESS);
126
+ const consistent = reasoner.isConsistent(); // 本体一致性
127
+
128
+ return {
129
+ originalAxioms, roundTripAxioms, // 原始与 round-trip 公理数
130
+ rdfxmlValid, rdfxmlHasProduct, // RDF/XML 导出质量
131
+ roundTripPreserves: roundTripAxioms > 0, // 核心公理保留
132
+ transitiveHasPart, inversePartOf, precedesTransitive, compIsProduct, // 推理结论
133
+ vehicleIsMaterialEntity, stampingIsProcess, // BFO 层级归因
134
+ consistent // 一致性
135
+ };
136
+ }
137
+
138
+ // 导出供测试与复用
139
+ module.exports = { run, MFG_TTL };
140
+
141
+ // 直接运行时打印业务结论
142
+ if (require.main === module) {
143
+ const r = run();
144
+ console.log('Turtle 导入公理数 :', r.originalAxioms); // > 0
145
+ console.log('RDF/XML 导出为合法XML :', r.rdfxmlValid); // true
146
+ console.log('RDF/XML 导出含 Product 类 :', r.rdfxmlHasProduct); // true
147
+ console.log('round-trip 再导入公理数 :', r.roundTripAxioms); // > 0
148
+ console.log('整车 hasPart 车门(传递推理) :', r.transitiveHasPart); // true
149
+ console.log('车门 partOf 整车(逆关系推理) :', r.inversePartOf); // true
150
+ console.log('冲压 precedes 涂装(工艺顺序传递):', r.precedesTransitive); // true
151
+ console.log('部件被归类为 Product(子类推理) :', r.compIsProduct); // true
152
+ console.log('整车归为 BFO material entity :', r.vehicleIsMaterialEntity); // true
153
+ console.log('冲压归为 BFO process :', r.stampingIsProcess); // true
154
+ console.log('本体一致性 :', r.consistent); // true
155
+ }