BioSight/python/phi/charclass.py
allaun 09b9f690e0 refactor(dna): optimize char classification and fix Unicode math symbol misclassification
- Pre-defined and unified character sets (OPERATOR_CHARS, BRACKET_CHARS, PUNCT_CHARS, WHITESPACE_CHARS).
- Defined precise sets for SYMMETRY_CHARS, PERIODICITY_CHARS, CONTINUITY_CHARS, and META_MATH_CHARS.
- Re-ordered specific checks to precede c.isalpha() so Unicode/Greek math letters are not misclassified as standard lower/upper alpha.

Build: 3307 jobs, 0 errors (lake build)
2026-06-27 22:53:16 -05:00

190 lines
6.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
phi.charclass — Layer 1: Character classification → Δ₁₁ byte histogram
Each ASCII or TeX character maps to 1 of 12 archetypal classes. The histogram
over these 12 classes is the F(E) feature vector. Note that the 30-base DNA layout
maps only the first 8 classes (indices 0-7) to Layer 1 (bases 0-7) as defined by
SilverSight's HachimojiCharClass.lean.
Dependencies: none (stdlib only)
"""
from __future__ import annotations
from typing import List
# ── 12 character classes ─────────────────────────────────────────────────
# Each class corresponds to a dimension of Δ₁₁ (the 11-simplex).
# The classes partition the visible ASCII range into 12 bins.
CHAR_CLASSES = {
"digit": 0, # 0-9
"lower_alpha": 1, # a-z
"upper_alpha": 2, # A-Z
"operator": 3, # + - * / ^ % = < > ! & | ~
"bracket": 4, # ( ) [ ] { }
"punctuation": 5, # . , ; : ' " @ # $ _ \
"whitespace": 6, # space, tab, newline
"other": 7, # everything else (Greek, Unicode math, etc.)
"symmetry": 8, # = $\approx$ $\equiv$ $\sim$
"periodicity": 9, # $\pi$ $\infty$ $\theta$ $\lambda$
"continuity": 10, # $\rightarrow$ $\Delta$ $\nabla$ $\int$
"meta_math": 11, # $\sqrt{}$ $\sum$ $\prod$ $\partial$
}
OPERATOR_CHARS = set("+-*/^%=<>!&|~")
BRACKET_CHARS = set("()[]{}")
PUNCT_CHARS = set(".,;:'\"@#$\\_")
WHITESPACE_CHARS = set(" \t\n\r")
# Unicode mathematical sets (placed at the top to prevent misclassification as standard alpha)
SYMMETRY_CHARS = set("≈≡∼")
PERIODICITY_CHARS = set("πθλ∞")
CONTINUITY_CHARS = set("→Δ∇∫")
META_MATH_CHARS = set("√∑∏∂")
def classify_char(c: str) -> int:
"""Classify a single character into 1 of 12 archetypal classes (0-11).
The 12 classes partition the visible ASCII and common TeX range:
+------+--------------+-------------------------------+
| Class | Name | Characters |
+------+--------------+-------------------------------+
| 0 | digit | 0-9 |
| 1 | lower_alpha | a-z |
| 2 | upper_alpha | A-Z |
| 3 | operator | + - * / ^ % = < > ! & | ~ |
| 4 | bracket | ( ) [ ] { } |
| 5 | punctuation | . , ; : ' \" @ # $ \\\\ _ |
| 6 | whitespace | space, tab, newline, CR |
| 7 | other | Unicode, non-ASCII, unassigned |
| 8 | symmetry | ≈ ≡ |
| 9 | periodicity | π θ λ ∞ |
| 10 | continuity | → Δ ∇ ∫ |
| 11 | meta_math | √ ∑ ∏ ∂ |
+------+--------------+-------------------------------+
Args:
c: A single-character string.
Returns:
An integer 0-11 identifying the character's class.
Examples:
>>> classify_char("3")
0
>>> classify_char("x")
1
>>> classify_char("X")
2
>>> classify_char("+")
3
>>> classify_char(")")
4
>>> classify_char(".")
5
>>> classify_char(" ")
6
>>> classify_char("©")
7
"""
# Check Unicode math classes first so Greek/math symbols are not misclassified as standard alpha
if c in PERIODICITY_CHARS:
return 9
if c in CONTINUITY_CHARS:
return 10
if c in SYMMETRY_CHARS:
return 8
if c in META_MATH_CHARS:
return 11
# Check standard ASCII classes
if c.isdigit():
return 0
if c.isalpha():
return 1 if c.islower() else 2
if c in OPERATOR_CHARS:
return 3
if c in BRACKET_CHARS:
return 4
if c in PUNCT_CHARS:
return 5
if c in WHITESPACE_CHARS:
return 6
return 7
def compute_F(equation: str) -> List[float]:
"""Compute F(E) — normalized byte-class histogram on Δ₁₂.
Returns 12 floats summing to 1.0. The first 8 classes (indices 0-7)
map directly to Layer 1 of the Φ DNA embedding (bases 0-7).
Pure function: no state, no side effects.
Examples:
>>> result = compute_F("x + 1")
>>> round(sum(result), 10)
1.0
"""
counts = [0] * 12
for c in equation:
counts[classify_char(c)] += 1
total = sum(counts)
if total == 0:
return [1.0 / 12] * 12
return [c / total for c in counts]
if __name__ == "__main__":
import math
# ── 1. Test every character class ─────────────────────────────────────
assert classify_char("0") == 0
assert classify_char("9") == 0
assert classify_char("a") == 1
assert classify_char("z") == 1
assert classify_char("A") == 2
assert classify_char("Z") == 2
assert classify_char("+") == 3
assert classify_char("*") == 3
assert classify_char("(") == 4
assert classify_char("}") == 4
assert classify_char(".") == 5
assert classify_char(",") == 5
assert classify_char(" ") == 6
assert classify_char("\t") == 6
assert classify_char("\n") == 6
assert classify_char("©") == 7 # non-ASCII, non-alpha → other
# ── 2. compute_F output sums to 1.0 for various equations ─────────────
for eq in ["x + 1", "E = mc^2", "a = b = c", "12345", " ", "((()))"]:
result = compute_F(eq)
assert len(result) == 12
assert abs(sum(result) - 1.0) < 1e-10, f"F({eq!r}) sum = {sum(result)}"
# ── 3. Edge cases ─────────────────────────────────────────────────────
# Empty string → uniform distribution
assert compute_F("") == [1.0 / 12] * 12
# All-same-class string
F_digits = compute_F("12345")
assert abs(F_digits[0] - 1.0) < 1e-10
# Mixed content
F_mixed = compute_F("a1 + b2")
assert abs(sum(F_mixed) - 1.0) < 1e-10
# ── 4. classify_char returns int in 0..11 for every printable ASCII ───
for code in range(32, 127):
c = chr(code)
cls = classify_char(c)
assert 0 <= cls <= 11, f"char {c!r} (code {code}) class {cls} out of 0..11"
assert isinstance(cls, int)
print("charclass.py: all verifications PASSED")