Skip to content

feat: Add QEF brain - #78

Merged
chrisjz merged 42 commits into
mainfrom
feat/add-qef-brain
Mar 17, 2026
Merged

feat: Add QEF brain#78
chrisjz merged 42 commits into
mainfrom
feat/add-qef-brain

Conversation

@chrisjz

@chrisjz chrisjz commented Mar 17, 2026

Copy link
Copy Markdown
Member

Changes:

  • Add QEF brain
  • Add feature expansion and gating to MLP PPO brain
  • Add MI analysis script for QEF brain

Summary by CodeRabbit

  • New Features

    • Added QEF (Quantum Entangled Features) brain architecture, MLPPPO feature-expansion and gating options, and many new example configs (QEF & MLPPPO: foraging, pursuit/stationary predators, thermotaxis, separable/paired/modal variants, fair comparisons).
  • Documentation

    • Updated architecture listings, README, CONTRIBUTING, and agent docs to include QEF and explicit architecture numbering/postfixes (including new “fair” postfix).
  • Tests

    • Added extensive unit and smoke tests covering QEF, feature expansion, gating, and training flows.
  • Tools

    • Added a mutual-information analysis script for feature comparisons.

@coderabbitai

coderabbitai Bot commented Mar 17, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a new QEF (Quantum Entangled Features) brain end-to-end: implementation, config schema and wiring, many example YAMLs (including "fair" ablations), MLPPPO feature-expansion/gating support, extensive tests and smoke integration, OpenSpec docs, and an MI analysis script.

Changes

Cohort / File(s) Summary
Core QEF implementation
packages/quantum-nematode/quantumnematode/brain/arch/qef.py
New QEFBrain and QEFBrainConfig implementing PQC-based feature extraction, entanglement topologies (modality_paired/ring/random), encoding/gate modes, Z/ZZ/(optional ZZZ)/cos-sin/xyz features, hybrid input, feature gating, separate critic support, and PPO integration.
Registry & wiring
packages/.../brain/arch/dtypes.py, packages/.../brain/arch/__init__.py, packages/.../utils/config_loader.py, packages/.../utils/brain_factory.py
Registered BrainType.QEF, exported QEF classes, added "qef": QEFBrainConfig to BRAIN_CONFIG_MAP, and extended factory to validate/instantiate QEFBrain.
MLPPPO feature expansion & gating
packages/.../brain/arch/mlpppo.py
Added feature_expansion (none
Example configs
configs/examples/qef_*.yml, configs/examples/mlpppo_*.yml, configs/examples/*_fair.yml, configs/examples/qrh_pursuit_predators_small.yml
Many new QEF example YAMLs (foraging, pursuit/stationary predators, thermotaxis, modality_paired/separable/ring variants), new MLPPPO fair configs, and one small config tweak (penalty_health_damage).
Tests & smoke
packages/.../tests/.../test_qef.py, packages/.../tests/.../test_mlpppo.py, packages/.../tests/.../test_smoke.py
Large new test suites for QEF and MLPPPO feature-expansion/gating; added qef_foraging_small.yml to smoke tests.
OpenSpec & docs
openspec/changes/.../add-qef-brain/*, openspec/specs/*, AGENTS.md, CONTRIBUTING.md, README.md, openspec/config.yaml
New OpenSpec proposal/design/specs/tasks for QEF, updated architecture listings/numbering, documentation edits to include QEF and new “fair” postfix.
Analysis script
scripts/qef_mi_analysis.py
New CLI script computing MI for entangled/separable/QRH features with permutation tests and JSON/text outputs.
Misc
openspec/changes/archive/2026-03-17-add-qef-brain/.openspec.yaml
New OpenSpec archive metadata file.

Sequence Diagram(s)

sequenceDiagram
    actor Env
    participant Agent as QEF Agent
    participant PQC as Quantum Circuit (PQC)
    participant FE as Feature Extractor
    participant Gate as Feature Gating
    participant Readout as PPO Readout
    participant PPO as PPO Trainer

    Env->>Agent: observe(state)
    Agent->>PQC: encode(state, encoding_mode)
    PQC->>PQC: apply entanglement(topology, depth)
    PQC-->>FE: statevector
    FE->>FE: extract features (Z, ZZ, [ZZZ], cos/sin/xyz)
    FE->>Gate: quantum features
    Agent->>Gate: raw sensory features (if hybrid)
    Gate->>Readout: gated features
    Readout->>Agent: action, value
    Agent->>Env: step(action)
    Agent->>PPO: collect rollout
    PPO->>Readout: minibatch update (apply gating gradients)
    Readout->>PPO: updated params
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Poem

🐰
I hopped through circuits, qubits in tow,
Eight small spins where entangled breezes blow.
Features bloom, gates blink with a twitch,
PPO hums softly — learning takes a stitch.
Carrot-coded cheer, hop! 🥕✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat: Add QEF brain' directly and clearly summarizes the main change — introduction of a new QEF (Quantum Entangled Features) brain architecture, which is the central focus of the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 95.60% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/add-qef-brain
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@chrisjz
chrisjz marked this pull request as ready for review March 17, 2026 07:42
@codecov

codecov Bot commented Mar 17, 2026

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (3)
configs/examples/mlpppo_thermotaxis_stationary_predators_large_fair.yml (1)

7-8: Remove no-op “was” entries in the changelog header.

These bullets read like changes, but the values are identical, which makes the diff summary less reliable.

Proposed cleanup
-# - rollout_buffer_size: 1024 (was 1024) — matches QEF
-# - num_minibatches: 4 (was 4) — matches QEF
+# - rollout_buffer_size: 1024 — matches QEF
+# - num_minibatches: 4 — matches QEF
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@configs/examples/mlpppo_thermotaxis_stationary_predators_large_fair.yml`
around lines 7 - 8, The changelog header contains no-op entries that repeat
identical values for rollout_buffer_size and num_minibatches; edit the header in
configs/examples/mlpppo_thermotaxis_stationary_predators_large_fair.yml to
remove the “(was 1024)” and “(was 4)” parenthetical notes (or delete those
bullet lines entirely) so the changelog only lists real changes—target the lines
mentioning rollout_buffer_size and num_minibatches to make the cleanup.
scripts/qef_mi_analysis.py (1)

364-441: Performance consideration: MI computed twice per permutation iteration.

Each permutation iteration calls mutual_info_classif twice (lines 415-426), which involves k-NN computation. With the default 1000 permutations, this results in 2000 MI calculations. While acceptable for this analysis script, this may become slow for larger datasets.

Consider caching the MI computation or adding a progress indicator for long-running analyses.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/qef_mi_analysis.py` around lines 364 - 441, The loop in
permutation_test computes mutual_info_classif twice per iteration (perm_a and
perm_b), which is expensive; fix by memoizing MI results: create a dict cache
keyed by a stable identifier of the permuted matrix (e.g., perm_a.tobytes() or a
hash) and lookup before calling mutual_info_classif for perm_a and perm_b, so
each unique permuted matrix is evaluated only once; optionally wrap the
permutation loop with a progress bar (tqdm) to surface long-running
progress—refer to permutation_test, perm_a, perm_b, mutual_info_classif, and
num_permutations when implementing.
packages/quantum-nematode/tests/quantumnematode_tests/brain/arch/test_qef.py (1)

155-159: Minor: Unused variable could use underscore convention.

The zz_part at line 157 is assigned but only used to validate the segment exists. Consider using _ prefix for clarity.

💡 Optional style improvement
-        _ = result[n : n + num_zz]  # zz_part — validates segment exists
+        _zz_part = result[n : n + num_zz]  # validates segment exists
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/quantum-nematode/tests/quantumnematode_tests/brain/arch/test_qef.py`
around lines 155 - 159, The slice assigned to validate the zz segment is
currently stored in a lone underscore ("_ = result[n : n + num_zz]") which is
ambiguous; rename it to a clearly unused-but-descriptive variable like
"_zz_part" (and update the inline comment if desired) so the intent to validate
the zz segment is obvious—modify the assignment in the test where z_part, zz
slice, cos_part, and sin_part are extracted (the variables z_part, _/zz slice,
cos_part, sin_part) to use _zz_part instead of a bare underscore.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@configs/examples/qef_pursuit_predators_small_modality_paired.yml`:
- Around line 5-13: Update the header comment "Modality-paired CZ pairs:
food↔nociception (0,2)(1,3)(4,6)(5,7)" to accurately state that only the sensory
cross-modal CZ pairs are (0,2) and (1,3) and that qubits 4–7 are
relay/superposition qubits (not additional food↔nociception couplings); adjust
the explanatory lines below (Feature breakdown / total features) if needed so
they no longer imply four modality-paired CZ links and instead describe the
2-module case with relays/superposition qubits.

In
`@configs/examples/qef_thermotaxis_pursuit_predators_large_modality_paired.yml`:
- Around line 5-14: The example claims "modality_paired" but qef.py currently
hardcodes pairs (0,2),(1,3),(4,6),(5,7) (see modality_paired handling around the
pair-list logic), which mispairs qubits when the active sensory_modules set is
{food_chemotaxis, nociception, thermotaxis}; fix by replacing the hardcoded pair
list with logic that derives paired edges from the active sensory_modules
mapping (or add a validation/guard in the modality_paired branch that
rejects/adjusts examples where modules don't map to the expected qubit layout),
i.e., compute the paired qubit tuples from sensory_modules (or compute a
modality->qubit index map) before creating modality_paired pairs, and
update/validate the example so it truly represents modality-paired coupling.

In `@packages/quantum-nematode/quantumnematode/brain/arch/mlpppo.py`:
- Around line 397-401: The gate_weights parameter is added to the optimizer but
is not included in the gradient clipping call, so after loss.backward() its
gradients bypass clip_grad_norm_; update the clipping logic (the clip_grad_norm_
call(s) that currently only target self.actor.parameters() and
self.critic.parameters()) to also include self.gate_weights when
self._feature_gating is true (or compute a combined list like
list(self.actor.parameters()) + list(self.critic.parameters()) +
([self.gate_weights] if self._feature_gating else [])); apply this change at
both places where clip_grad_norm_ is invoked so gate_weights gradients are
clipped consistently before optimizer.step().

In `@packages/quantum-nematode/quantumnematode/brain/arch/qef.py`:
- Around line 574-579: Add a configuration validation to prevent the unsupported
combination where gating expects raw input dims but receives quantum features:
in QEFBrainConfig (validate_hybrid_dependencies) check if hybrid_input is False
while gating/mode is "context" or "mixed" (or any gate config that expects
_raw_input_dim) and raise a ValueError with a clear message; additionally, in
QEFBrain.__init__ guard or assert the same invariant so the instance cannot be
constructed, and ensure code paths that call _compute_gate(x) are only reachable
when hybrid_input True (or when gate network is compatible with quantum feature
dims) to avoid runtime dimension mismatches with _compute_gate and
_raw_input_dim.

---

Nitpick comments:
In `@configs/examples/mlpppo_thermotaxis_stationary_predators_large_fair.yml`:
- Around line 7-8: The changelog header contains no-op entries that repeat
identical values for rollout_buffer_size and num_minibatches; edit the header in
configs/examples/mlpppo_thermotaxis_stationary_predators_large_fair.yml to
remove the “(was 1024)” and “(was 4)” parenthetical notes (or delete those
bullet lines entirely) so the changelog only lists real changes—target the lines
mentioning rollout_buffer_size and num_minibatches to make the cleanup.

In
`@packages/quantum-nematode/tests/quantumnematode_tests/brain/arch/test_qef.py`:
- Around line 155-159: The slice assigned to validate the zz segment is
currently stored in a lone underscore ("_ = result[n : n + num_zz]") which is
ambiguous; rename it to a clearly unused-but-descriptive variable like
"_zz_part" (and update the inline comment if desired) so the intent to validate
the zz segment is obvious—modify the assignment in the test where z_part, zz
slice, cos_part, and sin_part are extracted (the variables z_part, _/zz slice,
cos_part, sin_part) to use _zz_part instead of a bare underscore.

In `@scripts/qef_mi_analysis.py`:
- Around line 364-441: The loop in permutation_test computes mutual_info_classif
twice per iteration (perm_a and perm_b), which is expensive; fix by memoizing MI
results: create a dict cache keyed by a stable identifier of the permuted matrix
(e.g., perm_a.tobytes() or a hash) and lookup before calling mutual_info_classif
for perm_a and perm_b, so each unique permuted matrix is evaluated only once;
optionally wrap the permutation loop with a progress bar (tqdm) to surface
long-running progress—refer to permutation_test, perm_a, perm_b,
mutual_info_classif, and num_permutations when implementing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8f4d2bc5-e2a5-4b8c-b6c3-708f729ef0fa

📥 Commits

Reviewing files that changed from the base of the PR and between d498874 and a576dcb.

📒 Files selected for processing (34)
  • AGENTS.md
  • CONTRIBUTING.md
  • README.md
  • configs/examples/mlpppo_pursuit_predators_small_fair.yml
  • configs/examples/mlpppo_thermotaxis_pursuit_predators_large_fair.yml
  • configs/examples/mlpppo_thermotaxis_stationary_predators_large_fair.yml
  • configs/examples/qef_foraging_small.yml
  • configs/examples/qef_foraging_small_separable.yml
  • configs/examples/qef_pursuit_predators_small.yml
  • configs/examples/qef_pursuit_predators_small_modality_paired.yml
  • configs/examples/qef_pursuit_predators_small_ring_compact.yml
  • configs/examples/qef_thermotaxis_pursuit_predators_large.yml
  • configs/examples/qef_thermotaxis_pursuit_predators_large_modality_paired.yml
  • configs/examples/qef_thermotaxis_stationary_predators_large.yml
  • configs/examples/qrh_pursuit_predators_small.yml
  • openspec/changes/archive/2026-03-17-add-qef-brain/.openspec.yaml
  • openspec/changes/archive/2026-03-17-add-qef-brain/design.md
  • openspec/changes/archive/2026-03-17-add-qef-brain/proposal.md
  • openspec/changes/archive/2026-03-17-add-qef-brain/specs/brain-architecture/spec.md
  • openspec/changes/archive/2026-03-17-add-qef-brain/specs/qef-brain/spec.md
  • openspec/changes/archive/2026-03-17-add-qef-brain/tasks.md
  • openspec/config.yaml
  • openspec/specs/brain-architecture/spec.md
  • openspec/specs/qef-brain/spec.md
  • packages/quantum-nematode/quantumnematode/brain/arch/__init__.py
  • packages/quantum-nematode/quantumnematode/brain/arch/dtypes.py
  • packages/quantum-nematode/quantumnematode/brain/arch/mlpppo.py
  • packages/quantum-nematode/quantumnematode/brain/arch/qef.py
  • packages/quantum-nematode/quantumnematode/utils/brain_factory.py
  • packages/quantum-nematode/quantumnematode/utils/config_loader.py
  • packages/quantum-nematode/tests/quantumnematode_tests/brain/arch/test_mlpppo.py
  • packages/quantum-nematode/tests/quantumnematode_tests/brain/arch/test_qef.py
  • packages/quantum-nematode/tests/quantumnematode_tests/test_smoke.py
  • scripts/qef_mi_analysis.py

Comment thread configs/examples/qef_pursuit_predators_small_modality_paired.yml Outdated
Comment thread configs/examples/qef_thermotaxis_pursuit_predators_large_modality_paired.yml Outdated
Comment thread packages/quantum-nematode/quantumnematode/brain/arch/mlpppo.py
Comment thread packages/quantum-nematode/quantumnematode/brain/arch/mlpppo.py
Comment thread packages/quantum-nematode/quantumnematode/brain/arch/qef.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
packages/quantum-nematode/quantumnematode/brain/arch/mlpppo.py (1)

131-137: ⚠️ Potential issue | 🟠 Major

Random projection still breaks dimension-matched ablation semantics.

Line 135 says this mode “matches QEF feature dim”, but Line 440 sets self.input_dim = raw + feature_expansion_dim.
With 7 raw features and feature_expansion_dim=52, this produces 59 features, not 52.

💡 Suggested fix
     elif config.feature_expansion == "random_projection":
+        if config.feature_expansion_dim <= self._raw_input_dim:
+            msg = "feature_expansion_dim must be greater than raw input dimension"
+            raise ValueError(msg)
+        projected_dim = config.feature_expansion_dim - self._raw_input_dim
         rng = np.random.default_rng(config.feature_expansion_seed)
         self._projection_matrix = rng.standard_normal(
-            (self._raw_input_dim, config.feature_expansion_dim),
+            (self._raw_input_dim, projected_dim),
         ).astype(np.float32) / np.sqrt(self._raw_input_dim)
-        self.input_dim = self._raw_input_dim + config.feature_expansion_dim
+        self.input_dim = config.feature_expansion_dim
         logger.info(
             f"Random projection expansion: {self._raw_input_dim} raw + "
-            f"{config.feature_expansion_dim} projected = {self.input_dim} total features",
+            f"{projected_dim} projected = {self.input_dim} total features",
         )

Also applies to: 435-443

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@configs/examples/mlpppo_thermotaxis_pursuit_predators_large_fair.yml`:
- Around line 1-12: The config filename uses an unsupported postfix `_fair`;
rename the file mlpppo_thermotaxis_pursuit_predators_large_fair.yml to follow
the accepted pattern by replacing `_fair` with a supported postfix (e.g.,
`_classical` or `_finetune`) or remove the postfix entirely so it becomes
mlpppo_thermotaxis_pursuit_predators_large.yml; after renaming, update any
references to this filename in examples/indexes or scripts that load example
configs (search for mlpppo_thermotaxis_pursuit_predators_large_fair) to ensure
consistency.

In `@packages/quantum-nematode/quantumnematode/brain/arch/qef.py`:
- Around line 858-867: The random topology builder (_build_random_topology) uses
the global MODALITY_PAIRED_CZ length instead of the filtered modality_paired
count, so for small num_qubits it can pick more CZ edges than the actual
modality-paired set; change the code to derive num_cz from the already-filtered
modality_paired list (the same one computed around lines 847-851) by using its
length, then clamp with max_pairs (as already done) before sampling; apply the
same fix where the modality_paired count is used elsewhere in that region so
both branches use the filtered count rather than the global constant.
- Around line 507-515: The _quantum_feature_dim calculation currently uses
self.include_cossin which can undercount when feature_mode == "xyz" because the
feature emitter (in the block around the code that emits X+Y+Z and optional ZZ
at lines ~980-1003) always outputs X,Y,Z regardless of include_cossin; update
_quantum_feature_dim to compute size based on the active feature_mode (and
zz_mode/include_zzz) rather than blindly passing include_cossin, or override
include_cossin to True when self.feature_mode == "xyz"; ensure the dimension
matches the emitter logic (reference _quantum_feature_dim, self.feature_mode,
self.include_cossin, self.include_zzz and the emitter that generates X+Y+Z
(+ZZ)).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6dee654e-8a30-4319-be36-fe7bd39e37de

📥 Commits

Reviewing files that changed from the base of the PR and between a576dcb and 84b6cdc.

📒 Files selected for processing (7)
  • configs/examples/mlpppo_thermotaxis_pursuit_predators_large_fair.yml
  • configs/examples/mlpppo_thermotaxis_stationary_predators_large_fair.yml
  • configs/examples/qef_pursuit_predators_small_modality_paired.yml
  • configs/examples/qef_thermotaxis_pursuit_predators_large_modality_paired.yml
  • packages/quantum-nematode/quantumnematode/brain/arch/mlpppo.py
  • packages/quantum-nematode/quantumnematode/brain/arch/qef.py
  • packages/quantum-nematode/tests/quantumnematode_tests/brain/arch/test_qef.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • configs/examples/qef_pursuit_predators_small_modality_paired.yml
  • configs/examples/mlpppo_thermotaxis_stationary_predators_large_fair.yml
  • configs/examples/qef_thermotaxis_pursuit_predators_large_modality_paired.yml

Comment thread packages/quantum-nematode/quantumnematode/brain/arch/qef.py
Comment thread packages/quantum-nematode/quantumnematode/brain/arch/qef.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
packages/quantum-nematode/quantumnematode/brain/arch/mlpppo.py (1)

416-417: Use NumPy-style docstrings on new helper methods.

The newly added helper methods use short docstrings; project rules ask for NumPy-style function/class docstrings.

As per coding guidelines: "Use NumPy-style docstrings for functions and classes".

Also applies to: 520-521, 588-589

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/quantum-nematode/quantumnematode/brain/arch/mlpppo.py` around lines
416 - 417, Update the short docstring in the helper method
_init_feature_expansion (and the other newly added helper methods noted in the
review) to follow the project's NumPy-style docstring convention: add a one-line
summary, a short description if needed, and explicit sections for Parameters
(type and description) and Returns (type and description) and any Notes/Examples
if relevant; ensure the signature names (e.g., config: MLPPPOBrainConfig) appear
in Parameters and that the docstring is triple-quoted and placed immediately
under the def.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/quantum-nematode/quantumnematode/brain/arch/mlpppo.py`:
- Around line 388-396: The code silently disables self._feature_gating when
config.feature_expansion == "none"; instead, in the initialization block that
checks self._feature_gating and config.feature_expansion, validate compatibility
and raise a ValueError (with a clear message referencing feature_gating and
feature_expansion) if feature_gating is requested but feature_expansion is
"none" (rather than flipping self._feature_gating to False); keep the existing
setup of gate_weights and the log line when valid, and only permit the
silent-disable path to be removed or converted to an explicit error to fail
fast.

In `@packages/quantum-nematode/quantumnematode/brain/arch/qef.py`:
- Around line 855-859: _build_ring_topology currently returns both (0,1) and
(1,0) when num_qubits == 2 which duplicates the same CZ edge; change the builder
to produce each undirected edge only once (e.g., for general n produce
(i,(i+1)%n) but filter or normalize so reversed duplicates are removed —
simplest: if self.num_qubits <= 2 return [(0,1)] when n==2 and [] when n<2, or
build using normalized tuples (min,max) and deduplicate before returning; update
_build_ring_topology accordingly so gate_mode="cz" doesn't apply the same CZ
twice.
- Around line 991-998: The Y-channel expectation calculation in y_expectations
incorrectly uses np.imag(np.conj(statevector[high]) * statevector[low]) which
flips the Pauli-Y sign; update the computation in the block that references
_low_indices, _high_indices, statevector and y_expectations so it uses the
correct ordering (e.g., np.imag(np.conj(statevector[low]) * statevector[high])
or negate the current result) to restore the standard 2 * Im(<low|high>) sign
for Y expectations.

---

Nitpick comments:
In `@packages/quantum-nematode/quantumnematode/brain/arch/mlpppo.py`:
- Around line 416-417: Update the short docstring in the helper method
_init_feature_expansion (and the other newly added helper methods noted in the
review) to follow the project's NumPy-style docstring convention: add a one-line
summary, a short description if needed, and explicit sections for Parameters
(type and description) and Returns (type and description) and any Notes/Examples
if relevant; ensure the signature names (e.g., config: MLPPPOBrainConfig) appear
in Parameters and that the docstring is triple-quoted and placed immediately
under the def.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: edf4693b-f2ab-4461-9c5a-9a740fe0d497

📥 Commits

Reviewing files that changed from the base of the PR and between 84b6cdc and dc9b5bc.

📒 Files selected for processing (3)
  • AGENTS.md
  • packages/quantum-nematode/quantumnematode/brain/arch/mlpppo.py
  • packages/quantum-nematode/quantumnematode/brain/arch/qef.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • AGENTS.md

Comment thread packages/quantum-nematode/quantumnematode/brain/arch/mlpppo.py Outdated
Comment thread packages/quantum-nematode/quantumnematode/brain/arch/qef.py
Comment thread packages/quantum-nematode/quantumnematode/brain/arch/qef.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
packages/quantum-nematode/tests/quantumnematode_tests/brain/arch/test_mlpppo.py (1)

830-1110: Add explicit return type annotations to the newly added test methods.

Several newly added methods (e.g., Line [849], Line [861], Line [974], Line [1091]) omit return annotations. Please add -> None (or concrete return type) for consistency with repo typing standards.

As per coding guidelines "Provide comprehensive type annotations in all code".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/quantum-nematode/tests/quantumnematode_tests/brain/arch/test_mlpppo.py`
around lines 830 - 1110, Several newly added test methods (e.g.,
test_config_defaults, test_no_expansion_preserves_dim,
test_polynomial_output_values, test_gating_without_expansion_raises and other
tests in these classes) are missing explicit return type annotations; update
each test function signature to include -> None to match repo typing standards
(for example change "def test_...(self):" to "def test_...(self) -> None:") and
ensure all other new test methods in the file follow the same pattern.
packages/quantum-nematode/quantumnematode/brain/arch/qef.py (2)

339-345: Require device explicitly in the constructor.

Keeping device: DeviceType = DeviceType.CPU makes direct construction silently bypass the factory-owned device selection. Please drop the default so QEF matches the rest of brain/arch.

Based on learnings, "Architectures under packages/quantum-nematode/quantumnematode/brain/arch/ (e.g., QLIFLSTMBrain, CRH, QRC, etc.) should have their constructors require an explicit device: DeviceType parameter, with the brain factory (utils/brain_factory.py) responsible for reading config.device_type and passing it to the brain constructor."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/quantum-nematode/quantumnematode/brain/arch/qef.py` around lines 339
- 345, The QEF __init__ currently defaults device to DeviceType.CPU which
bypasses the factory selection; change the constructor signature in
quantumnematode.brain.arch.qef (the __init__ taking config: QEFBrainConfig,
num_actions, device: DeviceType = DeviceType.CPU, action_set) to require device:
DeviceType (remove the default), and update call sites (e.g., brain factory in
utils/brain_factory.py) to explicitly pass the device read from
config.device_type so QEF matches other architectures like
QLIFLSTMBrain/CRH/QRC.

167-173: Please convert the new public class docstrings to NumPy style.

QEFBrainConfig and QEFBrain are documented, but they still don't follow the repository's Parameters/Returns docstring format.

As per coding guidelines, "Use NumPy-style docstrings for functions and classes".

Also applies to: 328-335

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/quantum-nematode/quantumnematode/brain/arch/qef.py` around lines 167
- 173, The class docstrings for QEFBrainConfig and QEFBrain are not in NumPy
style; update both class-level docstrings to follow NumPy conventions by adding
a short summary line, a blank line, and a Parameters section (with parameter
names, types, and descriptions) for any init/config fields and a
Returns/Attributes section if applicable; specifically modify the docstrings in
the QEFBrainConfig class and the QEFBrain class (referenced around methods/lines
where these classes are defined) to include "Parameters" and
"Returns/Attributes" sections per the repo guideline and mirror the style used
by ReservoirHybridBaseConfig for names and types.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/quantum-nematode/quantumnematode/brain/arch/mlpppo.py`:
- Around line 436-441: Validate config.feature_expansion_dim before constructing
the random projection: in the block where config.feature_expansion ==
"random_projection" (around creation of rng, self._projection_matrix and
assignment to self.input_dim), check that config.feature_expansion_dim is an
integer > 0 and otherwise raise a clear ValueError (e.g., "feature_expansion_dim
must be > 0") so you fail fast instead of letting rng.standard_normal or
subsequent math produce degenerate behavior.

In `@packages/quantum-nematode/quantumnematode/brain/arch/qef.py`:
- Around line 816-832: The _create_copy_instance implementation constructs a
fresh QEFBrain but does not restore QEF-specific trainables, causing clones to
be behaviorally incorrect; modify QEFBrain to override copy() (or implement a
base-class copy hook invoked by copy()) so after the base copy restores
actor/critic/feature_norm/optimizer you also copy over gate_weights (numeric
tensor/state), load gate_network.state_dict() into the clone, and load
critic_norm.state_dict() into the clone (use the same device as
self._device_type); reference the methods/attributes _create_copy_instance,
copy(), gate_weights, gate_network, critic_norm, and QEFBrain and ensure
state_dict()/load_state_dict() and tensor.clone()/to(device) are used to
preserve exact state.

---

Nitpick comments:
In `@packages/quantum-nematode/quantumnematode/brain/arch/qef.py`:
- Around line 339-345: The QEF __init__ currently defaults device to
DeviceType.CPU which bypasses the factory selection; change the constructor
signature in quantumnematode.brain.arch.qef (the __init__ taking config:
QEFBrainConfig, num_actions, device: DeviceType = DeviceType.CPU, action_set) to
require device: DeviceType (remove the default), and update call sites (e.g.,
brain factory in utils/brain_factory.py) to explicitly pass the device read from
config.device_type so QEF matches other architectures like
QLIFLSTMBrain/CRH/QRC.
- Around line 167-173: The class docstrings for QEFBrainConfig and QEFBrain are
not in NumPy style; update both class-level docstrings to follow NumPy
conventions by adding a short summary line, a blank line, and a Parameters
section (with parameter names, types, and descriptions) for any init/config
fields and a Returns/Attributes section if applicable; specifically modify the
docstrings in the QEFBrainConfig class and the QEFBrain class (referenced around
methods/lines where these classes are defined) to include "Parameters" and
"Returns/Attributes" sections per the repo guideline and mirror the style used
by ReservoirHybridBaseConfig for names and types.

In
`@packages/quantum-nematode/tests/quantumnematode_tests/brain/arch/test_mlpppo.py`:
- Around line 830-1110: Several newly added test methods (e.g.,
test_config_defaults, test_no_expansion_preserves_dim,
test_polynomial_output_values, test_gating_without_expansion_raises and other
tests in these classes) are missing explicit return type annotations; update
each test function signature to include -> None to match repo typing standards
(for example change "def test_...(self):" to "def test_...(self) -> None:") and
ensure all other new test methods in the file follow the same pattern.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 690bfed5-f7d6-4351-a753-b6bddd18ae9f

📥 Commits

Reviewing files that changed from the base of the PR and between dc9b5bc and 78e5137.

📒 Files selected for processing (3)
  • packages/quantum-nematode/quantumnematode/brain/arch/mlpppo.py
  • packages/quantum-nematode/quantumnematode/brain/arch/qef.py
  • packages/quantum-nematode/tests/quantumnematode_tests/brain/arch/test_mlpppo.py

Comment thread packages/quantum-nematode/quantumnematode/brain/arch/mlpppo.py
Comment thread packages/quantum-nematode/quantumnematode/brain/arch/qef.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/quantum-nematode/quantumnematode/brain/arch/qef.py (1)

442-629: Align helper-method docstrings with NumPy-style sections.

Several methods in this block use brief prose docstrings; please standardize to NumPy-style Parameters/Returns format for consistency with repository guidance.

✍️ Example style adjustment
 def _compute_gate(self, gate_input: torch.Tensor) -> torch.Tensor:
-    """Compute gate values from static weights, context network, or both."""
+    """Compute feature gate values.
+
+    Parameters
+    ----------
+    gate_input : torch.Tensor
+        Input tensor for gate computation. For context/mixed gating, this is the
+        raw sensory slice. For static gating, the value is ignored.
+
+    Returns
+    -------
+    torch.Tensor
+        Gate tensor in ``[0, 1]`` with shape compatible with quantum feature dims.
+    """

As per coding guidelines: "Use NumPy-style docstrings for functions and classes".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/quantum-nematode/quantumnematode/brain/arch/qef.py` around lines 442
- 629, Several private helper methods (e.g., _init_caches,
_init_gating_and_critic, _quantum_feature_dim, _compute_feature_dim,
_get_reservoir_features, _apply_feature_gating, _compute_gate,
_get_critic_value, _collect_trainable_params, _needs_custom_forward) use brief
prose docstrings; update each to use NumPy-style docstrings with "Parameters"
(name: type, description) and "Returns" (type, description) sections as
appropriate, keeping the existing short summary line and types (np.ndarray,
torch.Tensor, int, None, list[torch.nn.Parameter], bool), and ensure any
side-effects (e.g., setting self._last_raw_features, adding optimizer params)
are noted in the Returns or Notes section when relevant.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/quantum-nematode/quantumnematode/brain/arch/qef.py`:
- Around line 442-629: Several private helper methods (e.g., _init_caches,
_init_gating_and_critic, _quantum_feature_dim, _compute_feature_dim,
_get_reservoir_features, _apply_feature_gating, _compute_gate,
_get_critic_value, _collect_trainable_params, _needs_custom_forward) use brief
prose docstrings; update each to use NumPy-style docstrings with "Parameters"
(name: type, description) and "Returns" (type, description) sections as
appropriate, keeping the existing short summary line and types (np.ndarray,
torch.Tensor, int, None, list[torch.nn.Parameter], bool), and ensure any
side-effects (e.g., setting self._last_raw_features, adding optimizer params)
are noted in the Returns or Notes section when relevant.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ea3374fb-4d7b-476b-8731-a0417a460901

📥 Commits

Reviewing files that changed from the base of the PR and between 78e5137 and f849cc2.

📒 Files selected for processing (1)
  • packages/quantum-nematode/quantumnematode/brain/arch/qef.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant