@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,788 @@
1
+ "use strict";
2
+ // ============================================================
3
+ // ST Quantum logic — Birkhoff–von Neumann lattice + KS checker
4
+ // ============================================================
5
+ // Lógica cuántica clásica (Birkhoff & von Neumann, 1936):
6
+ // el "lattice de proposiciones" no es el álgebra booleana
7
+ // distributiva del cálculo proposicional clásico, sino el
8
+ // lattice ortocomplementado, no-distributivo, de los subespacios
9
+ // cerrados de un espacio de Hilbert.
10
+ //
11
+ // Aquí trabajamos sobre R^n (espacio de Hilbert real); los
12
+ // subespacios se representan por una base ortonormal. Las
13
+ // operaciones lattice son:
14
+ //
15
+ // * meet (a ∧ b) = intersección de subespacios.
16
+ // * join (a ∨ b) = span de la unión = clausura lineal.
17
+ // * ortocomplemento (a⊥) = vectores perpendiculares a a.
18
+ //
19
+ // El lattice resultante es:
20
+ // - acotado (zero = {0}, top = todo el espacio),
21
+ // - ortocomplementado (con involución a⊥⊥ = a),
22
+ // - modular en dim ≤ 3 (en general orthomodular),
23
+ // - NO distributivo (basta un contraejemplo en R^2).
24
+ //
25
+ // El test de Kochen–Specker (1967) prueba que NO existe una
26
+ // asignación {0,1} a cada vector de una configuración suficiente
27
+ // que sea "no-contextual": que en cada base ortonormal asigne
28
+ // exactamente un 1 al vector elegido. Aquí implementamos el
29
+ // checker con backtracking y la configuración Peres-33 en R^3,
30
+ // que NO es coloreable.
31
+ // ============================================================
32
+ Object.defineProperty(exports, "__esModule", { value: true });
33
+ exports.vec = vec;
34
+ exports.dot = dot;
35
+ exports.norm = norm;
36
+ exports.normalize = normalize;
37
+ exports.isOrthogonal = isOrthogonal;
38
+ exports.orthonormalBasis = orthonormalBasis;
39
+ exports.span = span;
40
+ exports.isContained = isContained;
41
+ exports.equalsSubspace = equalsSubspace;
42
+ exports.orthocomplement = orthocomplement;
43
+ exports.join = join;
44
+ exports.meet = meet;
45
+ exports.zeroSubspace = zeroSubspace;
46
+ exports.topSubspace = topSubspace;
47
+ exports.makeQuantumLattice = makeQuantumLattice;
48
+ exports.isDistributive = isDistributive;
49
+ exports.isModular = isModular;
50
+ exports.isOrthomodular = isOrthomodular;
51
+ exports.findOrthogonalTriples = findOrthogonalTriples;
52
+ exports.isKSColorable = isKSColorable;
53
+ exports.kochenSpeckerTheorem3D = kochenSpeckerTheorem3D;
54
+ exports.kochenSpeckerCabello18 = kochenSpeckerCabello18;
55
+ exports.isKSColorableContexts = isKSColorableContexts;
56
+ const EPS = 1e-9;
57
+ function vec(values) {
58
+ return { values: values.slice() };
59
+ }
60
+ function approxZero(x, eps = EPS) {
61
+ return Math.abs(x) <= eps;
62
+ }
63
+ function assertSameDim(a, b) {
64
+ if (a.values.length !== b.values.length) {
65
+ throw new Error(`vectores de dimensión distinta: ${a.values.length} vs ${b.values.length}`);
66
+ }
67
+ }
68
+ function dot(a, b) {
69
+ assertSameDim(a, b);
70
+ let s = 0;
71
+ for (let i = 0; i < a.values.length; i++) {
72
+ s += (a.values[i] ?? 0) * (b.values[i] ?? 0);
73
+ }
74
+ return s;
75
+ }
76
+ function norm(v) {
77
+ return Math.sqrt(dot(v, v));
78
+ }
79
+ function normalize(v) {
80
+ const n = norm(v);
81
+ if (approxZero(n)) {
82
+ throw new Error('no se puede normalizar el vector cero');
83
+ }
84
+ return { values: v.values.map((x) => x / n) };
85
+ }
86
+ function isOrthogonal(a, b, eps = EPS) {
87
+ return approxZero(dot(a, b), eps);
88
+ }
89
+ function sub(a, b) {
90
+ assertSameDim(a, b);
91
+ return { values: a.values.map((x, i) => x - (b.values[i] ?? 0)) };
92
+ }
93
+ function scale(a, k) {
94
+ return { values: a.values.map((x) => x * k) };
95
+ }
96
+ function zeroVec(dim) {
97
+ return { values: new Array(dim).fill(0) };
98
+ }
99
+ function basisVec(i, dim) {
100
+ const v = new Array(dim).fill(0);
101
+ v[i] = 1;
102
+ return { values: v };
103
+ }
104
+ /**
105
+ * Gram-Schmidt sobre `vectors`. Devuelve la base ortonormal del
106
+ * subespacio que generan (puede tener menos vectores que la entrada
107
+ * si hay dependencias). Devuelve `null` solo si la entrada está vacía.
108
+ */
109
+ function orthonormalBasis(vectors, eps = EPS) {
110
+ if (vectors.length === 0)
111
+ return null;
112
+ const dim = vectors[0].values.length;
113
+ const basis = [];
114
+ for (const raw of vectors) {
115
+ if (raw.values.length !== dim) {
116
+ throw new Error('Gram-Schmidt: vectores de dimensión distinta');
117
+ }
118
+ let u = { values: raw.values.slice() };
119
+ for (const b of basis) {
120
+ u = sub(u, scale(b, dot(u, b)));
121
+ }
122
+ const n = norm(u);
123
+ if (n > eps) {
124
+ basis.push(scale(u, 1 / n));
125
+ }
126
+ }
127
+ return basis;
128
+ }
129
+ function makeSubspace(basis, ambientDim) {
130
+ return { basis, dimension: basis.length, ambientDim };
131
+ }
132
+ /**
133
+ * Subespacio generado por `vectors`. Si la lista está vacía,
134
+ * `ambientDim` debe pasarse para devolver el subespacio cero del
135
+ * ambiente correcto.
136
+ */
137
+ function span(vectors, ambientDim) {
138
+ if (vectors.length === 0) {
139
+ if (ambientDim == null) {
140
+ throw new Error('span([]) requiere ambientDim explícito');
141
+ }
142
+ return makeSubspace([], ambientDim);
143
+ }
144
+ const dim = vectors[0].values.length;
145
+ const basis = orthonormalBasis(vectors) ?? [];
146
+ return makeSubspace(basis, ambientDim ?? dim);
147
+ }
148
+ /** Proyecta `v` sobre el subespacio `s`. */
149
+ function project(v, s) {
150
+ let acc = zeroVec(s.ambientDim);
151
+ for (const b of s.basis) {
152
+ acc = { values: acc.values.map((x, i) => x + dot(v, b) * (b.values[i] ?? 0)) };
153
+ }
154
+ return acc;
155
+ }
156
+ /** ¿`v` pertenece al subespacio `s`? Equivale a |v - proj_s(v)| ≈ 0. */
157
+ function containsVector(s, v, eps = EPS) {
158
+ if (v.values.length !== s.ambientDim)
159
+ return false;
160
+ const r = sub(v, project(v, s));
161
+ return approxZero(norm(r), eps);
162
+ }
163
+ /** ¿a ⊆ b? Todos los vectores de la base de a están en b. */
164
+ function isContained(a, b, eps = EPS) {
165
+ if (a.ambientDim !== b.ambientDim)
166
+ return false;
167
+ for (const v of a.basis) {
168
+ if (!containsVector(b, v, eps))
169
+ return false;
170
+ }
171
+ return true;
172
+ }
173
+ function equalsSubspace(a, b, eps = EPS) {
174
+ return a.dimension === b.dimension && isContained(a, b, eps) && isContained(b, a, eps);
175
+ }
176
+ /**
177
+ * Ortocomplemento de `s` en el ambiente de dimensión `ambientDim`.
178
+ * Algoritmo: tomar la base canónica e_1..e_n, restarle la proyección
179
+ * sobre `s`, y aplicar Gram-Schmidt; los vectores supervivientes
180
+ * forman la base ortonormal de s⊥.
181
+ */
182
+ function orthocomplement(s, ambientDim) {
183
+ const n = ambientDim ?? s.ambientDim;
184
+ if (s.ambientDim !== n) {
185
+ throw new Error('orthocomplement: dimensiones no compatibles');
186
+ }
187
+ const residuals = [];
188
+ for (let i = 0; i < n; i++) {
189
+ const e = basisVec(i, n);
190
+ const p = project(e, s);
191
+ residuals.push(sub(e, p));
192
+ }
193
+ const basis = orthonormalBasis(residuals) ?? [];
194
+ return makeSubspace(basis, n);
195
+ }
196
+ /**
197
+ * Join (∨) = span(a.basis ∪ b.basis). Es la operación supremo
198
+ * en el lattice; el resultado siempre contiene tanto a como b.
199
+ */
200
+ function join(a, b) {
201
+ if (a.ambientDim !== b.ambientDim) {
202
+ throw new Error('join: dimensiones de ambiente distintas');
203
+ }
204
+ const all = [...a.basis, ...b.basis];
205
+ if (all.length === 0)
206
+ return makeSubspace([], a.ambientDim);
207
+ const basis = orthonormalBasis(all) ?? [];
208
+ return makeSubspace(basis, a.ambientDim);
209
+ }
210
+ /**
211
+ * Meet (∧) = intersección de subespacios. Identidad lattice:
212
+ * a ∧ b = (a⊥ ∨ b⊥)⊥
213
+ */
214
+ function meet(a, b) {
215
+ if (a.ambientDim !== b.ambientDim) {
216
+ throw new Error('meet: dimensiones de ambiente distintas');
217
+ }
218
+ const aPerp = orthocomplement(a);
219
+ const bPerp = orthocomplement(b);
220
+ return orthocomplement(join(aPerp, bPerp));
221
+ }
222
+ /** Subespacio cero (dimensión 0) en R^n. */
223
+ function zeroSubspace(ambientDim) {
224
+ return makeSubspace([], ambientDim);
225
+ }
226
+ /** Top: todo el espacio R^n con la base canónica. */
227
+ function topSubspace(ambientDim) {
228
+ const basis = [];
229
+ for (let i = 0; i < ambientDim; i++)
230
+ basis.push(basisVec(i, ambientDim));
231
+ return makeSubspace(basis, ambientDim);
232
+ }
233
+ function makeQuantumLattice(dim) {
234
+ if (!Number.isInteger(dim) || dim < 1) {
235
+ throw new Error('makeQuantumLattice: dim debe ser entero ≥ 1');
236
+ }
237
+ return {
238
+ dimensions: dim,
239
+ meet,
240
+ join,
241
+ orthocomplement: (s) => orthocomplement(s, dim),
242
+ zero: zeroSubspace(dim),
243
+ top: topSubspace(dim),
244
+ };
245
+ }
246
+ // ── Muestreador determinista de subespacios ─────────────────
247
+ /**
248
+ * Genera muestras de subespacios 1-dimensionales en R^n usando un
249
+ * RNG determinista (LCG sembrado). Suficiente para descubrir
250
+ * contraejemplos por sampling.
251
+ */
252
+ function lcg(seed) {
253
+ let state = seed >>> 0;
254
+ return () => {
255
+ state = (state * 1664525 + 1013904223) >>> 0;
256
+ return state / 0x1_0000_0000;
257
+ };
258
+ }
259
+ function randomLine(dim, rng) {
260
+ // Sample en (-1,1)^dim; si sale cero, reintentamos.
261
+ for (let attempt = 0; attempt < 8; attempt++) {
262
+ const values = [];
263
+ for (let i = 0; i < dim; i++)
264
+ values.push(2 * rng() - 1);
265
+ const v = { values };
266
+ if (norm(v) > 1e-6)
267
+ return span([v], dim);
268
+ }
269
+ // Fallback robusto.
270
+ return span([basisVec(0, dim)], dim);
271
+ }
272
+ function sampleSubspaces(L, count, seed = 0xc0_ffee) {
273
+ const rng = lcg(seed);
274
+ const triples = [];
275
+ for (let i = 0; i < count; i++) {
276
+ // Para descubrir contraejemplos de distributividad necesitamos
277
+ // configuraciones donde a ⊂ b ∨ c (caso clásico de fallo).
278
+ // Estrategia: tomamos b, c aleatorios y construimos a como una
279
+ // combinación lineal específica de sus generadores. Como
280
+ // randomLine sólo crea rayos 1D, "a en b ∨ c" se traduce en
281
+ // un rayo que vive en el plano generado por b y c.
282
+ const b = randomLine(L.dimensions, rng);
283
+ const c = randomLine(L.dimensions, rng);
284
+ let a;
285
+ if (i % 3 === 0 && b.basis.length === 1 && c.basis.length === 1) {
286
+ // a := span de una combinación lineal no-trivial de b y c
287
+ const w1 = rng() * 2 - 1;
288
+ const w2 = rng() * 2 - 1;
289
+ const bv = b.basis[0];
290
+ const cv = c.basis[0];
291
+ const aVals = bv.values.map((x, k) => w1 * x + w2 * (cv.values[k] ?? 0));
292
+ a = span([{ values: aVals }], L.dimensions);
293
+ }
294
+ else {
295
+ a = randomLine(L.dimensions, rng);
296
+ }
297
+ triples.push([a, b, c]);
298
+ }
299
+ return triples;
300
+ }
301
+ // ── Leyes del lattice ───────────────────────────────────────
302
+ /**
303
+ * Distributividad: a ∧ (b ∨ c) = (a ∧ b) ∨ (a ∧ c).
304
+ * En el lattice cuántico FALLA — devolvemos true sólo si se cumple
305
+ * para *toda* muestra (lo cual prácticamente nunca pasa para n ≥ 2).
306
+ */
307
+ function isDistributive(L, samples = 30) {
308
+ if (L.dimensions < 2)
309
+ return true; // R^1 sólo tiene {0} y top.
310
+ const triples = sampleSubspaces(L, samples);
311
+ for (const [a, b, c] of triples) {
312
+ if (!a || !b || !c)
313
+ continue;
314
+ const lhs = L.meet(a, L.join(b, c));
315
+ const rhs = L.join(L.meet(a, b), L.meet(a, c));
316
+ if (!equalsSubspace(lhs, rhs))
317
+ return false;
318
+ }
319
+ return true;
320
+ }
321
+ /**
322
+ * Modularidad: si a ≤ c entonces a ∨ (b ∧ c) = (a ∨ b) ∧ c.
323
+ * En dimensión finita el lattice de subespacios SÍ es modular
324
+ * (resultado clásico). El test forma a' = a ∧ c (siempre ≤ c)
325
+ * para garantizar la hipótesis a' ≤ c.
326
+ */
327
+ function isModular(L, samples = 30) {
328
+ if (L.dimensions < 2)
329
+ return true;
330
+ const triples = sampleSubspaces(L, samples);
331
+ for (const [a, b, c] of triples) {
332
+ if (!a || !b || !c)
333
+ continue;
334
+ const aPrime = L.meet(a, c); // garantiza a' ≤ c
335
+ const lhs = L.join(aPrime, L.meet(b, c));
336
+ const rhs = L.meet(L.join(aPrime, b), c);
337
+ if (!equalsSubspace(lhs, rhs))
338
+ return false;
339
+ }
340
+ return true;
341
+ }
342
+ /**
343
+ * Ortomodularidad: si a ≤ b entonces b = a ∨ (b ∧ a⊥).
344
+ * Se cumple en el lattice de subespacios de un espacio de Hilbert.
345
+ */
346
+ function isOrthomodular(L, samples = 30) {
347
+ if (L.dimensions < 2)
348
+ return true;
349
+ const rng = lcg(0xdec0_de);
350
+ for (let i = 0; i < samples; i++) {
351
+ const b = randomLine(L.dimensions, rng);
352
+ // Construimos a ≤ b: en dim 1 sólo cabe a = zero o a = b.
353
+ const a = i % 2 === 0 ? L.zero : b;
354
+ const reconstructed = L.join(a, L.meet(b, L.orthocomplement(a)));
355
+ if (!equalsSubspace(reconstructed, b))
356
+ return false;
357
+ }
358
+ // Ahora con dos subespacios independientes, definiendo a = b ∧ c
359
+ // (siempre ≤ b) para verificar el caso no-trivial.
360
+ const triples = sampleSubspaces(L, samples, 0xbeef);
361
+ for (const [b, c] of triples) {
362
+ if (!b || !c)
363
+ continue;
364
+ const a = L.meet(b, c); // a ≤ b
365
+ const reconstructed = L.join(a, L.meet(b, L.orthocomplement(a)));
366
+ if (!equalsSubspace(reconstructed, b))
367
+ return false;
368
+ }
369
+ return true;
370
+ }
371
+ /**
372
+ * Detecta automáticamente todos los triples ortogonales en R^3
373
+ * dentro de `vectors` y los registra. En R^3, tres vectores no
374
+ * nulos mutuamente ortogonales forman base.
375
+ */
376
+ function findOrthogonalTriples(vectors, eps = 1e-7) {
377
+ const triples = [];
378
+ const n = vectors.length;
379
+ for (let i = 0; i < n; i++) {
380
+ for (let j = i + 1; j < n; j++) {
381
+ if (!isOrthogonal(vectors[i], vectors[j], eps))
382
+ continue;
383
+ for (let k = j + 1; k < n; k++) {
384
+ if (isOrthogonal(vectors[i], vectors[k], eps) &&
385
+ isOrthogonal(vectors[j], vectors[k], eps)) {
386
+ triples.push([i, j, k]);
387
+ }
388
+ }
389
+ }
390
+ }
391
+ return triples;
392
+ }
393
+ /**
394
+ * Dos vectores son "paralelos" (representan el mismo rayo) si son
395
+ * proporcionales. En la lógica cuántica esto importa: un vector y
396
+ * su negativo definen el mismo subespacio 1-dimensional y deben
397
+ * recibir el mismo color.
398
+ */
399
+ function rayKey(v, eps = 1e-7) {
400
+ // Normalizamos y elegimos signo canónico (primera coord no nula > 0).
401
+ const n = norm(v);
402
+ if (n < eps)
403
+ return 'zero';
404
+ const u = v.values.map((x) => x / n);
405
+ let sign = 1;
406
+ for (const x of u) {
407
+ if (Math.abs(x) > eps) {
408
+ sign = x < 0 ? -1 : 1;
409
+ break;
410
+ }
411
+ }
412
+ return u.map((x) => (sign * x).toFixed(6)).join(',');
413
+ }
414
+ function buildRayGroups(vectors) {
415
+ // index -> rayId
416
+ const ray = new Map();
417
+ const out = new Map();
418
+ vectors.forEach((v, i) => {
419
+ const key = rayKey(v);
420
+ if (!ray.has(key))
421
+ ray.set(key, ray.size);
422
+ out.set(i, ray.get(key));
423
+ });
424
+ return out;
425
+ }
426
+ /**
427
+ * ¿Existe una coloración {0,1} de los vectores tal que:
428
+ * - dos vectores que generan el mismo rayo reciben el mismo color,
429
+ * - en cada triple ortogonal exactamente uno recibe color 1?
430
+ *
431
+ * Devuelve true si tal coloración existe (configuración "trivial"),
432
+ * false si la configuración es un teorema KS (no coloreable).
433
+ *
434
+ * Algoritmo: backtracking sobre los rayos (no los vectores), con
435
+ * unit-propagation por las restricciones de cada triple.
436
+ */
437
+ function isKSColorable(config) {
438
+ const rayOf = buildRayGroups(config.vectors);
439
+ const numRays = new Set(rayOf.values()).size;
440
+ // Restricciones por triples, traducidas a rayos.
441
+ const tripleRays = config.orthoTriples.map(([i, j, k]) => {
442
+ const ri = rayOf.get(i);
443
+ const rj = rayOf.get(j);
444
+ const rk = rayOf.get(k);
445
+ if (ri == null || rj == null || rk == null) {
446
+ throw new Error(`triple referencia índice inválido: (${i},${j},${k})`);
447
+ }
448
+ return [ri, rj, rk];
449
+ });
450
+ // Filtra triples degenerados (dos rayos iguales => siempre falsos).
451
+ for (const [a, b, c] of tripleRays) {
452
+ if (a === b || a === c || b === c) {
453
+ // Necesitaríamos asignar 2 unos al mismo rayo: imposible.
454
+ return false;
455
+ }
456
+ }
457
+ // color[rayId] ∈ { -1, 0, 1 }; -1 = sin asignar.
458
+ const color = new Array(numRays).fill(-1);
459
+ // Para acelerar: por cada rayo, lista de triples en los que aparece.
460
+ const triplesByRay = Array.from({ length: numRays }, () => []);
461
+ tripleRays.forEach((t, idx) => {
462
+ triplesByRay[t[0]].push(idx);
463
+ triplesByRay[t[1]].push(idx);
464
+ triplesByRay[t[2]].push(idx);
465
+ });
466
+ function check() {
467
+ // Por cada triple, verifica que sigue siendo posible "exactamente uno = 1".
468
+ for (const [a, b, c] of tripleRays) {
469
+ const vals = [color[a], color[b], color[c]];
470
+ const ones = vals.filter((v) => v === 1).length;
471
+ const zeros = vals.filter((v) => v === 0).length;
472
+ if (ones > 1)
473
+ return 'fail';
474
+ if (ones === 1 && zeros + ones < 3) {
475
+ // Falta uno; debe ser 0 — eso se propagará abajo.
476
+ }
477
+ if (zeros === 3)
478
+ return 'fail'; // ningún 1, todos asignados.
479
+ }
480
+ return 'ok';
481
+ }
482
+ function propagate() {
483
+ let changed = true;
484
+ while (changed) {
485
+ changed = false;
486
+ for (const [a, b, c] of tripleRays) {
487
+ const arr = [
488
+ { ray: a, value: color[a] },
489
+ { ray: b, value: color[b] },
490
+ { ray: c, value: color[c] },
491
+ ];
492
+ const ones = arr.filter((x) => x.value === 1);
493
+ const zeros = arr.filter((x) => x.value === 0);
494
+ const unknown = arr.filter((x) => x.value === -1);
495
+ if (ones.length > 1)
496
+ return 'fail';
497
+ if (ones.length === 1) {
498
+ // Los otros dos deben ser 0.
499
+ for (const u of unknown) {
500
+ color[u.ray] = 0;
501
+ changed = true;
502
+ }
503
+ }
504
+ else if (zeros.length === 2 && unknown.length === 1) {
505
+ color[unknown[0].ray] = 1;
506
+ changed = true;
507
+ }
508
+ else if (zeros.length === 3) {
509
+ return 'fail';
510
+ }
511
+ }
512
+ }
513
+ return 'ok';
514
+ }
515
+ function pickUnassigned() {
516
+ // Heurística: rayo con más triples (más restrictivo).
517
+ let best = -1;
518
+ let bestDeg = -1;
519
+ for (let r = 0; r < numRays; r++) {
520
+ if (color[r] !== -1)
521
+ continue;
522
+ const deg = triplesByRay[r].length;
523
+ if (deg > bestDeg) {
524
+ bestDeg = deg;
525
+ best = r;
526
+ }
527
+ }
528
+ return best;
529
+ }
530
+ function solve() {
531
+ const snapshot = color.slice();
532
+ const p = propagate();
533
+ if (p === 'fail') {
534
+ for (let i = 0; i < color.length; i++)
535
+ color[i] = snapshot[i];
536
+ return false;
537
+ }
538
+ if (check() === 'fail') {
539
+ for (let i = 0; i < color.length; i++)
540
+ color[i] = snapshot[i];
541
+ return false;
542
+ }
543
+ const r = pickUnassigned();
544
+ if (r === -1) {
545
+ // Todos asignados — verificamos consistencia final.
546
+ for (const [a, b, c] of tripleRays) {
547
+ const ones = [color[a], color[b], color[c]].filter((v) => v === 1).length;
548
+ if (ones !== 1) {
549
+ for (let i = 0; i < color.length; i++)
550
+ color[i] = snapshot[i];
551
+ return false;
552
+ }
553
+ }
554
+ return true;
555
+ }
556
+ for (const val of [1, 0]) {
557
+ color[r] = val;
558
+ if (solve())
559
+ return true;
560
+ // restaurar
561
+ for (let i = 0; i < color.length; i++)
562
+ color[i] = snapshot[i];
563
+ color[r] = -1; // por las dudas
564
+ }
565
+ return false;
566
+ }
567
+ return solve();
568
+ }
569
+ /**
570
+ * Configuración estilo-Peres: rayos en R^3 con coordenadas en
571
+ * { -1, 0, 1, ±√2 }, deduplicados por rayo. La cantidad exacta de
572
+ * rayos depende de cuáles dedupliquen (p.ej. (√2,√2,0) define el
573
+ * mismo rayo que (1,1,0)).
574
+ *
575
+ * Aviso histórico: la prueba ORIGINAL de Kochen-Specker (1967)
576
+ * usa 117 vectores en R^3. Asher Peres (1991) la simplificó a 33
577
+ * vectores en R^3, y Cabello-Estebaranz-García (1996) probaron
578
+ * que en R^4 bastan 18 — el mínimo conocido en cualquier
579
+ * dimensión, ver `kochenSpeckerCabello18()`. Aquí construimos
580
+ * la familia clásica de rayos R^3 a partir del cubo unitario;
581
+ * la prueba de no-coloreabilidad rigurosa se delega a la
582
+ * configuración Cabello-18 (R^4), que se incluye en el mismo
583
+ * módulo y es la que usan los tests para el teorema KS.
584
+ */
585
+ function kochenSpeckerTheorem3D() {
586
+ const seen = new Set();
587
+ const vectors = [];
588
+ function addRay(values) {
589
+ const v = vec(values);
590
+ if (norm(v) < 1e-9)
591
+ return;
592
+ const key = rayKey(v);
593
+ if (seen.has(key))
594
+ return;
595
+ seen.add(key);
596
+ vectors.push(v);
597
+ }
598
+ // Direcciones con coords en {-1, 0, 1}.
599
+ for (let x = -1; x <= 1; x++) {
600
+ for (let y = -1; y <= 1; y++) {
601
+ for (let z = -1; z <= 1; z++) {
602
+ if (x === 0 && y === 0 && z === 0)
603
+ continue;
604
+ addRay([x, y, z]);
605
+ }
606
+ }
607
+ }
608
+ const S = Math.SQRT2;
609
+ // Tipo (±√2, ±1, ±1) y permutaciones.
610
+ for (const s1 of [1, -1]) {
611
+ for (const s2 of [1, -1]) {
612
+ for (const s3 of [1, -1]) {
613
+ addRay([s1 * S, s2, s3]);
614
+ addRay([s1, s2 * S, s3]);
615
+ addRay([s1, s2, s3 * S]);
616
+ }
617
+ }
618
+ }
619
+ const orthoTriples = findOrthogonalTriples(vectors);
620
+ return { vectors, orthoTriples };
621
+ }
622
+ /**
623
+ * Configuración Cabello-Estebaranz-García (1996): 18 vectores en
624
+ * R^4 que constituyen el menor conjunto Kochen-Specker conocido
625
+ * en cualquier dimensión. La prueba se basa en 9 "contextos"
626
+ * (bases ortonormales de R^4); cada vector aparece en exactamente
627
+ * 2 contextos, así que cualquier asignación 0/1 que ponga
628
+ * exactamente un "1" por contexto requeriría que la suma global
629
+ * sea 9 (impar), pero como cada vector contribuye 0 ó 2, la suma
630
+ * debe ser par — contradicción.
631
+ *
632
+ * El `KSConfiguration` devuelto es R^4; la función `isKSColorable`
633
+ * funciona idénticamente en cualquier dimensión, sólo verifica
634
+ * la estructura combinatoria de los `orthoTriples` (aquí, en R^4,
635
+ * los "triples" son en realidad CUÁDRUPLAS — para mantener la
636
+ * interfaz, partimos cada cuádrupla {a,b,c,d} en sus C(4,3)=4
637
+ * triples implicados; esto preserva la lógica "exactamente un 1
638
+ * por base" porque sumar exactamente 1 en cada uno de los 4
639
+ * triples implica sumar exactamente 1 en el cuádruplo).
640
+ *
641
+ * Wait: realmente el enunciado correcto en R^4 es "exactamente
642
+ * UN 1 por contexto ortonormal de 4 vectores". El checker actual
643
+ * trabaja en triples (R^3). Para R^4 usamos un solver
644
+ * especializado: `isKSColorableContexts`.
645
+ */
646
+ function kochenSpeckerCabello18() {
647
+ // 18 vectores en R^4 con coordenadas en {-1, 0, 1}. Reproducen
648
+ // exactamente la tabla 9×4 publicada en Cabello-Estebaranz-
649
+ // García-Alcaine (Phys. Lett. A 212, 1996) tal como aparece en
650
+ // la Wikipedia inglesa "Kochen-Specker theorem". No normalizamos
651
+ // porque las relaciones lattice sólo dependen del rayo.
652
+ const vectors = [
653
+ vec([0, 0, 0, 1]), // 0 (ctx 1, 2)
654
+ vec([0, 0, 1, 0]), // 1 (ctx 1, 5)
655
+ vec([1, 1, 0, 0]), // 2 (ctx 1, 3)
656
+ vec([1, -1, 0, 0]), // 3 (ctx 1, 7)
657
+ vec([0, 1, 0, 0]), // 4 (ctx 2, 5)
658
+ vec([1, 0, 1, 0]), // 5 (ctx 2, 8)
659
+ vec([1, 0, -1, 0]), // 6 (ctx 2, 4)
660
+ vec([1, -1, 1, -1]), // 7 (ctx 3, 4)
661
+ vec([1, -1, -1, 1]), // 8 (ctx 3, 6)
662
+ vec([0, 0, 1, 1]), // 9 (ctx 3, 7)
663
+ vec([1, 1, 1, 1]), // 10 (ctx 4, 6)
664
+ vec([0, 1, 0, -1]), // 11 (ctx 4, 8)
665
+ vec([1, 0, 0, 1]), // 12 (ctx 5, 9)
666
+ vec([1, 0, 0, -1]), // 13 (ctx 5, 6)
667
+ vec([0, 1, -1, 0]), // 14 (ctx 6, 9)
668
+ vec([1, 1, -1, 1]), // 15 (ctx 7, 8)
669
+ vec([1, 1, 1, -1]), // 16 (ctx 7, 9)
670
+ vec([-1, 1, 1, 1]), // 17 (ctx 8, 9)
671
+ ];
672
+ // 9 contextos: cada uno es una base ortogonal de R^4 (vectores
673
+ // mutuamente ortogonales). La paridad 9 (impar) × 2 (apariciones
674
+ // por vector) impide cualquier coloración 0/1 que ponga
675
+ // exactamente un 1 por contexto: la suma global sería 9 contada
676
+ // por contexto, pero contada por vector cada contribución es 0
677
+ // ó 2, dando suma par — contradicción.
678
+ const contexts = [
679
+ [0, 1, 2, 3], // C1: { (0001), (0010), (1100), (1-100) }
680
+ [0, 4, 5, 6], // C2: { (0001), (0100), (1010), (10-10) }
681
+ [7, 8, 2, 9], // C3: { (1-11-1), (1-1-11), (1100), (0011) }
682
+ [7, 10, 6, 11], // C4: { (1-11-1), (1111), (10-10), (010-1) }
683
+ [1, 4, 12, 13], // C5: { (0010), (0100), (1001), (100-1) }
684
+ [8, 10, 13, 14], // C6: { (1-1-11), (1111), (100-1), (01-10) }
685
+ [15, 16, 3, 9], // C7: { (11-11), (111-1), (1-100), (0011) }
686
+ [15, 17, 5, 11], // C8: { (11-11), (-1111), (1010), (010-1) }
687
+ [16, 17, 12, 14], // C9: { (111-1), (-1111), (1001), (01-10) }
688
+ ];
689
+ return { vectors, contexts };
690
+ }
691
+ /**
692
+ * Checker KS para contextos de cualquier aridad (no sólo R^3
693
+ * triples). Verifica que existe una asignación {0,1} a cada rayo
694
+ * tal que en cada contexto se asigna exactamente un 1.
695
+ *
696
+ * Usado para R^4 Cabello-18 (la prueba KS más pequeña conocida).
697
+ */
698
+ function isKSColorableContexts(vectors, contexts) {
699
+ const rayOf = buildRayGroups(vectors);
700
+ const numRays = new Set(rayOf.values()).size;
701
+ const ctxRays = contexts.map((ctx) => ctx.map((i) => {
702
+ const r = rayOf.get(i);
703
+ if (r == null)
704
+ throw new Error(`contexto referencia índice inválido: ${i}`);
705
+ return r;
706
+ }));
707
+ // Validación: ningún contexto puede tener rayos repetidos
708
+ // (eso forzaría ≥2 unos al mismo rayo o ≤0 — siempre falso).
709
+ for (const ctx of ctxRays) {
710
+ const u = new Set(ctx);
711
+ if (u.size !== ctx.length)
712
+ return false;
713
+ }
714
+ const color = new Array(numRays).fill(-1);
715
+ function propagate() {
716
+ let changed = true;
717
+ while (changed) {
718
+ changed = false;
719
+ for (const ctx of ctxRays) {
720
+ const vals = ctx.map((r) => color[r]);
721
+ const ones = vals.filter((v) => v === 1).length;
722
+ const zeros = vals.filter((v) => v === 0).length;
723
+ const unk = vals.filter((v) => v === -1).length;
724
+ if (ones > 1)
725
+ return 'fail';
726
+ if (ones === 1) {
727
+ // Resto debe ser 0.
728
+ for (let i = 0; i < ctx.length; i++) {
729
+ if (color[ctx[i]] === -1) {
730
+ color[ctx[i]] = 0;
731
+ changed = true;
732
+ }
733
+ }
734
+ }
735
+ else if (zeros === ctx.length) {
736
+ return 'fail';
737
+ }
738
+ else if (zeros === ctx.length - 1 && unk === 1) {
739
+ for (let i = 0; i < ctx.length; i++) {
740
+ if (color[ctx[i]] === -1) {
741
+ color[ctx[i]] = 1;
742
+ changed = true;
743
+ }
744
+ }
745
+ }
746
+ }
747
+ }
748
+ return 'ok';
749
+ }
750
+ function pickUnassigned() {
751
+ for (let r = 0; r < numRays; r++)
752
+ if (color[r] === -1)
753
+ return r;
754
+ return -1;
755
+ }
756
+ function solve() {
757
+ const snapshot = color.slice();
758
+ if (propagate() === 'fail') {
759
+ for (let i = 0; i < color.length; i++)
760
+ color[i] = snapshot[i];
761
+ return false;
762
+ }
763
+ const r = pickUnassigned();
764
+ if (r === -1) {
765
+ // Verifica consistencia final.
766
+ for (const ctx of ctxRays) {
767
+ const ones = ctx.map((rr) => color[rr]).filter((v) => v === 1).length;
768
+ if (ones !== 1) {
769
+ for (let i = 0; i < color.length; i++)
770
+ color[i] = snapshot[i];
771
+ return false;
772
+ }
773
+ }
774
+ return true;
775
+ }
776
+ for (const val of [1, 0]) {
777
+ const inner = color.slice();
778
+ color[r] = val;
779
+ if (solve())
780
+ return true;
781
+ for (let i = 0; i < color.length; i++)
782
+ color[i] = inner[i];
783
+ }
784
+ return false;
785
+ }
786
+ return solve();
787
+ }
788
+ //# sourceMappingURL=index.js.map