diff --git a/sonnet/README.md b/sonnet/README.md index 8070b781..f3614749 100644 --- a/sonnet/README.md +++ b/sonnet/README.md @@ -180,6 +180,16 @@ a correlation-fibre action, regular cocycle, future adequacy, or effective compression theorem. The next work separates a finite collision-covector gate from a continuum Deng-calibrated fibre-response gate; neither has yet passed. +## Research-local calibration — AMP closure and ensemble carrier gate + +[`amp-ensemble-carrier-gate/`](amp-ensemble-carrier-gate/) separates the +finite M/P affine subsystem from the infinite A/M/P Lie closure. It proves an +exact logarithmic normal form, compiles homogeneous repeated ensembles without +Cartesian state enumeration, and shows that Addition opens a completed scale +tail outside the finite carrier. The AMP line earns `EXPAND`; every frozen +workload eliminates a surreal runtime, so the overall gate remains `NARROW` +until an interacting residual yields a measured computation advantage. + ## Research-local calibration — the \(S^6\) complex structure claim [`s6-complex-arithmetic-tower/`](s6-complex-arithmetic-tower/) studies a diff --git a/sonnet/amp-ensemble-carrier-gate/00-problem-frontier.md b/sonnet/amp-ensemble-carrier-gate/00-problem-frontier.md new file mode 100644 index 00000000..de1662ea --- /dev/null +++ b/sonnet/amp-ensemble-carrier-gate/00-problem-frontier.md @@ -0,0 +1,110 @@ +# Problem frontier: AMP closure, ensembles, and carrier necessity + +Status: frozen research contract for issue +[#150](https://github.com/mountain/process-geometry/issues/150). + +## 1. Question + +On the positive real line, or on a complex history lift with a chosen branch +of `Log`, consider + +\[ +A_t(x)=x+t, +\qquad +M_s(x)=e^s x, +\qquad +P_r(x)=\exp(e^r\Log x). +\] + +The motivating hypothesis is that Addition describes local accumulation, +Multiplication describes rescaling or independent assembly, and Power +objectifies repeated same-kind assembly. The hypothesis earns mathematical +credit only if it changes closure, representation, or a frozen computation. + +The first gate asks: + +> What is the smallest task-sufficient carrier for finite and iterated A/M/P +> histories, and can a Power-aware presentation compile an ensemble task +> without materializing its full Cartesian state space? + +`AMP` is research-local terminology here. It is not asserted to be the name +of an established mathematical field or one three-dimensional Lie group. + +## 2. Frozen task family + +The positive control uses a finite weighted state space `Omega` with partition +value + +\[ +Z_0=\sum_{\omega\in\Omega}w(\omega)>0. +\] + +A homogeneous assembly stage is + +\[ +Z_{k+1}=e^{b_k}Z_k^{n_k}, +\qquad n_k\in\mathbb N_{>0}. +\] + +Its declared observer asks only for total partition value, logarithmic +partition value, and the number of base replicas. It does not ask for named +microstates, correlations, marginals, or an interacting Hamiltonian. + +The negative control inserts Addition in the state chart. In the logarithmic +observer `y=log x`, this produces + +\[ +y\longmapsto \log(e^{\alpha y+\beta}+t), +\] + +which must either remain in the finite M/P carrier or exhibit an exact carrier +upgrade witness. + +## 3. Evidence firewall + +Separate all of the following: + +- a finite M/P word from the full A/M/P closure; +- integer replica count from arbitrary real or complex powering; +- fixed iteration height from symbolic or ordinal height; +- exact total-partition observation from reconstruction of the ensemble; +- a finite observer truncation from the full completed series; +- membership in a large ambient field from an effective implementation; +- compilation cost, certificate storage, replay cost, and output size. + +Matrices and polynomials may verify local identities. They receive no credit +as the ontology of the process rank. + +## 4. Acceptance and kill conditions + +The phase passes only if it supplies: + +1. exact adjacent conjugation and Lie-bracket laws; +2. a proof that the three infinitesimal generators do or do not close; +3. an explicit infinite closure witness if they do not; +4. an exact M/P normal form and replayable ensemble certificate; +5. a negative control that leaves the finite normal form; +6. a minimum-carrier disposition including a surreal necessity verdict. + +Narrow or stop if the apparent advantage is only: + +- relabelling repeated multiplication as Power without a reusable operation; +- hiding full state enumeration in an oracle; +- using noninteger powers as literal replica counts; +- reporting `No` containment as an algorithm; +- choosing Conway simplicity solely to force a surreal answer; +- discarding interaction or correlation data that the observer actually asks + to recover. + +## 5. Claim ceiling + +This Sonnet does not claim a complexity-class separation, a solution of the +three-dimensional Ising model, an exact renormalization theorem, a canonical +thermodynamic surreal limit, or a general surreal runtime. + +```text +Epistemic maturity: T1 exact finite results + T0 continuation +Engineering status: Sonnet-local Python certificate +Mathematical Core: unchanged +Experimental/Public API: none +``` diff --git a/sonnet/amp-ensemble-carrier-gate/01-closure-theorems.md b/sonnet/amp-ensemble-carrier-gate/01-closure-theorems.md new file mode 100644 index 00000000..0ada81d9 --- /dev/null +++ b/sonnet/amp-ensemble-carrier-gate/01-closure-theorems.md @@ -0,0 +1,226 @@ +# AMP closure theorems + +Status: exact on the declared positive-real or chosen-`Log` chart. + +## 1. The finite M/P subsystem + +Write + +\[ +\Phi_{a,b}(x)=e^b x^a, +\qquad a>0. +\] + +In the coordinate `y=log x`, this is the affine map + +\[ +y\longmapsto ay+b. +\] + +**Proposition 1.1.** The M/P histories close in the two-parameter family +`Phi`: + +\[ +\Phi_{a_2,b_2}\circ\Phi_{a_1,b_1} += +\Phi_{a_2a_1,\,a_2b_1+b_2}. +\] + +The Multiplication flow is `Phi_(1,s)` and the Power flow is +`Phi_(e^r,0)`. Hence + +\[ +P_rM_sP_r^{-1}=M_{e^r s}. +\] + +This is the orientation-preserving affine group of the logarithmic line. A +finite chronological word compiles into the two fields `(a,b)`, and replay on +the declared observer costs one multiplication and one addition. + +For one repeated map `Phi_(a,b)`, the `N`-fold iterate is + +\[ +\Phi_{a,b}^{\circ N} += +\begin{cases} +\Phi_{a^N,\,b(a^N-1)/(a-1)},&a\ne1,\\ +\Phi_{1,\,Nb},&a=1. +\end{cases} +\] + +Symbolic natural height therefore does not by itself force hyperseries or +surreal numbers for this subsystem. + +## 2. The full infinitesimal closure + +The generators are + +\[ +A=\partial_x, +\qquad +M=x\partial_x, +\qquad +P=x\log x\,\partial_x. +\] + +With + +\[ +[f\partial_x,g\partial_x]=(fg'-gf')\partial_x, +\] + +the first relations are + +\[ +[A,M]=A, +\qquad +[M,P]=M, +\qquad +[A,P]=(1+\log x)\partial_x. +\] + +The last field is not a constant linear combination of `A`, `M`, and `P`. +Thus the three-generator span is not a Lie algebra. + +For integers `m,p` and nonnegative integers `n,q`, define + +\[ +V_{m,n}=x^m(\log x)^n\partial_x. +\] + +**Theorem 2.1.** Their bracket is + +\[ +[V_{m,n},V_{p,q}] +=x^{m+p-1} +\left((p-m)(\log x)^{n+q} + +(q-n)(\log x)^{n+q-1}\right)\partial_x, +\] + +where a zero coefficient removes the formally negative logarithmic degree. + +This follows by differentiating the two coefficient functions and collecting +the two powers of `log x`. + +**Corollary 2.2.** The Lie algebra generated by `A`, `M`, and `P` is +infinite-dimensional. + +**Proof.** Since + +\[ +V_{0,1}=[A,P]-A, +\] + +we obtain + +\[ +[A,V_{0,1}]=V_{-1,0}. +\] + +Repeated bracketing gives + +\[ +\operatorname{ad}_A^{k-1}(V_{-1,0}) +=(-1)^{k-1}(k-1)!V_{-k,0}, +\qquad k\ge1. +\] + +The Laurent monomials `x^(-k)` are linearly independent. Therefore the +closure contains an infinite independent family. QED. + +This is the first strict mathematical reason not to model AMP as three +coordinates on an ordinary finite-dimensional manifold. + +## 3. Addition viewed by the M/P observer + +Set `q=e^(-y)=1/x`. A state translation becomes + +\[ +\log(e^y+t) +=y+\log(1+tq) +=y+\sum_{k\ge1}\frac{(-1)^{k+1}}{k}t^kq^k. +\] + +Formally this is an element of the completed positive ray `K[[q]]`; analytically +the displayed Taylor equality holds for `|tq|<1`. Its second derivative in +`y` is generically nonzero, so no affine M/P pair `(a,b)` represents it. + +A finite observer through degree `N` sees only `N` coefficients. Power sends +`q` to `q^a`; rational `a` may enlarge the exponent lattice, while finitely +many declared positive exponents still admit a pointed, locally finite +support cone. Arbitrary branches, infinite scale accumulation, or unbounded +iteration require a separate carrier gate. + +## 4. The `3n` process frame is anchored, not a `3n`-manifold + +For physical coordinates `x_1,...,x_n`, introduce formal local generator +labels + +\[ +e_{A_i},\qquad e_{M_i},\qquad e_{P_i}. +\] + +They define a rank-`3n` generating bundle with anchor + +\[ +\rho(e_{A_i})=\partial_{x_i}, +\qquad +\rho(e_{M_i})=x_i\partial_{x_i}, +\qquad +\rho(e_{P_i})=x_i\log(x_i)\partial_{x_i}. +\] + +**Proposition 4.1.** At every point of the positive chart, the anchor has +rank `n`, not `3n`. + +**Proof.** Its image contains every `partial_(x_i)` through `e_(A_i)`, so the +rank is at least `n`. All three generators for index `i` are scalar multiples +of the same tangent vector, with exact kernel relations + +\[ +\rho(e_{M_i}-x_i e_{A_i})=0, +\qquad +\rho(e_{P_i}-\log(x_i)e_{M_i})=0. +\] + +Thus the image has rank at most `n` and the local kernel has dimension `2n`. +QED. + +The `3n` description is nevertheless useful if it retains the generator +grade, legal compositions, and history. For an observable `f`, the process +signature + +\[ +\bigl(A_i f,M_i f,P_i f\bigr)_{i=1}^n +\] + +is a structured family of probes, not `3n` independent tangent coordinates. +In `y_i=log x_i`, for example, + +\[ +A_i=e^{-y_i}\partial_{y_i}, +\qquad +M_i=\partial_{y_i}, +\qquad +P_i=y_i\partial_{y_i}. +\] + +A good chart can therefore expose drift, scale response, and scale-of-scale +response directly. The new information comes from their transformation and +composition laws, not from pretending that the anchored values are +independent. Because the brackets also escape the finite `3n` span, this +finite generating bundle is not yet a closed Lie algebroid; its closure needs +the completed, filtered fibre described above. + +## 5. Structural interpretation + +The first AMP picture is not a bigger matrix algebra: + +- M/P is one finite affine chart after logarithmic observation; +- A/P interaction opens a completed scale fibre over that chart; +- finite observers take finite quotients of the completion; +- chart transport, support admissibility, and branch data are part of the + object. + +The matrices used to replay affine composition and the polynomials used to +replay a finite truncation are local calculation engines for this structure. diff --git a/sonnet/amp-ensemble-carrier-gate/02-ensemble-calibration.md b/sonnet/amp-ensemble-carrier-gate/02-ensemble-calibration.md new file mode 100644 index 00000000..a21fc7d0 --- /dev/null +++ b/sonnet/amp-ensemble-carrier-gate/02-ensemble-calibration.md @@ -0,0 +1,146 @@ +# Ensemble calibration and computational ledger + +Status: exact for homogeneous independent assembly and the declared coarse +observer. + +## 1. Power as objectified repeated assembly + +Let `Omega` be a finite weighted state space with + +\[ +Z=\sum_{\omega\in\Omega}w(\omega). +\] + +For `N` independent identical copies, Fubini factorization gives + +\[ +Z_{\Omega^N}=Z^N. +\] + +The source ensemble has `|Omega|^N` microstates. The total-partition observer +does not need to enumerate them: it objectifies repeated identical +Multiplication as one Power operation. In the free-energy coordinate +`F=log Z`, the same operation is the dilation + +\[ +F\longmapsto NF. +\] + +This is a strict task-relative software advantage. It is not a lossless +representation of the microscopic ensemble. + +## 2. Nested assembly compiler + +For stages + +\[ +Z_{k+1}=e^{b_k}Z_k^{n_k}, +\qquad +F_k=\log Z_k, +\] + +we have + +\[ +F_{k+1}=n_kF_k+b_k. +\] + +After `h` stages, + +\[ +F_h=\alpha_hF_0+\beta_h, +\] + +with + +\[ +\alpha_h=\prod_{k=0}^{h-1}n_k, +\qquad +\beta_{k+1}=n_k\beta_k+b_k, +\qquad +\beta_0=0. +\] + +The executable folds the history chronologically into `(alpha_h,beta_h)` and +independently records `alpha_h` as the number of base replicas. + +## 3. Frozen cost witness + +Take a three-state base ensemble and twenty binary homogeneous stages. Then + +\[ +\alpha=2^{20}=1{,}048{,}576, +\] + +so literal expansion has more than one million base leaves and + +\[ +3^{1{,}048{,}576} +\] + +Cartesian microstates. The compiled value state is two exact fields: +`(alpha,beta)`. Replaying a supplied `F_0` uses one multiplication and one +addition. + +| Cost axis | Explicit ensemble | AMP-compiled total observer | +|---|---:|---:| +| Base-copy leaves | `1,048,576` | not materialized | +| Microstates | `3^1,048,576` | not materialized | +| Evaluated state | full enumeration or factorized surrogate | 2 fields | +| Width of replica exponent | implicit in expansion | 21 bits | +| Replay after compilation | task dependent | 1 multiply + 1 add | +| Auditable source certificate | full construction or stage list | 20 stages + 2-field normal form | + +The certificate is not falsely counted as constant storage: when stage +parameters vary, the stage list remains an `O(h)` audit trail. Only the +number of evaluated task fields and the scalar-operation count are constant. +Their bit cost still grows with `alpha`, the supplied free energy, and the +requested output precision. For twenty binary stages, storing `alpha` needs +21 bits, while the unmaterialized microstate count needs more than one million +bits even before individual state records are charged. Repeated identical +stages also admit the closed iterate formula from Proposition 1.1. + +## 4. What this opens and what it does not + +The compiler directly helps tasks that ask for: + +- total partition/free-energy values of factorizable repeated systems; +- equivalence of long M/P assembly histories; +- repeated scale cascades with a shared homogeneous rule; +- finite shadows of an A/P perturbation around a dominant power regime. + +It is insufficient for: + +- named microstate reconstruction; +- correlations between replicas; +- interacting assembly where `Z_(A x B) != Z_A Z_B`; +- arbitrary real powers interpreted as literal replica counts; +- a thermodynamic or ordinal limit without a declared topology and observer. + +For an interacting system, write the honest residual + +\[ +R_{AB}=\log Z_{AB}-\log Z_A-\log Z_B. +\] + +The M/P compiler handles the factorized backbone; the residual is the new +information that must be transported in a completion or correlation fibre. +This is why the current result does not reduce the general three-dimensional +Ising problem: its hard content is precisely nonflattening interaction across +scales. + +## 5. Next computational gate + +The smallest nontrivial continuation is a power-dominant interacting map such +as + +\[ +x\longmapsto x^d+t +\] + +near infinity, or its partition analogue. The target is to compile a finite +observer conjugacy to the pure power map, record the residual support and +error, and compare `N` direct iterations with one compiled power iterate. +Classically this is related to a Böttcher coordinate; in the AMP programme it +tests whether the completed A/P fibre produces reusable iteration leverage +rather than only another formal expansion. diff --git a/sonnet/amp-ensemble-carrier-gate/03-carrier-disposition.md b/sonnet/amp-ensemble-carrier-gate/03-carrier-disposition.md new file mode 100644 index 00000000..d4076541 --- /dev/null +++ b/sonnet/amp-ensemble-carrier-gate/03-carrier-disposition.md @@ -0,0 +1,127 @@ +# Carrier and research disposition + +Status: first issue #150 gate. + +## 1. Minimum carriers for the frozen tasks + +| Task | Minimum demonstrated carrier | Surreal status | +|---|---|---| +| Finite M/P word | positive affine normal form in `y=log x` | eliminated | +| Symbolic natural iterate of one M/P map | same normal form with `a^N` | eliminated | +| Homogeneous finite ensemble total | integer replica exponent + affine free-energy state | eliminated | +| Fixed-order A/P tail | finite quotient of a completed ray / specified Hahn fragment | eliminated | +| Fixed finite AMP expression with typed exp/log | finite-stage LE carrier is an upper bound | eliminated as runtime | +| Uniform hyperiteration such as `F(x+1)=exp(F(x))` | hyperserial capability pressure | `No` not separated | +| Conway simplicity/birthday or arbitrary surreal input | surreal-specific observer by definition | software advantage unproved | + +The crucial correction is that Power necessity and surreal necessity are +different questions. Power is already forced as an operation by repeated +ensemble objectification and by the M/P conjugation law. The frozen values +remain in much smaller carriers. + +## 2. Updated primary-source boundary + +The carrier audit in +[`effective-scale-carrier-ladder`](../effective-scale-carrier-ladder/) +remains valid. Current primary work sharpens the semantic side but does not +provide the missing runtime lower bound: + +- Bagayoko, van der Hoeven, and Kaplan construct hyperseries fields closed + under hyperexponentials and hyperlogarithms at declared ordinal strengths; + their construction is an operation-bearing field, not merely `No` as an + ambient ordered field. The paper also leaves further calculus closure and + nested transseries questions explicit. +- Bagayoko constructs hyperseries subfields of `No` with embeddings that + commute with transfinite sums and hyperoperations. This further weakens any + claim that a hyperiteration task alone uniquely forces the whole surreal + class. +- Bagayoko and van der Hoeven equip `No` with hyperserial structure and + represent surreal numbers through hyperseries evaluated at `omega`; neither + theorem is automatically a bounded encoder, lowerer, or cost advantage. +- Mantova's 2026 monotonicity and Taylor theorem gives stronger calculus for + omega-series and LE-series composed with declared infinite arguments. It + does not state an unrestricted effective composition + `No x No -> No`, nor a compiler lower bound against smaller transseries + fields. + +Primary sources: + +1. V. Bagayoko, J. van der Hoeven, E. Kaplan, + [“Hyperserial fields”](https://elliotakaplan.github.io/Hyperserial_fields.pdf), + 2025 manuscript. +2. V. Bagayoko, + [“Hyperseries subfields of surreal numbers”](https://arxiv.org/abs/2409.16251), + 2024. +3. V. Bagayoko, J. van der Hoeven, + [“The hyperserial field of surreal numbers”](https://arxiv.org/abs/2310.14873), + 2023. +4. V. Bagayoko, J. van der Hoeven, + [“Surreal numbers as hyperseries”](https://arxiv.org/abs/2310.14879), + 2023. +5. V. Mantova, + [“Monotonicity and a Taylor approximation theorem for transseries”](https://arxiv.org/abs/2601.07747), + 2026. + +## 3. Surreal entry gate + +Do not introduce a surreal runtime until one frozen natural task supplies all +of: + +1. a proof that finite affine, completed cone/Hahn, LE, and a specified + hyperseries carrier are insufficient; +2. a `No`-specific operation or normalization not inserted only to force the + answer; +3. a finite effective shadow with comparison, truncation, and replay; +4. a measured theorem, reachability, compression, or total-cost advantage; +5. branch, domain, support, and ordinal-strength typing. + +An infinite ensemble is not enough. A thermodynamic limit often lowers to an +ordinary real free-energy density; finite-size asymptotics may fit Hahn or +transseries carriers; cardinal replication is not automatically surreal +arithmetic. + +## 4. Disposition + +The split verdict is: + +```text +AMP research line: EXPAND +surreal runtime for every frozen issue #150 workload: ELIMINATE +overall issue #150 gate: NARROW +``` + +`AMP: EXPAND` is earned by two exact facts: the full Lie closure is genuinely +infinite-dimensional, and Power supplies a replayable homogeneous-ensemble +compiler with an exponential source-state separation for the declared coarse +observer. + +The overall result remains `NARROW` because the computation is a factorized +control rather than a previously unsolved interacting problem. The next gate +must carry a nonzero interaction residual through power iteration and show a +measured advantage over direct iteration and ordinary asymptotic baselines. + +## 5. Programme consequence + +The emerging high-level object is a fibred completion, not one larger number +field: + +\[ +\text{finite M/P affine chart} +\quad+\quad +\text{completed A/P scale fibre} +\quad+\quad +\text{finite observer quotients}. +\] + +This directly extends the AM chamber result. Power acts on the scale lattice; +Addition creates completed tails; observers select finite quotients; surreal +numbers remain one possible semantic envelope only when later ordinal or +simplicity structure is actually task-visible. + +```text +Mathematical Core: unchanged +Research Programme: AMP line expands at T1; universality unchanged +Engineering Architecture: Sonnet-local compiler/certificate only +Theory Map: no promoted node +Experimental/Public API: none +``` diff --git a/sonnet/amp-ensemble-carrier-gate/README.md b/sonnet/amp-ensemble-carrier-gate/README.md new file mode 100644 index 00000000..08824fb2 --- /dev/null +++ b/sonnet/amp-ensemble-carrier-gate/README.md @@ -0,0 +1,29 @@ +# AMP closure and ensemble carrier gate + +This research-local Sonnet answers issue +[#150](https://github.com/mountain/process-geometry/issues/150). + +Read in order: + +1. [`00-problem-frontier.md`](00-problem-frontier.md) freezes the task and + claim ceiling. +2. [`01-closure-theorems.md`](01-closure-theorems.md) separates the finite + M/P subsystem from the infinite A/M/P Lie closure. +3. [`02-ensemble-calibration.md`](02-ensemble-calibration.md) gives the exact + homogeneous-ensemble compiler and its observer-relative cost ledger. +4. [`03-carrier-disposition.md`](03-carrier-disposition.md) states the minimum + carriers, current surreal boundary, and next gate. + +Executable evidence lives in +[`amp_ensemble_compiler.py`](amp_ensemble_compiler.py) and +[`test_amp_ensemble_carrier_gate.py`](../../tests/research/test_amp_ensemble_carrier_gate.py). + +Current result: + +```text +AMP research line: EXPAND +surreal runtime for the frozen workload: ELIMINATE +overall issue disposition: NARROW +``` + +No Mathematical Core, Public API, or runtime dependency changes follow. diff --git a/sonnet/amp-ensemble-carrier-gate/amp_ensemble_compiler.py b/sonnet/amp-ensemble-carrier-gate/amp_ensemble_compiler.py new file mode 100644 index 00000000..ac9d48d2 --- /dev/null +++ b/sonnet/amp-ensemble-carrier-gate/amp_ensemble_compiler.py @@ -0,0 +1,252 @@ +"""Research-local compiler for the finite M/P shadow of an AMP system. + +The positive-real maps + + M_b(x) = exp(b) * x + P_a(x) = x**a + +become affine maps ``y -> a*y + b`` in the logarithmic observer ``y=log x``. +This module records that exact normal form and applies it to homogeneous +ensemble assembly. Addition is deliberately excluded from the finite carrier: +in logarithmic coordinates ``x -> x+t`` contributes ``log(1+t*exp(-y))`` and +therefore an infinite completed ray rather than another affine map. + +This is a Sonnet-local executable certificate, not a Public API. +""" + +from __future__ import annotations + +from dataclasses import dataclass +from fractions import Fraction +from math import prod +from typing import Iterable + + +@dataclass(frozen=True) +class MPNormalForm: + """The logarithmic action ``y -> exponent*y + log_scale``.""" + + exponent: Fraction = Fraction(1) + log_scale: Fraction = Fraction(0) + + def __post_init__(self) -> None: + if self.exponent <= 0: + raise ValueError("the positive-real M/P chart requires exponent > 0") + + def apply_log(self, value: Fraction) -> Fraction: + return self.exponent * value + self.log_scale + + def then(self, later: "MPNormalForm") -> "MPNormalForm": + """Apply ``self`` first and ``later`` second.""" + + return MPNormalForm( + exponent=later.exponent * self.exponent, + log_scale=later.exponent * self.log_scale + later.log_scale, + ) + + def iterate(self, count: int) -> "MPNormalForm": + """Return the exact normal form of ``count`` repeated applications.""" + + if count < 0: + raise ValueError("iteration count must be nonnegative") + if count == 0: + return MPNormalForm() + + exponent = self.exponent**count + if self.exponent == 1: + log_scale = count * self.log_scale + else: + log_scale = self.log_scale * (exponent - 1) / (self.exponent - 1) + return MPNormalForm(exponent=exponent, log_scale=log_scale) + + +def multiplication(log_scale: int | Fraction) -> MPNormalForm: + """Return the M primitive ``x -> exp(log_scale) * x``.""" + + return MPNormalForm(log_scale=Fraction(log_scale)) + + +def power(exponent: int | Fraction) -> MPNormalForm: + """Return the P primitive ``x -> x**exponent`` on the positive chart.""" + + return MPNormalForm(exponent=Fraction(exponent)) + + +def fold_mp(history: Iterable[MPNormalForm]) -> MPNormalForm: + """Compile a chronological M/P word into two exact rational fields.""" + + result = MPNormalForm() + for step in history: + result = result.then(step) + return result + + +@dataclass(frozen=True) +class EnsembleStage: + """One homogeneous assembly ``Z -> exp(b) * Z**replicas``. + + Integer ``replicas`` has a literal Cartesian-product interpretation. + ``log_prefactor`` is kept in the logarithmic observer so compilation stays + exact without pretending that ``exp(b)`` is rational. + """ + + replicas: int + log_prefactor: Fraction = Fraction(0) + + def __post_init__(self) -> None: + if self.replicas < 1: + raise ValueError("a homogeneous ensemble stage needs replicas >= 1") + + def normal_form(self) -> MPNormalForm: + return MPNormalForm( + exponent=Fraction(self.replicas), + log_scale=self.log_prefactor, + ) + + +@dataclass(frozen=True) +class EnsembleCostLedger: + """Costs kept separate from the value certificate. + + ``microstate_count`` is represented symbolically as + ``base_state_count ** total_replicas``. The compiler never materializes + that Cartesian product. + """ + + base_state_count: int + total_replicas: int + stage_count: int + expanded_leaf_count: int + compiled_state_fields: int = 2 + replay_arithmetic_operations: int = 2 + + @property + def microstate_count_power(self) -> tuple[int, int]: + return self.base_state_count, self.total_replicas + + @property + def replica_exponent_bit_length(self) -> int: + """Exact storage width of the positive integer replica exponent.""" + + return self.total_replicas.bit_length() + + @property + def microstate_count_bit_length_lower_bound(self) -> int: + """A bound computed without materializing ``base**replicas``. + + If ``b=floor(log2(base))``, then ``base >= 2**b`` and therefore + ``base**replicas`` needs at least ``b*replicas+1`` binary digits. + """ + + if self.base_state_count == 1: + return 1 + base_log2_floor = self.base_state_count.bit_length() - 1 + return base_log2_floor * self.total_replicas + 1 + + +@dataclass(frozen=True) +class EnsembleFoldCertificate: + """Exact task-relative certificate for total partition/free-energy data.""" + + normal_form: MPNormalForm + ledger: EnsembleCostLedger + + def replay_log_partition(self, base_log_partition: Fraction) -> Fraction: + return self.normal_form.apply_log(base_log_partition) + + +def compile_homogeneous_ensemble( + base_state_count: int, + stages: Iterable[EnsembleStage], +) -> EnsembleFoldCertificate: + """Fold a nested homogeneous ensemble without enumerating microstates.""" + + if base_state_count < 1: + raise ValueError("base_state_count must be positive") + + frozen_stages = tuple(stages) + normal = fold_mp(stage.normal_form() for stage in frozen_stages) + total_replicas = prod(stage.replicas for stage in frozen_stages) + if normal.exponent != total_replicas: + raise AssertionError("ensemble exponent and replica product disagree") + + return EnsembleFoldCertificate( + normal_form=normal, + ledger=EnsembleCostLedger( + base_state_count=base_state_count, + total_replicas=total_replicas, + stage_count=len(frozen_stages), + expanded_leaf_count=total_replicas, + ), + ) + + +def logarithmic_addition_tail( + translation: int | Fraction, + order: int, +) -> tuple[tuple[int, Fraction], ...]: + """Truncate ``log(1 + translation*q)`` through ``q**order`` exactly. + + Here ``q=exp(-y)=1/x``. The returned pairs are ``(ray_degree, + coefficient)`` and form the fixed-observer shadow of Addition in the + logarithmic M/P chart. + """ + + if order < 0: + raise ValueError("observer order must be nonnegative") + t = Fraction(translation) + return tuple( + (degree, Fraction((-1) ** (degree + 1), degree) * t**degree) + for degree in range(1, order + 1) + ) + + +def monomial_vector_field_bracket( + left_power: int, + left_log_degree: int, + right_power: int, + right_log_degree: int, +) -> tuple[tuple[tuple[int, int], int], ...]: + r"""Bracket two fields ``x^m (log x)^n d/dx`` in sparse form. + + The exact identity is + + ``[V_mn,V_pq] = x^(m+p-1) ((p-m)L^(n+q) + + (q-n)L^(n+q-1)) d/dx``. + """ + + if left_log_degree < 0 or right_log_degree < 0: + raise ValueError("logarithmic degrees must be nonnegative") + + x_power = left_power + right_power - 1 + terms: dict[tuple[int, int], int] = {} + + leading = right_power - left_power + if leading: + terms[(x_power, left_log_degree + right_log_degree)] = leading + + lower = right_log_degree - left_log_degree + lower_degree = left_log_degree + right_log_degree - 1 + if lower and lower_degree >= 0: + key = (x_power, lower_degree) + terms[key] = terms.get(key, 0) + lower + + return tuple(sorted(terms.items())) + + +def negative_power_closure_witness(depth: int) -> tuple[int, int]: + r"""Return ``(coefficient, x_power)`` for the ``depth``-th witness. + + From ``V_01 = [A,P]-A`` we obtain ``[A,V_01]=V_-1,0``. Repeated + bracketing with ``A`` gives + + ``ad_A^(depth-1)(V_-1,0) = (-1)^(depth-1)(depth-1)! V_-depth,0``. + """ + + if depth < 1: + raise ValueError("closure depth must be positive") + + coefficient = 1 + for factor in range(1, depth): + coefficient *= -factor + return coefficient, -depth diff --git a/tests/research/test_amp_ensemble_carrier_gate.py b/tests/research/test_amp_ensemble_carrier_gate.py new file mode 100644 index 00000000..c332e00c --- /dev/null +++ b/tests/research/test_amp_ensemble_carrier_gate.py @@ -0,0 +1,214 @@ +"""Exact first-cut tests for AMP closure, ensemble folding, and carrier scope.""" + +from __future__ import annotations + +from fractions import Fraction +import importlib.util +from pathlib import Path +import sys + +import sympy as sp + + +MODULE_PATH = ( + Path(__file__).parents[2] + / "sonnet/amp-ensemble-carrier-gate/amp_ensemble_compiler.py" +) +SPEC = importlib.util.spec_from_file_location("amp_ensemble_compiler", MODULE_PATH) +assert SPEC and SPEC.loader +module = importlib.util.module_from_spec(SPEC) +sys.modules[SPEC.name] = module +SPEC.loader.exec_module(module) + + +def vector_field_bracket(left: sp.Expr, right: sp.Expr, x: sp.Symbol) -> sp.Expr: + """Coefficient of ``[left*d/dx, right*d/dx]``.""" + + return sp.expand(left * sp.diff(right, x) - right * sp.diff(left, x)) + + +def test_adjacent_amp_conjugations_are_exact_in_their_native_charts(): + x, y, s, t, r = sp.symbols("x y s t r", positive=True) + + # M_s A_t M_s^-1 = A_(exp(s)t) in the x chart. + conjugated_addition = sp.exp(s) * (sp.exp(-s) * x + t) + assert sp.simplify(conjugated_addition - (x + sp.exp(s) * t)) == 0 + + # In y=log(x), M_s is translation and P_r is dilation. Therefore + # P_r M_s P_r^-1 = M_(exp(r)s) without a branch simplification oracle. + conjugated_multiplication = sp.exp(r) * (sp.exp(-r) * y + s) + assert sp.simplify(conjugated_multiplication - (y + sp.exp(r) * s)) == 0 + + +def test_amp_generators_leave_their_three_dimensional_span(): + x = sp.symbols("x", positive=True) + A = sp.Integer(1) + M = x + P = x * sp.log(x) + + assert sp.simplify(vector_field_bracket(A, M, x) - A) == 0 + assert sp.simplify(vector_field_bracket(M, P, x) - M) == 0 + assert sp.simplify( + vector_field_bracket(A, P, x) - (1 + sp.log(x)) + ) == 0 + + # A constant linear combination of A, M, and P cannot equal log(x)*d/dx: + # the coefficient of x*log(x) first forces the P coefficient to zero, + # after which the logarithm remains unavailable. + c0, c1, c2 = sp.symbols("c0 c1 c2") + candidate = c0 + c1 * x + c2 * x * sp.log(x) + samples = [sp.E, sp.E**2, sp.E**3, sp.E**4] + equations = [sp.Eq(candidate.subs(x, value), sp.log(value)) for value in samples] + assert sp.solve(equations, (c0, c1, c2), dict=True) == [] + + +def test_general_monomial_logarithmic_bracket_formula(): + x = sp.symbols("x", positive=True) + for m, n, p, q in ((0, 0, 1, 1), (-2, 3, 4, 1), (1, 1, 0, 2)): + left = x**m * sp.log(x) ** n + right = x**p * sp.log(x) ** q + expected = sp.Integer(0) + for (x_power, log_degree), coefficient in module.monomial_vector_field_bracket( + m, n, p, q + ): + expected += coefficient * x**x_power * sp.log(x) ** log_degree + assert sp.simplify(vector_field_bracket(left, right, x) - expected) == 0 + + +def test_full_amp_lie_closure_contains_an_infinite_independent_family(): + witnesses = [module.negative_power_closure_witness(k) for k in range(1, 13)] + + assert [power for _, power in witnesses] == list(range(-1, -13, -1)) + assert [coefficient for coefficient, _ in witnesses[:5]] == [1, -1, 2, -6, 24] + + # Distinct Laurent monomials are linearly independent. A finite sweep of + # exponents records the theorem's explicit witnesses, not a dimension guess. + assert len({power for _, power in witnesses}) == len(witnesses) + + +def test_three_process_labels_per_variable_form_an_anchored_redundant_frame(): + x1, x2 = sp.symbols("x1 x2", positive=True) + + # Columns are A_1, M_1, P_1, A_2, M_2, P_2 in the physical tangent basis. + anchor = sp.Matrix( + [ + [1, x1, x1 * sp.log(x1), 0, 0, 0], + [0, 0, 0, 1, x2, x2 * sp.log(x2)], + ] + ) + + assert anchor.rank() == 2 + assert len(anchor.nullspace()) == 4 + assert anchor * sp.Matrix([-x1, 1, 0, 0, 0, 0]) == sp.zeros(2, 1) + assert anchor * sp.Matrix([0, -sp.log(x1), 1, 0, 0, 0]) == sp.zeros(2, 1) + + +def test_mp_words_compile_to_two_field_affine_normal_forms(): + history = ( + module.multiplication(Fraction(2, 3)), + module.power(Fraction(3, 2)), + module.multiplication(Fraction(-5, 7)), + module.power(2), + ) + normal = module.fold_mp(history) + + direct = Fraction(11, 5) + for step in history: + direct = step.apply_log(direct) + + assert normal.apply_log(Fraction(11, 5)) == direct + assert normal.exponent == 3 + assert normal.log_scale == Fraction(4, 7) + + +def test_mp_conjugation_and_repeated_iteration_have_closed_forms(): + exponent = Fraction(5, 3) + log_scale = Fraction(7, 4) + + conjugated = module.fold_mp( + ( + module.power(1 / exponent), + module.multiplication(log_scale), + module.power(exponent), + ) + ) + assert conjugated == module.multiplication(exponent * log_scale) + + primitive = module.MPNormalForm(exponent=Fraction(3, 2), log_scale=Fraction(5, 7)) + closed = primitive.iterate(40) + replay = module.MPNormalForm() + for _ in range(40): + replay = replay.then(primitive) + assert closed == replay + + +def test_homogeneous_ensemble_folds_without_cartesian_state_enumeration(): + stages = ( + module.EnsembleStage(2, Fraction(1)), + module.EnsembleStage(3, Fraction(-2)), + module.EnsembleStage(2, Fraction(4)), + ) + certificate = module.compile_homogeneous_ensemble(3, stages) + + base_log_partition = Fraction(5) + direct = base_log_partition + for stage in stages: + direct = stage.replicas * direct + stage.log_prefactor + + assert certificate.replay_log_partition(base_log_partition) == direct == 66 + assert certificate.normal_form.exponent == 12 + assert certificate.normal_form.log_scale == 6 + assert certificate.ledger.microstate_count_power == (3, 12) + assert 3**12 == 531_441 + assert certificate.ledger.compiled_state_fields == 2 + + +def test_power_objectifies_a_large_repeated_ensemble_for_a_coarse_observer(): + certificate = module.compile_homogeneous_ensemble( + base_state_count=3, + stages=(module.EnsembleStage(2),) * 20, + ) + + # The total-partition observer stores one exponent and one log prefactor. + # Literal expansion would expose over one million base copies and a + # Cartesian state count of 3**1_048_576. + assert certificate.normal_form.exponent == 1_048_576 + assert certificate.ledger.expanded_leaf_count == 1_048_576 + assert certificate.ledger.microstate_count_power == (3, 1_048_576) + assert certificate.ledger.compiled_state_fields == 2 + assert certificate.ledger.replay_arithmetic_operations == 2 + assert certificate.ledger.replica_exponent_bit_length == 21 + assert certificate.ledger.microstate_count_bit_length_lower_bound == 1_048_577 + + +def test_addition_breaks_the_finite_mp_carrier_but_has_a_fixed_hahn_shadow(): + q, t = sp.symbols("q t") + order = 8 + tail = module.logarithmic_addition_tail(Fraction(2, 3), order) + polynomial = sum(sp.Rational(coefficient.numerator, coefficient.denominator) * q**degree for degree, coefficient in tail) + + exact_series = sp.series(sp.log(1 + sp.Rational(2, 3) * q), q, 0, order + 1).removeO() + assert sp.expand(polynomial - exact_series) == 0 + + # In y=log(x), a translation x->x+t is y->log(exp(y)+t). Its second + # derivative is nonzero, so it is not another affine M/P normal form. + y = sp.symbols("y", real=True) + moved = sp.log(sp.exp(y) + t) + assert sp.simplify(sp.diff(moved, y, 2)) != 0 + + +def test_typed_boundaries_fail_closed(): + for bad_exponent in (0, -1): + try: + module.power(bad_exponent) + except ValueError: + pass + else: # pragma: no cover - explicit fail-closed boundary. + raise AssertionError("nonpositive power exponent was accepted") + + try: + module.compile_homogeneous_ensemble(2, (module.EnsembleStage(0),)) + except ValueError: + pass + else: # pragma: no cover + raise AssertionError("zero-replica ensemble stage was accepted")