eyeling 1.24.5 → 1.24.7

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 (294) hide show
  1. package/HANDBOOK.md +0 -99
  2. package/README.md +2 -2
  3. package/dist/browser/eyeling.browser.js +6 -0
  4. package/{see/examples/n3 → examples}/annotation.n3 +1 -1
  5. package/{see/examples/n3/backward_recursion.n3 → examples/backward-recursion.n3} +0 -2
  6. package/examples/collection.n3 +3 -0
  7. package/examples/context-association.n3 +59 -0
  8. package/{see/examples/n3/dijkstra_risk_path.n3 → examples/dijkstra-risk-path.n3} +3 -18
  9. package/{see/examples/n3/eco_route_insight.n3 → examples/eco-route-insight.n3} +2 -47
  10. package/{see/examples/n3/genetic_knapsack_selection.n3 → examples/genetic-knapsack-selection.n3} +2 -24
  11. package/{see/examples → examples}/input/annotation.trig +3 -3
  12. package/{see/examples/input/backward_recursion.trig → examples/input/backward-recursion.trig} +2 -2
  13. package/{see/examples/input/builtin_coverage.trig → examples/input/builtin-coverage.trig} +2 -2
  14. package/{see/examples → examples}/input/collection.trig +3 -3
  15. package/examples/input/context-association.trig +35 -0
  16. package/{see/examples/input/dijkstra_risk_path.trig → examples/input/dijkstra-risk-path.trig} +4 -4
  17. package/{see/examples/input/eco_route_insight.trig → examples/input/eco-route-insight.trig} +4 -4
  18. package/{see/examples/input/genetic_knapsack_selection.trig → examples/input/genetic-knapsack-selection.trig} +4 -4
  19. package/{see/examples/input/rc_discharge_envelope.trig → examples/input/rc-discharge-envelope.trig} +4 -4
  20. package/{see/examples/input/rdf_dataset.trig → examples/input/rdf-dataset.trig} +4 -4
  21. package/{see/examples/input/rdf_message_flow.trig → examples/input/rdf-message-flow.trig} +3 -3
  22. package/{see/examples/input/rdf_messages.trig → examples/input/rdf-messages.trig} +4 -4
  23. package/{see/examples/input/school_placement_audit.trig → examples/input/school-placement-audit.trig} +4 -4
  24. package/{see/examples/input/smoke_arithmetic.trig → examples/input/smoke-arithmetic.trig} +3 -3
  25. package/{see/examples/input/triple_terms.trig → examples/input/triple-terms.trig} +3 -3
  26. package/examples/output/annotation.n3 +0 -0
  27. package/examples/output/backward-recursion.n3 +4 -0
  28. package/examples/output/builtin-coverage.n3 +0 -0
  29. package/examples/output/collection.n3 +0 -0
  30. package/examples/output/context-association.n3 +9 -0
  31. package/examples/output/dijkstra-risk-path.n3 +3 -0
  32. package/examples/output/eco-route-insight.n3 +3 -0
  33. package/examples/output/genetic-knapsack-selection.n3 +3 -0
  34. package/examples/output/rc-discharge-envelope.n3 +9 -0
  35. package/examples/output/rc-discharge-envelope.txt +9 -0
  36. package/examples/output/rdf-dataset.n3 +5 -0
  37. package/examples/output/rdf-message-flow.n3 +7 -0
  38. package/examples/output/rdf-messages.n3 +7 -0
  39. package/examples/output/school-placement-audit.n3 +3 -0
  40. package/examples/output/smoke-arithmetic.n3 +5 -0
  41. package/examples/output/smoke-arithmetic.txt +5 -0
  42. package/examples/output/triple-terms.n3 +5 -0
  43. package/{see/examples/n3/rc_discharge_envelope.n3 → examples/rc-discharge-envelope.n3} +2 -15
  44. package/{see/examples/n3/rdf_dataset.n3 → examples/rdf-dataset.n3} +2 -11
  45. package/{see/examples/n3/rdf_message_flow.n3 → examples/rdf-message-flow.n3} +9 -75
  46. package/{see/examples/n3/rdf_messages.n3 → examples/rdf-messages.n3} +6 -43
  47. package/{see/examples/n3/school_placement_audit.n3 → examples/school-placement-audit.n3} +2 -14
  48. package/{see/examples/n3/smoke_arithmetic.n3 → examples/smoke-arithmetic.n3} +3 -5
  49. package/{see/examples/n3/triple_terms.n3 → examples/triple-terms.n3} +1 -4
  50. package/eyeling.js +6 -0
  51. package/lib/builtins.js +6 -0
  52. package/package.json +4 -7
  53. package/test/api.test.js +25 -8
  54. package/test/examples.test.js +22 -2
  55. package/test/package.test.js +16 -2
  56. package/see/README.md +0 -149
  57. package/see/examples/_see.js +0 -249
  58. package/see/examples/age.js +0 -1459
  59. package/see/examples/annotation.js +0 -1320
  60. package/see/examples/backward.js +0 -1405
  61. package/see/examples/backward_recursion.js +0 -1504
  62. package/see/examples/bayes_diagnosis.js +0 -2883
  63. package/see/examples/bayes_therapy.js +0 -4152
  64. package/see/examples/bmi.js +0 -3038
  65. package/see/examples/builtin_coverage.js +0 -2524
  66. package/see/examples/collection.js +0 -1320
  67. package/see/examples/complex.js +0 -3762
  68. package/see/examples/complex_matrix_stability.js +0 -2973
  69. package/see/examples/composition_of_injective_functions_is_injective.js +0 -2170
  70. package/see/examples/control_system.js +0 -1918
  71. package/see/examples/crypto_builtins_tests.js +0 -1489
  72. package/see/examples/delfour.js +0 -3174
  73. package/see/examples/digital_product_passport.js +0 -2856
  74. package/see/examples/dijkstra.js +0 -2070
  75. package/see/examples/dijkstra_risk_path.js +0 -1874
  76. package/see/examples/doc/age.md +0 -27
  77. package/see/examples/doc/annotation.md +0 -24
  78. package/see/examples/doc/backward.md +0 -26
  79. package/see/examples/doc/backward_recursion.md +0 -26
  80. package/see/examples/doc/bayes_diagnosis.md +0 -41
  81. package/see/examples/doc/bayes_therapy.md +0 -40
  82. package/see/examples/doc/bmi.md +0 -38
  83. package/see/examples/doc/builtin_coverage.md +0 -53
  84. package/see/examples/doc/collection.md +0 -24
  85. package/see/examples/doc/complex.md +0 -38
  86. package/see/examples/doc/complex_matrix_stability.md +0 -35
  87. package/see/examples/doc/composition_of_injective_functions_is_injective.md +0 -24
  88. package/see/examples/doc/control_system.md +0 -32
  89. package/see/examples/doc/crypto_builtins_tests.md +0 -27
  90. package/see/examples/doc/delfour.md +0 -37
  91. package/see/examples/doc/digital_product_passport.md +0 -36
  92. package/see/examples/doc/dijkstra.md +0 -28
  93. package/see/examples/doc/dijkstra_risk_path.md +0 -30
  94. package/see/examples/doc/dog.md +0 -28
  95. package/see/examples/doc/eco_route_insight.md +0 -33
  96. package/see/examples/doc/equals.md +0 -26
  97. package/see/examples/doc/equivalence_classes_overlap_implies_same_class.md +0 -24
  98. package/see/examples/doc/euler_identity.md +0 -39
  99. package/see/examples/doc/ev_roundtrip_planner.md +0 -32
  100. package/see/examples/doc/existential_rule.md +0 -24
  101. package/see/examples/doc/expression_eval.md +0 -26
  102. package/see/examples/doc/family_cousins.md +0 -24
  103. package/see/examples/doc/fastpow.md +0 -29
  104. package/see/examples/doc/fibonacci.md +0 -28
  105. package/see/examples/doc/french_cities.md +0 -28
  106. package/see/examples/doc/fundamental_theorem_arithmetic.md +0 -36
  107. package/see/examples/doc/genetic_knapsack_selection.md +0 -29
  108. package/see/examples/doc/goldbach_1000.md +0 -31
  109. package/see/examples/doc/good_cobbler.md +0 -27
  110. package/see/examples/doc/gps.md +0 -35
  111. package/see/examples/doc/gray_code_counter.md +0 -31
  112. package/see/examples/doc/greatest_lower_bound_uniqueness.md +0 -24
  113. package/see/examples/doc/group_inverse_uniqueness.md +0 -24
  114. package/see/examples/doc/hadamard_approx.md +0 -32
  115. package/see/examples/doc/hanoi.md +0 -26
  116. package/see/examples/doc/odrl_dpv_risk_ranked.md +0 -57
  117. package/see/examples/doc/path_discovery.md +0 -33
  118. package/see/examples/doc/rc_discharge_envelope.md +0 -33
  119. package/see/examples/doc/rdf_dataset.md +0 -26
  120. package/see/examples/doc/rdf_message_flow.md +0 -35
  121. package/see/examples/doc/rdf_messages.md +0 -37
  122. package/see/examples/doc/school_placement_audit.md +0 -31
  123. package/see/examples/doc/smoke_arithmetic.md +0 -31
  124. package/see/examples/doc/socrates.md +0 -24
  125. package/see/examples/doc/triple_terms.md +0 -26
  126. package/see/examples/doc/wind_turbine.md +0 -37
  127. package/see/examples/doc/witch.md +0 -28
  128. package/see/examples/dog.js +0 -1436
  129. package/see/examples/eco_route_insight.js +0 -2110
  130. package/see/examples/equals.js +0 -1363
  131. package/see/examples/equivalence_classes_overlap_implies_same_class.js +0 -1792
  132. package/see/examples/euler_identity.js +0 -2038
  133. package/see/examples/ev_roundtrip_planner.js +0 -2562
  134. package/see/examples/existential_rule.js +0 -1363
  135. package/see/examples/expression_eval.js +0 -1798
  136. package/see/examples/family_cousins.js +0 -1586
  137. package/see/examples/fastpow.js +0 -2207
  138. package/see/examples/fibonacci.js +0 -1594
  139. package/see/examples/french_cities.js +0 -1492
  140. package/see/examples/fundamental_theorem_arithmetic.js +0 -2106
  141. package/see/examples/genetic_knapsack_selection.js +0 -1743
  142. package/see/examples/goldbach_1000.js +0 -1798
  143. package/see/examples/good_cobbler.js +0 -1396
  144. package/see/examples/gps.js +0 -2813
  145. package/see/examples/gray_code_counter.js +0 -1641
  146. package/see/examples/greatest_lower_bound_uniqueness.js +0 -1918
  147. package/see/examples/group_inverse_uniqueness.js +0 -1897
  148. package/see/examples/hadamard_approx.js +0 -4417
  149. package/see/examples/hanoi.js +0 -1625
  150. package/see/examples/input/age.trig +0 -27
  151. package/see/examples/input/backward.trig +0 -25
  152. package/see/examples/input/bayes_diagnosis.trig +0 -111
  153. package/see/examples/input/bayes_therapy.trig +0 -130
  154. package/see/examples/input/bmi.trig +0 -28
  155. package/see/examples/input/complex.trig +0 -26
  156. package/see/examples/input/complex_matrix_stability.trig +0 -65
  157. package/see/examples/input/composition_of_injective_functions_is_injective.trig +0 -35
  158. package/see/examples/input/control_system.trig +0 -31
  159. package/see/examples/input/crypto_builtins_tests.trig +0 -25
  160. package/see/examples/input/delfour.trig +0 -90
  161. package/see/examples/input/digital_product_passport.trig +0 -116
  162. package/see/examples/input/dijkstra.trig +0 -34
  163. package/see/examples/input/dog.trig +0 -31
  164. package/see/examples/input/equals.trig +0 -25
  165. package/see/examples/input/equivalence_classes_overlap_implies_same_class.trig +0 -28
  166. package/see/examples/input/euler_identity.trig +0 -34
  167. package/see/examples/input/ev_roundtrip_planner.trig +0 -90
  168. package/see/examples/input/existential_rule.trig +0 -26
  169. package/see/examples/input/expression_eval.trig +0 -41
  170. package/see/examples/input/family_cousins.trig +0 -39
  171. package/see/examples/input/fastpow.trig +0 -25
  172. package/see/examples/input/fibonacci.trig +0 -51
  173. package/see/examples/input/french_cities.trig +0 -38
  174. package/see/examples/input/fundamental_theorem_arithmetic.trig +0 -42
  175. package/see/examples/input/goldbach_1000.trig +0 -53
  176. package/see/examples/input/good_cobbler.trig +0 -24
  177. package/see/examples/input/gps.trig +0 -35
  178. package/see/examples/input/gray_code_counter.trig +0 -33
  179. package/see/examples/input/greatest_lower_bound_uniqueness.trig +0 -29
  180. package/see/examples/input/group_inverse_uniqueness.trig +0 -29
  181. package/see/examples/input/hadamard_approx.trig +0 -32
  182. package/see/examples/input/hanoi.trig +0 -26
  183. package/see/examples/input/odrl_dpv_risk_ranked.trig +0 -107
  184. package/see/examples/input/path-discovery.trig +0 -96448
  185. package/see/examples/input/path_discovery.trig +0 -29
  186. package/see/examples/input/socrates.trig +0 -26
  187. package/see/examples/input/wind_turbine.trig +0 -48
  188. package/see/examples/input/witch.trig +0 -26
  189. package/see/examples/n3/age.n3 +0 -28
  190. package/see/examples/n3/backward.n3 +0 -22
  191. package/see/examples/n3/bayes_diagnosis.n3 +0 -122
  192. package/see/examples/n3/bayes_therapy.n3 +0 -149
  193. package/see/examples/n3/bmi.n3 +0 -145
  194. package/see/examples/n3/collection.n3 +0 -3
  195. package/see/examples/n3/complex.n3 +0 -140
  196. package/see/examples/n3/complex_matrix_stability.n3 +0 -113
  197. package/see/examples/n3/composition_of_injective_functions_is_injective.n3 +0 -27
  198. package/see/examples/n3/control_system.n3 +0 -59
  199. package/see/examples/n3/crypto_builtins_tests.n3 +0 -18
  200. package/see/examples/n3/delfour.n3 +0 -167
  201. package/see/examples/n3/digital_product_passport.n3 +0 -156
  202. package/see/examples/n3/dijkstra.n3 +0 -46
  203. package/see/examples/n3/dog.n3 +0 -20
  204. package/see/examples/n3/equals.n3 +0 -11
  205. package/see/examples/n3/equivalence_classes_overlap_implies_same_class.n3 +0 -19
  206. package/see/examples/n3/euler_identity.n3 +0 -41
  207. package/see/examples/n3/ev_roundtrip_planner.n3 +0 -82
  208. package/see/examples/n3/existential_rule.n3 +0 -10
  209. package/see/examples/n3/expression_eval.n3 +0 -21
  210. package/see/examples/n3/family_cousins.n3 +0 -62
  211. package/see/examples/n3/fastpow.n3 +0 -56
  212. package/see/examples/n3/fibonacci.n3 +0 -44
  213. package/see/examples/n3/french_cities.n3 +0 -28
  214. package/see/examples/n3/fundamental_theorem_arithmetic.n3 +0 -84
  215. package/see/examples/n3/goldbach_1000.n3 +0 -66
  216. package/see/examples/n3/good_cobbler.n3 +0 -10
  217. package/see/examples/n3/gps.n3 +0 -70
  218. package/see/examples/n3/gray_code_counter.n3 +0 -53
  219. package/see/examples/n3/greatest_lower_bound_uniqueness.n3 +0 -20
  220. package/see/examples/n3/group_inverse_uniqueness.n3 +0 -19
  221. package/see/examples/n3/hadamard_approx.n3 +0 -43
  222. package/see/examples/n3/hanoi.n3 +0 -16
  223. package/see/examples/n3/odrl_dpv_risk_ranked.n3 +0 -460
  224. package/see/examples/n3/path_discovery.n3 +0 -43
  225. package/see/examples/n3/socrates.n3 +0 -21
  226. package/see/examples/n3/wind_turbine.n3 +0 -85
  227. package/see/examples/n3/witch.n3 +0 -30
  228. package/see/examples/odrl_dpv_risk_ranked.js +0 -5128
  229. package/see/examples/output/age.md +0 -48
  230. package/see/examples/output/annotation.md +0 -43
  231. package/see/examples/output/backward.md +0 -50
  232. package/see/examples/output/backward_recursion.md +0 -54
  233. package/see/examples/output/bayes_diagnosis.md +0 -103
  234. package/see/examples/output/bayes_therapy.md +0 -84
  235. package/see/examples/output/bmi.md +0 -164
  236. package/see/examples/output/builtin_coverage.md +0 -99
  237. package/see/examples/output/collection.md +0 -44
  238. package/see/examples/output/complex.md +0 -61
  239. package/see/examples/output/complex_matrix_stability.md +0 -55
  240. package/see/examples/output/composition_of_injective_functions_is_injective.md +0 -62
  241. package/see/examples/output/control_system.md +0 -61
  242. package/see/examples/output/crypto_builtins_tests.md +0 -68
  243. package/see/examples/output/delfour.md +0 -100
  244. package/see/examples/output/digital_product_passport.md +0 -100
  245. package/see/examples/output/dijkstra.md +0 -74
  246. package/see/examples/output/dijkstra_risk_path.md +0 -76
  247. package/see/examples/output/dog.md +0 -50
  248. package/see/examples/output/eco_route_insight.md +0 -88
  249. package/see/examples/output/equals.md +0 -50
  250. package/see/examples/output/equivalence_classes_overlap_implies_same_class.md +0 -86
  251. package/see/examples/output/euler_identity.md +0 -73
  252. package/see/examples/output/ev_roundtrip_planner.md +0 -79
  253. package/see/examples/output/existential_rule.md +0 -54
  254. package/see/examples/output/expression_eval.md +0 -50
  255. package/see/examples/output/family_cousins.md +0 -187
  256. package/see/examples/output/fastpow.md +0 -36
  257. package/see/examples/output/fibonacci.md +0 -53
  258. package/see/examples/output/french_cities.md +0 -70
  259. package/see/examples/output/fundamental_theorem_arithmetic.md +0 -101
  260. package/see/examples/output/genetic_knapsack_selection.md +0 -66
  261. package/see/examples/output/goldbach_1000.md +0 -58
  262. package/see/examples/output/good_cobbler.md +0 -54
  263. package/see/examples/output/gps.md +0 -102
  264. package/see/examples/output/gray_code_counter.md +0 -68
  265. package/see/examples/output/greatest_lower_bound_uniqueness.md +0 -60
  266. package/see/examples/output/group_inverse_uniqueness.md +0 -60
  267. package/see/examples/output/hadamard_approx.md +0 -510
  268. package/see/examples/output/hanoi.md +0 -51
  269. package/see/examples/output/odrl_dpv_risk_ranked.md +0 -139
  270. package/see/examples/output/path_discovery.md +0 -65
  271. package/see/examples/output/rc_discharge_envelope.md +0 -102
  272. package/see/examples/output/rdf_dataset.md +0 -54
  273. package/see/examples/output/rdf_message_flow.md +0 -198
  274. package/see/examples/output/rdf_messages.md +0 -134
  275. package/see/examples/output/school_placement_audit.md +0 -99
  276. package/see/examples/output/smoke_arithmetic.md +0 -54
  277. package/see/examples/output/socrates.md +0 -55
  278. package/see/examples/output/triple_terms.md +0 -53
  279. package/see/examples/output/wind_turbine.md +0 -108
  280. package/see/examples/output/witch.md +0 -87
  281. package/see/examples/path_discovery.js +0 -1774
  282. package/see/examples/rc_discharge_envelope.js +0 -1993
  283. package/see/examples/rdf_dataset.js +0 -1512
  284. package/see/examples/rdf_message_flow.js +0 -2580
  285. package/see/examples/rdf_messages.js +0 -2176
  286. package/see/examples/school_placement_audit.js +0 -1867
  287. package/see/examples/smoke_arithmetic.js +0 -1483
  288. package/see/examples/socrates.js +0 -1420
  289. package/see/examples/triple_terms.js +0 -1442
  290. package/see/examples/wind_turbine.js +0 -2853
  291. package/see/examples/witch.js +0 -1519
  292. package/see/see.js +0 -2179
  293. package/test/see.test.js +0 -159
  294. /package/{see/examples/n3/builtin_coverage.n3 → examples/builtin-coverage.n3} +0 -0
@@ -1,4152 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
- const fs = require('fs');
4
- const path = require('path');
5
- const { fail, loadInput } = require('./_see');
6
-
7
- const crypto = require('crypto');
8
-
9
- function canonical(term) {
10
- if (term.kind === 'list') return ['list', term.items.map(canonical)];
11
- if (term.kind === 'triple') return ['triple', canonical(term.s), canonical(term.p), canonical(term.o)];
12
- if (term.kind === 'formula') return ['formula', term.atoms.map((a) => [canonical(a.s), canonical(a.p), canonical(a.o)])];
13
- return [term.kind, term.value];
14
- }
15
- function factKey(f) { return JSON.stringify([canonical(f.s), canonical(f.p), canonical(f.o)]); }
16
- function termIndexKey(t) { return JSON.stringify(canonical(t)); }
17
- function compoundIndexKey() { return Array.from(arguments).map(termIndexKey).join('\u001f'); }
18
- function termIsConcrete(t) {
19
- if (!t || t.kind === 'var') return false;
20
- if (t.kind === 'list') return t.items.every(termIsConcrete);
21
- if (t.kind === 'triple') return termIsConcrete(t.s) && termIsConcrete(t.p) && termIsConcrete(t.o);
22
- if (t.kind === 'formula') return t.atoms.every((a) => termIsConcrete(a.s) && termIsConcrete(a.p) && termIsConcrete(a.o));
23
- return true;
24
- }
25
- function isVar(t) { return t && t.kind === 'var'; }
26
- function isIri(t, iri) { return t && t.kind === 'iri' && t.value === iri; }
27
- function lit(value) { return { kind: 'lit', value }; }
28
- function blank(value) { return { kind: 'blank', value }; }
29
- function list(items) { return { kind: 'list', items }; }
30
- function cloneTerm(t) { return JSON.parse(JSON.stringify(t)); }
31
- function primitive(t) {
32
- if (!t) return undefined;
33
- if (t.kind === 'lit') return t.value;
34
- if (t.kind === 'iri') return t.value.replace(/^:/, '');
35
- if (t.kind === 'blank') return t.value;
36
- if (t.kind === 'list') return t.items.map(primitive);
37
- if (t.kind === 'triple') return termToN3(t);
38
- if (t.kind === 'formula') return termToN3(t);
39
- return undefined;
40
- }
41
- function literalToN3(value) {
42
- if (typeof value === 'string') return JSON.stringify(value);
43
- if (typeof value === 'number') {
44
- if (Object.is(value, -0)) return '0';
45
- if (Number.isInteger(value)) return String(value);
46
- return Number(value.toPrecision(15)).toString();
47
- }
48
- if (typeof value === 'boolean') return value ? 'true' : 'false';
49
- return JSON.stringify(value);
50
- }
51
- function termToN3(t) {
52
- if (!t) return 'undefined';
53
- if (t.kind === 'iri') return t.value;
54
- if (t.kind === 'lit') return literalToN3(t.value);
55
- if (t.kind === 'var') return '?' + t.value;
56
- if (t.kind === 'blank') return t.value.startsWith('_:') ? t.value : '_:' + t.value.replace(/^_+/, '');
57
- if (t.kind === 'list') return '(' + t.items.map(termToN3).join(' ') + ')';
58
- if (t.kind === 'triple') return '<<( ' + termToN3(t.s) + ' ' + termToN3(t.p) + ' ' + termToN3(t.o) + ' )>>';
59
- if (t.kind === 'formula') return '{ ' + t.atoms.map(atomToN3).join(' . ') + ' }';
60
- return String(t.value ?? t);
61
- }
62
- function atomToN3(f) { return termToN3(f.s) + ' ' + termToN3(f.p) + ' ' + termToN3(f.o); }
63
- function display(t) {
64
- const value = primitive(t);
65
- if (Array.isArray(value)) return value.map(String).join(' ');
66
- return String(value);
67
- }
68
- function deepEqual(a, b) {
69
- if (a?.kind === 'lit' && b?.kind === 'lit' && typeof a.value === 'number' && typeof b.value === 'number') {
70
- return Math.abs(a.value - b.value) < 1e-12;
71
- }
72
- return JSON.stringify(canonical(a)) === JSON.stringify(canonical(b));
73
- }
74
- function resolve(term, env, seen = new Set()) {
75
- if (term.kind === 'var' && Object.hasOwn(env, term.value)) {
76
- if (seen.has(term.value)) return term;
77
- seen.add(term.value);
78
- return resolve(env[term.value], env, seen);
79
- }
80
- if (term.kind === 'list') return list(term.items.map((item) => resolve(item, env, seen)));
81
- if (term.kind === 'triple') return { kind: 'triple', s: resolve(term.s, env), p: resolve(term.p, env), o: resolve(term.o, env) };
82
- if (term.kind === 'formula') return { kind: 'formula', atoms: term.atoms.map((a) => ({ s: resolve(a.s, env), p: resolve(a.p, env), o: resolve(a.o, env) })) };
83
- return term;
84
- }
85
- function unify(a, b, env) {
86
- a = resolve(a, env);
87
- b = resolve(b, env);
88
- if (a.kind === 'var') return { ...env, [a.value]: b };
89
- if (b.kind === 'var') return { ...env, [b.value]: a };
90
- if (a.kind === 'list' || b.kind === 'list') {
91
- if (a.kind !== 'list' || b.kind !== 'list' || a.items.length !== b.items.length) return null;
92
- let out = env;
93
- for (let i = 0; i < a.items.length; i += 1) {
94
- out = unify(a.items[i], b.items[i], out);
95
- if (!out) return null;
96
- }
97
- return out;
98
- }
99
- if (a.kind === 'triple' || b.kind === 'triple') {
100
- if (a.kind !== 'triple' || b.kind !== 'triple') return null;
101
- let out = unify(a.s, b.s, env);
102
- if (!out) return null;
103
- out = unify(a.p, b.p, out);
104
- if (!out) return null;
105
- return unify(a.o, b.o, out);
106
- }
107
- return deepEqual(a, b) ? env : null;
108
- }
109
- function bind(pattern, value, env) { return unify(pattern, value, env); }
110
- function matchFact(atom, fact, env) {
111
- let out = unify(atom.p, fact.p, env); if (!out) return null;
112
- out = unify(atom.s, fact.s, out); if (!out) return null;
113
- return unify(atom.o, fact.o, out);
114
- }
115
- function atomIsGround(atom, env) {
116
- return termIsGround(atom.s, env) && termIsGround(atom.p, env) && termIsGround(atom.o, env);
117
- }
118
- function termIsGround(t, env) {
119
- const r = resolve(t, env);
120
- if (r.kind === 'var') return false;
121
- if (r.kind === 'list') return r.items.every((item) => termIsGround(item, env));
122
- if (r.kind === 'triple') return termIsGround(r.s, env) && termIsGround(r.p, env) && termIsGround(r.o, env);
123
- if (r.kind === 'formula') return r.atoms.every((atom) => atomIsGround(atom, env));
124
- return true;
125
- }
126
- function stringValue(t) {
127
- const r = t;
128
- if (!r) return null;
129
- if (r.kind === 'lit') return String(r.value);
130
- if (r.kind === 'iri') return r.value.replace(/[<>]/g, '');
131
- if (r.kind === 'blank' || r.kind === 'var') return null;
132
- return termToN3(r);
133
- }
134
- function xsdDurationSeconds(value) {
135
- const m = String(value || '').match(/^(-)?P(?:(\d+(?:\.\d+)?)Y)?(?:(\d+(?:\.\d+)?)M)?(?:(\d+(?:\.\d+)?)W)?(?:(\d+(?:\.\d+)?)D)?(?:T(?:(\d+(?:\.\d+)?)H)?(?:(\d+(?:\.\d+)?)M)?(?:(\d+(?:\.\d+)?)S)?)?$/i);
136
- if (!m) return null;
137
- const sign = m[1] ? -1 : 1;
138
- const years = Number(m[2] || 0);
139
- const months = Number(m[3] || 0);
140
- const weeks = Number(m[4] || 0);
141
- const days = Number(m[5] || 0);
142
- const hours = Number(m[6] || 0);
143
- const minutes = Number(m[7] || 0);
144
- const seconds = Number(m[8] || 0);
145
-
146
- // xsd:duration years/months are calendar-relative. SEE uses Gregorian averages
147
- // for standalone numeric comparisons such as "age above P80Y".
148
- return sign * (
149
- years * 365.2425 * 86400 +
150
- months * (365.2425 / 12) * 86400 +
151
- weeks * 7 * 86400 +
152
- days * 86400 +
153
- hours * 3600 +
154
- minutes * 60 +
155
- seconds
156
- );
157
- }
158
-
159
- function toNumberMaybe(t) {
160
- const v = primitive(t);
161
- if (typeof v === 'number') return Number.isFinite(v) || Number.isNaN(v) ? v : null;
162
- if (typeof v === 'boolean') return v ? 1 : 0;
163
- if (typeof v !== 'string') return null;
164
- const dur = xsdDurationSeconds(v);
165
- if (dur !== null) return dur;
166
- const d = Date.parse(v);
167
- if (/^\d{4}-\d{2}-\d{2}(?:T|$)/.test(v) && Number.isFinite(d)) return d / 1000;
168
- const n = Number(v);
169
- return Number.isNaN(n) ? null : n;
170
- }
171
- function toNumber(t) {
172
- const n = toNumberMaybe(t);
173
- if (n === null || !Number.isFinite(n)) throw new Error('Expected numeric value, got ' + JSON.stringify(primitive(t)));
174
- return n;
175
- }
176
- function toIntegerMaybe(t) {
177
- const n = toNumberMaybe(t);
178
- if (n === null || !Number.isFinite(n) || !Number.isInteger(n)) return null;
179
- return n;
180
- }
181
- function parseDate(t) {
182
- const v = primitive(t);
183
- if (typeof v !== 'string') return null;
184
- const ms = Date.parse(v);
185
- return Number.isFinite(ms) ? new Date(ms) : null;
186
- }
187
- function dateTimeLiteral(date) { return lit(date.toISOString().replace(/\.000Z$/, 'Z')); }
188
- function durationLiteral(seconds) { return lit('PT' + Number(seconds.toPrecision(15)).toString() + 'S'); }
189
- function termFrom(value) {
190
- if (Array.isArray(value)) return list(value.map(termFrom));
191
- if (value && typeof value === 'object' && value.kind) return value;
192
- return lit(value);
193
- }
194
- function allBoundList(term, env) {
195
- const r = resolve(term, env);
196
- if (r.kind !== 'list') throw new Error('Expected N3 list');
197
- if (r.items.some((item) => resolve(item, env).kind === 'var')) return null;
198
- return r.items.map((item) => resolve(item, env));
199
- }
200
- function bindResult(pattern, value, env) {
201
- return bind(pattern, termFrom(value), env);
202
- }
203
- function bindTermResult(pattern, term, env) {
204
- const out = bind(pattern, term, env);
205
- return out ? [out] : [];
206
- }
207
- function succeedIf(ok, env) { return ok ? [env] : []; }
208
- function compareNumericTerms(a, b) {
209
- const na = toNumberMaybe(a), nb = toNumberMaybe(b);
210
- if (na === null || nb === null) return null;
211
- if (Number.isNaN(na) || Number.isNaN(nb)) return NaN;
212
- return na < nb ? -1 : na > nb ? 1 : 0;
213
- }
214
- function comparisonOperands(s, o, env) {
215
- const left = resolve(s, env), right = resolve(o, env);
216
- if (left.kind === 'list' && left.items.length === 2 && (right.kind === 'lit' ? right.value === true : right.kind === 'iri' && right.value === 'true')) {
217
- return [resolve(left.items[0], env), resolve(left.items[1], env)];
218
- }
219
- return [left, right];
220
- }
221
- function bindNumericOutput(pattern, value, env) {
222
- if (!Number.isFinite(value)) return [];
223
- const normalized = Number.isInteger(value) ? value : Number(value.toPrecision(15));
224
- return bindTermResult(pattern, lit(normalized), env);
225
- }
226
- function unaryMath(name, s, o, env, fwd, inv) {
227
- const left = resolve(s, env), right = resolve(o, env);
228
- if (left.kind !== 'var') return bindNumericOutput(o, fwd(toNumber(left)), env);
229
- if (right.kind !== 'var' && inv) return bindNumericOutput(s, inv(toNumber(right)), env);
230
- if (left.kind === 'var' && right.kind === 'var') return [env];
231
- return [];
232
- }
233
- function builtinMath(name, s, o, env) {
234
- const left = resolve(s, env);
235
- const right = resolve(o, env);
236
- const testCmp = (pred) => {
237
- const [a, b] = comparisonOperands(s, o, env);
238
- if (a.kind === 'var' || b.kind === 'var') return [];
239
- const cmp = compareNumericTerms(a, b);
240
- if (cmp === null || Number.isNaN(cmp)) return [];
241
- return succeedIf(pred(cmp), env);
242
- };
243
- if (name === 'math:lessThan') return testCmp((c) => c < 0);
244
- if (name === 'math:notLessThan') return testCmp((c) => c >= 0);
245
- if (name === 'math:greaterThan') return testCmp((c) => c > 0);
246
- if (name === 'math:notGreaterThan') return testCmp((c) => c <= 0);
247
- if (name === 'math:equalTo') return testCmp((c) => c === 0);
248
- if (name === 'math:notEqualTo') {
249
- const [a, b] = comparisonOperands(s, o, env);
250
- if (a.kind === 'var' || b.kind === 'var') return [];
251
- const cmp = compareNumericTerms(a, b);
252
- if (cmp !== null) return succeedIf(Number.isNaN(cmp) || cmp !== 0, env);
253
- return succeedIf(!deepEqual(a, b), env);
254
- }
255
- if (name === 'math:negation') return unaryMath(name, s, o, env, (x) => -x, (x) => -x);
256
- if (name === 'math:absoluteValue') {
257
- if (left.kind === 'var' && right.kind === 'var') return [env];
258
- if (left.kind !== 'var') return bindNumericOutput(o, Math.abs(toNumber(left)), env);
259
- const n = toNumber(right);
260
- const outs = [];
261
- for (const v of n === 0 ? [0] : [n, -n]) {
262
- const out = bind(s, lit(v), env); if (out) outs.push(out);
263
- }
264
- return outs;
265
- }
266
- if (name === 'math:degrees') return unaryMath(name, s, o, env, (x) => x * 180 / Math.PI, (x) => x * Math.PI / 180);
267
- const unary = {
268
- 'math:sin': [Math.sin, Math.asin], 'math:cos': [Math.cos, Math.acos], 'math:tan': [Math.tan, Math.atan],
269
- 'math:asin': [Math.asin, Math.sin], 'math:acos': [Math.acos, Math.cos], 'math:atan': [Math.atan, Math.tan],
270
- 'math:sinh': [Math.sinh, Math.asinh], 'math:cosh': [Math.cosh, Math.acosh], 'math:tanh': [Math.tanh, Math.atanh],
271
- 'math:rounded': [Math.round, null], 'math:floor': [Math.floor, null]
272
- };
273
- if (Object.hasOwn(unary, name)) {
274
- const [fwd, inv] = unary[name];
275
- if (typeof fwd !== 'function') return [];
276
- return unaryMath(name, s, o, env, fwd, typeof inv === 'function' ? inv : null);
277
- }
278
- if (name === 'math:exponentiation') {
279
- const l = resolve(s, env);
280
- if (l.kind !== 'list' || l.items.length !== 2) return [];
281
- const base = resolve(l.items[0], env);
282
- const exponent = resolve(l.items[1], env);
283
- const result = resolve(o, env);
284
- if (base.kind !== 'var' && exponent.kind !== 'var') return bindNumericOutput(o, Math.pow(toNumber(base), toNumber(exponent)), env);
285
- if (base.kind !== 'var' && result.kind !== 'var') {
286
- const b = toNumber(base), r = toNumber(result);
287
- if (b > 0 && b !== 1 && r > 0) return bindNumericOutput(l.items[1], Math.log(r) / Math.log(b), env);
288
- return [];
289
- }
290
- if (exponent.kind !== 'var' && result.kind !== 'var') {
291
- const e = toNumber(exponent), r = toNumber(result);
292
- if (e !== 0) return bindNumericOutput(l.items[0], Math.pow(r, 1 / e), env);
293
- return [];
294
- }
295
- return [];
296
- }
297
- if (name === 'math:product' || name === 'math:sum') {
298
- const vals = allBoundList(s, env); if (!vals) return [];
299
- if (vals.length === 2) {
300
- const [aT, bT] = vals;
301
- const aD = parseDate(aT);
302
- if (name === 'math:sum' && aD) {
303
- const secs = toNumberMaybe(bT);
304
- if (secs !== null && Number.isFinite(secs)) return bindTermResult(o, dateTimeLiteral(new Date(aD.getTime() + secs * 1000)), env);
305
- }
306
- }
307
- const value = name === 'math:product' ? vals.reduce((a, x) => a * toNumber(x), 1) : vals.reduce((a, x) => a + toNumber(x), 0);
308
- return bindNumericOutput(o, value, env);
309
- }
310
- if (name === 'math:difference' || name === 'math:quotient' || name === 'math:integerQuotient' || name === 'math:remainder') {
311
- const vals = allBoundList(s, env); if (!vals || vals.length !== 2) return [];
312
- const aD = parseDate(vals[0]), bD = parseDate(vals[1]);
313
- if (name === 'math:difference' && aD && bD) return bindTermResult(o, durationLiteral((aD.getTime() - bD.getTime()) / 1000), env);
314
- if (name === 'math:difference' && aD && !bD) {
315
- const secs = toNumberMaybe(vals[1]);
316
- if (secs !== null && Number.isFinite(secs)) return bindTermResult(o, dateTimeLiteral(new Date(aD.getTime() - secs * 1000)), env);
317
- }
318
- const a = toNumber(vals[0]), b = toNumber(vals[1]);
319
- if ((name === 'math:quotient' || name === 'math:integerQuotient' || name === 'math:remainder') && b === 0) return [];
320
- if (name === 'math:difference') return bindNumericOutput(o, a - b, env);
321
- if (name === 'math:quotient') return bindNumericOutput(o, a / b, env);
322
- if (!Number.isInteger(a) || !Number.isInteger(b)) return [];
323
- if (name === 'math:integerQuotient') return bindNumericOutput(o, Math.trunc(a / b), env);
324
- return bindNumericOutput(o, a % b, env);
325
- }
326
- return null;
327
- }
328
- function applyFormat(fmt, args) {
329
- let i = 0;
330
- return String(fmt).replace(/%([-0]?\d+)?(?:\.(\d+))?([%sdiufFeEgGc])/g, (m, width, precision, conv) => {
331
- if (conv === '%') return '%';
332
- const arg = args[i++];
333
- if (conv === 's') return String(arg ?? '');
334
- if (conv === 'c') return String.fromCodePoint(Number(arg));
335
- if ('diu'.includes(conv)) return String(Math.trunc(Number(arg)));
336
- const n = Number(arg);
337
- if (conv === 'f' || conv === 'F') return n.toFixed(precision == null ? 6 : Number(precision));
338
- if (conv === 'e' || conv === 'E') return n.toExponential(precision == null ? 6 : Number(precision));
339
- if (conv === 'g' || conv === 'G') return n.toPrecision(precision == null ? 6 : Number(precision)).replace(/\.0+(e|$)/i, '$1');
340
- return m;
341
- });
342
- }
343
- function compileRegex(pattern, flags = '') {
344
- try { return new RegExp(String(pattern), flags); }
345
- catch { return null; }
346
- }
347
- function builtinString(name, s, o, env) {
348
- const left = resolve(s, env), right = resolve(o, env);
349
- function output(value) { return bindTermResult(o, lit(String(value)), env); }
350
- const str = (term) => stringValue(resolve(term, env));
351
- if (name === 'string:concatenation') {
352
- const vals = allBoundList(s, env); if (!vals) return [];
353
- return output(vals.map(stringValue).join(''));
354
- }
355
- if (name === 'string:format') {
356
- const vals = allBoundList(s, env); if (!vals || vals.length === 0) return [];
357
- return output(applyFormat(stringValue(vals[0]), vals.slice(1).map(stringValue)));
358
- }
359
- if (name === 'string:length') { const a = str(s); return a === null ? [] : bindTermResult(o, lit(a.length), env); }
360
- if (name === 'string:charAt') {
361
- const vals = allBoundList(s, env); if (!vals || vals.length !== 2) return [];
362
- const a = stringValue(vals[0]); const idx = Math.trunc(toNumber(vals[1]));
363
- return output(idx < 0 || idx >= a.length ? '' : a.charAt(idx));
364
- }
365
- if (name === 'string:setCharAt') {
366
- const vals = allBoundList(s, env); if (!vals || vals.length !== 3) return [];
367
- const a = stringValue(vals[0]); const idx = Math.trunc(toNumber(vals[1])); const ch = String(stringValue(vals[2]) || '').charAt(0);
368
- if (idx < 0 || idx >= a.length) return output(a);
369
- return output(a.slice(0, idx) + ch + a.slice(idx + 1));
370
- }
371
- const a = str(s), b = str(o);
372
- if (name === 'string:contains') return a === null || b === null ? [] : succeedIf(a.includes(b), env);
373
- if (name === 'string:containsIgnoringCase') return a === null || b === null ? [] : succeedIf(a.toLowerCase().includes(b.toLowerCase()), env);
374
- if (name === 'string:startsWith') return a === null || b === null ? [] : succeedIf(a.startsWith(b), env);
375
- if (name === 'string:endsWith') return a === null || b === null ? [] : succeedIf(a.endsWith(b), env);
376
- if (name === 'string:equalIgnoringCase') return a === null || b === null ? [] : succeedIf(a.toLowerCase() === b.toLowerCase(), env);
377
- if (name === 'string:notEqualIgnoringCase') return a === null || b === null ? [] : succeedIf(a.toLowerCase() !== b.toLowerCase(), env);
378
- if (name === 'string:greaterThan') return a === null || b === null ? [] : succeedIf(a > b, env);
379
- if (name === 'string:lessThan') return a === null || b === null ? [] : succeedIf(a < b, env);
380
- if (name === 'string:notGreaterThan') return a === null || b === null ? [] : succeedIf(a <= b, env);
381
- if (name === 'string:notLessThan') return a === null || b === null ? [] : succeedIf(a >= b, env);
382
- if (name === 'string:matches' || name === 'string:notMatches') {
383
- if (a === null || b === null) return [];
384
- const re = compileRegex(b); if (!re) return [];
385
- const ok = re.test(a);
386
- return succeedIf(name === 'string:matches' ? ok : !ok, env);
387
- }
388
- if (name === 'string:replace') {
389
- const vals = allBoundList(s, env); if (!vals || vals.length !== 3) return [];
390
- const data = stringValue(vals[0]), pattern = stringValue(vals[1]), replacement = stringValue(vals[2]);
391
- const re = compileRegex(pattern, 'g'); if (!re) return [];
392
- return output(data.replace(re, replacement));
393
- }
394
- if (name === 'string:scrape') {
395
- const vals = allBoundList(s, env); if (!vals || vals.length !== 2) return [];
396
- const data = stringValue(vals[0]), pattern = stringValue(vals[1]);
397
- const re = compileRegex(pattern); if (!re) return [];
398
- const m = data.match(re); if (!m || m.length < 2) return [];
399
- return output(m[1]);
400
- }
401
- return null;
402
- }
403
- function builtinCrypto(name, s, o, env) {
404
- const algos = { 'crypto:sha': 'sha1', 'crypto:md5': 'md5', 'crypto:sha256': 'sha256', 'crypto:sha512': 'sha512' };
405
- if (!Object.hasOwn(algos, name)) return null;
406
- if (!termIsGround(s, env)) return [];
407
- const digest = crypto.createHash(algos[name]).update(String(primitive(resolve(s, env))), 'utf8').digest('hex');
408
- return bindTermResult(o, lit(digest), env);
409
- }
410
- function formulaContains(graph, patternAtoms, env, rules, depth) {
411
- const localGraph = graph && graph.facts ? graph : makeGraph(graph?.atoms || graph?.facts || []);
412
- return evalBody(patternAtoms, [env], localGraph, rules, depth + 1).length > 0;
413
- }
414
- function builtinLog(name, s, o, env, graph, rules, depth) {
415
- if (name === 'log:equalTo') return bindTermResult(s, resolve(o, env), env);
416
- if (name === 'log:notEqualTo') {
417
- const out = unify(resolve(s, env), resolve(o, env), env);
418
- return out ? [] : [env];
419
- }
420
- if (name === 'log:conjunction') {
421
- const vals = allBoundList(s, env); if (!vals) return [];
422
- const merged = [], seen = new Set();
423
- for (const part of vals) {
424
- if (part.kind === 'lit' && part.value === true) continue;
425
- if (part.kind !== 'formula') return [];
426
- for (const atom of part.atoms) { const k = factKey(atom); if (!seen.has(k)) { seen.add(k); merged.push(atom); } }
427
- }
428
- return bindTermResult(o, { kind: 'formula', atoms: merged }, env);
429
- }
430
- if (name === 'log:includes' || name === 'log:notIncludes') {
431
- const scope = resolve(s, env), pattern = resolve(o, env);
432
- if (pattern.kind !== 'formula') return [];
433
- const local = scope.kind === 'formula' ? makeGraph(scope.atoms) : graph;
434
- const ok = evalBody(pattern.atoms, [env], local, rules, depth + 1).length > 0;
435
- return succeedIf(name === 'log:includes' ? ok : !ok, env);
436
- }
437
- if (name === 'log:rawType') {
438
- const rt = resolve(s, env);
439
- if (rt.kind === 'var') return [];
440
- const ty = rt.kind === 'formula' ? 'log:Formula' : rt.kind === 'lit' ? 'log:Literal' : rt.kind === 'list' ? 'rdf:List' : 'log:Other';
441
- return bindTermResult(o, { kind: 'iri', value: ty }, env);
442
- }
443
- if (name === 'log:dtlit') {
444
- const l = resolve(s, env), obj = resolve(o, env);
445
- if (l.kind === 'list' && l.items.length === 2) {
446
- const lex = stringValue(resolve(l.items[0], env));
447
- const dt = resolve(l.items[1], env);
448
- if (lex === null || dt.kind !== 'iri') return [];
449
- return bindTermResult(o, lit(lex), env);
450
- }
451
- if (obj.kind === 'var') return [];
452
- return stringValue(obj) === null ? [] : [env];
453
- }
454
- if (name === 'log:outputString') return [env];
455
- if (name === 'log:collectAllIn') {
456
- const l = resolve(s, env); if (l.kind !== 'list' || l.items.length !== 3) return [];
457
- const [valueTemplate, clause, outList] = l.items;
458
- const scope = resolve(o, env);
459
- const local = scope.kind === 'formula' ? makeGraph(scope.atoms) : graph;
460
- if (clause.kind !== 'formula') return [];
461
- const sols = evalBody(clause.atoms, [env], local, rules, depth + 1);
462
- return bindTermResult(outList, list(sols.map((sol) => resolve(valueTemplate, sol))), env);
463
- }
464
- if (name === 'log:forAllIn') {
465
- const l = resolve(s, env); if (l.kind !== 'list' || l.items.length !== 2) return [];
466
- const [where, then] = l; if (where.kind !== 'formula' || then.kind !== 'formula') return [];
467
- const scope = resolve(o, env);
468
- const local = scope.kind === 'formula' ? makeGraph(scope.atoms) : graph;
469
- const sols = evalBody(where.atoms, [{}], local, rules, depth + 1);
470
- for (const sol of sols) if (!evalBody(then.atoms, [sol], local, rules, depth + 1).length) return [];
471
- return [env];
472
- }
473
- if (['log:content', 'log:semantics', 'log:semanticsOrError', 'log:parsedAsN3'].includes(name)) {
474
- throw new Error(name + ' requires dereferencing or parsing at runtime and is intentionally not available in offline specialized SEE output');
475
- }
476
- return null;
477
- }
478
- function splitList(items, parts, env, start = 0, idx = 0) {
479
- if (idx === parts.length) return start === items.length ? [env] : [];
480
- const outs = [];
481
- const last = idx === parts.length - 1;
482
- for (let end = start; end <= items.length; end += 1) {
483
- if (last && end !== items.length) continue;
484
- const out = bind(parts[idx], list(items.slice(start, end)), env);
485
- if (out) outs.push(...splitList(items, parts, out, end, idx + 1));
486
- }
487
- return outs;
488
- }
489
- function termSortKey(t) {
490
- if (t.kind === 'lit') { const n = Number(t.value); return Number.isNaN(n) ? '1:' + String(t.value) : '0:' + n.toString().padStart(20, '0'); }
491
- if (t.kind === 'iri') return '2:' + t.value;
492
- if (t.kind === 'list') return '3:' + t.items.map(termSortKey).join('|');
493
- return '9:' + JSON.stringify(canonical(t));
494
- }
495
- function builtinList(name, s, o, env, graph, rules, depth) {
496
- const predName = name === 'rdf:first' ? 'list:first' : name === 'rdf:rest' ? 'list:rest' : name;
497
- const left = resolve(s, env);
498
- const right = resolve(o, env);
499
- const listItems = (term) => term.kind === 'list' ? term.items.map((x) => resolve(x, env)) : null;
500
- if (predName === 'list:first') {
501
- const xs = listItems(left); if (!xs || !xs.length) return [];
502
- return bindTermResult(o, xs[0], env);
503
- }
504
- if (predName === 'list:rest') {
505
- const xs = listItems(left); if (!xs || !xs.length) return [];
506
- return bindTermResult(o, list(xs.slice(1)), env);
507
- }
508
- if (predName === 'list:firstRest') {
509
- const outs = [];
510
- if (left.kind === 'list' && left.items.length > 0 && !left.items.some((x) => resolve(x, env).kind === 'var')) {
511
- const items = left.items.map((x) => resolve(x, env));
512
- const out = bind(o, list([items[0], list(items.slice(1))]), env); if (out) outs.push(out);
513
- }
514
- if (right.kind === 'list' && right.items.length === 2) {
515
- const rest = resolve(right.items[1], env);
516
- const first = resolve(right.items[0], env);
517
- if (rest.kind === 'list') { const out = bind(s, list([first, ...rest.items]), env); if (out) outs.push(out); }
518
- }
519
- return outs;
520
- }
521
- if (predName === 'list:append') {
522
- if (left.kind !== 'list') return [];
523
- if (right.kind === 'list') return splitList(right.items, left.items, env);
524
- const outElems = [];
525
- for (const part of left.items) { const p = resolve(part, env); if (p.kind !== 'list') return []; outElems.push(...p.items); }
526
- return bindTermResult(o, list(outElems), env);
527
- }
528
- if (predName === 'list:iterate') {
529
- const xs = listItems(left); if (!xs) return [];
530
- const outs = [];
531
- for (let i = 0; i < xs.length; i += 1) { const out = bind(o, list([lit(i), xs[i]]), env); if (out) outs.push(out); }
532
- return outs;
533
- }
534
- if (predName === 'list:last') {
535
- const xs = listItems(left); if (!xs || !xs.length) return [];
536
- return bindTermResult(o, xs[xs.length - 1], env);
537
- }
538
- if (predName === 'list:memberAt') {
539
- if (left.kind !== 'list' || left.items.length !== 2) return [];
540
- const arr = resolve(left.items[0], env), idx = resolve(left.items[1], env);
541
- if (arr.kind !== 'list') return [];
542
- const outs = [];
543
- for (let i = 0; i < arr.items.length; i += 1) {
544
- let out = idx.kind === 'var' ? bind(left.items[1], lit(i), env) : (Number(idx.value) === i ? env : null);
545
- if (out) out = bind(o, arr.items[i], out);
546
- if (out) outs.push(out);
547
- }
548
- return outs;
549
- }
550
- if (predName === 'list:remove') {
551
- if (left.kind !== 'list' || left.items.length !== 2) return [];
552
- const arr = resolve(left.items[0], env), item = resolve(left.items[1], env);
553
- if (arr.kind !== 'list' || item.kind === 'var') return [];
554
- return bindTermResult(o, list(arr.items.filter((x) => !deepEqual(resolve(x, env), item))), env);
555
- }
556
- if (predName === 'list:member') {
557
- const xs = listItems(left); if (!xs) return [];
558
- return xs.map((x) => bind(o, x, env)).filter(Boolean);
559
- }
560
- if (predName === 'list:in') {
561
- const xs = listItems(right); if (!xs) return [];
562
- return xs.map((x) => bind(s, x, env)).filter(Boolean);
563
- }
564
- if (predName === 'list:length') {
565
- const xs = listItems(left); if (!xs) return [];
566
- return bindTermResult(o, lit(xs.length), env);
567
- }
568
- if (predName === 'list:notMember') {
569
- const xs = listItems(left); if (!xs) return [];
570
- return xs.some((x) => unify(o, x, env)) ? [] : [env];
571
- }
572
- if (predName === 'list:reverse') {
573
- if (left.kind === 'list') return bindTermResult(o, list([...left.items].reverse()), env);
574
- if (right.kind === 'list') return bindTermResult(s, list([...right.items].reverse()), env);
575
- return [];
576
- }
577
- if (predName === 'list:sort') {
578
- const source = left.kind === 'list' ? left : right.kind === 'list' ? right : null;
579
- if (!source || source.items.some((x) => resolve(x, env).kind === 'var')) return [];
580
- const sorted = [...source.items].sort((a, b) => termSortKey(a).localeCompare(termSortKey(b)));
581
- return left.kind === 'list' ? bindTermResult(o, list(sorted), env) : bindTermResult(s, list(sorted), env);
582
- }
583
- if (predName === 'list:map') {
584
- if (left.kind !== 'list' || left.items.length !== 2) return [];
585
- const arr = resolve(left.items[0], env), pred = resolve(left.items[1], env);
586
- if (arr.kind !== 'list' || pred.kind !== 'iri') return [];
587
- const values = [];
588
- for (let i = 0; i < arr.items.length; i += 1) {
589
- const valueVar = { kind: 'var', value: '__map_' + depth + '_' + i };
590
- const matches = evalAtom({ s: arr.items[i], p: pred, o: valueVar }, env, graph, rules, depth + 1);
591
- for (const m of matches) { const v = resolve(valueVar, m); if (v.kind !== 'var') values.push(v); }
592
- }
593
- return bindTermResult(o, list(values), env);
594
- }
595
- return null;
596
- }
597
- function parseDateTimeParts(t) {
598
- const v = primitive(t);
599
- if (typeof v !== 'string') return null;
600
- const m = v.match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d+)?)(Z|[+-]\d{2}:\d{2})?$/);
601
- if (!m) return null;
602
- return { year: Number(m[1]), month: Number(m[2]), day: Number(m[3]), hour: Number(m[4]), minute: Number(m[5]), second: Number(m[6]), timeZone: m[7] || '' };
603
- }
604
- function builtinTime(name, s, o, env) {
605
- if (name === 'time:localTime') return bindTermResult(o, lit(new Date().toISOString().replace(/\.000Z$/, 'Z')), env);
606
- const parts = parseDateTimeParts(resolve(s, env)); if (!parts) return [];
607
- const key = name.slice('time:'.length);
608
- if (['year','month','day','hour','minute','second'].includes(key)) return bindTermResult(o, lit(parts[key]), env);
609
- if (key === 'timeZone') return bindTermResult(o, lit(parts.timeZone || 'Z'), env);
610
- return null;
611
- }
612
- function evalBuiltin(atom, env, graph, rules, depth) {
613
- const pred = resolve(atom.p, env);
614
- if (pred.kind !== 'iri') return null;
615
- const name = pred.value;
616
- if (name.startsWith('math:')) return builtinMath(name, atom.s, atom.o, env);
617
- if (name.startsWith('string:')) return builtinString(name, atom.s, atom.o, env);
618
- if (name.startsWith('crypto:')) return builtinCrypto(name, atom.s, atom.o, env);
619
- if (name.startsWith('list:') || name === 'rdf:first' || name === 'rdf:rest') return builtinList(name, atom.s, atom.o, env, graph, rules, depth);
620
- if (name.startsWith('time:')) return builtinTime(name, atom.s, atom.o, env);
621
- if (name.startsWith('log:')) return builtinLog(name, atom.s, atom.o, env, graph, rules, depth);
622
- return null;
623
- }
624
- function renameTerm(term, suffix) {
625
- if (term.kind === 'var') return { kind: 'var', value: term.value + suffix };
626
- if (term.kind === 'list') return list(term.items.map((item) => renameTerm(item, suffix)));
627
- if (term.kind === 'formula') return { kind: 'formula', atoms: term.atoms.map((a) => renameAtom(a, suffix)) };
628
- return cloneTerm(term);
629
- }
630
- function renameAtom(atom, suffix) {
631
- return { s: renameTerm(atom.s, suffix), p: renameTerm(atom.p, suffix), o: renameTerm(atom.o, suffix) };
632
- }
633
- let renameCounter = 0;
634
- function evalBackward(atom, env, graph, rules, depth) {
635
- if (depth > 200) throw new Error('Backward rule recursion limit exceeded');
636
- const outs = [];
637
- for (const rule of rules) {
638
- if (rule.kind !== 'backward') continue;
639
- for (const headAtom of rule.head) {
640
- const suffix = '__rule' + rule.id + '_' + depth + '_' + (++renameCounter);
641
- const renamedHead = renameAtom(headAtom, suffix);
642
- let out = unify(atom.p, renamedHead.p, env); if (!out) continue;
643
- out = unify(atom.s, renamedHead.s, out); if (!out) continue;
644
- out = unify(atom.o, renamedHead.o, out); if (!out) continue;
645
- const renamedBody = rule.body.map((bodyAtom) => renameAtom(bodyAtom, suffix));
646
- outs.push(...evalBody(renamedBody, [out], graph, rules, depth + 1));
647
- }
648
- }
649
- return outs;
650
- }
651
- function evalAtom(atom, env, graph, rules, depth = 0) {
652
- const builtin = evalBuiltin(atom, env, graph, rules, depth);
653
- if (builtin !== null) return builtin;
654
- const outs = [];
655
- for (const fact of candidateFactsForAtom(atom, env, graph)) {
656
- const out = matchFact(atom, fact, env);
657
- if (out) outs.push(out);
658
- }
659
- outs.push(...evalBackward(atom, env, graph, rules, depth + 1));
660
- return outs;
661
- }
662
- function evalBody(atoms, envs, graph, rules, depth = 0) {
663
- let out = envs;
664
- for (const atom of atoms) {
665
- const next = [];
666
- for (const env of out) next.push(...evalAtom(atom, env, graph, rules, depth));
667
- out = next;
668
- if (!out.length) break;
669
- }
670
- return out;
671
- }
672
- function envSignature(env) {
673
- return crypto.createHash('sha1').update(JSON.stringify(Object.keys(env).sort().map((k) => [k, canonical(env[k])]))).digest('hex').slice(0, 12);
674
- }
675
- function instantiate(term, env, ruleId) {
676
- if (term.kind === 'var') {
677
- if (!Object.hasOwn(env, term.value)) throw new Error('Unbound variable in rule head: ?' + term.value);
678
- return cloneTerm(resolve(env[term.value], env));
679
- }
680
- if (term.kind === 'blank') return blank('_:r' + ruleId + '_' + envSignature(env) + '_' + term.value.replace(/^_/, ''));
681
- if (term.kind === 'list') return list(term.items.map((item) => instantiate(item, env, ruleId)));
682
- if (term.kind === 'triple') return { kind: 'triple', s: instantiate(term.s, env, ruleId), p: instantiate(term.p, env, ruleId), o: instantiate(term.o, env, ruleId) };
683
- if (term.kind === 'formula') return { kind: 'formula', atoms: term.atoms.map((a) => ({ s: instantiate(a.s, env, ruleId), p: instantiate(a.p, env, ruleId), o: instantiate(a.o, env, ruleId) })) };
684
- return cloneTerm(term);
685
- }
686
- function supportFactsForBody(body, env, graph) {
687
- const seen = new Set();
688
- const out = [];
689
- for (const atom of body || []) {
690
- const pred = resolve(atom.p, env);
691
- if (pred.kind === 'iri') {
692
- const builtin = pred.value.startsWith('math:') || pred.value.startsWith('string:') || pred.value.startsWith('crypto:') ||
693
- pred.value.startsWith('list:') || pred.value.startsWith('time:') || pred.value.startsWith('log:') ||
694
- pred.value === 'rdf:first' || pred.value === 'rdf:rest';
695
- if (builtin) continue;
696
- }
697
- for (const fact of candidateFactsForAtom(atom, env, graph)) {
698
- if (!matchFact(atom, fact, env)) continue;
699
- const key = factKey(fact);
700
- if (!seen.has(key)) { seen.add(key); out.push(fact); }
701
- }
702
- }
703
- return out;
704
- }
705
- function makeIndex() { return { p: new Map(), spByP: new Map(), poByP: new Map(), s: null, o: null }; }
706
- function pushIndex(map, key, fact) {
707
- let bucket = map.get(key);
708
- if (!bucket) { bucket = []; map.set(key, bucket); }
709
- bucket.push(fact);
710
- }
711
- function makeGraph(facts) {
712
- const graph = { facts: [], keys: new Set(), index: makeIndex() };
713
- for (const fact of facts) addFact(graph, fact);
714
- return graph;
715
- }
716
- function ensureFlatIndex(graph, kind, termSelector) {
717
- if (!graph.index[kind]) {
718
- const map = new Map();
719
- for (const fact of graph.facts) pushIndex(map, termIndexKey(termSelector(fact)), fact);
720
- graph.index[kind] = map;
721
- }
722
- return graph.index[kind];
723
- }
724
- function ensurePredicateTermIndex(graph, byPredicate, pKey, pFacts, termSelector) {
725
- let map = graph.index[byPredicate].get(pKey);
726
- if (!map) {
727
- map = new Map();
728
- for (const fact of pFacts) pushIndex(map, termIndexKey(termSelector(fact)), fact);
729
- graph.index[byPredicate].set(pKey, map);
730
- }
731
- return map;
732
- }
733
- function addFact(graph, fact) {
734
- const key = factKey(fact);
735
- if (graph.keys.has(key)) return false;
736
- graph.keys.add(key);
737
- graph.facts.push(fact);
738
- const pKey = termIndexKey(fact.p);
739
- pushIndex(graph.index.p, pKey, fact);
740
- if (graph.index.s) pushIndex(graph.index.s, termIndexKey(fact.s), fact);
741
- if (graph.index.o) pushIndex(graph.index.o, termIndexKey(fact.o), fact);
742
- const sp = graph.index.spByP.get(pKey);
743
- if (sp) pushIndex(sp, termIndexKey(fact.s), fact);
744
- const po = graph.index.poByP.get(pKey);
745
- if (po) pushIndex(po, termIndexKey(fact.o), fact);
746
- return true;
747
- }
748
- function candidateFactsForAtom(atom, env, graph) {
749
- if (!graph || !graph.index) return graph && graph.facts ? graph.facts : [];
750
- const s = resolve(atom.s, env), p = resolve(atom.p, env), o = resolve(atom.o, env);
751
- const sg = termIsConcrete(s), pg = termIsConcrete(p), og = termIsConcrete(o);
752
- if (pg) {
753
- const pKey = termIndexKey(p);
754
- const pFacts = graph.index.p.get(pKey) || [];
755
- if (sg) return ensurePredicateTermIndex(graph, 'spByP', pKey, pFacts, (f) => f.s).get(termIndexKey(s)) || [];
756
- if (og) return ensurePredicateTermIndex(graph, 'poByP', pKey, pFacts, (f) => f.o).get(termIndexKey(o)) || [];
757
- return pFacts;
758
- }
759
- if (sg) return ensureFlatIndex(graph, 's', (f) => f.s).get(termIndexKey(s)) || [];
760
- if (og) return ensureFlatIndex(graph, 'o', (f) => f.o).get(termIndexKey(o)) || [];
761
- return graph.facts;
762
- }
763
-
764
- function isBuiltinPredicateValue(name) {
765
- return typeof name === 'string' && (name.startsWith('math:') || name.startsWith('string:') || name.startsWith('crypto:') ||
766
- name.startsWith('list:') || name.startsWith('time:') || name.startsWith('log:') || name === 'rdf:first' || name === 'rdf:rest');
767
- }
768
- function collectFormulaDependencyKeys(term, keys) {
769
- if (!term) return true;
770
- if (term.kind === 'formula') {
771
- for (const atom of term.atoms || []) {
772
- if (!collectAtomDependencyKeys(atom, keys)) return false;
773
- }
774
- return true;
775
- }
776
- if (term.kind === 'list') {
777
- for (const item of term.items || []) if (!collectFormulaDependencyKeys(item, keys)) return false;
778
- }
779
- return true;
780
- }
781
- function collectAtomDependencyKeys(atom, keys) {
782
- const pred = atom && atom.p;
783
- if (!pred || pred.kind === 'var') return false;
784
- if (pred.kind === 'iri') {
785
- if (!isBuiltinPredicateValue(pred.value)) keys.add(termIndexKey(pred));
786
- else if (pred.value.startsWith('log:')) {
787
- if (!collectFormulaDependencyKeys(atom.s, keys)) return false;
788
- if (!collectFormulaDependencyKeys(atom.o, keys)) return false;
789
- }
790
- }
791
- return true;
792
- }
793
- function ruleDependencyPredicateKeys(rule) {
794
- const keys = new Set();
795
- for (const atom of rule.body || []) {
796
- if (!collectAtomDependencyKeys(atom, keys)) return null;
797
- }
798
- return keys;
799
- }
800
- function producedFactsCanAffectRules(producedPredicates, ruleDependencies) {
801
- if (!producedPredicates || !producedPredicates.size) return false;
802
- for (const deps of ruleDependencies) {
803
- if (deps === null) return true;
804
- for (const key of producedPredicates) if (deps.has(key)) return true;
805
- }
806
- return false;
807
- }
808
- function saturate(initialFacts, rules) {
809
- const graph = makeGraph(initialFacts);
810
- const trace = [];
811
- const maxIterations = 10000;
812
- const activeRules = (rules || []).filter((rule) => rule.kind !== 'backward');
813
- const ruleDependencies = activeRules.map(ruleDependencyPredicateKeys);
814
- for (let iter = 0; iter < maxIterations; iter += 1) {
815
- let changed = false;
816
- const producedPredicates = new Set();
817
- for (const rule of activeRules) {
818
- const matches = evalBody(rule.body, [{}], graph, rules);
819
- if (rule.kind === 'fuse') {
820
- if (matches.length) throw new Error('N3 fuse failed in compiled rule #' + rule.id);
821
- continue;
822
- }
823
- for (const env of matches) {
824
- const supportFacts = supportFactsForBody(rule.body, env, graph);
825
- const produced = [];
826
- for (const atom of rule.head) {
827
- const fact = { s: instantiate(atom.s, env, rule.id), p: instantiate(atom.p, env, rule.id), o: instantiate(atom.o, env, rule.id) };
828
- if (addFact(graph, fact)) {
829
- changed = true;
830
- produced.push(fact);
831
- producedPredicates.add(termIndexKey(fact.p));
832
- }
833
- }
834
- if (produced.length) {
835
- trace.push({
836
- rule: rule.id,
837
- produced: produced.length,
838
- producedFacts: produced.map(codeFact).map((x) => x.replace(/ \.$/, '')),
839
- supportFacts: supportFacts.map(codeFact).map((x) => x.replace(/ \.$/, ''))
840
- });
841
- }
842
- }
843
- }
844
- if (!changed) break;
845
- if (!producedFactsCanAffectRules(producedPredicates, ruleDependencies)) break;
846
- if (iter === maxIterations - 1) throw new Error('Compiled derivation did not reach a fixpoint');
847
- }
848
- return { graph, trace };
849
- }
850
- function queryFacts(graph, queries, rules) {
851
- const out = [];
852
- const seen = new Set();
853
- for (const query of queries || []) {
854
- const matches = evalBody(query.premise || [], [{}], graph, rules);
855
- for (const env of matches) {
856
- for (const atom of query.conclusion || []) {
857
- const fact = { s: instantiate(atom.s, env, 'q' + query.id), p: instantiate(atom.p, env, 'q' + query.id), o: instantiate(atom.o, env, 'q' + query.id) };
858
- if (!atomIsGround(fact, {})) throw new Error('Unbound variable in log:query projection');
859
- const key = factKey(fact);
860
- if (!seen.has(key)) { seen.add(key); out.push(fact); }
861
- }
862
- }
863
- }
864
- return out;
865
- }
866
- function outputStrings(graph) {
867
- return graph.facts
868
- .filter((f) => isIri(f.p, 'log:outputString'))
869
- .sort((a, b) => display(a.s).localeCompare(display(b.s)))
870
- .map((f) => String(primitive(f.o)));
871
- }
872
- function initialKeys(initialFacts) {
873
- if (!initialFacts) return new Set();
874
- if (initialFacts.__seeKeySet) return initialFacts.__seeKeySet;
875
- const keys = new Set((initialFacts || []).map(factKey));
876
- try { Object.defineProperty(initialFacts, '__seeKeySet', { value: keys, enumerable: false }); } catch (_) {}
877
- return keys;
878
- }
879
- function derivedFacts(graph, initialFacts) {
880
- const base = initialKeys(initialFacts);
881
- return graph.facts.filter((f) => !base.has(factKey(f)));
882
- }
883
- function codeFact(f) { return atomToN3(f) + ' .'; }
884
- function unquoteLiteral(text) {
885
- const m = String(text || '').match(/^\"([\s\S]*)\"$/);
886
- if (!m) return String(text || '');
887
- return m[1].replace(/\\"/g, '"').replace(/\\n/g, '\n').replace(/\\\\/g, '\\');
888
- }
889
- function readablePredicateName(term) {
890
- return String(term || '')
891
- .replace(/^[:<#]*/, '')
892
- .replace(/[>#]*$/g, '')
893
- .replace(/^./, (ch) => ch.toLowerCase());
894
- }
895
- function compactValidationValue(value) {
896
- return String(value || '').replace(/^OK\s*-\s*/i, '').trim();
897
- }
898
- function compactSupportFactText(fact) {
899
- const text = String(fact || '')
900
- .replace(/===\s*Reason\s+Why\s*===/gi, '=== Explanation ===')
901
- .replace(/===\s*Review\s*===/gi, '=== Explanation ===');
902
- const report = text.match(/^(.*?\blog:outputString)\s+/);
903
- if (report) return report[1] + ' "[authored report]"';
904
-
905
- return text.replace(/\s{2,}/g, ' ').trim();
906
- }
907
- function compactRuleComment(comment) {
908
- return compactSupportFactText(comment);
909
- }
910
- function shortTerm(t) { return termToN3(t); }
911
- function factSentence(f) {
912
- const s = shortTerm(f.s), p = shortTerm(f.p), o = shortTerm(f.o);
913
- if (isIri(f.p, 'rdf:type')) return s + ' is a ' + o + '.';
914
- if (isIri(f.p, 'rdfs:subClassOf')) return s + ' is a subclass of ' + o + '.';
915
- if (isIri(f.p, ':is') || /(^|:)is$/.test(p)) return s + ' is ' + o + '.';
916
- return s + ' ' + p + ' ' + o + '.';
917
- }
918
- function previewItems(items, limit = 2) {
919
- const list = Array.isArray(items) ? items.filter(Boolean).map(compactRuleComment) : [];
920
- const shown = list.slice(0, limit).join('; ');
921
- const more = list.length > limit ? '; … +' + (list.length - limit) + ' more' : '';
922
- return shown + more;
923
- }
924
- function describeRule(rule) {
925
- if (!rule) return 'compiled rule';
926
- const body = rule.bodyComment || [];
927
- const head = rule.headComment || [];
928
- if (rule.kind === 'fuse') {
929
- const preview = previewItems(body, 2) || 'forbidden pattern';
930
- return 'Fuse ' + rule.id + ' guards against ' + preview;
931
- }
932
- const bodyCount = body.length;
933
- const headCount = head.length;
934
- if (bodyCount <= 2 && headCount <= 2) {
935
- return 'Rule ' + rule.id + ': ' + (previewItems(body, 2) || 'true') + ' => ' + (previewItems(head, 2) || 'false');
936
- }
937
- return 'Rule ' + rule.id + ' (' + bodyCount + ' premise pattern(s) => ' + headCount + ' conclusion pattern(s))';
938
- }
939
- function traceApplications(trace, rules, limit = 6) {
940
- const byId = new Map((rules || []).map((r) => [r.id, r]));
941
- const grouped = new Map();
942
- for (const step of trace || []) {
943
- const facts = Array.isArray(step.producedFacts) ? step.producedFacts : [];
944
- if (!facts.length) continue;
945
- const key = String(step.rule);
946
- if (!grouped.has(key)) grouped.set(key, { rule: byId.get(step.rule), facts: [], supportFacts: [] });
947
- const entry = grouped.get(key);
948
- for (const fact of facts) if (!entry.facts.includes(fact)) entry.facts.push(fact);
949
- for (const fact of Array.isArray(step.supportFacts) ? step.supportFacts : []) {
950
- if (!entry.supportFacts.includes(fact)) entry.supportFacts.push(fact);
951
- }
952
- }
953
- return Array.from(grouped.values()).slice(0, limit);
954
- }
955
- function supportIndex(trace) {
956
- const index = new Map();
957
- for (const step of trace || []) {
958
- const facts = Array.isArray(step.producedFacts) ? step.producedFacts : [];
959
- for (const fact of facts) {
960
- if (!index.has(fact)) {
961
- index.set(fact, { rule: step.rule, supportFacts: Array.isArray(step.supportFacts) ? step.supportFacts : [] });
962
- }
963
- }
964
- }
965
- return index;
966
- }
967
- function supportTreeLines(fact, supportMap, sourceKeys, ruleMap, opts = {}) {
968
- const lines = [];
969
- const maxDepth = opts.maxDepth ?? 4;
970
- const maxChildren = opts.maxChildren ?? 4;
971
- const maxLines = opts.maxLines ?? 40;
972
- function walk(item, depth, seen) {
973
- if (lines.length >= maxLines) return;
974
- const indent = ' '.repeat(depth);
975
- if (/\blog:outputString\b/.test(String(item || ''))) {
976
- const support = supportMap.get(item);
977
- const rule = support ? ruleMap.get(support.rule) : null;
978
- const label = support ? (rule ? 'Rule ' + rule.id : 'compiled rule #' + support.rule) : 'no recorded rule support';
979
- lines.push(indent + '- ' + compactSupportFactText(item) + ' . _(authored report, ' + label + ')_');
980
- return;
981
- }
982
- if (sourceKeys.has(item)) {
983
- lines.push(indent + '- ' + compactSupportFactText(item) + ' . _(source)_');
984
- return;
985
- }
986
- const support = supportMap.get(item);
987
- if (!support) {
988
- lines.push(indent + '- ' + compactSupportFactText(item) + ' . _(no recorded rule support)_');
989
- return;
990
- }
991
- const rule = ruleMap.get(support.rule);
992
- const label = rule ? 'Rule ' + rule.id : 'compiled rule #' + support.rule;
993
- lines.push(indent + '- ' + compactSupportFactText(item) + ' . _(derived by ' + label + ')_');
994
- if (depth >= maxDepth) {
995
- if (support.supportFacts && support.supportFacts.length) lines.push(indent + ' - support omitted beyond depth ' + maxDepth);
996
- return;
997
- }
998
- const children = (support.supportFacts || []).slice(0, maxChildren);
999
- const childIndent = indent + ' ';
1000
- if (!children.length) {
1001
- lines.push(childIndent + '- no graph premises; built-ins/constants satisfied the rule.');
1002
- return;
1003
- }
1004
- for (const child of children) {
1005
- if (seen.has(child)) {
1006
- lines.push(childIndent + '- ' + compactSupportFactText(child) + ' . _(already shown)_');
1007
- continue;
1008
- }
1009
- const nextSeen = new Set(seen);
1010
- nextSeen.add(child);
1011
- walk(child, depth + 1, nextSeen);
1012
- if (lines.length >= maxLines) break;
1013
- }
1014
- if ((support.supportFacts || []).length > children.length) {
1015
- lines.push(childIndent + '- ... ' + ((support.supportFacts || []).length - children.length) + ' more premise fact(s)');
1016
- }
1017
- }
1018
- walk(fact, 0, new Set([fact]));
1019
- if (lines.length >= maxLines) lines.push('- … support tree truncated after ' + maxLines + ' line(s)');
1020
- return lines;
1021
- }
1022
- function conclusionSupportSection(selected, trace, rules, initialFacts, limit = 6) {
1023
- const supportMap = supportIndex(trace);
1024
- const sourceKeys = new Set((initialFacts || []).map((f) => codeFact(f).replace(/ \.$/, '')));
1025
- const ruleMap = new Map((rules || []).map((r) => [r.id, r]));
1026
- const facts = [];
1027
- const seen = new Set();
1028
- for (const f of selected || []) {
1029
- const key = codeFact(f).replace(/ \.$/, '');
1030
- if (!seen.has(key)) { seen.add(key); facts.push(key); }
1031
- }
1032
- const focus = facts.slice(-limit).reverse();
1033
- if (!focus.length) return [];
1034
- const lines = [];
1035
- lines.push('Selected explanation support:');
1036
- for (const fact of focus) {
1037
- lines.push(...supportTreeLines(fact, supportMap, sourceKeys, ruleMap).map((line) => ' ' + line));
1038
- }
1039
- return lines;
1040
- }
1041
- function evidenceSummaryLine(mode) {
1042
- if (mode === 'query') return 'The query-selected facts are serialized in the Formal TriG Output section.';
1043
- if (mode === 'formula') return 'The formula-valued facts are serialized in the Formal TriG Output section.';
1044
- return 'The selected facts are serialized in the Formal TriG Output section.';
1045
- }
1046
- function renderStructuredOutput({ title, graph, queries = [], rules = [], initialFacts = [], trace = [], mode = 'derived' }) {
1047
- let selected = [];
1048
- if (mode === 'query') selected = queryFacts(graph, queries, rules);
1049
- else if (mode === 'formula') selected = graph.facts.filter((f) => f.o && f.o.kind === 'formula');
1050
- else selected = derivedFacts(graph, initialFacts);
1051
- if (!selected.length) selected = graph.facts.slice(0, 30);
1052
-
1053
- const derived = derivedFacts(graph, initialFacts);
1054
- const keyFact = selected[selected.length - 1];
1055
- const lines = [];
1056
- lines.push('# ' + title);
1057
- lines.push('');
1058
- lines.push('## Entailment');
1059
- if (mode === 'query') {
1060
- lines.push('The compiled query selected ' + selected.length + ' fact(s) after the rule closure was computed.');
1061
- } else if (mode === 'formula') {
1062
- lines.push('The derivation produced ' + selected.length + ' formula-valued entailment(s).');
1063
- } else {
1064
- lines.push('The derivation produced ' + derived.length + ' new fact(s) from ' + initialFacts.length + ' stated fact(s).');
1065
- }
1066
- if (keyFact) lines.push('Main entailment: **' + factSentence(keyFact) + '**');
1067
- const bullets = selected.slice(-6).reverse();
1068
- if (bullets.length) {
1069
- lines.push('');
1070
- lines.push('Selected entailments:');
1071
- for (const fact of bullets) lines.push('- ' + codeFact(fact));
1072
- }
1073
- lines.push('');
1074
- lines.push('## Explanation');
1075
- const ordinaryRules = (rules || []).filter((r) => r.kind !== 'fuse').length;
1076
- const fuses = (rules || []).filter((r) => r.kind === 'fuse').length;
1077
- lines.push('Starts with ' + initialFacts.length + ' source fact(s), applies ' + ordinaryRules + ' rule(s), and reaches a fixpoint.');
1078
- if (queries.length) lines.push('The log:query projection then keeps only the matching fact(s) shown above.');
1079
- if (fuses) lines.push('The run also validates ' + fuses + ' fuse(s) for forbidden patterns.');
1080
- const apps = traceApplications(trace, rules);
1081
- if (apps.length) {
1082
- lines.push('');
1083
- lines.push('Derivation steps:');
1084
- const sourceKeys = new Set((initialFacts || []).map((f) => codeFact(f).replace(/ \.$/, '')));
1085
- for (const app of apps) {
1086
- const produced = app.facts.slice(0, 4).map((f) => compactSupportFactText(f) + ' .').join(', ');
1087
- const more = app.facts.length > 4 ? ', … +' + (app.facts.length - 4) + ' more' : '';
1088
- lines.push('- ' + describeRule(app.rule) + ' derives ' + produced + more);
1089
- if (app.supportFacts && app.supportFacts.length) {
1090
- const used = app.supportFacts.slice(0, 4).map((fact) => compactSupportFactText(fact) + ' . ' + (sourceKeys.has(fact) ? '_(source)_' : '_(derived)_')).join('; ');
1091
- const omitted = app.supportFacts.length > 4 ? '; … +' + (app.supportFacts.length - 4) + ' more premise fact(s)' : '';
1092
- lines.push(' - Uses: ' + used + omitted);
1093
- } else {
1094
- lines.push(' - Uses: no graph premises; built-ins/constants satisfied the rule.');
1095
- }
1096
- }
1097
- }
1098
- const supportLines = conclusionSupportSection(selected, trace, rules, initialFacts);
1099
- if (supportLines.length) {
1100
- lines.push('');
1101
- lines.push(...supportLines);
1102
- }
1103
- lines.push('');
1104
- lines.push(evidenceSummaryLine(mode));
1105
- return lines.join('\n') + '\n';
1106
- }
1107
- function renderRawOutput(graph, queries = [], rules = [], initialFacts = []) {
1108
- const outs = outputStrings(graph);
1109
- if (outs.length) return outs.join('');
1110
- if (queries && queries.length) {
1111
- const selected = queryFacts(graph, queries, rules);
1112
- if (selected.length) return selected.map((f) => codeFact(f)).join('\n') + '\n';
1113
- return '';
1114
- }
1115
- const formulaFacts = graph.facts.filter((f) => f.o && f.o.kind === 'formula');
1116
- if (formulaFacts.length) return formulaFacts.map((f) => codeFact(f)).join('\n') + '\n';
1117
- const derived = derivedFacts(graph, initialFacts);
1118
- const selected = derived.length ? derived : graph.facts.slice(0, 30);
1119
- return selected.map((f) => codeFact(f)).join('\n') + '\n';
1120
- }
1121
- function dedupeExplanationHeadings(text) {
1122
- let seen = false;
1123
- return String(text || '').replace(/^##\s+Explanation\s*$/gmi, () => {
1124
- if (seen) return '';
1125
- seen = true;
1126
- return '## Explanation';
1127
- });
1128
- }
1129
- function normalizePublicReport(markdown, title) {
1130
- let text = String(markdown || '').trimEnd();
1131
- if (!/^\s*#\s+/m.test(text)) text = '# ' + title + '\n\n' + text;
1132
- if (!/^##\s+Entailment\s*$/mi.test(text)) {
1133
- text = text.replace(/^(#\s+[^\n]+\n*)/, '$1\n## Entailment\n');
1134
- }
1135
- if (!/^##\s+Explanation\s*$/mi.test(text)) {
1136
- text += '\n\n## Explanation\nNo additional explanation was provided by the generated output.';
1137
- }
1138
- text = text.replace(/^##\s+([^\n]+?)\s*$/gm, (line, heading) => {
1139
- const normalized = heading.trim().toLowerCase();
1140
- if (normalized === 'insight' || normalized === 'conclusion' || normalized === 'entailment' || normalized === 'explanation') return '## ' + (normalized === 'explanation' ? 'Explanation' : 'Entailment');
1141
- return '**' + heading.trim() + '**';
1142
- });
1143
- text = dedupeExplanationHeadings(text);
1144
- return text.trimEnd() + '\n';
1145
- }
1146
- function markdownize(raw, title) {
1147
- let text = String(raw || '');
1148
- text = text
1149
- .replace(/===\s*Answer\s*===/g, '## Entailment')
1150
- .replace(/===\s*Reason\s+Why\s*===/gi, '## Explanation')
1151
- .replace(/===\s*Explanation\s*===/gi, '## Explanation')
1152
- .replace(/===\s*([^=]+?)\s*===/g, (_, h) => '**' + h.trim() + '**');
1153
- text = text.replace(/^C(\d+)\s+OK\s*-\s*/gm, 'C$1: ');
1154
- text = dedupeExplanationHeadings(text);
1155
- if (!text.trim()) text = '## Entailment\nNo log:outputString facts were derived.\n\n## Explanation\nThe compiled derivation did not produce authored report text.';
1156
- return normalizePublicReport(text, title);
1157
- }
1158
- function authoredSupportAppendix(graph, queries, rules, initialFacts, trace) {
1159
- const derived = derivedFacts(graph, initialFacts);
1160
- let selected = [];
1161
- if (queries && queries.length) selected = queryFacts(graph, queries, rules);
1162
- else if (graph.facts.some((f) => f.o && f.o.kind === 'formula')) selected = graph.facts.filter((f) => f.o && f.o.kind === 'formula');
1163
- else selected = derived;
1164
- const lines = [];
1165
- const ordinaryRules = (rules || []).filter((r) => r.kind !== 'fuse').length;
1166
- const apps = traceApplications(trace, rules, 6);
1167
- const supportLines = conclusionSupportSection(selected, trace, rules, initialFacts, 4);
1168
- if (!apps.length && !supportLines.length) return '';
1169
- lines.push('**Generated derivation support**');
1170
- lines.push('');
1171
- lines.push('Compiled support: ' + initialFacts.length + ' source fact(s), ' + ordinaryRules + ' rule(s), fixpoint reached before rendering.');
1172
- if (apps.length) {
1173
- lines.push('');
1174
- lines.push('Derivation steps:');
1175
- const sourceKeys = new Set((initialFacts || []).map((f) => codeFact(f).replace(/ \.$/, '')));
1176
- for (const app of apps) {
1177
- const produced = app.facts.slice(0, 4).map((f) => compactSupportFactText(f) + ' .').join(', ');
1178
- const more = app.facts.length > 4 ? ', … +' + (app.facts.length - 4) + ' more' : '';
1179
- lines.push('- ' + describeRule(app.rule) + ' derives ' + produced + more);
1180
- if (app.supportFacts && app.supportFacts.length) {
1181
- const used = app.supportFacts.slice(0, 4).map((fact) => compactSupportFactText(fact) + ' . ' + (sourceKeys.has(fact) ? '_(source)_' : '_(derived)_')).join('; ');
1182
- const omitted = app.supportFacts.length > 4 ? '; … +' + (app.supportFacts.length - 4) + ' more premise fact(s)' : '';
1183
- lines.push(' - Uses: ' + used + omitted);
1184
- } else {
1185
- lines.push(' - Uses: no graph premises; built-ins/constants satisfied the rule.');
1186
- }
1187
- }
1188
- }
1189
- if (supportLines.length) {
1190
- lines.push('');
1191
- lines.push(...supportLines);
1192
- }
1193
- return lines.join('\n');
1194
- }
1195
- function appendAuthoredExplanation(markdown, graph, queries, rules, initialFacts, trace) {
1196
- const appendix = authoredSupportAppendix(graph, queries, rules, initialFacts, trace);
1197
- if (!appendix) return markdown;
1198
- return markdown.trimEnd() + '\n\n' + appendix + '\n';
1199
- }
1200
- function renderPresentation(graph, queries, rules, initialFacts, title, trace) {
1201
- const outs = outputStrings(graph);
1202
- if (outs.length) return appendAuthoredExplanation(markdownize(outs.join(''), title), graph, queries, rules, initialFacts, trace);
1203
- if (queries && queries.length) return renderStructuredOutput({ title, graph, queries, rules, initialFacts, trace, mode: 'query' });
1204
- if (graph.facts.some((f) => f.o && f.o.kind === 'formula')) return renderStructuredOutput({ title, graph, queries, rules, initialFacts, trace, mode: 'formula' });
1205
- return renderStructuredOutput({ title, graph, queries, rules, initialFacts, trace, mode: 'derived' });
1206
- }
1207
-
1208
- const NAME = "bayes_therapy";
1209
- const TITLE = "Bayes Therapy";
1210
- const EXPECTED_INPUT_FACTS = 104;
1211
- const RULES = [
1212
- {
1213
- "kind": "fuse",
1214
- "id": 1,
1215
- "body": [
1216
- {
1217
- "s": {
1218
- "kind": "var",
1219
- "value": "d"
1220
- },
1221
- "p": {
1222
- "kind": "iri",
1223
- "value": ":prior"
1224
- },
1225
- "o": {
1226
- "kind": "var",
1227
- "value": "p"
1228
- }
1229
- },
1230
- {
1231
- "s": {
1232
- "kind": "var",
1233
- "value": "p"
1234
- },
1235
- "p": {
1236
- "kind": "iri",
1237
- "value": "math:lessThan"
1238
- },
1239
- "o": {
1240
- "kind": "lit",
1241
- "value": 0
1242
- }
1243
- }
1244
- ],
1245
- "bodyComment": [
1246
- "?d :prior ?p",
1247
- "?p math:lessThan 0"
1248
- ],
1249
- "headComment": []
1250
- },
1251
- {
1252
- "kind": "fuse",
1253
- "id": 2,
1254
- "body": [
1255
- {
1256
- "s": {
1257
- "kind": "var",
1258
- "value": "d"
1259
- },
1260
- "p": {
1261
- "kind": "iri",
1262
- "value": ":prior"
1263
- },
1264
- "o": {
1265
- "kind": "var",
1266
- "value": "p"
1267
- }
1268
- },
1269
- {
1270
- "s": {
1271
- "kind": "var",
1272
- "value": "p"
1273
- },
1274
- "p": {
1275
- "kind": "iri",
1276
- "value": "math:greaterThan"
1277
- },
1278
- "o": {
1279
- "kind": "lit",
1280
- "value": 1
1281
- }
1282
- }
1283
- ],
1284
- "bodyComment": [
1285
- "?d :prior ?p",
1286
- "?p math:greaterThan 1"
1287
- ],
1288
- "headComment": []
1289
- },
1290
- {
1291
- "kind": "fuse",
1292
- "id": 3,
1293
- "body": [
1294
- {
1295
- "s": {
1296
- "kind": "var",
1297
- "value": "_bodyBlank26"
1298
- },
1299
- "p": {
1300
- "kind": "iri",
1301
- "value": ":p"
1302
- },
1303
- "o": {
1304
- "kind": "var",
1305
- "value": "p"
1306
- }
1307
- },
1308
- {
1309
- "s": {
1310
- "kind": "var",
1311
- "value": "d"
1312
- },
1313
- "p": {
1314
- "kind": "iri",
1315
- "value": ":pGiven"
1316
- },
1317
- "o": {
1318
- "kind": "var",
1319
- "value": "_bodyBlank26"
1320
- }
1321
- },
1322
- {
1323
- "s": {
1324
- "kind": "var",
1325
- "value": "p"
1326
- },
1327
- "p": {
1328
- "kind": "iri",
1329
- "value": "math:lessThan"
1330
- },
1331
- "o": {
1332
- "kind": "lit",
1333
- "value": 0
1334
- }
1335
- }
1336
- ],
1337
- "bodyComment": [
1338
- "?_bodyBlank26 :p ?p",
1339
- "?d :pGiven ?_bodyBlank26",
1340
- "?p math:lessThan 0"
1341
- ],
1342
- "headComment": []
1343
- },
1344
- {
1345
- "kind": "fuse",
1346
- "id": 4,
1347
- "body": [
1348
- {
1349
- "s": {
1350
- "kind": "var",
1351
- "value": "_bodyBlank27"
1352
- },
1353
- "p": {
1354
- "kind": "iri",
1355
- "value": ":p"
1356
- },
1357
- "o": {
1358
- "kind": "var",
1359
- "value": "p"
1360
- }
1361
- },
1362
- {
1363
- "s": {
1364
- "kind": "var",
1365
- "value": "d"
1366
- },
1367
- "p": {
1368
- "kind": "iri",
1369
- "value": ":pGiven"
1370
- },
1371
- "o": {
1372
- "kind": "var",
1373
- "value": "_bodyBlank27"
1374
- }
1375
- },
1376
- {
1377
- "s": {
1378
- "kind": "var",
1379
- "value": "p"
1380
- },
1381
- "p": {
1382
- "kind": "iri",
1383
- "value": "math:greaterThan"
1384
- },
1385
- "o": {
1386
- "kind": "lit",
1387
- "value": 1
1388
- }
1389
- }
1390
- ],
1391
- "bodyComment": [
1392
- "?_bodyBlank27 :p ?p",
1393
- "?d :pGiven ?_bodyBlank27",
1394
- "?p math:greaterThan 1"
1395
- ],
1396
- "headComment": []
1397
- },
1398
- {
1399
- "kind": "fuse",
1400
- "id": 5,
1401
- "body": [
1402
- {
1403
- "s": {
1404
- "kind": "var",
1405
- "value": "t"
1406
- },
1407
- "p": {
1408
- "kind": "iri",
1409
- "value": "rdf:type"
1410
- },
1411
- "o": {
1412
- "kind": "iri",
1413
- "value": ":Therapy"
1414
- }
1415
- },
1416
- {
1417
- "s": {
1418
- "kind": "var",
1419
- "value": "t"
1420
- },
1421
- "p": {
1422
- "kind": "iri",
1423
- "value": ":adverse"
1424
- },
1425
- "o": {
1426
- "kind": "var",
1427
- "value": "p"
1428
- }
1429
- },
1430
- {
1431
- "s": {
1432
- "kind": "var",
1433
- "value": "p"
1434
- },
1435
- "p": {
1436
- "kind": "iri",
1437
- "value": "math:lessThan"
1438
- },
1439
- "o": {
1440
- "kind": "lit",
1441
- "value": 0
1442
- }
1443
- }
1444
- ],
1445
- "bodyComment": [
1446
- "?t rdf:type :Therapy",
1447
- "?t :adverse ?p",
1448
- "?p math:lessThan 0"
1449
- ],
1450
- "headComment": []
1451
- },
1452
- {
1453
- "kind": "fuse",
1454
- "id": 6,
1455
- "body": [
1456
- {
1457
- "s": {
1458
- "kind": "var",
1459
- "value": "t"
1460
- },
1461
- "p": {
1462
- "kind": "iri",
1463
- "value": "rdf:type"
1464
- },
1465
- "o": {
1466
- "kind": "iri",
1467
- "value": ":Therapy"
1468
- }
1469
- },
1470
- {
1471
- "s": {
1472
- "kind": "var",
1473
- "value": "t"
1474
- },
1475
- "p": {
1476
- "kind": "iri",
1477
- "value": ":adverse"
1478
- },
1479
- "o": {
1480
- "kind": "var",
1481
- "value": "p"
1482
- }
1483
- },
1484
- {
1485
- "s": {
1486
- "kind": "var",
1487
- "value": "p"
1488
- },
1489
- "p": {
1490
- "kind": "iri",
1491
- "value": "math:greaterThan"
1492
- },
1493
- "o": {
1494
- "kind": "lit",
1495
- "value": 1
1496
- }
1497
- }
1498
- ],
1499
- "bodyComment": [
1500
- "?t rdf:type :Therapy",
1501
- "?t :adverse ?p",
1502
- "?p math:greaterThan 1"
1503
- ],
1504
- "headComment": []
1505
- },
1506
- {
1507
- "kind": "fuse",
1508
- "id": 7,
1509
- "body": [
1510
- {
1511
- "s": {
1512
- "kind": "var",
1513
- "value": "t"
1514
- },
1515
- "p": {
1516
- "kind": "iri",
1517
- "value": "rdf:type"
1518
- },
1519
- "o": {
1520
- "kind": "iri",
1521
- "value": ":Therapy"
1522
- }
1523
- },
1524
- {
1525
- "s": {
1526
- "kind": "var",
1527
- "value": "t"
1528
- },
1529
- "p": {
1530
- "kind": "iri",
1531
- "value": ":successByDisease"
1532
- },
1533
- "o": {
1534
- "kind": "var",
1535
- "value": "ps"
1536
- }
1537
- },
1538
- {
1539
- "s": {
1540
- "kind": "var",
1541
- "value": "ps"
1542
- },
1543
- "p": {
1544
- "kind": "iri",
1545
- "value": "list:iterate"
1546
- },
1547
- "o": {
1548
- "kind": "list",
1549
- "items": [
1550
- {
1551
- "kind": "var",
1552
- "value": "i"
1553
- },
1554
- {
1555
- "kind": "var",
1556
- "value": "p"
1557
- }
1558
- ]
1559
- }
1560
- },
1561
- {
1562
- "s": {
1563
- "kind": "var",
1564
- "value": "p"
1565
- },
1566
- "p": {
1567
- "kind": "iri",
1568
- "value": "math:lessThan"
1569
- },
1570
- "o": {
1571
- "kind": "lit",
1572
- "value": 0
1573
- }
1574
- }
1575
- ],
1576
- "bodyComment": [
1577
- "?t rdf:type :Therapy",
1578
- "?t :successByDisease ?ps",
1579
- "?ps list:iterate (?i ?p)",
1580
- "?p math:lessThan 0"
1581
- ],
1582
- "headComment": []
1583
- },
1584
- {
1585
- "kind": "fuse",
1586
- "id": 8,
1587
- "body": [
1588
- {
1589
- "s": {
1590
- "kind": "var",
1591
- "value": "t"
1592
- },
1593
- "p": {
1594
- "kind": "iri",
1595
- "value": "rdf:type"
1596
- },
1597
- "o": {
1598
- "kind": "iri",
1599
- "value": ":Therapy"
1600
- }
1601
- },
1602
- {
1603
- "s": {
1604
- "kind": "var",
1605
- "value": "t"
1606
- },
1607
- "p": {
1608
- "kind": "iri",
1609
- "value": ":successByDisease"
1610
- },
1611
- "o": {
1612
- "kind": "var",
1613
- "value": "ps"
1614
- }
1615
- },
1616
- {
1617
- "s": {
1618
- "kind": "var",
1619
- "value": "ps"
1620
- },
1621
- "p": {
1622
- "kind": "iri",
1623
- "value": "list:iterate"
1624
- },
1625
- "o": {
1626
- "kind": "list",
1627
- "items": [
1628
- {
1629
- "kind": "var",
1630
- "value": "i"
1631
- },
1632
- {
1633
- "kind": "var",
1634
- "value": "p"
1635
- }
1636
- ]
1637
- }
1638
- },
1639
- {
1640
- "s": {
1641
- "kind": "var",
1642
- "value": "p"
1643
- },
1644
- "p": {
1645
- "kind": "iri",
1646
- "value": "math:greaterThan"
1647
- },
1648
- "o": {
1649
- "kind": "lit",
1650
- "value": 1
1651
- }
1652
- }
1653
- ],
1654
- "bodyComment": [
1655
- "?t rdf:type :Therapy",
1656
- "?t :successByDisease ?ps",
1657
- "?ps list:iterate (?i ?p)",
1658
- "?p math:greaterThan 1"
1659
- ],
1660
- "headComment": []
1661
- },
1662
- {
1663
- "kind": "backward",
1664
- "id": 9,
1665
- "body": [],
1666
- "head": [
1667
- {
1668
- "s": {
1669
- "kind": "list",
1670
- "items": [
1671
- {
1672
- "kind": "var",
1673
- "value": "d"
1674
- },
1675
- {
1676
- "kind": "list",
1677
- "items": []
1678
- }
1679
- ]
1680
- },
1681
- "p": {
1682
- "kind": "iri",
1683
- "value": ":pairList"
1684
- },
1685
- "o": {
1686
- "kind": "list",
1687
- "items": []
1688
- }
1689
- }
1690
- ],
1691
- "bodyComment": [],
1692
- "headComment": [
1693
- "(?d ()) :pairList ()"
1694
- ]
1695
- },
1696
- {
1697
- "kind": "backward",
1698
- "id": 10,
1699
- "body": [
1700
- {
1701
- "s": {
1702
- "kind": "var",
1703
- "value": "xs"
1704
- },
1705
- "p": {
1706
- "kind": "iri",
1707
- "value": "list:firstRest"
1708
- },
1709
- "o": {
1710
- "kind": "list",
1711
- "items": [
1712
- {
1713
- "kind": "var",
1714
- "value": "x"
1715
- },
1716
- {
1717
- "kind": "var",
1718
- "value": "rest"
1719
- }
1720
- ]
1721
- }
1722
- },
1723
- {
1724
- "s": {
1725
- "kind": "list",
1726
- "items": [
1727
- {
1728
- "kind": "var",
1729
- "value": "d"
1730
- },
1731
- {
1732
- "kind": "var",
1733
- "value": "rest"
1734
- }
1735
- ]
1736
- },
1737
- "p": {
1738
- "kind": "iri",
1739
- "value": ":pairList"
1740
- },
1741
- "o": {
1742
- "kind": "var",
1743
- "value": "tailPairs"
1744
- }
1745
- },
1746
- {
1747
- "s": {
1748
- "kind": "var",
1749
- "value": "pairs"
1750
- },
1751
- "p": {
1752
- "kind": "iri",
1753
- "value": "list:firstRest"
1754
- },
1755
- "o": {
1756
- "kind": "list",
1757
- "items": [
1758
- {
1759
- "kind": "list",
1760
- "items": [
1761
- {
1762
- "kind": "var",
1763
- "value": "d"
1764
- },
1765
- {
1766
- "kind": "var",
1767
- "value": "x"
1768
- }
1769
- ]
1770
- },
1771
- {
1772
- "kind": "var",
1773
- "value": "tailPairs"
1774
- }
1775
- ]
1776
- }
1777
- }
1778
- ],
1779
- "head": [
1780
- {
1781
- "s": {
1782
- "kind": "list",
1783
- "items": [
1784
- {
1785
- "kind": "var",
1786
- "value": "d"
1787
- },
1788
- {
1789
- "kind": "var",
1790
- "value": "xs"
1791
- }
1792
- ]
1793
- },
1794
- "p": {
1795
- "kind": "iri",
1796
- "value": ":pairList"
1797
- },
1798
- "o": {
1799
- "kind": "var",
1800
- "value": "pairs"
1801
- }
1802
- }
1803
- ],
1804
- "bodyComment": [
1805
- "?xs list:firstRest (?x ?rest)",
1806
- "(?d ?rest) :pairList ?tailPairs",
1807
- "?pairs list:firstRest ((?d ?x) ?tailPairs)"
1808
- ],
1809
- "headComment": [
1810
- "(?d ?xs) :pairList ?pairs"
1811
- ]
1812
- },
1813
- {
1814
- "kind": "backward",
1815
- "id": 11,
1816
- "body": [],
1817
- "head": [
1818
- {
1819
- "s": {
1820
- "kind": "list",
1821
- "items": [
1822
- {
1823
- "kind": "list",
1824
- "items": []
1825
- },
1826
- {
1827
- "kind": "var",
1828
- "value": "c"
1829
- }
1830
- ]
1831
- },
1832
- "p": {
1833
- "kind": "iri",
1834
- "value": ":pairWithConst"
1835
- },
1836
- "o": {
1837
- "kind": "list",
1838
- "items": []
1839
- }
1840
- }
1841
- ],
1842
- "bodyComment": [],
1843
- "headComment": [
1844
- "(() ?c) :pairWithConst ()"
1845
- ]
1846
- },
1847
- {
1848
- "kind": "backward",
1849
- "id": 12,
1850
- "body": [
1851
- {
1852
- "s": {
1853
- "kind": "var",
1854
- "value": "xs"
1855
- },
1856
- "p": {
1857
- "kind": "iri",
1858
- "value": "list:firstRest"
1859
- },
1860
- "o": {
1861
- "kind": "list",
1862
- "items": [
1863
- {
1864
- "kind": "var",
1865
- "value": "x"
1866
- },
1867
- {
1868
- "kind": "var",
1869
- "value": "rest"
1870
- }
1871
- ]
1872
- }
1873
- },
1874
- {
1875
- "s": {
1876
- "kind": "list",
1877
- "items": [
1878
- {
1879
- "kind": "var",
1880
- "value": "rest"
1881
- },
1882
- {
1883
- "kind": "var",
1884
- "value": "c"
1885
- }
1886
- ]
1887
- },
1888
- "p": {
1889
- "kind": "iri",
1890
- "value": ":pairWithConst"
1891
- },
1892
- "o": {
1893
- "kind": "var",
1894
- "value": "tailPairs"
1895
- }
1896
- },
1897
- {
1898
- "s": {
1899
- "kind": "var",
1900
- "value": "pairs"
1901
- },
1902
- "p": {
1903
- "kind": "iri",
1904
- "value": "list:firstRest"
1905
- },
1906
- "o": {
1907
- "kind": "list",
1908
- "items": [
1909
- {
1910
- "kind": "list",
1911
- "items": [
1912
- {
1913
- "kind": "var",
1914
- "value": "x"
1915
- },
1916
- {
1917
- "kind": "var",
1918
- "value": "c"
1919
- }
1920
- ]
1921
- },
1922
- {
1923
- "kind": "var",
1924
- "value": "tailPairs"
1925
- }
1926
- ]
1927
- }
1928
- }
1929
- ],
1930
- "head": [
1931
- {
1932
- "s": {
1933
- "kind": "list",
1934
- "items": [
1935
- {
1936
- "kind": "var",
1937
- "value": "xs"
1938
- },
1939
- {
1940
- "kind": "var",
1941
- "value": "c"
1942
- }
1943
- ]
1944
- },
1945
- "p": {
1946
- "kind": "iri",
1947
- "value": ":pairWithConst"
1948
- },
1949
- "o": {
1950
- "kind": "var",
1951
- "value": "pairs"
1952
- }
1953
- }
1954
- ],
1955
- "bodyComment": [
1956
- "?xs list:firstRest (?x ?rest)",
1957
- "(?rest ?c) :pairWithConst ?tailPairs",
1958
- "?pairs list:firstRest ((?x ?c) ?tailPairs)"
1959
- ],
1960
- "headComment": [
1961
- "(?xs ?c) :pairWithConst ?pairs"
1962
- ]
1963
- },
1964
- {
1965
- "kind": "backward",
1966
- "id": 13,
1967
- "body": [],
1968
- "head": [
1969
- {
1970
- "s": {
1971
- "kind": "list",
1972
- "items": [
1973
- {
1974
- "kind": "list",
1975
- "items": []
1976
- },
1977
- {
1978
- "kind": "list",
1979
- "items": []
1980
- }
1981
- ]
1982
- },
1983
- "p": {
1984
- "kind": "iri",
1985
- "value": ":zip"
1986
- },
1987
- "o": {
1988
- "kind": "list",
1989
- "items": []
1990
- }
1991
- }
1992
- ],
1993
- "bodyComment": [],
1994
- "headComment": [
1995
- "(() ()) :zip ()"
1996
- ]
1997
- },
1998
- {
1999
- "kind": "backward",
2000
- "id": 14,
2001
- "body": [
2002
- {
2003
- "s": {
2004
- "kind": "var",
2005
- "value": "as"
2006
- },
2007
- "p": {
2008
- "kind": "iri",
2009
- "value": "list:firstRest"
2010
- },
2011
- "o": {
2012
- "kind": "list",
2013
- "items": [
2014
- {
2015
- "kind": "var",
2016
- "value": "a"
2017
- },
2018
- {
2019
- "kind": "var",
2020
- "value": "arest"
2021
- }
2022
- ]
2023
- }
2024
- },
2025
- {
2026
- "s": {
2027
- "kind": "var",
2028
- "value": "bs"
2029
- },
2030
- "p": {
2031
- "kind": "iri",
2032
- "value": "list:firstRest"
2033
- },
2034
- "o": {
2035
- "kind": "list",
2036
- "items": [
2037
- {
2038
- "kind": "var",
2039
- "value": "b"
2040
- },
2041
- {
2042
- "kind": "var",
2043
- "value": "brest"
2044
- }
2045
- ]
2046
- }
2047
- },
2048
- {
2049
- "s": {
2050
- "kind": "list",
2051
- "items": [
2052
- {
2053
- "kind": "var",
2054
- "value": "arest"
2055
- },
2056
- {
2057
- "kind": "var",
2058
- "value": "brest"
2059
- }
2060
- ]
2061
- },
2062
- "p": {
2063
- "kind": "iri",
2064
- "value": ":zip"
2065
- },
2066
- "o": {
2067
- "kind": "var",
2068
- "value": "tailPairs"
2069
- }
2070
- },
2071
- {
2072
- "s": {
2073
- "kind": "var",
2074
- "value": "pairs"
2075
- },
2076
- "p": {
2077
- "kind": "iri",
2078
- "value": "list:firstRest"
2079
- },
2080
- "o": {
2081
- "kind": "list",
2082
- "items": [
2083
- {
2084
- "kind": "list",
2085
- "items": [
2086
- {
2087
- "kind": "var",
2088
- "value": "a"
2089
- },
2090
- {
2091
- "kind": "var",
2092
- "value": "b"
2093
- }
2094
- ]
2095
- },
2096
- {
2097
- "kind": "var",
2098
- "value": "tailPairs"
2099
- }
2100
- ]
2101
- }
2102
- }
2103
- ],
2104
- "head": [
2105
- {
2106
- "s": {
2107
- "kind": "list",
2108
- "items": [
2109
- {
2110
- "kind": "var",
2111
- "value": "as"
2112
- },
2113
- {
2114
- "kind": "var",
2115
- "value": "bs"
2116
- }
2117
- ]
2118
- },
2119
- "p": {
2120
- "kind": "iri",
2121
- "value": ":zip"
2122
- },
2123
- "o": {
2124
- "kind": "var",
2125
- "value": "pairs"
2126
- }
2127
- }
2128
- ],
2129
- "bodyComment": [
2130
- "?as list:firstRest (?a ?arest)",
2131
- "?bs list:firstRest (?b ?brest)",
2132
- "(?arest ?brest) :zip ?tailPairs",
2133
- "?pairs list:firstRest ((?a ?b) ?tailPairs)"
2134
- ],
2135
- "headComment": [
2136
- "(?as ?bs) :zip ?pairs"
2137
- ]
2138
- },
2139
- {
2140
- "kind": "backward",
2141
- "id": 15,
2142
- "body": [
2143
- {
2144
- "s": {
2145
- "kind": "var",
2146
- "value": "pair"
2147
- },
2148
- "p": {
2149
- "kind": "iri",
2150
- "value": "math:product"
2151
- },
2152
- "o": {
2153
- "kind": "var",
2154
- "value": "p"
2155
- }
2156
- }
2157
- ],
2158
- "head": [
2159
- {
2160
- "s": {
2161
- "kind": "var",
2162
- "value": "pair"
2163
- },
2164
- "p": {
2165
- "kind": "iri",
2166
- "value": ":mul"
2167
- },
2168
- "o": {
2169
- "kind": "var",
2170
- "value": "p"
2171
- }
2172
- }
2173
- ],
2174
- "bodyComment": [
2175
- "?pair math:product ?p"
2176
- ],
2177
- "headComment": [
2178
- "?pair :mul ?p"
2179
- ]
2180
- },
2181
- {
2182
- "kind": "backward",
2183
- "id": 16,
2184
- "body": [
2185
- {
2186
- "s": {
2187
- "kind": "var",
2188
- "value": "pair"
2189
- },
2190
- "p": {
2191
- "kind": "iri",
2192
- "value": "math:quotient"
2193
- },
2194
- "o": {
2195
- "kind": "var",
2196
- "value": "q"
2197
- }
2198
- }
2199
- ],
2200
- "head": [
2201
- {
2202
- "s": {
2203
- "kind": "var",
2204
- "value": "pair"
2205
- },
2206
- "p": {
2207
- "kind": "iri",
2208
- "value": ":quot2"
2209
- },
2210
- "o": {
2211
- "kind": "var",
2212
- "value": "q"
2213
- }
2214
- }
2215
- ],
2216
- "bodyComment": [
2217
- "?pair math:quotient ?q"
2218
- ],
2219
- "headComment": [
2220
- "?pair :quot2 ?q"
2221
- ]
2222
- },
2223
- {
2224
- "kind": "backward",
2225
- "id": 17,
2226
- "body": [
2227
- {
2228
- "s": {
2229
- "kind": "var",
2230
- "value": "ev"
2231
- },
2232
- "p": {
2233
- "kind": "iri",
2234
- "value": ":symptom"
2235
- },
2236
- "o": {
2237
- "kind": "var",
2238
- "value": "s"
2239
- }
2240
- },
2241
- {
2242
- "s": {
2243
- "kind": "var",
2244
- "value": "ev"
2245
- },
2246
- "p": {
2247
- "kind": "iri",
2248
- "value": ":present"
2249
- },
2250
- "o": {
2251
- "kind": "lit",
2252
- "value": true
2253
- }
2254
- },
2255
- {
2256
- "s": {
2257
- "kind": "var",
2258
- "value": "_bodyBlank28"
2259
- },
2260
- "p": {
2261
- "kind": "iri",
2262
- "value": ":symptom"
2263
- },
2264
- "o": {
2265
- "kind": "var",
2266
- "value": "s"
2267
- }
2268
- },
2269
- {
2270
- "s": {
2271
- "kind": "var",
2272
- "value": "_bodyBlank28"
2273
- },
2274
- "p": {
2275
- "kind": "iri",
2276
- "value": ":p"
2277
- },
2278
- "o": {
2279
- "kind": "var",
2280
- "value": "p"
2281
- }
2282
- },
2283
- {
2284
- "s": {
2285
- "kind": "var",
2286
- "value": "d"
2287
- },
2288
- "p": {
2289
- "kind": "iri",
2290
- "value": ":pGiven"
2291
- },
2292
- "o": {
2293
- "kind": "var",
2294
- "value": "_bodyBlank28"
2295
- }
2296
- }
2297
- ],
2298
- "head": [
2299
- {
2300
- "s": {
2301
- "kind": "list",
2302
- "items": [
2303
- {
2304
- "kind": "var",
2305
- "value": "d"
2306
- },
2307
- {
2308
- "kind": "var",
2309
- "value": "ev"
2310
- }
2311
- ]
2312
- },
2313
- "p": {
2314
- "kind": "iri",
2315
- "value": ":factor"
2316
- },
2317
- "o": {
2318
- "kind": "var",
2319
- "value": "p"
2320
- }
2321
- }
2322
- ],
2323
- "bodyComment": [
2324
- "?ev :symptom ?s",
2325
- "?ev :present true",
2326
- "?_bodyBlank28 :symptom ?s",
2327
- "?_bodyBlank28 :p ?p",
2328
- "?d :pGiven ?_bodyBlank28"
2329
- ],
2330
- "headComment": [
2331
- "(?d ?ev) :factor ?p"
2332
- ]
2333
- },
2334
- {
2335
- "kind": "backward",
2336
- "id": 18,
2337
- "body": [
2338
- {
2339
- "s": {
2340
- "kind": "var",
2341
- "value": "ev"
2342
- },
2343
- "p": {
2344
- "kind": "iri",
2345
- "value": ":symptom"
2346
- },
2347
- "o": {
2348
- "kind": "var",
2349
- "value": "s"
2350
- }
2351
- },
2352
- {
2353
- "s": {
2354
- "kind": "var",
2355
- "value": "ev"
2356
- },
2357
- "p": {
2358
- "kind": "iri",
2359
- "value": ":present"
2360
- },
2361
- "o": {
2362
- "kind": "lit",
2363
- "value": false
2364
- }
2365
- },
2366
- {
2367
- "s": {
2368
- "kind": "var",
2369
- "value": "_bodyBlank29"
2370
- },
2371
- "p": {
2372
- "kind": "iri",
2373
- "value": ":symptom"
2374
- },
2375
- "o": {
2376
- "kind": "var",
2377
- "value": "s"
2378
- }
2379
- },
2380
- {
2381
- "s": {
2382
- "kind": "var",
2383
- "value": "_bodyBlank29"
2384
- },
2385
- "p": {
2386
- "kind": "iri",
2387
- "value": ":p"
2388
- },
2389
- "o": {
2390
- "kind": "var",
2391
- "value": "p"
2392
- }
2393
- },
2394
- {
2395
- "s": {
2396
- "kind": "var",
2397
- "value": "d"
2398
- },
2399
- "p": {
2400
- "kind": "iri",
2401
- "value": ":pGiven"
2402
- },
2403
- "o": {
2404
- "kind": "var",
2405
- "value": "_bodyBlank29"
2406
- }
2407
- },
2408
- {
2409
- "s": {
2410
- "kind": "list",
2411
- "items": [
2412
- {
2413
- "kind": "lit",
2414
- "value": 1
2415
- },
2416
- {
2417
- "kind": "var",
2418
- "value": "p"
2419
- }
2420
- ]
2421
- },
2422
- "p": {
2423
- "kind": "iri",
2424
- "value": "math:difference"
2425
- },
2426
- "o": {
2427
- "kind": "var",
2428
- "value": "q"
2429
- }
2430
- }
2431
- ],
2432
- "head": [
2433
- {
2434
- "s": {
2435
- "kind": "list",
2436
- "items": [
2437
- {
2438
- "kind": "var",
2439
- "value": "d"
2440
- },
2441
- {
2442
- "kind": "var",
2443
- "value": "ev"
2444
- }
2445
- ]
2446
- },
2447
- "p": {
2448
- "kind": "iri",
2449
- "value": ":factor"
2450
- },
2451
- "o": {
2452
- "kind": "var",
2453
- "value": "q"
2454
- }
2455
- }
2456
- ],
2457
- "bodyComment": [
2458
- "?ev :symptom ?s",
2459
- "?ev :present false",
2460
- "?_bodyBlank29 :symptom ?s",
2461
- "?_bodyBlank29 :p ?p",
2462
- "?d :pGiven ?_bodyBlank29",
2463
- "(1 ?p) math:difference ?q"
2464
- ],
2465
- "headComment": [
2466
- "(?d ?ev) :factor ?q"
2467
- ]
2468
- },
2469
- {
2470
- "kind": "backward",
2471
- "id": 19,
2472
- "body": [
2473
- {
2474
- "s": {
2475
- "kind": "var",
2476
- "value": "d"
2477
- },
2478
- "p": {
2479
- "kind": "iri",
2480
- "value": ":prior"
2481
- },
2482
- "o": {
2483
- "kind": "var",
2484
- "value": "prior"
2485
- }
2486
- },
2487
- {
2488
- "s": {
2489
- "kind": "iri",
2490
- "value": ":Case"
2491
- },
2492
- "p": {
2493
- "kind": "iri",
2494
- "value": ":evidence"
2495
- },
2496
- "o": {
2497
- "kind": "var",
2498
- "value": "evs"
2499
- }
2500
- },
2501
- {
2502
- "s": {
2503
- "kind": "list",
2504
- "items": [
2505
- {
2506
- "kind": "var",
2507
- "value": "d"
2508
- },
2509
- {
2510
- "kind": "var",
2511
- "value": "evs"
2512
- }
2513
- ]
2514
- },
2515
- "p": {
2516
- "kind": "iri",
2517
- "value": ":pairList"
2518
- },
2519
- "o": {
2520
- "kind": "var",
2521
- "value": "pairs"
2522
- }
2523
- },
2524
- {
2525
- "s": {
2526
- "kind": "list",
2527
- "items": [
2528
- {
2529
- "kind": "var",
2530
- "value": "pairs"
2531
- },
2532
- {
2533
- "kind": "iri",
2534
- "value": ":factor"
2535
- }
2536
- ]
2537
- },
2538
- "p": {
2539
- "kind": "iri",
2540
- "value": "list:map"
2541
- },
2542
- "o": {
2543
- "kind": "var",
2544
- "value": "factors"
2545
- }
2546
- },
2547
- {
2548
- "s": {
2549
- "kind": "var",
2550
- "value": "factors"
2551
- },
2552
- "p": {
2553
- "kind": "iri",
2554
- "value": "math:product"
2555
- },
2556
- "o": {
2557
- "kind": "var",
2558
- "value": "likelihood"
2559
- }
2560
- },
2561
- {
2562
- "s": {
2563
- "kind": "list",
2564
- "items": [
2565
- {
2566
- "kind": "var",
2567
- "value": "prior"
2568
- },
2569
- {
2570
- "kind": "var",
2571
- "value": "likelihood"
2572
- }
2573
- ]
2574
- },
2575
- "p": {
2576
- "kind": "iri",
2577
- "value": "math:product"
2578
- },
2579
- "o": {
2580
- "kind": "var",
2581
- "value": "score"
2582
- }
2583
- }
2584
- ],
2585
- "head": [
2586
- {
2587
- "s": {
2588
- "kind": "var",
2589
- "value": "d"
2590
- },
2591
- "p": {
2592
- "kind": "iri",
2593
- "value": ":scoreFor"
2594
- },
2595
- "o": {
2596
- "kind": "var",
2597
- "value": "score"
2598
- }
2599
- }
2600
- ],
2601
- "bodyComment": [
2602
- "?d :prior ?prior",
2603
- ":Case :evidence ?evs",
2604
- "(?d ?evs) :pairList ?pairs",
2605
- "(?pairs :factor) list:map ?factors",
2606
- "?factors math:product ?likelihood",
2607
- "(?prior ?likelihood) math:product ?score"
2608
- ],
2609
- "headComment": [
2610
- "?d :scoreFor ?score"
2611
- ]
2612
- },
2613
- {
2614
- "kind": "rule",
2615
- "id": 20,
2616
- "body": [
2617
- {
2618
- "s": {
2619
- "kind": "iri",
2620
- "value": ":Case"
2621
- },
2622
- "p": {
2623
- "kind": "iri",
2624
- "value": ":diseases"
2625
- },
2626
- "o": {
2627
- "kind": "var",
2628
- "value": "ds"
2629
- }
2630
- },
2631
- {
2632
- "s": {
2633
- "kind": "list",
2634
- "items": [
2635
- {
2636
- "kind": "var",
2637
- "value": "ds"
2638
- },
2639
- {
2640
- "kind": "iri",
2641
- "value": ":scoreFor"
2642
- }
2643
- ]
2644
- },
2645
- "p": {
2646
- "kind": "iri",
2647
- "value": "list:map"
2648
- },
2649
- "o": {
2650
- "kind": "var",
2651
- "value": "scores"
2652
- }
2653
- },
2654
- {
2655
- "s": {
2656
- "kind": "var",
2657
- "value": "scores"
2658
- },
2659
- "p": {
2660
- "kind": "iri",
2661
- "value": "math:sum"
2662
- },
2663
- "o": {
2664
- "kind": "var",
2665
- "value": "total"
2666
- }
2667
- },
2668
- {
2669
- "s": {
2670
- "kind": "list",
2671
- "items": [
2672
- {
2673
- "kind": "var",
2674
- "value": "scores"
2675
- },
2676
- {
2677
- "kind": "var",
2678
- "value": "total"
2679
- }
2680
- ]
2681
- },
2682
- "p": {
2683
- "kind": "iri",
2684
- "value": ":pairWithConst"
2685
- },
2686
- "o": {
2687
- "kind": "var",
2688
- "value": "scorePairs"
2689
- }
2690
- },
2691
- {
2692
- "s": {
2693
- "kind": "list",
2694
- "items": [
2695
- {
2696
- "kind": "var",
2697
- "value": "scorePairs"
2698
- },
2699
- {
2700
- "kind": "iri",
2701
- "value": ":quot2"
2702
- }
2703
- ]
2704
- },
2705
- "p": {
2706
- "kind": "iri",
2707
- "value": "list:map"
2708
- },
2709
- "o": {
2710
- "kind": "var",
2711
- "value": "posteriors"
2712
- }
2713
- }
2714
- ],
2715
- "head": [
2716
- {
2717
- "s": {
2718
- "kind": "iri",
2719
- "value": ":Case"
2720
- },
2721
- "p": {
2722
- "kind": "iri",
2723
- "value": ":scores"
2724
- },
2725
- "o": {
2726
- "kind": "var",
2727
- "value": "scores"
2728
- }
2729
- },
2730
- {
2731
- "s": {
2732
- "kind": "iri",
2733
- "value": ":Case"
2734
- },
2735
- "p": {
2736
- "kind": "iri",
2737
- "value": ":evidenceTotal"
2738
- },
2739
- "o": {
2740
- "kind": "var",
2741
- "value": "total"
2742
- }
2743
- },
2744
- {
2745
- "s": {
2746
- "kind": "iri",
2747
- "value": ":Case"
2748
- },
2749
- "p": {
2750
- "kind": "iri",
2751
- "value": ":posteriors"
2752
- },
2753
- "o": {
2754
- "kind": "var",
2755
- "value": "posteriors"
2756
- }
2757
- }
2758
- ],
2759
- "bodyComment": [
2760
- ":Case :diseases ?ds",
2761
- "(?ds :scoreFor) list:map ?scores",
2762
- "?scores math:sum ?total",
2763
- "(?scores ?total) :pairWithConst ?scorePairs",
2764
- "(?scorePairs :quot2) list:map ?posteriors"
2765
- ],
2766
- "headComment": [
2767
- ":Case :scores ?scores",
2768
- ":Case :evidenceTotal ?total",
2769
- ":Case :posteriors ?posteriors"
2770
- ]
2771
- },
2772
- {
2773
- "kind": "rule",
2774
- "id": 21,
2775
- "body": [
2776
- {
2777
- "s": {
2778
- "kind": "iri",
2779
- "value": ":Case"
2780
- },
2781
- "p": {
2782
- "kind": "iri",
2783
- "value": ":diseases"
2784
- },
2785
- "o": {
2786
- "kind": "var",
2787
- "value": "ds"
2788
- }
2789
- },
2790
- {
2791
- "s": {
2792
- "kind": "iri",
2793
- "value": ":Case"
2794
- },
2795
- "p": {
2796
- "kind": "iri",
2797
- "value": ":posteriors"
2798
- },
2799
- "o": {
2800
- "kind": "var",
2801
- "value": "posts"
2802
- }
2803
- },
2804
- {
2805
- "s": {
2806
- "kind": "var",
2807
- "value": "ds"
2808
- },
2809
- "p": {
2810
- "kind": "iri",
2811
- "value": "list:iterate"
2812
- },
2813
- "o": {
2814
- "kind": "list",
2815
- "items": [
2816
- {
2817
- "kind": "var",
2818
- "value": "i"
2819
- },
2820
- {
2821
- "kind": "var",
2822
- "value": "d"
2823
- }
2824
- ]
2825
- }
2826
- },
2827
- {
2828
- "s": {
2829
- "kind": "list",
2830
- "items": [
2831
- {
2832
- "kind": "var",
2833
- "value": "posts"
2834
- },
2835
- {
2836
- "kind": "var",
2837
- "value": "i"
2838
- }
2839
- ]
2840
- },
2841
- "p": {
2842
- "kind": "iri",
2843
- "value": "list:memberAt"
2844
- },
2845
- "o": {
2846
- "kind": "var",
2847
- "value": "p"
2848
- }
2849
- }
2850
- ],
2851
- "head": [
2852
- {
2853
- "s": {
2854
- "kind": "var",
2855
- "value": "d"
2856
- },
2857
- "p": {
2858
- "kind": "iri",
2859
- "value": ":posterior"
2860
- },
2861
- "o": {
2862
- "kind": "var",
2863
- "value": "p"
2864
- }
2865
- }
2866
- ],
2867
- "bodyComment": [
2868
- ":Case :diseases ?ds",
2869
- ":Case :posteriors ?posts",
2870
- "?ds list:iterate (?i ?d)",
2871
- "(?posts ?i) list:memberAt ?p"
2872
- ],
2873
- "headComment": [
2874
- "?d :posterior ?p"
2875
- ]
2876
- },
2877
- {
2878
- "kind": "rule",
2879
- "id": 22,
2880
- "body": [
2881
- {
2882
- "s": {
2883
- "kind": "iri",
2884
- "value": ":Case"
2885
- },
2886
- "p": {
2887
- "kind": "iri",
2888
- "value": ":posteriors"
2889
- },
2890
- "o": {
2891
- "kind": "var",
2892
- "value": "posts"
2893
- }
2894
- },
2895
- {
2896
- "s": {
2897
- "kind": "var",
2898
- "value": "t"
2899
- },
2900
- "p": {
2901
- "kind": "iri",
2902
- "value": "rdf:type"
2903
- },
2904
- "o": {
2905
- "kind": "iri",
2906
- "value": ":Therapy"
2907
- }
2908
- },
2909
- {
2910
- "s": {
2911
- "kind": "var",
2912
- "value": "t"
2913
- },
2914
- "p": {
2915
- "kind": "iri",
2916
- "value": ":successByDisease"
2917
- },
2918
- "o": {
2919
- "kind": "var",
2920
- "value": "succ"
2921
- }
2922
- },
2923
- {
2924
- "s": {
2925
- "kind": "var",
2926
- "value": "t"
2927
- },
2928
- "p": {
2929
- "kind": "iri",
2930
- "value": ":adverse"
2931
- },
2932
- "o": {
2933
- "kind": "var",
2934
- "value": "adverse"
2935
- }
2936
- },
2937
- {
2938
- "s": {
2939
- "kind": "list",
2940
- "items": [
2941
- {
2942
- "kind": "var",
2943
- "value": "posts"
2944
- },
2945
- {
2946
- "kind": "var",
2947
- "value": "succ"
2948
- }
2949
- ]
2950
- },
2951
- "p": {
2952
- "kind": "iri",
2953
- "value": ":zip"
2954
- },
2955
- "o": {
2956
- "kind": "var",
2957
- "value": "pairs"
2958
- }
2959
- },
2960
- {
2961
- "s": {
2962
- "kind": "list",
2963
- "items": [
2964
- {
2965
- "kind": "var",
2966
- "value": "pairs"
2967
- },
2968
- {
2969
- "kind": "iri",
2970
- "value": ":mul"
2971
- }
2972
- ]
2973
- },
2974
- "p": {
2975
- "kind": "iri",
2976
- "value": "list:map"
2977
- },
2978
- "o": {
2979
- "kind": "var",
2980
- "value": "terms"
2981
- }
2982
- },
2983
- {
2984
- "s": {
2985
- "kind": "var",
2986
- "value": "terms"
2987
- },
2988
- "p": {
2989
- "kind": "iri",
2990
- "value": "math:sum"
2991
- },
2992
- "o": {
2993
- "kind": "var",
2994
- "value": "expectedSuccess"
2995
- }
2996
- },
2997
- {
2998
- "s": {
2999
- "kind": "iri",
3000
- "value": ":Model"
3001
- },
3002
- "p": {
3003
- "kind": "iri",
3004
- "value": ":benefitWeight"
3005
- },
3006
- "o": {
3007
- "kind": "var",
3008
- "value": "bw"
3009
- }
3010
- },
3011
- {
3012
- "s": {
3013
- "kind": "iri",
3014
- "value": ":Model"
3015
- },
3016
- "p": {
3017
- "kind": "iri",
3018
- "value": ":harmWeight"
3019
- },
3020
- "o": {
3021
- "kind": "var",
3022
- "value": "hw"
3023
- }
3024
- },
3025
- {
3026
- "s": {
3027
- "kind": "list",
3028
- "items": [
3029
- {
3030
- "kind": "var",
3031
- "value": "bw"
3032
- },
3033
- {
3034
- "kind": "var",
3035
- "value": "expectedSuccess"
3036
- }
3037
- ]
3038
- },
3039
- "p": {
3040
- "kind": "iri",
3041
- "value": "math:product"
3042
- },
3043
- "o": {
3044
- "kind": "var",
3045
- "value": "benefit"
3046
- }
3047
- },
3048
- {
3049
- "s": {
3050
- "kind": "list",
3051
- "items": [
3052
- {
3053
- "kind": "var",
3054
- "value": "hw"
3055
- },
3056
- {
3057
- "kind": "var",
3058
- "value": "adverse"
3059
- }
3060
- ]
3061
- },
3062
- "p": {
3063
- "kind": "iri",
3064
- "value": "math:product"
3065
- },
3066
- "o": {
3067
- "kind": "var",
3068
- "value": "harmCost"
3069
- }
3070
- },
3071
- {
3072
- "s": {
3073
- "kind": "list",
3074
- "items": [
3075
- {
3076
- "kind": "var",
3077
- "value": "benefit"
3078
- },
3079
- {
3080
- "kind": "var",
3081
- "value": "harmCost"
3082
- }
3083
- ]
3084
- },
3085
- "p": {
3086
- "kind": "iri",
3087
- "value": "math:difference"
3088
- },
3089
- "o": {
3090
- "kind": "var",
3091
- "value": "utility"
3092
- }
3093
- }
3094
- ],
3095
- "head": [
3096
- {
3097
- "s": {
3098
- "kind": "var",
3099
- "value": "t"
3100
- },
3101
- "p": {
3102
- "kind": "iri",
3103
- "value": ":expectedSuccess"
3104
- },
3105
- "o": {
3106
- "kind": "var",
3107
- "value": "expectedSuccess"
3108
- }
3109
- },
3110
- {
3111
- "s": {
3112
- "kind": "var",
3113
- "value": "t"
3114
- },
3115
- "p": {
3116
- "kind": "iri",
3117
- "value": ":expectedAdverse"
3118
- },
3119
- "o": {
3120
- "kind": "var",
3121
- "value": "adverse"
3122
- }
3123
- },
3124
- {
3125
- "s": {
3126
- "kind": "var",
3127
- "value": "t"
3128
- },
3129
- "p": {
3130
- "kind": "iri",
3131
- "value": ":utility"
3132
- },
3133
- "o": {
3134
- "kind": "var",
3135
- "value": "utility"
3136
- }
3137
- }
3138
- ],
3139
- "bodyComment": [
3140
- ":Case :posteriors ?posts",
3141
- "?t rdf:type :Therapy",
3142
- "?t :successByDisease ?succ",
3143
- "?t :adverse ?adverse",
3144
- "(?posts ?succ) :zip ?pairs",
3145
- "(?pairs :mul) list:map ?terms",
3146
- "?terms math:sum ?expectedSuccess",
3147
- ":Model :benefitWeight ?bw",
3148
- ":Model :harmWeight ?hw",
3149
- "(?bw ?expectedSuccess) math:product ?benefit",
3150
- "(?hw ?adverse) math:product ?harmCost",
3151
- "(?benefit ?harmCost) math:difference ?utility"
3152
- ],
3153
- "headComment": [
3154
- "?t :expectedSuccess ?expectedSuccess",
3155
- "?t :expectedAdverse ?adverse",
3156
- "?t :utility ?utility"
3157
- ]
3158
- },
3159
- {
3160
- "kind": "backward",
3161
- "id": 23,
3162
- "body": [
3163
- {
3164
- "s": {
3165
- "kind": "var",
3166
- "value": "t1"
3167
- },
3168
- "p": {
3169
- "kind": "iri",
3170
- "value": ":utility"
3171
- },
3172
- "o": {
3173
- "kind": "var",
3174
- "value": "u1"
3175
- }
3176
- },
3177
- {
3178
- "s": {
3179
- "kind": "var",
3180
- "value": "t2"
3181
- },
3182
- "p": {
3183
- "kind": "iri",
3184
- "value": ":utility"
3185
- },
3186
- "o": {
3187
- "kind": "var",
3188
- "value": "u2"
3189
- }
3190
- },
3191
- {
3192
- "s": {
3193
- "kind": "var",
3194
- "value": "u1"
3195
- },
3196
- "p": {
3197
- "kind": "iri",
3198
- "value": "math:notLessThan"
3199
- },
3200
- "o": {
3201
- "kind": "var",
3202
- "value": "u2"
3203
- }
3204
- }
3205
- ],
3206
- "head": [
3207
- {
3208
- "s": {
3209
- "kind": "list",
3210
- "items": [
3211
- {
3212
- "kind": "var",
3213
- "value": "t1"
3214
- },
3215
- {
3216
- "kind": "var",
3217
- "value": "t2"
3218
- }
3219
- ]
3220
- },
3221
- "p": {
3222
- "kind": "iri",
3223
- "value": ":betterOf"
3224
- },
3225
- "o": {
3226
- "kind": "var",
3227
- "value": "t1"
3228
- }
3229
- }
3230
- ],
3231
- "bodyComment": [
3232
- "?t1 :utility ?u1",
3233
- "?t2 :utility ?u2",
3234
- "?u1 math:notLessThan ?u2"
3235
- ],
3236
- "headComment": [
3237
- "(?t1 ?t2) :betterOf ?t1"
3238
- ]
3239
- },
3240
- {
3241
- "kind": "backward",
3242
- "id": 24,
3243
- "body": [
3244
- {
3245
- "s": {
3246
- "kind": "var",
3247
- "value": "t1"
3248
- },
3249
- "p": {
3250
- "kind": "iri",
3251
- "value": ":utility"
3252
- },
3253
- "o": {
3254
- "kind": "var",
3255
- "value": "u1"
3256
- }
3257
- },
3258
- {
3259
- "s": {
3260
- "kind": "var",
3261
- "value": "t2"
3262
- },
3263
- "p": {
3264
- "kind": "iri",
3265
- "value": ":utility"
3266
- },
3267
- "o": {
3268
- "kind": "var",
3269
- "value": "u2"
3270
- }
3271
- },
3272
- {
3273
- "s": {
3274
- "kind": "var",
3275
- "value": "u1"
3276
- },
3277
- "p": {
3278
- "kind": "iri",
3279
- "value": "math:lessThan"
3280
- },
3281
- "o": {
3282
- "kind": "var",
3283
- "value": "u2"
3284
- }
3285
- }
3286
- ],
3287
- "head": [
3288
- {
3289
- "s": {
3290
- "kind": "list",
3291
- "items": [
3292
- {
3293
- "kind": "var",
3294
- "value": "t1"
3295
- },
3296
- {
3297
- "kind": "var",
3298
- "value": "t2"
3299
- }
3300
- ]
3301
- },
3302
- "p": {
3303
- "kind": "iri",
3304
- "value": ":betterOf"
3305
- },
3306
- "o": {
3307
- "kind": "var",
3308
- "value": "t2"
3309
- }
3310
- }
3311
- ],
3312
- "bodyComment": [
3313
- "?t1 :utility ?u1",
3314
- "?t2 :utility ?u2",
3315
- "?u1 math:lessThan ?u2"
3316
- ],
3317
- "headComment": [
3318
- "(?t1 ?t2) :betterOf ?t2"
3319
- ]
3320
- },
3321
- {
3322
- "kind": "backward",
3323
- "id": 25,
3324
- "body": [
3325
- {
3326
- "s": {
3327
- "kind": "var",
3328
- "value": "ts"
3329
- },
3330
- "p": {
3331
- "kind": "iri",
3332
- "value": "list:firstRest"
3333
- },
3334
- "o": {
3335
- "kind": "list",
3336
- "items": [
3337
- {
3338
- "kind": "var",
3339
- "value": "t"
3340
- },
3341
- {
3342
- "kind": "list",
3343
- "items": []
3344
- }
3345
- ]
3346
- }
3347
- }
3348
- ],
3349
- "head": [
3350
- {
3351
- "s": {
3352
- "kind": "list",
3353
- "items": [
3354
- {
3355
- "kind": "var",
3356
- "value": "ts"
3357
- }
3358
- ]
3359
- },
3360
- "p": {
3361
- "kind": "iri",
3362
- "value": ":bestTherapy"
3363
- },
3364
- "o": {
3365
- "kind": "var",
3366
- "value": "t"
3367
- }
3368
- }
3369
- ],
3370
- "bodyComment": [
3371
- "?ts list:firstRest (?t ())"
3372
- ],
3373
- "headComment": [
3374
- "(?ts) :bestTherapy ?t"
3375
- ]
3376
- },
3377
- {
3378
- "kind": "backward",
3379
- "id": 26,
3380
- "body": [
3381
- {
3382
- "s": {
3383
- "kind": "var",
3384
- "value": "ts"
3385
- },
3386
- "p": {
3387
- "kind": "iri",
3388
- "value": "list:firstRest"
3389
- },
3390
- "o": {
3391
- "kind": "list",
3392
- "items": [
3393
- {
3394
- "kind": "var",
3395
- "value": "head"
3396
- },
3397
- {
3398
- "kind": "var",
3399
- "value": "rest"
3400
- }
3401
- ]
3402
- }
3403
- },
3404
- {
3405
- "s": {
3406
- "kind": "var",
3407
- "value": "rest"
3408
- },
3409
- "p": {
3410
- "kind": "iri",
3411
- "value": "list:firstRest"
3412
- },
3413
- "o": {
3414
- "kind": "list",
3415
- "items": [
3416
- {
3417
- "kind": "var",
3418
- "value": "_"
3419
- },
3420
- {
3421
- "kind": "var",
3422
- "value": "__"
3423
- }
3424
- ]
3425
- }
3426
- },
3427
- {
3428
- "s": {
3429
- "kind": "list",
3430
- "items": [
3431
- {
3432
- "kind": "var",
3433
- "value": "rest"
3434
- }
3435
- ]
3436
- },
3437
- "p": {
3438
- "kind": "iri",
3439
- "value": ":bestTherapy"
3440
- },
3441
- "o": {
3442
- "kind": "var",
3443
- "value": "bestRest"
3444
- }
3445
- },
3446
- {
3447
- "s": {
3448
- "kind": "list",
3449
- "items": [
3450
- {
3451
- "kind": "var",
3452
- "value": "head"
3453
- },
3454
- {
3455
- "kind": "var",
3456
- "value": "bestRest"
3457
- }
3458
- ]
3459
- },
3460
- "p": {
3461
- "kind": "iri",
3462
- "value": ":betterOf"
3463
- },
3464
- "o": {
3465
- "kind": "var",
3466
- "value": "best"
3467
- }
3468
- }
3469
- ],
3470
- "head": [
3471
- {
3472
- "s": {
3473
- "kind": "list",
3474
- "items": [
3475
- {
3476
- "kind": "var",
3477
- "value": "ts"
3478
- }
3479
- ]
3480
- },
3481
- "p": {
3482
- "kind": "iri",
3483
- "value": ":bestTherapy"
3484
- },
3485
- "o": {
3486
- "kind": "var",
3487
- "value": "best"
3488
- }
3489
- }
3490
- ],
3491
- "bodyComment": [
3492
- "?ts list:firstRest (?head ?rest)",
3493
- "?rest list:firstRest (?_ ?__)",
3494
- "(?rest) :bestTherapy ?bestRest",
3495
- "(?head ?bestRest) :betterOf ?best"
3496
- ],
3497
- "headComment": [
3498
- "(?ts) :bestTherapy ?best"
3499
- ]
3500
- },
3501
- {
3502
- "kind": "rule",
3503
- "id": 27,
3504
- "body": [
3505
- {
3506
- "s": {
3507
- "kind": "iri",
3508
- "value": ":Case"
3509
- },
3510
- "p": {
3511
- "kind": "iri",
3512
- "value": ":therapies"
3513
- },
3514
- "o": {
3515
- "kind": "var",
3516
- "value": "ts"
3517
- }
3518
- },
3519
- {
3520
- "s": {
3521
- "kind": "list",
3522
- "items": [
3523
- {
3524
- "kind": "var",
3525
- "value": "ts"
3526
- }
3527
- ]
3528
- },
3529
- "p": {
3530
- "kind": "iri",
3531
- "value": ":bestTherapy"
3532
- },
3533
- "o": {
3534
- "kind": "var",
3535
- "value": "best"
3536
- }
3537
- }
3538
- ],
3539
- "head": [
3540
- {
3541
- "s": {
3542
- "kind": "iri",
3543
- "value": ":Case"
3544
- },
3545
- "p": {
3546
- "kind": "iri",
3547
- "value": ":recommendedTherapy"
3548
- },
3549
- "o": {
3550
- "kind": "var",
3551
- "value": "best"
3552
- }
3553
- }
3554
- ],
3555
- "bodyComment": [
3556
- ":Case :therapies ?ts",
3557
- "(?ts) :bestTherapy ?best"
3558
- ],
3559
- "headComment": [
3560
- ":Case :recommendedTherapy ?best"
3561
- ]
3562
- },
3563
- {
3564
- "kind": "rule",
3565
- "id": 28,
3566
- "body": [
3567
- {
3568
- "s": {
3569
- "kind": "iri",
3570
- "value": ":Case"
3571
- },
3572
- "p": {
3573
- "kind": "iri",
3574
- "value": ":recommendedTherapy"
3575
- },
3576
- "o": {
3577
- "kind": "var",
3578
- "value": "best"
3579
- }
3580
- },
3581
- {
3582
- "s": {
3583
- "kind": "var",
3584
- "value": "best"
3585
- },
3586
- "p": {
3587
- "kind": "iri",
3588
- "value": ":label"
3589
- },
3590
- "o": {
3591
- "kind": "var",
3592
- "value": "bestLabel"
3593
- }
3594
- },
3595
- {
3596
- "s": {
3597
- "kind": "var",
3598
- "value": "best"
3599
- },
3600
- "p": {
3601
- "kind": "iri",
3602
- "value": ":expectedSuccess"
3603
- },
3604
- "o": {
3605
- "kind": "var",
3606
- "value": "bestSuccess"
3607
- }
3608
- },
3609
- {
3610
- "s": {
3611
- "kind": "var",
3612
- "value": "best"
3613
- },
3614
- "p": {
3615
- "kind": "iri",
3616
- "value": ":expectedAdverse"
3617
- },
3618
- "o": {
3619
- "kind": "var",
3620
- "value": "bestAdverse"
3621
- }
3622
- },
3623
- {
3624
- "s": {
3625
- "kind": "var",
3626
- "value": "best"
3627
- },
3628
- "p": {
3629
- "kind": "iri",
3630
- "value": ":utility"
3631
- },
3632
- "o": {
3633
- "kind": "var",
3634
- "value": "bestUtility"
3635
- }
3636
- },
3637
- {
3638
- "s": {
3639
- "kind": "iri",
3640
- "value": ":Paxlovid"
3641
- },
3642
- "p": {
3643
- "kind": "iri",
3644
- "value": ":utility"
3645
- },
3646
- "o": {
3647
- "kind": "var",
3648
- "value": "paxU"
3649
- }
3650
- },
3651
- {
3652
- "s": {
3653
- "kind": "iri",
3654
- "value": ":Paxlovid"
3655
- },
3656
- "p": {
3657
- "kind": "iri",
3658
- "value": ":expectedSuccess"
3659
- },
3660
- "o": {
3661
- "kind": "var",
3662
- "value": "paxS"
3663
- }
3664
- },
3665
- {
3666
- "s": {
3667
- "kind": "iri",
3668
- "value": ":Paxlovid"
3669
- },
3670
- "p": {
3671
- "kind": "iri",
3672
- "value": ":expectedAdverse"
3673
- },
3674
- "o": {
3675
- "kind": "var",
3676
- "value": "paxA"
3677
- }
3678
- },
3679
- {
3680
- "s": {
3681
- "kind": "iri",
3682
- "value": ":Oseltamivir"
3683
- },
3684
- "p": {
3685
- "kind": "iri",
3686
- "value": ":utility"
3687
- },
3688
- "o": {
3689
- "kind": "var",
3690
- "value": "oseU"
3691
- }
3692
- },
3693
- {
3694
- "s": {
3695
- "kind": "iri",
3696
- "value": ":Oseltamivir"
3697
- },
3698
- "p": {
3699
- "kind": "iri",
3700
- "value": ":expectedSuccess"
3701
- },
3702
- "o": {
3703
- "kind": "var",
3704
- "value": "oseS"
3705
- }
3706
- },
3707
- {
3708
- "s": {
3709
- "kind": "iri",
3710
- "value": ":Oseltamivir"
3711
- },
3712
- "p": {
3713
- "kind": "iri",
3714
- "value": ":expectedAdverse"
3715
- },
3716
- "o": {
3717
- "kind": "var",
3718
- "value": "oseA"
3719
- }
3720
- },
3721
- {
3722
- "s": {
3723
- "kind": "iri",
3724
- "value": ":SupportiveCare"
3725
- },
3726
- "p": {
3727
- "kind": "iri",
3728
- "value": ":utility"
3729
- },
3730
- "o": {
3731
- "kind": "var",
3732
- "value": "supU"
3733
- }
3734
- },
3735
- {
3736
- "s": {
3737
- "kind": "iri",
3738
- "value": ":SupportiveCare"
3739
- },
3740
- "p": {
3741
- "kind": "iri",
3742
- "value": ":expectedSuccess"
3743
- },
3744
- "o": {
3745
- "kind": "var",
3746
- "value": "supS"
3747
- }
3748
- },
3749
- {
3750
- "s": {
3751
- "kind": "iri",
3752
- "value": ":SupportiveCare"
3753
- },
3754
- "p": {
3755
- "kind": "iri",
3756
- "value": ":expectedAdverse"
3757
- },
3758
- "o": {
3759
- "kind": "var",
3760
- "value": "supA"
3761
- }
3762
- },
3763
- {
3764
- "s": {
3765
- "kind": "iri",
3766
- "value": ":Antibiotic"
3767
- },
3768
- "p": {
3769
- "kind": "iri",
3770
- "value": ":utility"
3771
- },
3772
- "o": {
3773
- "kind": "var",
3774
- "value": "antibU"
3775
- }
3776
- },
3777
- {
3778
- "s": {
3779
- "kind": "iri",
3780
- "value": ":Antibiotic"
3781
- },
3782
- "p": {
3783
- "kind": "iri",
3784
- "value": ":expectedSuccess"
3785
- },
3786
- "o": {
3787
- "kind": "var",
3788
- "value": "antibS"
3789
- }
3790
- },
3791
- {
3792
- "s": {
3793
- "kind": "iri",
3794
- "value": ":Antibiotic"
3795
- },
3796
- "p": {
3797
- "kind": "iri",
3798
- "value": ":expectedAdverse"
3799
- },
3800
- "o": {
3801
- "kind": "var",
3802
- "value": "antibA"
3803
- }
3804
- },
3805
- {
3806
- "s": {
3807
- "kind": "iri",
3808
- "value": ":Antihistamine"
3809
- },
3810
- "p": {
3811
- "kind": "iri",
3812
- "value": ":utility"
3813
- },
3814
- "o": {
3815
- "kind": "var",
3816
- "value": "antiU"
3817
- }
3818
- },
3819
- {
3820
- "s": {
3821
- "kind": "iri",
3822
- "value": ":Antihistamine"
3823
- },
3824
- "p": {
3825
- "kind": "iri",
3826
- "value": ":expectedSuccess"
3827
- },
3828
- "o": {
3829
- "kind": "var",
3830
- "value": "antiS"
3831
- }
3832
- },
3833
- {
3834
- "s": {
3835
- "kind": "iri",
3836
- "value": ":Antihistamine"
3837
- },
3838
- "p": {
3839
- "kind": "iri",
3840
- "value": ":expectedAdverse"
3841
- },
3842
- "o": {
3843
- "kind": "var",
3844
- "value": "antiA"
3845
- }
3846
- },
3847
- {
3848
- "s": {
3849
- "kind": "list",
3850
- "items": [
3851
- {
3852
- "kind": "lit",
3853
- "value": "=== Answer ===\nRecommended therapy: %s (utility = %.6f).\nexpected success : %.6f\nadverse probability : %.6f\n\nTherapy utilities:\n Paxlovid utility = %.6f success = %.6f adverse = %.6f\n Oseltamivir utility = %.6f success = %.6f adverse = %.6f\n Supportive care utility = %.6f success = %.6f adverse = %.6f\n Antibiotic utility = %.6f success = %.6f adverse = %.6f\n Antihistamine utility = %.6f success = %.6f adverse = %.6f\n\n=== Explanation ===\nThe N3 source first computes disease posteriors from the symptom evidence. It then combines those posterior probabilities with therapy-specific success probabilities, subtracting the weighted adverse-effect penalty from the weighted expected benefit."
3854
- },
3855
- {
3856
- "kind": "var",
3857
- "value": "bestLabel"
3858
- },
3859
- {
3860
- "kind": "var",
3861
- "value": "bestUtility"
3862
- },
3863
- {
3864
- "kind": "var",
3865
- "value": "bestSuccess"
3866
- },
3867
- {
3868
- "kind": "var",
3869
- "value": "bestAdverse"
3870
- },
3871
- {
3872
- "kind": "var",
3873
- "value": "paxU"
3874
- },
3875
- {
3876
- "kind": "var",
3877
- "value": "paxS"
3878
- },
3879
- {
3880
- "kind": "var",
3881
- "value": "paxA"
3882
- },
3883
- {
3884
- "kind": "var",
3885
- "value": "oseU"
3886
- },
3887
- {
3888
- "kind": "var",
3889
- "value": "oseS"
3890
- },
3891
- {
3892
- "kind": "var",
3893
- "value": "oseA"
3894
- },
3895
- {
3896
- "kind": "var",
3897
- "value": "supU"
3898
- },
3899
- {
3900
- "kind": "var",
3901
- "value": "supS"
3902
- },
3903
- {
3904
- "kind": "var",
3905
- "value": "supA"
3906
- },
3907
- {
3908
- "kind": "var",
3909
- "value": "antibU"
3910
- },
3911
- {
3912
- "kind": "var",
3913
- "value": "antibS"
3914
- },
3915
- {
3916
- "kind": "var",
3917
- "value": "antibA"
3918
- },
3919
- {
3920
- "kind": "var",
3921
- "value": "antiU"
3922
- },
3923
- {
3924
- "kind": "var",
3925
- "value": "antiS"
3926
- },
3927
- {
3928
- "kind": "var",
3929
- "value": "antiA"
3930
- }
3931
- ]
3932
- },
3933
- "p": {
3934
- "kind": "iri",
3935
- "value": "string:format"
3936
- },
3937
- "o": {
3938
- "kind": "var",
3939
- "value": "Block"
3940
- }
3941
- }
3942
- ],
3943
- "head": [
3944
- {
3945
- "s": {
3946
- "kind": "iri",
3947
- "value": ":bayesTherapy"
3948
- },
3949
- "p": {
3950
- "kind": "iri",
3951
- "value": "log:outputString"
3952
- },
3953
- "o": {
3954
- "kind": "var",
3955
- "value": "Block"
3956
- }
3957
- },
3958
- {
3959
- "s": {
3960
- "kind": "iri",
3961
- "value": ":bayesTherapy"
3962
- },
3963
- "p": {
3964
- "kind": "iri",
3965
- "value": ":recommends"
3966
- },
3967
- "o": {
3968
- "kind": "var",
3969
- "value": "best"
3970
- }
3971
- }
3972
- ],
3973
- "bodyComment": [
3974
- ":Case :recommendedTherapy ?best",
3975
- "?best :label ?bestLabel",
3976
- "?best :expectedSuccess ?bestSuccess",
3977
- "?best :expectedAdverse ?bestAdverse",
3978
- "?best :utility ?bestUtility",
3979
- ":Paxlovid :utility ?paxU",
3980
- ":Paxlovid :expectedSuccess ?paxS",
3981
- ":Paxlovid :expectedAdverse ?paxA",
3982
- ":Oseltamivir :utility ?oseU",
3983
- ":Oseltamivir :expectedSuccess ?oseS",
3984
- ":Oseltamivir :expectedAdverse ?oseA",
3985
- ":SupportiveCare :utility ?supU",
3986
- ":SupportiveCare :expectedSuccess ?supS",
3987
- ":SupportiveCare :expectedAdverse ?supA",
3988
- ":Antibiotic :utility ?antibU",
3989
- ":Antibiotic :expectedSuccess ?antibS",
3990
- ":Antibiotic :expectedAdverse ?antibA",
3991
- ":Antihistamine :utility ?antiU",
3992
- ":Antihistamine :expectedSuccess ?antiS",
3993
- ":Antihistamine :expectedAdverse ?antiA",
3994
- "(\"=== Answer ===\\nRecommended therapy: %s (utility = %.6f).\\nexpected success : %.6f\\nadverse probability : %.6f\\n\\nTherapy utilities:\\n Paxlovid utility = %.6f success = %.6f adverse = %.6f\\n Oseltamivir utility = %.6f success = %.6f adverse = %.6f\\n Supportive care utility = %.6f success = %.6f adverse = %.6f\\n Antibiotic utility = %.6f success = %.6f adverse = %.6f\\n Antihistamine utility = %.6f success = %.6f adverse = %.6f\\n\\n=== Explanation ===\\nThe N3 source first computes disease posteriors from the symptom evidence. It then combines those posterior probabilities with therapy-specific success probabilities, subtracting the weighted adverse-effect penalty from the weighted expected benefit.\" ?bestLabel ?bestUtility ?bestSuccess ?bestAdverse ?paxU ?paxS ?paxA ?oseU ?oseS ?oseA ?supU ?supS ?supA ?antibU ?antibS ?antibA ?antiU ?antiS ?antiA) string:format ?Block"
3995
- ],
3996
- "headComment": [
3997
- ":bayesTherapy log:outputString ?Block",
3998
- ":bayesTherapy :recommends ?best"
3999
- ]
4000
- }
4001
- ];
4002
- const QUERIES = [
4003
- {
4004
- "id": 1,
4005
- "premise": [
4006
- {
4007
- "s": {
4008
- "kind": "iri",
4009
- "value": ":bayesTherapy"
4010
- },
4011
- "p": {
4012
- "kind": "iri",
4013
- "value": ":recommends"
4014
- },
4015
- "o": {
4016
- "kind": "var",
4017
- "value": "Therapy"
4018
- }
4019
- }
4020
- ],
4021
- "conclusion": [
4022
- {
4023
- "s": {
4024
- "kind": "iri",
4025
- "value": ":bayesTherapy"
4026
- },
4027
- "p": {
4028
- "kind": "iri",
4029
- "value": ":recommends"
4030
- },
4031
- "o": {
4032
- "kind": "var",
4033
- "value": "Therapy"
4034
- }
4035
- }
4036
- ],
4037
- "premiseComment": [
4038
- ":bayesTherapy :recommends ?Therapy"
4039
- ],
4040
- "conclusionComment": [
4041
- ":bayesTherapy :recommends ?Therapy"
4042
- ]
4043
- }
4044
- ];
4045
- const DOC_MARKDOWN = "# Bayes Therapy\n\nGenerated by `see.js` from a Notation3 source file.\n\nExtends the Bayesian diagnosis model with a therapy utility layer. Adapted\nfrom Eyeling's bayes-therapy.n3. Values are illustrative only and are not\nmedical advice.\n\n## Compilation summary\n\n- Example name: `bayes_therapy`\n- Input facts emitted: 104\n- Forward rules compiled: 5\n- Backward predicate rules compiled: 15\n- Fuses compiled: 8\n- Predicate count: 45\n\n## Built-ins used\n\n- `list:firstRest`\n- `list:iterate`\n- `list:map`\n- `list:memberAt`\n- `log:outputString`\n- `math:difference`\n- `math:greaterThan`\n- `math:lessThan`\n- `math:notLessThan`\n- `math:product`\n- `math:quotient`\n- `math:sum`\n- `string:format`\n\n## Runtime model\n\nThe generated `examples/bayes_therapy.js` is a specialized JavaScript derivation program. For ordinary sources, `see.js` emits the source facts as `examples/input/bayes_therapy.trig`. For rules-only sources, generation can reuse an existing external evidence file such as `examples/input/bayes-therapy.trig` or `examples/input/bayes_therapy.trig`. The runner reads that TriG evidence directly and performs a local fixpoint derivation; it does not parse the program source or call an external reasoner.\n\n## Output model\n\nRunning `node examples/bayes_therapy.js` produces a SEE-style Markdown report with an **Entailment** section, an **Explanation** section, and a **Formal TriG Output** section containing the selected derived/query facts.\n";
4046
- function seeMetadata(data) { return (data && data.__see) || {}; }
4047
- function trustedDerivation(data) { const meta = seeMetadata(data); const facts = data && Array.isArray(data.facts) ? data.facts : []; const expectedFacts = EXPECTED_INPUT_FACTS || Number(meta.InputFacts || 0); if (meta.SourceSHA256 && meta.SourceSHA256 !== "18244b81f37328f7d77c8e88a4749891c3d773ffbf19affecd7f118c6208395d") throw new Error('input evidence does not match the N3 source compiled into this example'); const result = saturate(facts, RULES); const rawOutput = renderRawOutput(result.graph, QUERIES, RULES, facts); fail('Compiled N3 derivation failed', { 'input evidence metadata is present and matches compiled source': meta.SourceSHA256 === "18244b81f37328f7d77c8e88a4749891c3d773ffbf19affecd7f118c6208395d", 'input evidence facts were loaded': expectedFacts > 0 ? facts.length === expectedFacts : facts.length >= 0, 'compiled rules were loaded': RULES.length === 28, 'compiled query directives were loaded': QUERIES.length === 1, 'a derivation fixpoint was reached': result.graph.facts.length >= facts.length, 'query or output facts were produced': rawOutput.length > 0 }); return { ...result, rawOutput, inputFacts: facts }; }
4048
- function snapshotMarkdown(markdown) { return markdown.split(/\n/).map((line) => line ? line + ' \n' : '\n').join(''); }
4049
- function prefixLinesFromTrig(trig) {
4050
- const out = [];
4051
- const seen = new Set();
4052
- for (const rawLine of String(trig || '').split(String.fromCharCode(10))) {
4053
- const trimmed = rawLine.replace(String.fromCharCode(13), '').trim();
4054
- if (!trimmed.toLowerCase().startsWith('@prefix ')) continue;
4055
- if (!seen.has(trimmed)) { seen.add(trimmed); out.push(trimmed); }
4056
- }
4057
- if (!out.some((line) => line.toLowerCase().startsWith('@prefix rdf:'))) out.push('@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .');
4058
- return out;
4059
- }
4060
- function formalOutputFacts(graph, queries, rules, initialFacts) {
4061
- const base = initialKeys(initialFacts);
4062
- const out = [];
4063
- const seen = new Set();
4064
- const add = (fact) => {
4065
- if (!fact) return;
4066
- const key = factKey(fact);
4067
- if (!seen.has(key)) { seen.add(key); out.push(fact); }
4068
- };
4069
- if (queries && queries.length) {
4070
- for (const fact of queryFacts(graph, queries, rules)) add(fact);
4071
- return out;
4072
- }
4073
- for (const fact of derivedFacts(graph, initialFacts)) add(fact);
4074
- if (!out.length) {
4075
- for (const fact of graph.facts) if (fact.o && fact.o.kind === 'formula' && !base.has(factKey(fact))) add(fact);
4076
- }
4077
- return out;
4078
- }
4079
- function termHasTripleTerm(term) {
4080
- if (!term) return false;
4081
- if (term.kind === 'triple') return true;
4082
- if (term.kind === 'list') return term.items.some(termHasTripleTerm);
4083
- if (term.kind === 'formula') return term.atoms.some(atomHasTripleTerm);
4084
- return false;
4085
- }
4086
- function atomHasTripleTerm(atom) { return termHasTripleTerm(atom.s) || termHasTripleTerm(atom.p) || termHasTripleTerm(atom.o); }
4087
- function factsHaveTripleTerms(facts) { return (facts || []).some(atomHasTripleTerm); }
4088
- function trigHasVersion12(trig) { return /^s*(?:@version|VERSION)s+["']1.2["']/mi.test(String(trig || '')); }
4089
- function trigGraphBlock(label, atoms) {
4090
- const lines = [label + ' {'];
4091
- for (const atom of atoms || []) lines.push(' ' + atomToN3(atom) + ' .');
4092
- lines.push('}');
4093
- return lines;
4094
- }
4095
- function formalFactToTrigLines(fact, state) {
4096
- if (fact.o && fact.o.kind === 'formula') {
4097
- if (isIri(fact.p, 'log:nameOf')) return trigGraphBlock(termToN3(fact.s), fact.o.atoms);
4098
- state.formulaCounter += 1;
4099
- state.needOutPrefix = true;
4100
- const label = 'out:formula' + state.formulaCounter;
4101
- return [termToN3(fact.s) + ' ' + termToN3(fact.p) + ' ' + label + ' .', '', ...trigGraphBlock(label, fact.o.atoms)];
4102
- }
4103
- return [codeFact(fact)];
4104
- }
4105
- function trigMetadataBlock(trig) {
4106
- const lines = String(trig || '').split(String.fromCharCode(10));
4107
- const out = [];
4108
- let depth = 0;
4109
- let active = false;
4110
- for (const line of lines) {
4111
- const trimmed = line.trim();
4112
- if (!active && !trimmed.startsWith('in:metadata')) continue;
4113
- active = true;
4114
- out.push(line.replace(String.fromCharCode(13), ''));
4115
- depth += (line.match(/{/g) || []).length;
4116
- depth -= (line.match(/}/g) || []).length;
4117
- if (active && depth <= 0) break;
4118
- }
4119
- return out.length ? out.join(String.fromCharCode(10)).trimEnd() : '';
4120
- }
4121
- function formalOutputToTrig(facts, trig) {
4122
- const state = { formulaCounter: 0, needOutPrefix: false };
4123
- const body = [];
4124
- for (const fact of facts || []) {
4125
- body.push(...formalFactToTrigLines(fact, state));
4126
- }
4127
- const metadata = trigMetadataBlock(trig);
4128
- if (metadata) {
4129
- if (body.length) body.push('');
4130
- body.push(metadata);
4131
- }
4132
- if (!body.length) return '';
4133
- const prefixes = prefixLinesFromTrig(trig);
4134
- if (state.needOutPrefix && !prefixes.some((line) => line.toLowerCase().startsWith('@prefix out:'))) prefixes.push('@prefix out: <https://example.org/see/output#> .');
4135
- const nl = String.fromCharCode(10);
4136
- const version = factsHaveTripleTerms(facts) ? 'VERSION "1.2"' + nl + nl : '';
4137
- return version + prefixes.join(nl) + nl + nl + body.join(nl);
4138
- }
4139
- function appendFormalTrigOutput(markdown, graph, queries, rules, initialFacts, data) {
4140
- const trig = formalOutputToTrig(formalOutputFacts(graph, queries, rules, initialFacts), data && data.trig);
4141
- if (!trig) return markdown;
4142
- const nl = String.fromCharCode(10);
4143
- const fence = String.fromCharCode(96).repeat(3);
4144
- const fenced = trig.trimEnd().replace(new RegExp(fence, 'g'), '` ` `');
4145
- return markdown.trimEnd() + nl + nl + '## Formal TriG Output' + nl + nl + fence + 'trig' + nl + fenced + nl + fence + nl;
4146
- }
4147
- function outputMarkdown() { const data = loadInput(NAME); const result = trustedDerivation(data); const markdown = renderPresentation(result.graph, QUERIES, RULES, result.inputFacts, TITLE, result.trace); return snapshotMarkdown(appendFormalTrigOutput(markdown, result.graph, QUERIES, RULES, result.inputFacts, data)); }
4148
- function documentationMarkdown() { return DOC_MARKDOWN; }
4149
- function writeArtefacts() { const outputDir = path.join(__dirname, 'output'); const docDir = path.join(__dirname, 'doc'); fs.mkdirSync(outputDir, { recursive: true }); fs.mkdirSync(docDir, { recursive: true }); fs.writeFileSync(path.join(outputDir, NAME + '.md'), outputMarkdown(), 'utf8'); fs.writeFileSync(path.join(docDir, NAME + '.md'), documentationMarkdown(), 'utf8'); }
4150
- function main(argv = process.argv.slice(2)) { if (argv.includes('--write') || argv.includes('--write-files') || argv.includes('--snapshot')) { writeArtefacts(); return; } if (argv.includes('--doc')) { process.stdout.write(documentationMarkdown()); return; } process.stdout.write(outputMarkdown()); }
4151
- if (require.main === module) main();
4152
- module.exports = { trustedDerivation, outputMarkdown, documentationMarkdown, writeArtefacts };