Files
2026-09-30 10:45:48 +08:00

284 lines
16 KiB
Python

"""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()