Audit conditional PN recruitment and graded APL source timing

This commit is contained in:
Digital Drosophila Archive
2026-09-30 10:45:48 +08:00
parent 9437bbff79
commit b2cd81c7b9
283 changed files with 159989 additions and 9 deletions
@@ -0,0 +1,23 @@
# Phase 4AI — PN recruitment and graded-APL source audit
Read-only, post-outcome conditional accounting of 80 already sealed Phase 4AG-r2 records. This is not a new whole-brain experiment, a learning trial, an independent brain oracle, or an APL-removal counterfactual.
## Frozen contracts
- Reuse sealed Phase 4AH `replay_core.py` without modification; reconstruct actual ALPN targets (686 in the full graph).
- Keep the full frozen fast-APL effective-edge zeroing, delay, refractory, reset, threshold, ordering and float64 LIF coefficients. PN graded inhibition is exactly zero because the existing overlay applied only to KC.
- Separate accepted timed incoming-edge antecedents, non-feedback voltage lineage, and the legacy nonnegative graded-APL input map. The latter is not signed PN-to-APL LIF current.
- APL source groups: trial design ALPN, other ALPN, KC. Reject unaccounted nonzero input support. Compare summed mathematical float64 traces with stored float32 using prior analytic per-tick bounds, including grouping roundoff. Accumulated source shares remain descriptive; their robust majority is not proven.
- Strict timing: direct PN arrival at s+18 must precede the KC threshold tick; APL write at s follows the threshold and can affect only later ticks. Never-fired cells remain explicitly censored.
- Primary odor statistics retain fixed 686 coordinates; secondary statistics retain the fixed complement of six-odor design union. Technical repeats are excluded from odor comparisons.
## Execution
Use the existing CPU environment, Python `-B`, and four-thread OMP/MKL/OpenBLAS/Arrow limits. No Torch import, GPU or parameter changes are needed.
1. `prepare.py`: synthetic tests, source/input hashes, prior integrity, fixed inventory, metadata schema and preregistration.
2. `run_audit.py`: exact PN conditional replay, event-stream provenance, APL split, twelve repeat checks.
3. `finalize.py`: independently re-read saved evidence, validate timed edge events, aggregate all fixed records, check prior integrity, seal model and experiment.
4. `publication.py`: verify both seals, then exclusively publish small evidence to a new registry. Bulk arrays stay on the server; Git is not their off-host backup.
Any failure is preserved. Do not edit a registered source or reuse a populated experiment directory. A new revision requires an explicit separate directory and record. Audit PASS never implies learning PASS, identified unique causality, or permission to tune frozen models.
@@ -0,0 +1,329 @@
"""Non-feedback float64 attribution of the frozen, recorded graded APL trace.
No files, Torch, GPU, neuronal state, or counterfactual simulation are used.
The reference is mathematical source accounting, NOT bitwise CUDA replay.
Full bundle output is generated even for graph fixtures; the caller must not
interpret inhibition for absent fixture KCs as inhibition actually applied.
"""
from __future__ import annotations
import math
import numpy as np
N = 166700
GROUPS = ("design_ALPN", "non_design_ALPN", "KC")
DECAY32 = np.float32(math.exp(-.1 / 20.))
GAIN32 = np.float32(.01)
def _require(ok, message):
if not ok:
raise ValueError(message)
def _ids(value, name):
value = np.asarray(value)
_require(value.dtype == np.int32 and value.ndim == 1, name + " must be an int32 vector")
_require(np.all((value >= 0) & (value < N)) and np.all(value[1:] > value[:-1]),
name + " must contain sorted unique global IDs")
return value
def _positive_array(value, shape, name):
value = np.asarray(value)
_require(value.dtype == np.float32 and value.shape == shape, name + " has the wrong shape/dtype")
_require(np.isfinite(value).all() and np.all(value >= 0), name + " must be finite and nonnegative")
return value
def _up(value):
return np.nextafter(np.asarray(value, np.float64), np.inf)
def _add(a, b):
return _up(np.asarray(a, np.float64) + np.asarray(b, np.float64))
def _mul(a, b):
return _up(np.asarray(a, np.float64) * np.asarray(b, np.float64))
def _gamma(count, unit_roundoff):
_require(count * unit_roundoff < 1, "Undefined gamma bound")
numerator = _mul(count, unit_roundoff)
denominator = np.nextafter(1. - numerator, -np.inf)
return _up(numerator / denominator)
def _sum_upper(values):
"""Outward-rounded sum on axis zero; inputs are nonnegative."""
result = np.zeros(values.shape[1:], np.float64)
for value in values:
result = _add(result, value)
return result
def _sum_groups(values):
# Explicit separate additions; never rely on a backend reduction over G.
return np.add(np.add(values[0], values[1]), values[2])
def _positive_dot_upper(state, matrix):
result = np.zeros(matrix.shape[1], np.float64)
for index in range(len(state)):
result = _add(result, _mul(state[index], matrix[index]))
return result
def _normal(value, tiny):
return bool(np.isfinite(value).all() and np.all((value == 0) | (value >= tiny)))
def _metric():
return dict(elements=0, sum_abs_error=0., max_abs_error=0., max_error_bound=0.,
max_bound_utilization=0., bound_violations=0, zero_reference_nonzero_actual=0)
def _measure(metric, actual, reference, bound):
_require(np.isfinite(reference).all() and np.isfinite(bound).all(), "Nonfinite reference/bound")
error = np.abs(actual.astype(np.float64) - reference)
upper = np.where(error == 0, 0., _up(error))
impossible_zero = (reference == 0) & (actual != 0)
bad = (upper > bound) | impossible_zero
usage = np.divide(upper, bound, out=np.zeros_like(upper), where=bound > 0)
metric['elements'] += error.size
metric['sum_abs_error'] += float(error.sum(dtype=np.float64))
metric['max_abs_error'] = max(metric['max_abs_error'], float(error.max(initial=0)))
metric['max_error_bound'] = max(metric['max_error_bound'], float(bound.max(initial=0)))
metric['max_bound_utilization'] = max(metric['max_bound_utilization'], float(usage.max(initial=0)))
metric['bound_violations'] += int(bad.sum())
metric['zero_reference_nonzero_actual'] += int(impossible_zero.sum())
def decompose_apl_sources(I32, O32, pn_globals, kc_globals, design_pn_globals,
event_step, event_node, drive32, state32, h32, *,
decay32, gain32, standard_fp32, chunk_size=512, callback=None,
first_kc_tick=None):
"""Attribute APL input/output to three exact anatomical source groups.
I32 is the full (2,166700) normalized float32 input matrix; O32 is (2,K),
with columns in sorted kc_globals order. Traces are drive/state float32
(T,2), inhibition float32 (T,K), including ALL bundle KC output columns.
Actual event vectors are int32 and sorted/unique by tick/global neuron.
Design IDs must be a subset of pn_globals; fixtures' design definition is
supplied explicitly by the caller, never inferred from response outcome.
standard_fp32 must be True only after historical metadata verifies TF32 is
disabled and matmul precision is 'highest'. This function cannot inspect a
GPU environment. d/q must have the exact frozen float32 constant bits.
Return summary (pure JSON values), tick_rows (T*3*2 JSON dictionaries),
first_kc_tick (int32[K], -1 for never fired), and per_kc cumulative arrays.
Optional first_kc_tick is checked against actual events, never overrides
them. No T*3*K history is retained; source cumulative storage is O(3*K).
callback(tick, dict) optionally receives copies of drive/state group arrays
(3,2), plus their totals, never a full inhibition history.
Early means strictly tick < observed first KC spike; same-tick APL output
follows threshold and cannot cause that spike. Never-fired KC output and
output strictly before the first spike of ANY KC are reported separately.
"""
_require(standard_fp32 is True, "Historical standard FP32 arithmetic must be verified by caller")
_require(isinstance(decay32, np.float32) and isinstance(gain32, np.float32) and
decay32.view(np.uint32) == DECAY32.view(np.uint32) and
gain32.view(np.uint32) == GAIN32.view(np.uint32), "Frozen float32 decay/gain bits changed")
_require(isinstance(chunk_size, (int, np.integer)) and not isinstance(chunk_size, (bool, np.bool_)) and
chunk_size > 0, "chunk_size must be a positive integer")
_require(callback is None or callable(callback), "callback must be callable")
pn = _ids(pn_globals, 'pn_globals')
kc = _ids(kc_globals, 'kc_globals')
design = _ids(design_pn_globals, 'design_pn_globals')
_require(len(kc) > 0 and not np.intersect1d(pn, kc).size, "PN/KC identities overlap or KC set is empty")
_require(np.isin(design, pn).all(), "Design PN is outside the anatomical PN population")
k = len(kc)
I = _positive_array(I32, (2, N), 'I32').astype(np.float64)
O = _positive_array(O32, (2, k), 'O32').astype(np.float64)
state32 = np.asarray(state32)
_require(state32.ndim == 2 and len(state32) > 0, "Empty/invalid state trace")
steps = len(state32)
state32 = _positive_array(state32, (steps, 2), 'state32')
drive32 = _positive_array(drive32, (steps, 2), 'drive32')
h32 = np.asarray(h32)
_require(h32.dtype == np.float32 and h32.shape == (steps, k), "h32 has wrong shape/dtype")
# Validate without allocating a dense T*K temporary boolean array.
for start in range(0, k, chunk_size):
value = h32[:, start:start + chunk_size]
_require(np.isfinite(value).all() and np.all(value >= 0), "h32 must be finite and nonnegative")
labels = np.full(N, -1, np.int8)
labels[pn], labels[design], labels[kc] = 1, 0, 2
support = np.any(I != 0, axis=0)
unknown = np.flatnonzero(support & (labels < 0))
_require(not len(unknown), "Nonzero APL input outside design/non-design PN/KC: " + str(unknown[:10].tolist()))
ticks, nodes = np.asarray(event_step), np.asarray(event_node)
_require(ticks.dtype == nodes.dtype == np.int32 and ticks.ndim == nodes.ndim == 1 and
ticks.shape == nodes.shape, "Actual events must be matching int32 vectors")
_require(np.all((ticks >= 0) & (ticks < steps)) and np.all((nodes >= 0) & (nodes < N)), "Event out of range")
_require(np.all((ticks[1:] > ticks[:-1]) | ((ticks[1:] == ticks[:-1]) & (nodes[1:] > nodes[:-1]))),
"Actual events must be sorted and unique")
ptr = np.searchsorted(ticks, np.arange(steps + 1))
lookup = np.full(N, -1, np.int32)
lookup[kc] = np.arange(k, dtype=np.int32)
first = np.full(k, steps, np.int32)
is_kc = lookup[nodes] >= 0
np.minimum.at(first, lookup[nodes[is_kc]], ticks[is_kc])
ever = first < steps
first_any = int(first.min()) if ever.any() else None
first[~ever] = -1
if first_kc_tick is not None:
supplied = np.asarray(first_kc_tick)
_require(supplied.dtype == np.int32 and supplied.shape == (k,) and np.array_equal(supplied, first),
"Supplied first_kc_tick disagrees with observed actual KC events")
d, q = float(decay32), float(gain32)
u32, u64 = 2.**-24, 2.**-53
gd32, gd64 = _gamma(N - 1, u32), _gamma(N - 1, u64)
gs32, gs64 = _gamma(2, u32), _gamma(2, u64)
gh32, gh64, gg64 = _gamma(5, u32), _gamma(5, u64), _gamma(2, u64)
group_state = np.zeros((3, 2), np.float64)
e64 = np.zeros_like(group_state)
e32 = np.zeros(2, np.float64)
previous32 = np.zeros(2, np.float64)
statistics = {name: _metric() for name in ('drive', 'state', 'inhibition')}
tiny32, tiny64 = np.finfo(np.float32).tiny, np.finfo(np.float64).tiny
normal = _normal(I, tiny32) and _normal(O, tiny32)
sums = {name: dict(actual_spikes=0, input_supported_spikes=0, first_actual_spike_tick=None,
first_nonzero_drive_tick=None, cumulative_drive_by_apl=np.zeros(2),
cumulative_state_by_apl=np.zeros(2), h_sum_mV=0., h_before_first_KC_sum_mV=0.,
h_never_fired_KC_sum_mV=0., h_before_first_any_KC_sum_mV=0.) for name in GROUPS}
rows = []
per_kc = dict(neuron_idx=kc.copy(), first_spike_tick=first.copy(), ever_fired=ever.copy())
for name in GROUPS:
for suffix in ('pre_first_h_sum_mV', 'never_fired_h_sum_mV', 'h_sum_mV'):
per_kc[name + '_' + suffix] = np.zeros(k, np.float64)
O_total, O_never = O.sum(axis=1), O[:, ~ever].sum(axis=1)
for tick in range(steps):
fired = nodes[ptr[tick]:ptr[tick + 1]]
group_drive = np.zeros_like(group_state)
spike_counts = np.zeros(3, np.int64)
for group, name in enumerate(GROUPS):
selected = fired[labels[fired] == group]
spike_counts[group] = len(selected)
group_drive[group] = I[:, selected].sum(axis=1, dtype=np.float64)
acc = sums[name]
acc['actual_spikes'] += len(selected)
acc['input_supported_spikes'] += int(support[selected].sum())
if len(selected) and acc['first_actual_spike_tick'] is None:
acc['first_actual_spike_tick'] = tick
if np.any(group_drive[group] > 0) and acc['first_nonzero_drive_tick'] is None:
acc['first_nonzero_drive_tick'] = tick
# Each source-group positive reduction independently bounds its exact
# real sum. Outward sum across groups bounds the common exact drive.
Dupper = _up(group_drive / np.nextafter(1. - gd64, -np.inf))
total_Dupper = _sum_upper(Dupper)
drive_ref = _sum_groups(group_drive)
drive_bound = _add(_mul(gd32, total_Dupper),
_add(_sum_upper(_mul(gd64, Dupper)), _mul(gg64, _sum_upper(group_drive))))
e32 = _add(_mul(d, e32), _add(_mul(gs32, _add(_mul(d, previous32), total_Dupper)),
_mul(1. + u32, _mul(gd32, total_Dupper))))
e64 = _add(_mul(d, e64), _add(_mul(gs64, _add(_mul(d, group_state), Dupper)),
_mul(1. + u64, _mul(gd64, Dupper))))
normal &= _normal(d * previous32, tiny32) and _normal(d * group_state, tiny64)
group_state = np.add(np.multiply(d, group_state), group_drive)
state_ref = _sum_groups(group_state)
state_bound = _add(e32, _add(_sum_upper(e64), _mul(gg64, _sum_upper(group_state))))
observed_state = state32[tick].astype(np.float64)
normal &= _normal(drive32[tick], tiny32) and _normal(observed_state, tiny32)
_measure(statistics['drive'], drive32[tick], drive_ref, drive_bound)
_measure(statistics['state'], state32[tick], state_ref, state_bound)
for start in range(0, k, chunk_size):
stop = min(k, start + chunk_size)
matrix = O[:, start:stop]
h_group = np.empty((3, stop - start), np.float64)
h_error = np.empty_like(h_group)
for group in range(3):
products = group_state[group, :, None] * matrix
dot = np.add(products[0], products[1])
h_group[group] = np.multiply(q, dot)
normal &= _normal(products, tiny64) and _normal(h_group[group], tiny64)
h_error[group] = _add(_mul(q, _positive_dot_upper(e64[group], matrix)),
_mul(gh64, _mul(q, _positive_dot_upper(group_state[group], matrix))))
name = GROUPS[group]
per_kc[name + '_h_sum_mV'][start:stop] += h_group[group]
early_mask = ever[start:stop] & (tick < first[start:stop])
per_kc[name + '_pre_first_h_sum_mV'][start:stop] += h_group[group] * early_mask
per_kc[name + '_never_fired_h_sum_mV'][start:stop] += h_group[group] * ~ever[start:stop]
h_ref = _sum_groups(h_group)
h32_error = _add(_mul(q, _positive_dot_upper(e32, matrix)),
_mul(gh32, _mul(q, _positive_dot_upper(observed_state, matrix))))
bound = _add(h32_error, _add(_sum_upper(h_error), _mul(gg64, _sum_upper(h_group))))
actual_products = observed_state[:, None] * matrix
actual_dot = np.add(actual_products[0], actual_products[1])
normal &= _normal(actual_products, tiny32) and _normal(q * actual_dot, tiny32)
normal &= _normal(h32[tick, start:stop], tiny32)
_measure(statistics['inhibition'], h32[tick, start:stop], h_ref, bound)
# Aggregate output per source and per APL, never T*G*K. This is linear
# f64 measurement; grouping/reduction is not claimed bitwise identical.
early = ever & (tick < first)
O_early = O[:, early].sum(axis=1)
before_any = first_any is not None and tick < first_any
for group, name in enumerate(GROUPS):
acc = sums[name]
acc['cumulative_drive_by_apl'] += group_drive[group]
acc['cumulative_state_by_apl'] += group_state[group]
for apl in range(2):
amplitude = q * group_state[group, apl]
h_sum = float(amplitude * O_total[apl])
h_early = float(amplitude * O_early[apl])
h_never = float(amplitude * O_never[apl])
h_any = h_sum if before_any else 0.
row = dict(tick=tick, group=name, apl_index=apl, source_spikes=int(spike_counts[group]),
drive64=float(group_drive[group, apl]), state64=float(group_state[group, apl]),
h_sum_mV=h_sum, h_before_first_KC_sum_mV=h_early,
h_never_fired_KC_sum_mV=h_never, h_before_first_any_KC_sum_mV=h_any)
rows.append(row)
for key in ('h_sum_mV', 'h_before_first_KC_sum_mV', 'h_never_fired_KC_sum_mV', 'h_before_first_any_KC_sum_mV'):
acc[key] += row[key]
if callback is not None:
callback(tick, dict(drive_by_group=group_drive.copy(), state_by_group=group_state.copy(),
drive_total=drive_ref.copy(), state_total=state_ref.copy()))
previous32 = observed_state
total_h = sum(value['h_sum_mV'] for value in sums.values())
total_drive = sum(float(value['cumulative_drive_by_apl'].sum()) for value in sums.values())
for acc in sums.values():
acc['generated_h_fraction'] = None if total_h == 0 else acc['h_sum_mV'] / total_h
acc['drive_fraction'] = None if total_drive == 0 else float(acc['cumulative_drive_by_apl'].sum()) / total_drive
for key in ('cumulative_drive_by_apl', 'cumulative_state_by_apl'):
acc[key] = acc[key].tolist()
for metric in statistics.values():
metric['mean_abs_error'] = metric.pop('sum_abs_error') / metric['elements']
finite_metrics = all(np.isfinite([row[key] for row in rows]).all() for key in
('drive64', 'state64', 'h_sum_mV', 'h_before_first_KC_sum_mV', 'h_never_fired_KC_sum_mV', 'h_before_first_any_KC_sum_mV'))
_require(finite_metrics, "Nonfinite aggregate accounting")
_require(all(np.isfinite(value).all() for value in per_kc.values()), "Nonfinite per-KC accounting")
passed = bool(normal and all(metric['bound_violations'] == 0 for metric in statistics.values()))
summary = dict(pass_all=passed, steps=steps, neurons=N, apl=2, bundle_KC=k,
actual_events=len(nodes), groups=sums, group_order=list(GROUPS),
input_support_partition_exact=True, unknown_nonzero_input_columns=0,
source_population_counts={name: int(np.count_nonzero(labels == index)) for index, name in enumerate(GROUPS)},
input_supported_population_counts={name: int(np.count_nonzero(support & (labels == index))) for index, name in enumerate(GROUPS)},
first_any_KC_spike_tick=first_any, ever_fired_KC=int(ever.sum()), never_fired_KC=int((~ever).sum()),
decay_f32_bits=f'{int(decay32.view(np.uint32)):08x}', gain_f32_bits=f'{int(gain32.view(np.uint32)):08x}',
comparison=statistics, theoretical_bound=dict(applicable=bool(normal),
normal_or_zero_arithmetic=bool(normal), historical_standard_fp32_verified_by_caller=True,
gamma_definition='gamma_n=n*u/(1-n*u); u32=2^-24,u64=2^-53; outward rounded',
drive_terms_bound=N-1, state_operation_bound=2, output_operation_bound=5, group_sum_operation_bound=2,
state_recurrence='E_p<=d*E_p_prev+gamma_2,p*(d*abs(s_p_prev)+D_upper)+(1+u_p)*gamma_(N-1),p*D_upper',
grouped_f64_bound='Sum source-group error bounds, plus gamma_2,64*upward_sum(group_values) for per-tick compared drive/state/h totals only',
output_bound='q*upward_dot(E_p,O)+gamma_5,p*q*upward_dot(s_p,O); f32 error plus all f64 group/output/sum errors',
tolerance_fitted_to_observed_error=False,
scope='Per-tick summed-source drive/state/h trace comparisons only; not cumulative source fractions'),
early_definition='strict tick<each observed first KC spike; never-fired columns separate; same-tick end APL excluded',
value_units=dict(drive64='legacy normalized-contact spike drive', state64='legacy normalized-drive accumulator',
h='legacy mV per state-update step; sums span output KC and recorded ticks, not instantaneous conductance'),
generated_full_bundle_trace=True, fixture_absent_KC_output_is_not_claimed_applied=True,
row_source_spikes_repeated_for_each_APL=True, nonfeedback=True, CUDA_float32_bitwise_replay=False,
cumulative_and_fraction_metrics_descriptive_float64=True,
cumulative_source_fraction_error_bounds_verified=False,
source_majority_robustness_proven=False,
independent_brain_oracle=False, lesion_or_counterfactual=False, parameters_changed=False)
return dict(summary=summary, tick_rows=rows, first_kc_tick=first, per_kc=per_kc)
@@ -0,0 +1,17 @@
58f2f78b94aa783cc30b4b5e79ab003cc83f8a09b66c195d963bca6ee691e44c README.md
61f4c35b464315d19bbffce534cfc037a0111725da0eb07ee53a41db81767fcb apl_sources.py
a166da3d964b49ca28a013d3a3cf33df1607c76d4a6a53a8ca8e2d955aa92cb0 context.py
40e0f8a9e075db42ac63163de8362d808b9110f371e49f6d4088267eecf2eb4c finalize.py
0663c1f723f614ebcdb666b46eaa49288aec26125d6aceb18cd237330a705968 pn_observer.py
9fbef01968c54637c9063bb1e2d7f45fdc97b886b3c25815a6146fc5f219164c prepare.py
7a79c499098b74163e7bb16adabcbc54e7069dafa204d0b99c7f4c03d79f8016 publication.py
a5a7861e8ced4739cd1a1f4314b8af7cff71168499f1ae6ed94ac71b481bcdd8 run_audit.py
669e91a862efea5f243a054c883bc1a183e96b0bcf02fac5f6972c4a8272a4cb structure_metrics.py
a7ac0f38877e0244a4bcc574264c72617ec487544a19dbc705e0c1e26c4be78d test_apl_sources.py
c2e66adb18d25264d21bfce16462ef698a3ba09d178908bef1068881d46ac1e7 test_harness.py
fff3cb9da17d9d638e53a609a265d6531ed82824d10e06fcb3863edfeab7a267 test_pn_observer.py
a3516aefa6a753f8fca6c5a4c2109ae4d65ce0ab0278e4795d537148f04495ff test_publication.py
de1298a4a92facad97339e9a4cdb60ea2b7c30adc1a6f05274bd3be034239717 test_structure_metrics.py
d687ceb171c7dad77dfe2eb53524091a7ee02ddc04d9bbafb3b4a59b0d1eb66c test_validate_events.py
32a33988c5c9619b2ff3553c2d508924a404ade17b526541a2ff113a61df68e4 validate_events.py
a53443ac124e9bebc813867a5015d77276c2bd3edf89cd606a57d54756fe0dd7 manifest.json
@@ -0,0 +1,86 @@
"""Phase 4AI: read-only PN/APL accounting of sealed Phase 4AG-r2 records."""
import hashlib
import importlib.util
import json
import sys
from pathlib import Path
ROOT = Path('/data/digital-drosophila')
MODEL = Path(__file__).resolve().parent
EXP = ROOT / 'experiments/phase4ai-pn-recruitment-audit'
AH_MODEL = ROOT / 'models/male-cns-lif/kc-drive-audit-v1'
AH = ROOT / 'experiments/phase4ah-kc-drive-audit'
AG_MODEL = ROOT / 'models/male-cns-lif/author-apl-lab-v2'
AG = ROOT / 'experiments/phase4ag-author-apl-r2'
META = ROOT / 'datasets/male-cns-v1.0/processed/neuron-only/neuron-index/unified-metadata.parquet'
COEFF = ROOT / 'experiments/phase4af-author-fullgraph/oracle/no_input/coefficients.json'
GROUPS = ('KC', 'APL', 'ALPN', 'MBON', 'anatomical_DAN', 'dopamine_annotation_only',
'ALLN', 'ALIN', 'ALON', 'olfactory_sensory', 'other', 'unclassified')
def load_module(name, path):
spec = importlib.util.spec_from_file_location(name, path)
module = importlib.util.module_from_spec(spec)
sys.modules[name] = module
spec.loader.exec_module(module)
return module
def digest(path):
h = hashlib.sha256()
with Path(path).open('rb') as f:
for b in iter(lambda: f.read(8 << 20), b''):
h.update(b)
return h.hexdigest()
def read(path):
return json.loads(Path(path).read_text(encoding='utf-8'))
def save(path, value):
path = Path(path)
path.parent.mkdir(parents=True, exist_ok=True)
with path.open('x', encoding='utf-8') as f:
json.dump(value, f, indent=2, ensure_ascii=False, allow_nan=False)
f.write('\n')
def sources():
return {p.name: digest(p) for p in sorted(MODEL.iterdir()) if p.is_file()
and p.name not in ('manifest.json', 'checksums.sha256')}
def integrity():
prior = load_module('sealed_ah_context_ai', AH_MODEL / 'context.py')
result = prior.integrity()
sys.path.insert(0, str(ROOT / 'models/male-cns-lif/terminal-scope-diagnostic-v1'))
from diagnostic import manifest_check
for path in (AH_MODEL, AH):
result[str(path.relative_to(ROOT))] = manifest_check(path, digest)
assert all(row['pass'] for row in result.values())
return result
def check():
record = read(EXP / 'protocol/preregistered.json')
assert record['sources'] == sources(), 'Registered source changed'
for row in record['inputs']:
assert digest(ROOT / row['path']) == row['sha256'], row['path']
for row in read(EXP / 'protocol/prepared-hashes.json'):
assert digest(EXP / row['path']) == row['sha256'], row['path']
return record
def seal(root):
rows = [dict(path=str(p.relative_to(root)), bytes=p.stat().st_size, sha256=digest(p))
for p in sorted(root.rglob('*')) if p.is_file() and '__pycache__' not in p.parts]
save(root / 'manifest.json', dict(root=str(root), files=rows))
with (root / 'checksums.sha256').open('x') as f:
for row in rows:
f.write(row['sha256'] + ' ' + row['path'] + '\n')
f.write(digest(root / 'manifest.json') + ' manifest.json\n')
def bit_equal(a, b):
return a.dtype == b.dtype and a.shape == b.shape and a.tobytes() == b.tobytes()
@@ -0,0 +1,258 @@
"""Independently re-read evidence, aggregate descriptive outcomes, and seal."""
from collections import Counter
import numpy as np
import pandas as pd
import pyarrow.parquet as pq
from context import (ROOT, MODEL, EXP, AG, AG_MODEL, GROUPS, read, save, digest, check,
integrity, seal, bit_equal)
from run_audit import graph_view, first_ticks, temporal_relation
from structure_metrics import aggregate_structure
from validate_events import validate_batch
def expected_inventory():
result = [(n, 0, 'fixture') for n in read(AG_MODEL / 'config.json')['fixtures']]
for row in read(AG / 'protocol/calibration-cases.json'):
result.append((row['name'], 0, 'calibration'))
if row['seed'] == 51101:
result.append((row['name'], 1, 'calibration'))
return result
def verify_trial(item):
out = EXP / 'trials' / (item['case'] + '-r' + str(item['repeat']))
source = ROOT / item['source']
result = read(out / 'summary.json')
hashes = read(out / 'output-hashes.json')
assert len({r['path'] for r in hashes}) == len(hashes)
assert {r['path'] for r in hashes} == {p.name for p in out.iterdir() if p.is_file() and p.name != 'output-hashes.json'}
for row in hashes:
assert digest(out / row['path']) == row['sha256'] and (out / row['path']).stat().st_size == row['bytes']
assert (result['case'], result['repeat'], result['kind']) == (item['case'], item['repeat'], item['kind'])
assert result['pass_all'] and all(result['exact'].values()) and result['APL_source_bound_pass']
for name, sha in result['input_sha256'].items():
assert digest(source / name) == sha
spec = read(AG / 'cases' / item['case'] / 'spec.json')
assert result['steps'] == spec['steps'] and result['duration_ms'] == spec['duration_ms']
for key in ('mode', 'seed', 'odor_id'):
assert result[key] == spec.get(key)
graph = 'fixtures' if item['kind'] == 'fixture' else 'full'
_, incoming, _, codes, targets, positions, _ = graph_view(graph)
pn_table = pd.read_parquet(out / 'per-pn.parquet')
kc_table = pd.read_parquet(out / 'per-kc-apl-sources.parquet')
apl = read(out / 'apl-source-summary.json')
assert apl['pass_all'] and apl['theoretical_bound']['applicable']
assert all(v['bound_violations'] == 0 for v in apl['comparison'].values())
assert not apl['source_majority_robustness_proven']
with np.load(source / 'state.npz') as expected, np.load(out / 'replay-final.npz') as actual:
assert bit_equal(actual['target_globals'], targets)
for key in ('v', 'g', 'ref', 'counts'):
assert bit_equal(actual[key], expected[key][positions])
selected = np.isin(expected['neuron_idx'], targets)
for key in ('step', 'neuron_idx'):
assert bit_equal(actual[key], expected[key][selected])
assert bit_equal(pn_table.neuron_idx.to_numpy(), targets)
assert bit_equal(pn_table.spike_count.to_numpy(), actual['counts'])
assert bit_equal(pn_table.first_spike_tick.to_numpy(), actual['first_spike'])
assert bit_equal(actual['first_spike'], first_ticks(expected['step'], expected['neuron_idx'], targets))
kc = np.load(AG / 'apl-bundle/kc_globals.npy')
assert bit_equal(kc_table.neuron_idx.to_numpy(), kc)
assert bit_equal(kc_table.first_spike_tick.to_numpy(), first_ticks(expected['step'], expected['neuron_idx'], kc))
source_keys = expected['step'].astype(np.int64) * 166700 + expected['neuron_idx']
assert np.all(source_keys[1:] > source_keys[:-1])
source_time_keys = np.sort(expected['neuron_idx'].astype(np.int64) * spec['steps'] + expected['step'])
final_first = actual['first_spike'].copy()
assert np.array_equal(pn_table.first_spike_observed, pn_table.first_spike_tick >= 0)
for name in pn_table.select_dtypes(include='number'):
values = pn_table[name].to_numpy()
assert not np.isinf(values).any()
if np.isnan(values).any():
assert name.startswith('first_') and np.array_equal(np.isnan(values), ~pn_table.first_spike_observed.to_numpy())
assert np.isfinite(kc_table.select_dtypes(include='number').to_numpy()).all()
design = pn_table.is_design_target.to_numpy()
with np.load(AG / 'cases' / item['case'] / 'requests.npz') as req:
table = pd.read_csv(source / 'requests.csv')
assert np.array_equal(table.neuron_idx, req['neuron_idx']) and np.array_equal(table.tick, req['tick'])
requested = np.bincount(req['neuron_idx'], minlength=166700)[targets]
accepted = np.bincount(req['neuron_idx'][table.accepted.to_numpy().astype(bool)], minlength=166700)[targets]
assert np.array_equal(pn_table.requested, requested) and np.array_equal(pn_table.accepted_requests, accepted)
if item['kind'] == 'calibration':
with np.load(AG / 'cases' / item['case'] / 'pn-drive.npz') as pdz:
assert np.array_equal(design, np.isin(targets, pdz['targets']))
totals = np.zeros(len(targets), np.int64)
edge_totals = np.zeros(len(incoming.edge_id), np.int64)
count = 0
last_record_key = -1
for batch in pq.ParquetFile(out / 'accepted-prefirst-edge-events.parquet').iter_batches(batch_size=65536):
columns = {name: batch.column(name).to_numpy(zero_copy_only=False) for name in batch.schema.names}
checked = validate_batch(columns, edge_ids=incoming.edge_id, srcglobals=incoming.src_global,
dstglobals=targets[incoming.dst_local], weights=incoming.weights, target_globals=targets,
target_first=final_first, source_event_keys=source_keys)
totals += checked['per_target_count']
count += checked['count']
pos = np.searchsorted(incoming.edge_id, columns['edge_id'])
keys = columns['arrival_tick'].astype(np.int64) * 25582938 + columns['edge_id']
assert np.all(keys[1:] > keys[:-1]) and (not len(keys) or int(keys[0]) > last_record_key)
if len(keys):
last_record_key = int(keys[-1])
np.add.at(edge_totals, pos, 1)
assert np.array_equal(columns['incoming_edge_row'], pos)
assert np.array_equal(columns['source_group'], np.asarray(GROUPS)[codes[pos]])
assert np.array_equal(columns['target_is_design'], design[incoming.dst_local[pos]])
assert count == result['observer']['first_arrival_record_count']
expected_totals = sum((pn_table[g + '_accepted_nonzero_before_first_edges'].to_numpy() for g in GROUPS), start=np.zeros(len(targets), np.int64))
assert np.array_equal(totals, expected_totals)
edge_summary = pd.read_parquet(out / 'prefirst-edge-summary.parquet')
assert int(edge_summary.accepted_event_count.sum()) == count
assert len(edge_summary) == result['observer']['edge_summary_count']
selected_edges = np.flatnonzero(edge_totals)
assert np.array_equal(edge_summary.edge_id.to_numpy(), incoming.edge_id[selected_edges])
assert np.array_equal(edge_summary.accepted_event_count.to_numpy(), edge_totals[selected_edges])
# Independent completeness: initially ref=0 and no reset before the first spike.
# Every nonzero source event arriving strictly before that boundary must be present.
end = np.where(final_first[incoming.dst_local] >= 0, final_first[incoming.dst_local], spec['steps'])
source_start = incoming.src_global.astype(np.int64) * spec['steps']
source_end = source_start + np.maximum(end - 18, 0)
independent_counts = np.searchsorted(source_time_keys, source_end) - np.searchsorted(source_time_keys, source_start)
independent_counts[incoming.weights == 0] = 0
assert np.array_equal(edge_totals, independent_counts), 'Independent timed antecedent coverage mismatch'
# Validate aggregation receipts against per-neuron evidence instead of trusting JSON alone.
for stratum, mask in (('all_PN', np.ones(len(targets), bool)), ('design_PN', design),
('non_design_PN', ~design), ('never_active_PN', final_first < 0)):
agg = result['observer']['aggregates'][stratum]
assert agg['neurons'] == int(mask.sum()) and agg['spikes'] == int(pn_table.spike_count.to_numpy()[mask].sum())
for group, metrics in agg['source_groups'].items():
for metric, value in metrics.items():
summed = pn_table[group + '_' + metric].to_numpy()[mask].sum(dtype=np.longdouble)
if isinstance(value, int):
assert int(summed) == value
else:
# Serialization to per-neuron f64 and regrouping changes only final reporting arithmetic.
assert abs(float(summed) - value) <= 64 * np.finfo(np.float64).eps * max(1., abs(value))
tick_table = pd.read_parquet(out / 'apl-per-tick.parquet')
assert len(tick_table) == spec['steps'] * 6
assert not tick_table[['tick', 'group', 'apl_index']].duplicated().any()
assert set(tick_table.group.unique()) == {'design_ALPN', 'non_design_ALPN', 'KC'}
for group in ('design_ALPN', 'non_design_ALPN', 'KC'):
metric = group + '_h_sum_mV'
observed = float(kc_table[metric].sum())
expected_sum = apl['groups'][group]['h_sum_mV']
assert abs(observed - expected_sum) <= 128 * spec['steps'] * np.finfo(np.float64).eps * max(1., abs(expected_sum))
return result, pn_table, kc_table, apl
def main():
check()
assert not (EXP / 'audit/failure.json').exists(), 'Cannot promote a preserved failure'
inventory = read(EXP / 'protocol/inventory.json')
identities = [(r['case'], r['repeat'], r['kind']) for r in inventory]
assert identities == expected_inventory() and len(set(identities)) == 80
completed = read(EXP / 'audit/completed.json')
assert completed['pass_all']
ids = [(r['case'], r['repeat']) for r in completed['trials']]
assert len(ids) == len(set(ids)) == 80 and set(ids) == {(r[0], r[1]) for r in identities}
assert all(r['pass_all'] for r in completed['trials'])
repeats = completed['repeat_checks']
assert len(repeats) == len({r['case'] for r in repeats}) == 12
assert {r['case'] for r in repeats} == {r['case'] for r in inventory if r['repeat'] == 1}
assert all(r['pass_all'] and all(r['checks'].values()) for r in repeats)
reports, metrics, by_mode = [], [], {}
cal_rows = read(AG / 'protocol/calibration-cases.json')
odors = list(dict.fromkeys(r['odor_id'] for r in cal_rows))
assert len(odors) == 6
for item in inventory:
report, pn, kc, apl = verify_trial(item)
reports.append(report)
print('VERIFIED', item['case'], item['repeat'], flush=True)
if item['kind'] != 'calibration' or item['repeat'] != 0:
continue
metrics.append(dict(mode=report['mode'], odor_index=odors.index(report['odor_id']), seed=report['seed'],
counts=pn.spike_count.to_numpy(), design_mask=pn.is_design_target.to_numpy()))
by_mode.setdefault(report['mode'], []).append((report, pn, kc, apl))
# Independently repeat the stored repeat gate without executing a trajectory.
for item in inventory:
if item['repeat'] != 1:
continue
a = EXP / 'trials' / (item['case'] + '-r0')
b = EXP / 'trials' / (item['case'] + '-r1')
for name in ('per-pn.parquet', 'prefirst-edge-summary.parquet', 'apl-per-tick.parquet', 'per-kc-apl-sources.parquet'):
assert pd.read_parquet(a / name).equals(pd.read_parquet(b / name))
assert digest(a / 'accepted-prefirst-edge-events.parquet') == digest(b / 'accepted-prefirst-edge-events.parquet')
assert read(a / 'apl-source-summary.json') == read(b / 'apl-source-summary.json')
with np.load(a / 'replay-final.npz') as aa, np.load(b / 'replay-final.npz') as bb:
assert set(aa.files) == set(bb.files) and all(bit_equal(aa[k], bb[k]) for k in aa.files)
structure = aggregate_structure(metrics)
structure['odor_index_to_id'] = odors
structure['ALPN_column_neuron_idx'] = np.load(AG / 'apl-bundle/pn_globals.npy').tolist()
save(EXP / 'audit/PN-odor-structure.json', structure)
aggregate = {}
for mode, trials in by_mode.items():
assert len(trials) == 30
sources = {}
for group in ('design_ALPN', 'non_design_ALPN', 'KC'):
sources[group] = {metric: sum(a['groups'][group][metric] for _, _, _, a in trials) for metric in (
'h_sum_mV', 'h_before_first_KC_sum_mV', 'h_never_fired_KC_sum_mV', 'h_before_first_any_KC_sum_mV')}
sources[group]['drive_sum'] = sum(sum(a['groups'][group]['cumulative_drive_by_apl']) for _, _, _, a in trials)
for group in sources:
for key in ('h_sum_mV', 'h_before_first_KC_sum_mV', 'h_before_first_any_KC_sum_mV', 'drive_sum'):
total = sum(s[key] for s in sources.values())
sources[group][key + '_fraction'] = None if total == 0 else sources[group][key] / total
source_inputs = {group: {metric: sum(r['observer']['aggregates']['non_design_PN']['source_groups'][group][metric]
for r, _, _, _ in trials) for metric in trials[0][0]['observer']['aggregates']['non_design_PN']['source_groups'][group]}
for group in GROUPS}
allpn = pd.concat([p for _, p, _, _ in trials], ignore_index=True)
allkc = pd.concat([k for _, _, k, _ in trials], ignore_index=True)
activated = allkc[allkc.first_spike_tick >= 0]
first_metrics = [r for r, _, _, _ in trials]
aggregate[mode] = dict(trials=30,
first_non_design_vs_first_KC=dict(Counter(r['first_non_design_vs_first_KC'] for r in first_metrics)),
first_non_design_PN_tick_range=[min(r['first_non_design_PN_tick'] for r in first_metrics), max(r['first_non_design_PN_tick'] for r in first_metrics)],
first_any_KC_tick_range=[min(r['first_any_KC_tick'] for r in first_metrics), max(r['first_any_KC_tick'] for r in first_metrics)],
each_active_KC_relation=dict(activated.first_non_design_relation.value_counts()),
each_active_KC_count=len(activated),
each_active_KC_has_strict_pre_first_nondesign_PN_edge=int((activated.non_design_ALPN_strict_pre_first_edge_events > 0).sum()),
PN_neuron_trials=len(allpn), PN_active_neuron_trials=int(allpn.first_spike_observed.sum()),
PN_spikes=int(allpn.spike_count.sum()), design_PN_spikes=int(allpn.loc[allpn.is_design_target, 'spike_count'].sum()),
nondesign_PN_spikes=int(allpn.loc[~allpn.is_design_target, 'spike_count'].sum()),
non_design_PN_input_sources=source_inputs, APL_sources=sources,
common_non_design_dimensions=structure['design']['common_non_design_count'],
counts_are_neuron_trials_not_distinct_neurons=True)
aggregate[mode]['each_active_KC_relation'] = {k: int(v) for k, v in aggregate[mode]['each_active_KC_relation'].items()}
after = integrity()
save(EXP / 'regression/old-integrity-after.json', after)
assert read(AG / 'regression/frozen-five.json')['pass_all']
result = dict(status='PASS-CONDITIONAL-PN-APL-SOURCE-AUDIT', pass_all=True,
exact_PN_trials=80, fixture_dense_pre_post_trials=8, CAL_event_final_trials=72, repeat_accounting_pass=12,
modes=aggregate, max_PN_voltage_ledger_residual_SI=max(r['observer']['voltage_decomposition']['maximum_reconstruction_residual_SI'] for r in reports),
CPU_audit_wall_seconds=sum(r['CPU_audit_wall_seconds'] for r in reports),
old_integrity_pass=all(r['pass'] for r in after.values()),
prior_frozen_five_pass=True, frozen_five_reexecuted_this_audit=False,
prior_frozen_five_sha256=digest(AG / 'regression/frozen-five.json'),
new_brain_simulation=False, GPU_used=False, training=False, heldout_access=False,
candidate_generated=False, learning_achieved=False, prior_CAL_failure_unchanged=True,
source_fraction_robustness_proven=False, counterfactual_causality_tested=False,
limitations=['Logged upstream spikes are conditioning inputs, not an independent whole-brain oracle',
'Real timed edges are accepted antecedents, not unique causes or necessity proofs',
'APL uses the unchanged nonnegative engineering input map, not signed PN-to-APL LIF drive',
'APL summed traces pass prior per-tick error bounds; accumulated shares remain descriptive',
'Shared PN activity does not imply absent odor information; no learning gate applied',
'No independently saved per-tick PN states for CAL; fixtures have full histories',
'Frozen five simulation executions were not repeated; previous sealed PASS checked by hash'])
save(EXP / 'audit/final-status.json', result)
with (EXP / 'REPORT.md').open('x') as f:
f.write('# Phase 4AI — conditional PN recruitment and APL source audit\n\n'
'Status: `PASS-CONDITIONAL-PN-APL-SOURCE-AUDIT`.\n\n'
'80 existing records; PN events/counts/final states exact; eight fixture histories exact; twelve repeats exact. '
'No new brain experiment, tuning, training, GPU, or learning candidate.\n\n'
'See audit/final-status.json and audit/PN-odor-structure.json. Accepted edges are timed antecedents, '
'not unique causes. Graded-APL cumulative source shares are descriptive, not causal or error-bounded majority claims. '
'Prior CAL failure remains unchanged. Frozen integrity passed; five reference simulations were not rerun.\n')
check()
assert sum(p.stat().st_size for p in EXP.rglob('*') if p.is_file()) < 2 * 1024**3
seal(MODEL)
seal(EXP)
print(result['status'], flush=True)
if __name__ == '__main__':
main()
@@ -0,0 +1,85 @@
{
"root": "/data/digital-drosophila/models/male-cns-lif/pn-recruitment-audit-v1",
"files": [
{
"path": "README.md",
"bytes": 2504,
"sha256": "58f2f78b94aa783cc30b4b5e79ab003cc83f8a09b66c195d963bca6ee691e44c"
},
{
"path": "apl_sources.py",
"bytes": 19165,
"sha256": "61f4c35b464315d19bbffce534cfc037a0111725da0eb07ee53a41db81767fcb"
},
{
"path": "context.py",
"bytes": 3182,
"sha256": "a166da3d964b49ca28a013d3a3cf33df1607c76d4a6a53a8ca8e2d955aa92cb0"
},
{
"path": "finalize.py",
"bytes": 17774,
"sha256": "40e0f8a9e075db42ac63163de8362d808b9110f371e49f6d4088267eecf2eb4c"
},
{
"path": "pn_observer.py",
"bytes": 23294,
"sha256": "0663c1f723f614ebcdb666b46eaa49288aec26125d6aceb18cd237330a705968"
},
{
"path": "prepare.py",
"bytes": 7062,
"sha256": "9fbef01968c54637c9063bb1e2d7f45fdc97b886b3c25815a6146fc5f219164c"
},
{
"path": "publication.py",
"bytes": 14239,
"sha256": "7a79c499098b74163e7bb16adabcbc54e7069dafa204d0b99c7f4c03d79f8016"
},
{
"path": "run_audit.py",
"bytes": 16829,
"sha256": "a5a7861e8ced4739cd1a1f4314b8af7cff71168499f1ae6ed94ac71b481bcdd8"
},
{
"path": "structure_metrics.py",
"bytes": 10327,
"sha256": "669e91a862efea5f243a054c883bc1a183e96b0bcf02fac5f6972c4a8272a4cb"
},
{
"path": "test_apl_sources.py",
"bytes": 12733,
"sha256": "a7ac0f38877e0244a4bcc574264c72617ec487544a19dbc705e0c1e26c4be78d"
},
{
"path": "test_harness.py",
"bytes": 1452,
"sha256": "c2e66adb18d25264d21bfce16462ef698a3ba09d178908bef1068881d46ac1e7"
},
{
"path": "test_pn_observer.py",
"bytes": 8472,
"sha256": "fff3cb9da17d9d638e53a609a265d6531ed82824d10e06fcb3863edfeab7a267"
},
{
"path": "test_publication.py",
"bytes": 10514,
"sha256": "a3516aefa6a753f8fca6c5a4c2109ae4d65ce0ab0278e4795d537148f04495ff"
},
{
"path": "test_structure_metrics.py",
"bytes": 10003,
"sha256": "de1298a4a92facad97339e9a4cdb60ea2b7c30adc1a6f05274bd3be034239717"
},
{
"path": "test_validate_events.py",
"bytes": 6426,
"sha256": "d687ceb171c7dad77dfe2eb53524091a7ee02ddc04d9bbafb3b4a59b0d1eb66c"
},
{
"path": "validate_events.py",
"bytes": 6884,
"sha256": "32a33988c5c9619b2ff3553c2d508924a404ade17b526541a2ff113a61df68e4"
}
]
}
@@ -0,0 +1,315 @@
"""CPU-only observer for the unchanged Phase 4AH replay_core callback.
All input events are fixed observations, not interventions. This module writes
no files and never changes a callback array. Incoming records are antecedents,
not a selected cause, shortest path, necessity test, or whole-brain simulation.
"""
from __future__ import annotations
import numpy as np
DELAY = 18
COEFF_KEYS = ("gd", "c0", "cg", "cv", "threshold", "reset", "seed_volt")
FLOAT_KEYS = ("old_v", "old_g", "v_integrated", "g_decayed", "v_threshold",
"v_after_reset", "g_after_reset", "v_pre_apl", "g_pre_apl", "delta_si", "v", "g")
INT_KEYS = ("ref_before", "ref_after_reset", "ref_pre_apl", "ref")
BOOL_KEYS = ("available", "request", "request_accepted", "request_rejected", "fired")
def require(condition, message):
if not condition:
raise ValueError(message)
def bit_equal(a, b):
return a.dtype == b.dtype and a.shape == b.shape and np.array_equal(
np.ascontiguousarray(a).view(np.uint8), np.ascontiguousarray(b).view(np.uint8))
class PNObserver:
def __init__(self, target_globals, design_target_globals, incoming, edge_groups,
group_names, coeff, steps, *, max_first_event_rows, event_sink=None):
targets = np.asarray(target_globals)
require(targets.dtype == np.int32 and targets.ndim == 1 and len(targets) > 0 and
np.all((targets >= 0) & (targets < 166700)) and np.all(np.diff(targets) > 0),
"Targets must be sorted unique global int32 IDs")
design = np.asarray(design_target_globals)
require(design.dtype == np.int32 and design.ndim == 1 and len(np.unique(design)) == len(design) and
np.isin(design, targets).all(), "Design target IDs must be unique int32 subset of observed PNs")
require(type(steps) is int and steps > 0, "steps must be a positive integer")
require(type(max_first_event_rows) is int and max_first_event_rows > 0, "Explicit positive row budget required")
require(event_sink is None or callable(event_sink), "event_sink must be callable or None")
names = tuple(group_names)
require(names and all(isinstance(name, str) and name for name in names) and len(set(names)) == len(names),
"Source group names must be nonempty and unique")
codes = np.asarray(edge_groups)
e = len(incoming.edge_id)
require(codes.ndim == 1 and codes.shape == (e,) and codes.dtype.kind in "iu" and
np.all((codes >= 0) & (codes < len(names))), "Invalid source-group code per incoming edge")
require(incoming.target_count == len(targets) and incoming.weights.dtype == np.float64 and
np.isfinite(incoming.weights).all(), "Incoming index/weights mismatch")
require(all(name in coeff and np.isfinite(coeff[name]) for name in COEFF_KEYS), "Missing/nonfinite coefficient")
self.targets = targets.copy()
self.design = np.isin(targets, design)
self.incoming, self.groups, self.names = incoming, codes.astype(np.int64, copy=True), names
self.coeff = {name: np.float64(coeff[name]) for name in COEFF_KEYS}
self.steps, self.n = steps, len(targets)
self.max_rows, self.sink = max_first_event_rows, event_sink
self.callback_count, self.record_count = 0, 0
self.first_arrival_records = []
self.first = np.full(self.n, -1, np.int32)
self.first_request = np.full(self.n, -1, np.int32)
self.first_accepted_request = np.full(self.n, -1, np.int32)
self.first_positive_arrival = np.full(self.n, -1, np.int32)
self.counts = np.zeros(self.n, np.int32)
self.requested = np.zeros(self.n, np.int64)
self.request_accepted = np.zeros(self.n, np.int64)
self.request_rejected = np.zeros(self.n, np.int64)
self.first_request_coincident = np.zeros(self.n, bool)
self.first_state = {name: np.full(self.n, np.nan, np.float64) for name in
("old_v", "old_g", "v_integrated", "v_threshold", "threshold_margin", "ref_before")}
shape = (len(names), self.n)
self.stats = {name: np.zeros(shape, np.int64) for name in
("due_edges", "accepted_edges", "rejected_edges", "accepted_zero_edges", "rejected_zero_edges",
"accepted_positive_edges", "accepted_negative_edges", "rejected_positive_edges", "rejected_negative_edges",
"accepted_nonzero_before_first_edges", "accepted_positive_before_first_edges", "accepted_negative_before_first_edges")}
self.sums = {name: np.zeros(shape, np.longdouble) for name in
("accepted_positive_V", "accepted_negative_abs_V", "rejected_positive_V", "rejected_negative_abs_V",
"accepted_positive_before_first_V", "accepted_negative_before_first_abs_V")}
self.edge_prefirst_count = np.zeros(e, np.int64)
self.edge_first_arrival = np.full(e, -1, np.int32)
self.edge_last_arrival = np.full(e, -1, np.int32)
# Non-feedback signed-source decomposition. Residual corrections are
# explicit lanes, never silently assigned to an anatomical population.
self.lane_names = [name + "/positive_weight" for name in names] + [name + "/negative_weight" for name in names]
self.lane_names += ["initial_and_affine_baseline", "request_or_reset", "roundoff_residual"]
self.baseline_lane, self.request_lane, self.round_lane = 2 * len(names), 2 * len(names) + 1, 2 * len(names) + 2
self.lv = np.zeros((len(self.lane_names), self.n), np.longdouble)
self.lg = np.zeros_like(self.lv)
self.first_integrated_lanes = np.full_like(self.lv, np.nan)
self.first_threshold_lanes = np.full_like(self.lv, np.nan)
self.first_ledger_residual = np.full(self.n, np.nan, np.longdouble)
self.integration_roundoff_v = np.zeros(self.n, np.longdouble)
self.integration_roundoff_g = np.zeros(self.n, np.longdouble)
self.arrival_roundoff_g = np.zeros(self.n, np.longdouble)
self.max_ledger_residual = np.longdouble(0)
self.previous = None
self.finished = False
def _validate_stage(self, tick, s):
require(not self.finished and type(tick) in (int, np.int32, np.int64) and
int(tick) == self.callback_count and tick < self.steps, "Missing, duplicate or out-of-order callback tick")
for names, dtype in ((FLOAT_KEYS, np.float64), (INT_KEYS, np.int32), (BOOL_KEYS, bool)):
for name in names:
require(name in s and isinstance(s[name], np.ndarray) and s[name].shape == (self.n,) and
s[name].dtype == dtype, "Missing/wrong callback array: " + name)
require(np.isfinite(s[name]).all(), "Nonfinite callback array: " + name)
require("h32" in s and s["h32"].dtype == np.float32 and s["h32"].shape == (self.n,) and
np.all(s["h32"] == 0) and np.all(s["delta_si"] == 0), "PN observer requires zero graded APL h/delta")
require(bit_equal(s["g"], s["g_pre_apl"]) and bit_equal(s["v"], s["v_pre_apl"]) and
bit_equal(s["ref"], s["ref_pre_apl"]), "Nonzero or unexpected post-APL PN state change")
require(np.all((s["ref_before"] >= 0) & (s["ref_before"] <= 22)) and
np.all((s["ref"] >= 0) & (s["ref"] <= 22)), "Refractory range mismatch")
require(np.array_equal(s["available"], s["ref_before"] <= 1), "Availability does not match pre-step refractory")
require(np.array_equal(s["request_accepted"], s["request"] & s["available"]) and
np.array_equal(s["request_rejected"], s["request"] & ~s["available"]), "Request accounting mismatch")
require(not np.any(s["request"] & ~self.design), "Observed request outside frozen odor design targets")
require(np.array_equal(s["fired"], s["available"] & (s["v_threshold"] > self.coeff["threshold"])),
"Callback firing does not match strict threshold")
if self.previous is not None:
require(all(bit_equal(s[key], self.previous[old]) for key, old in
(("old_v", "v"), ("old_g", "g"), ("ref_before", "ref"))), "Discontinuous callback state")
due = s.get("due_edge_indices")
require(isinstance(due, np.ndarray) and due.dtype == np.int64 and due.ndim == 1 and
np.all((due >= 0) & (due < len(self.incoming.edge_id))) and np.all(np.diff(due) > 0),
"Incoming queue must retain unique canonical edge rows")
require("due_edge_id" in s and bit_equal(s["due_edge_id"], self.incoming.edge_id[due]), "Incoming edge-ID mismatch")
accepted = s.get("arrival_accepted")
require(isinstance(accepted, np.ndarray) and accepted.dtype == bool and accepted.shape == due.shape and
np.array_equal(accepted, s["ref_after_reset"][self.incoming.dst_local[due]] == 0), "Arrival guard mismatch")
require(tick >= DELAY or not len(due), "Incoming event before the fixed 18-step delay")
return due, accepted
def __call__(self, tick, s):
due, accepted = self._validate_stage(tick, s)
tick = int(tick)
dst, weights, groups = self.incoming.dst_local[due], self.incoming.weights[due], self.groups[due]
before = self.first < 0
first_now = before & s["fired"]
# Arrivals happen AFTER this tick's threshold. Same-tick arrivals are
# never antecedents to a first spike, even if malformed data said accepted.
strictly_before = before[dst] & ~s["fired"][dst]
record_mask = accepted & (weights != 0) & strictly_before
new_records = int(np.count_nonzero(record_mask))
require(self.record_count + new_records <= self.max_rows,
"First-arrival record resource limit exceeded; no truncation or event selection permitted")
if self.previous is None:
self.lv[self.baseline_lane] = s["old_v"].astype(np.longdouble)
self.lg[self.baseline_lane] = s["old_g"].astype(np.longdouble)
available = s["available"]
# Use old lane-g for V, as in the author update; do NOT use decayed g.
self.lv[:, available] = (np.longdouble(self.coeff["cv"]) * self.lv[:, available] +
np.longdouble(self.coeff["cg"]) * self.lg[:, available])
self.lv[self.baseline_lane, available] += np.longdouble(self.coeff["c0"])
self.lg[:, available] *= np.longdouble(self.coeff["gd"])
rv = s["v_integrated"].astype(np.longdouble) - self.lv.sum(axis=0, dtype=np.longdouble)
rg = s["g_decayed"].astype(np.longdouble) - self.lg.sum(axis=0, dtype=np.longdouble)
self.integration_roundoff_v += rv
self.integration_roundoff_g += rg
self.lv[self.round_lane] += rv
self.lg[self.round_lane] += rg
self.first_integrated_lanes[:, first_now] = self.lv[:, first_now]
req = s["request_accepted"]
self.lv[:, req] = 0
self.lv[self.request_lane, req] = np.longdouble(self.coeff["seed_volt"])
self.first_threshold_lanes[:, first_now] = self.lv[:, first_now]
vres = s["v_threshold"].astype(np.longdouble) - self.lv.sum(axis=0, dtype=np.longdouble)
self.first_ledger_residual[first_now] = vres[first_now]
self.max_ledger_residual = max(self.max_ledger_residual, np.max(np.abs(vres), initial=np.longdouble(0)))
for name in self.first_state:
values = (self.coeff["threshold"] - s["v_threshold"]) if name == "threshold_margin" else s[name]
self.first_state[name][first_now] = values[first_now]
self.first_request_coincident[first_now] = req[first_now]
self.first[first_now] = tick
for array, selected in ((self.first_request, s["request"]), (self.first_accepted_request, req)):
array[(array < 0) & selected] = tick
self.requested += s["request"].astype(np.int64)
self.request_accepted += req.astype(np.int64)
self.request_rejected += s["request_rejected"].astype(np.int64)
self.counts += s["fired"].astype(np.int32)
fired = s["fired"]
self.lv[:, fired] = 0
self.lv[self.request_lane, fired] = np.longdouble(self.coeff["reset"])
self.lg[:, fired] = 0
positive, negative, zero = weights > 0, weights < 0, weights == 0
picks = {"due_edges": np.ones(len(due), bool), "accepted_edges": accepted,
"rejected_edges": ~accepted, "accepted_zero_edges": accepted & zero,
"rejected_zero_edges": ~accepted & zero,
"accepted_positive_edges": accepted & positive, "accepted_negative_edges": accepted & negative,
"rejected_positive_edges": ~accepted & positive, "rejected_negative_edges": ~accepted & negative,
"accepted_nonzero_before_first_edges": record_mask,
"accepted_positive_before_first_edges": record_mask & positive,
"accepted_negative_before_first_edges": record_mask & negative}
for name, mask in picks.items():
np.add.at(self.stats[name], (groups[mask], dst[mask]), 1)
for name, mask, sign in (
("accepted_positive_V", accepted & positive, 1), ("accepted_negative_abs_V", accepted & negative, -1),
("rejected_positive_V", ~accepted & positive, 1), ("rejected_negative_abs_V", ~accepted & negative, -1),
("accepted_positive_before_first_V", record_mask & positive, 1),
("accepted_negative_before_first_abs_V", record_mask & negative, -1)):
np.add.at(self.sums[name], (groups[mask], dst[mask]), sign * weights[mask].astype(np.longdouble))
for offset, mask in ((0, accepted & positive), (len(self.names), accepted & negative)):
np.add.at(self.lg, (groups[mask] + offset, dst[mask]), weights[mask].astype(np.longdouble))
ag = s["g_pre_apl"].astype(np.longdouble) - self.lg.sum(axis=0, dtype=np.longdouble)
self.arrival_roundoff_g += ag
self.lg[self.round_lane] += ag
gres = s["g"].astype(np.longdouble) - self.lg.sum(axis=0, dtype=np.longdouble)
self.max_ledger_residual = max(self.max_ledger_residual, np.max(np.abs(gres), initial=np.longdouble(0)))
require(np.isfinite(self.lv).all() and np.isfinite(self.lg).all(), "Nonfinite non-feedback lineage ledger")
positive_targets = np.unique(dst[accepted & positive])
self.first_positive_arrival[positive_targets[self.first_positive_arrival[positive_targets] < 0]] = tick
selected_rows = due[record_mask]
np.add.at(self.edge_prefirst_count, selected_rows, 1)
self.edge_first_arrival[selected_rows[self.edge_first_arrival[selected_rows] < 0]] = tick
self.edge_last_arrival[selected_rows] = tick
rows = []
for edge in selected_rows:
target = int(self.incoming.dst_local[edge])
weight = float(self.incoming.weights[edge])
rows.append({"edge_id": int(self.incoming.edge_id[edge]), "incoming_edge_row": int(edge),
"source_neuron_idx": int(self.incoming.src_global[edge]), "target_neuron_idx": int(self.targets[target]),
"source_group": self.names[int(self.groups[edge])], "source_spike_tick": tick - DELAY,
"arrival_tick": tick, "target_is_design": bool(self.design[target]), "accepted": True,
"weight_SI": weight, "weight_sign": 1 if weight > 0 else -1,
"ref_before": int(s["ref_before"][target]), "ref_at_arrival": int(s["ref_after_reset"][target]),
"available_at_integration": bool(s["available"][target]),
"old_v_SI": float(s["old_v"][target]), "old_g_SI": float(s["old_g"][target]),
"v_integrated_SI": float(s["v_integrated"][target]), "v_prethreshold_SI": float(s["v_threshold"][target]),
"threshold_margin_SI": float(self.coeff["threshold"] - s["v_threshold"][target]),
"g_before_arrivals_SI": float(s["g_after_reset"][target]),
"record_scope": "accepted nonzero input strictly before any observed first spike; join final first_spike_tick"})
if rows:
if self.sink is None:
self.first_arrival_records.extend(rows)
else:
self.sink(rows)
self.record_count += len(rows)
self.previous = {name: s[name].copy() for name in ("v", "g", "ref")}
self.callback_count += 1
def edge_summary(self):
"""All edges with stored pre-first records, including never-active PNs."""
selected = np.flatnonzero(self.edge_prefirst_count)
dst = self.incoming.dst_local[selected]
return {"edge_id": self.incoming.edge_id[selected].copy(),
"source_neuron_idx": self.incoming.src_global[selected].copy(), "target_neuron_idx": self.targets[dst].copy(),
"source_group": np.asarray(self.names, dtype=str)[self.groups[selected]],
"weight_SI": self.incoming.weights[selected].copy(),
"accepted_event_count": self.edge_prefirst_count[selected].copy(),
"nominal_weight_times_event_count_SI": (self.incoming.weights[selected].astype(np.longdouble) *
self.edge_prefirst_count[selected]).astype(np.float64),
"first_arrival_tick": self.edge_first_arrival[selected].copy(),
"last_arrival_tick": self.edge_last_arrival[selected].copy(),
"target_first_spike_tick": self.first[dst].copy(), "target_is_design": self.design[dst].copy()}
def finish(self, result):
"""Return (per-PN arrays, JSON report); caller verifies original events/state.
first_* floating fields are NaN when first_spike_observed is false.
They must not be imputed to zero or interpreted as observed voltages.
"""
require(not self.finished and self.callback_count == self.steps and self.previous is not None, "Observer did not cover every tick")
require(bit_equal(result["target_globals"], self.targets) and bit_equal(result["first_spike"], self.first) and
bit_equal(result["counts"], self.counts), "Replay result identity/count/first spike differs from observer")
require(all(bit_equal(result[name], self.previous[name]) for name in ("v", "g", "ref")), "Replay final state differs from last callback")
require(int(self.edge_prefirst_count.sum()) == self.record_count ==
int(self.stats["accepted_nonzero_before_first_edges"].sum()), "Pre-first event coverage mismatch")
require(np.array_equal(self.stats["due_edges"], self.stats["accepted_edges"] + self.stats["rejected_edges"]),
"Due/accepted/rejected coverage mismatch")
data = {"neuron_idx": self.targets.copy(), "is_design_target": self.design.copy(),
"spike_count": self.counts.copy(), "first_spike_tick": self.first.copy(), "first_spike_observed": self.first >= 0,
"first_request_tick": self.first_request.copy(), "first_accepted_request_tick": self.first_accepted_request.copy(),
"first_accepted_positive_arrival_tick": self.first_positive_arrival.copy(),
"requested": self.requested.copy(), "accepted_requests": self.request_accepted.copy(),
"rejected_requests": self.request_rejected.copy(), "first_spike_coincident_with_accepted_request": self.first_request_coincident.copy(),
"first_voltage_ledger_residual_SI": self.first_ledger_residual.astype(np.float64),
"integration_roundoff_v_SI": self.integration_roundoff_v.astype(np.float64),
"integration_roundoff_g_SI": self.integration_roundoff_g.astype(np.float64),
"arrival_roundoff_g_SI": self.arrival_roundoff_g.astype(np.float64)}
data.update({"first_" + name + ("_SI" if name != "ref_before" else ""): value.copy()
for name, value in self.first_state.items()})
for gi, name in enumerate(self.names):
for key, value in {**self.stats, **self.sums}.items():
data[name + "_" + key] = value[gi].copy() if key in self.stats else value[gi].astype(np.float64)
for index, name in enumerate(self.lane_names):
data["first_integrated_V_from_" + name] = self.first_integrated_lanes[index].astype(np.float64)
data["first_prethreshold_V_from_" + name] = self.first_threshold_lanes[index].astype(np.float64)
aggregates = {}
for name, mask in (("all_PN", np.ones(self.n, bool)), ("design_PN", self.design),
("non_design_PN", ~self.design), ("never_active_PN", self.first < 0)):
aggregates[name] = {"neurons": int(mask.sum()), "active": int(np.count_nonzero(mask & (self.first >= 0))),
"spikes": int(self.counts[mask].sum()), "source_groups": {
group: {**{key: int(value[gi, mask].sum()) for key, value in self.stats.items()},
**{key: float(value[gi, mask].sum(dtype=np.longdouble)) for key, value in self.sums.items()}}
for gi, group in enumerate(self.names)}}
report = {"pass_all": True, "scope": "Observer coverage/internal consistency only; caller must verify recorded PN events and final state exactly",
"callback_count": self.callback_count, "steps": self.steps, "PN_count": self.n,
"source_group_names": list(self.names), "first_arrival_record_count": self.record_count,
"first_arrival_record_limit": self.max_rows, "records_truncated": False,
"edge_summary_count": int(np.count_nonzero(self.edge_prefirst_count)), "aggregates": aggregates,
"time_contract": "source_spike_tick=arrival_tick-18; arrivals follow threshold; first-spike tick arrivals excluded",
"record_contract": "Every accepted nonzero edge event strictly before first spike for every PN; never-active PNs retain full-window records with final first=-1",
"sum_contract": "Observer nominal signed weight sums, not the sequentially rounded runtime g; weight-times-count edge summaries are descriptive",
"voltage_decomposition": {"nonfeedback": True, "precision": str(np.dtype(np.longdouble)),
"lanes": list(self.lane_names), "maximum_reconstruction_residual_SI": float(self.max_ledger_residual),
"roundoff_lane_explicit": True, "fitted_tolerance": False,
"reset_clears_prior_lanes": True, "request_override_has_separate_lane": True,
"first_integrated_is_before_request_override": True,
"never_spiked_first_fields_are_NaN": True,
"threshold_crossing_contributions_are_not_necessity_or_unique_cause": True},
"graded_APL_to_PN": "Required h32=0 and delta_si=0 every tick; fast APL weights supplied already frozen-masked by caller",
"new_brain_run": False, "parameter_changes": False, "shortest_path_claim": False,
"unique_cause_claim": False, "whole_brain_intervention_claim": False}
self.finished = True
return data, report
@@ -0,0 +1,93 @@
"""Register fixed conditional audit before reading PN contribution results."""
from datetime import datetime, timezone
import platform
import subprocess
import sys
import numpy as np
import pandas as pd
from context import (ROOT, MODEL, EXP, AH, AH_MODEL, AG, AG_MODEL, META, COEFF,
GROUPS, read, save, digest, sources, integrity, load_module)
def main():
assert not EXP.exists() or not any(EXP.iterdir()), 'Populated audit directory must not be reused'
assert read(AH / 'audit/final-status.json')['status'] == 'PASS-CONDITIONAL-KC-DRIVE-AUDIT'
assert read(AG / 'audit/final-status.json')['numerical_gate_pass']
for sub in ('protocol', 'regression', 'trials', 'audit', 'logs'):
(EXP / sub).mkdir(parents=True, exist_ok=False)
test_command = [sys.executable, '-B', '-m', 'unittest', '-v',
'test_pn_observer', 'test_apl_sources', 'test_structure_metrics', 'test_harness',
'test_validate_events', 'test_publication']
tested = subprocess.run(test_command, cwd=MODEL, capture_output=True, text=True)
with (EXP / 'regression/unit-tests.log').open('x') as f:
f.write(tested.stdout + tested.stderr)
save(EXP / 'regression/unit-tests.json', dict(command=test_command, exit_code=tested.returncode,
pass_all=tested.returncode == 0, sha256=digest(EXP / 'regression/unit-tests.log')))
assert tested.returncode == 0
paths = [AH / 'manifest.json', AH / 'checksums.sha256', AH_MODEL / 'manifest.json',
AH_MODEL / 'checksums.sha256', AH_MODEL / 'replay_core.py', AH_MODEL / 'populations.py',
AG / 'manifest.json', AG / 'checksums.sha256', AG_MODEL / 'manifest.json',
AG_MODEL / 'checksums.sha256', META, COEFF,
ROOT / 'datasets/male-cns-v1.0/processed/neuron-only/gpu/csr-weights.int64.npy']
save(EXP / 'protocol/preregistered.json', dict(
timestamp_utc=datetime.now(timezone.utc).isoformat(), sources=sources(),
inputs=[dict(path=str(p.relative_to(ROOT)), sha256=digest(p)) for p in paths],
parent_commit=subprocess.check_output(['git', '-C', str(ROOT), 'rev-parse', 'HEAD'], text=True).strip(),
scope='Post-outcome conditional PN/APL source audit; no new whole-brain simulation or learning',
previous_KC_outcome_known=True, before_PN_contribution_accounting=True,
new_GPU_use=False, max_threads=4, output_budget_bytes=2 * 1024**3,
per_trial_first_arrival_row_limit=1000000, truncation_allowed=False,
exact_gate='All PN events/counts/final v,g,ref; fixture pre/post histories; 12 deterministic accounting repeats',
APL_gate='Source float64 mathematical accounting within prior standard-float32 analytic roundoff bounds; not CUDA bitwise replay',
hypotheses={
'temporal_precedence': 'For every trial and every KC first spike, non-design PN spike must be strictly earlier; equals/after/absent retained',
'direct_PN_KC_arrival': 'PN source tick+18 strictly less than KC first spike; same tick arrival is after threshold',
'APL_source_precedence': 'Group h write at tick s affects only KC threshold ticks greater than s',
'APL_share': 'Cumulative group shares are descriptive float64; no accumulated source-share error bound or robust-majority claim',
'odor_structure': 'Fixed 686-dimensional counts; secondary fixed outside-six-odor-design-union subset; no activity-fraction or learning gate'},
attribution_limits=['Accepted edge antecedents are not proof of single-neuron necessity or intervention causality',
'Non-design means not in static design targets; does not mean noise or biologically incorrect',
'Source-V lanes are non-feedback accounting with initial/constant/request/reset/roundoff lanes',
'APL input matrix is legacy nonnegative raw-contact-normalized engineering mapping, not signed LIF current',
'No CAL per-tick target state was independently saved; final states and events only',
'Fixtures generated h for 4064 KC but applied only to fixture KC'],
python=sys.version, numpy=np.__version__, pandas=pd.__version__, machine=platform.machine(),
longdouble_mantissa_bits=int(np.finfo(np.longdouble).nmant)))
save(EXP / 'regression/old-integrity-before.json', integrity())
population = load_module('frozen_population_ai', AH_MODEL / 'populations.py')
assert digest(META) == population.METADATA_SHA256
meta = pd.read_parquet(META).sort_values('neuron_idx').reset_index(drop=True)
labels, report = population.classify(meta)
assert report['pass_all']
for name, count in (('ALLN', 420), ('ALIN', 24), ('ALON', 14), ('olfactory', 2639)):
selected = (meta.annotation_class == name).fillna(False).to_numpy(dtype=bool)
assert int(selected.sum()) == count and np.all(labels[selected] == 'other')
labels[selected] = 'olfactory_sensory' if name == 'olfactory' else name
assert set(np.unique(labels)).issubset(GROUPS)
for label, fname, count in (('KC', 'kc_globals.npy', 4064), ('APL', 'apl_globals.npy', 2), ('ALPN', 'pn_globals.npy', 686)):
observed = np.flatnonzero(labels == label).astype(np.int32)
assert len(observed) == count and np.array_equal(observed, np.load(AG / 'apl-bundle' / fname))
report.update(refined_exact_class_counts={label: int((labels == label).sum()) for label in GROUPS},
refinement='AH anatomical classifier, then exact ALLN/ALIN/ALON/olfactory classes split only from other; no name-prefix guessing')
save(EXP / 'protocol/population-audit.json', report)
save(EXP / 'protocol/metadata-schema.json', {c: dict(dtype=str(meta[c].dtype), nulls=int(meta[c].isna().sum())) for c in meta})
meta[['neuron_idx', 'body_id', 'annotation_class', 'annotation_type', 'neurotransmitter']].assign(
audit_source_group=labels).to_parquet(EXP / 'protocol/neuron-source-groups.parquet', index=False)
inventory = [dict(case=name, repeat=0, kind='fixture') for name in read(AG_MODEL / 'config.json')['fixtures']]
for row in read(AG / 'protocol/calibration-cases.json'):
inventory.append(dict(case=row['name'], repeat=0, kind='calibration'))
if row['seed'] == 51101:
inventory.append(dict(case=row['name'], repeat=1, kind='calibration'))
assert len(inventory) == len({(r['case'], r['repeat']) for r in inventory}) == 80
for row in inventory:
source = AG / 'gpu' / (row['case'] + '-r' + str(row['repeat']))
assert read(source / 'summary.json')['complete']
row['source'] = str(source.relative_to(ROOT))
save(EXP / 'protocol/inventory.json', inventory)
save(EXP / 'protocol/prepared-hashes.json', [dict(path=str(p.relative_to(EXP)), sha256=digest(p))
for p in sorted((EXP / 'protocol').iterdir()) if p.is_file() and p.name != 'prepared-hashes.json'])
print('REGISTERED fixed 80 existing records; no new brain simulation', flush=True)
if __name__ == '__main__':
main()
@@ -0,0 +1,270 @@
"""Publish small evidence only after independent verification of both seals.
No prior verification helper is imported or executed. Publishing verifies
bytes and declared completion; it does not rerun or certify a scientific gate.
Every destination is exclusive. An interrupted publication is retained, not
deleted, overwritten, or silently resumed.
"""
from __future__ import annotations
import hashlib
import json
from pathlib import Path, PurePosixPath
import re
import shutil
import stat
ROOT = Path('/data/digital-drosophila')
MODEL_RELATIVE = Path('models/male-cns-lif/pn-recruitment-audit-v1')
EXPERIMENT_RELATIVE = Path('experiments/phase4ai-pn-recruitment-audit')
REGISTRY_RELATIVE = Path('registry/phase4ai-pn-recruitment-audit')
FINAL_STATUS = 'PASS-CONDITIONAL-PN-APL-SOURCE-AUDIT'
MAX_EVIDENCE_BYTES = 4 * 1024 ** 2
EVIDENCE_SUFFIXES = frozenset(('.json', '.csv', '.md', '.log', '.sha256'))
CONTROLS = frozenset(('manifest.json', 'checksums.sha256'))
SHA256 = re.compile(r'^[0-9a-f]{64}$')
def _require(condition, message):
if not condition:
raise ValueError(message)
def _unique_object(pairs):
result = {}
for name, value in pairs:
_require(name not in result, 'Duplicate JSON object key: ' + name)
result[name] = value
return result
def _bad_constant(value):
raise ValueError('Nonfinite JSON constant: ' + value)
def _json_bytes(data):
return json.loads(data.decode('utf-8'), object_pairs_hook=_unique_object,
parse_constant=_bad_constant)
def _digest(path):
checksum = hashlib.sha256()
with Path(path).open('rb') as handle:
for block in iter(lambda: handle.read(8 << 20), b''):
checksum.update(block)
return checksum.hexdigest()
def _write_json(path, value):
with Path(path).open('x', encoding='utf-8') as handle:
json.dump(value, handle, indent=2, ensure_ascii=False, allow_nan=False)
handle.write('\n')
def _relative_name(value):
_require(isinstance(value, str) and bool(value) and '\\' not in value and
'\x00' not in value and '\n' not in value and '\r' not in value,
'Invalid manifest/checksum relative path')
path = PurePosixPath(value)
_require(not path.is_absolute() and str(path) == value and
all(part not in ('', '.', '..') and ':' not in part for part in path.parts),
'Noncanonical or escaping relative path: ' + value)
return path
def _regular_file(base, relative):
rel = _relative_name(relative)
target = base
for part in rel.parts:
target = target / part
_require(not target.is_symlink(), 'Symlink not allowed in sealed path: ' + str(target))
_require(target.exists() and stat.S_ISREG(target.stat().st_mode),
'Missing/nonregular sealed file: ' + str(target))
_require(target.resolve().is_relative_to(base), 'Sealed file escapes its root')
return target
def verify_seal(directory):
"""Independently verify every listed byte/hash and the checksum inventory.
Unlisted files fail, apart from __pycache__ files explicitly excluded by
the producer's seal contract. Such caches are counted, never published.
The checksum file must describe exactly the manifest payload plus the
manifest itself. Symlinks, duplicate paths and path traversal fail.
"""
supplied = Path(directory)
_require(supplied.is_absolute() and supplied.is_dir() and not supplied.is_symlink(),
'A sealed root must be an absolute real directory')
base = supplied.resolve(strict=True)
manifest_path = _regular_file(base, 'manifest.json')
checksums_path = _regular_file(base, 'checksums.sha256')
manifest_bytes = manifest_path.read_bytes()
manifest_sha = hashlib.sha256(manifest_bytes).hexdigest()
manifest = _json_bytes(manifest_bytes)
_require(isinstance(manifest, dict) and set(manifest) == {'root', 'files'}, 'Unexpected seal manifest schema')
_require(isinstance(manifest['root'], str) and Path(manifest['root']).is_absolute() and
Path(manifest['root']).resolve(strict=True) == base, 'Manifest names another root')
_require(isinstance(manifest['files'], list) and bool(manifest['files']), 'Empty/invalid manifest payload')
rows, expected = [], {}
for row in manifest['files']:
_require(isinstance(row, dict) and set(row) == {'path', 'bytes', 'sha256'}, 'Invalid manifest file row')
relative = row['path']
parsed = _relative_name(relative)
_require(relative not in CONTROLS and '__pycache__' not in parsed.parts,
'Control/cache file incorrectly listed as payload: ' + relative)
_require(relative not in expected, 'Duplicate manifest path: ' + relative)
_require(type(row['bytes']) is int and row['bytes'] >= 0 and isinstance(row['sha256'], str) and
SHA256.fullmatch(row['sha256']), 'Invalid byte count or SHA-256: ' + relative)
path = _regular_file(base, relative)
_require(path.stat().st_size == row['bytes'], 'Payload byte count mismatch: ' + relative)
_require(_digest(path) == row['sha256'], 'Payload SHA-256 mismatch: ' + relative)
_require(path.stat().st_size == row['bytes'], 'Payload changed during verification: ' + relative)
expected[relative] = row['sha256']
rows.append(dict(row))
observed, excluded_caches = set(), 0
for path in base.rglob('*'):
_require(not path.is_symlink(), 'Symlink found in sealed tree: ' + str(path))
if path.is_dir():
continue
_require(stat.S_ISREG(path.stat().st_mode), 'Nonregular file in sealed tree: ' + str(path))
relative = path.relative_to(base).as_posix()
if '__pycache__' in path.relative_to(base).parts:
excluded_caches += 1
else:
observed.add(relative)
_require(observed == set(expected) | CONTROLS,
'Sealed tree has unlisted/missing files: ' + repr(sorted(observed ^ (set(expected) | CONTROLS))))
checksums_bytes = checksums_path.read_bytes()
checksum_rows = {}
for line in checksums_bytes.decode('utf-8').splitlines():
_require(len(line) >= 67 and line[64:66] == ' ' and SHA256.fullmatch(line[:64]),
'Malformed checksums.sha256 line')
relative = line[66:]
_relative_name(relative)
_require(relative not in checksum_rows, 'Duplicate checksum path: ' + relative)
checksum_rows[relative] = line[:64]
_require(checksum_rows == {**expected, 'manifest.json': manifest_sha},
'Checksum inventory or manifest self-checksum mismatch')
return dict(pass_all=True, root=str(base), payload_file_count=len(rows),
payload_bytes=sum(row['bytes'] for row in rows), manifest_sha256=manifest_sha,
checksums_sha256=hashlib.sha256(checksums_bytes).hexdigest(),
excluded_pycache_files=excluded_caches, files=sorted(rows, key=lambda row: row['path']),
verification_scope='All sealed payload bytes/SHA-256, exact checksum inventory, and manifest self-SHA; no scientific gate execution')
def _copy_verified(source, destination, byte_count, checksum):
_require(source.stat().st_size == byte_count, 'Source size changed before evidence copy')
destination.parent.mkdir(parents=True, exist_ok=True)
with source.open('rb') as src, destination.open('xb') as dst:
shutil.copyfileobj(src, dst, length=1 << 20)
_require(destination.stat().st_size == byte_count and _digest(destination) == checksum,
'Copied evidence failed its sealed byte/hash check')
_require(source.stat().st_size == byte_count and _digest(source) == checksum,
'Sealed source changed during evidence copy')
def _control_rows(root, verification):
return [dict(path='manifest.json', bytes=(root / 'manifest.json').stat().st_size,
sha256=verification['manifest_sha256']),
dict(path='checksums.sha256', bytes=(root / 'checksums.sha256').stat().st_size,
sha256=verification['checksums_sha256'])]
def publish(root=ROOT):
"""Create the one new registry exclusively; call only after finalize seals.
``root`` exists for isolated synthetic tests. Production uses the fixed
default project root and fixed Phase 4AI relative directories above.
"""
root = Path(root)
_require(root.is_absolute() and root.is_dir() and not root.is_symlink(), 'Invalid project root')
root = root.resolve(strict=True)
model, experiment, registry = (root / part for part in
(MODEL_RELATIVE, EXPERIMENT_RELATIVE, REGISTRY_RELATIVE))
_require(not registry.exists() and not registry.is_symlink(), 'Registry already exists; no overwrite/resume')
for path in (model, experiment, registry.parent):
current = root
for part in path.relative_to(root).parts:
current = current / part
_require(not current.is_symlink(), 'Symlink in publication root path: ' + str(current))
verified = {'model': verify_seal(model), 'experiment': verify_seal(experiment)}
experiment_rows = {row['path']: row for row in verified['experiment']['files']}
_require('audit/final-status.json' in experiment_rows,
'Final status must exist inside the sealed experiment payload')
status = _json_bytes((experiment / 'audit/final-status.json').read_bytes())
_require(isinstance(status, dict) and status.get('status') == FINAL_STATUS and
status.get('pass_all') is True, 'Finalize completion status is missing or unexpected')
for flag in ('candidate_generated', 'learning_achieved', 'new_brain_simulation', 'GPU_used'):
_require(status.get(flag) is False, 'Unexpected finalized scope flag: ' + flag)
plans, omitted = [], []
for row in verified['experiment']['files'] + _control_rows(experiment, verified['experiment']):
allowed = PurePosixPath(row['path']).suffix.lower() in EVIDENCE_SUFFIXES
if allowed and row['bytes'] <= MAX_EVIDENCE_BYTES:
plans.append((experiment, row, 'evidence/' + row['path']))
else:
omitted.append(dict(path=row['path'], bytes=row['bytes'],
reason='exceeds_4_MiB' if row['bytes'] > MAX_EVIDENCE_BYTES else 'bulk_or_non_evidence_extension'))
for row in _control_rows(model, verified['model']):
_require(row['bytes'] <= MAX_EVIDENCE_BYTES, 'Model seal control exceeds small-evidence limit')
plans.append((model, row, 'model/' + row['path']))
for control in ('manifest.json', 'checksums.sha256'):
_require(any(target == 'evidence/' + control for _, _, target in plans),
'Experiment seal control exceeds small-evidence limit')
_require(any(target == 'evidence/audit/final-status.json' for _, _, target in plans),
'Final status exceeds small-evidence limit')
registry.parent.mkdir(parents=True, exist_ok=True)
registry.mkdir(exist_ok=False)
try:
records = []
for source_root, row, relative in plans:
source = _regular_file(source_root.resolve(), row['path'])
target = registry / relative
_copy_verified(source, target, row['bytes'], row['sha256'])
records.append(dict(source=source.relative_to(root).as_posix(), copy=relative,
bytes=row['bytes'], sha256=row['sha256']))
# Revalidate after copying, including payloads deliberately not copied.
after = {'model': verify_seal(model), 'experiment': verify_seal(experiment)}
_require(after == verified, 'A sealed tree changed during publication')
proof = {name: {key: value for key, value in report.items() if key != 'files'}
for name, report in verified.items()}
_write_json(registry / 'seal-verification.json', proof)
_write_json(registry / 'evidence-index.json', records)
receipt_files = []
for path in sorted(registry.rglob('*')):
if path.is_file():
receipt_files.append(dict(path=path.relative_to(registry).as_posix(),
bytes=path.stat().st_size, sha256=_digest(path)))
receipt = dict(publication_complete=True, registry=registry.relative_to(root).as_posix(),
project_root=str(root), declared_audit_status=status['status'],
model_manifest_sha256=verified['model']['manifest_sha256'],
experiment_manifest_sha256=verified['experiment']['manifest_sha256'],
copied_evidence_files=len(records), copied_evidence_bytes=sum(row['bytes'] for row in records),
files=receipt_files, experiment_payload_not_copied=omitted,
model_payload_not_duplicated=True, model_payload_remains_at=MODEL_RELATIVE.as_posix(),
bulk_remains_at=EXPERIMENT_RELATIVE.as_posix(),
complete_bulk_backup=False, scientific_gate_executed_by_publisher=False,
scientific_gate_certified_by_publication=False, candidate_generated=False,
learning_achieved=False, existing_files_modified=False,
receipt_self_hash='Not self-referential; returned by publish() and printed by main()',
limits=dict(max_selected_evidence_file_bytes=MAX_EVIDENCE_BYTES,
selected_suffixes=sorted(EVIDENCE_SUFFIXES)))
receipt_path = registry / 'publication-receipt.json'
_write_json(receipt_path, receipt)
return dict(publication_complete=True, registry=str(registry), copied_evidence_files=len(records),
receipt_sha256=_digest(receipt_path), scientific_gate_executed_by_publisher=False)
except Exception as error:
failure = registry / 'publication-failure.json'
if not failure.exists():
_write_json(failure, dict(publication_complete=False, type=type(error).__name__,
message=str(error), partial_outputs_preserved=True,
existing_files_modified=False))
raise
def main():
print(json.dumps(publish(), ensure_ascii=False, allow_nan=False), flush=True)
if __name__ == '__main__':
main()
@@ -0,0 +1,283 @@
"""Read existing records and replay PN targets only; no GPU or counterfactual."""
from functools import lru_cache
import time
import traceback
import numpy as np
import pandas as pd
import pyarrow as pa
import pyarrow.parquet as pq
from context import (ROOT, EXP, AH_MODEL, AG, COEFF, GROUPS, read, save, digest,
check, bit_equal, load_module)
from pn_observer import PNObserver
from apl_sources import decompose_apl_sources
def first_ticks(event_tick, event_node, targets):
first = np.full(166700, np.iinfo(np.int32).max, np.int32)
np.minimum.at(first, event_node, event_tick)
first[first == np.iinfo(np.int32).max] = -1
return first[targets]
def temporal_relation(source_tick, target_tick):
if source_tick < 0 or target_tick < 0:
return 'unobserved_source' if source_tick < 0 and target_tick >= 0 else (
'unobserved_target' if source_tick >= 0 else 'both_unobserved')
return 'before' if source_tick < target_tick else ('same_tick' if source_tick == target_tick else 'after')
def min_observed(values):
values = np.asarray(values)
values = values[values >= 0]
return int(values.min()) if len(values) else -1
class EventSink:
"""Streaming accepted antecedents, never silently truncate."""
def __init__(self, path):
ints64 = ('edge_id', 'incoming_edge_row')
ints32 = ('source_neuron_idx', 'target_neuron_idx', 'source_spike_tick', 'arrival_tick',
'weight_sign', 'ref_before', 'ref_at_arrival')
bools = ('target_is_design', 'accepted', 'available_at_integration')
floats = ('weight_SI', 'old_v_SI', 'old_g_SI', 'v_integrated_SI', 'v_prethreshold_SI',
'threshold_margin_SI', 'g_before_arrivals_SI')
self.schema = pa.schema([(k, t) for names, t in ((ints64, pa.int64()), (ints32, pa.int32()),
(bools, pa.bool_()), (floats, pa.float64()), (('source_group', 'record_scope'), pa.string())) for k in names])
assert not path.exists()
self.writer = pq.ParquetWriter(path, self.schema, compression='zstd')
self.rows = 0
def __call__(self, rows):
self.writer.write_table(pa.Table.from_pylist(rows, schema=self.schema))
self.rows += len(rows)
def close(self):
self.writer.close()
@lru_cache(maxsize=2)
def graph_view(graph_name):
core = load_module('sealed_ah_replay_ai_' + graph_name, AH_MODEL / 'replay_core.py')
folder = AG / 'graphs' / graph_name
nodes = np.load(folder / 'nodes.npy', mmap_mode='r')
pn = np.load(AG / 'apl-bundle/pn_globals.npy')
apl = np.load(AG / 'apl-bundle/apl_globals.npy')
targets, positions, _ = np.intersect1d(nodes, pn, assume_unique=True, return_indices=True)
assert len(targets) > 0, 'Empty PN fixture subset: stop and report nonapplicable; never fabricate targets'
lookup = np.full(len(nodes), -1, np.int32)
lookup[positions] = np.arange(len(targets), dtype=np.int32)
dst = np.load(folder / 'dst.npy', mmap_mode='r')
selected = np.flatnonzero(lookup[dst] >= 0)
src = nodes[np.load(folder / 'src.npy', mmap_mode='r')[selected]]
ids = np.load(folder / 'edge_id.npy', mmap_mode='r')[selected]
weights = np.load(folder / 'weights.npy', mmap_mode='r')[selected].copy()
weights[np.isin(src, apl)] = 0.0
raw = np.load(ROOT / 'datasets/male-cns-v1.0/processed/neuron-only/gpu/csr-weights.int64.npy', mmap_mode='r')[ids]
assert raw.dtype == np.int64 and np.all(raw > 0)
incoming = core.IncomingIndex(src, lookup[dst[selected]], ids, weights, len(targets))
groups = pd.read_parquet(EXP / 'protocol/neuron-source-groups.parquet').audit_source_group.to_numpy()
codes = np.array([GROUPS.index(x) for x in groups], np.int32)[src]
audit = dict(graph=graph_name, PN_targets=len(targets), incoming_edges=len(ids), contacts=int(raw.sum()),
zeroed_fast_APL_edges=int(np.isin(src, apl).sum()), graded_APL_to_PN=False,
groups={g: dict(edges=int((codes == i).sum()), contacts=int(raw[codes == i].sum())) for i, g in enumerate(GROUPS)},
source_graph_unchanged=True, effective_fast_APL_zero_mask_preserved=True)
return core, incoming, raw, codes, targets, positions, audit
@lru_cache(maxsize=2)
def pn_kc_edges(graph_name):
folder = AG / 'graphs' / graph_name
nodes = np.load(folder / 'nodes.npy', mmap_mode='r')
pn = np.load(AG / 'apl-bundle/pn_globals.npy')
kc = np.load(AG / 'apl-bundle/kc_globals.npy')
src = nodes[np.load(folder / 'src.npy', mmap_mode='r')]
dst = nodes[np.load(folder / 'dst.npy', mmap_mode='r')]
picked = np.flatnonzero(np.isin(src, pn) & np.isin(dst, kc))
return src[picked], np.searchsorted(kc, dst[picked]), np.load(folder / 'weights.npy', mmap_mode='r')[picked]
def pn_kc_before_first(graph_name, state, kc_first, design):
"""All PN edge arrivals strictly before first KC spike; no refractory yet."""
src, dst, weights = pn_kc_edges(graph_name)
rows = {'neuron_idx': np.load(AG / 'apl-bundle/kc_globals.npy').copy(), 'first_spike_tick': kc_first.copy()}
for name in ('design_ALPN', 'non_design_ALPN'):
rows[name + '_strict_pre_first_edge_events'] = np.zeros(len(kc_first), np.int64)
rows[name + '_strict_pre_first_positive_V'] = np.zeros(len(kc_first), np.float64)
rows[name + '_strict_pre_first_negative_abs_V'] = np.zeros(len(kc_first), np.float64)
# Fixed graph edges only. Before the first spike, initially zero ref has never been reset.
for source in np.unique(src):
edges = np.flatnonzero((src == source) & (kc_first[dst] >= 0))
spikes = state['step'][state['neuron_idx'] == source]
count = np.searchsorted(spikes, kc_first[dst[edges]] - 18, side='left')
label = 'design_ALPN' if source in design else 'non_design_ALPN'
np.add.at(rows[label + '_strict_pre_first_edge_events'], dst[edges], count)
np.add.at(rows[label + '_strict_pre_first_positive_V'], dst[edges], count * np.maximum(weights[edges], 0))
np.add.at(rows[label + '_strict_pre_first_negative_abs_V'], dst[edges], count * np.maximum(-weights[edges], 0))
return rows
def audit_trial(row, population):
start = time.perf_counter()
out = EXP / 'trials' / (row['case'] + '-r' + str(row['repeat']))
out.mkdir(exist_ok=False)
source, case = ROOT / row['source'], AG / 'cases' / row['case']
spec = read(case / 'spec.json')
graph_name = 'fixtures' if row['kind'] == 'fixture' else 'full'
core, incoming, raw, codes, targets, positions, graph_audit = graph_view(graph_name)
with np.load(source / 'state.npz', allow_pickle=False) as data:
state = {k: data[k].copy() for k in data.files}
assert set(state) == {'step', 'neuron_idx', 'counts', 'v', 'g', 'ref'}
with np.load(case / 'requests.npz', allow_pickle=False) as data:
req = {k: data[k].copy() for k in data.files}
rt = pd.read_csv(source / 'requests.csv')
assert np.array_equal(req['tick'], rt.tick) and np.array_equal(req['neuron_idx'], rt.neuron_idx)
assert (rt.attempted == 1).all() and rt.accepted.isin([0, 1]).all()
assert np.array_equal(rt.rejected, 1 - rt.accepted)
if row['kind'] == 'calibration':
with np.load(case / 'pn-drive.npz', allow_pickle=False) as data:
design = np.sort(data['targets'].copy())
assert design.dtype == np.int32 and data['rates_hz'].dtype == np.float32
assert len(design) == spec['target_count'] and (data['rates_hz'] > 0).all()
else:
design = np.intersect1d(req['neuron_idx'], targets)
assert np.isin(design, targets).all() and len(np.unique(design)) == len(design)
expected_mask = np.isin(state['neuron_idx'], targets)
expected = {k: state[k][expected_mask] for k in ('step', 'neuron_idx')}
initial_v = np.full(len(targets), spec['model']['resting_potential_mv'], np.float64) * np.float64(.001)
initial_g = np.zeros(len(targets), np.float64)
if (case / 'arrays.npz').exists():
with np.load(case / 'arrays.npz', allow_pickle=False) as data:
initial_v = data['initial_v_mv'][positions] * np.float64(.001)
initial_g = data['initial_g_mv'][positions] * np.float64(.001)
histories = {}
if row['kind'] == 'fixture':
for key, dtype in (('v', 'float64'), ('g', 'float64'), ('ref', 'int32')):
histories[key] = np.load(source / f'{key}-history.{dtype}.npy', mmap_mode='r')[:, positions]
histories['pre_' + key] = np.load(source / f'preAPL-{key}.{dtype}.npy', mmap_mode='r')[:, positions]
sink = EventSink(out / 'accepted-prefirst-edge-events.parquet')
observer = PNObserver(targets, design, incoming, codes, GROUPS, read(COEFF), spec['steps'],
max_first_event_rows=1000000, event_sink=sink)
request_lookup = np.full(166700, -1, np.int32)
request_lookup[targets] = np.arange(len(targets), dtype=np.int32)
def callback(tick, stage):
for key in ('v', 'g', 'ref'):
if histories:
assert bit_equal(stage[key], histories[key][tick]), 'Fixture post state mismatch'
assert bit_equal(stage[key + '_pre_apl'], histories['pre_' + key][tick]), 'Fixture pre state mismatch'
indices = np.flatnonzero((req['tick'] == tick) & np.isin(req['neuron_idx'], targets))
if len(indices):
local = request_lookup[req['neuron_idx'][indices]]
assert np.array_equal(stage['request_accepted'][local], rt.accepted.to_numpy()[indices].astype(bool))
observer(tick, stage)
try:
result = core.replay(initial_v, initial_g, read(COEFF), spec['steps'], targets, req,
dict(step=state['step'], neuron_idx=state['neuron_idx']), incoming,
np.zeros((spec['steps'], len(targets)), np.float32), callback)
finally:
sink.close()
exact = {k: bit_equal(result[k], state[k][positions]) for k in ('v', 'g', 'ref', 'counts')}
exact.update({k: bit_equal(result[k], expected[k]) for k in ('step', 'neuron_idx')})
assert all(exact.values()), 'PN replay diverged: ' + str(exact)
data, observer_report = observer.finish(result)
assert sink.rows == observer_report['first_arrival_record_count']
table = pd.DataFrame(data)
table.insert(1, 'body_id', population.iloc[targets].body_id.to_numpy())
table.insert(2, 'annotation_type', population.iloc[targets].annotation_type.to_numpy())
table.to_parquet(out / 'per-pn.parquet', index=False)
edges = pd.DataFrame(observer.edge_summary())
if len(edges):
edge_positions = np.searchsorted(incoming.edge_id, edges.edge_id.to_numpy())
assert np.array_equal(incoming.edge_id[edge_positions], edges.edge_id.to_numpy())
edges['raw_contact_count'] = raw[edge_positions]
for prefix in ('source', 'target'):
global_ids = edges[prefix + '_neuron_idx'].to_numpy()
edges[prefix + '_body_id'] = population.iloc[global_ids].body_id.to_numpy()
edges[prefix + '_type'] = population.iloc[global_ids].annotation_type.to_numpy()
edges.to_parquet(out / 'prefirst-edge-summary.parquet', index=False)
with (out / 'replay-final.npz').open('xb') as f:
np.savez_compressed(f, **result)
kc = np.load(AG / 'apl-bundle/kc_globals.npy')
pn = np.load(AG / 'apl-bundle/pn_globals.npy')
first_kc = first_ticks(state['step'], state['neuron_idx'], kc)
first_pn = first_ticks(state['step'], state['neuron_idx'], pn)
first_nondesign = min_observed(first_pn[~np.isin(pn, design)])
first_anykc = min_observed(first_kc)
component = read(source / 'apl-component.json')
env = component['environment']
assert env['cuda_matmul_allow_tf32'] is False and env['float32_matmul_precision'] == 'highest'
d32 = np.array([int(component['decay_f32_bits'], 16)], np.uint32).view(np.float32)[0]
q32 = np.array([int(component['gain_f32_bits'], 16)], np.uint32).view(np.float32)[0]
apl = decompose_apl_sources(np.load(AG / 'apl-bundle/input_matrix.npy', mmap_mode='r'),
np.load(AG / 'apl-bundle/output_matrix.npy', mmap_mode='r'), pn, kc, design,
state['step'], state['neuron_idx'], np.load(source / 'apl-drive.float32.npy', mmap_mode='r'),
np.load(source / 'apl-state.float32.npy', mmap_mode='r'),
np.load(source / 'apl-inhibition.float32.npy', mmap_mode='r'),
decay32=d32, gain32=q32, standard_fp32=True, first_kc_tick=first_kc)
assert apl['summary']['pass_all']
save(out / 'apl-source-summary.json', apl['summary'])
pd.DataFrame(apl['tick_rows']).to_parquet(out / 'apl-per-tick.parquet', index=False)
per_kc = pd.DataFrame(apl['per_kc'])
per_kc.insert(1, 'body_id', population.iloc[kc].body_id.to_numpy())
per_kc['KC_present_in_source_graph'] = np.isin(kc, np.load(spec['graph_dir'] + '/nodes.npy'))
per_kc['first_non_design_PN_tick'] = first_nondesign
per_kc['first_non_design_relation'] = [temporal_relation(first_nondesign, int(t)) for t in first_kc]
for key, value in pn_kc_before_first(graph_name, state, first_kc, design).items():
if key not in ('neuron_idx', 'first_spike_tick'):
per_kc[key] = value
per_kc.to_parquet(out / 'per-kc-apl-sources.parquet', index=False)
report = dict(case=row['case'], repeat=row['repeat'], kind=row['kind'], pass_all=True, exact=exact,
every_tick_fixture_pre_post_exact=bool(histories), CAL_per_tick_independent_state_available=False,
steps=spec['steps'], duration_ms=spec['duration_ms'], mode=spec.get('mode'), seed=spec.get('seed'),
odor_id=spec.get('odor_id'), graph=graph_audit, observer=observer_report,
first_non_design_PN_tick=first_nondesign, first_any_KC_tick=first_anykc,
first_non_design_vs_first_KC=temporal_relation(first_nondesign, first_anykc),
fixture_design_definition='Unique requested PN IDs for numerical fixture only; not odor design' if histories else None,
APL_source_bound_pass=apl['summary']['pass_all'], candidate_generated=False, new_brain_simulation=False,
CPU_audit_wall_seconds=time.perf_counter() - start,
input_sha256={f: digest(source / f) for f in ('state.npz', 'requests.csv', 'summary.json',
'apl-component.json', 'apl-drive.float32.npy', 'apl-state.float32.npy', 'apl-inhibition.float32.npy')})
save(out / 'summary.json', report)
save(out / 'output-hashes.json', [dict(path=p.name, sha256=digest(p), bytes=p.stat().st_size)
for p in sorted(out.iterdir()) if p.is_file()])
return report
def main():
check()
population = pd.read_parquet(EXP / 'protocol/neuron-source-groups.parquet')
inventory = read(EXP / 'protocol/inventory.json')
receipts = []
for row in inventory:
try:
report = audit_trial(row, population)
receipts.append(dict(case=row['case'], repeat=row['repeat'], pass_all=report['pass_all']))
assert sum(p.stat().st_size for p in EXP.rglob('*') if p.is_file()) < 2 * 1024**3
print(row['case'], row['repeat'], 'EXACT PN / APL BOUND PASS',
round(report['CPU_audit_wall_seconds'], 3), 'CPU sec', flush=True)
except Exception as error:
save(EXP / 'audit/failure.json', dict(case=row, error=type(error).__name__, message=str(error),
traceback=traceback.format_exc(), completed=receipts, new_brain_simulation=False))
raise
repeats = []
for row in inventory:
if row['repeat'] != 1:
continue
a = EXP / 'trials' / (row['case'] + '-r0')
b = EXP / 'trials' / (row['case'] + '-r1')
checks = {}
for f in ('per-pn.parquet', 'prefirst-edge-summary.parquet', 'apl-per-tick.parquet', 'per-kc-apl-sources.parquet'):
checks[f] = pd.read_parquet(a / f).equals(pd.read_parquet(b / f))
checks['antecedent_events'] = digest(a / 'accepted-prefirst-edge-events.parquet') == digest(b / 'accepted-prefirst-edge-events.parquet')
checks['apl-summary'] = read(a / 'apl-source-summary.json') == read(b / 'apl-source-summary.json')
with np.load(a / 'replay-final.npz') as aa, np.load(b / 'replay-final.npz') as bb:
checks['replay'] = set(aa.files) == set(bb.files) and all(bit_equal(aa[k], bb[k]) for k in aa.files)
assert all(checks.values()), 'Repeated accounting differs'
repeats.append(dict(case=row['case'], pass_all=True, checks=checks))
assert len(receipts) == 80 and len(repeats) == 12
save(EXP / 'audit/completed.json', dict(pass_all=True, trials=receipts, repeat_checks=repeats,
meaning='Conditional PN exactness and bounded APL attribution only; not a learning or causal gate'))
print('PASS 80 conditional audits and 12 repeats', flush=True)
if __name__ == '__main__':
main()
@@ -0,0 +1,179 @@
"""Fixed descriptive ALPN-count comparisons; pure NumPy, no files or tuning.
Column positions refer to the caller's fixed canonical 686-ALPN order. This
module cannot assign body IDs or infer anatomical identities. Repeated runs
are integrity evidence, never additional independent seeds in these metrics.
"""
from __future__ import annotations
import itertools
import numpy as np
MODES = ('physiological', 'matched_energy')
ODORS = tuple(range(6))
SEEDS = tuple(range(51101, 51106))
N_ALPN = 686
FIELDS = frozenset(('mode', 'odor_index', 'seed', 'counts', 'design_mask'))
METRICS = ('cosine_distance', 'pearson_correlation', 'jaccard', 'euclidean_distance')
def _require(condition, message):
if not condition:
raise ValueError(message)
def _integer(value, name):
_require(isinstance(value, (int, np.integer)) and not isinstance(value, (bool, np.bool_)),
name + ' must be an integer, not a Boolean')
return int(value)
def _array(value, dtype, name):
_require(isinstance(value, np.ndarray) and not np.ma.isMaskedArray(value),
name + ' must be an unmasked NumPy array')
_require(value.dtype == np.dtype(dtype) and value.shape == (N_ALPN,),
name + ' must have dtype ' + np.dtype(dtype).name + ' and shape (686,)')
return np.array(value, copy=True, order='C')
def _pair_metrics(first, second):
# Cast BEFORE subtraction/norm so int32 extrema do not overflow.
x, y = first.astype(np.float64), second.astype(np.float64)
active_x, active_y = first > 0, second > 0
intersection = int(np.count_nonzero(active_x & active_y))
union = int(np.count_nonzero(active_x | active_y))
result = dict(active_a=int(active_x.sum()), active_b=int(active_y.sum()),
active_intersection=intersection, active_union=union)
if not len(first):
result.update({name: None for name in METRICS})
return result
norm_x, norm_y = float(np.linalg.norm(x)), float(np.linalg.norm(y))
cosine = None if norm_x == 0 or norm_y == 0 else float(np.clip(
np.dot(x, y) / (norm_x * norm_y), -1., 1.))
# A constant or one-channel vector has undefined Pearson correlation;
# equality does not turn it into evidence of shared structure.
correlation = None if bool(np.all(x == x[0]) or np.all(y == y[0])) else float(
np.clip(np.corrcoef(x, y)[0, 1], -1., 1.))
result.update(cosine_distance=None if cosine is None else float(1. - cosine),
pearson_correlation=correlation,
jaccard=None if union == 0 else float(intersection / union),
euclidean_distance=float(np.linalg.norm(x - y)))
_require(all(value is None or np.isfinite(value) for value in result.values()),
'A structure metric became nonfinite')
return result
def _summary(rows):
result = {}
for name in METRICS:
values = np.asarray([row[name] for row in rows if row[name] is not None], np.float64)
result[name] = dict(mean=None if not len(values) else float(values.mean()),
variance_ddof0=None if not len(values) else float(values.var(ddof=0)),
valid_comparisons=int(len(values)), undefined_comparisons=int(len(rows) - len(values)))
return result
def _view(mode, records, positions):
arrays = {(odor, seed): records[(mode, odor, seed)]['counts'][positions]
for odor in ODORS for seed in SEEDS}
within, between, pairs = [], [], []
for odor in ODORS:
for first_seed, second_seed in itertools.combinations(SEEDS, 2):
within.append(dict(odor_index=odor, seed_a=first_seed, seed_b=second_seed,
**_pair_metrics(arrays[(odor, first_seed)], arrays[(odor, second_seed)])))
for first_odor, second_odor in itertools.combinations(ODORS, 2):
pair_between = []
for seed in SEEDS:
row = dict(odor_index_a=first_odor, odor_index_b=second_odor, seed=seed,
**_pair_metrics(arrays[(first_odor, seed)], arrays[(second_odor, seed)]))
pair_between.append(row)
between.append(row)
# Original pair-specific comparison: 10 within-seed pairs for each
# member odor, not a baseline pooled across all six odors.
pair_within = [row for row in within if row['odor_index'] in (first_odor, second_odor)]
within_summary, between_summary = _summary(pair_within), _summary(pair_between)
differences = {name: None if (within_summary[name]['mean'] is None or
between_summary[name]['mean'] is None) else
float(between_summary[name]['mean'] - within_summary[name]['mean'])
for name in METRICS}
pairs.append(dict(odor_index_a=first_odor, odor_index_b=second_odor,
within_comparison_count=len(pair_within), between_comparison_count=len(pair_between),
within=within_summary, between=between_summary,
mean_between_minus_within=differences,
within_comparisons=pair_within, between_comparisons=pair_between))
_require(len(within) == 60 and len(between) == 75 and len(pairs) == 15 and
all(row['within_comparison_count'] == 20 and row['between_comparison_count'] == 5
for row in pairs), 'Internal fixed comparison inventory changed')
return dict(dimensions=int(len(positions)), applicable=bool(len(positions)),
column_positions=[int(value) for value in positions],
within_comparison_count=len(within), between_comparison_count=len(between), pair_count=len(pairs),
within=_summary(within), between=_summary(between),
within_comparisons=within, between_comparisons=between, pairs=pairs)
def aggregate_structure(records):
"""Describe precisely 60 fixed CAL records, without selecting results.
Each record has exactly mode, odor_index, seed, counts:int32[686] and
design_mask:bool[686]. There are two named modes, six odors (0..5), five
seeds (51101..51105), and no repeat records. Every odor's design mask must
be identical across seeds AND modes. No caller-owned array is modified.
Undefined cosine (zero norm), Pearson (constant vector), or Jaccard (empty
active union) is null with explicit valid/undefined counts. An empty
common-nondesign population is nonapplicable, with every metric null.
"""
_require(isinstance(records, list) and len(records) == 60,
'Exactly 60 base CAL records are required; technical repeats must be excluded')
indexed, masks = {}, {}
for position, record in enumerate(records):
_require(isinstance(record, dict) and set(record) == FIELDS,
'Record schema must contain exactly ' + ', '.join(sorted(FIELDS)))
mode = record['mode']
_require(isinstance(mode, str) and mode in MODES, 'Unexpected CAL mode')
odor = _integer(record['odor_index'], 'odor_index')
seed = _integer(record['seed'], 'seed')
_require(odor in ODORS and seed in SEEDS, 'Odor index or seed outside the fixed CAL inventory')
key = mode, odor, seed
_require(key not in indexed, 'Duplicate CAL identity: ' + str(key))
counts = _array(record['counts'], np.int32, 'counts')
design = _array(record['design_mask'], np.bool_, 'design_mask')
_require(bool(np.all(counts >= 0)), 'Spike counts must be nonnegative')
if odor in masks:
_require(np.array_equal(design, masks[odor]),
'An odor design mask changed across seed or mode: ' + str(odor))
else:
masks[odor] = design.copy()
indexed[key] = dict(counts=counts, design_mask=design)
expected = set(itertools.product(MODES, ODORS, SEEDS))
_require(set(indexed) == expected, 'Incomplete fixed CAL identity set')
union = np.logical_or.reduce([masks[odor] for odor in ODORS])
primary = np.arange(N_ALPN, dtype=np.int32)
common = np.flatnonzero(~union).astype(np.int32)
return dict(schema='phase4ai-alpn-structure-v1', record_count=60, ALPN_dimensions=N_ALPN,
design=dict(identical_across_seeds_and_modes=True,
design_neuron_count_by_odor={str(odor): int(masks[odor].sum()) for odor in ODORS},
design_union_count=int(union.sum()), common_non_design_count=int(len(common)),
common_non_design_column_positions=[int(value) for value in common],
common_non_design_definition='Fixed complement of the union of all six CAL odor design masks; same columns in all modes/seeds'),
modes={mode: dict(trials=30, fixed_686=_view(mode, indexed, primary),
common_non_design=_view(mode, indexed, common)) for mode in MODES},
protocol=dict(odor_indices=list(ODORS), seeds=list(SEEDS), variance_ddof=0,
within='All 10 distinct seed pairs within each of six odors: 60 comparisons per mode',
between='Same-seed pairs for each of 15 odor pairs: 75 comparisons per mode',
pair_baseline='Only each odor pair: 10+10 within comparisons and five same-seed between comparisons',
counts='Original nonnegative int32 spike counts; no normalization, fitting or resampling',
undefined_cosine='null if either vector has zero norm',
undefined_Pearson='null if either vector is constant, including dimension one',
undefined_Jaccard='null if active union is empty',
empty_population='All metrics null, applicable=false; no fabricated zero distance',
clipping='Only cosine/correlation numerical roundoff is clipped to their mathematical [-1,1] range',
technical_repeats_included=False, population_columns='Caller-supplied fixed canonical ALPN order; positions are not neuron_idx'),
decision_gate_applied=False, learning_claimed=False, absence_of_encoding_claimed=False,
limitations=['Descriptive CAL structure only, not a held-out or learning result',
'Shared activity can coexist with odor-specific information',
'Active-set Jaccard can saturate even when spike-count patterns differ',
'Valid metric counts vary when a metric is undefined; null is not zero similarity',
'No KC sparsity gate is transferred to the ALPN population'])
@@ -0,0 +1,242 @@
"""Synthetic CPU-only tests. No real records, files, Torch, GPU, or model runs."""
import json
import sys
import unittest
import numpy as np
from apl_sources import N, GROUPS, DECAY32, GAIN32, decompose_apl_sources
def fixture(events=((0, 1), (1, 4), (2, 10), (4, 20)), steps=6):
I = np.zeros((2, N), np.float32)
I[:, 1] = [1., .3]
I[:, 4] = [.5, 2.]
I[:, 10] = [1.1, .2]
I[:, 20] = [.7, 1.5]
O = np.array([[1., .7, .2, 0.], [.3, .5, 1., 2.]], np.float32)
pairs = np.asarray(events, np.int32).reshape(-1, 2)
tick, node = pairs[:, 0], pairs[:, 1]
# This is merely one legal ordinary f32 reduction implementation for
# exercising the mathematical bound, not a CUDA-equality oracle.
state = np.zeros(2, np.float32)
drive_log, state_log, h_log = [], [], []
for t in range(steps):
drive = I[:, node[tick == t]].sum(axis=1, dtype=np.float32)
state = np.add(np.multiply(DECAY32, state), drive)
h = np.multiply(np.matmul(state, O), GAIN32)
drive_log.append(drive)
state_log.append(state.copy())
h_log.append(h)
return dict(I32=I, O32=O, pn_globals=np.array([1, 4, 6], np.int32),
kc_globals=np.array([10, 20, 30, 40], np.int32), design_pn_globals=np.array([1], np.int32),
event_step=tick, event_node=node, drive32=np.asarray(drive_log),
state32=np.asarray(state_log), h32=np.asarray(h_log),
decay32=DECAY32, gain32=GAIN32, standard_fp32=True)
class AttributionTests(unittest.TestCase):
def test_three_groups_cover_drive_and_pass_prior_bound(self):
f = fixture()
calls = []
out = decompose_apl_sources(**f, callback=lambda t, s: calls.append(s))
summary = out['summary']
self.assertTrue(summary['pass_all'])
self.assertTrue(summary['input_support_partition_exact'])
np.testing.assert_array_equal(out['first_kc_tick'], [2, 4, -1, -1])
self.assertEqual(len(out['tick_rows']), 6 * 3 * 2)
self.assertEqual([summary['groups'][g]['actual_spikes'] for g in GROUPS], [1, 1, 2])
for s in calls:
np.testing.assert_array_equal(s['drive_total'], (s['drive_by_group'][0] + s['drive_by_group'][1]) + s['drive_by_group'][2])
np.testing.assert_array_equal(s['state_total'], (s['state_by_group'][0] + s['state_by_group'][1]) + s['state_by_group'][2])
self.assertFalse(summary['CUDA_float32_bitwise_replay'])
self.assertFalse(summary['independent_brain_oracle'])
self.assertFalse(summary['theoretical_bound']['tolerance_fitted_to_observed_error'])
self.assertFalse(summary['cumulative_source_fraction_error_bounds_verified'])
self.assertFalse(summary['source_majority_robustness_proven'])
json.dumps(summary, allow_nan=False)
json.dumps(out['tick_rows'], allow_nan=False)
def test_early_excludes_same_tick_and_never_fired_columns(self):
f = fixture(events=((0, 1), (2, 10)))
out = decompose_apl_sources(**f)
rows = [r for r in out['tick_rows'] if r['group'] == 'design_ALPN' and r['apl_index'] == 0]
d, q = float(DECAY32), float(GAIN32)
self.assertAlmostEqual(rows[0]['h_before_first_KC_sum_mV'], q * 1.)
self.assertAlmostEqual(rows[1]['h_before_first_KC_sum_mV'], q * d)
self.assertEqual(rows[2]['h_before_first_KC_sum_mV'], 0.)
self.assertGreater(rows[2]['h_never_fired_KC_sum_mV'], 0.)
self.assertGreater(rows[1]['h_before_first_any_KC_sum_mV'], 0.)
self.assertEqual(rows[2]['h_before_first_any_KC_sum_mV'], 0.)
def test_first_kc_at_zero_has_no_early_output(self):
out = decompose_apl_sources(**fixture(events=((0, 1), (0, 10))))
self.assertEqual(out['summary']['first_any_KC_spike_tick'], 0)
self.assertTrue(all(r['h_before_first_any_KC_sum_mV'] == 0 for r in out['tick_rows']))
self.assertTrue(all(r['h_before_first_KC_sum_mV'] == 0 for r in out['tick_rows']))
def test_no_kc_spikes_keep_never_output_separate(self):
out = decompose_apl_sources(**fixture(events=((0, 1),)))
self.assertIsNone(out['summary']['first_any_KC_spike_tick'])
np.testing.assert_array_equal(out['first_kc_tick'], [-1] * 4)
for row in out['tick_rows']:
self.assertEqual(row['h_sum_mV'], row['h_never_fired_KC_sum_mV'])
self.assertEqual(row['h_before_first_KC_sum_mV'], 0.)
self.assertEqual(row['h_before_first_any_KC_sum_mV'], 0.)
def test_zero_input_exact_zeros_and_undefined_fractions(self):
out = decompose_apl_sources(**fixture(events=()))
self.assertTrue(out['summary']['pass_all'])
for group in out['summary']['groups'].values():
self.assertEqual(group['h_sum_mV'], 0.)
self.assertIsNone(group['generated_h_fraction'])
self.assertIsNone(group['drive_fraction'])
def test_source_first_spike_is_not_first_nonzero_drive(self):
out = decompose_apl_sources(**fixture(events=((0, 6), (2, 4), (3, 100))))
group = out['summary']['groups']['non_design_ALPN']
self.assertEqual(group['actual_spikes'], 2)
self.assertEqual(group['input_supported_spikes'], 1)
self.assertEqual(group['first_actual_spike_tick'], 0)
self.assertEqual(group['first_nonzero_drive_tick'], 2)
self.assertEqual(out['summary']['actual_events'], 3)
self.assertTrue(out['summary']['pass_all'])
def test_empty_design_set_reclassifies_pn_not_drops_them(self):
f = fixture()
f['design_pn_globals'] = np.empty(0, np.int32)
out = decompose_apl_sources(**f)
self.assertTrue(out['summary']['pass_all'])
self.assertEqual(out['summary']['groups']['design_ALPN']['actual_spikes'], 0)
self.assertEqual(out['summary']['groups']['non_design_ALPN']['actual_spikes'], 2)
def test_chunk_size_does_not_change_source_accounting(self):
f = fixture()
a = decompose_apl_sources(**f, chunk_size=1)
b = decompose_apl_sources(**f, chunk_size=7)
self.assertTrue(a['summary']['pass_all'] and b['summary']['pass_all'])
self.assertEqual(a['tick_rows'], b['tick_rows'])
self.assertEqual(a['summary']['groups'], b['summary']['groups'])
for name in ('drive', 'state', 'inhibition'):
for key in ('max_abs_error', 'max_error_bound', 'max_bound_utilization', 'bound_violations', 'elements'):
self.assertEqual(a['summary']['comparison'][name][key], b['summary']['comparison'][name][key])
def test_callback_and_core_never_modify_inputs_or_running_state(self):
f = fixture()
inputs = {k: v.copy() for k, v in f.items() if isinstance(v, np.ndarray)}
expected = decompose_apl_sources(**f)
def mutate(t, s):
for value in s.values():
value[:] = 100.
actual = decompose_apl_sources(**f, callback=mutate)
self.assertEqual(actual['summary'], expected['summary'])
self.assertEqual(actual['tick_rows'], expected['tick_rows'])
for name, before in inputs.items():
np.testing.assert_array_equal(np.ascontiguousarray(f[name]).view(np.uint8),
np.ascontiguousarray(before).view(np.uint8))
def test_per_kc_strict_pre_first_and_never_sums(self):
f = fixture(events=((0, 1), (2, 10)))
out = decompose_apl_sources(**f, first_kc_tick=np.array([2, -1, -1, -1], np.int32))
per = out['per_kc']
d, q = float(DECAY32), float(GAIN32)
first_two = q * (1. + d) * (float(f['I32'][0, 1]) * float(f['O32'][0, 0]) +
float(f['I32'][1, 1]) * float(f['O32'][1, 0]))
self.assertAlmostEqual(per['design_ALPN_pre_first_h_sum_mV'][0], first_two)
np.testing.assert_array_equal(per['design_ALPN_pre_first_h_sum_mV'][1:], [0., 0., 0.])
self.assertEqual(per['design_ALPN_never_fired_h_sum_mV'][0], 0.)
np.testing.assert_array_equal(per['design_ALPN_never_fired_h_sum_mV'][1:], per['design_ALPN_h_sum_mV'][1:])
self.assertEqual(per['KC_pre_first_h_sum_mV'][0], 0.)
self.assertTrue(out['summary']['fixture_absent_KC_output_is_not_claimed_applied'])
def test_supplied_first_times_must_match_actual_logs(self):
for first in (np.array([3, 4, -1, -1], np.int32), np.array([2, 4, -1, -1], np.int64)):
with self.subTest(first=first), self.assertRaises(ValueError):
decompose_apl_sources(**fixture(), first_kc_tick=first)
def test_corrupted_positive_trace_violates_unfitted_bound(self):
for field in ('drive32', 'state32', 'h32'):
with self.subTest(field=field):
f = fixture()
f[field][1, 0] += np.float32(100.)
out = decompose_apl_sources(**f)
self.assertFalse(out['summary']['pass_all'])
target = {'drive32': 'drive', 'state32': 'state', 'h32': 'inhibition'}[field]
self.assertGreater(out['summary']['comparison'][target]['bound_violations'], 0)
def test_zero_reference_cannot_accept_nonzero_actual(self):
f = fixture(events=())
f['h32'][0, 0] = np.finfo(np.float32).tiny
out = decompose_apl_sources(**f)
self.assertFalse(out['summary']['pass_all'])
self.assertEqual(out['summary']['comparison']['inhibition']['zero_reference_nonzero_actual'], 1)
def test_subnormal_disables_theoretical_pass(self):
f = fixture(events=())
f['I32'][0, 1] = np.float32(np.finfo(np.float32).tiny / 2)
out = decompose_apl_sources(**f)
self.assertFalse(out['summary']['pass_all'])
self.assertFalse(out['summary']['theoretical_bound']['applicable'])
class ValidationTests(unittest.TestCase):
def test_nonzero_unknown_source_is_rejected(self):
f = fixture()
f['I32'][0, 100] = 1.
with self.assertRaisesRegex(ValueError, 'outside design/non-design'):
decompose_apl_sources(**f)
def test_bad_identity_and_nonpartition_are_rejected(self):
for key, value in [('design_pn_globals', np.array([10], np.int32)),
('design_pn_globals', np.array([1, 1], np.int32)),
('pn_globals', np.array([1, 4, 10], np.int32)),
('kc_globals', np.array([10, 20, 40, 30], np.int32)),
('pn_globals', np.array([1, 4, 6], np.int64))]:
with self.subTest(key=key):
f = fixture()
f[key] = value
with self.assertRaises(ValueError):
decompose_apl_sources(**f)
def test_invalid_events_dtype_order_duplicate_range(self):
changes = [('event_step', np.array([0, 1, 2, 4], np.int64)),
('event_step', np.array([1, 0, 2, 4], np.int32)),
('event_step', np.array([0, 1, 2, 6], np.int32)),
('event_node', np.array([1, 4, 10, N], np.int32))]
for key, value in changes:
with self.subTest(key=key):
f = fixture()
f[key] = value
with self.assertRaises(ValueError):
decompose_apl_sources(**f)
f = fixture(events=((0, 1), (0, 1)))
with self.assertRaises(ValueError):
decompose_apl_sources(**f)
def test_invalid_trace_matrix_precision_constants_or_environment(self):
variants = [dict(standard_fp32=False), dict(standard_fp32=1), dict(chunk_size=0),
dict(decay32=float(DECAY32)), dict(gain32=np.nextafter(GAIN32, np.float32(np.inf))),
dict(callback=3)]
for change in variants:
with self.subTest(change=change), self.assertRaises(ValueError):
decompose_apl_sources(**(fixture() | change))
for name in ('I32', 'O32', 'drive32', 'state32', 'h32'):
for bad in ('dtype', 'negative', 'nonfinite'):
with self.subTest(name=name, bad=bad):
f = fixture()
if bad == 'dtype':
f[name] = f[name].astype(np.float64)
else:
f[name].flat[0] = -1. if bad == 'negative' else np.nan
with self.assertRaises(ValueError):
decompose_apl_sources(**f)
def test_no_dense_source_history_or_scientific_runtime(self):
out = decompose_apl_sources(**fixture())
self.assertEqual(set(out), {'summary', 'tick_rows', 'first_kc_tick', 'per_kc'})
self.assertNotIn('torch', sys.modules)
self.assertNotIn('brian2', sys.modules)
if __name__ == '__main__':
unittest.main(verbosity=2)
@@ -0,0 +1,36 @@
import tempfile
import unittest
from pathlib import Path
import numpy as np
import pyarrow.parquet as pq
from run_audit import first_ticks, temporal_relation, min_observed, EventSink
class HarnessTests(unittest.TestCase):
def test_first_tick_uses_minimum_not_order(self):
self.assertEqual(first_ticks(np.array([4, 2, 3], np.int32), np.array([7, 7, 8], np.int32),
np.array([7, 8, 9], np.int32)).tolist(), [2, 3, -1])
def test_strict_temporal_boundary(self):
self.assertEqual(temporal_relation(17, 18), 'before')
self.assertEqual(temporal_relation(18, 18), 'same_tick')
self.assertEqual(temporal_relation(19, 18), 'after')
self.assertEqual(temporal_relation(-1, 18), 'unobserved_source')
self.assertEqual(temporal_relation(18, -1), 'unobserved_target')
self.assertEqual(temporal_relation(-1, -1), 'both_unobserved')
def test_min_observed(self):
self.assertEqual(min_observed([-1, 0, 3]), 0)
self.assertEqual(min_observed([-1, -1]), -1)
def test_empty_event_sink_has_schema(self):
with tempfile.TemporaryDirectory() as tmp:
path = Path(tmp) / 'events.parquet'
sink = EventSink(path)
sink.close()
self.assertEqual(pq.read_table(path).num_rows, 0)
self.assertIn('source_spike_tick', pq.read_schema(path).names)
if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,152 @@
"""Synthetic CPU-only tests, including the untouched sibling AH callback."""
import importlib.util
from pathlib import Path
import unittest
import numpy as np
from pn_observer import PNObserver
path = Path(__file__).resolve().parent.parent / "kc-drive-audit-v1/replay_core.py"
spec = importlib.util.spec_from_file_location("frozen_ah_observer_test_core", path)
core = importlib.util.module_from_spec(spec)
spec.loader.exec_module(core)
def event(rows=()):
values = np.array(rows, np.int32).reshape(-1, 2)
return {"step": values[:, 0], "neuron_idx": values[:, 1]}
def run(*, edges=(), events=(), requests=(), n=1, design=(), steps=25, coeff=None,
initial_v=None, initial_g=None, sink=None, cap=1000, h=None, hook=None):
targets = np.arange(100, 100 + n, dtype=np.int32)
constants = dict(gd=1., c0=0., cg=1., cv=1., threshold=1., reset=0., seed_volt=2.)
if coeff: constants.update(coeff)
arrays = np.asarray(edges).reshape(-1, 4)
incoming = core.IncomingIndex(arrays[:, 0].astype(np.int32), arrays[:, 1].astype(np.int32),
np.arange(len(arrays), dtype=np.int64) + 81, arrays[:, 2].astype(np.float64), n)
groups = arrays[:, 3].astype(np.int16)
observer = PNObserver(targets, np.array(design, np.int32), incoming, groups, ("ALPN", "other"), constants,
steps, max_first_event_rows=cap, event_sink=sink)
def callback(tick, state):
if hook: hook(tick, state, observer)
observer(tick, state)
result = core.replay(np.zeros(n, np.float64) if initial_v is None else np.array(initial_v, np.float64),
np.zeros(n, np.float64) if initial_g is None else np.array(initial_g, np.float64), constants, steps, targets,
event(requests), event(events), incoming, np.zeros((steps, n), np.float32) if h is None else h, callback)
data, report = observer.finish(result)
return observer, result, data, report
class PNObserverTests(unittest.TestCase):
def test_18_step_arrival_then_19_step_first_spike(self):
observer, result, data, report = run(edges=[(10, 0, 2., 0)], events=[(0, 10)])
self.assertEqual(data["first_spike_tick"].tolist(), [19])
self.assertEqual(len(observer.first_arrival_records), 1)
row = observer.first_arrival_records[0]
self.assertEqual((row["source_spike_tick"], row["arrival_tick"]), (0, 18))
self.assertEqual(row["v_prethreshold_SI"], 0.)
self.assertEqual(row["threshold_margin_SI"], 1.)
self.assertEqual(data["first_integrated_V_from_ALPN/positive_weight"].tolist(), [2.])
self.assertEqual(observer.edge_summary()["target_first_spike_tick"].tolist(), [19])
self.assertTrue(report["pass_all"])
def test_same_tick_first_spike_arrival_is_rejected_not_antecedent(self):
observer, _, data, _ = run(edges=[(10, 0, 2., 0)], events=[(0, 10)], requests=[(18, 100)], design=[100])
self.assertEqual(data["first_spike_tick"].tolist(), [18])
self.assertEqual(observer.first_arrival_records, [])
self.assertEqual(data["ALPN_rejected_positive_edges"].tolist(), [1])
self.assertEqual(data["ALPN_accepted_positive_before_first_edges"].tolist(), [0])
self.assertEqual(data["first_prethreshold_V_from_request_or_reset"].tolist(), [2.])
def test_all_positive_and_inhibitory_events_are_retained(self):
observer, _, data, _ = run(edges=[(10, 0, 2., 0), (11, 0, -.5, 1), (12, 0, 0., 1)],
events=[(0, 10), (0, 11), (0, 12)])
self.assertEqual([r["weight_sign"] for r in observer.first_arrival_records], [1, -1])
self.assertEqual(data["first_spike_tick"].tolist(), [19])
self.assertEqual(data["other_accepted_zero_edges"].tolist(), [1])
self.assertEqual(data["other_accepted_negative_before_first_abs_V"].tolist(), [.5])
self.assertEqual(data["first_integrated_V_from_other/negative_weight"].tolist(), [-.5])
def test_never_active_targets_retain_all_prefirst_records(self):
observer, _, data, report = run(edges=[(10, 0, .25, 0)], events=[(0, 10), (1, 10)],
coeff={"cg": 0.})
self.assertEqual(data["first_spike_tick"].tolist(), [-1])
self.assertTrue(np.isnan(data["first_v_threshold_SI"][0]))
self.assertEqual(observer.edge_summary()["accepted_event_count"].tolist(), [2])
self.assertEqual(observer.edge_summary()["target_first_spike_tick"].tolist(), [-1])
self.assertEqual(report["first_arrival_record_count"], 2)
def test_multiple_targets_independent_first_times_and_design(self):
observer, _, data, _ = run(n=2, edges=[(10, 0, 2., 0), (10, 1, .25, 0)],
events=[(0, 10)], requests=[(23, 101)], design=[101])
self.assertEqual(data["first_spike_tick"].tolist(), [19, 23])
self.assertEqual([r["target_is_design"] for r in observer.first_arrival_records], [False, True])
self.assertEqual(data["first_spike_coincident_with_accepted_request"].tolist(), [False, True])
def test_old_g_not_decayed_g_used_for_first_voltage(self):
_, _, data, _ = run(edges=[(10, 0, 4., 0)], events=[(0, 10)],
coeff={"gd": .1, "cg": .5, "cv": 0.})
self.assertEqual(data["first_integrated_V_from_ALPN/positive_weight"].tolist(), [2.])
self.assertEqual(data["first_spike_tick"].tolist(), [19])
def test_initial_state_is_not_assigned_to_source_class(self):
_, _, data, _ = run(initial_g=[2.])
self.assertEqual(data["first_spike_tick"].tolist(), [0])
self.assertEqual(data["first_integrated_V_from_initial_and_affine_baseline"].tolist(), [2.])
self.assertEqual(data["first_integrated_V_from_ALPN/positive_weight"].tolist(), [0.])
def test_streaming_sink_and_row_budget_fail_closed(self):
received = []
observer, _, _, report = run(edges=[(10, 0, .2, 0)], events=[(0, 10)],
sink=lambda rows: received.extend(rows))
self.assertEqual(observer.first_arrival_records, [])
self.assertEqual(len(received), report["first_arrival_record_count"])
with self.assertRaisesRegex(ValueError, "resource limit"):
run(edges=[(10, 0, .2, 0), (11, 0, .2, 1)], events=[(0, 10), (0, 11)], cap=1)
def test_nonzero_PN_APL_and_non_design_request_are_rejected(self):
h = np.zeros((25, 1), np.float32); h[0, 0] = 1
with self.assertRaisesRegex(ValueError, "zero graded APL"):
run(h=h)
with self.assertRaisesRegex(ValueError, "outside frozen odor design"):
run(requests=[(0, 100)])
def test_callback_arrays_not_modified(self):
snapshots = []
def hook(tick, state, observer):
if tick == 0:
before = {key: value.copy() for key, value in state.items() if isinstance(value, np.ndarray)}
observer(tick, state)
for key, value in before.items():
self.assertEqual(state[key].tobytes(), value.tobytes())
snapshots.append(True)
# Already consumed this tick; stop this synthetic test directly.
raise RuntimeError("checked immutability")
with self.assertRaisesRegex(RuntimeError, "checked immutability"):
run(hook=hook)
self.assertEqual(snapshots, [True])
def test_bad_queue_guard_and_tick_fail_closed(self):
def wrong_guard(tick, state, observer):
if tick == 18: state["arrival_accepted"][:] = False
with self.assertRaisesRegex(ValueError, "Arrival guard"):
run(edges=[(10, 0, 2., 0)], events=[(0, 10)], hook=wrong_guard)
def wrong_tick(tick, state, observer):
observer(tick + 1, state)
with self.assertRaisesRegex(ValueError, "out-of-order"):
run(hook=wrong_tick)
def test_sequential_arrival_roundoff_has_own_lane(self):
_, _, data, report = run(edges=[(10, 0, 1e16, 0), (11, 0, 1., 0), (12, 0, -1e16, 1)],
events=[(0, 10), (0, 11), (0, 12)], coeff={"cg": 0.})
if np.finfo(np.longdouble).nmant > np.finfo(np.float64).nmant:
self.assertEqual(data["arrival_roundoff_g_SI"].tolist(), [-1.])
self.assertTrue(report["voltage_decomposition"]["roundoff_lane_explicit"])
self.assertFalse(report["unique_cause_claim"])
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,205 @@
"""Only temporary synthetic seals are used; production publication is never run."""
import hashlib
import json
from pathlib import Path
import tempfile
import unittest
from unittest import mock
import publication
def _sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def _write(path, value):
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps(value), encoding='utf-8')
def _seal(root):
rows = [dict(path=path.relative_to(root).as_posix(), bytes=path.stat().st_size, sha256=_sha(path))
for path in sorted(root.rglob('*')) if path.is_file() and
path.name not in ('manifest.json', 'checksums.sha256') and '__pycache__' not in path.parts]
_write(root / 'manifest.json', dict(root=str(root), files=rows))
lines = [row['sha256'] + ' ' + row['path'] for row in rows]
lines.append(_sha(root / 'manifest.json') + ' manifest.json')
(root / 'checksums.sha256').write_text('\n'.join(lines) + '\n', encoding='utf-8')
class PublicationTests(unittest.TestCase):
def setUp(self):
self.temporary = tempfile.TemporaryDirectory(prefix='phase4ai-publication-unit-')
self.addCleanup(self.temporary.cleanup)
self.root = Path(self.temporary.name).resolve()
self.model = self.root / publication.MODEL_RELATIVE
self.experiment = self.root / publication.EXPERIMENT_RELATIVE
self.registry = self.root / publication.REGISTRY_RELATIVE
self.model.mkdir(parents=True)
self.experiment.mkdir(parents=True)
(self.model / 'module.py').write_text('# synthetic\n', encoding='utf-8')
status = dict(status=publication.FINAL_STATUS, pass_all=True, candidate_generated=False,
learning_achieved=False, new_brain_simulation=False, GPU_used=False)
_write(self.experiment / 'audit/final-status.json', status)
_write(self.experiment / 'trials/example/summary.json', dict(synthetic=True))
_write(self.experiment / 'trials/example/apl-summary.json', dict(synthetic=True))
(self.experiment / 'REPORT.md').write_text('Synthetic evidence.\n', encoding='utf-8')
(self.experiment / 'unit-tests.log').write_text('Synthetic tests passed.\n', encoding='utf-8')
(self.experiment / 'counts.npy').write_bytes(b'not-a-real-array')
_seal(self.model)
_seal(self.experiment)
def test_all_payload_and_checksum_self_hash_are_verified(self):
result = publication.verify_seal(self.experiment)
self.assertTrue(result['pass_all'])
self.assertEqual(result['payload_file_count'], 6)
self.assertEqual(result['manifest_sha256'], _sha(self.experiment / 'manifest.json'))
def test_publication_only_copies_small_evidence_and_leaves_sources_unchanged(self):
before = {str(path): _sha(path) for base in (self.model, self.experiment)
for path in base.rglob('*') if path.is_file()}
outcome = publication.publish(self.root)
self.assertTrue(outcome['publication_complete'])
self.assertFalse(outcome['scientific_gate_executed_by_publisher'])
self.assertTrue((self.registry / 'evidence/trials/example/apl-summary.json').is_file())
self.assertTrue((self.registry / 'evidence/unit-tests.log').is_file())
self.assertFalse((self.registry / 'evidence/counts.npy').exists())
self.assertFalse((self.registry / 'model/module.py').exists())
self.assertTrue((self.registry / 'model/manifest.json').is_file())
receipt = json.loads((self.registry / 'publication-receipt.json').read_text())
self.assertFalse(receipt['complete_bulk_backup'])
self.assertFalse(receipt['scientific_gate_certified_by_publication'])
for row in receipt['files']:
path = self.registry / row['path']
self.assertEqual(path.stat().st_size, row['bytes'])
self.assertEqual(_sha(path), row['sha256'])
for name, checksum in before.items():
self.assertEqual(_sha(Path(name)), checksum)
def test_existing_registry_is_never_overwritten_or_resumed(self):
self.registry.mkdir(parents=True)
sentinel = self.registry / 'keep.txt'
sentinel.write_text('keep', encoding='utf-8')
with self.assertRaisesRegex(ValueError, 'Registry already exists'):
publication.publish(self.root)
self.assertEqual(sentinel.read_text(), 'keep')
self.assertEqual(list(self.registry.iterdir()), [sentinel])
def test_bulk_payload_corruption_blocks_before_registry_creation(self):
(self.experiment / 'counts.npy').write_bytes(b'corrupt')
with self.assertRaisesRegex(ValueError, 'Payload byte count mismatch'):
publication.publish(self.root)
self.assertFalse(self.registry.exists())
def test_same_size_payload_hash_corruption_is_detected(self):
path = self.experiment / 'counts.npy'
path.write_bytes(b'x' * path.stat().st_size)
with self.assertRaisesRegex(ValueError, 'Payload SHA-256 mismatch'):
publication.verify_seal(self.experiment)
def test_missing_payload_or_unlisted_file_is_detected(self):
(self.experiment / 'extra.txt').write_text('unlisted', encoding='utf-8')
with self.assertRaisesRegex(ValueError, 'unlisted/missing'):
publication.verify_seal(self.experiment)
def test_wrong_manifest_self_checksum_is_detected(self):
path = self.experiment / 'checksums.sha256'
lines = path.read_text().splitlines()
lines[-1] = '0' * 64 + ' manifest.json'
path.write_text('\n'.join(lines) + '\n')
with self.assertRaisesRegex(ValueError, 'manifest self-checksum'):
publication.verify_seal(self.experiment)
def test_duplicate_checksum_path_is_detected(self):
path = self.experiment / 'checksums.sha256'
text = path.read_text()
path.write_text(text + text.splitlines()[0] + '\n')
with self.assertRaisesRegex(ValueError, 'Duplicate checksum'):
publication.verify_seal(self.experiment)
def test_manifest_root_mismatch_is_detected(self):
path = self.experiment / 'manifest.json'
value = json.loads(path.read_text())
value['root'] = str(self.model)
_write(path, value)
with self.assertRaisesRegex(ValueError, 'another root'):
publication.verify_seal(self.experiment)
def test_manifest_duplicate_path_and_traversal_are_rejected(self):
manifest = self.experiment / 'manifest.json'
original = json.loads(manifest.read_text())
for bad_path in ('../escape.txt', '/absolute', 'a/../escape', 'a\\escape', 'C:/escape'):
with self.subTest(path=bad_path):
value = json.loads(json.dumps(original))
value['files'][0]['path'] = bad_path
_write(manifest, value)
with self.assertRaises(ValueError):
publication.verify_seal(self.experiment)
original['files'].append(original['files'][0].copy())
_write(manifest, original)
with self.assertRaisesRegex(ValueError, 'Duplicate manifest path'):
publication.verify_seal(self.experiment)
def test_explicitly_excluded_pycache_is_not_published(self):
cache = self.experiment / '__pycache__/unused.pyc'
cache.parent.mkdir()
cache.write_bytes(b'cache')
self.assertEqual(publication.verify_seal(self.experiment)['excluded_pycache_files'], 1)
publication.publish(self.root)
self.assertFalse((self.registry / 'evidence/__pycache__').exists())
def test_file_size_limit_skips_large_json_without_omitting_verification(self):
huge = self.experiment / 'huge.json'
huge.write_bytes(b' ' * (publication.MAX_EVIDENCE_BYTES + 1))
_seal(self.experiment)
publication.publish(self.root)
self.assertFalse((self.registry / 'evidence/huge.json').exists())
receipt = json.loads((self.registry / 'publication-receipt.json').read_text())
omitted = {row['path']: row for row in receipt['experiment_payload_not_copied']}
self.assertEqual(omitted['huge.json']['reason'], 'exceeds_4_MiB')
def test_unexpected_final_status_or_scope_flag_blocks_publication(self):
path = self.experiment / 'audit/final-status.json'
original = json.loads(path.read_text())
for field, value in [('status', 'OTHER-PASS'), ('pass_all', False), ('learning_achieved', True),
('GPU_used', True), ('new_brain_simulation', True), ('candidate_generated', True)]:
with self.subTest(field=field):
bad = dict(original)
bad[field] = value
_write(path, bad)
_seal(self.experiment)
with self.assertRaises(ValueError):
publication.publish(self.root)
self.assertFalse(self.registry.exists())
def test_copy_failure_is_retained_without_success_receipt(self):
with mock.patch.object(publication, '_copy_verified', side_effect=OSError('synthetic interruption')):
with self.assertRaisesRegex(OSError, 'synthetic interruption'):
publication.publish(self.root)
self.assertTrue(self.registry.is_dir())
self.assertTrue((self.registry / 'publication-failure.json').is_file())
self.assertFalse((self.registry / 'publication-receipt.json').exists())
with self.assertRaisesRegex(ValueError, 'Registry already exists'):
publication.publish(self.root)
def test_source_change_during_copy_prevents_success(self):
original = publication._copy_verified
changed = False
def copy_then_modify(source, target, byte_count, checksum):
nonlocal changed
original(source, target, byte_count, checksum)
if not changed:
changed = True
(self.experiment / 'counts.npy').write_bytes(b'deliberately-changed-after-initial-verification')
with mock.patch.object(publication, '_copy_verified', side_effect=copy_then_modify):
with self.assertRaisesRegex(ValueError, 'Payload byte count mismatch'):
publication.publish(self.root)
self.assertFalse((self.registry / 'publication-receipt.json').exists())
self.assertTrue((self.registry / 'publication-failure.json').exists())
if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,204 @@
"""Synthetic tests only; no saved scientific results are accessed."""
import copy
import json
import unittest
import numpy as np
from structure_metrics import aggregate_structure, MODES, SEEDS, METRICS
def records():
rows = []
for mode in MODES:
for odor in range(6):
design = np.zeros(686, bool)
design[odor] = True
for seed in SEEDS:
count = np.zeros(686, np.int32)
count[odor] = 10
count[10] = seed - SEEDS[0]
count[11] = odor
rows.append(dict(mode=mode, odor_index=odor, seed=seed,
counts=count, design_mask=design.copy()))
return rows
class StructureMetricsTests(unittest.TestCase):
def test_fixed_complete_inventory_and_pair_specific_baseline(self):
result = aggregate_structure(records())
self.assertEqual(result['record_count'], 60)
self.assertEqual(result['design']['design_union_count'], 6)
self.assertEqual(result['design']['common_non_design_count'], 680)
self.assertEqual(result['design']['common_non_design_column_positions'], list(range(6, 686)))
for mode in MODES:
self.assertEqual(result['modes'][mode]['trials'], 30)
for view_name in ('fixed_686', 'common_non_design'):
view = result['modes'][mode][view_name]
self.assertEqual(len(view['within_comparisons']), 60)
self.assertEqual(len(view['between_comparisons']), 75)
self.assertEqual(len(view['pairs']), 15)
for pair in view['pairs']:
self.assertEqual(len(pair['within_comparisons']), 20)
self.assertEqual(len(pair['between_comparisons']), 5)
self.assertEqual({row['odor_index'] for row in pair['within_comparisons']},
{pair['odor_index_a'], pair['odor_index_b']})
self.assertEqual([row['seed'] for row in pair['between_comparisons']], list(SEEDS))
json.dumps(result, allow_nan=False)
def test_primary_retains_design_columns_and_common_view_is_fixed(self):
result = aggregate_structure(records())['modes'][MODES[0]]
pair = result['fixed_686']['pairs'][0]
common_pair = result['common_non_design']['pairs'][0]
# Odors zero and one differ by two ten-count design axes plus one
# shared-coordinate count; same-seed variability cancels between.
self.assertEqual(pair['between']['euclidean_distance']['mean'], np.sqrt(201.))
self.assertEqual(common_pair['between']['euclidean_distance']['mean'], 1.)
self.assertEqual(pair['within']['euclidean_distance']['mean'], 2.)
self.assertEqual(common_pair['within']['euclidean_distance']['mean'], 2.)
def test_input_order_does_not_change_result(self):
rows = records()
expected = aggregate_structure(rows)
actual = aggregate_structure(list(reversed(rows)))
self.assertEqual(expected, actual)
def test_inputs_unchanged_and_readonly_arrays_accepted(self):
rows = records()
before = copy.deepcopy(rows)
for row in rows:
row['counts'].setflags(write=False)
row['design_mask'].setflags(write=False)
aggregate_structure(rows)
for old, new in zip(before, rows):
np.testing.assert_array_equal(old['counts'], new['counts'])
np.testing.assert_array_equal(old['design_mask'], new['design_mask'])
self.assertFalse(new['counts'].flags.writeable)
def test_zero_vectors_do_not_become_similarity_evidence(self):
rows = records()
for row in rows:
row['counts'].fill(0)
result = aggregate_structure(rows)
for mode in MODES:
for name in ('fixed_686', 'common_non_design'):
view = result['modes'][mode][name]
for metric in ('cosine_distance', 'pearson_correlation', 'jaccard'):
self.assertIsNone(view['within'][metric]['mean'])
self.assertEqual(view['within'][metric]['valid_comparisons'], 0)
self.assertEqual(view['between'][metric]['undefined_comparisons'], 75)
self.assertEqual(view['between']['euclidean_distance']['mean'], 0.)
json.dumps(result, allow_nan=False)
def test_constant_nonzero_vectors_have_undefined_pearson(self):
rows = records()
for row in rows:
row['counts'].fill(1)
view = aggregate_structure(rows)['modes'][MODES[0]]['fixed_686']
self.assertIsNone(view['within']['pearson_correlation']['mean'])
self.assertEqual(view['within']['jaccard']['mean'], 1.)
self.assertAlmostEqual(view['within']['cosine_distance']['mean'], 0., places=14)
def test_empty_common_population_is_nonapplicable(self):
rows = records()
for row in rows:
row['design_mask'].fill(True)
result = aggregate_structure(rows)
self.assertEqual(result['design']['common_non_design_count'], 0)
for mode in MODES:
view = result['modes'][mode]['common_non_design']
self.assertFalse(view['applicable'])
self.assertEqual(view['dimensions'], 0)
for metric in METRICS:
self.assertIsNone(view['between'][metric]['mean'])
self.assertEqual(view['within'][metric]['undefined_comparisons'], 60)
def test_int32_extrema_are_promoted_before_subtraction_and_norm(self):
rows = records()
maximum = np.iinfo(np.int32).max
for row in rows:
row['counts'].fill(0)
row['counts'][row['odor_index']] = maximum
result = aggregate_structure(rows)['modes'][MODES[0]]['fixed_686']
distance = result['pairs'][0]['between']['euclidean_distance']['mean']
self.assertAlmostEqual(distance / float(maximum), np.sqrt(2.))
self.assertEqual(result['between']['cosine_distance']['mean'], 1.)
json.dumps(result, allow_nan=False)
def test_missing_record_or_extra_repeat_rejected(self):
rows = records()
for bad in (rows[:-1], rows + [copy.deepcopy(rows[0])]):
with self.assertRaisesRegex(ValueError, 'Exactly 60'):
aggregate_structure(bad)
def test_duplicate_identity_rejected_even_with_sixty_rows(self):
rows = records()
rows[-1] = copy.deepcopy(rows[0])
with self.assertRaisesRegex(ValueError, 'Duplicate CAL identity'):
aggregate_structure(rows)
def test_mask_change_across_seed_rejected(self):
rows = records()
rows[1]['design_mask'][100] = True
with self.assertRaisesRegex(ValueError, 'mask changed across seed or mode'):
aggregate_structure(rows)
def test_mask_change_across_mode_rejected(self):
rows = records()
for row in rows:
if row['mode'] == MODES[1] and row['odor_index'] == 0:
row['design_mask'][100] = True
with self.assertRaisesRegex(ValueError, 'mask changed across seed or mode'):
aggregate_structure(rows)
def test_negative_counts_and_incorrect_dtype_or_shape_rejected(self):
changes = [('negative', lambda row: row['counts'].__setitem__(0, -1)),
('counts64', lambda row: row.update(counts=row['counts'].astype(np.int64))),
('counts_float', lambda row: row.update(counts=row['counts'].astype(np.float64))),
('shape', lambda row: row.update(counts=np.zeros(685, np.int32))),
('mask_dtype', lambda row: row.update(design_mask=row['design_mask'].astype(np.uint8))),
('mask_shape', lambda row: row.update(design_mask=np.zeros(685, bool)))]
for label, change in changes:
with self.subTest(label=label):
rows = records()
change(rows[0])
with self.assertRaises(ValueError):
aggregate_structure(rows)
def test_strict_record_schema_and_id_ranges(self):
changes = [lambda row: row.update(extra=1), lambda row: row.pop('counts'),
lambda row: row.update(mode='new_mode'), lambda row: row.update(odor_index=6),
lambda row: row.update(odor_index=True), lambda row: row.update(seed=51106),
lambda row: row.update(seed=float(SEEDS[0]))]
for change in changes:
rows = records()
change(rows[0])
with self.assertRaises(ValueError):
aggregate_structure(rows)
def test_partial_undefined_metrics_report_counts_without_imputation(self):
rows = records()
# One zero-count record per mode. Four of the 60 within comparisons
# and five of the 75 between comparisons then have undefined cosine.
for row in rows:
if row['odor_index'] == 0 and row['seed'] == SEEDS[0]:
row['counts'].fill(0)
view = aggregate_structure(rows)['modes'][MODES[0]]['fixed_686']
self.assertEqual(view['within']['cosine_distance']['undefined_comparisons'], 4)
self.assertEqual(view['between']['cosine_distance']['undefined_comparisons'], 5)
self.assertEqual(view['within']['cosine_distance']['valid_comparisons'], 56)
self.assertEqual(view['between']['cosine_distance']['valid_comparisons'], 70)
def test_one_common_channel_pearson_is_undefined(self):
rows = records()
for row in rows:
row['design_mask'][:685] = True
row['counts'][685] = row['odor_index'] + 1
view = aggregate_structure(rows)['modes'][MODES[0]]['common_non_design']
self.assertEqual(view['dimensions'], 1)
self.assertIsNone(view['between']['pearson_correlation']['mean'])
self.assertEqual(view['between']['cosine_distance']['mean'], 0.)
if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,134 @@
"""Pure synthetic checks for stateless pre-first event validation."""
import unittest
import numpy as np
from validate_events import COLUMN_DTYPES, N_GLOBAL, validate_batch
def fixture():
reference = dict(edge_ids=np.array([7, 20, 99], np.int64),
srcglobals=np.array([3, 4, 3], np.int32), dstglobals=np.array([10, 10, 20], np.int32),
weights=np.array([.001, -.002, .003], np.float64),
target_globals=np.array([10, 20, 30], np.int32), target_first=np.array([30, -1, 0], np.int32),
source_event_keys=np.array([3, 4, 4 * N_GLOBAL + 3], np.int64))
# Arbitrary order, repeated edge at a later tick, negative and positive.
values = dict(edge_id=[99, 20, 7, 99], source_neuron_idx=[3, 4, 3, 3],
target_neuron_idx=[20, 10, 10, 20], source_spike_tick=[4, 0, 0, 0],
arrival_tick=[22, 18, 18, 18], weight_sign=[1, -1, 1, 1],
ref_at_arrival=[0] * 4, weight_SI=[.003, -.002, .001, .003], accepted=[True] * 4)
columns = {name: np.array(values[name], dtype) for name, dtype in COLUMN_DTYPES.items()}
return columns, reference
class EventValidationTests(unittest.TestCase):
def test_unordered_rows_real_edges_signed_weights_and_never_first(self):
columns, ref = fixture()
original = {k: v.copy() for k, v in columns.items()}
result = validate_batch(columns, **ref)
self.assertEqual(result['count'], 4)
np.testing.assert_array_equal(result['per_target_count'], [2, 2, 0])
self.assertEqual(result['per_target_count'].dtype, np.int64)
self.assertFalse(result['unique_cause_claim'])
self.assertFalse(result['cross_batch_completeness_checked'])
for key in columns:
np.testing.assert_array_equal(columns[key], original[key])
def test_empty_valid_but_missing_wrong_dtype_or_shape_still_rejected(self):
columns, ref = fixture()
empty = {name: value[:0] for name, value in columns.items()}
result = validate_batch(empty, **ref)
self.assertEqual(result['count'], 0)
np.testing.assert_array_equal(result['per_target_count'], [0, 0, 0])
bad = empty.copy()
bad['arrival_tick'] = np.empty(0, np.int64)
with self.assertRaises(ValueError):
validate_batch(bad, **ref)
bad = empty.copy()
del bad['accepted']
with self.assertRaises(ValueError):
validate_batch(bad, **ref)
bad = empty.copy()
bad['weight_sign'] = np.empty((0, 1), np.int32)
with self.assertRaises(ValueError):
validate_batch(bad, **ref)
def test_every_edge_field_and_weight_bit_is_checked(self):
for field, value in [('edge_id', 8), ('source_neuron_idx', 4), ('target_neuron_idx', 10),
('weight_sign', -1), ('weight_SI', np.nextafter(.003, np.inf))]:
with self.subTest(field=field):
columns, ref = fixture()
columns[field][0] = value
with self.assertRaises(ValueError):
validate_batch(columns, **ref)
columns, ref = fixture()
ref['weights'][2] = 0.
columns['weight_SI'][[0, 3]] = -0.
with self.assertRaisesRegex(ValueError, 'bits mismatch'):
validate_batch(columns, **ref)
columns['weight_SI'][[0, 3]] = 0.
with self.assertRaisesRegex(ValueError, 'zero-weight'):
validate_batch(columns, **ref)
def test_guard_strict_prefirst_and_source_delay(self):
changes = [('accepted', False), ('ref_at_arrival', 1), ('source_spike_tick', -1),
('source_spike_tick', 3), ('arrival_tick', 21)]
for field, value in changes:
with self.subTest(field=field):
columns, ref = fixture()
columns[field][0] = value
with self.assertRaises(ValueError):
validate_batch(columns, **ref)
for first in (22, 21):
columns, ref = fixture()
ref['target_first'][1] = first
with self.assertRaisesRegex(ValueError, 'strictly before'):
validate_batch(columns, **ref)
def test_source_event_membership_and_target_population(self):
columns, ref = fixture()
ref['source_event_keys'] = ref['source_event_keys'][:2]
with self.assertRaisesRegex(ValueError, 'source spike'):
validate_batch(columns, **ref)
columns, ref = fixture()
ref['target_globals'] = np.array([10, 30], np.int32)
ref['target_first'] = np.array([30, 0], np.int32)
with self.assertRaisesRegex(ValueError, 'target global'):
validate_batch(columns, **ref)
def test_duplicate_rows_rejected_without_sort_assumption(self):
columns, ref = fixture()
for value in columns.values():
value[0] = value[3]
with self.assertRaisesRegex(ValueError, 'Duplicate edge event'):
validate_batch(columns, **ref)
def test_invalid_reference_schema_order_duplicate_range_nonfinite(self):
variants = [dict(edge_ids=np.array([7, 20, 99], np.int32)),
dict(edge_ids=np.array([7, 99, 20], np.int64)),
dict(edge_ids=np.array([7, 20, 20], np.int64)),
dict(srcglobals=np.array([3, 4, N_GLOBAL], np.int32)),
dict(weights=np.array([.001, -.002, np.inf])),
dict(target_first=np.array([30, -2, 0], np.int32)),
dict(source_event_keys=np.array([3, 3, 4], np.int64)),
dict(source_event_keys=np.array([4, 3], np.int64)),
dict(source_event_keys=np.array([-1, 3], np.int64))]
for change in variants:
with self.subTest(change=change):
columns, ref = fixture()
with self.assertRaises(ValueError):
validate_batch(columns, **(ref | change))
def test_optional_design_and_local_row_fields_are_not_assumed(self):
columns, ref = fixture()
columns['incoming_edge_row'] = np.array([1000, 2, 1, 1000], np.int64)
columns['target_is_design'] = np.array([True, False, True, False])
self.assertEqual(validate_batch(columns, **ref)['count'], 4)
bad = columns.copy()
bad['accepted'] = columns['accepted'].astype(np.uint8)
with self.assertRaises(ValueError):
validate_batch(bad, **ref)
if __name__ == '__main__':
unittest.main(verbosity=2)
@@ -0,0 +1,123 @@
"""Stateless independent checks for accepted pre-first anatomical event rows.
Pure NumPy: no files or brain execution. Passing establishes row consistency
with the supplied graph and recorded source events, not necessity/unique cause.
The caller owns provenance, design labels, trial bounds, cross-batch duplicate
detection, expected totals, and completeness of the full record collection.
"""
from collections.abc import Mapping
import numpy as np
N_GLOBAL = 166700
DELAY_STEPS = 18
COLUMN_DTYPES = {
'edge_id': np.int64,
'source_neuron_idx': np.int32,
'target_neuron_idx': np.int32,
'source_spike_tick': np.int32,
'arrival_tick': np.int32,
'weight_sign': np.int32,
'ref_at_arrival': np.int32,
'weight_SI': np.float64,
'accepted': np.bool_,
}
def _require(condition, message):
if not condition:
raise ValueError(message)
def _vector(value, dtype, name, length=None):
_require(isinstance(value, np.ndarray), name + ' must be a NumPy array')
_require(value.dtype == np.dtype(dtype) and value.ndim == 1, name + ' has the wrong dtype/shape')
_require(length is None or len(value) == length, name + ' has the wrong length')
return value
def _globals(value, name, length=None, sorted_unique=False):
value = _vector(value, np.int32, name, length)
_require(np.all((value >= 0) & (value < N_GLOBAL)), name + ' contains an out-of-range global ID')
if sorted_unique:
_require(np.all(value[1:] > value[:-1]), name + ' must be sorted and unique')
return value
def _lookup(sorted_reference, wanted, name):
positions = np.searchsorted(sorted_reference, wanted)
_require(np.all(positions < len(sorted_reference)), name + ' is absent from the reference')
_require(np.array_equal(sorted_reference[positions], wanted), name + ' is absent from the reference')
return positions
def validate_batch(columns, *, edge_ids, srcglobals, dstglobals, weights,
target_globals, target_first, source_event_keys):
"""Validate arbitrary-order rows; return count and target-indexed int64 counts.
Required columns and exact dtypes are COLUMN_DTYPES. Additional columns are
intentionally not interpreted: in particular incoming_edge_row has a
caller-specific coordinate system, and design/source labels are separate.
References: sorted unique nonnegative edge_ids:int64[E]; source/destination
globals:int32[E]; finite effective SI weights:float64[E]; sorted unique
target_globals:int32[K]; target_first:int32[K] (-1 means never fired);
source_event_keys:int64 sorted unique, encoding tick*166700+global ID.
Every row must reference a real nonzero edge, its exact weight bits/sign,
accepted=True/ref_at_arrival=0, a recorded source event exactly 18 ticks
earlier, and arrival strictly before the target's first spike, if any.
Duplicate (arrival_tick,edge_id) rows within this batch are rejected without
assuming any input row ordering. Cross-batch duplicates require caller state.
Empty batches still require valid complete schema/references and return zero.
No supplied array is modified or sorted in place.
"""
_require(isinstance(columns, Mapping), 'columns must be a mapping')
_require(set(COLUMN_DTYPES).issubset(columns), 'Missing required event columns')
ids = _vector(edge_ids, np.int64, 'edge_ids')
e = len(ids)
_require(np.all(ids >= 0) and np.all(ids[1:] > ids[:-1]), 'edge_ids must be sorted unique nonnegative IDs')
sources = _globals(srcglobals, 'srcglobals', e)
destinations = _globals(dstglobals, 'dstglobals', e)
weight = _vector(weights, np.float64, 'weights', e)
_require(np.isfinite(weight).all(), 'Nonfinite reference weight')
targets = _globals(target_globals, 'target_globals', sorted_unique=True)
first = _vector(target_first, np.int32, 'target_first', len(targets))
_require(np.all(first >= -1), 'target_first must be -1 or a nonnegative tick')
keys = _vector(source_event_keys, np.int64, 'source_event_keys')
largest_key = int(np.iinfo(np.int32).max) * N_GLOBAL + N_GLOBAL - 1
_require(np.all((keys >= 0) & (keys <= largest_key)) and np.all(keys[1:] > keys[:-1]),
'source_event_keys must be sorted unique valid int32-tick/global encodings')
count = len(_vector(columns['edge_id'], np.int64, 'columns.edge_id'))
data = {name: _vector(columns[name], dtype, 'columns.' + name, count)
for name, dtype in COLUMN_DTYPES.items()}
_require(np.isfinite(data['weight_SI']).all(), 'Nonfinite recorded weight')
_require(np.all(data['accepted']) and np.all(data['ref_at_arrival'] == 0),
'Recorded arrival was not accepted at ref=0')
row_edge = _lookup(ids, data['edge_id'], 'Recorded edge ID')
_require(np.array_equal(data['source_neuron_idx'], sources[row_edge]), 'Recorded edge source mismatch')
_require(np.array_equal(data['target_neuron_idx'], destinations[row_edge]), 'Recorded edge target mismatch')
actual_weight = weight[row_edge]
_require(np.array_equal(np.ascontiguousarray(data['weight_SI']).view(np.uint64),
np.ascontiguousarray(actual_weight).view(np.uint64)), 'Recorded weight bits mismatch')
_require(np.all(actual_weight != 0), 'Pre-first nonzero-event table contains a zero-weight edge')
_require(np.array_equal(data['weight_sign'], np.sign(actual_weight).astype(np.int32)), 'Recorded weight sign mismatch')
local_targets = _lookup(targets, data['target_neuron_idx'], 'Recorded target global')
arrival = data['arrival_tick'].astype(np.int64)
source_tick = data['source_spike_tick'].astype(np.int64)
_require(np.all(source_tick >= 0) and np.array_equal(source_tick, arrival - DELAY_STEPS),
'Source/arrival delay is not exactly 18 nonnegative ticks')
wanted_keys = source_tick * np.int64(N_GLOBAL) + data['source_neuron_idx'].astype(np.int64)
_lookup(keys, wanted_keys, 'Recorded source spike')
target_first_rows = first[local_targets].astype(np.int64)
_require(np.all((target_first_rows == -1) | (arrival < target_first_rows)),
'Arrival is not strictly before the observed first target spike')
if count > 1:
order = np.lexsort((data['edge_id'], arrival))
sorted_arrival, sorted_edge = arrival[order], data['edge_id'][order]
_require(not np.any((sorted_arrival[1:] == sorted_arrival[:-1]) &
(sorted_edge[1:] == sorted_edge[:-1])), 'Duplicate edge event within batch')
per_target = np.bincount(local_targets, minlength=len(targets)).astype(np.int64, copy=False)
_require(int(per_target.sum()) == count, 'Target counts do not cover the batch')
return dict(pass_all=True, count=count, per_target_count=per_target,
unique_cause_claim=False, cross_batch_completeness_checked=False)