@stevenvo780/st-lang 4.7.0 → 4.9.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.
- package/dist/logic/profiles/quantum/index.d.ts +153 -0
- package/dist/logic/profiles/quantum/index.d.ts.map +1 -0
- package/dist/logic/profiles/quantum/index.js +788 -0
- package/dist/logic/profiles/quantum/index.js.map +1 -0
- package/dist/namespaces/reasoning.d.ts +3 -1
- package/dist/namespaces/reasoning.d.ts.map +1 -1
- package/dist/namespaces/reasoning.js +5 -1
- package/dist/namespaces/reasoning.js.map +1 -1
- package/dist/proof-systems/certificate/canonical.d.ts +18 -0
- package/dist/proof-systems/certificate/canonical.d.ts.map +1 -0
- package/dist/proof-systems/certificate/canonical.js +79 -0
- package/dist/proof-systems/certificate/canonical.js.map +1 -0
- package/dist/proof-systems/certificate/generate.d.ts +39 -0
- package/dist/proof-systems/certificate/generate.d.ts.map +1 -0
- package/dist/proof-systems/certificate/generate.js +259 -0
- package/dist/proof-systems/certificate/generate.js.map +1 -0
- package/dist/proof-systems/certificate/index.d.ts +7 -0
- package/dist/proof-systems/certificate/index.d.ts.map +1 -0
- package/dist/proof-systems/certificate/index.js +23 -0
- package/dist/proof-systems/certificate/index.js.map +1 -0
- package/dist/proof-systems/certificate/lfsc.d.ts +15 -0
- package/dist/proof-systems/certificate/lfsc.d.ts.map +1 -0
- package/dist/proof-systems/certificate/lfsc.js +395 -0
- package/dist/proof-systems/certificate/lfsc.js.map +1 -0
- package/dist/proof-systems/certificate/rules.d.ts +8 -0
- package/dist/proof-systems/certificate/rules.d.ts.map +1 -0
- package/dist/proof-systems/certificate/rules.js +369 -0
- package/dist/proof-systems/certificate/rules.js.map +1 -0
- package/dist/proof-systems/certificate/types.d.ts +114 -0
- package/dist/proof-systems/certificate/types.d.ts.map +1 -0
- package/dist/proof-systems/certificate/types.js +18 -0
- package/dist/proof-systems/certificate/types.js.map +1 -0
- package/dist/proof-systems/certificate/verify.d.ts +20 -0
- package/dist/proof-systems/certificate/verify.d.ts.map +1 -0
- package/dist/proof-systems/certificate/verify.js +171 -0
- package/dist/proof-systems/certificate/verify.js.map +1 -0
- package/dist/reasoning/ban-logic/analyze.d.ts +31 -0
- package/dist/reasoning/ban-logic/analyze.d.ts.map +1 -0
- package/dist/reasoning/ban-logic/analyze.js +113 -0
- package/dist/reasoning/ban-logic/analyze.js.map +1 -0
- package/dist/reasoning/ban-logic/index.d.ts +7 -0
- package/dist/reasoning/ban-logic/index.d.ts.map +1 -0
- package/dist/reasoning/ban-logic/index.js +66 -0
- package/dist/reasoning/ban-logic/index.js.map +1 -0
- package/dist/reasoning/ban-logic/protocols.d.ts +54 -0
- package/dist/reasoning/ban-logic/protocols.d.ts.map +1 -0
- package/dist/reasoning/ban-logic/protocols.js +219 -0
- package/dist/reasoning/ban-logic/protocols.js.map +1 -0
- package/dist/reasoning/ban-logic/rules.d.ts +83 -0
- package/dist/reasoning/ban-logic/rules.d.ts.map +1 -0
- package/dist/reasoning/ban-logic/rules.js +409 -0
- package/dist/reasoning/ban-logic/rules.js.map +1 -0
- package/dist/reasoning/ban-logic/terms.d.ts +26 -0
- package/dist/reasoning/ban-logic/terms.d.ts.map +1 -0
- package/dist/reasoning/ban-logic/terms.js +262 -0
- package/dist/reasoning/ban-logic/terms.js.map +1 -0
- package/dist/reasoning/ban-logic/types.d.ts +107 -0
- package/dist/reasoning/ban-logic/types.d.ts.map +1 -0
- package/dist/reasoning/ban-logic/types.js +27 -0
- package/dist/reasoning/ban-logic/types.js.map +1 -0
- package/dist/reasoning/combinatorial-games/index.d.ts +105 -0
- package/dist/reasoning/combinatorial-games/index.d.ts.map +1 -0
- package/dist/reasoning/combinatorial-games/index.js +377 -0
- package/dist/reasoning/combinatorial-games/index.js.map +1 -0
- package/dist/reasoning/differential-privacy/index.d.ts +121 -0
- package/dist/reasoning/differential-privacy/index.d.ts.map +1 -0
- package/dist/reasoning/differential-privacy/index.js +417 -0
- package/dist/reasoning/differential-privacy/index.js.map +1 -0
- package/dist/reasoning/mechanism-design/auctions.d.ts +49 -0
- package/dist/reasoning/mechanism-design/auctions.d.ts.map +1 -0
- package/dist/reasoning/mechanism-design/auctions.js +179 -0
- package/dist/reasoning/mechanism-design/auctions.js.map +1 -0
- package/dist/reasoning/mechanism-design/index.d.ts +5 -0
- package/dist/reasoning/mechanism-design/index.d.ts.map +1 -0
- package/dist/reasoning/mechanism-design/index.js +39 -0
- package/dist/reasoning/mechanism-design/index.js.map +1 -0
- package/dist/reasoning/mechanism-design/myerson.d.ts +64 -0
- package/dist/reasoning/mechanism-design/myerson.d.ts.map +1 -0
- package/dist/reasoning/mechanism-design/myerson.js +253 -0
- package/dist/reasoning/mechanism-design/myerson.js.map +1 -0
- package/dist/reasoning/mechanism-design/types.d.ts +44 -0
- package/dist/reasoning/mechanism-design/types.d.ts.map +1 -0
- package/dist/reasoning/mechanism-design/types.js +22 -0
- package/dist/reasoning/mechanism-design/types.js.map +1 -0
- package/dist/reasoning/mechanism-design/vcg.d.ts +29 -0
- package/dist/reasoning/mechanism-design/vcg.d.ts.map +1 -0
- package/dist/reasoning/mechanism-design/vcg.js +305 -0
- package/dist/reasoning/mechanism-design/vcg.js.map +1 -0
- package/dist/reasoning/probabilistic/distributions.d.ts +44 -0
- package/dist/reasoning/probabilistic/distributions.d.ts.map +1 -0
- package/dist/reasoning/probabilistic/distributions.js +207 -0
- package/dist/reasoning/probabilistic/distributions.js.map +1 -0
- package/dist/reasoning/probabilistic/examples.d.ts +31 -0
- package/dist/reasoning/probabilistic/examples.d.ts.map +1 -0
- package/dist/reasoning/probabilistic/examples.js +85 -0
- package/dist/reasoning/probabilistic/examples.js.map +1 -0
- package/dist/reasoning/probabilistic/index.d.ts +6 -0
- package/dist/reasoning/probabilistic/index.d.ts.map +1 -0
- package/dist/reasoning/probabilistic/index.js +42 -0
- package/dist/reasoning/probabilistic/index.js.map +1 -0
- package/dist/reasoning/probabilistic/inference.d.ts +45 -0
- package/dist/reasoning/probabilistic/inference.d.ts.map +1 -0
- package/dist/reasoning/probabilistic/inference.js +579 -0
- package/dist/reasoning/probabilistic/inference.js.map +1 -0
- package/dist/reasoning/probabilistic/types.d.ts +153 -0
- package/dist/reasoning/probabilistic/types.d.ts.map +1 -0
- package/dist/reasoning/probabilistic/types.js +37 -0
- package/dist/reasoning/probabilistic/types.js.map +1 -0
- package/dist/solver/smt-z3/index.d.ts +3 -0
- package/dist/solver/smt-z3/index.d.ts.map +1 -0
- package/dist/solver/smt-z3/index.js +11 -0
- package/dist/solver/smt-z3/index.js.map +1 -0
- package/dist/solver/smt-z3/types.d.ts +52 -0
- package/dist/solver/smt-z3/types.d.ts.map +1 -0
- package/dist/solver/smt-z3/types.js +6 -0
- package/dist/solver/smt-z3/types.js.map +1 -0
- package/dist/solver/smt-z3/z3-wasm-backend.d.ts +88 -0
- package/dist/solver/smt-z3/z3-wasm-backend.d.ts.map +1 -0
- package/dist/solver/smt-z3/z3-wasm-backend.js +437 -0
- package/dist/solver/smt-z3/z3-wasm-backend.js.map +1 -0
- package/dist/tests/logic/profiles/quantum/quantum.test.d.ts +2 -0
- package/dist/tests/logic/profiles/quantum/quantum.test.d.ts.map +1 -0
- package/dist/tests/logic/profiles/quantum/quantum.test.js +209 -0
- package/dist/tests/logic/profiles/quantum/quantum.test.js.map +1 -0
- package/dist/tests/proof-systems/certificate/certificate.test.d.ts +2 -0
- package/dist/tests/proof-systems/certificate/certificate.test.d.ts.map +1 -0
- package/dist/tests/proof-systems/certificate/certificate.test.js +449 -0
- package/dist/tests/proof-systems/certificate/certificate.test.js.map +1 -0
- package/dist/tests/reasoning/ban-logic/ban-logic.test.d.ts +2 -0
- package/dist/tests/reasoning/ban-logic/ban-logic.test.d.ts.map +1 -0
- package/dist/tests/reasoning/ban-logic/ban-logic.test.js +270 -0
- package/dist/tests/reasoning/ban-logic/ban-logic.test.js.map +1 -0
- package/dist/tests/reasoning/combinatorial-games/combinatorial-games.test.d.ts +2 -0
- package/dist/tests/reasoning/combinatorial-games/combinatorial-games.test.d.ts.map +1 -0
- package/dist/tests/reasoning/combinatorial-games/combinatorial-games.test.js +203 -0
- package/dist/tests/reasoning/combinatorial-games/combinatorial-games.test.js.map +1 -0
- package/dist/tests/reasoning/differential-privacy/differential-privacy.test.d.ts +2 -0
- package/dist/tests/reasoning/differential-privacy/differential-privacy.test.d.ts.map +1 -0
- package/dist/tests/reasoning/differential-privacy/differential-privacy.test.js +388 -0
- package/dist/tests/reasoning/differential-privacy/differential-privacy.test.js.map +1 -0
- package/dist/tests/reasoning/mechanism-design/mechanism-design.test.d.ts +2 -0
- package/dist/tests/reasoning/mechanism-design/mechanism-design.test.d.ts.map +1 -0
- package/dist/tests/reasoning/mechanism-design/mechanism-design.test.js +290 -0
- package/dist/tests/reasoning/mechanism-design/mechanism-design.test.js.map +1 -0
- package/dist/tests/reasoning/probabilistic/probabilistic.test.d.ts +2 -0
- package/dist/tests/reasoning/probabilistic/probabilistic.test.d.ts.map +1 -0
- package/dist/tests/reasoning/probabilistic/probabilistic.test.js +370 -0
- package/dist/tests/reasoning/probabilistic/probabilistic.test.js.map +1 -0
- package/dist/tests/solver/smt-z3/z3-wasm-backend.test.d.ts +2 -0
- package/dist/tests/solver/smt-z3/z3-wasm-backend.test.d.ts.map +1 -0
- package/dist/tests/solver/smt-z3/z3-wasm-backend.test.js +394 -0
- package/dist/tests/solver/smt-z3/z3-wasm-backend.test.js.map +1 -0
- package/dist/tests/tooling/mathlib/mathlib.test.d.ts +2 -0
- package/dist/tests/tooling/mathlib/mathlib.test.d.ts.map +1 -0
- package/dist/tests/tooling/mathlib/mathlib.test.js +214 -0
- package/dist/tests/tooling/mathlib/mathlib.test.js.map +1 -0
- package/dist/tests/tooling/proof-guidance/features.test.d.ts +2 -0
- package/dist/tests/tooling/proof-guidance/features.test.d.ts.map +1 -0
- package/dist/tests/tooling/proof-guidance/features.test.js +72 -0
- package/dist/tests/tooling/proof-guidance/features.test.js.map +1 -0
- package/dist/tests/tooling/proof-guidance/model.test.d.ts +2 -0
- package/dist/tests/tooling/proof-guidance/model.test.d.ts.map +1 -0
- package/dist/tests/tooling/proof-guidance/model.test.js +165 -0
- package/dist/tests/tooling/proof-guidance/model.test.js.map +1 -0
- package/dist/tests/tooling/proof-guidance/search.test.d.ts +2 -0
- package/dist/tests/tooling/proof-guidance/search.test.d.ts.map +1 -0
- package/dist/tests/tooling/proof-guidance/search.test.js +238 -0
- package/dist/tests/tooling/proof-guidance/search.test.js.map +1 -0
- package/dist/tests/type-theory/cubical/cubical.test.d.ts +2 -0
- package/dist/tests/type-theory/cubical/cubical.test.d.ts.map +1 -0
- package/dist/tests/type-theory/cubical/cubical.test.js +207 -0
- package/dist/tests/type-theory/cubical/cubical.test.js.map +1 -0
- package/dist/tests/type-theory/effects/effects.test.d.ts +2 -0
- package/dist/tests/type-theory/effects/effects.test.d.ts.map +1 -0
- package/dist/tests/type-theory/effects/effects.test.js +242 -0
- package/dist/tests/type-theory/effects/effects.test.js.map +1 -0
- package/dist/tooling/mathlib/group.d.ts +27 -0
- package/dist/tooling/mathlib/group.d.ts.map +1 -0
- package/dist/tooling/mathlib/group.js +89 -0
- package/dist/tooling/mathlib/group.js.map +1 -0
- package/dist/tooling/mathlib/index.d.ts +8 -0
- package/dist/tooling/mathlib/index.d.ts.map +1 -0
- package/dist/tooling/mathlib/index.js +40 -0
- package/dist/tooling/mathlib/index.js.map +1 -0
- package/dist/tooling/mathlib/instances.d.ts +29 -0
- package/dist/tooling/mathlib/instances.d.ts.map +1 -0
- package/dist/tooling/mathlib/instances.js +139 -0
- package/dist/tooling/mathlib/instances.js.map +1 -0
- package/dist/tooling/mathlib/lemmas.d.ts +3 -0
- package/dist/tooling/mathlib/lemmas.d.ts.map +1 -0
- package/dist/tooling/mathlib/lemmas.js +72 -0
- package/dist/tooling/mathlib/lemmas.js.map +1 -0
- package/dist/tooling/mathlib/order.d.ts +29 -0
- package/dist/tooling/mathlib/order.d.ts.map +1 -0
- package/dist/tooling/mathlib/order.js +91 -0
- package/dist/tooling/mathlib/order.js.map +1 -0
- package/dist/tooling/mathlib/ring.d.ts +15 -0
- package/dist/tooling/mathlib/ring.d.ts.map +1 -0
- package/dist/tooling/mathlib/ring.js +91 -0
- package/dist/tooling/mathlib/ring.js.map +1 -0
- package/dist/tooling/mathlib/types.d.ts +62 -0
- package/dist/tooling/mathlib/types.d.ts.map +1 -0
- package/dist/tooling/mathlib/types.js +7 -0
- package/dist/tooling/mathlib/types.js.map +1 -0
- package/dist/tooling/proof-guidance/features.d.ts +10 -0
- package/dist/tooling/proof-guidance/features.d.ts.map +1 -0
- package/dist/tooling/proof-guidance/features.js +97 -0
- package/dist/tooling/proof-guidance/features.js.map +1 -0
- package/dist/tooling/proof-guidance/index.d.ts +5 -0
- package/dist/tooling/proof-guidance/index.d.ts.map +1 -0
- package/dist/tooling/proof-guidance/index.js +25 -0
- package/dist/tooling/proof-guidance/index.js.map +1 -0
- package/dist/tooling/proof-guidance/model.d.ts +42 -0
- package/dist/tooling/proof-guidance/model.d.ts.map +1 -0
- package/dist/tooling/proof-guidance/model.js +149 -0
- package/dist/tooling/proof-guidance/model.js.map +1 -0
- package/dist/tooling/proof-guidance/search.d.ts +7 -0
- package/dist/tooling/proof-guidance/search.d.ts.map +1 -0
- package/dist/tooling/proof-guidance/search.js +102 -0
- package/dist/tooling/proof-guidance/search.js.map +1 -0
- package/dist/tooling/proof-guidance/types.d.ts +77 -0
- package/dist/tooling/proof-guidance/types.d.ts.map +1 -0
- package/dist/tooling/proof-guidance/types.js +8 -0
- package/dist/tooling/proof-guidance/types.js.map +1 -0
- package/dist/type-theory/cubical/equality.d.ts +4 -0
- package/dist/type-theory/cubical/equality.d.ts.map +1 -0
- package/dist/type-theory/cubical/equality.js +78 -0
- package/dist/type-theory/cubical/equality.js.map +1 -0
- package/dist/type-theory/cubical/index.d.ts +14 -0
- package/dist/type-theory/cubical/index.d.ts.map +1 -0
- package/dist/type-theory/cubical/index.js +71 -0
- package/dist/type-theory/cubical/index.js.map +1 -0
- package/dist/type-theory/cubical/infer.d.ts +18 -0
- package/dist/type-theory/cubical/infer.d.ts.map +1 -0
- package/dist/type-theory/cubical/infer.js +241 -0
- package/dist/type-theory/cubical/infer.js.map +1 -0
- package/dist/type-theory/cubical/interval.d.ts +12 -0
- package/dist/type-theory/cubical/interval.d.ts.map +1 -0
- package/dist/type-theory/cubical/interval.js +118 -0
- package/dist/type-theory/cubical/interval.js.map +1 -0
- package/dist/type-theory/cubical/normalize.d.ts +5 -0
- package/dist/type-theory/cubical/normalize.d.ts.map +1 -0
- package/dist/type-theory/cubical/normalize.js +191 -0
- package/dist/type-theory/cubical/normalize.js.map +1 -0
- package/dist/type-theory/cubical/path-algebra.d.ts +12 -0
- package/dist/type-theory/cubical/path-algebra.d.ts.map +1 -0
- package/dist/type-theory/cubical/path-algebra.js +109 -0
- package/dist/type-theory/cubical/path-algebra.js.map +1 -0
- package/dist/type-theory/cubical/substitute.d.ts +3 -0
- package/dist/type-theory/cubical/substitute.d.ts.map +1 -0
- package/dist/type-theory/cubical/substitute.js +109 -0
- package/dist/type-theory/cubical/substitute.js.map +1 -0
- package/dist/type-theory/cubical/types.d.ts +77 -0
- package/dist/type-theory/cubical/types.d.ts.map +1 -0
- package/dist/type-theory/cubical/types.js +258 -0
- package/dist/type-theory/cubical/types.js.map +1 -0
- package/dist/type-theory/effects/core.d.ts +27 -0
- package/dist/type-theory/effects/core.d.ts.map +1 -0
- package/dist/type-theory/effects/core.js +79 -0
- package/dist/type-theory/effects/core.js.map +1 -0
- package/dist/type-theory/effects/exception.d.ts +18 -0
- package/dist/type-theory/effects/exception.d.ts.map +1 -0
- package/dist/type-theory/effects/exception.js +59 -0
- package/dist/type-theory/effects/exception.js.map +1 -0
- package/dist/type-theory/effects/index.d.ts +11 -0
- package/dist/type-theory/effects/index.d.ts.map +1 -0
- package/dist/type-theory/effects/index.js +50 -0
- package/dist/type-theory/effects/index.js.map +1 -0
- package/dist/type-theory/effects/reader.d.ts +20 -0
- package/dist/type-theory/effects/reader.d.ts.map +1 -0
- package/dist/type-theory/effects/reader.js +62 -0
- package/dist/type-theory/effects/reader.js.map +1 -0
- package/dist/type-theory/effects/state.d.ts +31 -0
- package/dist/type-theory/effects/state.d.ts.map +1 -0
- package/dist/type-theory/effects/state.js +91 -0
- package/dist/type-theory/effects/state.js.map +1 -0
- package/dist/type-theory/effects/types.d.ts +45 -0
- package/dist/type-theory/effects/types.d.ts.map +1 -0
- package/dist/type-theory/effects/types.js +21 -0
- package/dist/type-theory/effects/types.js.map +1 -0
- package/dist/type-theory/effects/writer.d.ts +30 -0
- package/dist/type-theory/effects/writer.d.ts.map +1 -0
- package/dist/type-theory/effects/writer.js +79 -0
- package/dist/type-theory/effects/writer.js.map +1 -0
- 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
|