From 882e5f8994de7929dd04a9604a063d37b1792f0d Mon Sep 17 00:00:00 2001 From: dmitrii-f-t27 Date: Sat, 17 Oct 2026 18:51:40 -0300 Subject: [PATCH] spec(port): port specs/port/trinity/src/phi-engine/quantum/qutritizer.t27 (Closes #9781) Port gHashTag/trinity:src/phi-engine/quantum/qutritizer.zig (at ee512359254b) as specs/port/trinity/src/phi-engine/quantum/ qutritizer.t27 - Roadmap Stage 5, goal #4547, target t27c gen-rust. The trit-to-qutrit converter's decisions are ported as pure functions and tested (9 tests, 9 pass, 0 vacuous, 49 runtime asserts, 100% function coverage): the uniform 1/sqrt(3) superposition the state starts from (Newton's method replaces the math library sqrt, 40 rounds), the sign-bucket threshold (strictly positive is plus, strictly negative is minus, zero is zero), the strict-majority bias (only a trit class strictly more frequent than BOTH others takes the 0.1 boost - a tie boosts nothing), and the norm that brings the three amplitudes back to unit length; an empty input returns the raw uniform superposition. The QutritState record is carried as a struct with the three amplitudes. The amplitude windows in the tests were measured on the generated code (boosted 0.638479, unboosted 0.544217 for the uniform 0.5773503 + 0.1 bias shape). All four generators (gen, gen-rust, gen-c, gen-verilog) emit this spec before the push. Verified: parse OK, spec-status IMPLEMENTED, typecheck 0 errors, coverage 5/5, test-report 9/9 pass, 0 BLOCKED, gen 0 'not yet implemented', boundary exactly this one file, dupe_scan: all 5 function names unique, bare scan reports zero error lines. Dmitrii Fedorov ([@dmitrii-f-t27](https://github.com/dmitrii-f-t27)) --- .../src/phi-engine/quantum/qutritizer.t27 | 208 ++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 specs/port/trinity/src/phi-engine/quantum/qutritizer.t27 diff --git a/specs/port/trinity/src/phi-engine/quantum/qutritizer.t27 b/specs/port/trinity/src/phi-engine/quantum/qutritizer.t27 new file mode 100644 index 0000000000..3613db4a77 --- /dev/null +++ b/specs/port/trinity/src/phi-engine/quantum/qutritizer.t27 @@ -0,0 +1,208 @@ +module port::trinity::qutritizer; + +// Port of gHashTag/trinity:src/phi-engine/quantum/qutritizer.zig (at +// ee512359254b, ~110 lines) - t27 issue #9781, Roadmap Stage 5 (goal +// #4547), target t27c gen-rust. The trit-to-qutrit converter's decisions +// as pure functions: the uniform 1/sqrt(3) superposition the state starts +// from, the sign-bucket threshold, the strict-majority bias (only a trit +// class strictly more frequent than BOTH others gets the 0.1 boost - a tie +// boosts nothing), and the norm that brings the amplitudes back to unit +// length. Newton's method replaces the math library sqrt, as in the +// earlier sqrt ports of this series. + +// The boost targets of the frequency argmax; NONE covers every tie. +pub const QUTRITIZER_BOOST_MINUS: i32 = 0; +pub const QUTRITIZER_BOOST_ZERO: i32 = 1; +pub const QUTRITIZER_BOOST_PLUS: i32 = 2; +pub const QUTRITIZER_BOOST_NONE: i32 = 3; + +// The MVP bias of the original (line 62). +pub const QUTRITIZER_BIAS: f64 = 0.1; + +// QutritState (original lines 20-27): the three amplitudes of +// psi = alpha|-1> + beta|0> + gamma|+1>. +pub struct QutritState { + alpha: f64, + beta: f64, + gamma: f64, +} + +// Newton's method for sqrt, 40 rounds - the series' portable square root. +pub fn qutritizer_sqrt(x: f64) -> f64 { + if (x <= 0.0) { + return 0.0; + } + var g: f64 = x; + var i: usize = 0; + while (i < 40) { + g = (g + x / g) / 2.0; + i += 1; + } + return g; +} + +// Line 36: the uniform superposition amplitude 1/sqrt(3). +pub fn qutritizer_uniform_amplitude() -> f64 { + const s = qutritizer_sqrt(3.0); + return 1.0 / s; +} + +// Lines 46-54: the MVP threshold - strictly positive trits are plus, +// strictly negative are minus, zero is zero. +pub fn qutritizer_trit_bucket(t: i8) -> i32 { + if (t > 0) { + return 1; + } + if (t < 0) { + return -1; + } + return 0; +} + +// Lines 66-72: only the strictly most frequent class is boosted - ties +// and second places boost nothing. +pub fn qutritizer_strict_argmax(count_minus: i64, count_zero: i64, count_plus: i64) -> i32 { + if (count_minus > count_zero and count_minus > count_plus) { + return QUTRITIZER_BOOST_MINUS; + } + if (count_zero > count_minus and count_zero > count_plus) { + return QUTRITIZER_BOOST_ZERO; + } + if (count_plus > count_minus and count_plus > count_zero) { + return QUTRITIZER_BOOST_PLUS; + } + return QUTRITIZER_BOOST_NONE; +} + +// Line 33: the conversion. The state starts uniform; with at least one +// trit the strictly most frequent class takes the 0.1 bias and the three +// amplitudes are renormalized to unit length; an empty input returns the +// raw uniform superposition. +pub fn tritsToQutrit(trits: []const i8) -> QutritState { + var count_minus: i64 = 0; + var count_zero: i64 = 0; + var count_plus: i64 = 0; + for t in trits { + const bucket = qutritizer_trit_bucket(t); + if (bucket == 1) { + count_plus += 1; + } + if (bucket == -1) { + count_minus += 1; + } + if (bucket == 0) { + count_zero += 1; + } + } + const total: i64 = count_minus + count_zero + count_plus; + const uniform = qutritizer_uniform_amplitude(); + var alpha: f64 = uniform; + var beta: f64 = uniform; + var gamma: f64 = uniform; + if (total > 0) { + const target = qutritizer_strict_argmax(count_minus, count_zero, count_plus); + if (target == QUTRITIZER_BOOST_MINUS) { + alpha = alpha + QUTRITIZER_BIAS; + } + if (target == QUTRITIZER_BOOST_ZERO) { + beta = beta + QUTRITIZER_BIAS; + } + if (target == QUTRITIZER_BOOST_PLUS) { + gamma = gamma + QUTRITIZER_BIAS; + } + const norm = qutritizer_sqrt(alpha * alpha + beta * beta + gamma * gamma); + if (norm > 0.0) { + alpha = alpha / norm; + beta = beta / norm; + gamma = gamma / norm; + } + } + return QutritState { alpha: alpha, beta: beta, gamma: gamma }; +} + +test sqrt_newton_converges { + assert(qutritizer_sqrt(0.0) == 0.0); + assert(qutritizer_sqrt(4.0) > 1.9999); + assert(qutritizer_sqrt(4.0) < 2.0001); + assert(qutritizer_sqrt(9.0) > 2.9998); + assert(qutritizer_sqrt(9.0) < 3.0002); + assert(qutritizer_sqrt(3.0) > 1.7320); + assert(qutritizer_sqrt(3.0) < 1.7321); +} + +test uniform_amplitude_is_inverse_sqrt3 { + const u = qutritizer_uniform_amplitude(); + assert(u > 0.5772); + assert(u < 0.5775); +} + +test bucket_threshold { + assert(qutritizer_trit_bucket(1) == 1); + assert(qutritizer_trit_bucket(13) == 1); + assert(qutritizer_trit_bucket(0) == 0); + assert(qutritizer_trit_bucket(-1) == -1); + assert(qutritizer_trit_bucket(-13) == -1); +} + +test strict_majority_only { + assert(qutritizer_strict_argmax(4, 2, 1) == QUTRITIZER_BOOST_MINUS); + assert(qutritizer_strict_argmax(0, 3, 1) == QUTRITIZER_BOOST_ZERO); + assert(qutritizer_strict_argmax(1, 2, 4) == QUTRITIZER_BOOST_PLUS); + assert(qutritizer_strict_argmax(0, 0, 5) == QUTRITIZER_BOOST_PLUS); + assert(qutritizer_strict_argmax(2, 2, 1) == QUTRITIZER_BOOST_NONE); + assert(qutritizer_strict_argmax(3, 1, 3) == QUTRITIZER_BOOST_NONE); + assert(qutritizer_strict_argmax(1, 1, 1) == QUTRITIZER_BOOST_NONE); +} + +test empty_input_is_raw_uniform { + var none: [0]i8 = []; + const q = tritsToQutrit(&none); + assert(q.alpha > 0.5772); + assert(q.alpha < 0.5775); + assert(q.beta > 0.5772); + assert(q.gamma > 0.5772); +} + +test balanced_input_stays_uniform { + var mixed: [3]i8 = [-1, 0, 1]; + const q = tritsToQutrit(&mixed); + assert(q.alpha > 0.5772); + assert(q.alpha < 0.5775); + assert(q.beta > 0.5772); + assert(q.beta < 0.5775); + assert(q.gamma > 0.5772); + assert(q.gamma < 0.5775); +} + +test zero_majority_boosts_beta { + var zeros: [3]i8 = [0, 0, 0]; + const q = tritsToQutrit(&zeros); + assert(q.beta > 0.637); + assert(q.beta < 0.639); + assert(q.alpha > 0.5441); + assert(q.alpha < 0.5443); + assert(q.gamma > 0.5441); + assert(q.gamma < 0.5443); +} + +test plus_majority_boosts_gamma { + var plus: [3]i8 = [1, 1, 0]; + const q = tritsToQutrit(&plus); + assert(q.gamma > 0.637); + assert(q.gamma < 0.639); + assert(q.beta > 0.5441); + assert(q.beta < 0.5443); + assert(q.alpha > 0.5441); + assert(q.alpha < 0.5443); +} + +test minus_majority_boosts_alpha { + var minus: [3]i8 = [-5, -6, 7]; + const q = tritsToQutrit(&minus); + assert(q.alpha > 0.637); + assert(q.alpha < 0.639); + assert(q.beta > 0.5441); + assert(q.beta < 0.5443); + assert(q.gamma > 0.5441); + assert(q.gamma < 0.5443); +}