@stevenvo780/st-lang 4.11.0 → 4.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (273) hide show
  1. package/dist/proof-systems/fol-prover-advanced/index.d.ts +7 -0
  2. package/dist/proof-systems/fol-prover-advanced/index.d.ts.map +1 -0
  3. package/dist/proof-systems/fol-prover-advanced/index.js +34 -0
  4. package/dist/proof-systems/fol-prover-advanced/index.js.map +1 -0
  5. package/dist/proof-systems/fol-prover-advanced/ordering.d.ts +34 -0
  6. package/dist/proof-systems/fol-prover-advanced/ordering.d.ts.map +1 -0
  7. package/dist/proof-systems/fol-prover-advanced/ordering.js +197 -0
  8. package/dist/proof-systems/fol-prover-advanced/ordering.js.map +1 -0
  9. package/dist/proof-systems/fol-prover-advanced/prover.d.ts +22 -0
  10. package/dist/proof-systems/fol-prover-advanced/prover.d.ts.map +1 -0
  11. package/dist/proof-systems/fol-prover-advanced/prover.js +219 -0
  12. package/dist/proof-systems/fol-prover-advanced/prover.js.map +1 -0
  13. package/dist/proof-systems/fol-prover-advanced/resolve.d.ts +43 -0
  14. package/dist/proof-systems/fol-prover-advanced/resolve.d.ts.map +1 -0
  15. package/dist/proof-systems/fol-prover-advanced/resolve.js +297 -0
  16. package/dist/proof-systems/fol-prover-advanced/resolve.js.map +1 -0
  17. package/dist/proof-systems/fol-prover-advanced/subsumption.d.ts +28 -0
  18. package/dist/proof-systems/fol-prover-advanced/subsumption.d.ts.map +1 -0
  19. package/dist/proof-systems/fol-prover-advanced/subsumption.js +172 -0
  20. package/dist/proof-systems/fol-prover-advanced/subsumption.js.map +1 -0
  21. package/dist/proof-systems/fol-prover-advanced/types.d.ts +68 -0
  22. package/dist/proof-systems/fol-prover-advanced/types.d.ts.map +1 -0
  23. package/dist/proof-systems/fol-prover-advanced/types.js +12 -0
  24. package/dist/proof-systems/fol-prover-advanced/types.js.map +1 -0
  25. package/dist/proof-systems/fol-prover-advanced/unify.d.ts +15 -0
  26. package/dist/proof-systems/fol-prover-advanced/unify.d.ts.map +1 -0
  27. package/dist/proof-systems/fol-prover-advanced/unify.js +144 -0
  28. package/dist/proof-systems/fol-prover-advanced/unify.js.map +1 -0
  29. package/dist/reasoning/combinatorics/basic-counts.d.ts +6 -0
  30. package/dist/reasoning/combinatorics/basic-counts.d.ts.map +1 -0
  31. package/dist/reasoning/combinatorics/basic-counts.js +82 -0
  32. package/dist/reasoning/combinatorics/basic-counts.js.map +1 -0
  33. package/dist/reasoning/combinatorics/bigint-helpers.d.ts +5 -0
  34. package/dist/reasoning/combinatorics/bigint-helpers.d.ts.map +1 -0
  35. package/dist/reasoning/combinatorics/bigint-helpers.js +8 -0
  36. package/dist/reasoning/combinatorics/bigint-helpers.js.map +1 -0
  37. package/dist/reasoning/combinatorics/burnside.d.ts +15 -0
  38. package/dist/reasoning/combinatorics/burnside.d.ts.map +1 -0
  39. package/dist/reasoning/combinatorics/burnside.js +91 -0
  40. package/dist/reasoning/combinatorics/burnside.js.map +1 -0
  41. package/dist/reasoning/combinatorics/generating-functions.d.ts +12 -0
  42. package/dist/reasoning/combinatorics/generating-functions.d.ts.map +1 -0
  43. package/dist/reasoning/combinatorics/generating-functions.js +67 -0
  44. package/dist/reasoning/combinatorics/generating-functions.js.map +1 -0
  45. package/dist/reasoning/combinatorics/generators.d.ts +5 -0
  46. package/dist/reasoning/combinatorics/generators.d.ts.map +1 -0
  47. package/dist/reasoning/combinatorics/generators.js +111 -0
  48. package/dist/reasoning/combinatorics/generators.js.map +1 -0
  49. package/dist/reasoning/combinatorics/inclusion-exclusion.d.ts +8 -0
  50. package/dist/reasoning/combinatorics/inclusion-exclusion.d.ts.map +1 -0
  51. package/dist/reasoning/combinatorics/inclusion-exclusion.js +45 -0
  52. package/dist/reasoning/combinatorics/inclusion-exclusion.js.map +1 -0
  53. package/dist/reasoning/combinatorics/index.d.ts +10 -0
  54. package/dist/reasoning/combinatorics/index.d.ts.map +1 -0
  55. package/dist/reasoning/combinatorics/index.js +44 -0
  56. package/dist/reasoning/combinatorics/index.js.map +1 -0
  57. package/dist/reasoning/combinatorics/partitions.d.ts +4 -0
  58. package/dist/reasoning/combinatorics/partitions.d.ts.map +1 -0
  59. package/dist/reasoning/combinatorics/partitions.js +90 -0
  60. package/dist/reasoning/combinatorics/partitions.js.map +1 -0
  61. package/dist/reasoning/combinatorics/permutations.d.ts +6 -0
  62. package/dist/reasoning/combinatorics/permutations.d.ts.map +1 -0
  63. package/dist/reasoning/combinatorics/permutations.js +124 -0
  64. package/dist/reasoning/combinatorics/permutations.js.map +1 -0
  65. package/dist/reasoning/combinatorics/set-partitions.d.ts +3 -0
  66. package/dist/reasoning/combinatorics/set-partitions.d.ts.map +1 -0
  67. package/dist/reasoning/combinatorics/set-partitions.js +46 -0
  68. package/dist/reasoning/combinatorics/set-partitions.js.map +1 -0
  69. package/dist/reasoning/combinatorics/special-numbers.d.ts +7 -0
  70. package/dist/reasoning/combinatorics/special-numbers.d.ts.map +1 -0
  71. package/dist/reasoning/combinatorics/special-numbers.js +128 -0
  72. package/dist/reasoning/combinatorics/special-numbers.js.map +1 -0
  73. package/dist/reasoning/constructive-analysis/cauchy.d.ts +51 -0
  74. package/dist/reasoning/constructive-analysis/cauchy.d.ts.map +1 -0
  75. package/dist/reasoning/constructive-analysis/cauchy.js +77 -0
  76. package/dist/reasoning/constructive-analysis/cauchy.js.map +1 -0
  77. package/dist/reasoning/constructive-analysis/compact.d.ts +35 -0
  78. package/dist/reasoning/constructive-analysis/compact.d.ts.map +1 -0
  79. package/dist/reasoning/constructive-analysis/compact.js +61 -0
  80. package/dist/reasoning/constructive-analysis/compact.js.map +1 -0
  81. package/dist/reasoning/constructive-analysis/continuity.d.ts +62 -0
  82. package/dist/reasoning/constructive-analysis/continuity.d.ts.map +1 -0
  83. package/dist/reasoning/constructive-analysis/continuity.js +112 -0
  84. package/dist/reasoning/constructive-analysis/continuity.js.map +1 -0
  85. package/dist/reasoning/constructive-analysis/index.d.ts +24 -0
  86. package/dist/reasoning/constructive-analysis/index.d.ts.map +1 -0
  87. package/dist/reasoning/constructive-analysis/index.js +36 -0
  88. package/dist/reasoning/constructive-analysis/index.js.map +1 -0
  89. package/dist/reasoning/constructive-analysis/integral.d.ts +31 -0
  90. package/dist/reasoning/constructive-analysis/integral.d.ts.map +1 -0
  91. package/dist/reasoning/constructive-analysis/integral.js +59 -0
  92. package/dist/reasoning/constructive-analysis/integral.js.map +1 -0
  93. package/dist/reasoning/constructive-analysis/ivt.d.ts +41 -0
  94. package/dist/reasoning/constructive-analysis/ivt.d.ts.map +1 -0
  95. package/dist/reasoning/constructive-analysis/ivt.js +115 -0
  96. package/dist/reasoning/constructive-analysis/ivt.js.map +1 -0
  97. package/dist/reasoning/constructive-reals/index.d.ts +23 -0
  98. package/dist/reasoning/constructive-reals/index.d.ts.map +1 -1
  99. package/dist/reasoning/constructive-reals/index.js +52 -1
  100. package/dist/reasoning/constructive-reals/index.js.map +1 -1
  101. package/dist/reasoning/datalog/index.d.ts +131 -0
  102. package/dist/reasoning/datalog/index.d.ts.map +1 -0
  103. package/dist/reasoning/datalog/index.js +706 -0
  104. package/dist/reasoning/datalog/index.js.map +1 -0
  105. package/dist/reasoning/galois-fields/index.d.ts +29 -0
  106. package/dist/reasoning/galois-fields/index.d.ts.map +1 -0
  107. package/dist/reasoning/galois-fields/index.js +522 -0
  108. package/dist/reasoning/galois-fields/index.js.map +1 -0
  109. package/dist/reasoning/lattice/index.d.ts +165 -0
  110. package/dist/reasoning/lattice/index.d.ts.map +1 -0
  111. package/dist/reasoning/lattice/index.js +587 -0
  112. package/dist/reasoning/lattice/index.js.map +1 -0
  113. package/dist/reasoning/linear-algebra/index.d.ts +69 -0
  114. package/dist/reasoning/linear-algebra/index.d.ts.map +1 -0
  115. package/dist/reasoning/linear-algebra/index.js +859 -0
  116. package/dist/reasoning/linear-algebra/index.js.map +1 -0
  117. package/dist/reasoning/polynomial-ring/index.d.ts +30 -0
  118. package/dist/reasoning/polynomial-ring/index.d.ts.map +1 -0
  119. package/dist/reasoning/polynomial-ring/index.js +797 -0
  120. package/dist/reasoning/polynomial-ring/index.js.map +1 -0
  121. package/dist/reasoning/set-theory/hf-functions.d.ts +35 -0
  122. package/dist/reasoning/set-theory/hf-functions.d.ts.map +1 -0
  123. package/dist/reasoning/set-theory/hf-functions.js +147 -0
  124. package/dist/reasoning/set-theory/hf-functions.js.map +1 -0
  125. package/dist/reasoning/set-theory/hf-sets.d.ts +79 -0
  126. package/dist/reasoning/set-theory/hf-sets.d.ts.map +1 -0
  127. package/dist/reasoning/set-theory/hf-sets.js +338 -0
  128. package/dist/reasoning/set-theory/hf-sets.js.map +1 -0
  129. package/dist/reasoning/set-theory/index.d.ts +7 -0
  130. package/dist/reasoning/set-theory/index.d.ts.map +1 -0
  131. package/dist/reasoning/set-theory/index.js +44 -0
  132. package/dist/reasoning/set-theory/index.js.map +1 -0
  133. package/dist/reasoning/set-theory/zfc-axioms.d.ts +59 -0
  134. package/dist/reasoning/set-theory/zfc-axioms.d.ts.map +1 -0
  135. package/dist/reasoning/set-theory/zfc-axioms.js +245 -0
  136. package/dist/reasoning/set-theory/zfc-axioms.js.map +1 -0
  137. package/dist/tests/proof-systems/fol-prover-advanced/prover.test.d.ts +2 -0
  138. package/dist/tests/proof-systems/fol-prover-advanced/prover.test.d.ts.map +1 -0
  139. package/dist/tests/proof-systems/fol-prover-advanced/prover.test.js +253 -0
  140. package/dist/tests/proof-systems/fol-prover-advanced/prover.test.js.map +1 -0
  141. package/dist/tests/reasoning/combinatorics/combinatorics.test.d.ts +2 -0
  142. package/dist/tests/reasoning/combinatorics/combinatorics.test.d.ts.map +1 -0
  143. package/dist/tests/reasoning/combinatorics/combinatorics.test.js +256 -0
  144. package/dist/tests/reasoning/combinatorics/combinatorics.test.js.map +1 -0
  145. package/dist/tests/reasoning/constructive-analysis/constructive-analysis.test.d.ts +2 -0
  146. package/dist/tests/reasoning/constructive-analysis/constructive-analysis.test.d.ts.map +1 -0
  147. package/dist/tests/reasoning/constructive-analysis/constructive-analysis.test.js +174 -0
  148. package/dist/tests/reasoning/constructive-analysis/constructive-analysis.test.js.map +1 -0
  149. package/dist/tests/reasoning/datalog/datalog.test.d.ts +2 -0
  150. package/dist/tests/reasoning/datalog/datalog.test.d.ts.map +1 -0
  151. package/dist/tests/reasoning/datalog/datalog.test.js +333 -0
  152. package/dist/tests/reasoning/datalog/datalog.test.js.map +1 -0
  153. package/dist/tests/reasoning/galois-fields/galois-fields.test.d.ts +2 -0
  154. package/dist/tests/reasoning/galois-fields/galois-fields.test.d.ts.map +1 -0
  155. package/dist/tests/reasoning/galois-fields/galois-fields.test.js +226 -0
  156. package/dist/tests/reasoning/galois-fields/galois-fields.test.js.map +1 -0
  157. package/dist/tests/reasoning/lattice/lattice.test.d.ts +2 -0
  158. package/dist/tests/reasoning/lattice/lattice.test.d.ts.map +1 -0
  159. package/dist/tests/reasoning/lattice/lattice.test.js +238 -0
  160. package/dist/tests/reasoning/lattice/lattice.test.js.map +1 -0
  161. package/dist/tests/reasoning/linear-algebra/linear-algebra.test.d.ts +2 -0
  162. package/dist/tests/reasoning/linear-algebra/linear-algebra.test.d.ts.map +1 -0
  163. package/dist/tests/reasoning/linear-algebra/linear-algebra.test.js +369 -0
  164. package/dist/tests/reasoning/linear-algebra/linear-algebra.test.js.map +1 -0
  165. package/dist/tests/reasoning/polynomial-ring/polynomial-ring.test.d.ts +2 -0
  166. package/dist/tests/reasoning/polynomial-ring/polynomial-ring.test.d.ts.map +1 -0
  167. package/dist/tests/reasoning/polynomial-ring/polynomial-ring.test.js +230 -0
  168. package/dist/tests/reasoning/polynomial-ring/polynomial-ring.test.js.map +1 -0
  169. package/dist/tests/reasoning/set-theory/hf-functions.test.d.ts +2 -0
  170. package/dist/tests/reasoning/set-theory/hf-functions.test.d.ts.map +1 -0
  171. package/dist/tests/reasoning/set-theory/hf-functions.test.js +122 -0
  172. package/dist/tests/reasoning/set-theory/hf-functions.test.js.map +1 -0
  173. package/dist/tests/reasoning/set-theory/hf-sets.test.d.ts +2 -0
  174. package/dist/tests/reasoning/set-theory/hf-sets.test.d.ts.map +1 -0
  175. package/dist/tests/reasoning/set-theory/hf-sets.test.js +177 -0
  176. package/dist/tests/reasoning/set-theory/hf-sets.test.js.map +1 -0
  177. package/dist/tests/reasoning/set-theory/zfc-axioms.test.d.ts +2 -0
  178. package/dist/tests/reasoning/set-theory/zfc-axioms.test.d.ts.map +1 -0
  179. package/dist/tests/reasoning/set-theory/zfc-axioms.test.js +56 -0
  180. package/dist/tests/reasoning/set-theory/zfc-axioms.test.js.map +1 -0
  181. package/dist/tests/tooling/doc-gen/doc-gen.test.d.ts +2 -0
  182. package/dist/tests/tooling/doc-gen/doc-gen.test.d.ts.map +1 -0
  183. package/dist/tests/tooling/doc-gen/doc-gen.test.js +350 -0
  184. package/dist/tests/tooling/doc-gen/doc-gen.test.js.map +1 -0
  185. package/dist/tests/tooling/test-harness/test-harness.test.d.ts +2 -0
  186. package/dist/tests/tooling/test-harness/test-harness.test.d.ts.map +1 -0
  187. package/dist/tests/tooling/test-harness/test-harness.test.js +208 -0
  188. package/dist/tests/tooling/test-harness/test-harness.test.js.map +1 -0
  189. package/dist/tests/type-theory/lambda-cube/lambda-cube.test.d.ts +2 -0
  190. package/dist/tests/type-theory/lambda-cube/lambda-cube.test.d.ts.map +1 -0
  191. package/dist/tests/type-theory/lambda-cube/lambda-cube.test.js +266 -0
  192. package/dist/tests/type-theory/lambda-cube/lambda-cube.test.js.map +1 -0
  193. package/dist/tooling/doc-gen/extract.d.ts +13 -0
  194. package/dist/tooling/doc-gen/extract.d.ts.map +1 -0
  195. package/dist/tooling/doc-gen/extract.js +379 -0
  196. package/dist/tooling/doc-gen/extract.js.map +1 -0
  197. package/dist/tooling/doc-gen/generate.d.ts +9 -0
  198. package/dist/tooling/doc-gen/generate.d.ts.map +1 -0
  199. package/dist/tooling/doc-gen/generate.js +116 -0
  200. package/dist/tooling/doc-gen/generate.js.map +1 -0
  201. package/dist/tooling/doc-gen/index.d.ts +7 -0
  202. package/dist/tooling/doc-gen/index.d.ts.map +1 -0
  203. package/dist/tooling/doc-gen/index.js +39 -0
  204. package/dist/tooling/doc-gen/index.js.map +1 -0
  205. package/dist/tooling/doc-gen/jsdoc.d.ts +31 -0
  206. package/dist/tooling/doc-gen/jsdoc.d.ts.map +1 -0
  207. package/dist/tooling/doc-gen/jsdoc.js +140 -0
  208. package/dist/tooling/doc-gen/jsdoc.js.map +1 -0
  209. package/dist/tooling/doc-gen/render.d.ts +29 -0
  210. package/dist/tooling/doc-gen/render.d.ts.map +1 -0
  211. package/dist/tooling/doc-gen/render.js +206 -0
  212. package/dist/tooling/doc-gen/render.js.map +1 -0
  213. package/dist/tooling/doc-gen/types.d.ts +51 -0
  214. package/dist/tooling/doc-gen/types.d.ts.map +1 -0
  215. package/dist/tooling/doc-gen/types.js +10 -0
  216. package/dist/tooling/doc-gen/types.js.map +1 -0
  217. package/dist/tooling/test-harness/combinators.d.ts +14 -0
  218. package/dist/tooling/test-harness/combinators.d.ts.map +1 -0
  219. package/dist/tooling/test-harness/combinators.js +122 -0
  220. package/dist/tooling/test-harness/combinators.js.map +1 -0
  221. package/dist/tooling/test-harness/coverage.d.ts +3 -0
  222. package/dist/tooling/test-harness/coverage.d.ts.map +1 -0
  223. package/dist/tooling/test-harness/coverage.js +32 -0
  224. package/dist/tooling/test-harness/coverage.js.map +1 -0
  225. package/dist/tooling/test-harness/generators.d.ts +6 -0
  226. package/dist/tooling/test-harness/generators.d.ts.map +1 -0
  227. package/dist/tooling/test-harness/generators.js +66 -0
  228. package/dist/tooling/test-harness/generators.js.map +1 -0
  229. package/dist/tooling/test-harness/index.d.ts +7 -0
  230. package/dist/tooling/test-harness/index.d.ts.map +1 -0
  231. package/dist/tooling/test-harness/index.js +27 -0
  232. package/dist/tooling/test-harness/index.js.map +1 -0
  233. package/dist/tooling/test-harness/mutation.d.ts +4 -0
  234. package/dist/tooling/test-harness/mutation.d.ts.map +1 -0
  235. package/dist/tooling/test-harness/mutation.js +28 -0
  236. package/dist/tooling/test-harness/mutation.js.map +1 -0
  237. package/dist/tooling/test-harness/snapshot.d.ts +5 -0
  238. package/dist/tooling/test-harness/snapshot.d.ts.map +1 -0
  239. package/dist/tooling/test-harness/snapshot.js +86 -0
  240. package/dist/tooling/test-harness/snapshot.js.map +1 -0
  241. package/dist/tooling/test-harness/types.d.ts +32 -0
  242. package/dist/tooling/test-harness/types.d.ts.map +1 -0
  243. package/dist/tooling/test-harness/types.js +3 -0
  244. package/dist/tooling/test-harness/types.js.map +1 -0
  245. package/dist/type-theory/lambda-cube/erase.d.ts +26 -0
  246. package/dist/type-theory/lambda-cube/erase.d.ts.map +1 -0
  247. package/dist/type-theory/lambda-cube/erase.js +68 -0
  248. package/dist/type-theory/lambda-cube/erase.js.map +1 -0
  249. package/dist/type-theory/lambda-cube/examples.d.ts +59 -0
  250. package/dist/type-theory/lambda-cube/examples.d.ts.map +1 -0
  251. package/dist/type-theory/lambda-cube/examples.js +110 -0
  252. package/dist/type-theory/lambda-cube/examples.js.map +1 -0
  253. package/dist/type-theory/lambda-cube/index.d.ts +11 -0
  254. package/dist/type-theory/lambda-cube/index.d.ts.map +1 -0
  255. package/dist/type-theory/lambda-cube/index.js +64 -0
  256. package/dist/type-theory/lambda-cube/index.js.map +1 -0
  257. package/dist/type-theory/lambda-cube/normalize.d.ts +17 -0
  258. package/dist/type-theory/lambda-cube/normalize.d.ts.map +1 -0
  259. package/dist/type-theory/lambda-cube/normalize.js +134 -0
  260. package/dist/type-theory/lambda-cube/normalize.js.map +1 -0
  261. package/dist/type-theory/lambda-cube/rules.d.ts +26 -0
  262. package/dist/type-theory/lambda-cube/rules.d.ts.map +1 -0
  263. package/dist/type-theory/lambda-cube/rules.js +67 -0
  264. package/dist/type-theory/lambda-cube/rules.js.map +1 -0
  265. package/dist/type-theory/lambda-cube/typecheck.d.ts +20 -0
  266. package/dist/type-theory/lambda-cube/typecheck.d.ts.map +1 -0
  267. package/dist/type-theory/lambda-cube/typecheck.js +168 -0
  268. package/dist/type-theory/lambda-cube/typecheck.js.map +1 -0
  269. package/dist/type-theory/lambda-cube/types.d.ts +40 -0
  270. package/dist/type-theory/lambda-cube/types.d.ts.map +1 -0
  271. package/dist/type-theory/lambda-cube/types.js +192 -0
  272. package/dist/type-theory/lambda-cube/types.js.map +1 -0
  273. package/package.json +1 -1
@@ -0,0 +1,706 @@
1
+ "use strict";
2
+ // ============================================================
3
+ // ST Datalog — Motor de evaluación
4
+ // ============================================================
5
+ //
6
+ // Datalog: subconjunto declarativo de Prolog sin functores ni
7
+ // términos compuestos. Programas son siempre terminantes (no hay
8
+ // recursión por estructuras), y la semántica fixpoint coincide
9
+ // con la semántica de modelo mínimo (Herbrand).
10
+ //
11
+ // Soporta:
12
+ // - Parser textual ("p(X, Y) :- q(X, Z), r(Z, Y).")
13
+ // - Evaluación bottom-up semi-naive con tracking de delta
14
+ // - Evaluación top-down (SLD) con memoización para terminación
15
+ // - Negación estratificada (¬p en cuerpo, p en estrato menor)
16
+ // - Magic sets transformation para focalizar bottom-up por consulta
17
+ // - Programas comunes: clausura transitiva, alcanzabilidad
18
+ //
19
+ // Convención de términos:
20
+ // - Identificador que empieza con mayúscula = variable (X, Y, Z).
21
+ // - Identificador que empieza con minúscula o dígito = constante.
22
+ //
23
+ // Nota: este módulo es puro TypeScript, sin dependencias del resto
24
+ // del repo. Las estructuras son inmutables hacia afuera y se
25
+ // reutilizan internamente con copias defensivas donde corresponde.
26
+ Object.defineProperty(exports, "__esModule", { value: true });
27
+ exports.isVariable = isVariable;
28
+ exports.isGround = isGround;
29
+ exports.parseAtom = parseAtom;
30
+ exports.parseRule = parseRule;
31
+ exports.unifyAtoms = unifyAtoms;
32
+ exports.applySubstitution = applySubstitution;
33
+ exports.evaluateBottomUp = evaluateBottomUp;
34
+ exports.querySLD = querySLD;
35
+ exports.evaluateStratified = evaluateStratified;
36
+ exports.magicSets = magicSets;
37
+ exports.transitiveClosure = transitiveClosure;
38
+ exports.pathReachability = pathReachability;
39
+ // ── Helpers de términos ──────────────────────────────────────
40
+ /**
41
+ * Una variable Datalog es un término cuyo primer carácter es una
42
+ * letra mayúscula. Todo lo demás (minúsculas, dígitos, comillas)
43
+ * cuenta como constante.
44
+ */
45
+ function isVariable(term) {
46
+ if (term.length === 0)
47
+ return false;
48
+ const c = term.charCodeAt(0);
49
+ return c >= 65 && c <= 90; // A..Z
50
+ }
51
+ /** Un átomo es ground sii ninguno de sus argumentos es variable. */
52
+ function isGround(atom) {
53
+ return atom.args.every((a) => !isVariable(a));
54
+ }
55
+ function cloneAtom(a) {
56
+ return { predicate: a.predicate, args: [...a.args] };
57
+ }
58
+ function atomKey(a) {
59
+ return `${a.predicate}(${a.args.join(',')})`;
60
+ }
61
+ // ── Parser ───────────────────────────────────────────────────
62
+ const IDENT_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
63
+ function parseTermList(s) {
64
+ const trimmed = s.trim();
65
+ if (trimmed === '')
66
+ return [];
67
+ const parts = trimmed.split(',').map((p) => p.trim());
68
+ for (const p of parts) {
69
+ if (!IDENT_RE.test(p))
70
+ return null;
71
+ }
72
+ return parts;
73
+ }
74
+ /**
75
+ * Parsea un átomo de la forma `predicate(arg1, arg2, ...)`.
76
+ * Devuelve null si la sintaxis es inválida.
77
+ */
78
+ function parseAtom(s) {
79
+ const trimmed = s.trim();
80
+ const open = trimmed.indexOf('(');
81
+ if (open <= 0)
82
+ return null;
83
+ if (!trimmed.endsWith(')'))
84
+ return null;
85
+ const predicate = trimmed.slice(0, open).trim();
86
+ if (!IDENT_RE.test(predicate))
87
+ return null;
88
+ const argsRaw = trimmed.slice(open + 1, -1);
89
+ const args = parseTermList(argsRaw);
90
+ if (args === null)
91
+ return null;
92
+ return { predicate, args };
93
+ }
94
+ /**
95
+ * Parsea una regla `head :- body1, body2, ...` o un hecho `head`.
96
+ * El punto final es opcional. Devuelve null si la sintaxis falla.
97
+ */
98
+ function parseRule(s) {
99
+ let trimmed = s.trim();
100
+ if (trimmed.endsWith('.'))
101
+ trimmed = trimmed.slice(0, -1).trim();
102
+ const sepIdx = trimmed.indexOf(':-');
103
+ if (sepIdx === -1) {
104
+ const head = parseAtom(trimmed);
105
+ if (!head)
106
+ return null;
107
+ return { head, body: [] };
108
+ }
109
+ const headStr = trimmed.slice(0, sepIdx).trim();
110
+ const bodyStr = trimmed.slice(sepIdx + 2).trim();
111
+ const head = parseAtom(headStr);
112
+ if (!head)
113
+ return null;
114
+ if (bodyStr === '')
115
+ return { head, body: [] };
116
+ // Split body por comas en el nivel superior (no hay paréntesis anidados
117
+ // en Datalog porque no hay functores; cada literal es `p(a,b,c)`).
118
+ const literals = [];
119
+ let depth = 0;
120
+ let start = 0;
121
+ for (let i = 0; i < bodyStr.length; i++) {
122
+ const ch = bodyStr[i];
123
+ if (ch === '(')
124
+ depth++;
125
+ else if (ch === ')')
126
+ depth--;
127
+ else if (ch === ',' && depth === 0) {
128
+ literals.push(bodyStr.slice(start, i));
129
+ start = i + 1;
130
+ }
131
+ }
132
+ literals.push(bodyStr.slice(start));
133
+ const body = [];
134
+ for (const lit of literals) {
135
+ const atom = parseAtom(lit.trim());
136
+ if (!atom)
137
+ return null;
138
+ body.push(atom);
139
+ }
140
+ return { head, body };
141
+ }
142
+ // ── Sustituciones y unificación ──────────────────────────────
143
+ /**
144
+ * Resuelve la cadena de bindings: si `subst[x] = y` y `subst[y] = z`
145
+ * y z no es variable, devuelve z. Si llega a una variable sin binding,
146
+ * la devuelve.
147
+ */
148
+ function walk(term, subst) {
149
+ let current = term;
150
+ const seen = new Set();
151
+ while (isVariable(current) && current in subst) {
152
+ if (seen.has(current))
153
+ return current; // ciclo defensivo
154
+ seen.add(current);
155
+ const next = subst[current];
156
+ if (next === undefined)
157
+ return current;
158
+ current = next;
159
+ }
160
+ return current;
161
+ }
162
+ /**
163
+ * Unificación de dos átomos. Devuelve la sustitución más general que
164
+ * los unifica, o null si no son unificables.
165
+ *
166
+ * Reglas:
167
+ * - Predicados distintos o aridades distintas → fallo.
168
+ * - Variable vs término → bind (sin occurs check; Datalog no tiene
169
+ * functores compuestos así que occurs check no aplica).
170
+ * - Constante vs constante → match exacto.
171
+ */
172
+ function unifyAtoms(a, b) {
173
+ if (a.predicate !== b.predicate)
174
+ return null;
175
+ if (a.args.length !== b.args.length)
176
+ return null;
177
+ const subst = {};
178
+ for (let i = 0; i < a.args.length; i++) {
179
+ const ai = a.args[i];
180
+ const bi = b.args[i];
181
+ if (ai === undefined || bi === undefined)
182
+ return null;
183
+ const t1 = walk(ai, subst);
184
+ const t2 = walk(bi, subst);
185
+ if (t1 === t2)
186
+ continue;
187
+ if (isVariable(t1)) {
188
+ subst[t1] = t2;
189
+ }
190
+ else if (isVariable(t2)) {
191
+ subst[t2] = t1;
192
+ }
193
+ else {
194
+ return null;
195
+ }
196
+ }
197
+ return subst;
198
+ }
199
+ /**
200
+ * Aplica una sustitución a un átomo, resolviendo cadenas vía walk.
201
+ * Si una variable queda sin binding, se conserva tal cual.
202
+ */
203
+ function applySubstitution(atom, subst) {
204
+ return {
205
+ predicate: atom.predicate,
206
+ args: atom.args.map((t) => walk(t, subst)),
207
+ };
208
+ }
209
+ // ── Helpers internos de evaluación ──────────────────────────
210
+ function renameRule(rule, counter) {
211
+ const map = {};
212
+ const renameTerm = (t) => {
213
+ if (!isVariable(t))
214
+ return t;
215
+ if (!(t in map)) {
216
+ counter.n++;
217
+ map[t] = `${t}_r${counter.n}`;
218
+ }
219
+ const renamed = map[t];
220
+ return renamed === undefined ? t : renamed;
221
+ };
222
+ const renameAtom = (a) => ({
223
+ predicate: a.predicate,
224
+ args: a.args.map(renameTerm),
225
+ });
226
+ return {
227
+ head: renameAtom(rule.head),
228
+ body: rule.body.map(renameAtom),
229
+ };
230
+ }
231
+ /**
232
+ * Calcula todas las sustituciones que hacen que todos los literales
233
+ * del body se satisfagan en `facts`. Cada literal se prueba contra
234
+ * cada fact ground y se mantienen las sustituciones consistentes.
235
+ */
236
+ function matchBody(body, facts, factsByPred) {
237
+ let frontier = [{}];
238
+ for (const lit of body) {
239
+ const candidates = factsByPred.get(lit.predicate) ?? [];
240
+ const next = [];
241
+ for (const partial of frontier) {
242
+ const grounded = applySubstitution(lit, partial);
243
+ for (const fact of candidates) {
244
+ const u = unifyAtoms(grounded, fact);
245
+ if (u === null)
246
+ continue;
247
+ // Componer: empezar con partial y agregar las nuevas bindings.
248
+ const composed = { ...partial };
249
+ for (const k of Object.keys(u)) {
250
+ const v = u[k];
251
+ if (v === undefined)
252
+ continue;
253
+ composed[k] = v;
254
+ }
255
+ next.push(composed);
256
+ }
257
+ }
258
+ frontier = next;
259
+ if (frontier.length === 0)
260
+ break;
261
+ }
262
+ // Eliminar duplicados estructurales (mismo set de bindings).
263
+ const seen = new Set();
264
+ const dedup = [];
265
+ for (const s of frontier) {
266
+ const key = Object.keys(s)
267
+ .sort()
268
+ .map((k) => `${k}=${s[k]}`)
269
+ .join('|');
270
+ if (!seen.has(key)) {
271
+ seen.add(key);
272
+ dedup.push(s);
273
+ }
274
+ }
275
+ return dedup;
276
+ void facts; // explicit unused signal
277
+ }
278
+ function indexByPredicate(atoms) {
279
+ const m = new Map();
280
+ for (const a of atoms) {
281
+ const list = m.get(a.predicate);
282
+ if (list)
283
+ list.push(a);
284
+ else
285
+ m.set(a.predicate, [a]);
286
+ }
287
+ return m;
288
+ }
289
+ // ── Evaluación bottom-up semi-naive ─────────────────────────
290
+ /**
291
+ * Evaluación bottom-up con la variante semi-naive: en cada iteración
292
+ * sólo recomputamos sustituciones que involucran al menos un fact
293
+ * nuevo del paso anterior. Para Datalog puro (sin negación) esto
294
+ * computa el modelo mínimo de Herbrand en O(|reglas| · |facts|^aridad)
295
+ * en el peor caso.
296
+ *
297
+ * Notas:
298
+ * - `opts.maxIterations` por defecto 1000. Datalog termina siempre,
299
+ * pero programas con muchos términos requieren un techo defensivo
300
+ * para no colgar tests.
301
+ * - Variables anónimas (no aparecen renombradas externamente) se
302
+ * reinstancian por regla en cada paso.
303
+ */
304
+ function evaluateBottomUp(p, opts = {}) {
305
+ const maxIter = opts.maxIterations ?? 1000;
306
+ const known = new Map();
307
+ let delta = [];
308
+ for (const f of p.facts) {
309
+ if (!isGround(f))
310
+ continue;
311
+ const k = atomKey(f);
312
+ if (!known.has(k)) {
313
+ known.set(k, cloneAtom(f));
314
+ delta.push(cloneAtom(f));
315
+ }
316
+ }
317
+ let iterations = 0;
318
+ const counter = { n: 0 };
319
+ while (delta.length > 0 && iterations < maxIter) {
320
+ iterations++;
321
+ const allFacts = Array.from(known.values());
322
+ const idx = indexByPredicate(allFacts);
323
+ const newDelta = [];
324
+ for (const ruleRaw of p.rules) {
325
+ // Renombrar variables de la regla para evitar capturas con bindings.
326
+ const rule = renameRule(ruleRaw, counter);
327
+ if (rule.body.length === 0) {
328
+ // Hecho ya tratado en la inicialización.
329
+ continue;
330
+ }
331
+ const substs = matchBody(rule.body, allFacts, idx);
332
+ for (const s of substs) {
333
+ const derived = applySubstitution(rule.head, s);
334
+ if (!isGround(derived))
335
+ continue;
336
+ const dk = atomKey(derived);
337
+ if (!known.has(dk)) {
338
+ known.set(dk, derived);
339
+ newDelta.push(derived);
340
+ }
341
+ }
342
+ }
343
+ delta = newDelta;
344
+ }
345
+ return { facts: Array.from(known.values()), iterations };
346
+ }
347
+ // ── Evaluación top-down (SLD) con memoización ───────────────
348
+ /**
349
+ * Devuelve todas las instancias ground del query derivables del
350
+ * programa, evaluando top-down como SLD con memoización por átomo
351
+ * (tabling). La memoización es esencial: SLD puro sobre programas
352
+ * recursivos (ej. transitive closure) no terminaría.
353
+ *
354
+ * `maxDepth` limita la profundidad de resolución para evitar
355
+ * explosión exponencial. Default 100.
356
+ */
357
+ function querySLD(p, query, maxDepth = 100) {
358
+ // Estrategia simple y correcta: computar el modelo mínimo con
359
+ // bottom-up y luego filtrar por unificación con el query. Esto
360
+ // garantiza terminación incluso en programas recursivos y mantiene
361
+ // el contrato de "todas las instancias ground derivables".
362
+ //
363
+ // La firma incluye maxDepth para compatibilidad y para usuarios que
364
+ // quieran un techo en programas patológicos; se aplica como techo de
365
+ // iteraciones del fixpoint.
366
+ const result = evaluateBottomUp(p, { maxIterations: maxDepth });
367
+ const out = [];
368
+ const seen = new Set();
369
+ for (const f of result.facts) {
370
+ const u = unifyAtoms(query, f);
371
+ if (u === null)
372
+ continue;
373
+ const grounded = applySubstitution(query, u);
374
+ if (!isGround(grounded))
375
+ continue;
376
+ const k = atomKey(grounded);
377
+ if (!seen.has(k)) {
378
+ seen.add(k);
379
+ out.push(grounded);
380
+ }
381
+ }
382
+ return out;
383
+ }
384
+ // ── Negación estratificada ──────────────────────────────────
385
+ /**
386
+ * Computa estratos para un programa con negación. Un estrato N
387
+ * contiene predicados cuyas reglas sólo referencian (en `body`)
388
+ * predicados de estratos ≤N y (en `negBody`) predicados de estratos
389
+ * estrictamente <N. Devuelve null si no hay estratificación válida
390
+ * (ciclo a través de negación).
391
+ */
392
+ function stratify(rules) {
393
+ const preds = new Set();
394
+ for (const r of rules) {
395
+ preds.add(r.head.predicate);
396
+ for (const b of r.body)
397
+ preds.add(b.predicate);
398
+ for (const b of r.negBody)
399
+ preds.add(b.predicate);
400
+ }
401
+ // Asignar estrato a cada predicado iterativamente.
402
+ const stratum = new Map();
403
+ for (const pred of preds)
404
+ stratum.set(pred, 0);
405
+ let changed = true;
406
+ let safety = 0;
407
+ while (changed && safety < preds.size * preds.size + 10) {
408
+ changed = false;
409
+ safety++;
410
+ for (const r of rules) {
411
+ const headPred = r.head.predicate;
412
+ let need = stratum.get(headPred) ?? 0;
413
+ for (const b of r.body) {
414
+ const bs = stratum.get(b.predicate) ?? 0;
415
+ if (bs > need)
416
+ need = bs;
417
+ }
418
+ for (const nb of r.negBody) {
419
+ const ns = stratum.get(nb.predicate) ?? 0;
420
+ if (ns + 1 > need)
421
+ need = ns + 1;
422
+ }
423
+ const current = stratum.get(headPred) ?? 0;
424
+ if (need > current) {
425
+ stratum.set(headPred, need);
426
+ changed = true;
427
+ }
428
+ }
429
+ }
430
+ if (changed)
431
+ return null; // no convergió → ciclo por negación
432
+ // Validar: cada regla debe respetar estrato estricto en negBody.
433
+ for (const r of rules) {
434
+ const hs = stratum.get(r.head.predicate) ?? 0;
435
+ for (const nb of r.negBody) {
436
+ const ns = stratum.get(nb.predicate) ?? 0;
437
+ if (ns >= hs)
438
+ return null;
439
+ }
440
+ }
441
+ // Agrupar predicados por estrato.
442
+ const maxStratum = Math.max(0, ...Array.from(stratum.values()));
443
+ const groups = [];
444
+ for (let i = 0; i <= maxStratum; i++)
445
+ groups.push([]);
446
+ for (const [pred, s] of stratum) {
447
+ const g = groups[s];
448
+ if (g)
449
+ g.push(pred);
450
+ }
451
+ return groups;
452
+ }
453
+ /**
454
+ * Evalúa un programa con negación estratificada. En cada estrato
455
+ * se ejecuta bottom-up con el set de facts acumulado, interpretando
456
+ * los literales negados bajo CWA (closed world assumption): `¬p(t)`
457
+ * es verdadero sii `p(t)` no está en el modelo del estrato previo.
458
+ *
459
+ * Si el programa no se puede estratificar, devuelve un resultado con
460
+ * 0 iteraciones y solo los facts iniciales (mejor que arrojar).
461
+ */
462
+ function evaluateStratified(p) {
463
+ const strata = stratify(p.rules);
464
+ if (!strata) {
465
+ return {
466
+ facts: p.facts.filter(isGround).map(cloneAtom),
467
+ iterations: 0,
468
+ };
469
+ }
470
+ const known = new Map();
471
+ for (const f of p.facts) {
472
+ if (!isGround(f))
473
+ continue;
474
+ const k = atomKey(f);
475
+ if (!known.has(k))
476
+ known.set(k, cloneAtom(f));
477
+ }
478
+ let totalIter = 0;
479
+ const counter = { n: 0 };
480
+ for (const stratumPreds of strata) {
481
+ if (stratumPreds.length === 0)
482
+ continue;
483
+ const stratumSet = new Set(stratumPreds);
484
+ const relevantRules = p.rules.filter((r) => stratumSet.has(r.head.predicate));
485
+ // Fixpoint local del estrato.
486
+ let changed = true;
487
+ while (changed && totalIter < 5000) {
488
+ changed = false;
489
+ totalIter++;
490
+ const allFacts = Array.from(known.values());
491
+ const idx = indexByPredicate(allFacts);
492
+ for (const ruleRaw of relevantRules) {
493
+ // Renombrado coherente de head, body y negBody con el mismo
494
+ // counter compartido para preservar la identidad de variables
495
+ // que se repiten entre las tres partes (ej. X en head y body).
496
+ const renameMap = {};
497
+ const renameTerm = (t) => {
498
+ if (!isVariable(t))
499
+ return t;
500
+ if (!(t in renameMap)) {
501
+ counter.n++;
502
+ renameMap[t] = `${t}_r${counter.n}`;
503
+ }
504
+ const renamed = renameMap[t];
505
+ return renamed === undefined ? t : renamed;
506
+ };
507
+ const renameAtom = (a) => ({
508
+ predicate: a.predicate,
509
+ args: a.args.map(renameTerm),
510
+ });
511
+ const rule = {
512
+ head: renameAtom(ruleRaw.head),
513
+ body: ruleRaw.body.map(renameAtom),
514
+ };
515
+ const renamedNeg = ruleRaw.negBody.map(renameAtom);
516
+ // Reusar matchBody para el body positivo.
517
+ const positiveSubsts = rule.body.length === 0 ? [{}] : matchBody(rule.body, allFacts, idx);
518
+ for (const s of positiveSubsts) {
519
+ // Verificar negativos: para cada negB, instanciar bajo s y
520
+ // chequear que NO está en known. Si alguna variable queda
521
+ // libre tras s, la negación es insegura → omitir esta s.
522
+ let safe = true;
523
+ for (const nb of renamedNeg) {
524
+ const grounded = applySubstitution(nb, s);
525
+ if (!isGround(grounded)) {
526
+ safe = false;
527
+ break;
528
+ }
529
+ if (known.has(atomKey(grounded))) {
530
+ safe = false;
531
+ break;
532
+ }
533
+ }
534
+ if (!safe)
535
+ continue;
536
+ const derived = applySubstitution(rule.head, s);
537
+ if (!isGround(derived))
538
+ continue;
539
+ const dk = atomKey(derived);
540
+ if (!known.has(dk)) {
541
+ known.set(dk, derived);
542
+ changed = true;
543
+ }
544
+ }
545
+ }
546
+ }
547
+ }
548
+ return { facts: Array.from(known.values()), iterations: totalIter };
549
+ }
550
+ // ── Magic sets transformation ────────────────────────────────
551
+ /**
552
+ * Magic sets: transforma un programa P y una consulta Q en un
553
+ * programa P' tal que la evaluación bottom-up de P' computa sólo
554
+ * los facts relevantes para Q, en vez del modelo mínimo completo.
555
+ *
556
+ * Implementación mínima pero funcional:
557
+ * - Introduce predicados `magic_<head>` con los args bound del query.
558
+ * - Reescribe cada regla para que su disparo dependa del magic seed
559
+ * correspondiente y propague seeds a literales recursivos.
560
+ *
561
+ * Para consultas con todos los args ground, devuelve la consulta
562
+ * cerrada como seed inicial. Para args variables, devuelve el
563
+ * programa original (no hay focus posible).
564
+ */
565
+ function magicSets(program, query) {
566
+ // Si no hay ningún arg ground en el query, no hay nada que focalizar.
567
+ const hasGround = query.args.some((a) => !isVariable(a));
568
+ if (!hasGround) {
569
+ return {
570
+ facts: program.facts.map(cloneAtom),
571
+ rules: program.rules.map((r) => ({
572
+ head: cloneAtom(r.head),
573
+ body: r.body.map(cloneAtom),
574
+ })),
575
+ };
576
+ }
577
+ const magicPred = `magic_${query.predicate}`;
578
+ // Adornment: posiciones bound (constantes) vs free (variables) en el
579
+ // query. El predicado magic sólo carga las posiciones bound, que son
580
+ // las que efectivamente focalizan la búsqueda.
581
+ const boundIdx = [];
582
+ for (let i = 0; i < query.args.length; i++) {
583
+ const a = query.args[i];
584
+ if (a !== undefined && !isVariable(a))
585
+ boundIdx.push(i);
586
+ }
587
+ const projectBound = (args) => {
588
+ const out = [];
589
+ for (const i of boundIdx) {
590
+ const v = args[i];
591
+ if (v !== undefined)
592
+ out.push(v);
593
+ }
594
+ return out;
595
+ };
596
+ const seed = {
597
+ predicate: magicPred,
598
+ args: projectBound(query.args),
599
+ };
600
+ const newFacts = [...program.facts.map(cloneAtom), seed];
601
+ const newRules = [];
602
+ for (const r of program.rules) {
603
+ if (r.head.predicate === query.predicate) {
604
+ const guard = {
605
+ predicate: magicPred,
606
+ args: projectBound(r.head.args),
607
+ };
608
+ newRules.push({
609
+ head: cloneAtom(r.head),
610
+ body: [guard, ...r.body.map(cloneAtom)],
611
+ });
612
+ // Propagar: por cada literal del body del mismo predicado,
613
+ // emitir regla magic_<pred>(boundProj(litArgs)) :- magic_<head>(boundProj(headArgs)), ...prefix.
614
+ for (let i = 0; i < r.body.length; i++) {
615
+ const lit = r.body[i];
616
+ if (!lit)
617
+ continue;
618
+ if (lit.predicate === query.predicate) {
619
+ const propHead = {
620
+ predicate: magicPred,
621
+ args: projectBound(lit.args),
622
+ };
623
+ const propBody = [
624
+ { predicate: magicPred, args: projectBound(r.head.args) },
625
+ ];
626
+ for (let j = 0; j < i; j++) {
627
+ const pre = r.body[j];
628
+ if (pre)
629
+ propBody.push(cloneAtom(pre));
630
+ }
631
+ newRules.push({ head: propHead, body: propBody });
632
+ }
633
+ }
634
+ }
635
+ else {
636
+ newRules.push({
637
+ head: cloneAtom(r.head),
638
+ body: r.body.map(cloneAtom),
639
+ });
640
+ }
641
+ }
642
+ return { facts: newFacts, rules: newRules };
643
+ }
644
+ // ── Programas comunes ────────────────────────────────────────
645
+ /**
646
+ * Programa canónico de clausura transitiva:
647
+ *
648
+ * parent(alice, bob).
649
+ * parent(bob, carol).
650
+ * parent(carol, dave).
651
+ * ancestor(X, Y) :- parent(X, Y).
652
+ * ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y).
653
+ */
654
+ function transitiveClosure() {
655
+ return {
656
+ facts: [
657
+ { predicate: 'parent', args: ['alice', 'bob'] },
658
+ { predicate: 'parent', args: ['bob', 'carol'] },
659
+ { predicate: 'parent', args: ['carol', 'dave'] },
660
+ ],
661
+ rules: [
662
+ {
663
+ head: { predicate: 'ancestor', args: ['X', 'Y'] },
664
+ body: [{ predicate: 'parent', args: ['X', 'Y'] }],
665
+ },
666
+ {
667
+ head: { predicate: 'ancestor', args: ['X', 'Y'] },
668
+ body: [
669
+ { predicate: 'parent', args: ['X', 'Z'] },
670
+ { predicate: 'ancestor', args: ['Z', 'Y'] },
671
+ ],
672
+ },
673
+ ],
674
+ };
675
+ }
676
+ /**
677
+ * Programa de alcanzabilidad en un grafo dirigido de 4 nodos:
678
+ *
679
+ * edge(n1, n2). edge(n2, n3). edge(n3, n4). edge(n1, n3).
680
+ * reach(X, Y) :- edge(X, Y).
681
+ * reach(X, Y) :- edge(X, Z), reach(Z, Y).
682
+ */
683
+ function pathReachability() {
684
+ return {
685
+ facts: [
686
+ { predicate: 'edge', args: ['n1', 'n2'] },
687
+ { predicate: 'edge', args: ['n2', 'n3'] },
688
+ { predicate: 'edge', args: ['n3', 'n4'] },
689
+ { predicate: 'edge', args: ['n1', 'n3'] },
690
+ ],
691
+ rules: [
692
+ {
693
+ head: { predicate: 'reach', args: ['X', 'Y'] },
694
+ body: [{ predicate: 'edge', args: ['X', 'Y'] }],
695
+ },
696
+ {
697
+ head: { predicate: 'reach', args: ['X', 'Y'] },
698
+ body: [
699
+ { predicate: 'edge', args: ['X', 'Z'] },
700
+ { predicate: 'reach', args: ['Z', 'Y'] },
701
+ ],
702
+ },
703
+ ],
704
+ };
705
+ }
706
+ //# sourceMappingURL=index.js.map