@stevenvo780/st-lang 4.8.0 → 4.10.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 (265) hide show
  1. package/dist/logic/profiles/natural-deduction-nk/formula.d.ts +18 -0
  2. package/dist/logic/profiles/natural-deduction-nk/formula.d.ts.map +1 -0
  3. package/dist/logic/profiles/natural-deduction-nk/formula.js +102 -0
  4. package/dist/logic/profiles/natural-deduction-nk/formula.js.map +1 -0
  5. package/dist/logic/profiles/natural-deduction-nk/index.d.ts +5 -0
  6. package/dist/logic/profiles/natural-deduction-nk/index.d.ts.map +1 -0
  7. package/dist/logic/profiles/natural-deduction-nk/index.js +28 -0
  8. package/dist/logic/profiles/natural-deduction-nk/index.js.map +1 -0
  9. package/dist/logic/profiles/natural-deduction-nk/prover.d.ts +49 -0
  10. package/dist/logic/profiles/natural-deduction-nk/prover.d.ts.map +1 -0
  11. package/dist/logic/profiles/natural-deduction-nk/prover.js +557 -0
  12. package/dist/logic/profiles/natural-deduction-nk/prover.js.map +1 -0
  13. package/dist/logic/profiles/natural-deduction-nk/types.d.ts +48 -0
  14. package/dist/logic/profiles/natural-deduction-nk/types.d.ts.map +1 -0
  15. package/dist/logic/profiles/natural-deduction-nk/types.js +35 -0
  16. package/dist/logic/profiles/natural-deduction-nk/types.js.map +1 -0
  17. package/dist/logic/profiles/quantum/index.d.ts +153 -0
  18. package/dist/logic/profiles/quantum/index.d.ts.map +1 -0
  19. package/dist/logic/profiles/quantum/index.js +788 -0
  20. package/dist/logic/profiles/quantum/index.js.map +1 -0
  21. package/dist/namespaces/reasoning.d.ts +2 -1
  22. package/dist/namespaces/reasoning.d.ts.map +1 -1
  23. package/dist/namespaces/reasoning.js +3 -1
  24. package/dist/namespaces/reasoning.js.map +1 -1
  25. package/dist/proof-systems/certificate/canonical.d.ts +18 -0
  26. package/dist/proof-systems/certificate/canonical.d.ts.map +1 -0
  27. package/dist/proof-systems/certificate/canonical.js +79 -0
  28. package/dist/proof-systems/certificate/canonical.js.map +1 -0
  29. package/dist/proof-systems/certificate/generate.d.ts +39 -0
  30. package/dist/proof-systems/certificate/generate.d.ts.map +1 -0
  31. package/dist/proof-systems/certificate/generate.js +259 -0
  32. package/dist/proof-systems/certificate/generate.js.map +1 -0
  33. package/dist/proof-systems/certificate/index.d.ts +7 -0
  34. package/dist/proof-systems/certificate/index.d.ts.map +1 -0
  35. package/dist/proof-systems/certificate/index.js +23 -0
  36. package/dist/proof-systems/certificate/index.js.map +1 -0
  37. package/dist/proof-systems/certificate/lfsc.d.ts +15 -0
  38. package/dist/proof-systems/certificate/lfsc.d.ts.map +1 -0
  39. package/dist/proof-systems/certificate/lfsc.js +395 -0
  40. package/dist/proof-systems/certificate/lfsc.js.map +1 -0
  41. package/dist/proof-systems/certificate/rules.d.ts +8 -0
  42. package/dist/proof-systems/certificate/rules.d.ts.map +1 -0
  43. package/dist/proof-systems/certificate/rules.js +369 -0
  44. package/dist/proof-systems/certificate/rules.js.map +1 -0
  45. package/dist/proof-systems/certificate/types.d.ts +114 -0
  46. package/dist/proof-systems/certificate/types.d.ts.map +1 -0
  47. package/dist/proof-systems/certificate/types.js +18 -0
  48. package/dist/proof-systems/certificate/types.js.map +1 -0
  49. package/dist/proof-systems/certificate/verify.d.ts +20 -0
  50. package/dist/proof-systems/certificate/verify.d.ts.map +1 -0
  51. package/dist/proof-systems/certificate/verify.js +171 -0
  52. package/dist/proof-systems/certificate/verify.js.map +1 -0
  53. package/dist/reasoning/automata/dfa.d.ts +17 -0
  54. package/dist/reasoning/automata/dfa.d.ts.map +1 -0
  55. package/dist/reasoning/automata/dfa.js +276 -0
  56. package/dist/reasoning/automata/dfa.js.map +1 -0
  57. package/dist/reasoning/automata/index.d.ts +8 -0
  58. package/dist/reasoning/automata/index.d.ts.map +1 -0
  59. package/dist/reasoning/automata/index.js +64 -0
  60. package/dist/reasoning/automata/index.js.map +1 -0
  61. package/dist/reasoning/automata/languages.d.ts +10 -0
  62. package/dist/reasoning/automata/languages.d.ts.map +1 -0
  63. package/dist/reasoning/automata/languages.js +78 -0
  64. package/dist/reasoning/automata/languages.js.map +1 -0
  65. package/dist/reasoning/automata/nfa.d.ts +8 -0
  66. package/dist/reasoning/automata/nfa.d.ts.map +1 -0
  67. package/dist/reasoning/automata/nfa.js +122 -0
  68. package/dist/reasoning/automata/nfa.js.map +1 -0
  69. package/dist/reasoning/automata/pda.d.ts +10 -0
  70. package/dist/reasoning/automata/pda.d.ts.map +1 -0
  71. package/dist/reasoning/automata/pda.js +169 -0
  72. package/dist/reasoning/automata/pda.js.map +1 -0
  73. package/dist/reasoning/automata/regex.d.ts +6 -0
  74. package/dist/reasoning/automata/regex.d.ts.map +1 -0
  75. package/dist/reasoning/automata/regex.js +259 -0
  76. package/dist/reasoning/automata/regex.js.map +1 -0
  77. package/dist/reasoning/automata/types.d.ts +69 -0
  78. package/dist/reasoning/automata/types.d.ts.map +1 -0
  79. package/dist/reasoning/automata/types.js +29 -0
  80. package/dist/reasoning/automata/types.js.map +1 -0
  81. package/dist/reasoning/ban-logic/analyze.d.ts +31 -0
  82. package/dist/reasoning/ban-logic/analyze.d.ts.map +1 -0
  83. package/dist/reasoning/ban-logic/analyze.js +113 -0
  84. package/dist/reasoning/ban-logic/analyze.js.map +1 -0
  85. package/dist/reasoning/ban-logic/index.d.ts +7 -0
  86. package/dist/reasoning/ban-logic/index.d.ts.map +1 -0
  87. package/dist/reasoning/ban-logic/index.js +66 -0
  88. package/dist/reasoning/ban-logic/index.js.map +1 -0
  89. package/dist/reasoning/ban-logic/protocols.d.ts +54 -0
  90. package/dist/reasoning/ban-logic/protocols.d.ts.map +1 -0
  91. package/dist/reasoning/ban-logic/protocols.js +219 -0
  92. package/dist/reasoning/ban-logic/protocols.js.map +1 -0
  93. package/dist/reasoning/ban-logic/rules.d.ts +83 -0
  94. package/dist/reasoning/ban-logic/rules.d.ts.map +1 -0
  95. package/dist/reasoning/ban-logic/rules.js +409 -0
  96. package/dist/reasoning/ban-logic/rules.js.map +1 -0
  97. package/dist/reasoning/ban-logic/terms.d.ts +26 -0
  98. package/dist/reasoning/ban-logic/terms.d.ts.map +1 -0
  99. package/dist/reasoning/ban-logic/terms.js +262 -0
  100. package/dist/reasoning/ban-logic/terms.js.map +1 -0
  101. package/dist/reasoning/ban-logic/types.d.ts +107 -0
  102. package/dist/reasoning/ban-logic/types.d.ts.map +1 -0
  103. package/dist/reasoning/ban-logic/types.js +27 -0
  104. package/dist/reasoning/ban-logic/types.js.map +1 -0
  105. package/dist/reasoning/computability/index.d.ts +239 -0
  106. package/dist/reasoning/computability/index.d.ts.map +1 -0
  107. package/dist/reasoning/computability/index.js +851 -0
  108. package/dist/reasoning/computability/index.js.map +1 -0
  109. package/dist/reasoning/differential-privacy/index.d.ts +121 -0
  110. package/dist/reasoning/differential-privacy/index.d.ts.map +1 -0
  111. package/dist/reasoning/differential-privacy/index.js +417 -0
  112. package/dist/reasoning/differential-privacy/index.js.map +1 -0
  113. package/dist/reasoning/number-theory/crt.d.ts +9 -0
  114. package/dist/reasoning/number-theory/crt.d.ts.map +1 -0
  115. package/dist/reasoning/number-theory/crt.js +39 -0
  116. package/dist/reasoning/number-theory/crt.js.map +1 -0
  117. package/dist/reasoning/number-theory/diophantine.d.ts +10 -0
  118. package/dist/reasoning/number-theory/diophantine.d.ts.map +1 -0
  119. package/dist/reasoning/number-theory/diophantine.js +87 -0
  120. package/dist/reasoning/number-theory/diophantine.js.map +1 -0
  121. package/dist/reasoning/number-theory/factorization.d.ts +12 -0
  122. package/dist/reasoning/number-theory/factorization.d.ts.map +1 -0
  123. package/dist/reasoning/number-theory/factorization.js +136 -0
  124. package/dist/reasoning/number-theory/factorization.js.map +1 -0
  125. package/dist/reasoning/number-theory/gcd.d.ts +8 -0
  126. package/dist/reasoning/number-theory/gcd.d.ts.map +1 -0
  127. package/dist/reasoning/number-theory/gcd.js +51 -0
  128. package/dist/reasoning/number-theory/gcd.js.map +1 -0
  129. package/dist/reasoning/number-theory/index.d.ts +9 -0
  130. package/dist/reasoning/number-theory/index.d.ts.map +1 -0
  131. package/dist/reasoning/number-theory/index.js +46 -0
  132. package/dist/reasoning/number-theory/index.js.map +1 -0
  133. package/dist/reasoning/number-theory/modular.d.ts +6 -0
  134. package/dist/reasoning/number-theory/modular.d.ts.map +1 -0
  135. package/dist/reasoning/number-theory/modular.js +75 -0
  136. package/dist/reasoning/number-theory/modular.js.map +1 -0
  137. package/dist/reasoning/number-theory/primality.d.ts +6 -0
  138. package/dist/reasoning/number-theory/primality.d.ts.map +1 -0
  139. package/dist/reasoning/number-theory/primality.js +144 -0
  140. package/dist/reasoning/number-theory/primality.js.map +1 -0
  141. package/dist/reasoning/number-theory/symbols.d.ts +3 -0
  142. package/dist/reasoning/number-theory/symbols.d.ts.map +1 -0
  143. package/dist/reasoning/number-theory/symbols.js +57 -0
  144. package/dist/reasoning/number-theory/symbols.js.map +1 -0
  145. package/dist/reasoning/real-analysis/index.d.ts +127 -0
  146. package/dist/reasoning/real-analysis/index.d.ts.map +1 -0
  147. package/dist/reasoning/real-analysis/index.js +638 -0
  148. package/dist/reasoning/real-analysis/index.js.map +1 -0
  149. package/dist/reasoning/topology/index.d.ts +41 -0
  150. package/dist/reasoning/topology/index.d.ts.map +1 -0
  151. package/dist/reasoning/topology/index.js +739 -0
  152. package/dist/reasoning/topology/index.js.map +1 -0
  153. package/dist/tests/logic/profiles/natural-deduction-nk/nk.test.d.ts +2 -0
  154. package/dist/tests/logic/profiles/natural-deduction-nk/nk.test.d.ts.map +1 -0
  155. package/dist/tests/logic/profiles/natural-deduction-nk/nk.test.js +288 -0
  156. package/dist/tests/logic/profiles/natural-deduction-nk/nk.test.js.map +1 -0
  157. package/dist/tests/logic/profiles/quantum/quantum.test.d.ts +2 -0
  158. package/dist/tests/logic/profiles/quantum/quantum.test.d.ts.map +1 -0
  159. package/dist/tests/logic/profiles/quantum/quantum.test.js +209 -0
  160. package/dist/tests/logic/profiles/quantum/quantum.test.js.map +1 -0
  161. package/dist/tests/proof-systems/certificate/certificate.test.d.ts +2 -0
  162. package/dist/tests/proof-systems/certificate/certificate.test.d.ts.map +1 -0
  163. package/dist/tests/proof-systems/certificate/certificate.test.js +449 -0
  164. package/dist/tests/proof-systems/certificate/certificate.test.js.map +1 -0
  165. package/dist/tests/reasoning/automata/automata.test.d.ts +2 -0
  166. package/dist/tests/reasoning/automata/automata.test.d.ts.map +1 -0
  167. package/dist/tests/reasoning/automata/automata.test.js +310 -0
  168. package/dist/tests/reasoning/automata/automata.test.js.map +1 -0
  169. package/dist/tests/reasoning/ban-logic/ban-logic.test.d.ts +2 -0
  170. package/dist/tests/reasoning/ban-logic/ban-logic.test.d.ts.map +1 -0
  171. package/dist/tests/reasoning/ban-logic/ban-logic.test.js +270 -0
  172. package/dist/tests/reasoning/ban-logic/ban-logic.test.js.map +1 -0
  173. package/dist/tests/reasoning/computability/computability.test.d.ts +2 -0
  174. package/dist/tests/reasoning/computability/computability.test.d.ts.map +1 -0
  175. package/dist/tests/reasoning/computability/computability.test.js +246 -0
  176. package/dist/tests/reasoning/computability/computability.test.js.map +1 -0
  177. package/dist/tests/reasoning/differential-privacy/differential-privacy.test.d.ts +2 -0
  178. package/dist/tests/reasoning/differential-privacy/differential-privacy.test.d.ts.map +1 -0
  179. package/dist/tests/reasoning/differential-privacy/differential-privacy.test.js +388 -0
  180. package/dist/tests/reasoning/differential-privacy/differential-privacy.test.js.map +1 -0
  181. package/dist/tests/reasoning/number-theory/number-theory.test.d.ts +2 -0
  182. package/dist/tests/reasoning/number-theory/number-theory.test.d.ts.map +1 -0
  183. package/dist/tests/reasoning/number-theory/number-theory.test.js +170 -0
  184. package/dist/tests/reasoning/number-theory/number-theory.test.js.map +1 -0
  185. package/dist/tests/reasoning/real-analysis/real-analysis.test.d.ts +2 -0
  186. package/dist/tests/reasoning/real-analysis/real-analysis.test.d.ts.map +1 -0
  187. package/dist/tests/reasoning/real-analysis/real-analysis.test.js +197 -0
  188. package/dist/tests/reasoning/real-analysis/real-analysis.test.js.map +1 -0
  189. package/dist/tests/reasoning/topology/topology.test.d.ts +2 -0
  190. package/dist/tests/reasoning/topology/topology.test.d.ts.map +1 -0
  191. package/dist/tests/reasoning/topology/topology.test.js +327 -0
  192. package/dist/tests/reasoning/topology/topology.test.js.map +1 -0
  193. package/dist/tests/tooling/exporters/lean4/lean4-exporter.test.d.ts +2 -0
  194. package/dist/tests/tooling/exporters/lean4/lean4-exporter.test.d.ts.map +1 -0
  195. package/dist/tests/tooling/exporters/lean4/lean4-exporter.test.js +473 -0
  196. package/dist/tests/tooling/exporters/lean4/lean4-exporter.test.js.map +1 -0
  197. package/dist/tests/tooling/mathlib/mathlib.test.d.ts +2 -0
  198. package/dist/tests/tooling/mathlib/mathlib.test.d.ts.map +1 -0
  199. package/dist/tests/tooling/mathlib/mathlib.test.js +214 -0
  200. package/dist/tests/tooling/mathlib/mathlib.test.js.map +1 -0
  201. package/dist/tests/type-theory/effects/effects.test.d.ts +2 -0
  202. package/dist/tests/type-theory/effects/effects.test.d.ts.map +1 -0
  203. package/dist/tests/type-theory/effects/effects.test.js +242 -0
  204. package/dist/tests/type-theory/effects/effects.test.js.map +1 -0
  205. package/dist/tooling/exporters/lean4/index.d.ts +47 -0
  206. package/dist/tooling/exporters/lean4/index.d.ts.map +1 -0
  207. package/dist/tooling/exporters/lean4/index.js +423 -0
  208. package/dist/tooling/exporters/lean4/index.js.map +1 -0
  209. package/dist/tooling/mathlib/group.d.ts +27 -0
  210. package/dist/tooling/mathlib/group.d.ts.map +1 -0
  211. package/dist/tooling/mathlib/group.js +89 -0
  212. package/dist/tooling/mathlib/group.js.map +1 -0
  213. package/dist/tooling/mathlib/index.d.ts +8 -0
  214. package/dist/tooling/mathlib/index.d.ts.map +1 -0
  215. package/dist/tooling/mathlib/index.js +40 -0
  216. package/dist/tooling/mathlib/index.js.map +1 -0
  217. package/dist/tooling/mathlib/instances.d.ts +29 -0
  218. package/dist/tooling/mathlib/instances.d.ts.map +1 -0
  219. package/dist/tooling/mathlib/instances.js +139 -0
  220. package/dist/tooling/mathlib/instances.js.map +1 -0
  221. package/dist/tooling/mathlib/lemmas.d.ts +3 -0
  222. package/dist/tooling/mathlib/lemmas.d.ts.map +1 -0
  223. package/dist/tooling/mathlib/lemmas.js +72 -0
  224. package/dist/tooling/mathlib/lemmas.js.map +1 -0
  225. package/dist/tooling/mathlib/order.d.ts +29 -0
  226. package/dist/tooling/mathlib/order.d.ts.map +1 -0
  227. package/dist/tooling/mathlib/order.js +91 -0
  228. package/dist/tooling/mathlib/order.js.map +1 -0
  229. package/dist/tooling/mathlib/ring.d.ts +15 -0
  230. package/dist/tooling/mathlib/ring.d.ts.map +1 -0
  231. package/dist/tooling/mathlib/ring.js +91 -0
  232. package/dist/tooling/mathlib/ring.js.map +1 -0
  233. package/dist/tooling/mathlib/types.d.ts +62 -0
  234. package/dist/tooling/mathlib/types.d.ts.map +1 -0
  235. package/dist/tooling/mathlib/types.js +7 -0
  236. package/dist/tooling/mathlib/types.js.map +1 -0
  237. package/dist/type-theory/effects/core.d.ts +27 -0
  238. package/dist/type-theory/effects/core.d.ts.map +1 -0
  239. package/dist/type-theory/effects/core.js +79 -0
  240. package/dist/type-theory/effects/core.js.map +1 -0
  241. package/dist/type-theory/effects/exception.d.ts +18 -0
  242. package/dist/type-theory/effects/exception.d.ts.map +1 -0
  243. package/dist/type-theory/effects/exception.js +59 -0
  244. package/dist/type-theory/effects/exception.js.map +1 -0
  245. package/dist/type-theory/effects/index.d.ts +11 -0
  246. package/dist/type-theory/effects/index.d.ts.map +1 -0
  247. package/dist/type-theory/effects/index.js +50 -0
  248. package/dist/type-theory/effects/index.js.map +1 -0
  249. package/dist/type-theory/effects/reader.d.ts +20 -0
  250. package/dist/type-theory/effects/reader.d.ts.map +1 -0
  251. package/dist/type-theory/effects/reader.js +62 -0
  252. package/dist/type-theory/effects/reader.js.map +1 -0
  253. package/dist/type-theory/effects/state.d.ts +31 -0
  254. package/dist/type-theory/effects/state.d.ts.map +1 -0
  255. package/dist/type-theory/effects/state.js +91 -0
  256. package/dist/type-theory/effects/state.js.map +1 -0
  257. package/dist/type-theory/effects/types.d.ts +45 -0
  258. package/dist/type-theory/effects/types.d.ts.map +1 -0
  259. package/dist/type-theory/effects/types.js +21 -0
  260. package/dist/type-theory/effects/types.js.map +1 -0
  261. package/dist/type-theory/effects/writer.d.ts +30 -0
  262. package/dist/type-theory/effects/writer.d.ts.map +1 -0
  263. package/dist/type-theory/effects/writer.js +79 -0
  264. package/dist/type-theory/effects/writer.js.map +1 -0
  265. package/package.json +1 -1
@@ -0,0 +1,739 @@
1
+ "use strict";
2
+ // ============================================================
3
+ // ST Topology — Complejos simpliciales y homología
4
+ // ============================================================
5
+ //
6
+ // Implementa complejos simpliciales abstractos y el cómputo de su
7
+ // homología sobre coeficientes en Z/2 y en Z. Calcula característica
8
+ // de Euler, números de Betti y factores invariantes (torsión).
9
+ //
10
+ // Convenciones:
11
+ // • Un simplex se representa como una lista ordenada estrictamente
12
+ // creciente de vértices (índices enteros no negativos). La clave
13
+ // canónica es `v0,v1,...,vk`.
14
+ // • Un complejo es cerrado bajo caras: `addSimplex(K, s)` añade `s`
15
+ // y todas sus subcaras al complejo.
16
+ // • Orientación inducida: la orientación canónica del k-simplex
17
+ // `[v_0,...,v_k]` es la dada por el orden creciente. La cara
18
+ // que omite el vértice i-ésimo tiene signo `(-1)^i` (coeficientes Z)
19
+ // y se usa el conteo de paridad de inversiones para reordenar.
20
+ // • Sobre Z/2 los signos no importan y el operador borde es lineal
21
+ // mod 2.
22
+ //
23
+ // Resultados clásicos verificados en tests:
24
+ // • Triángulo (1-borde): χ = 0.
25
+ // • Esfera S^2 (borde de tetraedro): β = [1,0,1], χ = 2.
26
+ // • Toro T²: β_{Z/2} = [1,2,1], χ = 0.
27
+ // • Plano proyectivo RP²: β_{Z/2} = [1,1,1], β_Z = [1,0,0]
28
+ // con torsión Z/2 en dimensión 1.
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.makeComplex = makeComplex;
31
+ exports.addSimplex = addSimplex;
32
+ exports.faces = faces;
33
+ exports.boundaryZ2 = boundaryZ2;
34
+ exports.boundaryZ = boundaryZ;
35
+ exports.dimension = dimension;
36
+ exports.fVector = fVector;
37
+ exports.eulerCharacteristic = eulerCharacteristic;
38
+ exports.rankBoundaryZ2 = rankBoundaryZ2;
39
+ exports.bettiNumberZ2 = bettiNumberZ2;
40
+ exports.smithNormalForm = smithNormalForm;
41
+ exports.bettiNumberZ = bettiNumberZ;
42
+ exports.torsionZ = torsionZ;
43
+ exports.nSimplex = nSimplex;
44
+ exports.spheres = spheres;
45
+ exports.torus2 = torus2;
46
+ exports.projectivePlane = projectivePlane;
47
+ exports.kleinBottle = kleinBottle;
48
+ exports.computeHomology = computeHomology;
49
+ // ------------------------------------------------------------
50
+ // Utilidades de claves y normalización
51
+ // ------------------------------------------------------------
52
+ // Clave canónica `v0,v1,...,vk` para un simplex previamente ordenado.
53
+ function key(s) {
54
+ return s.join(',');
55
+ }
56
+ // Decodifica una clave canónica a la lista de vértices.
57
+ function parseKey(k) {
58
+ if (k === '')
59
+ return [];
60
+ return k.split(',').map((x) => Number(x));
61
+ }
62
+ // Devuelve una copia del simplex ordenada ascendentemente. No muta.
63
+ function normalize(s) {
64
+ const out = s.slice();
65
+ out.sort((a, b) => a - b);
66
+ // Eliminar duplicados — un "simplex" con vértices repetidos no es válido.
67
+ for (let i = 1; i < out.length; i++) {
68
+ if (out[i] === out[i - 1]) {
69
+ throw new Error(`simplex con vértices repetidos: ${s.join(',')}`);
70
+ }
71
+ }
72
+ return out;
73
+ }
74
+ // ------------------------------------------------------------
75
+ // API de construcción
76
+ // ------------------------------------------------------------
77
+ function makeComplex() {
78
+ return {
79
+ vertices: [],
80
+ simplices: new Map(),
81
+ dim: -1,
82
+ };
83
+ }
84
+ // Añade un simplex y todas sus caras al complejo.
85
+ function addSimplex(K, s) {
86
+ const sorted = normalize(s);
87
+ const k = sorted.length - 1;
88
+ if (k < 0)
89
+ return; // simplex vacío: nada que añadir
90
+ // Añadir todos los subsimplices (powerset no vacío).
91
+ const n = sorted.length;
92
+ for (let mask = 1; mask < 1 << n; mask++) {
93
+ const sub = [];
94
+ for (let i = 0; i < n; i++) {
95
+ if ((mask >> i) & 1) {
96
+ const v = sorted[i];
97
+ if (v !== undefined)
98
+ sub.push(v);
99
+ }
100
+ }
101
+ const dim = sub.length - 1;
102
+ const kk = key(sub);
103
+ let bucket = K.simplices.get(dim);
104
+ if (!bucket) {
105
+ bucket = new Set();
106
+ K.simplices.set(dim, bucket);
107
+ }
108
+ bucket.add(kk);
109
+ if (dim === 0) {
110
+ const v = sub[0];
111
+ if (v !== undefined && !K.vertices.includes(v)) {
112
+ K.vertices.push(v);
113
+ }
114
+ }
115
+ }
116
+ if (k > K.dim)
117
+ K.dim = k;
118
+ }
119
+ // ------------------------------------------------------------
120
+ // Caras y operador borde
121
+ // ------------------------------------------------------------
122
+ // Todas las caras directas (codimensión 1) de un k-simplex: hay k+1.
123
+ function faces(s) {
124
+ if (s.length <= 1)
125
+ return [];
126
+ const out = [];
127
+ for (let i = 0; i < s.length; i++) {
128
+ const face = [];
129
+ for (let j = 0; j < s.length; j++) {
130
+ if (j !== i) {
131
+ const v = s[j];
132
+ if (v !== undefined)
133
+ face.push(v);
134
+ }
135
+ }
136
+ out.push(face);
137
+ }
138
+ return out;
139
+ }
140
+ // Borde sobre Z/2: la lista de caras sin orientación.
141
+ function boundaryZ2(simplex) {
142
+ return faces(simplex);
143
+ }
144
+ // Borde sobre Z: cada cara con signo (-1)^i, donde i es el índice del
145
+ // vértice omitido en el orden canónico del simplex.
146
+ function boundaryZ(simplex) {
147
+ if (simplex.length <= 1)
148
+ return [];
149
+ const out = [];
150
+ for (let i = 0; i < simplex.length; i++) {
151
+ const face = [];
152
+ for (let j = 0; j < simplex.length; j++) {
153
+ if (j !== i) {
154
+ const v = simplex[j];
155
+ if (v !== undefined)
156
+ face.push(v);
157
+ }
158
+ }
159
+ const sign = i % 2 === 0 ? 1 : -1;
160
+ out.push({ sign, simplex: face });
161
+ }
162
+ return out;
163
+ }
164
+ // ------------------------------------------------------------
165
+ // Invariantes elementales
166
+ // ------------------------------------------------------------
167
+ function dimension(K) {
168
+ return K.dim;
169
+ }
170
+ // f-vector: f_i = número de i-simplices, i = 0..dim.
171
+ function fVector(K) {
172
+ const out = [];
173
+ for (let i = 0; i <= K.dim; i++) {
174
+ out.push(K.simplices.get(i)?.size ?? 0);
175
+ }
176
+ return out;
177
+ }
178
+ // Característica de Euler χ = ∑ (-1)^i f_i.
179
+ function eulerCharacteristic(K) {
180
+ const f = fVector(K);
181
+ let chi = 0;
182
+ for (let i = 0; i < f.length; i++) {
183
+ const fi = f[i];
184
+ if (fi === undefined)
185
+ continue;
186
+ chi += (i % 2 === 0 ? 1 : -1) * fi;
187
+ }
188
+ return chi;
189
+ }
190
+ // ------------------------------------------------------------
191
+ // Matriz borde y rango sobre F_2
192
+ // ------------------------------------------------------------
193
+ // Lista ordenada (estable) de los simplices de dimensión `d`.
194
+ function orderedSimplices(K, d) {
195
+ const bucket = K.simplices.get(d);
196
+ if (!bucket)
197
+ return [];
198
+ const arr = Array.from(bucket);
199
+ arr.sort();
200
+ return arr;
201
+ }
202
+ // Construye la matriz del operador ∂_d : C_d → C_{d-1} sobre Z/2.
203
+ // Filas = simplices de dim d-1, columnas = simplices de dim d.
204
+ function boundaryMatrixZ2(K, d) {
205
+ if (d <= 0)
206
+ return [];
207
+ const cols = orderedSimplices(K, d);
208
+ const rows = orderedSimplices(K, d - 1);
209
+ const rowIndex = new Map();
210
+ rows.forEach((k, i) => rowIndex.set(k, i));
211
+ const M = Array.from({ length: rows.length }, () => new Array(cols.length).fill(0));
212
+ for (let c = 0; c < cols.length; c++) {
213
+ const colKey = cols[c];
214
+ if (colKey === undefined)
215
+ continue;
216
+ const simplex = parseKey(colKey);
217
+ for (const f of faces(simplex)) {
218
+ const idx = rowIndex.get(key(f));
219
+ if (idx !== undefined) {
220
+ const row = M[idx];
221
+ if (row)
222
+ row[c] ^= 1;
223
+ }
224
+ }
225
+ }
226
+ return M;
227
+ }
228
+ // Rango sobre F_2 vía eliminación gaussiana mod 2.
229
+ function rankF2(M) {
230
+ const rows = M.length;
231
+ if (rows === 0)
232
+ return 0;
233
+ const first = M[0];
234
+ const cols = first ? first.length : 0;
235
+ if (cols === 0)
236
+ return 0;
237
+ // Copia mutable.
238
+ const A = M.map((r) => r.slice());
239
+ let rank = 0;
240
+ let col = 0;
241
+ for (let r = 0; r < rows && col < cols; col++) {
242
+ // Buscar pivote en columna `col` a partir de fila `r`.
243
+ let pivot = -1;
244
+ for (let i = r; i < rows; i++) {
245
+ const rowA = A[i];
246
+ if (rowA && rowA[col] === 1) {
247
+ pivot = i;
248
+ break;
249
+ }
250
+ }
251
+ if (pivot === -1)
252
+ continue;
253
+ // Swap.
254
+ if (pivot !== r) {
255
+ const tmp = A[r];
256
+ const piv = A[pivot];
257
+ if (tmp && piv) {
258
+ A[r] = piv;
259
+ A[pivot] = tmp;
260
+ }
261
+ }
262
+ // Eliminar abajo Y arriba (forma reducida no es necesaria para rango,
263
+ // pero limpiar arriba simplifica razonar).
264
+ const pivotRow = A[r];
265
+ if (!pivotRow)
266
+ continue;
267
+ for (let i = 0; i < rows; i++) {
268
+ if (i === r)
269
+ continue;
270
+ const rowI = A[i];
271
+ if (rowI && rowI[col] === 1) {
272
+ for (let j = col; j < cols; j++) {
273
+ const pv = pivotRow[j] ?? 0;
274
+ rowI[j] = (rowI[j] ?? 0) ^ pv;
275
+ }
276
+ }
277
+ }
278
+ r++;
279
+ rank++;
280
+ }
281
+ return rank;
282
+ }
283
+ // Rango del operador borde ∂_d sobre Z/2.
284
+ function rankBoundaryZ2(K, dim) {
285
+ if (dim <= 0)
286
+ return 0;
287
+ const M = boundaryMatrixZ2(K, dim);
288
+ return rankF2(M);
289
+ }
290
+ // Números de Betti sobre Z/2:
291
+ // β_d = dim ker ∂_d - dim im ∂_{d+1}
292
+ // = n_d - rank ∂_d - rank ∂_{d+1}
293
+ function bettiNumberZ2(K, dim) {
294
+ if (dim < 0)
295
+ return 0;
296
+ const nd = K.simplices.get(dim)?.size ?? 0;
297
+ const rankD = rankBoundaryZ2(K, dim);
298
+ const rankD1 = rankBoundaryZ2(K, dim + 1);
299
+ return nd - rankD - rankD1;
300
+ }
301
+ // ------------------------------------------------------------
302
+ // Smith Normal Form sobre Z
303
+ // ------------------------------------------------------------
304
+ // Matriz borde ∂_d sobre Z (con signos). Filas = simplices dim d-1,
305
+ // columnas = simplices dim d.
306
+ function boundaryMatrixZ(K, d) {
307
+ if (d <= 0)
308
+ return [];
309
+ const cols = orderedSimplices(K, d);
310
+ const rows = orderedSimplices(K, d - 1);
311
+ const rowIndex = new Map();
312
+ rows.forEach((k, i) => rowIndex.set(k, i));
313
+ const M = Array.from({ length: rows.length }, () => new Array(cols.length).fill(0));
314
+ for (let c = 0; c < cols.length; c++) {
315
+ const colKey = cols[c];
316
+ if (colKey === undefined)
317
+ continue;
318
+ const simplex = parseKey(colKey);
319
+ for (const { sign, simplex: f } of boundaryZ(simplex)) {
320
+ const idx = rowIndex.get(key(f));
321
+ if (idx !== undefined) {
322
+ const row = M[idx];
323
+ if (row)
324
+ row[c] = (row[c] ?? 0) + sign;
325
+ }
326
+ }
327
+ }
328
+ return M;
329
+ }
330
+ function absGcd(a, b) {
331
+ let x = Math.abs(a);
332
+ let y = Math.abs(b);
333
+ while (y !== 0) {
334
+ const t = y;
335
+ y = x % y;
336
+ x = t;
337
+ }
338
+ return x;
339
+ }
340
+ // Smith Normal Form sobre Z para una matriz entera.
341
+ // Devuelve la SNF (diagonal con factores invariantes d_1 | d_2 | ... | d_r,
342
+ // resto ceros), el rango (= número de pivotes no nulos) y la dimensión del
343
+ // kernel (cols - rank).
344
+ //
345
+ // Algoritmo: reducción iterativa estilo Bareiss/Euclidiana sobre filas y
346
+ // columnas hasta diagonalizar. Para complejos pequeños es más que suficiente.
347
+ function smithNormalForm(matrix) {
348
+ const rows = matrix.length;
349
+ const firstRow = matrix[0];
350
+ const cols = firstRow ? firstRow.length : 0;
351
+ // Copia profunda.
352
+ const A = matrix.map((r) => r.slice());
353
+ if (rows === 0 || cols === 0) {
354
+ return {
355
+ snf: A,
356
+ rankIm: 0,
357
+ rankKer: cols,
358
+ invariants: [],
359
+ };
360
+ }
361
+ const rowSwap = (i, j) => {
362
+ if (i === j)
363
+ return;
364
+ const ri = A[i];
365
+ const rj = A[j];
366
+ if (ri && rj) {
367
+ A[i] = rj;
368
+ A[j] = ri;
369
+ }
370
+ };
371
+ const colSwap = (i, j) => {
372
+ if (i === j)
373
+ return;
374
+ for (let r = 0; r < rows; r++) {
375
+ const row = A[r];
376
+ if (!row)
377
+ continue;
378
+ const tmp = row[i] ?? 0;
379
+ row[i] = row[j] ?? 0;
380
+ row[j] = tmp;
381
+ }
382
+ };
383
+ const rowMulNeg = (i) => {
384
+ const row = A[i];
385
+ if (!row)
386
+ return;
387
+ for (let c = 0; c < cols; c++)
388
+ row[c] = -(row[c] ?? 0);
389
+ };
390
+ const rowAddMul = (target, source, k) => {
391
+ // A[target] += k * A[source]
392
+ const rt = A[target];
393
+ const rs = A[source];
394
+ if (!rt || !rs)
395
+ return;
396
+ for (let c = 0; c < cols; c++)
397
+ rt[c] = (rt[c] ?? 0) + k * (rs[c] ?? 0);
398
+ };
399
+ const colAddMul = (target, source, k) => {
400
+ // A[:, target] += k * A[:, source]
401
+ for (let r = 0; r < rows; r++) {
402
+ const row = A[r];
403
+ if (!row)
404
+ continue;
405
+ row[target] = (row[target] ?? 0) + k * (row[source] ?? 0);
406
+ }
407
+ };
408
+ let pivot = 0;
409
+ while (pivot < Math.min(rows, cols)) {
410
+ // 1) Encontrar entrada no nula en el bloque [pivot..rows-1, pivot..cols-1]
411
+ let found = false;
412
+ let pi = pivot;
413
+ let pj = pivot;
414
+ let best = Infinity;
415
+ for (let i = pivot; i < rows; i++) {
416
+ const row = A[i];
417
+ if (!row)
418
+ continue;
419
+ for (let j = pivot; j < cols; j++) {
420
+ const v = row[j] ?? 0;
421
+ if (v !== 0) {
422
+ const av = Math.abs(v);
423
+ if (av < best) {
424
+ best = av;
425
+ pi = i;
426
+ pj = j;
427
+ found = true;
428
+ }
429
+ }
430
+ }
431
+ }
432
+ if (!found)
433
+ break;
434
+ rowSwap(pivot, pi);
435
+ colSwap(pivot, pj);
436
+ // 2) Reducir entrada por entrada en la fila y columna del pivote
437
+ // hasta que sólo quede el pivote en su cruz.
438
+ let changed = true;
439
+ while (changed) {
440
+ changed = false;
441
+ const rowP = A[pivot];
442
+ if (!rowP)
443
+ break;
444
+ const piv = rowP[pivot] ?? 0;
445
+ if (piv === 0)
446
+ break;
447
+ // Limpiar columna del pivote (debajo y arriba).
448
+ for (let i = 0; i < rows; i++) {
449
+ if (i === pivot)
450
+ continue;
451
+ const row = A[i];
452
+ if (!row)
453
+ continue;
454
+ const v = row[pivot] ?? 0;
455
+ if (v === 0)
456
+ continue;
457
+ const q = Math.trunc(v / piv);
458
+ if (q !== 0) {
459
+ rowAddMul(i, pivot, -q);
460
+ }
461
+ const rem = row[pivot] ?? 0;
462
+ if (rem !== 0) {
463
+ // swap y volver a iterar para hacer Euclides en columna.
464
+ rowSwap(i, pivot);
465
+ changed = true;
466
+ break;
467
+ }
468
+ }
469
+ if (changed)
470
+ continue;
471
+ // Limpiar fila del pivote (derecha e izquierda).
472
+ const pivRow2 = A[pivot];
473
+ if (!pivRow2)
474
+ break;
475
+ const piv2 = pivRow2[pivot] ?? 0;
476
+ if (piv2 === 0)
477
+ break;
478
+ for (let j = 0; j < cols; j++) {
479
+ if (j === pivot)
480
+ continue;
481
+ const v = pivRow2[j] ?? 0;
482
+ if (v === 0)
483
+ continue;
484
+ const q = Math.trunc(v / piv2);
485
+ if (q !== 0) {
486
+ colAddMul(j, pivot, -q);
487
+ }
488
+ const rem = pivRow2[j] ?? 0;
489
+ if (rem !== 0) {
490
+ colSwap(j, pivot);
491
+ changed = true;
492
+ break;
493
+ }
494
+ }
495
+ if (changed)
496
+ continue;
497
+ // 3) Asegurar que el pivote divide a todas las entradas restantes.
498
+ // Si no, sumar la fila ofensiva al pivote para reducir el pivote
499
+ // a un gcd más chico y volver a iterar.
500
+ const pivVal = A[pivot]?.[pivot] ?? 0;
501
+ if (pivVal === 0)
502
+ break;
503
+ const absPiv = Math.abs(pivVal);
504
+ let divides = true;
505
+ outer: for (let i = pivot + 1; i < rows; i++) {
506
+ const row = A[i];
507
+ if (!row)
508
+ continue;
509
+ for (let j = pivot + 1; j < cols; j++) {
510
+ const v = row[j] ?? 0;
511
+ if (v !== 0 && v % absPiv !== 0) {
512
+ // Llevar esa fila a la del pivote y reiniciar.
513
+ rowAddMul(pivot, i, 1);
514
+ divides = false;
515
+ break outer;
516
+ }
517
+ }
518
+ }
519
+ if (!divides) {
520
+ changed = true;
521
+ continue;
522
+ }
523
+ }
524
+ // Asegurar signo no negativo del pivote (convención positiva).
525
+ const pivVal = A[pivot]?.[pivot] ?? 0;
526
+ if (pivVal < 0)
527
+ rowMulNeg(pivot);
528
+ pivot++;
529
+ }
530
+ // Recoger factores invariantes en la diagonal.
531
+ const invariants = [];
532
+ const limit = Math.min(rows, cols);
533
+ for (let i = 0; i < limit; i++) {
534
+ const v = A[i]?.[i] ?? 0;
535
+ if (v !== 0)
536
+ invariants.push(Math.abs(v));
537
+ }
538
+ // Por construcción ya quedan en orden de divisibilidad creciente,
539
+ // pero re-canonicalizamos: sort y luego ajustamos divisibilidad si
540
+ // fuera necesario (no debería).
541
+ invariants.sort((a, b) => a - b);
542
+ // Asegurar divisibilidad d_i | d_{i+1}. Si no, "propagar" via gcd/lcm
543
+ // — caso raro, pero blindamos.
544
+ for (let i = 0; i < invariants.length - 1; i++) {
545
+ const a = invariants[i] ?? 0;
546
+ const b = invariants[i + 1] ?? 0;
547
+ const g = absGcd(a, b);
548
+ if (g !== a) {
549
+ const l = (a * b) / g;
550
+ invariants[i] = g;
551
+ invariants[i + 1] = l;
552
+ }
553
+ }
554
+ return {
555
+ snf: A,
556
+ rankIm: invariants.length,
557
+ rankKer: cols - invariants.length,
558
+ invariants,
559
+ };
560
+ }
561
+ // ------------------------------------------------------------
562
+ // Homología sobre Z
563
+ // ------------------------------------------------------------
564
+ // β_d = rank ker ∂_d - rank im ∂_{d+1} (sobre Z, dimensión libre de la
565
+ // homología, equivalente a contar copias de Z en H_d).
566
+ function bettiNumberZ(K, dim) {
567
+ if (dim < 0)
568
+ return 0;
569
+ const nd = K.simplices.get(dim)?.size ?? 0;
570
+ const Md = boundaryMatrixZ(K, dim);
571
+ const Md1 = boundaryMatrixZ(K, dim + 1);
572
+ const rankD = Md.length === 0 ? 0 : smithNormalForm(Md).rankIm;
573
+ const rankD1 = Md1.length === 0 ? 0 : smithNormalForm(Md1).rankIm;
574
+ // ker ∂_d = nd - rankD
575
+ return nd - rankD - rankD1;
576
+ }
577
+ // Factores invariantes (>1) de la torsión de H_d sobre Z:
578
+ // H_d = Z^{β_d} ⊕ ⊕_i Z/d_i, con d_1 | d_2 | ... | d_k, d_i > 1.
579
+ // Los factores vienen de los invariantes de ∂_{d+1} que son >1.
580
+ function torsionZ(K, dim) {
581
+ if (dim < 0)
582
+ return [];
583
+ const M = boundaryMatrixZ(K, dim + 1);
584
+ if (M.length === 0)
585
+ return [];
586
+ const { invariants } = smithNormalForm(M);
587
+ return invariants.filter((d) => d > 1);
588
+ }
589
+ // ------------------------------------------------------------
590
+ // Complejos estándar
591
+ // ------------------------------------------------------------
592
+ // Complejo del n-simplex completo: todos los subconjuntos de {0,...,n}.
593
+ // `nSimplex(2)` da un triángulo con su 2-cara rellena (no la frontera).
594
+ function nSimplex(n) {
595
+ const K = makeComplex();
596
+ if (n < 0)
597
+ return K;
598
+ const verts = [];
599
+ for (let i = 0; i <= n; i++)
600
+ verts.push(i);
601
+ addSimplex(K, verts);
602
+ return K;
603
+ }
604
+ // Frontera del (n+1)-simplex = triangulación canónica de S^n.
605
+ // `spheres(2)` = borde del tetraedro = 4 vértices, 6 aristas, 4 triángulos.
606
+ function spheres(n) {
607
+ const K = makeComplex();
608
+ if (n < 0) {
609
+ // S^{-1} = ∅ por convención de algunos textos; aquí devolvemos vacío.
610
+ return K;
611
+ }
612
+ // Vértices 0..n+1.
613
+ const verts = [];
614
+ for (let i = 0; i <= n + 1; i++)
615
+ verts.push(i);
616
+ // Añadir todos los subsimplices de tamaño n+1 (es decir, dimensión n).
617
+ // Cada uno es el complemento de un vértice.
618
+ for (let omit = 0; omit < verts.length; omit++) {
619
+ const face = verts.filter((_, i) => i !== omit);
620
+ addSimplex(K, face);
621
+ }
622
+ return K;
623
+ }
624
+ // Triangulación del toro T² basada en un cuadrado 3×3 con identificaciones
625
+ // opuestas estándar (a b a⁻¹ b⁻¹). 9 vértices etiquetados como (i,j) con
626
+ // i,j ∈ {0,1,2}, identificando (3,j) ≡ (0,j) y (i,3) ≡ (i,0). Cada celda
627
+ // 1×1 se divide en 2 triángulos por la diagonal (i,j)-(i+1,j+1).
628
+ //
629
+ // Resultado: 9 vértices, 27 aristas, 18 triángulos.
630
+ // χ = 9 - 27 + 18 = 0, β = [1,2,1].
631
+ function torus2() {
632
+ const K = makeComplex();
633
+ // Mapeo (i, j) ∈ Z₃ × Z₃ → índice 3*i + j ∈ {0..8}
634
+ const v = (i, j) => 3 * (((i % 3) + 3) % 3) + (((j % 3) + 3) % 3);
635
+ for (let i = 0; i < 3; i++) {
636
+ for (let j = 0; j < 3; j++) {
637
+ const a = v(i, j);
638
+ const b = v(i + 1, j);
639
+ const c = v(i, j + 1);
640
+ const d = v(i + 1, j + 1);
641
+ // Dos triángulos por celda: (a,b,d) y (a,d,c).
642
+ addSimplex(K, [a, b, d]);
643
+ addSimplex(K, [a, d, c]);
644
+ }
645
+ }
646
+ return K;
647
+ }
648
+ // Triangulación mínima del plano proyectivo real RP² (6 vértices,
649
+ // 15 aristas, 10 triángulos). Esta es la triangulación canónica del
650
+ // hemisferio con identificación antipodal del ecuador.
651
+ function projectivePlane() {
652
+ const K = makeComplex();
653
+ const triangles = [
654
+ [0, 1, 2],
655
+ [0, 2, 3],
656
+ [0, 3, 4],
657
+ [0, 4, 5],
658
+ [0, 1, 5],
659
+ [1, 2, 4],
660
+ [2, 3, 5],
661
+ [1, 3, 4],
662
+ [1, 3, 5],
663
+ [2, 4, 5],
664
+ ];
665
+ for (const t of triangles)
666
+ addSimplex(K, t);
667
+ return K;
668
+ }
669
+ // Triangulación de la botella de Klein como cuadrado 3×3 con
670
+ // identificaciones (a b a b⁻¹): bordes horizontales pegan en paralelo,
671
+ // bordes verticales pegan con flip. Concretamente:
672
+ // (i, 3) ≡ (i, 0) (horizontal sin twist)
673
+ // (3, j) ≡ (0, 2 - j) (vertical con twist)
674
+ // Cada celda 1×1 dividida en 2 triángulos.
675
+ //
676
+ // Resultado: 9 vértices, χ = 0, β_Z = [1,1,0], torsión Z/2 en dim 1.
677
+ function kleinBottle() {
678
+ const K = makeComplex();
679
+ // v(i, j) representa el vértice (i mod 3, j mod 3) con flip al cruzar
680
+ // la dirección i: (3, j) ↦ (0, 2 - j).
681
+ const v = (i, j) => {
682
+ let ii = i;
683
+ let jj = j;
684
+ // Reducir i a [0,3): cada vez que i cruza el borde superior,
685
+ // se invierte la coordenada j (flip).
686
+ while (ii >= 3) {
687
+ ii -= 3;
688
+ jj = 2 - jj;
689
+ }
690
+ while (ii < 0) {
691
+ ii += 3;
692
+ jj = 2 - jj;
693
+ }
694
+ jj = ((jj % 3) + 3) % 3;
695
+ return 3 * ii + jj;
696
+ };
697
+ for (let i = 0; i < 3; i++) {
698
+ for (let j = 0; j < 3; j++) {
699
+ const a = v(i, j);
700
+ const b = v(i + 1, j);
701
+ const c = v(i, j + 1);
702
+ const d = v(i + 1, j + 1);
703
+ addSimplex(K, [a, b, d]);
704
+ addSimplex(K, [a, d, c]);
705
+ }
706
+ }
707
+ return K;
708
+ }
709
+ // ------------------------------------------------------------
710
+ // Cómputo completo de homología
711
+ // ------------------------------------------------------------
712
+ function computeHomology(K, coefficients = 'Z2') {
713
+ const d = K.dim;
714
+ const bettiNumbers = [];
715
+ if (coefficients === 'Z2') {
716
+ for (let i = 0; i <= d; i++)
717
+ bettiNumbers.push(bettiNumberZ2(K, i));
718
+ return {
719
+ dim: d,
720
+ bettiNumbers,
721
+ eulerChar: eulerCharacteristic(K),
722
+ };
723
+ }
724
+ // Z
725
+ const torsion = {};
726
+ for (let i = 0; i <= d; i++) {
727
+ bettiNumbers.push(bettiNumberZ(K, i));
728
+ const t = torsionZ(K, i);
729
+ if (t.length > 0)
730
+ torsion[i] = t;
731
+ }
732
+ return {
733
+ dim: d,
734
+ bettiNumbers,
735
+ eulerChar: eulerCharacteristic(K),
736
+ torsion,
737
+ };
738
+ }
739
+ //# sourceMappingURL=index.js.map