Files
digital-drosophila/models/male-cns-lif/conditioning-execution-v1/test_learning_gates.py
T
2026-09-30 19:49:02 +08:00

425 lines
26 KiB
Python

"""CPU synthetic fixtures only: no real brain, file receipts or science data."""
import copy
import hashlib
import json
import unittest
import numpy as np
import learning_gates as g
NODES = np.arange(6, dtype=np.int32)
POPS = {'MBON': np.array([0, 1, 2], np.int32), 'legacyDownstream': NODES.copy(),
'nonMBONDownstream': np.array([3, 4, 5], np.int32), 'MBON01': np.array([0], np.int32),
'MBON12': np.array([1], np.int32)}
C, N = g.M.CUES
def sha(value):
return hashlib.sha256(str(value).encode()).hexdigest()
def registry():
blocks = {}
counter = 0
for mode in g.M.MODES:
for dan in g.M.DAN_TYPES:
for cue in g.M.CUES:
for rep in range(1, 6):
block = f'{mode}/{dan}/{cue}/{rep}'
base = 2**40 + counter * 10
blocks[block] = dict(mode=mode, dan_type=dan, compartment_verbatim=g.DAN_COMPARTMENTS[dan],
conditioned_cue=cue, replicate=rep,
training_sources=[dict(stream_id=f'{block}/{split}/{assay}', seed=base + j, split=split)
for j, (split, assay) in enumerate((('training', 'normal'), ('training', 'delayed'),
('training', 'reversal'), ('design', 'order')))],
evaluation_sources={cue: dict(stream_id=f'{block}/evaluation/{cue}', seed=base + 7 + j, split='evaluation')
for j, cue in enumerate(g.M.CUES)},
evaluation_input_sha256={cue: sha(f'{block}/input/{cue}') for cue in g.M.CUES})
counter += 1
return dict(schema=g.REGISTRY_SCHEMA, protocol_sha256=sha('synthetic-unregistered-protocol'),
population_binding_sha256=sha('synthetic-population-binding'), nodes_raw_sha256=g.M._hash(NODES),
population_membership_sha256=g.M.validate_populations(NODES, POPS)['membership_sha256'], blocks=blocks)
def authority(reg):
return dict(schema=g.AUTHORITY_SCHEMA, registry_sha256=g.descriptor_sha256(reg),
verification_receipt_sha256=sha('SYNTHETIC-NOT-A-REAL-VERIFICATION'),
execution_inventory_sha256=sha('SYNTHETIC-NOT-EXECUTED'), population_binding_sha256=reg['population_binding_sha256'])
def state(direction=0, *, downstream=True, g_effect=True, offset=0):
counts = [1, 1, 0, 1, 0, 0]
if direction:
counts[1 if direction > 0 else 0] += abs(direction)
if downstream:
counts[3] += abs(direction)
events = sorted((10 + k * 20 + offset, i) for i, count in enumerate(counts) for k in range(count))
conductance = np.zeros(6, np.float64)
if direction and g_effect:
conductance[0] = .002 * abs(direction)
return dict(step=np.array([tick for tick, _ in events], np.int32),
neuron_idx=np.array([i for _, i in events], np.int32), counts=np.array(counts, np.int32),
v=np.full(6, -.052, np.float64), g=conductance, ref=np.zeros(6, np.int32))
def states(conditioned=C, strength=0, *, neutral_strength=0, downstream=True):
neutral = next(cue for cue in g.M.CUES if cue != conditioned)
return {conditioned: state(strength, downstream=downstream), neutral: state(neutral_strength, downstream=downstream)}
def pair(reg, block, label, values, *, delta, checkpoint, policy='common_frozen_reset'):
return dict(schema=g.PAIR_SCHEMA, block_id=block, snapshot_id=f'{block}/{label}',
receipt_sha256=sha(f'{block}/{label}/pair'),
probe_receipt_sha256={cue: sha(f'{block}/{label}/probe/{cue}') for cue in g.M.CUES},
evaluation_input_sha256=dict(reg['blocks'][block]['evaluation_input_sha256']),
state_raw_sha256={cue: g.M.validate_state(values[cue], nodes=NODES, steps=1200)['hashes'] for cue in g.M.CUES},
states=values, state_policy=policy, source_checkpoint_sha256=checkpoint, delta_sha256=delta,
probe_steps=1200, cs_start_tick=0, cs_stop_tick_exclusive=1000, US_requested=False,
weight_updates_enabled=False, feedback_to_training_or_idle=False)
def rebind(pair_value):
pair_value['state_raw_sha256'] = {cue: g.M.validate_state(pair_value['states'][cue], nodes=NODES, steps=1200)['hashes']
for cue in g.M.CUES}
def execution(block, arm, cue, *, initial=None):
return dict(receipt_sha256=sha(f'{block}/{arm}/execution'), recording_verified=True, complete=True,
completed_epochs=100, reinforcement_opportunities=50, terminal_pairings=50, epoch_duration_ms=120.,
cs_duration_ms=100., us_tick=900, initial_delta_sha256=initial or sha('zero-delta'),
terminal_delta_sha256=sha(f'{block}/{arm}/delta'), terminal_checkpoint_sha256=sha(f'{block}/{arm}/terminal'),
neural_state_policy='fresh_epoch_delta_only', weight_rule='frozen_temporal_eligibility_v2', reinforced_cue=cue)
def common(reg, block):
value = reg['blocks'][block]
return dict(replicate_id=block, replicate_unit='independent_training',
training_stream_ids=[x['stream_id'] for x in value['training_sources']],
evaluation_stream_ids=[value['evaluation_sources'][cue]['stream_id'] for cue in g.M.CUES])
def blocks(reg, mode, dan, cue):
return [key for key, value in reg['blocks'].items()
if (value['mode'], value['dan_type'], value['conditioned_cue']) == (mode, dan, cue)]
def reversal_rows(reg, mode='physiological', dan='PAM15', cue=C):
rows = []
neutral = next(x for x in g.M.CUES if x != cue)
direction = 1 if dan == 'PAM15' else -1
for block in blocks(reg, mode, dan, cue):
acq = execution(block, 'acquisition', cue)
executions = dict(acquisition=acq,
reversal=execution(block, 'reversal', neutral, initial=acq['terminal_delta_sha256']),
no_reversal=execution(block, 'no_reversal', cue, initial=acq['terminal_delta_sha256']))
row = common(reg, block)
row['execution'] = executions
row['pre'] = pair(reg, block, 'pre', states(cue), delta=acq['initial_delta_sha256'], checkpoint=sha('reset'))
values = dict(acquisition=states(cue, direction), reversal=states(cue, direction, neutral_strength=2 * direction),
no_reversal=states(cue, 2 * direction))
for arm, value in values.items():
e = executions[arm]
row[arm] = pair(reg, block, arm, value, delta=e['terminal_delta_sha256'], checkpoint=e['terminal_checkpoint_sha256'])
rows.append(row)
return rows
def idle(block, branch, cue):
source = execution(block, 'paired' if branch == 'trained' else 'frozen', cue)
if branch == 'frozen':
source['terminal_delta_sha256'] = source['initial_delta_sha256']
checkpoints, previous = {}, source['terminal_checkpoint_sha256']
for second in (0, 1, 10):
current = sha(f'{block}/{branch}/idle-checkpoint/{second}')
checkpoints[str(second)] = dict(checkpoint_sha256=current, parent_checkpoint_sha256=previous,
elapsed_ticks=second * 10000, absolute_tick=1200 + second * 10000,
delta_sha256=source['terminal_delta_sha256'], carry_sha256={key: sha(f'{block}/{branch}/{second}/{key}') for key in g.CARRY})
previous = current
return dict(source_checkpoint_sha256=source['terminal_checkpoint_sha256'], delta_sha256=source['terminal_delta_sha256'],
idle_lineage_id=f'{block}/{branch}/idle10', idle_receipt_sha256=sha(f'{block}/{branch}/idle-receipt'),
total_idle_ticks=100000, no_input=True, updates_disabled=True, reset_state=False,
analytic_time_advance=False, one_second_is_prefix_of_ten_second=True, checkpoints=checkpoints, source_execution=source)
def retention_rows(reg, mode='physiological', dan='PAM15', cue=C):
rows = []
direction = 1 if dan == 'PAM15' else -1
for block in blocks(reg, mode, dan, cue):
row = common(reg, block)
row.update(execution={branch: idle(block, branch, cue) for branch in ('trained', 'frozen')}, pre={}, checkpoints={})
for branch in ('trained', 'frozen'):
e = row['execution'][branch]
row['pre'][branch] = pair(reg, block, 'pre-' + branch, states(cue),
delta=e['source_execution']['initial_delta_sha256'], checkpoint=sha('reset'))
for second in (0, 1, 10):
row['checkpoints'][str(second)] = {}
for branch in ('trained', 'frozen'):
e = row['execution'][branch]
row['checkpoints'][str(second)][branch] = pair(reg, block, f'{branch}/{second}',
states(cue, direction if branch == 'trained' else 0), delta=e['delta_sha256'],
checkpoint=e['checkpoints'][str(second)]['checkpoint_sha256'], policy='continuous_checkpoint')
rows.append(row)
return rows
def acquisition_rows(reg, mode='physiological', dan='PAM15', cue=C, assay='normal'):
rows = []
for block in blocks(reg, mode, dan, cue):
row = common(reg, block)
row.update(assay=assay, mode=mode, dan_type=dan, conditioned_cue=cue, arms={})
for arm in g.M.ARMS:
strength = (1 if dan == 'PAM15' else -1) if arm == 'paired' else 0
metric = g.M.arm_metrics(states(cue), states(cue, strength), conditioned_cue=cue, nodes=NODES, populations=POPS)
e = dict(complete=True, recording_verified=True, receipt_sha256=sha(f'{block}/{assay}/{arm}/execution'), assay=assay,
epoch_duration_ms=180. if assay == 'delayed' else 120., cs_duration_ms=100., us_tick=1500 if assay == 'delayed' else 900,
completed_epochs=150 if arm == 'unpaired' else 100, reinforcement_opportunities=0 if arm == 'CS-only' else 50, terminal_pairings=50)
row['arms'][arm] = dict(metrics=metric, execution=e)
rows.append(row)
return rows
class GatesTests(unittest.TestCase):
def setUp(self):
self.reg = registry()
self.auth = authority(self.reg)
def evaluate(self, assay, rows, *, mode='physiological', dan='PAM15', cue=C):
kwargs = dict(mode=mode, dan_type=dan, conditioned_cue=cue, registry=self.reg, authority=self.auth)
if assay in ('normal', 'delayed'):
return g.evaluate_acquisition(rows, assay=assay, **kwargs)
return getattr(g, 'evaluate_' + assay)(rows, nodes=NODES, populations=POPS, downstream_policy=g.DOWNSTREAM_POLICY, **kwargs)
def test_registry_checks_real_seed_collision_and_exact_40_cells(self):
for mutation in ('eval_train', 'eval_eval', 'train_train', 'duplicate_cell', '63bit', 'boolseed', 'extra_eval', 'missing_block'):
reg = registry()
values = list(reg['blocks'].values())
if mutation == 'eval_train': values[0]['evaluation_sources'][C]['seed'] = values[1]['training_sources'][0]['seed']
if mutation == 'eval_eval': values[1]['evaluation_sources'][C]['seed'] = values[0]['evaluation_sources'][C]['seed']
if mutation == 'train_train': values[1]['training_sources'][0]['stream_id'] = values[0]['training_sources'][0]['stream_id']
if mutation == 'duplicate_cell': values[1]['replicate'] = values[0]['replicate']
if mutation == '63bit': values[0]['training_sources'][0]['seed'] = 2**63
if mutation == 'boolseed': values[0]['training_sources'][0]['seed'] = True
if mutation == 'extra_eval': values[0]['evaluation_sources']['extra'] = values[0]['evaluation_sources'][C]
if mutation == 'missing_block': reg['blocks'].pop(next(iter(reg['blocks'])))
with self.subTest(mutation=mutation), self.assertRaises(ValueError):
g.validate_registry(reg, expected_sha256=g.descriptor_sha256(reg))
self.assertEqual(g.validate_registry(self.reg, expected_sha256=self.auth['registry_sha256'])['blocks'], 40)
def test_registry_hash_and_population_mutation_rejected(self):
self.reg['protocol_sha256'] = sha('other')
with self.assertRaisesRegex(ValueError, 'changed'):
self.evaluate('reversal', reversal_rows(self.reg))
self.reg = registry(); self.auth = authority(self.reg)
bad = dict(POPS, nonMBONDownstream=np.array([3, 4], np.int32))
with self.assertRaises(ValueError):
g.evaluate_reversal(reversal_rows(self.reg), mode='physiological', dan_type='PAM15', conditioned_cue=C,
registry=self.reg, authority=self.auth, nodes=NODES, populations=bad, downstream_policy=g.DOWNSTREAM_POLICY)
def test_all_four_assays_both_signs_reciprocal_cues_and_no_claims(self):
for assay, factory in (('normal', acquisition_rows), ('delayed', acquisition_rows), ('reversal', reversal_rows), ('retention', retention_rows)):
for dan in g.M.DAN_TYPES:
for cue in g.M.CUES:
rows = factory(self.reg, dan=dan, cue=cue, **({'assay': assay} if assay in ('normal', 'delayed') else {}))
result = self.evaluate(assay, rows, dan=dan, cue=cue)
with self.subTest(assay=assay, dan=dan, cue=cue):
self.assertTrue(result['predicate_pass'])
self.assertEqual(result['successful_same_replicate_conjunctions'], 5)
self.assertFalse(result['scientific_learning_pass_claimed'])
self.assertFalse(result['external_authority_verified'])
self.assertFalse(result['data_backed_claimed'])
json.dumps(result, allow_nan=False)
def test_reversal_zero_is_failure_but_legacy_style_inequality_is_true(self):
rows = reversal_rows(self.reg)
for row in rows:
row['reversal']['states'] = states(C, 1, neutral_strength=1); rebind(row['reversal'])
result = self.evaluate('reversal', rows)
self.assertFalse(result['predicate_pass'])
self.assertTrue(all(row['legacy_style_sign_inequality_on_registered_S'] for row in result['replicates']))
def test_reversal_old_cue_only_and_mbon_only_cannot_satisfy_new_downstream_gate(self):
for only_old_cue in (True, False):
rows = reversal_rows(self.reg)
for row in rows:
if only_old_cue:
row['reversal']['states'] = states(C, -1)
else:
row['reversal']['states'][N] = state(2, downstream=False)
rebind(row['reversal'])
result = self.evaluate('reversal', rows)
self.assertFalse(result['predicate_pass'])
if not only_old_cue:
change = result['replicates'][0]['acquisition_to_reversal_changes_by_cue'][N]['populations']
self.assertTrue(change['legacyDownstream']['events_changed'])
self.assertFalse(change['nonMBONDownstream']['events_changed'])
def test_reversal_same_replicate_conjunction_and_exact_three(self):
rows = reversal_rows(self.reg)
rows[2]['no_reversal']['states'] = states(C, -1); rebind(rows[2]['no_reversal'])
rows[3]['reversal']['states'] = states(C, 1, neutral_strength=1); rebind(rows[3]['reversal'])
rows[4]['reversal']['states'][N] = state(2, downstream=False); rebind(rows[4]['reversal'])
result = self.evaluate('reversal', rows)
self.assertEqual(result['successful_same_replicate_conjunctions'], 2)
self.assertFalse(result['predicate_pass'])
rows[2] = reversal_rows(self.reg)[2]
self.assertTrue(self.evaluate('reversal', rows)['predicate_pass'])
def test_retention_same_replicate_at_both_times_not_separate_time_majorities(self):
rows = retention_rows(self.reg)
for index, times in ((2, ('10',)), (3, ('1',)), (4, ('1', '10'))):
for second in times:
p = rows[index]['checkpoints'][second]['trained']
p['states'] = states(); rebind(p)
result = self.evaluate('retention', rows)
self.assertEqual(result['successful_same_replicate_conjunctions'], 2)
self.assertFalse(result['predicate_pass'])
rows[2] = retention_rows(self.reg)[2]
self.assertTrue(self.evaluate('retention', rows)['predicate_pass'])
def test_retention_frozen_equality_opposite_sign_and_no_nonmbon_change_fail(self):
for variant in ('equal_frozen', 'opposite', 'mbon_only'):
rows = retention_rows(self.reg)
for row in rows:
for second in ('1', '10'):
pair_value = row['checkpoints'][second]['trained']
if variant == 'equal_frozen':
pair_value = row['checkpoints'][second]['frozen']; pair_value['states'] = states(C, 1)
elif variant == 'opposite': pair_value['states'] = states(C, -1)
else: pair_value['states'] = states(C, 1, downstream=False)
rebind(pair_value)
self.assertFalse(self.evaluate('retention', rows)['predicate_pass'])
def test_retention_chain_full_state_clock_and_probe_policy_mutations_rejected(self):
for variant in ('clock', 'delta', 'parent', 'queue', 'reset', 'analytic', 'prefix', 'missing_time', 'input', 'feedback', 'newUS', 'short_probe', 'fresh_probe', 'raw_state'):
rows = retention_rows(self.reg)
execution_value = rows[0]['execution']['trained']
cp = execution_value['checkpoints']['10']
p = rows[0]['checkpoints']['10']['trained']
if variant == 'clock': cp['absolute_tick'] += 1
if variant == 'delta': cp['delta_sha256'] = sha('changed')
if variant == 'parent': cp['parent_checkpoint_sha256'] = execution_value['source_checkpoint_sha256']
if variant == 'queue': cp['carry_sha256'].pop('apl_pending')
if variant == 'reset': execution_value['reset_state'] = True
if variant == 'analytic': execution_value['analytic_time_advance'] = True
if variant == 'prefix': execution_value['one_second_is_prefix_of_ten_second'] = False
if variant == 'missing_time': rows[0]['checkpoints'].pop('0')
if variant == 'input': p['evaluation_input_sha256'][C] = sha('other')
if variant == 'feedback': p['feedback_to_training_or_idle'] = True
if variant == 'newUS': p['US_requested'] = True
if variant == 'short_probe': p['probe_steps'] = 1000
if variant == 'fresh_probe': p['state_policy'] = 'common_frozen_reset'
if variant == 'raw_state': p['states'][C]['v'][0] += .001
with self.subTest(variant=variant), self.assertRaises(ValueError): self.evaluate('retention', rows)
def test_reversal_delta_lineage_terminal_inventory_and_receipt_mutations_rejected(self):
for variant in ('resetdelta', 'early', 'epochs', 'cue', 'receipt', 'snapshot_receipt', 'probeAB', 'evaldraw', 'wrongcell', 'trainstream'):
rows = reversal_rows(self.reg)
e = rows[0]['execution']['reversal']
if variant == 'resetdelta': e['initial_delta_sha256'] = sha('zero')
if variant == 'early': e['terminal_pairings'] = 20
if variant == 'epochs': e['completed_epochs'] = 99
if variant == 'cue': e['reinforced_cue'] = C
if variant == 'receipt': e['receipt_sha256'] = rows[0]['execution']['acquisition']['receipt_sha256']
if variant == 'snapshot_receipt': rows[0]['reversal']['receipt_sha256'] = rows[0]['acquisition']['receipt_sha256']
if variant == 'probeAB': rows[0]['reversal']['probe_receipt_sha256'][N] = rows[0]['reversal']['probe_receipt_sha256'][C]
if variant == 'evaldraw': rows[0]['replicate_unit'] = 'evaluation'
if variant == 'wrongcell': rows[1]['replicate_id'] = rows[0]['replicate_id']
if variant == 'trainstream': rows[0]['training_stream_ids'] = rows[1]['training_stream_ids']
with self.subTest(variant=variant), self.assertRaises(ValueError): self.evaluate('reversal', rows)
def test_acquisition_controls_and_frozen_gate_are_preserved(self):
for variant in ('missing_control', 'delayed_timing', 'metric_mutation', 'population'):
rows = acquisition_rows(self.reg, assay='delayed')
if variant == 'missing_control': rows[0]['arms'].pop('DAN-only')
if variant == 'delayed_timing': rows[0]['arms']['frozen']['execution']['us_tick'] = 900
if variant == 'metric_mutation': rows[0]['arms']['paired']['metrics']['rawS'] = 999.
if variant == 'population': rows[0]['arms']['paired']['metrics']['cues'][C]['nodes_raw_sha256'] = sha('other')
with self.subTest(variant=variant), self.assertRaises(ValueError): self.evaluate('delayed', rows)
def normal_reports(self):
return [self.evaluate('normal', acquisition_rows(self.reg, mode, dan, cue), mode=mode, dan=dan, cue=cue)
for mode in g.M.MODES for dan in g.M.DAN_TYPES for cue in g.M.CUES]
def test_cohort_exact_eight_cells_missing_not_run_and_mutation_rejected(self):
reports = self.normal_reports()
result = g.summarize_cohort(reports, registry=self.reg, authority=self.auth, required_assays=('normal',))
self.assertTrue(result['all_functional_predicates_pass'])
self.assertFalse(result['legacy_H_and_integrity_gates_included'])
missing = g.summarize_cohort(reports[:-1], registry=self.reg, authority=self.auth, required_assays=('normal',))
self.assertIsNone(missing['all_functional_predicates_pass'])
self.assertEqual(sum(x['status'] == 'NOT-RUN' for x in missing['table']), 1)
for variant in ('duplicate', 'predicate', 'conjunction', 'controlgain', 'unsupportedclaim'):
changed = copy.deepcopy(reports)
if variant == 'duplicate': changed[-1] = changed[0]
if variant == 'predicate': changed[0]['predicate_pass'] = False
if variant == 'conjunction': changed[0]['replicates'][0]['conjunction_pass'] = False
if variant == 'controlgain': next(iter(changed[0]['legacy_control_MBON_gains'].values()))[changed[0]['replicates'][0]['replicate_id']] = 900.
if variant == 'unsupportedclaim': changed[0]['scientific_learning_pass_claimed'] = True
with self.subTest(variant=variant), self.assertRaises(ValueError):
g.summarize_cohort(changed, registry=self.reg, authority=self.auth, required_assays=('normal',))
def test_legacy_H_mapping_absent_and_both_DAN_control_sources_explicit(self):
reports = self.normal_reports()
self.assertEqual(g.legacy_h_cohort_audit(reports, registry=self.reg, authority=self.auth, declared_mapping=None)['status'], 'NOT-TESTABLE')
good = g.legacy_h_cohort_audit(reports, registry=self.reg, authority=self.auth, declared_mapping=g.H_MAPPING)
self.assertEqual(len(good['groups']), 4)
self.assertTrue(good['both_pass'])
rows = acquisition_rows(self.reg, dan='PPL103')
for row in rows:
row['arms']['random reward']['metrics'] = g.M.arm_metrics(states(), states(C, -2), conditioned_cue=C, nodes=NODES, populations=POPS)
replacement = self.evaluate('normal', rows, dan='PPL103')
reports = [replacement if (x['mode'], x['dan_type'], x['conditioned_cue']) == ('physiological', 'PPL103', C) else x for x in reports]
result = g.legacy_h_cohort_audit(reports, registry=self.reg, authority=self.auth, declared_mapping=g.H_MAPPING)
group = next(x for x in result['groups'] if x['mode'] == 'physiological' and x['conditioned_cue'] == C)
self.assertTrue(group['control_sources']['PAM15']['predicate_pass'])
self.assertFalse(group['control_sources']['PPL103']['predicate_pass'])
self.assertFalse(result['both_pass'])
def test_full_cohort_recomputes_followup_predicates_and_keeps_assay_majorities_separate(self):
reports = []
for mode in g.M.MODES:
for dan in g.M.DAN_TYPES:
for cue in g.M.CUES:
for assay, factory in (('normal', acquisition_rows), ('delayed', acquisition_rows),
('reversal', reversal_rows), ('retention', retention_rows)):
rows = factory(self.reg, mode, dan, cue, **({'assay': assay} if assay in ('normal', 'delayed') else {}))
reports.append(self.evaluate(assay, rows, mode=mode, dan=dan, cue=cue))
result = g.summarize_cohort(reports, registry=self.reg, authority=self.auth, required_assays=g.ASSAYS)
self.assertEqual(len(result['table']), 32)
self.assertTrue(result['all_functional_predicates_pass'])
for variant in ('reversal_sign', 'reversal_predicate', 'retention_sign', 'retention_predicate', 'retention_time0'):
changed = copy.deepcopy(reports)
rev = next(x for x in changed if x['assay'] == 'reversal')['replicates'][0]
ret = next(x for x in changed if x['assay'] == 'retention')['replicates'][0]
if variant == 'reversal_sign': rev['rawS']['reversal'] = 999.
if variant == 'reversal_predicate': rev['predicates']['strict_three_signed_relations'] = False
if variant == 'retention_sign': ret['times']['10']['rawS_trained'] = 999.
if variant == 'retention_predicate': ret['times']['10']['predicates']['beyond_time_matched_frozen'] = False
if variant == 'retention_time0': ret['times']['0']['contributes_to_gate'] = True
with self.subTest(variant=variant), self.assertRaises(ValueError):
g.summarize_cohort(changed, registry=self.reg, authority=self.auth, required_assays=g.ASSAYS)
def test_frozen_retention_source_cannot_claim_updated_delta(self):
rows = retention_rows(self.reg)
rows[0]['execution']['frozen']['source_execution']['initial_delta_sha256'] = sha('another-zero')
with self.assertRaisesRegex(ValueError, 'Frozen training'):
self.evaluate('retention', rows)
def test_inputs_not_mutated_and_output_does_not_alias_inputs(self):
rows = reversal_rows(self.reg)
before = copy.deepcopy(rows)
result = self.evaluate('reversal', rows)
for old, new in zip(before, rows):
for snapshot in ('pre', 'acquisition', 'reversal', 'no_reversal'):
for cue in g.M.CUES:
for key in g.M.STATE_KEYS:
np.testing.assert_array_equal(old[snapshot]['states'][cue][key], new[snapshot]['states'][cue][key])
result['replicates'][0]['metrics']['acquisition']['rawS'] = 888.
self.assertEqual(self.evaluate('reversal', rows)['replicates'][0]['rawS']['acquisition'], 1.)
if __name__ == '__main__':
unittest.main()