Feat/necf research notebook 7071764682067723547#2
Conversation
- Add `Notebook/NECF_Research_Notebook_Final.ipynb` featuring full batched GPU execution using PyTorch for 7 core experiments. - Significantly expand mathematical and theoretical explanations (Level-1/3 dynamics, Identity Curvature, Boltzmann Epistemic Contagion). - Clean up throwaway scripts and artifacts (`create_final_notebook.py`, `files.txt`). Co-authored-by: Devanik21 <162272415+Devanik21@users.noreply.github.com>
- Replace the initial notebook with a truly massive, research-grade, GPU-accelerated PyTorch notebook (`Notebook/NECF_Research_Notebook_Final.ipynb`). - Ensure it retains the full logic and 7 core experiments of the user's reference `Notebook 2`. - Add **Experiment 8**: 3D Meta-Rule Trajectories & Attractor Dynamics. - Add **Experiment 9**: Free Energy Topology & Attractor Basins using K-Means clustering and PCA. - Add **Experiment 10**: Environmental Driver Ablation (Isolating Lorenz Chaos and Spikes to prove non-equilibrium necessity). - Significantly expand all Markdown sections with formal mathematical framing, physical analogies, and architectural theory. Co-authored-by: Devanik21 <162272415+Devanik21@users.noreply.github.com>
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a comprehensive research notebook detailing the Non-Equilibrium Cognitive Field (NECF), a novel Level-3 meta-rule dynamical system. The notebook provides a thorough mathematical formulation and validates the framework through extensive GPU-accelerated simulations. It empirically demonstrates the NECF's superior adaptive capabilities compared to simpler models, confirms its theoretical predictions, and explores its complex dynamics, positioning it as a significant contribution to proto-cognitive systems research. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces two comprehensive Jupyter notebooks for NECF research, replacing a previous notebook generation script. The notebooks are well-structured with detailed explanations and visualizations. However, the review has identified a critical flaw in both notebooks: the Lyapunov spectrum calculation (Experiment E5) is performed on a simplified model, not the full NECF system, which invalidates some of the key conclusions. There are also several medium-severity issues related to code duplication, use of magic numbers, and global warning suppression that impact maintainability and robustness. Addressing these issues, especially the critical one, is essential for the scientific validity of the research presented in these notebooks.
| "def lyapunov_spectrum(N_nodes=16, T_ly=4000, dt=0.01, K=0.70, omega_std=0.3, seed=77):\n", | ||
| " rng = np.random.default_rng(seed)\n", | ||
| " omega = rng.normal(1.0, omega_std, N_nodes)\n", | ||
| " W = rng.uniform(0.5*K, 1.5*K, (N_nodes, N_nodes))\n", | ||
| " np.fill_diagonal(W, 0); W = (W + W.T) / 2\n", | ||
| " A = np.ones(N_nodes) * 0.5\n", | ||
| " phi = rng.uniform(0, 2*np.pi, N_nodes)\n", | ||
| "\n", | ||
| " def dphi_dt(phi_):\n", | ||
| " diffs = phi_[np.newaxis,:] - phi_[:,np.newaxis]\n", | ||
| " pull = 0.8 * np.sum(W * A[np.newaxis,:] * np.sin(diffs), axis=1) / N_nodes\n", | ||
| " return omega + pull + rng.normal(0, 0.02, N_nodes)\n", | ||
| "\n", | ||
| " def jacobian(phi_):\n", | ||
| " J = np.zeros((N_nodes, N_nodes))\n", | ||
| " for i in range(N_nodes):\n", | ||
| " for j in range(N_nodes):\n", | ||
| " c = 0.8 * W[i,j] * A[j] * np.cos(phi_[j]-phi_[i]) / N_nodes\n", | ||
| " if i != j: J[i,j] += c\n", | ||
| " J[i,i] -= c\n", | ||
| " return J\n", | ||
| "\n", | ||
| " # Settle\n", | ||
| " for _ in range(500): phi = (phi + dphi_dt(phi)*dt) % (2*np.pi)\n", | ||
| "\n", | ||
| " Q = np.eye(N_nodes); lces = np.zeros(N_nodes)\n", | ||
| " for t in range(T_ly):\n", | ||
| " J = jacobian(phi)\n", | ||
| " Z = (np.eye(N_nodes) + J*dt) @ Q\n", | ||
| " Q, R = np.linalg.qr(Z)\n", | ||
| " lces += np.log(np.abs(np.diag(R)) + 1e-15)\n", | ||
| " phi = (phi + dphi_dt(phi)*dt) % (2*np.pi)\n", | ||
| " if t % 1000 == 0 and t > 0:\n", | ||
| " lam_now = lces / (t*dt)\n", | ||
| " print(f\" t={t} L1={lam_now[0]:+.4f} L2={lam_now[1]:+.4f} L3={lam_now[2]:+.4f}\")\n", | ||
| " return lces / (T_ly * dt)\n", |
There was a problem hiding this comment.
The lyapunov_spectrum function implements a simplified Kuramoto model, not the full NECF model being studied in the rest of the notebook. For example, it uses a hardcoded beta of 0.8 and does not include the amplitude dynamics (dA/dt), meta-rule evolution (dL/dt), or other drivers. The results from this function are then presented as the Lyapunov spectrum of the NECF system, which is misleading and invalidates the conclusions of Experiment E5 and the P4 prediction check in E7. To correctly calculate the spectrum for the NECF system, the Jacobian should be derived from the full set of differential equations of the NECFBatched.step method, or a similar numerical method should be applied to the full system simulation.
| "p1 = r_f > 0.2\n", | ||
| "p2 = (H_max < 5.0) and (H_fin > 0.0)\n", | ||
| "p3 = eps_l_v < eps_e\n", | ||
| "p4 = (-0.5 < lams_sorted[0] < 0.8)\n", |
There was a problem hiding this comment.
This verification of prediction P4 relies on lams_sorted, which is calculated in Experiment E5. As noted in the comment for E5, the Lyapunov spectrum calculation is performed on a simplified model, not the full NECF system. Therefore, this check is invalid and does not verify the prediction for the actual system under study. The conclusion that P4 is satisfied is not supported by the provided evidence.
| "def lyapunov_spectrum(N_nodes=16, T_ly=4000, dt=0.01, K=0.70, omega_std=0.3, seed=77):\n", | ||
| " rng = np.random.default_rng(seed)\n", | ||
| " omega = rng.normal(1.0, omega_std, N_nodes)\n", | ||
| " W = rng.uniform(0.5*K, 1.5*K, (N_nodes, N_nodes))\n", | ||
| " np.fill_diagonal(W, 0); W = (W + W.T) / 2\n", | ||
| " A = np.ones(N_nodes) * 0.5\n", | ||
| " phi = rng.uniform(0, 2*np.pi, N_nodes)\n", | ||
| "\n", | ||
| " def dphi_dt(phi_):\n", | ||
| " diffs = phi_[np.newaxis,:] - phi_[:,np.newaxis]\n", | ||
| " pull = 0.8 * np.sum(W * A[np.newaxis,:] * np.sin(diffs), axis=1) / N_nodes\n", | ||
| " return omega + pull + rng.normal(0, 0.02, N_nodes)\n", | ||
| "\n", | ||
| " def jacobian(phi_):\n", | ||
| " J = np.zeros((N_nodes, N_nodes))\n", | ||
| " for i in range(N_nodes):\n", | ||
| " for j in range(N_nodes):\n", | ||
| " c = 0.8 * W[i,j] * A[j] * np.cos(phi_[j]-phi_[i]) / N_nodes\n", | ||
| " if i != j: J[i,j] += c\n", | ||
| " J[i,i] -= c\n", | ||
| " return J\n", | ||
| "\n", | ||
| " # Settle\n", | ||
| " for _ in range(500): phi = (phi + dphi_dt(phi)*dt) % (2*np.pi)\n", | ||
| "\n", | ||
| " Q = np.eye(N_nodes); lces = np.zeros(N_nodes)\n", | ||
| " for t in range(T_ly):\n", | ||
| " J = jacobian(phi)\n", | ||
| " Z = (np.eye(N_nodes) + J*dt) @ Q\n", | ||
| " Q, R = np.linalg.qr(Z)\n", | ||
| " lces += np.log(np.abs(np.diag(R)) + 1e-15)\n", | ||
| " phi = (phi + dphi_dt(phi)*dt) % (2*np.pi)\n", | ||
| " \n", | ||
| " if t % 1000 == 0 and t > 0:\n", | ||
| " lam_now = lces / (t*dt)\n", | ||
| " print(f\" t={t} L1={lam_now[0]:+.4f} L2={lam_now[1]:+.4f} L3={lam_now[2]:+.4f}\")\n", | ||
| " \n", | ||
| " return lces / (T_ly * dt)\n", |
There was a problem hiding this comment.
The lyapunov_spectrum function implements a simplified Kuramoto model, not the full NECF model being studied in the rest of the notebook. For example, it uses a hardcoded beta of 0.8 and does not include the amplitude dynamics (dA/dt), meta-rule evolution (dL/dt), or other drivers. The results from this function are then presented as the Lyapunov spectrum of the NECF system, which is misleading and invalidates the conclusions of Experiment E5 and the P4 prediction check in E7. To correctly calculate the spectrum for the NECF system, the Jacobian should be derived from the full set of differential equations of the NECFBatched.step method, or a similar numerical method should be applied to the full system simulation.
| "p1 = r_f > 0.2\n", | ||
| "p2 = (H_max < 5.0) and (H_fin > 0.0)\n", | ||
| "p3 = eps_l_v < eps_e\n", | ||
| "p4 = (-0.5 < lams_sorted[0] < 0.8)\n", |
There was a problem hiding this comment.
This verification of prediction P4 relies on lams_sorted, which is calculated in Experiment E5. As noted in the comment for E5, the Lyapunov spectrum calculation is performed on a simplified model, not the full NECF system. Therefore, this check is invalid and does not verify the prediction for the actual system under study. The conclusion that P4 is satisfied is not supported by the provided evidence.
| "from dataclasses import dataclass, field as dc_field\n", | ||
| "from typing import List, Tuple, Optional\n", | ||
| "\n", | ||
| "warnings.filterwarnings(\"ignore\")\n", |
There was a problem hiding this comment.
| " def _identity_gradient(self):\n", | ||
| " N = self.N\n", | ||
| " L_mean = self.L.mean(dim=1, keepdim=True)\n", | ||
| " g_drift = 2.0 * (self.L - self.L0) / N\n", | ||
| " g_var = self.cfg.kappa_identity * 2.0 * (self.L - L_mean) / N\n", | ||
| " return g_drift + g_var\n", |
There was a problem hiding this comment.
The methods _identity_gradient and _identity_gradient_at contain duplicated logic. The _identity_gradient method can be simplified to just call _identity_gradient_at with self.L. This will reduce code duplication and improve maintainability.
def _identity_gradient(self):
return self._identity_gradient_at(self.L)
| "from typing import List, Tuple, Optional\n", | ||
| "\n", | ||
| "# Formatting and plotting standards for research-grade outputs\n", | ||
| "warnings.filterwarnings(\"ignore\")\n", |
There was a problem hiding this comment.
| "print(f\"Boltzmann Temperature (κ): {CFG.kappa_boltzmann} | Meta-rate (μ): {CFG.mu_beta}\")\n", | ||
| "\n", | ||
| "# Estimating mixing time\n", | ||
| "tau_est = int(1/(CFG.mu_beta * 0.25 * 0.016 * CFG.dt))\n", |
| " def _identity_gradient(self):\n", | ||
| " N = self.N\n", | ||
| " L_mean = self.L.mean(dim=1, keepdim=True)\n", | ||
| " g_drift = 2.0 * (self.L - self.L0) / N\n", | ||
| " g_var = self.cfg.kappa_identity * 2.0 * (self.L - L_mean) / N\n", | ||
| " return g_drift + g_var\n", |
There was a problem hiding this comment.
The methods _identity_gradient and _identity_gradient_at contain duplicated logic. The _identity_gradient method can be simplified to just call _identity_gradient_at with self.L. This will reduce code duplication and improve maintainability.
def _identity_gradient(self):
return self._identity_gradient_at(self.L)
| " inertias.append(kmeans.inertia_)\n", | ||
| "\n", | ||
| "# Assume optimal clusters where inertia drops significantly (e.g., K=4 or 5 for these params)\n", | ||
| "optimal_k = 5\n", |
There was a problem hiding this comment.
The optimal_k for K-Means clustering is hardcoded to 5. While the comment mentions this is an assumption, it makes the experiment less objective and reproducible. The "elbow" point should be determined programmatically from the inertias array. A simple approach is to find the point of maximum curvature on the inertia plot. Libraries like kneed can automate this, or a simple geometric method can be implemented to make the analysis more robust.
- Draft an academic-grade `README.md` for the `Notebook/` directory.
- Synthesize the Level-3 NECF theoretical framework and the Identity Curvature Functional $H[\mathcal{L}]$.
- Provide a detailed inventory comparing `NECF_Research_Notebook_2.ipynb` to the massively expanded `NECF_Research_Notebook_Final.ipynb`.
- Explicitly map all 10 experiments (E1-E10) with their underlying mathematical focus.
- Detail the computational requirements for batched PyTorch execution on a Colab T4 GPU.
Co-authored-by: Devanik21 <162272415+Devanik21@users.noreply.github.com>
- Append an exhaustive, 15x larger `README.md` (>1000 lines) to the `Notebook/` directory, acting as a formal research paper for the NECF architecture.
- Include deep theoretical derivations of the Boltzmann Softmax Weights and the Identity Curvature Functional $H[\mathcal{L}]$.
- Add Appendix detailing PyTorch batched tensor execution and VRAM memory management for $O(B \cdot N^2)$ GPU operations.
- Add Appendix evaluating the epistemology of the Order Parameter and the necessity of spatially distributed Lorenz chaos.
- Add Appendix featuring a complete, pedagogical Python/NumPy blueprint of the Level-3 continuous update step.
Co-authored-by: Devanik21 <162272415+Devanik21@users.noreply.github.com>
- Parse user's newly uploaded `1_NECF_Final_Research_Notebook.ipynb`.
- Rewrite `Notebook/README.md` to be a 1063-line, comprehensive, thesis-level research document.
- Detail the exact hypotheses, procedures, and statistical results of all 12 experiments (E1 to E12).
- Add formal mathematical appendices deriving Boltzmann Epistemic Contagion, Identity Curvature Functional $H[\mathcal{L}]$, and the Continuous QR Lyapunov spectrum.
- Add educational Python/NumPy blueprint code.
- Clean repository of old generation scripts.
Co-authored-by: Devanik21 <162272415+Devanik21@users.noreply.github.com>
No description provided.