diff --git a/Cargo.lock b/Cargo.lock index c2983f44f..e5cf6284b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1311,6 +1311,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "cmb-consciousness" +version = "0.1.0" +dependencies = [ + "rand 0.8.5", + "rand_chacha 0.3.1", + "ruvector-consciousness", +] + [[package]] name = "codespan-reporting" version = "0.11.1" diff --git a/Cargo.toml b/Cargo.toml index 0276959c3..70f33487d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -141,6 +141,7 @@ members = [ # Consciousness metrics (IIT Φ, causal emergence) "crates/ruvector-consciousness", "crates/ruvector-consciousness-wasm", + "examples/cmb-consciousness", ] resolver = "2" diff --git a/examples/cmb-consciousness/Cargo.toml b/examples/cmb-consciousness/Cargo.toml new file mode 100644 index 000000000..8cbab8b02 --- /dev/null +++ b/examples/cmb-consciousness/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "cmb-consciousness" +version = "0.1.0" +edition = "2021" +license = "MIT" +description = "CMB radiation consciousness analysis using IIT Phi, causal emergence, and MinCut" +publish = false + +[[bin]] +name = "cmb-consciousness" +path = "src/main.rs" + +[dependencies] +ruvector-consciousness = { path = "../../crates/ruvector-consciousness", default-features = false, features = ["phi", "emergence", "collapse"] } +rand = "0.8" +rand_chacha = "0.3" diff --git a/examples/cmb-consciousness/RESEARCH.md b/examples/cmb-consciousness/RESEARCH.md new file mode 100644 index 000000000..389619ce3 --- /dev/null +++ b/examples/cmb-consciousness/RESEARCH.md @@ -0,0 +1,453 @@ +# CMB Consciousness Explorer: Applying Integrated Information Theory to Cosmic Microwave Background Radiation + +**Version:** 0.1.0 +**Date:** 2026-03-31 +**Status:** Experimental / Exploratory + +--- + +## 1. Abstract + +This project applies Integrated Information Theory (IIT 4.0) to the angular power spectrum of the Cosmic Microwave Background (CMB) radiation in order to test whether the observed CMB exhibits non-random integrated information structure beyond what is predicted by standard Lambda-CDM cosmology. We construct a Transition Probability Matrix (TPM) from the Planck 2018 TT power spectrum by treating logarithmically binned multipole bands as nodes in a causal network, compute the integrated information Phi across those bands, and compare the result against Monte Carlo null realizations drawn from a Gaussian random field with identical spectral properties. We additionally apply causal emergence analysis (effective information, RSVD spectral emergence) and sliding-window Phi spectroscopy to characterize the informational structure of the CMB across angular scales. We expect the null hypothesis to hold --- that the CMB's informational structure is fully accounted for by the LCDM power spectrum --- but identify the known CMB anomalies (Cold Spot, hemispherical asymmetry, quadrupole-octupole alignment) as candidates for localized Phi excess that merit further investigation. + +--- + +## 2. Scientific Background + +### 2.1 The Cosmic Microwave Background + +The Cosmic Microwave Background (CMB) is the relic thermal radiation from the epoch of recombination, approximately 380,000 years after the Big Bang (redshift z ~ 1100). At this epoch, the universe cooled sufficiently for hydrogen atoms to form, decoupling photons from baryonic matter and producing a nearly isotropic blackbody radiation field that has since redshifted to a present-day temperature of T = 2.72548 +/- 0.00057 K (Fixsen 2009). + +The ESA Planck satellite (2009--2013) produced the most precise full-sky maps of CMB temperature anisotropies to date, achieving angular resolution of approximately 5 arcminutes and sensitivity of delta T/T ~ 10^-6 across nine frequency bands from 30 to 857 GHz (Planck Collaboration 2020a). + +**Angular Power Spectrum.** The statistical properties of the CMB temperature field T(theta, phi) are conventionally characterized by its angular power spectrum C_l, obtained by expanding the temperature fluctuations in spherical harmonics: + + delta T(theta, phi) / T = sum_{l,m} a_{lm} Y_{lm}(theta, phi) + +The angular power spectrum is defined as the variance of the harmonic coefficients: + + C_l = (1 / (2l + 1)) * sum_m |a_{lm}|^2 + +In practice, results are presented as D_l = l(l+1) C_l / (2 pi), which has units of micro-K squared and produces a roughly flat spectrum at low multipoles and prominent acoustic peaks at higher multipoles. + +**Standard LCDM Predictions.** The six-parameter LCDM model predicts the following structure in the CMB power spectrum: + +- **Sachs-Wolfe plateau** (l < 30): Large-angle fluctuations driven by gravitational potential perturbations at the surface of last scattering. The spectrum is approximately flat in D_l, reflecting the nearly scale-invariant Harrison-Zeldovich-Peebles primordial spectrum. + +- **Acoustic peaks** (100 < l < 2500): A series of harmonic peaks produced by acoustic oscillations of the photon-baryon fluid before recombination. The first peak at l ~ 220 corresponds to the mode that completed exactly one half-oscillation by the time of decoupling. The relative heights and positions of the peaks encode the baryon density (Omega_b h^2), the matter density (Omega_m h^2), and the spatial curvature (Omega_k). + +- **Silk damping tail** (l > 1500): Exponential suppression of power at small angular scales due to photon diffusion during recombination. The damping scale depends on the number of relativistic species (N_eff) and the primordial helium fraction (Y_p). + +**Known CMB Anomalies.** Despite the extraordinary success of the LCDM model, several large-angle anomalies have been identified in CMB data at marginal statistical significance: + +- **The Cold Spot** (Cruz et al. 2005): An anomalously cold region approximately 10 degrees in diameter centered near Galactic coordinates (l = 209, b = -57), with temperature decrement approximately -150 micro-K. Its significance depends on the a posteriori correction applied. + +- **Hemispherical power asymmetry** (Eriksen et al. 2004): The CMB variance is approximately 6% larger in one hemisphere than the other, with a preferred axis near (l = 225, b = -22). + +- **Quadrupole-octupole alignment** (Tegmark et al. 2003; de Oliveira-Costa et al. 2004): The l = 2 and l = 3 multipoles share an anomalous alignment of their principal axes, sometimes called the "axis of evil." The probability of such alignment under Gaussian random isotropic assumptions is approximately 1/1000. + +- **Low quadrupole power**: The observed quadrupole C_2 is lower than the LCDM best-fit prediction, though the cosmic variance uncertainty at l = 2 is large. + +These anomalies, while individually of marginal significance, motivate the search for unexpected structure in the CMB using information-theoretic methods that may be sensitive to correlations beyond the two-point function. + +### 2.2 Integrated Information Theory (IIT) + +Integrated Information Theory, developed by Tononi (2004, 2008) and substantially revised in IIT 4.0 (Albantakis et al. 2023), is a mathematical framework for quantifying the degree to which a system possesses irreducible causal structure. Originally developed as a theory of consciousness, the mathematical formalism is applicable to any system describable by a Transition Probability Matrix. + +**Core Concepts.** + +The central quantity in IIT is Phi (the upper-case Greek letter), which measures the integrated information of a system --- the amount of information generated by a system above and beyond the information generated by its parts. + +A system's causal structure is specified by its **Transition Probability Matrix (TPM)**, T, where entry T_{ij} gives the probability of the system transitioning from state i to state j in one time step. For a system of n elements, the TPM is an n x n row-stochastic matrix (each row sums to 1). + +**Minimum Information Partition (MIP).** To compute Phi, one considers all possible bipartitions of the system into two non-empty subsystems A and B. For each partition, one computes the distance between the TPM of the whole system and the product of the TPMs of the parts: + + phi(partition) = d(P_whole, P_A tensor P_B) + +where d is a distance measure and tensor denotes the product distribution. The MIP is the partition that minimizes this distance: + + Phi = min_{partitions} phi(partition) + +A system with Phi > 0 possesses irreducible causal structure: it cannot be fully described by the independent behavior of its parts. + +**IIT 4.0 Updates.** The 2023 revision (Albantakis et al. 2023) introduced several important changes from IIT 3.0: + +- **Intrinsic difference** replaces KL divergence as the distance measure. IIT 4.0 uses the Earth Mover's Distance (Wasserstein-1 metric) because it respects the metric structure of the state space, unlike KL divergence which is topology-blind. For one-dimensional discrete distributions, this reduces to the cumulative L1 difference: + + d_EMD(p, q) = sum_i |sum_{j<=i} (p_j - q_j)| + +- **Intrinsic information** replaces extrinsic (observer-relative) information. All quantities are defined from the system's own perspective. + +- **Cause-effect structure** is computed via cause and effect repertoires for each mechanism-purview pair, measuring how much a mechanism constrains its purview's past (cause repertoire) and future (effect repertoire) relative to the unconstrained maximum-entropy distribution. + +**Algorithmic Complexity.** Exact Phi computation requires enumerating all possible bipartitions, which grows as O(2^n). The `ruvector-consciousness` crate implements four algorithms with different complexity-accuracy tradeoffs: + +| Algorithm | Complexity | Applicability | +|---|---|---| +| Exact | O(2^n * n^2) | n <= 16 elements | +| Spectral | O(n^2 log n) | n <= 1000, good approximation | +| Stochastic | O(k * n^2) | Any n, configurable samples k | +| Greedy Bisection | O(n^3) | Fast lower bound | + +### 2.3 Causal Emergence + +Erik Hoel's causal emergence framework (Hoel et al. 2013; Hoel 2017) addresses a complementary question: can a macro-scale (coarse-grained) description of a system carry more causal information than its micro-scale description? + +**Effective Information (EI).** For a system described by TPM T of dimension n x n, the effective information is: + + EI(T) = (1/n) * sum_{s=1}^{n} D_KL(T_s || U) + +where T_s is the s-th row of T (the transition distribution from state s) and U is the uniform distribution over n states. EI measures how much knowing the current state reduces uncertainty about the future, relative to maximum ignorance. + +EI decomposes into two components: + +- **Determinism**: How precisely each state maps to a unique outcome. + + det(T) = log(n) - (1/n) * sum_s H(T_s) + + where H(T_s) is the Shannon entropy of row s. + +- **Degeneracy**: How many distinct states lead to the same future. + + deg(T) = log(n) - H(column_avg(T)) + + where column_avg(T) is the stationary distribution averaged over columns. + +EI = det - deg (approximately). + +**Causal Emergence.** A system exhibits causal emergence when there exists a coarse-graining (macro-mapping) M that maps micro-states to macro-states such that: + + CE = EI(T_macro) - EI(T_micro) > 0 + +This means the macro-level description is more causally informative than the micro-level description: "the map is better than the territory." + +**SVD-Based Emergence (Zhang et al. 2025).** A complementary approach computes causal emergence from the singular value decomposition of the TPM. The singular values sigma_1 >= sigma_2 >= ... >= sigma_n encode the effective dimensionality of the system's causal structure. Key metrics: + +- **Effective rank**: The exponential of the spectral entropy of the normalized singular values. + + r_eff = exp(-sum_i p_i * log(p_i)) + where p_i = sigma_i / sum_j sigma_j + +- **Spectral entropy**: How evenly distributed the singular values are. Low spectral entropy (few dominant singular values) indicates effective coarse-graining --- the system's causal structure is well-approximated by a lower-dimensional system. + +The `ruvector-consciousness` crate implements randomized SVD via the Halko-Martinsson-Tropp algorithm, achieving O(n^2 * k) complexity instead of O(n^3) for full SVD, where k is the target rank. + +--- + +## 3. Methodology + +### 3.1 Data Source + +The primary data source is the Planck 2018 temperature-temperature (TT) angular power spectrum: + +- **File:** `COM_PowerSpect_CMB-TT-full_R3.01.txt` +- **Source:** Planck Legacy Archive (https://pla.esac.esa.int/) +- **Format:** ASCII table with columns: multipole l, D_l (micro-K^2), lower error bar, upper error bar +- **Coverage:** l = 2 to l ~ 2500 +- **Reference:** Planck Collaboration (2020b), "Planck 2018 results. V. CMB power spectra and likelihoods." + +The power spectrum D_l encodes the variance of temperature fluctuations at each angular scale theta ~ 180/l degrees. It is a complete statistical characterization of the CMB under the assumption of Gaussianity and isotropy (which holds to high precision for l > 30). + +### 3.2 TPM Construction + +The central modeling step is the construction of a Transition Probability Matrix from the angular power spectrum. This step maps the CMB's spectral structure into the formalism required by IIT. The procedure is as follows: + +**Step 1: Logarithmic Binning.** The multipole range [l_min, l_max] is divided into N logarithmically spaced bins. Logarithmic binning is chosen because: + +- The physical processes driving CMB anisotropies operate on logarithmic scales (decades in l correspond to distinct physical regimes). +- The density of independent modes increases as (2l + 1) per multipole, so linear binning would over-represent high-l modes. +- Standard cosmological analysis uses logarithmic or pseudo-logarithmic binning. + +Each bin B_k = [l_k^low, l_k^high] is characterized by its band power: + + P_k = (1 / N_k) * sum_{l in B_k} D_l + +where N_k is the number of multipoles in bin k. + +**Step 2: Cross-Band Correlation Matrix.** The raw correlation between bins i and j is computed from the power spectrum coupling. In the simplest model, the correlation is derived from the band-power covariance, which for a Gaussian random field on the full sky is: + + Cov(P_i, P_j) = (2 / N_i * N_j) * sum_{l in B_i intersect B_j} D_l^2 / (2l + 1) + +For non-overlapping bins (i != j), the correlation arises from mode-coupling due to the survey mask, beam asymmetry, and foreground residuals. In this initial analysis, we adopt a simpler model: the cross-band coupling strength is proportional to the geometric mean of the band powers, modulated by an exponential decay in log-multipole separation: + + W_{ij} = sqrt(P_i * P_j) * exp(-|log(l_i) - log(l_j)| / lambda) + +where l_i is the central multipole of bin i and lambda is a correlation length scale (default: lambda = 1.0 in log-l space, corresponding to one decade of angular scale coupling). + +**Step 3: Row Normalization.** The weight matrix W is converted to a row-stochastic TPM by normalizing each row: + + T_{ij} = W_{ij} / sum_k W_{ik} + +This ensures each row sums to 1, satisfying the TPM constraint. + +**Physical Interpretation.** The resulting TPM encodes the following: entry T_{ij} represents the probability that information (causal influence) at angular scale i propagates to angular scale j. This is a causal model in the IIT sense --- it describes how the system's state at one scale constrains its state at other scales. High T_{ij} means scales i and j are tightly coupled; low T_{ij} means they are causally independent. + +This construction is a modeling choice, not a unique mapping. Alternative TPM constructions (e.g., based on the full covariance matrix, or on pixel-space correlations from HEALPix maps) would yield different results. The sensitivity of Phi to the TPM construction is itself informative and is characterized through the null hypothesis testing described in Section 3.4. + +### 3.3 Analysis Pipeline + +The analysis pipeline consists of five stages, each implemented using the `ruvector-consciousness` crate. + +**Stage 1: Global Phi Computation.** Compute the integrated information Phi of the full N-bin TPM. For N <= 16, exact computation is feasible (enumerate all 2^{N-1} - 1 bipartitions). For larger N, the spectral approximation is used: + + Phi_spectral ~ lambda_2(L) * (1 - lambda_2(L)) + +where lambda_2(L) is the second-smallest eigenvalue of the normalized Laplacian of the TPM, interpreted as a graph. The spectral gap is a well-known proxy for graph connectivity and mixing time. + +**Stage 2: Regional Analysis.** The multipole range is divided into physically motivated regions, and Phi is computed for each region independently: + +| Region | Multipole Range | Physical Process | +|---|---|---| +| Sachs-Wolfe plateau | l = 2--30 | Gravitational potential (ISW) | +| First acoustic peak | l = 100--300 | First compression of baryon-photon fluid | +| Second acoustic peak | l = 400--600 | First rarefaction | +| Third acoustic peak | l = 700--900 | Second compression | +| Damping tail | l = 1500--2500 | Silk diffusion damping | + +Regional analysis tests whether specific physical regimes exhibit more or less integrated structure than others. + +**Stage 3: Sliding Window Phi Spectrum.** A window of width W bins is slid across the full multipole range in steps of S bins. At each position, Phi is computed for the sub-TPM within the window. The resulting Phi(l) curve --- the "Phi spectrum" --- reveals how integrated information varies as a function of angular scale. + +**Stage 4: Causal Emergence Analysis.** For the full TPM, compute: + +- Effective information EI at the micro level (full N-bin TPM) +- A search over coarse-grainings: merge adjacent bins in pairs, triples, etc., and compute EI at each macro level +- Causal emergence CE = EI_macro - EI_micro for each coarse-graining +- Determinism and degeneracy decomposition at each level + +If CE > 0 for some coarse-graining, the CMB's informational structure is better captured at a larger angular scale than the finest binning --- a signature of emergent structure. + +**Stage 5: SVD Emergence Analysis.** Compute the randomized SVD of the TPM and derive: + +- Singular value spectrum sigma_1, ..., sigma_N +- Effective rank r_eff +- Spectral entropy H_sv + +A low effective rank relative to the matrix dimension indicates that the causal structure is compressible --- few modes dominate the system's dynamics. + +### 3.4 Null Hypothesis Testing + +The null hypothesis H_0 is: the observed CMB power spectrum is a realization of a Gaussian random field with the LCDM best-fit power spectrum, and any integrated information it exhibits is consistent with that of such realizations. + +**Null Model Construction.** For each Monte Carlo realization k = 1, ..., N_MC: + +1. Generate a synthetic power spectrum by perturbing the observed D_l values with Gaussian noise drawn from the reported error bars: + + D_l^(k) = D_l^obs + epsilon_l, epsilon_l ~ N(0, sigma_l^2) + + where sigma_l is the average of the upper and lower error bars at multipole l. + +2. Construct a TPM from D_l^(k) using the identical binning and correlation procedure as for the observed data. + +3. Compute Phi, EI, CE, and SVD metrics for the synthetic TPM. + +**Statistical Assessment.** After N_MC >= 100 realizations, we compute: + +- **Z-score**: z = (Phi_obs - mean(Phi_null)) / std(Phi_null) +- **P-value**: fraction of null realizations with Phi >= Phi_obs (one-tailed) +- **Effect size** (Cohen's d): d = (Phi_obs - mean(Phi_null)) / std(Phi_null) + +A result with |z| > 3 (p < 0.003) would be considered nominally significant. However, given the multiple comparisons involved (global Phi, regional Phi, sliding window, EI, CE), a Bonferroni or false discovery rate correction must be applied. + +--- + +## 4. Expected Results + +### 4.1 Null Hypothesis Expectation + +We expect the null hypothesis to hold. The CMB power spectrum is extremely well described by the six-parameter LCDM model (Planck Collaboration 2020c), with reduced chi-squared approximately 1.0 across the full multipole range. The known CMB anomalies are at marginal statistical significance (2--3 sigma before look-elsewhere corrections) and affect primarily the low-l multipoles where cosmic variance is large. + +The TPM constructed from the power spectrum captures only the two-point statistics of the CMB (the power spectrum itself). Since the LCDM model predicts a Gaussian random field, which is fully characterized by its two-point function, the TPM should contain no information beyond what is already in the LCDM prediction. Thus, the Phi of the observed TPM should be statistically consistent with the Phi of null realizations. + +### 4.2 Possible Positive Results + +A statistically significant excess in Phi (z > 3 after multiple-comparison correction) would indicate that the observed power spectrum contains correlated structure beyond what is expected from Gaussian fluctuations with the same spectral shape plus measurement noise. Possible causes, ranked from most to least likely: + +1. **Foreground contamination residuals.** Incomplete subtraction of Galactic dust, synchrotron, or free-free emission could introduce correlated structure across multipole bands. + +2. **Systematic effects.** Beam asymmetry, scan-strategy artifacts, or calibration residuals could produce spurious correlations. + +3. **Non-Gaussian primordial perturbations.** Some inflationary models predict small departures from Gaussianity (f_NL != 0) that would introduce correlations beyond the power spectrum. + +4. **Novel physics.** Topology of the universe, cosmic strings, bubble collisions, or other exotic scenarios could produce localized anomalous structure. + +5. **Structured intelligence or organized information.** The least likely explanation and the most extraordinary claim. Extraordinary evidence would be required, including replication across frequencies, consistency between Planck and WMAP, and spatial localization via HEALPix analysis. + +### 4.3 CMB Anomalies in Phi Space + +The known CMB anomalies primarily affect the low-l multipoles (l < 30), which fall within the Sachs-Wolfe plateau region. We predict: + +- The **low quadrupole** would reduce Phi in the Sachs-Wolfe region (less power means less coupling). +- The **quadrupole-octupole alignment** could produce anomalously high Phi at l = 2--3 if the alignment creates correlated structure between those scales. +- The **hemispherical asymmetry** is not detectable from the full-sky power spectrum alone (it requires hemisphere-separated analysis on HEALPix maps). +- The **Cold Spot** is a localized feature that would require spatially-resolved Phi analysis. + +--- + +## 5. Interpretation Guide + +### 5.1 Reading the Phi Spectrum + +The sliding-window Phi spectrum Phi(l) plots integrated information as a function of central multipole. Key features to look for: + +- **Peaks in Phi(l)** indicate angular scales where the CMB bands are most tightly integrated --- where information about one scale most strongly constrains other scales. We expect peaks near the acoustic peak positions (l ~ 220, 540, 800) because these scales are physically coupled through the photon-baryon fluid dynamics. + +- **Troughs in Phi(l)** indicate scales where the CMB structure is decomposable --- the system behaves like independent parts. We expect troughs between acoustic peaks (at the "valleys" in the power spectrum) and in the damping tail where modes are exponentially suppressed. + +- **Monotonic decline** in the damping tail (l > 1500) would indicate progressive loss of causal structure as Silk damping washes out the primordial correlations. + +### 5.2 Physical Meaning of High and Low Phi + +- **High Phi (Phi >> 0):** The system at those angular scales is irreducibly integrated. No partition of the multipole bands can fully decompose the system's dynamics. Physically, this means the angular scales are tightly coupled and cannot be analyzed independently. This is expected wherever the physical processes (acoustic oscillations, gravitational coupling) create correlations across scales. + +- **Low Phi (Phi ~ 0):** The system is decomposable. The multipole bands within that range behave approximately independently. This is expected in the damping tail, where each mode is driven by independent stochastic perturbations and progressively erased by diffusion. + +- **Phi = 0 exactly:** The system has a partition into independent subsystems. In IIT terms, the system "is not one thing" --- it is two or more causally independent components. + +### 5.3 Limitations + +This analysis has several important limitations that must be considered when interpreting results: + +1. **Two-point statistics only.** The angular power spectrum captures only the two-point correlation function of the CMB temperature field. All information about non-Gaussianity, phase correlations, and higher-order statistics is discarded. A Gaussian random field with the same power spectrum would produce statistically identical TPMs. + +2. **No spatial localization.** The power spectrum is a global (full-sky averaged) statistic. Localized features (Cold Spot, point sources, Sunyaev-Zeldovich clusters) are diluted into the spherical harmonic decomposition. Spatially-resolved analysis requires HEALPix maps (see Section 6). + +3. **Bin count dependence.** The number of bins N directly affects the TPM dimension and therefore the Phi value. More bins increase the state space but also increase noise per bin. The results must be reported as a function of N and compared to null models at the same N. + +4. **TPM construction is non-unique.** The mapping from power spectrum to TPM involves modeling choices (binning scheme, correlation kernel, decay length lambda). Different constructions would yield different Phi values. The null hypothesis testing controls for this by applying the same construction to null realizations, but the absolute Phi value is model-dependent. + +5. **Temporal dynamics are absent.** IIT is designed for systems with temporal dynamics (state at time t determines state at time t+1). The CMB is a snapshot --- a single realization of a spatial random field. Our "temporal" axis is actually angular scale. This is a metaphorical, not literal, application of IIT. + +6. **Computational constraints.** Exact Phi computation is feasible only for N <= 16 bins. For finer resolution, approximate algorithms introduce their own uncertainties. + +--- + +## 6. Future Directions + +### 6.1 Full-Sky HEALPix Analysis + +The most important extension is to move from the angular power spectrum to full-sky pixel-space analysis using HEALPix maps. This would: + +- Enable spatial localization of Phi anomalies (e.g., is the Cold Spot a Phi hotspot?) +- Permit hemisphere-separated analysis to test the hemispherical asymmetry +- Capture non-Gaussian structure that the power spectrum misses +- Allow comparison of different foreground-cleaning methods (Commander, NILC, SEVEM, SMICA) + +The input data would be the Planck SMICA CMB temperature map at HEALPix resolution N_side = 2048 (approximately 50 million pixels). At this resolution, direct TPM construction is infeasible; hierarchical coarse-graining (using the HEALPix nested pixel scheme) or patch-based analysis would be required. + +### 6.2 Multi-Frequency Analysis + +The Planck satellite observed at nine frequencies (30, 44, 70, 100, 143, 217, 353, 545, 857 GHz). Constructing TPMs from individual frequency channels would allow: + +- Disentangling CMB signal from frequency-dependent foregrounds +- Cross-frequency Phi analysis to test for frequency-dependent integrated structure +- Identification of foreground-driven Phi artifacts + +### 6.3 Polarization Spectra + +The CMB is linearly polarized at the approximately 5% level. The polarization power spectra (TE, EE, and the as-yet-undetected BB from primordial gravitational waves) contain independent information about the physics of recombination and inflation. Extending the analysis to: + +- **TE cross-spectrum:** Correlations between temperature and E-mode polarization +- **EE auto-spectrum:** Pure polarization signal, less contaminated by foregrounds +- **BB auto-spectrum:** If detected, would probe tensor perturbations from inflation + +Multi-spectrum TPM construction (using TT, TE, and EE jointly) would provide a richer causal structure with 3N-dimensional state space. + +### 6.4 Foreground Comparison + +Systematically comparing Phi between: + +- Raw frequency maps (CMB + foregrounds) +- Component-separated CMB maps (SMICA, Commander, NILC, SEVEM) +- Foreground-only maps (synchrotron, dust, free-free) + +This comparison would establish whether any observed Phi excess is attributable to foreground residuals rather than primordial signal. + +### 6.5 Non-Gaussianity Detection via Higher-Order Phi + +The standard f_NL parameterization of primordial non-Gaussianity measures the three-point function (bispectrum). IIT-based analysis could provide a complementary non-Gaussianity diagnostic: + +- Compute Phi from the bispectrum B(l_1, l_2, l_3) in addition to the power spectrum +- Construct TPMs from the trispectrum (connected four-point function) +- Compare information content across n-point functions to quantify how much causal structure is captured at each order + +### 6.6 Comparison with Other Cosmological Datasets + +Extend the methodology to: + +- **21 cm hydrogen line** (HERA, SKA): The 3D power spectrum of neutral hydrogen provides a volumetric (rather than projected) probe of cosmic structure. +- **Large-scale structure** (DESI, Euclid): Galaxy power spectra and correlation functions as alternative TPM inputs. +- **Gravitational wave background** (LIGO/Virgo/KAGRA, LISA, PTA): Strain power spectra as probes of integrated information in spacetime dynamics. + +--- + +## 7. References + +Albantakis, L., Barbosa, L., Findlay, G., Grasso, M., Haun, A.M., Marshall, W., Mayner, W.G.P., Zaeemzadeh, A., Boly, M., Juel, B.E., Sasai, S., Fujii, K., David, I., Hendren, J., Lang, J.P., and Tononi, G. (2023). "Integrated Information Theory (IIT) 4.0: Formulating the Properties of Phenomenal Existence in Physical Terms." *PLOS Computational Biology*, 19(10), e1011465. https://doi.org/10.1371/journal.pcbi.1011465 + +Bennett, C.L., Hill, R.S., Hinshaw, G., Larson, D., Smith, K.M., Dunkley, J., Gold, B., Halpern, M., Jarosik, N., Kogut, A., Komatsu, E., Limon, M., Meyer, S.S., Nolta, M.R., Odegard, N., Page, L., Spergel, D.N., Tucker, G.S., Weiland, J.L., Wollack, E., and Wright, E.L. (2011). "Seven-Year Wilkinson Microwave Anisotropy Probe (WMAP) Observations: Are There Cosmic Microwave Background Anomalies?" *The Astrophysical Journal Supplement Series*, 192(2), 17. https://doi.org/10.1088/0067-0049/192/2/17 + +Cruz, M., Martinez-Gonzalez, E., Vielva, P., and Cayon, L. (2005). "Detection of a non-Gaussian spot in WMAP." *Monthly Notices of the Royal Astronomical Society*, 356(1), 29--40. https://doi.org/10.1111/j.1365-2966.2004.08419.x + +de Oliveira-Costa, A., Tegmark, M., Zaldarriaga, M., and Hamilton, A. (2004). "Significance of the largest scale CMB fluctuations in WMAP." *Physical Review D*, 69(6), 063516. https://doi.org/10.1103/PhysRevD.69.063516 + +Eriksen, H.K., Hansen, F.K., Banday, A.J., Gorski, K.M., and Lilje, P.B. (2004). "Asymmetries in the Cosmic Microwave Background Anisotropy Field." *The Astrophysical Journal*, 605(1), 14--20. https://doi.org/10.1086/382267 + +Fixsen, D.J. (2009). "The Temperature of the Cosmic Microwave Background." *The Astrophysical Journal*, 707(2), 916--920. https://doi.org/10.1088/0004-637X/707/2/916 + +Halko, N., Martinsson, P.-G., and Tropp, J. (2011). "Finding structure with randomness: Probabilistic algorithms for constructing approximate matrix decompositions." *SIAM Review*, 53(2), 217--288. https://doi.org/10.1137/090771806 + +Hoel, E.P., Albantakis, L., and Tononi, G. (2013). "Quantifying causal emergence shows that macro can beat micro." *Proceedings of the National Academy of Sciences*, 110(49), 19790--19795. https://doi.org/10.1073/pnas.1314922110 + +Hoel, E.P. (2017). "When the Map is Better Than the Territory." *Entropy*, 19(5), 188. https://doi.org/10.3390/e19050188 + +Planck Collaboration (2020a). "Planck 2018 results. I. Overview and the cosmological legacy of Planck." *Astronomy & Astrophysics*, 641, A1. https://doi.org/10.1051/0004-6361/201833880 + +Planck Collaboration (2020b). "Planck 2018 results. V. CMB power spectra and likelihoods." *Astronomy & Astrophysics*, 641, A5. https://doi.org/10.1051/0004-6361/201936386 + +Planck Collaboration (2020c). "Planck 2018 results. VI. Cosmological parameters." *Astronomy & Astrophysics*, 641, A6. https://doi.org/10.1051/0004-6361/201833910 + +Tegmark, M., de Oliveira-Costa, A., and Hamilton, A. (2003). "A high resolution foreground cleaned CMB map from WMAP." *Physical Review D*, 68(12), 123523. https://doi.org/10.1103/PhysRevD.68.123523 + +Tononi, G. (2004). "An information integration theory of consciousness." *BMC Neuroscience*, 5, 42. https://doi.org/10.1186/1471-2202-5-42 + +Tononi, G. (2008). "Consciousness as Integrated Information: a Provisional Manifesto." *Biological Bulletin*, 215(3), 216--242. https://doi.org/10.2307/25470707 + +Zhang, J., Liu, K., and Hoel, E.P. (2025). "Dynamical reversibility and causal emergence based on SVD." *npj Complexity*. https://doi.org/10.1038/s44260-025-00041-z + +--- + +## Appendix A: Notation Summary + +| Symbol | Meaning | +|---|---| +| l | Multipole moment (angular wavenumber) | +| C_l | Angular power spectrum coefficient | +| D_l | l(l+1) C_l / (2 pi), in micro-K^2 | +| T_{ij} | Transition probability from state i to state j | +| Phi | Integrated information (IIT) | +| EI | Effective information (causal emergence) | +| CE | Causal emergence (EI_macro - EI_micro) | +| MIP | Minimum information partition | +| d_EMD | Earth Mover's Distance (Wasserstein-1) | +| D_KL | Kullback-Leibler divergence | +| H | Shannon entropy | +| sigma_k | k-th singular value | +| r_eff | Effective rank (exp of spectral entropy) | +| N | Number of multipole bins | +| W | Window width (sliding Phi analysis) | +| lambda | Correlation length in log-l space | +| N_MC | Number of Monte Carlo null realizations | + +## Appendix B: Reproducibility + +All results can be reproduced by running: + +```bash +cd examples/cmb-consciousness +cargo run --release +``` + +The analysis uses deterministic seeding (via `rand_chacha`) for all stochastic components, ensuring bitwise reproducibility across runs. The default random seed is 42. + +Dependencies are pinned in `Cargo.toml` and use the `ruvector-consciousness` crate with features `phi`, `emergence`, and `collapse`. diff --git a/examples/cmb-consciousness/src/analysis.rs b/examples/cmb-consciousness/src/analysis.rs new file mode 100644 index 000000000..ff54b08f4 --- /dev/null +++ b/examples/cmb-consciousness/src/analysis.rs @@ -0,0 +1,227 @@ +//! Consciousness analysis pipeline: IIT Phi, causal emergence, null testing. + +use ruvector_consciousness::emergence::CausalEmergenceEngine; +use ruvector_consciousness::phi::auto_compute_phi; +use ruvector_consciousness::rsvd_emergence::{RsvdEmergenceEngine, RsvdEmergenceResult}; +use ruvector_consciousness::traits::EmergenceEngine; +use ruvector_consciousness::types::{ + ComputeBudget, EmergenceResult, PhiResult, + TransitionMatrix as ConsciousnessTPM, +}; + +use crate::data::TransitionMatrix; +use rand::SeedableRng; +use rand_chacha::ChaCha8Rng; + +/// Full analysis results +pub struct AnalysisResults { + pub full_phi: PhiResult, + pub regional_phis: Vec<(String, PhiResult)>, + pub phi_spectrum: Vec<(usize, usize, f64)>, // (start, end, phi) + pub emergence: EmergenceResult, + pub svd_emergence: RsvdEmergenceResult, + pub null_phis: Vec, + pub z_score: f64, + pub p_value: f64, +} + +/// Convert our TPM to the consciousness crate's format +fn to_consciousness_tpm(tpm: &TransitionMatrix) -> ConsciousnessTPM { + ConsciousnessTPM::new(tpm.size, tpm.data.clone()) +} + +/// Extract a sub-TPM for a subset of bins +fn extract_sub_tpm(tpm: &TransitionMatrix, bins: &[usize]) -> ConsciousnessTPM { + let n = bins.len(); + let mut sub = vec![0.0f64; n * n]; + for (si, &bi) in bins.iter().enumerate() { + let row_sum: f64 = bins.iter().map(|&bj| tpm.data[bi * tpm.size + bj]).sum(); + for (sj, &bj) in bins.iter().enumerate() { + sub[si * n + sj] = tpm.data[bi * tpm.size + bj] / row_sum.max(1e-30); + } + } + ConsciousnessTPM::new(n, sub) +} + +/// Run the complete analysis pipeline +pub fn run_analysis( + tpm: &TransitionMatrix, + ps: &crate::data::PowerSpectrum, + n_bins: usize, + alpha: f64, + null_samples: usize, +) -> AnalysisResults { + let budget = ComputeBudget::default(); + let ctpm = to_consciousness_tpm(tpm); + + // 1. Full system Phi + println!("\n--- Computing IIT Phi (full system, n={}) ---", n_bins); + let full_phi = auto_compute_phi(&ctpm, None, &budget) + .expect("Failed to compute Phi for full system"); + println!( + " Phi = {:.6} (algorithm: {}, elapsed: {:?})", + full_phi.phi, full_phi.algorithm, full_phi.elapsed + ); + + // 2. Regional sub-system Phi + let mut regional_phis = Vec::new(); + let regions = define_regions(n_bins, &tpm.bin_centers); + for (name, bins) in ®ions { + if bins.len() >= 2 { + let sub = extract_sub_tpm(tpm, bins); + match auto_compute_phi(&sub, None, &budget) { + Ok(phi) => { + println!(" {} Phi = {:.6} (bins {:?})", name, phi.phi, bins); + regional_phis.push((name.clone(), phi)); + } + Err(e) => { + println!(" {} Phi computation failed: {}", name, e); + } + } + } + } + + // 3. Sliding window Phi spectrum + let window = (n_bins / 4).max(3).min(8); + let mut phi_spectrum = Vec::new(); + for start in 0..=(n_bins.saturating_sub(window)) { + let bins: Vec = (start..start + window).collect(); + let sub = extract_sub_tpm(tpm, &bins); + if let Ok(phi) = auto_compute_phi(&sub, None, &budget) { + phi_spectrum.push((start, start + window, phi.phi)); + } + } + + // 4. Causal emergence + println!("\n--- Causal Emergence Analysis ---"); + let emergence_engine = CausalEmergenceEngine::new(n_bins.min(16)); + let emergence = emergence_engine + .compute_emergence(&ctpm, &budget) + .expect("Failed to compute causal emergence"); + println!( + " EI_micro = {:.4} bits, determinism = {:.4}, degeneracy = {:.4}", + emergence.ei_micro, emergence.determinism, emergence.degeneracy + ); + + // 5. SVD emergence + println!("\n--- SVD Emergence Analysis ---"); + let svd_engine = RsvdEmergenceEngine::default(); + let svd_emergence = svd_engine + .compute(&ctpm, &budget) + .expect("Failed to compute SVD emergence"); + println!( + " Effective rank = {}/{}, entropy = {:.4}, emergence = {:.4}", + svd_emergence.effective_rank, n_bins, + svd_emergence.spectral_entropy, svd_emergence.emergence_index + ); + + // 6. Null hypothesis testing + println!( + "\n--- Null Hypothesis Testing ({} GRF realizations) ---", + null_samples + ); + let mut rng = ChaCha8Rng::seed_from_u64(42); + let mut null_phis = Vec::with_capacity(null_samples); + for i in 0..null_samples { + let null_tpm = crate::data::generate_null_tpm(ps, n_bins, alpha, &mut rng); + let null_ctpm = to_consciousness_tpm(&null_tpm); + if let Ok(null_phi) = auto_compute_phi(&null_ctpm, None, &budget) { + null_phis.push(null_phi.phi); + } + if (i + 1) % 25 == 0 { + print!(" [{}/{}] ", i + 1, null_samples); + } + } + println!(); + + // Compute statistics + let null_mean = if null_phis.is_empty() { + 0.0 + } else { + null_phis.iter().sum::() / null_phis.len() as f64 + }; + let null_std = if null_phis.len() > 1 { + (null_phis + .iter() + .map(|&p| (p - null_mean).powi(2)) + .sum::() + / (null_phis.len() as f64 - 1.0)) + .sqrt() + } else { + 0.0 + }; + let z_score = if null_std > 1e-10 { + (full_phi.phi - null_mean) / null_std + } else { + 0.0 + }; + let p_value = if null_phis.is_empty() { + 1.0 + } else { + null_phis.iter().filter(|&&p| p >= full_phi.phi).count() as f64 + / null_phis.len() as f64 + }; + + AnalysisResults { + full_phi, + regional_phis, + phi_spectrum, + emergence, + svd_emergence, + null_phis, + z_score, + p_value, + } +} + +/// Define physically meaningful regions based on CMB angular scales +fn define_regions(n_bins: usize, centers: &[f64]) -> Vec<(String, Vec)> { + let mut regions = Vec::new(); + + // Sachs-Wolfe plateau: l < 50 + let sw: Vec = centers + .iter() + .enumerate() + .filter(|(_, &c)| c < 50.0) + .map(|(i, _)| i) + .collect(); + if !sw.is_empty() { + regions.push(("Sachs-Wolfe".to_string(), sw)); + } + + // Acoustic peaks: l ~ 100-1000 + let acoustic: Vec = centers + .iter() + .enumerate() + .filter(|(_, &c)| c >= 100.0 && c <= 1000.0) + .map(|(i, _)| i) + .collect(); + if !acoustic.is_empty() { + regions.push(("Acoustic peaks".to_string(), acoustic)); + } + + // Damping tail: l > 1000 + let damping: Vec = centers + .iter() + .enumerate() + .filter(|(_, &c)| c > 1000.0) + .map(|(i, _)| i) + .collect(); + if !damping.is_empty() { + regions.push(("Damping tail".to_string(), damping)); + } + + // First acoustic peak region: l ~ 150-300 + let peak1: Vec = centers + .iter() + .enumerate() + .filter(|(_, &c)| c >= 150.0 && c <= 300.0) + .map(|(i, _)| i) + .collect(); + if !peak1.is_empty() { + regions.push(("1st peak".to_string(), peak1)); + } + + let _ = n_bins; // used for potential future expansion + regions +} diff --git a/examples/cmb-consciousness/src/data.rs b/examples/cmb-consciousness/src/data.rs new file mode 100644 index 000000000..28e253d5a --- /dev/null +++ b/examples/cmb-consciousness/src/data.rs @@ -0,0 +1,219 @@ +//! CMB data acquisition and transition probability matrix construction. + +/// Planck 2018 CMB TT Power Spectrum +const PLANCK_URL: &str = "https://irsa.ipac.caltech.edu/data/Planck/release_3/ancillary-data/cosmoparams/COM_PowerSpect_CMB-TT-full_R3.01.txt"; + +pub struct PowerSpectrum { + pub ells: Vec, + pub d_ells: Vec, + pub errors: Vec, +} + +pub struct TransitionMatrix { + pub size: usize, + pub data: Vec, + pub bin_edges: Vec, + pub bin_centers: Vec, +} + +impl TransitionMatrix { + #[allow(dead_code)] + pub fn row(&self, i: usize) -> &[f64] { + &self.data[i * self.size..(i + 1) * self.size] + } + + #[allow(dead_code)] + pub fn as_flat(&self) -> &[f64] { + &self.data + } +} + +/// Download Planck power spectrum data using curl, with synthetic fallback. +pub fn download_power_spectrum() -> PowerSpectrum { + // Try curl download + if let Ok(output) = std::process::Command::new("curl") + .args(["-sL", "--connect-timeout", "10", PLANCK_URL]) + .output() + { + if output.status.success() { + if let Ok(text) = String::from_utf8(output.stdout) { + if let Some(ps) = parse_planck_tt(&text) { + println!( + "Downloaded Planck 2018 TT power spectrum: {} multipoles", + ps.ells.len() + ); + return ps; + } + } + } + } + + println!("Using synthetic LCDM power spectrum (download unavailable)"); + generate_synthetic_spectrum() +} + +/// Parse Planck TT power spectrum ASCII format. +/// Columns: ell, D_ell, error_minus, error_plus +fn parse_planck_tt(text: &str) -> Option { + let mut ells = Vec::new(); + let mut d_ells = Vec::new(); + let mut errors = Vec::new(); + + for line in text.lines() { + let line = line.trim(); + if line.is_empty() || line.starts_with('#') { + continue; + } + let parts: Vec<&str> = line.split_whitespace().collect(); + if parts.len() >= 4 { + if let (Ok(l), Ok(d), Ok(e1), Ok(e2)) = ( + parts[0].parse::(), + parts[1].parse::(), + parts[2].parse::(), + parts[3].parse::(), + ) { + if l >= 2.0 { + ells.push(l); + d_ells.push(d); + errors.push((e1.abs() + e2.abs()) / 2.0); + } + } + } + } + + if ells.len() > 100 { + Some(PowerSpectrum { + ells, + d_ells, + errors, + }) + } else { + None + } +} + +/// Generate synthetic LCDM power spectrum with acoustic peaks. +fn generate_synthetic_spectrum() -> PowerSpectrum { + let mut ells = Vec::new(); + let mut d_ells = Vec::new(); + let mut errors = Vec::new(); + + for l in 2..=2500 { + let l_f = l as f64; + // Sachs-Wolfe plateau + acoustic oscillations + damping + let sw = 6000.0 / (1.0 + (l_f / 10.0).powi(2)); + let acoustic = 5800.0 + * (l_f * std::f64::consts::PI / 301.0).cos().powi(2) + * (-l_f / 1500.0).exp() + * (l_f / 200.0).min(1.0); + let d_l = (sw + acoustic).max(0.0); + + ells.push(l_f); + d_ells.push(d_l); + errors.push(d_l * 0.02 + 10.0); + } + + PowerSpectrum { + ells, + d_ells, + errors, + } +} + +/// Convert power spectrum to transition probability matrix. +/// +/// Method: +/// 1. Partition multipoles into N logarithmic bins +/// 2. Compute cross-band correlation from power coupling +/// 3. Row-normalize to get transition probabilities +pub fn power_spectrum_to_tpm(ps: &PowerSpectrum, n_bins: usize, alpha: f64) -> TransitionMatrix { + // Log-space bin edges + let l_min = ps.ells[0].ln(); + let l_max = ps.ells.last().unwrap().ln(); + let bin_edges: Vec = (0..=n_bins) + .map(|i| (l_min + (l_max - l_min) * i as f64 / n_bins as f64).exp()) + .collect(); + + let bin_centers: Vec = bin_edges + .windows(2) + .map(|w| (w[0] * w[1]).sqrt()) // geometric mean + .collect(); + + // Compute bin-averaged power + let mut bin_power = vec![0.0f64; n_bins]; + let mut bin_counts = vec![0usize; n_bins]; + + for (&l, &d) in ps.ells.iter().zip(ps.d_ells.iter()) { + for b in 0..n_bins { + if l >= bin_edges[b] && l < bin_edges[b + 1] { + bin_power[b] += d; + bin_counts[b] += 1; + break; + } + } + } + + for b in 0..n_bins { + if bin_counts[b] > 0 { + bin_power[b] /= bin_counts[b] as f64; + } + } + + // Cross-correlation matrix with Gaussian coupling kernel + let mut corr = vec![0.0f64; n_bins * n_bins]; + for i in 0..n_bins { + let w_i = bin_edges[i + 1] - bin_edges[i]; + for j in 0..n_bins { + let w_j = bin_edges[j + 1] - bin_edges[j]; + let delta = (bin_centers[i] - bin_centers[j]).abs(); + let sigma2 = w_i * w_j; + let coupling = (-delta * delta / (2.0 * sigma2.max(1.0))).exp(); + corr[i * n_bins + j] = + (bin_power[i] * bin_power[j]).sqrt().max(1e-10) * coupling; + } + } + + // Row-normalize with sharpness alpha + let mut tpm = vec![0.0f64; n_bins * n_bins]; + for i in 0..n_bins { + let row_sum: f64 = (0..n_bins) + .map(|j| corr[i * n_bins + j].powf(alpha)) + .sum(); + for j in 0..n_bins { + tpm[i * n_bins + j] = corr[i * n_bins + j].powf(alpha) / row_sum.max(1e-30); + } + } + + TransitionMatrix { + size: n_bins, + data: tpm, + bin_edges, + bin_centers, + } +} + +/// Generate a null-model TPM by perturbing the power spectrum within error bars. +pub fn generate_null_tpm( + ps: &PowerSpectrum, + n_bins: usize, + alpha: f64, + rng: &mut impl rand::Rng, +) -> TransitionMatrix { + let perturbed_d_ells: Vec = ps + .d_ells + .iter() + .zip(ps.errors.iter()) + .map(|(&d, &e)| { + let noise: f64 = rng.sample::(rand::distributions::Standard); + (d + noise * e).max(0.0) + }) + .collect(); + + let perturbed_ps = PowerSpectrum { + ells: ps.ells.clone(), + d_ells: perturbed_d_ells, + errors: ps.errors.clone(), + }; + + power_spectrum_to_tpm(&perturbed_ps, n_bins, alpha) +} diff --git a/examples/cmb-consciousness/src/main.rs b/examples/cmb-consciousness/src/main.rs new file mode 100644 index 000000000..a4e1b81e6 --- /dev/null +++ b/examples/cmb-consciousness/src/main.rs @@ -0,0 +1,100 @@ +//! CMB Consciousness Explorer +//! +//! Explores the Cosmic Microwave Background radiation for signatures of +//! integrated information using IIT Phi, causal emergence, and MinCut analysis. + +mod analysis; +mod data; +mod report; + +fn main() { + println!("+==========================================================+"); + println!("| CMB Consciousness Explorer -- IIT 4.0 Analysis |"); + println!("| Searching for integrated information in the CMB |"); + println!("+==========================================================+"); + + // Parse CLI args + let args: Vec = std::env::args().collect(); + let n_bins = parse_arg(&args, "--bins", 16usize); + let null_samples = parse_arg(&args, "--null-samples", 100usize); + let alpha = parse_arg(&args, "--alpha", 1.0f64); + let output = parse_str_arg(&args, "--output", "cmb_report.svg"); + + println!("\nConfiguration:"); + println!(" Bins: {}", n_bins); + println!(" Null samples: {}", null_samples); + println!(" Alpha: {:.1}", alpha); + println!(" Output: {}", output); + + // Step 1: Acquire data + println!("\n=== Step 1: Acquiring CMB Data ==="); + let ps = data::download_power_spectrum(); + println!( + " Multipole range: l = {}..{}", + ps.ells[0] as u32, + *ps.ells.last().unwrap() as u32 + ); + + // Step 2: Construct TPM + println!("\n=== Step 2: Constructing Transition Probability Matrix ==="); + let tpm = data::power_spectrum_to_tpm(&ps, n_bins, alpha); + println!(" TPM size: {}x{}", tpm.size, tpm.size); + println!( + " Bin edges (l): {:?}", + tpm.bin_edges + .iter() + .map(|x| *x as u32) + .collect::>() + ); + + // Step 3: Run analysis + println!("\n=== Step 3: Consciousness Analysis ==="); + let results = analysis::run_analysis(&tpm, &ps, n_bins, alpha, null_samples); + + // Step 4: Generate report + println!("\n=== Step 4: Results ==="); + report::print_summary(&results, &tpm); + + // Step 5: Generate SVG + let svg = report::generate_svg(&results, &tpm, &ps); + std::fs::write(output, &svg).expect("Failed to write SVG report"); + println!("\nSVG report saved to: {}", parse_str_arg(&args, "--output", "cmb_report.svg")); + + // Final verdict + println!("\n+==========================================================+"); + if results.p_value < 0.05 { + println!( + "| RESULT: Anomalous integrated information detected! |" + ); + println!( + "| p = {:.4}, z = {:.2} -- warrants further investigation |", + results.p_value, results.z_score + ); + } else { + println!( + "| RESULT: CMB consistent with Gaussian random field |" + ); + println!( + "| p = {:.4}, z = {:.2} -- no evidence of structured |", + results.p_value, results.z_score + ); + println!( + "| intelligence at this resolution |" + ); + } + println!("+==========================================================+"); +} + +fn parse_arg(args: &[String], name: &str, default: T) -> T { + args.windows(2) + .find(|w| w[0] == name) + .and_then(|w| w[1].parse().ok()) + .unwrap_or(default) +} + +fn parse_str_arg<'a>(args: &'a [String], name: &str, default: &'a str) -> &'a str { + args.windows(2) + .find(|w| w[0] == name) + .map(|w| w[1].as_str()) + .unwrap_or(default) +} diff --git a/examples/cmb-consciousness/src/report.rs b/examples/cmb-consciousness/src/report.rs new file mode 100644 index 000000000..67c163719 --- /dev/null +++ b/examples/cmb-consciousness/src/report.rs @@ -0,0 +1,402 @@ +//! Report generation: text summary and SVG visualization. + +use crate::analysis::AnalysisResults; +use crate::data::{PowerSpectrum, TransitionMatrix}; + +pub fn print_summary(results: &AnalysisResults, tpm: &TransitionMatrix) { + println!("\n--- IIT Phi Analysis ---"); + println!( + "Full system Phi: {:.6} ({})", + results.full_phi.phi, results.full_phi.algorithm + ); + + for (name, phi) in &results.regional_phis { + println!("{:20} Phi = {:.6}", name, phi.phi); + } + + println!("\n--- Phi Spectrum (sliding window) ---"); + let max_phi = results + .phi_spectrum + .iter() + .map(|x| x.2) + .fold(0.0f64, f64::max); + for (start, end, phi) in &results.phi_spectrum { + let bar_len = if max_phi > 0.0 { + (phi / max_phi * 30.0) as usize + } else { + 0 + }; + let l_start = tpm + .bin_centers + .get(*start) + .map(|x| *x as u32) + .unwrap_or(0); + let l_end = tpm + .bin_centers + .get(end.saturating_sub(1)) + .map(|x| *x as u32) + .unwrap_or(0); + println!( + " l={:>4}..{:<4} Phi={:.4} {}", + l_start, + l_end, + phi, + "|".repeat(bar_len) + ); + } + + println!("\n--- Causal Emergence ---"); + println!( + "EI (micro): {:.4} bits", + results.emergence.ei_micro + ); + println!("Determinism: {:.4}", results.emergence.determinism); + println!("Degeneracy: {:.4}", results.emergence.degeneracy); + + println!("\n--- SVD Emergence ---"); + println!( + "Effective rank: {}/{}", + results.svd_emergence.effective_rank, tpm.size + ); + println!( + "Spectral entropy: {:.4}", + results.svd_emergence.spectral_entropy + ); + println!( + "Emergence index: {:.4}", + results.svd_emergence.emergence_index + ); + println!( + "Reversibility: {:.4}", + results.svd_emergence.reversibility + ); + + println!("\n--- Null Hypothesis Testing ---"); + let null_mean = if results.null_phis.is_empty() { + 0.0 + } else { + results.null_phis.iter().sum::() / results.null_phis.len() as f64 + }; + let null_std = if results.null_phis.len() > 1 { + (results + .null_phis + .iter() + .map(|p| (p - null_mean).powi(2)) + .sum::() + / (results.null_phis.len() as f64 - 1.0)) + .sqrt() + } else { + 0.0 + }; + println!("Phi (observed): {:.6}", results.full_phi.phi); + println!("Phi (null mean): {:.6} +/- {:.6}", null_mean, null_std); + println!("z-score: {:.2}", results.z_score); + println!("p-value: {:.4}", results.p_value); +} + +/// Generate a self-contained SVG report with charts. +pub fn generate_svg( + results: &AnalysisResults, + tpm: &TransitionMatrix, + ps: &PowerSpectrum, +) -> String { + let mut svg = String::with_capacity(20_000); + + svg.push_str( + r#" + + + +CMB Consciousness Analysis Report +IIT 4.0 Phi, Causal Emergence, Null Hypothesis Testing +"#, + ); + + // Panel 1: Power spectrum (y=100, h=300) + svg.push_str(&render_power_spectrum(ps, &tpm.bin_edges, 50, 100, 1100, 280)); + + // Panel 2: TPM heatmap (y=420, h=300) + svg.push_str(&render_tpm_heatmap(tpm, 50, 420, 500, 280)); + + // Panel 3: Phi spectrum (y=420, h=300, x=600) + svg.push_str(&render_phi_spectrum( + &results.phi_spectrum, + 600, + 420, + 550, + 280, + )); + + // Panel 4: Null distribution (y=750, h=300) + svg.push_str(&render_null_distribution( + &results.null_phis, + results.full_phi.phi, + 50, + 750, + 1100, + 280, + )); + + // Panel 5: Summary stats (y=1100) + svg.push_str(&render_summary_stats(results, tpm, 50, 1100)); + + svg.push_str("\n"); + svg +} + +fn render_power_spectrum( + ps: &PowerSpectrum, + bin_edges: &[f64], + x: i32, + y: i32, + w: i32, + h: i32, +) -> String { + let mut s = format!("\n", x, y); + s.push_str(&format!( + "CMB TT Power Spectrum (D_l vs l)\n", + w / 2 + )); + s.push_str(&format!( + "\n", + w, h + )); + + let l_max = ps.ells.last().unwrap_or(&2500.0); + let d_max = ps.d_ells.iter().cloned().fold(0.0f64, f64::max).max(1.0); + + // Plot power spectrum as polyline (subsample for SVG size) + let step = (ps.ells.len() / 500).max(1); + s.push_str("\n"); + + // Mark bin edges + for &edge in bin_edges { + if edge > 0.0 { + let px = (edge.ln() / l_max.ln() * w as f64) as i32; + s.push_str(&format!( + "\n", + px, px, h + )); + } + } + + s.push_str("\n"); + s +} + +fn render_tpm_heatmap(tpm: &TransitionMatrix, x: i32, y: i32, w: i32, h: i32) -> String { + let mut s = format!("\n", x, y); + s.push_str(&format!( + "Transition Probability Matrix\n", + w / 2 + )); + + let cell_w = w as f64 / tpm.size as f64; + let cell_h = h as f64 / tpm.size as f64; + let max_val = tpm.data.iter().cloned().fold(0.0f64, f64::max).max(1e-10); + + for i in 0..tpm.size { + for j in 0..tpm.size { + let val = tpm.data[i * tpm.size + j] / max_val; + let r = (255.0 * (1.0 - val)) as u8; + let g = (255.0 * (1.0 - val * 0.5)) as u8; + let b = 255u8; + s.push_str(&format!( + "\n", + j as f64 * cell_w, + i as f64 * cell_h, + cell_w + 0.5, + cell_h + 0.5, + r, + g, + b + )); + } + } + + s.push_str("\n"); + s +} + +fn render_phi_spectrum( + spectrum: &[(usize, usize, f64)], + x: i32, + y: i32, + w: i32, + h: i32, +) -> String { + let mut s = format!("\n", x, y); + s.push_str(&format!( + "Phi Spectrum (sliding window)\n", + w / 2 + )); + s.push_str(&format!( + "\n", + w, h + )); + + let max_phi = spectrum + .iter() + .map(|x| x.2) + .fold(0.0f64, f64::max) + .max(1e-10); + let bar_w = w as f64 / spectrum.len().max(1) as f64; + + for (i, (_, _, phi)) in spectrum.iter().enumerate() { + let bar_h = (phi / max_phi * (h - 30) as f64) as i32; + let bx = (i as f64 * bar_w) as i32 + 1; + s.push_str(&format!( + "\n", + bx, + h - bar_h - 15, + (bar_w - 2.0).max(1.0) as i32, + bar_h + )); + } + + s.push_str("\n"); + s +} + +fn render_null_distribution( + null_phis: &[f64], + observed: f64, + x: i32, + y: i32, + w: i32, + h: i32, +) -> String { + let mut s = format!("\n", x, y); + s.push_str(&format!( + "Null Distribution (GRF) vs Observed Phi\n", + w / 2 + )); + s.push_str(&format!( + "\n", + w, h + )); + + if null_phis.is_empty() { + s.push_str(&format!( + "No null samples\n", + w / 2, + h / 2 + )); + s.push_str("\n"); + return s; + } + + // Histogram of null phis + let n_hist_bins = 30usize; + let phi_min = + null_phis.iter().cloned().fold(f64::INFINITY, f64::min).min(observed) * 0.9; + let phi_max = + null_phis.iter().cloned().fold(0.0f64, f64::max).max(observed) * 1.1; + let range = (phi_max - phi_min).max(1e-10); + let bin_width = range / n_hist_bins as f64; + + let mut hist = vec![0u32; n_hist_bins]; + for &p in null_phis { + let bin = ((p - phi_min) / bin_width).floor() as usize; + if bin < n_hist_bins { + hist[bin] += 1; + } + } + let max_count = *hist.iter().max().unwrap_or(&1); + + let bar_w = w as f64 / n_hist_bins as f64; + for (i, &count) in hist.iter().enumerate() { + let bar_h = (count as f64 / max_count as f64 * (h - 40) as f64) as i32; + s.push_str(&format!( + "\n", + i as f64 * bar_w, + h - bar_h - 20, + bar_w - 1.0, + bar_h + )); + } + + // Mark observed value + let obs_x = ((observed - phi_min) / range * w as f64) as i32; + s.push_str(&format!( + "\n", + obs_x, + obs_x, + h - 20 + )); + s.push_str(&format!( + "Observed\n", + obs_x, + h - 5 + )); + + s.push_str("\n"); + s +} + +fn render_summary_stats(results: &AnalysisResults, tpm: &TransitionMatrix, x: i32, y: i32) -> String { + let mut s = format!("\n", x, y); + s.push_str("Summary Statistics\n"); + + let null_mean = if results.null_phis.is_empty() { + 0.0 + } else { + results.null_phis.iter().sum::() / results.null_phis.len() as f64 + }; + let lines = vec![ + format!( + "Full System Phi: {:.6} (n={})", + results.full_phi.phi, tpm.size + ), + format!( + "Null Mean Phi: {:.6} ({} samples)", + null_mean, + results.null_phis.len() + ), + format!("z-score: {:.3}", results.z_score), + format!("p-value: {:.4}", results.p_value), + format!( + "EI (micro): {:.4} bits", + results.emergence.ei_micro + ), + format!("Determinism: {:.4}", results.emergence.determinism), + format!( + "SVD Eff. Rank: {}/{}", + results.svd_emergence.effective_rank, tpm.size + ), + format!( + "Emergence Index: {:.4}", + results.svd_emergence.emergence_index + ), + if results.p_value < 0.05 { + "Verdict: ANOMALOUS -- warrants investigation".to_string() + } else { + "Verdict: CONSISTENT with Gaussian random field".to_string() + }, + ]; + + for (i, line) in lines.iter().enumerate() { + s.push_str(&format!( + "{}\n", + 20 + i * 18, + line + )); + } + + s.push_str("\n"); + s +}