Skip to content

Commit 90ff471

Browse files
Resolve molecular hub vs valence-electron arity
Keep both declared relations: (center, ligand_electron_i) for the 3-structure and (center_electron, ligand_electron) for the bond. Water again has a degree-2 hub and a quaternion without installing (x,y,z).
1 parent 26fd6b0 commit 90ff471

8 files changed

Lines changed: 151 additions & 55 deletions

research/epac/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ until a canonical `The-Interdependency/epac` source is created and pinned in
1717
- [`docs/arity.md`](docs/arity.md) — arity is declared dimensional coupling,
1818
not ambient dimension count. Charged oriented couplings plus degree are the
1919
three-dimensional structure.
20+
- [`docs/constraints.md`](docs/constraints.md) — standing constraints and
21+
resolved contradictions for this candidate.
2022
- [`docs/preregistration-molecular-geometry-from-element-gonols.md`](docs/preregistration-molecular-geometry-from-element-gonols.md)
2123
provisional candidate: Z=1–18 element gonols from atomic structure only, then
2224
affixiation of H₂, H₂O, NH₃, CH₄, CO₂ through unpaired valence electrons,

research/epac/docs/arity.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,18 @@ Hydrogen-1 is one proton and no neutrons.
2525
At atomic scale the hub is that closed nucleus and every electron instance has
2626
its own `(nucleus, electron_i)` with slot charges `(Z, -1)`.
2727

28-
Molecular scale promotes already-closed unpaired valence electrons as arity
29-
axes. Each bond is `(center_electron, ligand_electron)` with charges `(-1, -1)`.
30-
Closed atoms remain molecular participants. Nucleons and core electrons stay
31-
inside those atoms. Water is two valence-electron couplings, not `(O#2, H#0)`.
28+
Molecular scale has two declared relations:
29+
30+
- 3-structure: hub is the closed center atom; every ligand unpaired valence
31+
electron has `(center, ligand_e_i)`.
32+
- bond: unpaired valence electrons are arity-coupled as
33+
`(center_e_i, ligand_e_i)` with charges `(-1, -1)`.
34+
35+
Nucleons and core electrons stay inside closed atoms. Water's 3 is
36+
`(O#2, H0_e)` and `(O#2, H1_e)`, degree 2 on oxygen. That is not `(O#2, H#0)`
37+
atom-atom and not a ternary `(x,y,z)`.
38+
39+
See `constraints.md`.
3240

3341
Degree is required. For ambient `{x,y,z}` with couplings `(z,x)` and `(z,y)`:
3442

research/epac/docs/constraints.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# EPAC constraint ledger
2+
3+
Status: **provisional candidate**. Not org canon. Resolved means the constructor
4+
now obeys the listed rule. Unresolved remains `hmmm`.
5+
6+
## Constraints that stand
7+
8+
| Id | Constraint | Standing |
9+
|---|---|---|
10+
| C1 | `epac.public_gonol`, not `edcm.gonol` | resolved |
11+
| C2 | `(z,x) ≠ (x,z)` | resolved |
12+
| C3 | overlap is not a proof of `(x,y,z)` | resolved |
13+
| C4 | degree is required | resolved |
14+
| C5 | 3-structure = oriented couplings + charge state + degree | resolved at each scale that has a 3 |
15+
| C6 | representing a 3 takes 4 quaternion components; scalar is Möbius ε | resolved where a local 3 exists |
16+
| C7 | Hamilton product is not a coupling proof | resolved (forbidden rule) |
17+
| C8 | letters/abbreviations are not physics axes | resolved |
18+
| C9 | protons and neutrons are precursor gonols of the nucleus | resolved |
19+
| C10 | electrons couple to the closed nucleus; nucleons stay inside it | resolved |
20+
| C11 | closed gonols are atomic at the next scale; promotion is allowed | resolved |
21+
| C12 | molecular attachment consumes closed unpaired valence electrons, not `atomic_of` | resolved |
22+
| C13 | atomic s→p promotion is an atomic excited gonol, not VSEPR | resolved |
23+
| C14 | H₂ is a single binary and is not a 3 | resolved |
24+
| C15 | sealed chemistry shapes stay out of construction | resolved |
25+
| C16 | nothing bigger than atoms is an *input* to element construction | resolved |
26+
27+
## Contradictions
28+
29+
### X1 — molecular hub
30+
31+
- C5/C6 and “every instance has `(z, x_i)` / `(z, y_j)`” require **one hub** with degree ≥ 2 to make a molecular 3.
32+
- “Valence electrons are arity coupled” was implemented as disjoint `(center_electron, ligand_electron)` pairs, each hub degree 1, so **no molecular 3**.
33+
34+
**Resolution:** two declared relations, not one inferred from the other.
35+
36+
1. **3-structure:** hub `z` is the closed center atom; instances are ligand unpaired valence electrons: `(center, ligand_e_i)`.
37+
2. **Bond:** unpaired valence electrons are arity-coupled to each other: `(center_e_i, ligand_e_i)`.
38+
39+
Water: `deg(O#2)=2` on `(O#2, H0_e)` and `(O#2, H1_e)`; quaternion `(ε, 8, −1, −1)`. Bonds remain the two electron–electron couplings. Not `(x,y,z)`.
40+
41+
### X2 — “do not reopen electrons” vs “electrons make molecules”
42+
43+
**Resolution:** promote already-closed unpaired valence electron gonols as molecular *instances*. Do not flatten nucleons or core electrons into molecular axes.
44+
45+
### X3 — consume atomic 3-structure vs formula-count geometry
46+
47+
**Resolution:** composition still names which atoms. Attachment sites and charges come from closed gonols. Molecular 3 uses the closed center as hub and ligand valence electrons as instances.
48+
49+
### X4 — internucleon `(every proton, every neutron)` vs no all-pairs authority
50+
51+
**Unresolved / hmmm.** Bipartite `(proton, neutron)` is a declared nuclear candidate, not p–p or n–n fill, and not a selected nuclear force. Multiple proton hubs at nuclear scale is the same *shape* of question as X1 and is not closed here.
52+
53+
## Usage
54+
55+
After changing couplings, replay:
56+
57+
```bash
58+
cd research/epac
59+
PYTHONPATH=".:../ucns/src" python3 -m unittest discover -s tests -q
60+
```

research/epac/docs/preregistration-molecular-geometry-from-element-gonols.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ proton gonols (charge +1) and neutron gonols (charge 0)
3131
-> close that atomic 3-structure inside the element gonol
3232
-> unpaired-valence electron gonols already closed inside each atom
3333
-> if needed, a closed promoted atomic gonol (same n s→p); no table re-lookup
34-
-> declared oriented (center_electron, ligand_electron) arity-2 couplings with charges (-1, -1)
34+
-> declared oriented (center_electron, ligand_electron) bond couplings with charges (-1, -1)
35+
-> declared oriented (closed_center, ligand_electron_i) 3-structure; one hub, every instance
3536
-> molecular three-dimensional structure = those atom-instance couplings + charge states + degree
3637
-> each local 3 represented in 4 quaternion components (scalar ε plus the three axis charges)
3738
-> molecular Public Gonol (closed atoms remain atomic participants)

research/epac/epac_dimensional_arity.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@
1010
physical instance of ``y`` has its own declared ``(z, y_j)``. A second
1111
occurrence is a second instance, not a reuse of the first coupling.
1212
``(x_i, z)`` does not satisfy ``(z, x_i)``. Letters and abbreviations are
13-
not this domain. At atomic scale the instances are electrons and the hub is
14-
the nucleus. At molecular scale the instances are closed atom gonols.
13+
not this domain. At atomic scale the hub is the nucleus and the instances
14+
are electrons. At molecular scale the hub is the closed center atom and the
15+
instances are ligand unpaired valence electrons. Bond couplings between
16+
those valence electrons are a second declared relation, not a replacement
17+
hub.
1518
1619
The three-dimensional structure is the combination of declared oriented
1720
couplings, their arity charge states, and degree. That span can involve three

research/epac/epac_molecular.py

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
"""Molecular EPAC Public Gonols from closed valence-electron arity couplings.
1+
"""Molecular EPAC Public Gonols from closed atoms and valence-electron arity.
22
3-
Molecules are made where unpaired valence electrons couple. Each bond is a
4-
declared arity-2 coupling of two already-closed valence electron gonols:
5-
``(center_electron, ligand_electron)``. Closed atoms remain molecular
6-
participants; nucleons and core electrons stay inside them. The table is
7-
not re-queried.
3+
Two declared relations:
4+
5+
- 3-structure: hub is the closed center atom; instances are ligand unpaired
6+
valence electrons ``(center, ligand_e_i)``.
7+
- bond: those valence electrons couple as ``(center_e_i, ligand_e_i)``.
8+
9+
Closed atoms remain molecular participants. Nucleons and core electrons stay
10+
inside them. The table is not re-queried.
811
912
Construction uses ``epac.public_gonol``, not ``edcm.gonol``. No sealed
1013
molecular-shape file is opened here.
@@ -84,29 +87,43 @@ def _atom_dimension_id(gonol: ClosedPublicGonol) -> str:
8487
return f"{symbol_of(gonol)}#{gonol.occurrence}"
8588

8689

87-
def _declared_valence_space(
90+
def _declared_molecular_space(
91+
*,
92+
center: ClosedPublicGonol | None,
8893
bonds: tuple[tuple[ClosedPublicGonol, ClosedPublicGonol], ...],
8994
):
90-
"""Arity-2 couplings of closed valence electrons. Atoms are not these axes."""
95+
"""Bond couplings plus, when a center exists, the molecular 3-structure.
96+
97+
Bonds: ``(center_electron, ligand_electron)``.
98+
3-structure: ``(closed_center, ligand_electron_i)`` so one hub has every instance.
99+
"""
91100

92101
ambient: list[str] = []
93102
charges: dict[str, int] = {}
94103
declarations: list[list[str]] = []
95-
by_hub: dict[str, list[str]] = {}
104+
105+
def _add(axis_id: str, charge: int) -> None:
106+
if axis_id not in charges:
107+
ambient.append(axis_id)
108+
charges[axis_id] = charge
109+
96110
for hub_electron, instance_electron in bonds:
97-
hub_id = hub_electron.source_id
98-
instance_id = instance_electron.source_id
99-
if hub_id not in charges:
100-
ambient.append(hub_id)
101-
charges[hub_id] = ELECTRON_CHARGE
102-
if instance_id not in charges:
103-
ambient.append(instance_id)
104-
charges[instance_id] = ELECTRON_CHARGE
105-
declarations.append([hub_id, instance_id])
106-
by_hub.setdefault(hub_id, []).append(instance_id)
111+
_add(hub_electron.source_id, ELECTRON_CHARGE)
112+
_add(instance_electron.source_id, ELECTRON_CHARGE)
113+
declarations.append([hub_electron.source_id, instance_electron.source_id])
114+
ligand_ids = tuple(instance.source_id for _hub, instance in bonds)
115+
if center is not None:
116+
center_id = _atom_dimension_id(center)
117+
_add(center_id, nuclear_charge(center))
118+
for ligand_id in ligand_ids:
119+
declarations.append([center_id, ligand_id])
107120
declared = space(ambient, declarations, charges=charges)
108-
for hub_id, instance_ids in by_hub.items():
109-
oriented_instance_couplings(declared, hub_id=hub_id, instance_ids=tuple(instance_ids))
121+
if center is not None and ligand_ids:
122+
oriented_instance_couplings(declared, hub_id=_atom_dimension_id(center), instance_ids=ligand_ids)
123+
for hub_electron, instance_electron in bonds:
124+
oriented_instance_couplings(
125+
declared, hub_id=hub_electron.source_id, instance_ids=(instance_electron.source_id,)
126+
)
110127
return declared
111128

112129

@@ -234,8 +251,13 @@ def construct_molecule(formula: str) -> MolecularConstruction:
234251
center_attachment_ids = tuple(electron.source_id for electron in center_electrons)
235252
ligand_attachment_ids = tuple(_attachment_electron_ids(item) for item in ligands)
236253
mobius = _mobius_coupling(bonds=bonds)
237-
dimensional = _declared_valence_space(bonds)
238-
instance_couplings = tuple((hub.source_id, instance.source_id) for hub, instance in bonds)
254+
dimensional = _declared_molecular_space(center=center, bonds=bonds)
255+
valence_electron_bonds = tuple((hub.source_id, instance.source_id) for hub, instance in bonds)
256+
instance_couplings = (
257+
tuple((_atom_dimension_id(center), instance.source_id) for _hub, instance in bonds)
258+
if center is not None
259+
else valence_electron_bonds
260+
)
239261
geometry = geometry_from_declared_couplings(dimensional)
240262
receipt = construct_public_gonol(
241263
source_id=f"epac.molecule:{formula}",
@@ -292,6 +314,7 @@ def construct_molecule(formula: str) -> MolecularConstruction:
292314
"charged_structure_readout": charged_structure_readout(geometry["structure"]),
293315
"topology_structure_readout": topology_structure_readout(geometry["structure"]),
294316
"oriented_instance_couplings": instance_couplings,
317+
"valence_electron_bonds": valence_electron_bonds,
295318
}
296319
return MolecularConstruction(formula=formula, receipt=receipt, invariants=invariants)
297320

research/epac/tests/test_geometry_comparison_after_construction.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ def test_charged_couplings_are_the_three_dimensional_structure(self) -> None:
2828
carbon_dioxide = constructions["CO2"].receipt.structure
2929
self.assertIsNotNone(water)
3030
self.assertIsNotNone(carbon_dioxide)
31-
self.assertEqual(water["participating_dimension_count"], 4)
32-
self.assertEqual(carbon_dioxide["participating_dimension_count"], 8)
31+
self.assertEqual(water["participating_dimension_count"], 5)
32+
self.assertEqual(carbon_dioxide["participating_dimension_count"], 9)
3333
self.assertFalse(water["ternary_coupling_declared"])
3434
self.assertNotEqual(
3535
topology_structure_readout(water),
@@ -38,13 +38,13 @@ def test_charged_couplings_are_the_three_dimensional_structure(self) -> None:
3838
water_charged = charged_structure_readout(water)
3939
co2_charged = charged_structure_readout(carbon_dioxide)
4040
self.assertNotEqual(water_charged, co2_charged)
41-
self.assertEqual(len(water_charged[0]), 2)
42-
self.assertTrue(all(part[0] == 2 and part[1] == ((-1, -1), 1) for part in water_charged[0]))
41+
self.assertEqual(len(water_charged[0]), 4)
42+
self.assertTrue(all(part[0] == 2 for part in water_charged[0]))
43+
self.assertTrue(any(part[2][0] == "O#2" for part in water_charged[0]))
4344
self.assertTrue(
44-
all(name.startswith("epac.electron:") for part in water_charged[0] for name in part[2])
45+
any(name.startswith("epac.electron:") for part in water_charged[0] for name in part[2])
4546
)
46-
self.assertEqual(len(co2_charged[0]), 4)
47-
self.assertTrue(all(part[0] == 2 and part[1] == ((-1, -1), 1) for part in co2_charged[0]))
47+
self.assertEqual(len(co2_charged[0]), 8)
4848

4949
def test_sealed_shape_comparison_uses_charged_structure(self) -> None:
5050
constructions = construct_declared_molecules()

research/epac/tests/test_molecular_affixiation.py

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -43,45 +43,45 @@ def test_unpaired_valence_and_shells_are_used(self) -> None:
4343
def test_declared_couplings_are_binary_and_do_not_fill_ambient(self) -> None:
4444
molecules = construct_declared_molecules()
4545
water = molecules["H2O"].invariants["dimensional_geometry"]
46-
self.assertEqual(water["ambient_count"], 4)
47-
self.assertEqual([c["arity"] for c in water["couplings"]], [2, 2])
46+
self.assertEqual(water["ambient_count"], 5)
47+
self.assertEqual(len(water["couplings"]), 4)
48+
self.assertTrue(all(c["arity"] == 2 for c in water["couplings"]))
4849
ids = [c["declared_ids"] for c in water["couplings"]]
49-
self.assertEqual(len(ids), 2)
5050
self.assertTrue(all(len(item) == 2 for item in ids))
51-
self.assertTrue(all(name.startswith("epac.electron:") for pair in ids for name in pair))
5251
methane = molecules["CH4"].invariants["dimensional_geometry"]
53-
self.assertEqual(methane["ambient_count"], 8)
54-
self.assertEqual([c["arity"] for c in methane["couplings"]], [2, 2, 2, 2])
52+
self.assertEqual(len(methane["couplings"]), 8)
5553
self.assertFalse(any(c["arity"] == 5 for c in methane["couplings"]))
5654
self.assertFalse(methane["inferred_from_ambient"])
5755
self.assertFalse(methane["inferred_higher_arity_from_overlap"])
58-
self.assertEqual(water["structure"]["participating_dimension_count"], 4)
56+
self.assertEqual(water["structure"]["participating_dimension_count"], 5)
5957
self.assertFalse(water["structure"]["ternary_coupling_declared"])
6058
self.assertFalse(water["structure"]["inferred_cartesian_embedding"])
61-
self.assertEqual(water["couplings"][0]["slot_charges"], (-1, -1))
62-
self.assertEqual(methane["couplings"][0]["slot_charges"], (-1, -1))
6359
water_receipt = molecules["H2O"].receipt
6460
self.assertEqual(water_receipt.constructor_id, "epac.public_gonol")
65-
self.assertEqual(len(water_receipt.structure["parts"]), 2)
61+
self.assertEqual(len(water_receipt.structure["parts"]), 4)
6662
water_instances = molecules["H2O"].invariants["oriented_instance_couplings"]
6763
self.assertEqual(len(water_instances), 2)
68-
self.assertTrue(all(item[0].startswith("epac.electron:O#2:") for item in water_instances))
64+
self.assertEqual({item[0] for item in water_instances}, {"O#2"})
6965
self.assertEqual(
7066
[item[1] for item in water_instances],
7167
["epac.electron:H#0:0", "epac.electron:H#1:0"],
7268
)
69+
self.assertEqual(len(molecules["H2O"].invariants["valence_electron_bonds"]), 2)
70+
self.assertTrue(
71+
all(item[0].startswith("epac.electron:O#2:") for item in molecules["H2O"].invariants["valence_electron_bonds"])
72+
)
7373
methane_instances = molecules["CH4"].invariants["oriented_instance_couplings"]
7474
self.assertEqual(len(methane_instances), 4)
75-
self.assertTrue(all(item[0].startswith("epac.electron:C#0:") for item in methane_instances))
75+
self.assertTrue(all(item[0] == "C#0" for item in methane_instances))
7676
self.assertEqual(
7777
[item[1] for item in methane_instances],
7878
["epac.electron:H#1:0", "epac.electron:H#2:0", "epac.electron:H#3:0", "epac.electron:H#4:0"],
7979
)
8080
self.assertEqual(len(molecules["H2"].invariants["oriented_instance_couplings"]), 1)
8181
water_ids = {name for part in water_receipt.structure["parts"] for name in part["coupling"]}
82-
self.assertTrue(all(name.startswith("epac.electron:") for name in water_ids))
83-
self.assertNotIn("O#2", water_ids)
82+
self.assertIn("O#2", water_ids)
8483
self.assertNotIn("H#0", water_ids)
84+
self.assertTrue(any(name.startswith("epac.electron:H#0:") for name in water_ids))
8585
oxygen = next(
8686
item
8787
for item in water_receipt.gonol.participants
@@ -109,11 +109,10 @@ def test_declared_couplings_are_binary_and_do_not_fill_ambient(self) -> None:
109109
self.assertNotIn("atomic_of", source)
110110
self.assertNotIn("from epac_atomic", source)
111111
self.assertEqual(water_receipt.structure["representation_dimension"], 4)
112-
self.assertEqual(water_receipt.structure["participating_dimension_count"], 4)
113-
self.assertEqual(quaternion_structure_readout(water_receipt.structure), ())
114-
self.assertEqual(quaternion_structure_readout(molecules["CO2"].receipt.structure), ())
112+
self.assertEqual(water_receipt.structure["participating_dimension_count"], 5)
113+
water_quat = quaternion_structure_readout(water_receipt.structure)
114+
self.assertTrue(any(item[1][0] == "O#2" for item in water_quat))
115115
self.assertEqual(quaternion_structure_readout(molecules["H2"].receipt.structure), ())
116-
self.assertEqual(quaternion_structure_readout(molecules["CH4"].receipt.structure), ())
117116

118117
def test_ucns_coupling_binds_declared_attachments(self) -> None:
119118
molecules = construct_declared_molecules()

0 commit comments

Comments
 (0)