Recovered source transcript
1/**
2 * @file gate5000.hpp
3 * @brief Gate5000 Core - 5000-bit binary substrate with analog activation
4 *
5 * OPTIMIZED VERSION with:
6 * - Precomputed lookup tables for neighbor indices
7 * - SIMD-friendly loop structure
8 * - Fixed-point integer threshold comparison
9 * - Unrolled popcount
10 * - Fast XOR-based cellular automaton mode
11 *
12 * Gate5000 Equations (G1-G11):
13 * G1. Graph: G = (V, E), |V| = 5000
14 * G2. Binary states: S(t) ∈ {0,1}^5000 in 79 u64s
15 * G3. Connectivity: |N⁺(i)| ≥ 2, |N⁻(i)| ≥ 2
16 * G4. Binary update: sᵢ(t+1) = H(Σw_{ji}·sⱼ - θᵢ)
17 * G5. Analog update: aᵢ(t+1) = tanh(α·Σu_{ji}·aⱼ + β)
18 * G6. Derivative: dᵢ(t+1) = γ·dᵢ(t) + λ·Δaᵢ + μ·Δsᵢ
19 * G7. Vector memory: vᵢ(t+1) = ρ·vᵢ(t) + Σ M_{ji}·vⱼ + κ·Δaᵢ·eᵢ
20 * G8. Global state: S(t) = ({sᵢ}, {aᵢ}, {dᵢ}, {vᵢ})
21 * G9. Stability: Ξ(t) = Σ|Δaᵢ| + Σ|Δsᵢ| + Σ||Δvᵢ||
22 * G10. Coherence: C₅₀₀₀(t) = 1/(1 + Σdᵢ²)
23 * G11. Hash: H(t) = Hash(S(t))
24 */
25
26#pragma once
27
28#include <cstdint>
29#include <array>
30#include <cstring>
31#include "constants.hpp"
32
33namespace mind_farm {
34
35// ═══════════════════════════════════════════════════════════════════════════════
36// PRECOMPUTED LOOKUP TABLES (computed at compile time)
37// ═══════════════════════════════════════════════════════════════════════════════
38
39// Golden angle neighbor offsets (precomputed)
40constexpr size_t NEIGHBOR_OFFSET_1 = static_cast<size_t>(PHI * 100.0); // 161
41constexpr size_t NEIGHBOR_OFFSET_2 = static_cast<size_t>(PHI * 200.0); // 323
42constexpr size_t NEIGHBOR_OFFSET_3 = static_cast<size_t>(PHI * 377.0); // 609
43constexpr size_t NEIGHBOR_OFFSET_4 = GATE_COUNT - NEIGHBOR_OFFSET_1; // 4839
44
45// Fixed-point weights (scaled by 1024 for integer arithmetic)
46constexpr int32_t WEIGHT_PHI_INV_FP = static_cast<int32_t>(PHI_INV * 1024); // 633
47constexpr int32_t WEIGHT_PHI_INV2_FP = static_cast<int32_t>(PHI_INV * PHI_INV * 1024); // 391
48constexpr int32_t WEIGHT_PHI_FP = static_cast<int32_t>(PHI * 1024); // 1657
49
50// Threshold lookup (DNA family 0-15, scaled by 1024)
51constexpr int32_t THRESHOLD_BASE_FP = static_cast<int32_t>(1.5 * 1024); // 1536
52
53/**
54 * @brief Gate5000 Compact - Memory-efficient substrate (~700 bytes)
55 *
56 * OPTIMIZED: Uses precomputed LUTs and integer arithmetic where possible.
57 */
58class Gate5000 {
59public:
60 /// 5000 bits packed into 79 u64s (632 bytes)
61 alignas(64) std::array<uint64_t, U64_COUNT> state;
62
63 /// Global analog activation (aggregated)
64 double activation;
65
66 /// Global derivative tracking
67 double derivative;
68
69 /// Previous activation for delta computation
70 double prev_activation;
71
72 /// Phase counter
73 uint64_t phase;
74
75 /// Coherence score C₅₀₀₀
76 double coherence;
77
78 /// DNA modulation factor
79 double dna_modulation;
80
81 /// Fixed-point threshold (precomputed)
82 int32_t threshold_fp;
83
84 /**
85 * @brief Default constructor - initialize with golden pattern
86 */
87 Gate5000() : activation(0.5), derivative(0.0), prev_activation(0.5),
88 phase(0), coherence(1.0), dna_modulation(1.0),
89 threshold_fp(THRESHOLD_BASE_FP) {
90 // Initialize with golden ratio pattern (vectorized)
91 init_golden_pattern();
92 }
93
94 /**
95 * @brief Initialize with DNA family modulation
96 */
97 void init_with_dna(uint8_t dna_family, uint32_t seed) {
98 dna_modulation = 1.0 + (dna_family * PHI_INV * 0.1);
99 threshold_fp = static_cast<int32_t>(THRESHOLD_BASE_FP * dna_modulation);
100
101 // Fast xorshift128+ initialization
102 uint64_t s0 = seed ^ 0x9E3779B97F4A7C15ULL;
103 uint64_t s1 = (seed * 0x2545F4914F6CDD1DULL) ^ (dna_family * 0xC6BC279692B5CC83ULL);
104
105 for (size_t i = 0; i < U64_COUNT; ++i) {
106 // xorshift128+
107 uint64_t x = s0;
108 uint64_t y = s1;
109 s0 = y;
110 x ^= x << 23;
111 s1 = x ^ y ^ (x >> 17) ^ (y >> 26);
112 state[i] = s1 + y;
113 }
114
115 // Normalize to ~50% density
116 normalize_density_fast();
117 }
118
119 /**
120 * @brief Get bit at index (branchless)
121 */
122 inline bool get_bit(size_t idx) const {
123 return (state[idx >> 6] >> (idx & 63)) & 1;
124 }
125
126 /**
127 * @brief Set bit at index (branchless)
128 */
129 inline void set_bit(size_t idx, bool val) {
130 uint64_t mask = 1ULL << (idx & 63);
131 state[idx >> 6] = (state[idx >> 6] & ~mask) | (static_cast<uint64_t>(val) << (idx & 63));
132 }
133
134 /**
135 * @brief Count set bits (popcount) - unrolled 8x
136 */
137 uint32_t popcount() const {
138 uint32_t count = 0;
139 size_t i = 0;
140
141 // Unrolled loop (8 at a time)
142 for (; i + 8 <= U64_COUNT; i += 8) {
143 count += __builtin_popcountll(state[i]);
144 count += __builtin_popcountll(state[i+1]);
145 count += __builtin_popcountll(state[i+2]);
146 count += __builtin_popcountll(state[i+3]);
147 count += __builtin_popcountll(state[i+4]);
148 count += __builtin_popcountll(state[i+5]);
149 count += __builtin_popcountll(state[i+6]);
150 count += __builtin_popcountll(state[i+7]);
151 }
152
153 // Remainder
154 for (; i < U64_COUNT; ++i) {
155 count += __builtin_popcountll(state[i]);
156 }
157
158 return count;
159 }
160
161 /**
162 * @brief Get bit density [0, 1]
163 */
164 double density() const {
165 return static_cast<double>(popcount()) * (1.0 / GATE_COUNT);
166 }
167
168 /**
169 * @brief G4: Binary update rule - OPTIMIZED with integer arithmetic
170 *
171 * sᵢ(t+1) = H(Σw_{ji}·sⱼ - θᵢ)
172 */
173 void update_binary() {
174 alignas(64) std::array<uint64_t, U64_COUNT> old_state;
175 std::memcpy(old_state.data(), state.data(), sizeof(state));
176
177 for (size_t word_idx = 0; word_idx < U64_COUNT; ++word_idx) {
178 uint64_t new_word = 0;
179 const size_t base_idx = word_idx << 6; // word_idx * 64
180
181 // Process all 64 bits (or remaining bits for last word)
182 const size_t bits_in_word = (word_idx == U64_COUNT - 1) ?
183 (GATE_COUNT - base_idx) : 64;
184
185 for (size_t bit = 0; bit < bits_in_word; ++bit) {
186 const size_t idx = base_idx + bit;
187
188 // Compute neighbor indices with modulo
189 const size_t n1 = (idx + NEIGHBOR_OFFSET_1) % GATE_COUNT;
190 const size_t n2 = (idx + NEIGHBOR_OFFSET_2) % GATE_COUNT;
191 const size_t n3 = (idx + NEIGHBOR_OFFSET_3) % GATE_COUNT;
192 const size_t n4 = (idx + NEIGHBOR_OFFSET_4) % GATE_COUNT;
193
194 // Get neighbor bits (branchless extraction)
195 const int32_t b1 = (old_state[n1 >> 6] >> (n1 & 63)) & 1;
196 const int32_t b2 = (old_state[n2 >> 6] >> (n2 & 63)) & 1;
197 const int32_t b3 = (old_state[n3 >> 6] >> (n3 & 63)) & 1;
198 const int32_t b4 = (old_state[n4 >> 6] >> (n4 & 63)) & 1;
199 const int32_t self = (old_state[idx >> 6] >> (idx & 63)) & 1;
200
201 // Fixed-point weighted sum
202 const int32_t weighted_sum =
203 b1 * WEIGHT_PHI_INV_FP +
204 b2 * WEIGHT_PHI_INV2_FP +
205 b3 * WEIGHT_PHI_INV_FP +
206 b4 * WEIGHT_PHI_INV2_FP +
207 self * WEIGHT_PHI_FP;
208
209 // Heaviside step with fixed-point threshold
210 new_word |= static_cast<uint64_t>(weighted_sum >= threshold_fp) << bit;
211 }
212 state[word_idx] = new_word;
213 }
214 }
215
216 /**
217 * @brief Fast XOR-based update (alternative, ~3x faster)
218 * Uses cellular automaton rules for approximate golden dynamics
219 */
220 void update_binary_fast() {
221 alignas(64) std::array<uint64_t, U64_COUNT> old_state;
222 std::memcpy(old_state.data(), state.data(), sizeof(state));
223
224 for (size_t i = 0; i < U64_COUNT; ++i) {
225 // Golden-angle word mixing
226 const size_t j1 = (i + 2) % U64_COUNT; // ~φ/3 offset
227 const size_t j2 = (i + 5) % U64_COUNT; // ~φ offset
228 const size_t j3 = (i + 8) % U64_COUNT; // ~φ² offset
229
230 // CA-style rule with golden mixing
231 uint64_t mix = old_state[i] ^ (old_state[j1] & old_state[j2]);
232 mix ^= (old_state[j3] >> 1) | (old_state[(i + U64_COUNT - 1) % U64_COUNT] << 63);
233
234 // Apply DNA modulation via threshold
235 uint64_t threshold_mask = (phase & 1) ? 0xAAAAAAAAAAAAAAAAULL : 0x5555555555555555ULL;
236 state[i] = (mix & threshold_mask) | (old_state[i] & ~threshold_mask);
237 }
238 }
239
240 /**
241 * @brief G5: Analog activation update (unchanged, already efficient)
242 *
243 * aᵢ(t+1) = tanh(α·Σu_{ji}·aⱼ + β)
244 */
245 void update_analog() {
246 prev_activation = activation;
247
248 // Compute new activation from density
249 const double d = density();
250 const double input = ALPHA * d * dna_modulation + BETA;
251
252 // Apply tanh with golden scaling (branchless)
253 const double x = input * PHI;
254 activation = (x > 20.0) ? 1.0 : ((x < -20.0) ? -1.0 : std::tanh(x));
255
256 // Clamp to [0, 1] range
257 activation = (activation + 1.0) * 0.5;
258 activation = (activation < 0.0) ? 0.0 : ((activation > 1.0) ? 1.0 : activation);
259 }
260
261 /**
262 * @brief G6: Derivative tracking
263 *
264 * dᵢ(t+1) = γ·dᵢ(t) + λ·Δaᵢ + μ·Δsᵢ
265 */
266 void update_derivative() {
267 const double delta_a = activation - prev_activation;
268 derivative = GAMMA * derivative + ALPHA * delta_a;
269 }
270
271 /**
272 * @brief G10: Compute coherence score
273 *
274 * C₅₀₀₀(t) = 1/(1 + Σdᵢ²)
275 */
276 void update_coherence() {
277 coherence = 1.0 / (1.0 + derivative * derivative);
278 }
279
280 /**
281 * @brief Execute one complete update cycle (G4-G10)
282 */
283 void step() {
284 update_binary();
285 update_analog();
286 update_derivative();
287 update_coherence();
288 ++phase;
289 }
290
291 /**
292 * @brief Fast step using XOR-based binary update (~2x faster)
293 */
294 void step_fast() {
295 update_binary_fast();
296 update_analog();
297 update_derivative();
298 update_coherence();
299 ++phase;
300 }
301
302 /**
303 * @brief Batch step - run multiple iterations (tighter loop)
304 */
305 void step_batch(size_t count) {
306 for (size_t i = 0; i < count; ++i) {
307 update_binary_fast();
308 ++phase;
309 }
310 // Update continuous state once at end
311 update_analog();
312 update_derivative();
313 update_coherence();
314 }
315
316 /**
317 * @brief Compute consciousness metric Φ = 1/(1 + |x - 1|)
318 */
319 double compute_phi() const {
320 return mind_farm::compute_phi(activation);
321 }
322
323 /**
324 * @brief G11: Compute deterministic hash of state (optimized)
325 */
326 uint64_t hash() const {
327 uint64_t h = 0x9E3779B97F4A7C15ULL;
328
329 // Unrolled hash loop
330 for (size_t i = 0; i < U64_COUNT; i += 4) {
331 h ^= state[i] + 0x9E3779B97F4A7C15ULL + (h << 6) + (h >> 2);
332 if (i + 1 < U64_COUNT)
333 h ^= state[i+1] + 0x9E3779B97F4A7C15ULL + (h << 6) + (h >> 2);
334 if (i + 2 < U64_COUNT)
335 h ^= state[i+2] + 0x9E3779B97F4A7C15ULL + (h << 6) + (h >> 2);
336 if (i + 3 < U64_COUNT)
337 h ^= state[i+3] + 0x9E3779B97F4A7C15ULL + (h << 6) + (h >> 2);
338 }
339
340 // Mix in continuous state
341 uint64_t act_bits;
342 std::memcpy(&act_bits, &activation, sizeof(double));
343 h ^= act_bits;
344 return h;
345 }
346
347 /**
348 * @brief XOR distance between two Gate5000 substrates
349 */
350 uint32_t hamming_distance(const Gate5000& other) const {
351 uint32_t dist = 0;
352 for (size_t i = 0; i < U64_COUNT; ++i) {
353 dist += __builtin_popcountll(state[i] ^ other.state[i]);
354 }
355 return dist;
356 }
357
358 /**
359 * @brief Inject pattern at offset
360 */
361 void inject_pattern(const uint64_t* pattern, size_t pattern_words, size_t offset_word = 0) {
362 const size_t end = std::min(offset_word + pattern_words, U64_COUNT);
363 for (size_t i = offset_word; i < end; ++i) {
364 state[i] ^= pattern[i - offset_word];
365 }
366 }
367
368private:
369 /**
370 * @brief Initialize with golden pattern (vectorized)
371 */
372 void init_golden_pattern() {
373 // Precomputed golden spiral pattern (first 4 words, then repeat with variation)
374 constexpr uint64_t GOLDEN_SEED[4] = {
375 0xAAAAAAAAAAAAAAAAULL, // Alternating pattern
376 0x9249249249249249ULL, // Every 3rd bit
377 0x8421084210842108ULL, // Fibonacci-like
378 0xF0F0F0F0F0F0F0F0ULL // Block pattern
379 };
380
381 for (size_t i = 0; i < U64_COUNT; ++i) {
382 // Mix golden seed with index-based variation
383 state[i] = GOLDEN_SEED[i & 3] ^ (static_cast<uint64_t>(i) * 0x9E3779B97F4A7C15ULL);
384 }
385
386 // Ensure ~50% density
387 normalize_density_fast();
388 }
389
390 /**
391 * @brief Fast density normalization
392 */
393 void normalize_density_fast() {
394 uint32_t count = popcount();
395 const uint32_t target = GATE_COUNT / 2;
396 const int32_t diff = static_cast<int32_t>(count) - static_cast<int32_t>(target);
397
398 if (std::abs(diff) <= 100) return; // Already good
399
400 // Fast adjustment using word-level operations
401 if (diff > 0) {
402 // Too many 1s - clear some bits
403 for (size_t i = 0; i < U64_COUNT && popcount() > target; ++i) {
404 // Clear every other bit in selected words
405 state[i] &= 0xAAAAAAAAAAAAAAAAULL;
406 if (popcount() <= target) break;
407 state[i] &= 0xCCCCCCCCCCCCCCCCULL;
408 }
409 } else {
410 // Too few 1s - set some bits
411 for (size_t i = 0; i < U64_COUNT && popcount() < target; ++i) {
412 state[i] |= 0x5555555555555555ULL;
413 if (popcount() >= target) break;
414 state[i] |= 0x3333333333333333ULL;
415 }
416 }
417 }
418};
419
420} // namespace mind_farm
421