Seal Phase 4AJ fixed APL timing hypothesis audit
This commit is contained in:
@@ -0,0 +1 @@
|
||||
"""Discoverable synthetic tests; no scientific execution during imports."""
|
||||
@@ -0,0 +1,169 @@
|
||||
"""Synthetic array-only comparator tests: no backend or scientific inputs."""
|
||||
from pathlib import Path
|
||||
import copy
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import numpy as np
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
||||
import compare_timing as compare
|
||||
|
||||
|
||||
def traces(delay, steps, width=3):
|
||||
generated = np.arange(steps * width, dtype=np.float32).reshape(steps, width) * np.float32(.125)
|
||||
full = np.concatenate((np.zeros((delay, width), dtype=np.float32), generated))
|
||||
return generated, full[:steps].copy(), full[steps:].copy()
|
||||
|
||||
|
||||
def sequence_result(generated, applied, pending, delay):
|
||||
checks, differences = {}, {}
|
||||
compare._timing_sequence_checks(generated, applied, pending, delay, 'test', checks, differences)
|
||||
return checks, differences
|
||||
|
||||
|
||||
def metadata_run(delay, steps, cpu=False):
|
||||
generated, applied, pending = traces(delay, steps, 4064)
|
||||
state = np.tile(np.array([.25, 1.125], np.float32), (steps, 1))
|
||||
timing = dict(apl_delay_steps=delay, steps=steps, pending_generated_count=min(steps, delay),
|
||||
generated_rows=steps, applied_generated_rows=max(steps-delay, 0), pending_shape=[delay, 4064],
|
||||
pending_initial_zero_prefix=max(delay-steps, 0),
|
||||
pending_application_tick_start=steps, pending_application_tick_stop_exclusive=steps+delay,
|
||||
pending_generated_tick_start=max(steps-delay, 0), pending_generated_tick_stop_exclusive=steps,
|
||||
pending_raw_sha256=compare.raw_hash(pending, '<f4'),
|
||||
final_apl_state_float32=state[-1].tolist(),
|
||||
final_apl_state_u32_bits=state[-1].view(np.uint32).tolist(), final_apl_state_nonzero=True,
|
||||
brain_tail_advanced=False, future_apl_decay_or_feedback_generated=False,
|
||||
finite_generated_sequence_only=True, closed_loop_branch_integrals_claimed_equal=False,
|
||||
biological_delay_measurement_claimed=False, brain_steps_after_window=0,
|
||||
APL_generation_steps_after_window=0, future_generated_decay_tail_included=False)
|
||||
summary = dict(apl_timing=copy.deepcopy(timing), pending_generated_count=min(steps, delay),
|
||||
pending_initial_zero_prefix=max(delay-steps, 0), pending_tail_shape=[delay, 4064],
|
||||
future_generated_decay_tail_included=False, APL_worker_ticks=steps)
|
||||
return dict(apl={'inhibition': generated, 'applied': applied, 'state': state}, pending=pending,
|
||||
timing=timing, summary=summary)
|
||||
|
||||
|
||||
class TimingComparisonTests(unittest.TestCase):
|
||||
def test_delay_zero_and_18_partition(self):
|
||||
for delay in (0, 18):
|
||||
for steps in (1, 7, 18, 19, 54):
|
||||
with self.subTest(delay=delay, steps=steps):
|
||||
checks, differences = sequence_result(*traces(delay, steps), delay)
|
||||
self.assertTrue(all(checks.values()), differences)
|
||||
|
||||
def test_one_tick_shift_rejected_independently(self):
|
||||
generated, applied, pending = traces(18, 40)
|
||||
applied[18:] = generated[1:23]
|
||||
checks, _ = sequence_result(generated, applied, pending, 18)
|
||||
self.assertFalse(checks['test.fixed_delay_applied.bitwise_exact'])
|
||||
|
||||
def test_pending_wrong_chronology_rejected(self):
|
||||
generated, applied, pending = traces(18, 40)
|
||||
checks, _ = sequence_result(generated, applied, pending[::-1].copy(), 18)
|
||||
self.assertFalse(checks['test.fixed_delay_pending.bitwise_exact'])
|
||||
|
||||
def test_initial_zero_must_be_positive_bits(self):
|
||||
generated, applied, pending = traces(18, 4)
|
||||
pending.view(np.uint32)[0, 0] = 0x80000000
|
||||
checks, _ = sequence_result(generated, applied, pending, 18)
|
||||
self.assertFalse(checks['test.fixed_delay_pending.bitwise_exact'])
|
||||
generated, applied, pending = traces(18, 22)
|
||||
applied.view(np.uint32)[0, 0] = 0x80000000
|
||||
checks, _ = sequence_result(generated, applied, pending, 18)
|
||||
self.assertFalse(checks['test.fixed_delay_applied.bitwise_exact'])
|
||||
|
||||
def test_generated_signed_zero_preserved(self):
|
||||
generated, applied, pending = traces(0, 1)
|
||||
generated.view(np.uint32)[0, 0] = 0x80000000
|
||||
applied[:] = generated
|
||||
checks, _ = sequence_result(generated, applied, pending, 0)
|
||||
self.assertTrue(all(checks.values()))
|
||||
applied.view(np.uint32)[0, 0] = 0
|
||||
checks, _ = sequence_result(generated, applied, pending, 0)
|
||||
self.assertFalse(checks['test.fixed_delay_applied.bitwise_exact'])
|
||||
|
||||
def test_schema_and_delay_fail_closed(self):
|
||||
generated, applied, pending = traces(18, 4)
|
||||
for delay in (True, 1, 18.0):
|
||||
with self.assertRaises(ValueError):
|
||||
sequence_result(generated, applied, pending, delay)
|
||||
with self.assertRaises(ValueError):
|
||||
sequence_result(generated.astype(np.float64), applied, pending, 18)
|
||||
with self.assertRaises(ValueError):
|
||||
sequence_result(generated, applied, pending[-4:], 18)
|
||||
|
||||
def test_nonfinite_or_negative_generated_fails_even_if_shift_matches(self):
|
||||
for value in (np.inf, np.nan, -1):
|
||||
generated, applied, pending = traces(0, 2)
|
||||
generated[0, 0] = value
|
||||
applied[:] = generated
|
||||
checks, _ = sequence_result(generated, applied, pending, 0)
|
||||
self.assertFalse(checks['test.timing_finite_nonnegative'])
|
||||
|
||||
def test_both_backend_metadata_valid(self):
|
||||
for role in ('gpu', 'cpu', 'first_gpu', 'second_gpu'):
|
||||
for delay, steps in ((0, 25), (18, 7), (18, 25)):
|
||||
run = metadata_run(delay, steps, cpu=role == 'cpu')
|
||||
checks = {}
|
||||
compare._timing_metadata_checks(run, role, delay, steps, checks)
|
||||
self.assertTrue(all(checks.values()), checks)
|
||||
|
||||
def test_metadata_rejects_wrong_count_tail_advance_and_final_state(self):
|
||||
for role in ('gpu', 'cpu'):
|
||||
for change in ('count', 'tail', 'final', 'prefix', 'hash'):
|
||||
run = metadata_run(18, 25, cpu=role == 'cpu')
|
||||
if change == 'count':
|
||||
run['timing']['pending_generated_count'] = 17
|
||||
elif change == 'tail':
|
||||
run['timing']['brain_steps_after_window' if role == 'cpu' else 'brain_tail_advanced'] = 1
|
||||
elif change == 'final':
|
||||
run['timing']['final_apl_state_u32_bits'][0] += 1
|
||||
elif change == 'prefix':
|
||||
run['timing']['pending_initial_zero_prefix'] = False
|
||||
else:
|
||||
run['timing']['pending_raw_sha256'] = '0' * 64
|
||||
checks = {}
|
||||
compare._timing_metadata_checks(run, role, 18, 25, checks)
|
||||
self.assertFalse(all(checks.values()), (role, change))
|
||||
|
||||
def test_g_write_uses_applied_and_is_unconditional_during_ref(self):
|
||||
nodes, kc = np.array([10, 12], np.int32), np.array([10], np.int32)
|
||||
v = np.full((3, 2), -.06, np.float64)
|
||||
ref = np.array([[22, 0], [21, 0], [20, 0]], np.int32)
|
||||
before = np.array([[0, -.001], [-0., .001], [.002, -.003]], np.float64)
|
||||
applied = np.array([[.25], [0], [1]], np.float32)
|
||||
after = before.copy()
|
||||
after[:, 0] -= applied[:, 0].astype(np.float64) * np.float64(.001)
|
||||
run = dict(pre={'v': v, 'g': before, 'ref': ref}, histories={'v': v.copy(), 'g': after, 'ref': ref.copy()},
|
||||
apl={'applied': applied, 'inhibition': np.full((3, 1), 99, np.float32)})
|
||||
checks, differences = {}, {}
|
||||
compare._check_apl_application(run, 'test', nodes, kc, checks, differences)
|
||||
self.assertTrue(all(checks.values()), differences)
|
||||
run['histories']['g'] = before.copy() # Hypothetical refractory guard must fail.
|
||||
checks, differences = {}, {}
|
||||
compare._check_apl_application(run, 'test', nodes, kc, checks, differences)
|
||||
self.assertFalse(checks['test.apl_unconditional_g_write.bitwise_exact'])
|
||||
|
||||
def test_pair_comparison_includes_applied_and_pending(self):
|
||||
def output():
|
||||
generated, applied, pending = traces(18, 20)
|
||||
return dict(state={'step': np.empty(0, np.int32), 'neuron_idx': np.empty(0, np.int32),
|
||||
'counts': np.zeros(1, np.int32), 'ref': np.zeros(1, np.int32),
|
||||
'v': np.zeros(1, np.float64), 'g': np.zeros(1, np.float64)},
|
||||
apl={'drive': np.zeros((20, 2), np.float32), 'state': np.zeros((20, 2), np.float32),
|
||||
'inhibition': np.pad(generated, ((0, 0), (0, 4061))),
|
||||
'applied': np.pad(applied, ((0, 0), (0, 4061)))},
|
||||
pending=np.pad(pending, ((0, 0), (0, 4061))),
|
||||
hashes=[], queues=[], requests=[], component={}, histories={}, pre={})
|
||||
left, right = output(), output()
|
||||
right['apl']['applied'][0, 0] = 1
|
||||
right['pending'][0, 0] += 1
|
||||
checks, differences = {}, {}
|
||||
compare._pair_outputs(left, right, checks, differences, 1, 20, False)
|
||||
self.assertFalse(checks['apl.applied.bitwise_exact'])
|
||||
self.assertFalse(checks['apl.pending.bitwise_exact'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,129 @@
|
||||
"""Synthetic CPU-only checks; no Torch, data bundle, or scientific trial."""
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import numpy as np
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
||||
from timing_queue import TimingQueue, audit_sequence
|
||||
|
||||
|
||||
class TimingQueueTests(unittest.TestCase):
|
||||
def sequence(self, delay, steps, width=3):
|
||||
generated = np.arange(1, steps * width + 1, dtype=np.float32).reshape(steps, width)
|
||||
queue = TimingQueue(delay, width)
|
||||
applied = np.empty_like(generated)
|
||||
for tick, row in enumerate(generated):
|
||||
applied[tick] = queue.push(row, tick=tick)
|
||||
return queue, generated, applied, queue.pending()
|
||||
|
||||
def test_delay_zero_identity(self):
|
||||
queue, generated, applied, pending = self.sequence(0, 40)
|
||||
self.assertTrue(np.array_equal(generated.view(np.uint32), applied.view(np.uint32)))
|
||||
self.assertEqual(pending.shape, (0, 3))
|
||||
self.assertTrue(audit_sequence(generated, applied, pending, 0)["pass_all"])
|
||||
self.assertEqual(queue.metadata()["pending_generated_count"], 0)
|
||||
|
||||
def test_delay_18_boundary(self):
|
||||
_, generated, applied, pending = self.sequence(18, 39)
|
||||
self.assertTrue(np.all(applied[:18].view(np.uint32) == 0))
|
||||
np.testing.assert_array_equal(applied[18], generated[0])
|
||||
np.testing.assert_array_equal(applied[36], generated[18])
|
||||
np.testing.assert_array_equal(pending, generated[-18:])
|
||||
audit_sequence(generated, applied, pending, 18)
|
||||
|
||||
def test_short_sequence_keeps_initial_pending_slots(self):
|
||||
for steps in (0, 1, 7, 17, 18, 19):
|
||||
with self.subTest(steps=steps):
|
||||
queue, generated, applied, pending = self.sequence(18, steps)
|
||||
meta = audit_sequence(generated, applied, pending, 18)
|
||||
self.assertEqual(pending.shape, (18, 3))
|
||||
self.assertEqual(meta["pending_initial_zero_prefix"], max(18 - steps, 0))
|
||||
self.assertEqual(meta["pending_generated_count"], min(18, steps))
|
||||
self.assertEqual(queue.steps, steps)
|
||||
self.assertTrue(np.all(pending[:max(18 - steps, 0)].view(np.uint32) == 0))
|
||||
|
||||
def test_no_alias_to_input_or_return_or_pending(self):
|
||||
queue = TimingQueue(18, 1)
|
||||
row = np.array([3], dtype=np.float32)
|
||||
first = queue.push(row)
|
||||
row[0] = 9
|
||||
first[0] = 8
|
||||
pending = queue.pending()
|
||||
pending[:] = 12
|
||||
for _ in range(17):
|
||||
queue.push(np.zeros(1, dtype=np.float32))
|
||||
self.assertEqual(queue.push(np.zeros(1, dtype=np.float32))[0], 3)
|
||||
|
||||
def test_zero_delay_return_owned(self):
|
||||
row = np.array([2], dtype=np.float32)
|
||||
value = TimingQueue(0, 1).push(row)
|
||||
value[0] = 99
|
||||
self.assertEqual(row[0], 2)
|
||||
|
||||
def test_signed_zero_subnormal_and_extreme_bits(self):
|
||||
row = np.array([0x80000000, 1, 0x7f7fffff], dtype=np.uint32).view(np.float32)
|
||||
for delay in (0, 18):
|
||||
queue = TimingQueue(delay, 3)
|
||||
generated = np.stack([row.copy() for _ in range(23)])
|
||||
applied = np.stack([queue.push(x) for x in generated])
|
||||
audit_sequence(generated, applied, queue.pending(), delay)
|
||||
|
||||
def test_reject_invalid_configuration(self):
|
||||
for delay in (True, 1, -18, 18.0, np.int32(18)):
|
||||
with self.assertRaises(ValueError):
|
||||
TimingQueue(delay)
|
||||
for width in (0, -1, True, 2.0):
|
||||
with self.assertRaises(ValueError):
|
||||
TimingQueue(18, width)
|
||||
|
||||
def test_reject_invalid_sample_without_advance(self):
|
||||
queue = TimingQueue(18, 2)
|
||||
bad = [np.ones(2, dtype=np.float64), np.ones((1, 2), dtype=np.float32),
|
||||
np.ones(3, dtype=np.float32), [1, 2],
|
||||
np.array([np.nan, 1], dtype=np.float32), np.array([np.inf, 1], dtype=np.float32),
|
||||
np.array([-1, 1], dtype=np.float32)]
|
||||
for row in bad:
|
||||
with self.assertRaises(ValueError):
|
||||
queue.push(row)
|
||||
self.assertEqual(queue.steps, 0)
|
||||
|
||||
def test_tick_must_be_consecutive(self):
|
||||
queue = TimingQueue(0, 1)
|
||||
row = np.zeros(1, dtype=np.float32)
|
||||
for tick in (1, True, -1, .0):
|
||||
with self.assertRaises(ValueError):
|
||||
queue.push(row, tick=tick)
|
||||
queue.push(row, tick=0)
|
||||
with self.assertRaises(ValueError):
|
||||
queue.push(row, tick=0)
|
||||
self.assertEqual(queue.steps, 1)
|
||||
|
||||
def test_audit_detects_shift_or_initial_negative_zero(self):
|
||||
_, generated, applied, pending = self.sequence(18, 40)
|
||||
applied[18, 0] += 1
|
||||
with self.assertRaises(ValueError):
|
||||
audit_sequence(generated, applied, pending, 18)
|
||||
_, generated, applied, pending = self.sequence(18, 40)
|
||||
applied.view(np.uint32)[0, 0] = 0x80000000
|
||||
with self.assertRaises(ValueError):
|
||||
audit_sequence(generated, applied, pending, 18)
|
||||
|
||||
def test_audit_rejects_invalid_schema(self):
|
||||
_, generated, applied, pending = self.sequence(18, 2)
|
||||
for g, a, p in ((generated.astype(np.float64), applied, pending),
|
||||
(generated, applied[:1], pending), (generated, applied, pending[:2])):
|
||||
with self.assertRaises(ValueError):
|
||||
audit_sequence(g, a, p, 18)
|
||||
|
||||
def test_finite_sequence_sum_preserved_without_brain_tail(self):
|
||||
queue, generated, applied, pending = self.sequence(18, 53)
|
||||
np.testing.assert_array_equal(applied.sum(axis=0, dtype=np.float64) + pending.sum(axis=0, dtype=np.float64),
|
||||
generated.sum(axis=0, dtype=np.float64))
|
||||
self.assertEqual(queue.steps, 53)
|
||||
self.assertFalse(queue.metadata()["brain_tail_advanced"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user