500 lines
36 KiB
Python
500 lines
36 KiB
Python
#!/usr/bin/env python3
|
|
"""Audit frozen nonlinear paths using saved vectors, not scalar curvature fits.
|
|
|
|
Artifact validity, independently verified linear accuracy, observed nonlinear
|
|
improvement, and physical validity are different conclusions. Remainder floors
|
|
are heuristic estimates, never certified FEM assembly bounds.
|
|
"""
|
|
import argparse
|
|
import csv
|
|
import hashlib
|
|
import json
|
|
import math
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
P = 'nonlinear_step_'
|
|
DIRECTIONS = ('full', 'shape', 'fields')
|
|
PATHS = ('raw', 'curvature')
|
|
EPS = sys.float_info.epsilon
|
|
GR = {'gravity_gradient_relation', 'poisson_balance'}
|
|
GV = {'gravity_gradient', 'gravity_potential'}
|
|
BASE_FILES = {'metadata.txt', P + 'layout.csv'} | {P + n + '.csv' for n in ('summary', 'linear', 'paths', 'blocks', 'mixed', 'preparations', 'inner', 'restorations')} | {
|
|
P + n + '.txt' for n in ('physical_base', 'normalized_base', 'residual', 'rhs', 'state_factors', 'residual_factors', 'restored_residual')
|
|
} | {P + k + '_' + d + '.txt' for k in ('direction', 'action', 'restored_action') for d in DIRECTIONS}
|
|
|
|
|
|
def digest(path):
|
|
return hashlib.sha256(path.read_bytes()).hexdigest()
|
|
|
|
|
|
def rows(path):
|
|
with path.open() as stream:
|
|
return list(csv.DictReader(stream))
|
|
|
|
|
|
def vector(path):
|
|
tokens = path.read_text().split()
|
|
count = int(tokens[0])
|
|
values = [float(t) for t in tokens[1:]]
|
|
if count <= 0 or count != len(values) or not all(math.isfinite(v) for v in values):
|
|
raise ValueError(f'Invalid finite vector: {path}')
|
|
return values
|
|
|
|
|
|
def norm(v):
|
|
return math.sqrt(math.fsum(x * x for x in v))
|
|
|
|
|
|
def dot(a, b):
|
|
if len(a) != len(b): raise ValueError('Incompatible vectors')
|
|
return math.fsum(x * y for x, y in zip(a, b))
|
|
|
|
|
|
def minus(a, b):
|
|
if len(a) != len(b): raise ValueError('Incompatible vectors')
|
|
return [x - y for x, y in zip(a, b)]
|
|
|
|
|
|
def close(a, b, scale=0.0):
|
|
return math.isfinite(a) and math.isfinite(b) and abs(a - b) <= 5e-10 * max(abs(a), abs(b)) + 512 * EPS * abs(scale) + 1e-28
|
|
|
|
|
|
def nonnegative(x):
|
|
return math.isfinite(x) and x >= 0
|
|
|
|
|
|
def sanitize(value):
|
|
if isinstance(value, float) and not math.isfinite(value): return None
|
|
if isinstance(value, dict): return {k: sanitize(v) for k, v in value.items()}
|
|
if isinstance(value, (list, tuple)): return [sanitize(v) for v in value]
|
|
return value
|
|
|
|
|
|
def flag(row, key, check, prefix):
|
|
check(prefix + key + ':boolean', row[key] in ('0', '1'))
|
|
return row[key] == '1'
|
|
|
|
|
|
def layout_for(layout, kind, count):
|
|
result, covered = {}, []
|
|
entries = [r for r in layout if r['kind'] == kind]
|
|
for row in entries:
|
|
start, size = int(row['offset']), int(row['size'])
|
|
if start < 0 or size < 0: raise ValueError('Invalid layout')
|
|
result[row['block']] = (start, size)
|
|
covered.extend(range(start, start + size))
|
|
if len(result) != len(entries) or covered != list(range(count)):
|
|
raise ValueError(f'{kind} blocks do not partition the vector')
|
|
return result
|
|
|
|
|
|
def indices(layout, names):
|
|
return sorted(i for name in names for i in range(layout[name][0], sum(layout[name])))
|
|
|
|
|
|
def measurements(base, action, trial, alpha):
|
|
prediction = [f + alpha * j for f, j in zip(base, action)]
|
|
remainder = minus(trial, prediction)
|
|
fn, jn, ln, tn, rn = map(norm, (base, action, prediction, trial, remainder))
|
|
projection = dot(prediction, remainder)
|
|
identity = abs(tn * tn - ln * ln - 2 * projection - rn * rn)
|
|
return {'base_norm': fn, 'action_norm': jn, 'linear_prediction_norm': ln, 'residual_norm': tn,
|
|
'remainder_norm': rn, 'remainder_over_alpha': rn / alpha, 'remainder_over_alpha_squared': rn / alpha ** 2,
|
|
'linear_dot_remainder': projection, 'norm_identity_error': identity}, prediction, remainder
|
|
|
|
|
|
def check_measurements(row, values, check, prefix):
|
|
a = float(row['alpha'])
|
|
scale = values['base_norm'] + a * values['action_norm'] + values['residual_norm']
|
|
for name, value in values.items():
|
|
reported = float(row[name])
|
|
if name == 'norm_identity_error':
|
|
check(prefix + name, math.isfinite(reported) and max(abs(reported), value) <= 2048 * EPS * scale ** 2 + 1e-28)
|
|
else:
|
|
rounding_scale = scale / a if name == 'remainder_over_alpha' else scale / a ** 2 if name == 'remainder_over_alpha_squared' else scale ** 2 if name == 'linear_dot_remainder' else scale
|
|
check(prefix + name, close(value, reported, rounding_scale))
|
|
|
|
|
|
def vector_orders(observations, linear_passed):
|
|
groups = {}
|
|
for row in observations: groups.setdefault((row['path'], row['direction'], row['block']), []).append(row)
|
|
output = []
|
|
for key, entries in groups.items():
|
|
entries.sort(key=lambda r: r['alpha'], reverse=True)
|
|
intervals = []
|
|
for first, second in zip(entries, entries[1:]):
|
|
resolved = all(r['usable'] and r['increment_resolved'] and r['remainder_norm'] > 10 * r['floor'] for r in (first, second))
|
|
if resolved:
|
|
intervals.append({'alpha_large': first['alpha'], 'alpha_small': second['alpha'],
|
|
'vector_remainder_order': math.log(first['remainder_norm'] / second['remainder_norm']) / math.log(first['alpha'] / second['alpha']),
|
|
'derivative_error_ratio': second['remainder_over_alpha'] / first['remainder_over_alpha']})
|
|
output.append(dict(zip(('path', 'direction', 'block'), key)) | {'resolved_intervals': intervals,
|
|
'status': 'resolved_vector_observations' if intervals else 'unresolved',
|
|
'eligible_for_newton_forcing_comparison': linear_passed})
|
|
return output
|
|
|
|
|
|
def inspect_case(folder):
|
|
try: return inspect_case_artifacts(Path(folder))
|
|
except (OSError, ValueError, KeyError, TypeError, IndexError, OverflowError, ZeroDivisionError) as error:
|
|
return {'passed': False, 'checks': [{'check': 'complete_readable_artifacts', 'passed': False, 'error': str(error)}],
|
|
'observations_valid': False, 'vector_order_observations': [], 'required_artifacts': sorted(BASE_FILES)}
|
|
|
|
|
|
def inspect_case_artifacts(folder):
|
|
checks = []
|
|
def check(name, passed): checks.append({'check': name, 'passed': bool(passed)})
|
|
summary_rows = rows(folder / (P + 'summary.csv'))
|
|
summary = {r['metric']: float(r['value']) for r in summary_rows}
|
|
check('unique_summary', len(summary) == len(summary_rows))
|
|
meta = dict(line.split('=', 1) for line in (folder / 'metadata.txt').read_text().splitlines() if '=' in line)
|
|
saved = {name: vector(folder / (P + name + '.txt')) for name in ('physical_base', 'normalized_base', 'residual', 'rhs', 'state_factors', 'residual_factors')}
|
|
x, physical, f = saved['normalized_base'], saved['physical_base'], saved['residual']
|
|
sf, rf = saved['state_factors'], saved['residual_factors']
|
|
check('state_dimensions', len(x) == len(physical) == len(sf))
|
|
check('residual_dimensions', len(f) == len(saved['rhs']) == len(rf))
|
|
check('positive_factors', all(v > 0 for v in sf + rf))
|
|
check('normalized_physical_consistency', all(close(a, b * c, abs(a)) for a, b, c in zip(x, physical, sf)))
|
|
check('rhs_is_minus_F', saved['rhs'] == [-v for v in f])
|
|
layout = rows(folder / (P + 'layout.csv'))
|
|
vl, rl = layout_for(layout, 'value', len(x)), layout_for(layout, 'residual', len(f))
|
|
gi, gr, si = indices(vl, GV), indices(rl, GR), set(indices(vl, {'surface_deformation'}))
|
|
retained = sorted(set(range(len(x))) - set(gi))
|
|
dirs = {d: vector(folder / (P + 'direction_' + d + '.txt')) for d in DIRECTIONS}
|
|
acts = {d: vector(folder / (P + 'action_' + d + '.txt')) for d in DIRECTIONS}
|
|
for d in DIRECTIONS: check(d + ':dimensions', len(dirs[d]) == len(x) and len(acts[d]) == len(f))
|
|
check('shape_split_exact', dirs['shape'] == [v if i in si else 0.0 for i, v in enumerate(dirs['full'])])
|
|
check('fields_split_exact', dirs['fields'] == [0.0 if i in si else v for i, v in enumerate(dirs['full'])])
|
|
split_error = norm([a - b - c for a, b, c in zip(acts['full'], acts['shape'], acts['fields'])])
|
|
check('action_split', split_error <= 512 * EPS * sum(norm(v) for v in acts.values()) + 1e-28)
|
|
lr = rows(folder / (P + 'linear.csv'))
|
|
check('one_linear_report', len(lr) == 1)
|
|
linear = lr[0]
|
|
rhs_norm, defect = norm(saved['rhs']), norm([a + b for a, b in zip(f, acts['full'])])
|
|
target = max(summary['linear_absolute_tolerance'], float(meta['linear_tol']) * rhs_norm)
|
|
check('linear_control_matches_metadata', summary['linear_relative_tolerance'] == float(meta['linear_tol']) and summary['linear_maximum_iterations'] == int(meta['max_linear']) and summary['linear_restart_length'] == int(meta['restart']))
|
|
gate = defect <= target
|
|
for key, value in [('rhs_norm', rhs_norm), ('verified_true_norm', defect), ('verified_relative_true', defect / rhs_norm), ('threshold', target)]:
|
|
check('linear:' + key, close(value, float(linear[key]), 1.0 if key == 'verified_relative_true' else rhs_norm))
|
|
check('summary_linear_gate', summary['linear_verified_gate'] == int(gate))
|
|
check('honest_linear_gate', flag(linear, 'verified_gate', check, 'linear:') == gate)
|
|
converged = flag(linear, 'converged', check, 'linear:')
|
|
check('linear_status', converged == (linear['status'] == '0'))
|
|
check('linear_finite_reported_defect', nonnegative(float(linear['reported_true_norm'])))
|
|
check('linear_budget', 0 <= int(linear['iterations']) <= int(meta['max_linear']))
|
|
check('linear_time', nonnegative(float(linear['seconds'])))
|
|
path_rows, block_rows, mixed_rows = (rows(folder / (P + n + '.csv')) for n in ('paths', 'blocks', 'mixed'))
|
|
pm = {(int(r['sample']), r['direction'], r['path']): r for r in path_rows}
|
|
bm = {(int(r['sample']), r['direction'], r['path'], r['block']): r for r in block_rows}
|
|
mm = {(int(r['sample']), r['path'], r['block']): r for r in mixed_rows}
|
|
check('unique_paths', len(pm) == len(path_rows)); check('unique_blocks', len(bm) == len(block_rows)); check('unique_mixed', len(mm) == len(mixed_rows))
|
|
samples = sorted({key[0] for key in pm})
|
|
check('eight_samples', samples == list(range(8)))
|
|
check('complete_path_grid', set(pm) == {(i, d, p) for i in samples for d in DIRECTIONS for p in PATHS})
|
|
layouts = {'all': (0, len(f)), **rl}
|
|
check('complete_block_grid', set(bm) == {(i,d,p,b) for i in samples for d in DIRECTIONS for p in PATHS for b in layouts})
|
|
check('complete_mixed_grid', set(mm) == {(i,p,b) for i in samples for p in PATHS for b in layouts})
|
|
restoration_error = validate_restoration(folder, summary, f, acts, layouts, check)
|
|
inner_rows = rows(folder / (P + 'inner.csv'))
|
|
inner_map = {(int(r['sample']), r['direction']): r for r in inner_rows}
|
|
check('unique_inner_reports', len(inner_map) == len(inner_rows))
|
|
check('inner_coverage', set(inner_map) == {(i,d) for i in samples for d in DIRECTIONS if pm[(i,d,'raw')]['prepared'] == '1'})
|
|
validate_work(folder, summary, linear, inner_rows, path_rows, check)
|
|
cancellation = []
|
|
for block, (start, size) in layouts.items():
|
|
an = {d:norm(acts[d][start:start+size]) for d in DIRECTIONS}
|
|
denominator = an['shape'] * an['fields']
|
|
cancellation.append({'block':block, 'action_norms':an,
|
|
'shape_fields_cosine':dot(acts['shape'][start:start+size],acts['fields'][start:start+size])/denominator if denominator else None,
|
|
'full_over_sum_split_norms':an['full']/(an['shape']+an['fields']) if an['shape']+an['fields'] else None})
|
|
required, observations, outcomes = set(BASE_FILES), [], []
|
|
for sample in samples:
|
|
alphas = {float(pm[(sample, d, p)]['alpha']) for d in DIRECTIONS for p in PATHS}
|
|
check(f'{sample}:common_positive_alpha', len(alphas) == 1 and all(math.isfinite(a) and a > 0 for a in alphas))
|
|
a, data = next(iter(alphas)), {}
|
|
check(f'{sample}:recorded_alpha', a == summary['alpha_' + str(sample)])
|
|
for d in DIRECTIONS:
|
|
pred_name = P + 'prediction_' + d + '_a' + str(sample) + '.txt'
|
|
required.add(pred_name)
|
|
saved_prediction = vector(folder / pred_name)
|
|
check(f'{sample}:{d}:prediction_vector', len(saved_prediction) == len(f) and all(close(v,f0+a*j,abs(f0)+a*abs(j)) for v,f0,j in zip(saved_prediction,f,acts[d])))
|
|
for path in PATHS:
|
|
row, label = pm[(sample, d, path)], f'{sample}:{d}:{path}:'
|
|
flags = {k: flag(row, k, check, label) for k in ('prepared', 'inner_converged', 'prepared_gate', 'usable', 'increment_resolved')}
|
|
check(label + 'usable_definition', flags['usable'] == (flags['prepared'] and flags['inner_converged'] and flags['prepared_gate']))
|
|
check(label + 'seconds', nonnegative(float(row['seconds'])))
|
|
correction = [0.0] * len(x)
|
|
if path == 'curvature' and flags['inner_converged']:
|
|
correction_name = P + 'correction_curvature_' + d + '_a' + str(sample) + '.txt'
|
|
required.add(correction_name); correction = vector(folder / correction_name)
|
|
check(label + 'correction_only_gravity', len(correction) == len(x) and all(correction[i] == 0 for i in retained))
|
|
if path == 'curvature' and (sample,d) in inner_map:
|
|
ir = inner_map[(sample,d)]
|
|
inner_converged = ir['converged'] == '1'
|
|
check(label + 'inner_matches', flags['inner_converged'] == inner_converged and inner_converged == (ir['status'] == '0') and float(ir['alpha']) == a)
|
|
inner_target = max(summary['gravity_absolute_tolerance'],summary['gravity_relative_tolerance']*float(ir['rhs_norm']))
|
|
check(label + 'inner_target', close(float(ir['threshold']),inner_target,inner_target))
|
|
if inner_converged: check(label + 'inner_gate', nonnegative(float(ir['true_norm'])) and float(ir['true_norm']) <= inner_target)
|
|
if path == 'raw': check(label + 'vacuous_flags', flags['inner_converged'] and flags['prepared_gate'])
|
|
if not flags['prepared']:
|
|
check(label + 'not_usable', not flags['usable'])
|
|
check(label + 'unprepared_metrics_unavailable', all(math.isnan(float(row[k])) for k in ('residual_norm','merit','remainder_norm','linear_dot_remainder','norm_identity_error','heuristic_roundoff_scale')))
|
|
for block in layouts:
|
|
br = bm[(sample,d,path,block)]
|
|
check(label + block + ':unprepared_unavailable', all(math.isnan(float(br[k])) for k in ('residual_norm','remainder_norm','linear_dot_remainder','norm_identity_error')))
|
|
outcomes.append({'sample':sample,'alpha':a,'direction':d,'path':path,**flags,
|
|
'status':'raw_preparation_failed' if path=='raw' else 'raw_preparation_blocked' if pm[(sample,d,'raw')]['prepared']=='0' else 'inner_solve_failed' if not flags['inner_converged'] else 'corrected_preparation_failed'})
|
|
data[(d, path)] = None; continue
|
|
files = {k: P + k + '_' + path + '_' + d + '_a' + str(sample) + '.txt' for k in ('state', 'residual')}
|
|
required.update(files.values())
|
|
state, trial = vector(folder / files['state']), vector(folder / files['residual'])
|
|
check(label + 'dimensions', len(state) == len(x) and len(trial) == len(f))
|
|
values, prediction, remainder = measurements(f, acts[d], trial, a)
|
|
check_measurements(row, values, check, label)
|
|
check(label + 'merit', close(.5 * values['residual_norm'] ** 2, float(row['merit']), values['residual_norm'] ** 2))
|
|
check(label + 'slope', close(dot(f, acts[d]), float(row['slope']), norm(f) * norm(acts[d])))
|
|
increment = minus(state, x)
|
|
intended = [a * v + delta for v,delta in zip(dirs[d],correction)]
|
|
addition_error = norm(minus(increment,intended))
|
|
expected_norm = norm(intended)
|
|
check(label + 'expected_step_norm', close(expected_norm,float(row['expected_step_norm']),expected_norm))
|
|
check(label + 'addition_error_norm', close(addition_error,float(row['addition_error_norm']),norm(x)))
|
|
resolved = expected_norm > 64*EPS*(1+norm(x)) and norm(increment)>0 and addition_error <= .01*expected_norm
|
|
check(label + 'honest_increment_resolution', flags['increment_resolved'] == resolved)
|
|
derivative = values['remainder_over_alpha']/values['action_norm'] if values['action_norm']>0 else math.nan
|
|
check(label + 'relative_derivative_error', close(derivative,float(row['relative_derivative_error']),derivative) if math.isfinite(derivative) else math.isnan(float(row['relative_derivative_error'])))
|
|
check(label + 'actual_step_norm', close(norm(increment), float(row['actual_step_norm']), norm(x)))
|
|
if path == 'raw':
|
|
intended = [a * v for v in dirs[d]]
|
|
error = norm(minus(increment, intended))
|
|
check(label + 'raw_state_path', error <= 512 * EPS * (norm(x) + norm(intended)) + 1e-28)
|
|
check(label + 'vacuous_gravity_flags', flags['inner_converged'] and flags['prepared_gate'])
|
|
else:
|
|
raw = data[(d, 'raw')]
|
|
check(label + 'prepared_raw_required', raw is not None)
|
|
delta = minus(state, raw['state'])
|
|
check(label + 'saved_correction_matches_state', norm(minus(delta,correction)) <= 512*EPS*(norm(state)+norm(correction))+1e-28)
|
|
check(label + 'retained_coordinates_unchanged', all(delta[i] == 0 for i in retained))
|
|
check(label + 'gravity_correction_norm', close(norm(delta), float(row['gravity_correction_norm']), norm(state)))
|
|
target_defect = norm(remainder[i] for i in gr)
|
|
check(label + 'gravity_affine_target_defect', close(target_defect, float(row['gravity_target_defect']), values['base_norm'] + a * values['action_norm']))
|
|
allowance, threshold = float(row['gravity_arithmetic_allowance']), float(row['gravity_target_threshold'])
|
|
check(label + 'threshold_is_inner_defect_plus_allowance', close(threshold,float(inner_map[(sample,d)]['true_norm'])+allowance,threshold))
|
|
check(label + 'gravity_thresholds', nonnegative(allowance) and nonnegative(threshold) and threshold >= allowance)
|
|
if flags['prepared_gate']:
|
|
check(label + 'gravity_target_gate', target_defect <= threshold + 512 * EPS * values['base_norm'])
|
|
check(label + 'gravity_affine_gate', nonnegative(float(row['gravity_affine_disagreement'])) and float(row['gravity_affine_disagreement']) <= allowance)
|
|
data[(d, path)] = {'state': state, 'trial': trial, 'prediction': prediction, 'remainder': remainder, 'flags': flags}
|
|
outcomes.append({'sample': sample, 'alpha': a, 'direction': d, 'path': path, **flags, 'status':'usable' if flags['usable'] else 'prepared_gravity_gate_failed',
|
|
'actual_gravity_residual_norm':norm(trial[i] for i in gr),
|
|
'gravity_affine_target_defect':float(row['gravity_target_defect']) if path=='curvature' else None,
|
|
'actual_norm': values['residual_norm'], 'predicted_norm': values['linear_prediction_norm'],
|
|
'actual_merit_decrease': .5 * (values['base_norm'] ** 2 - values['residual_norm'] ** 2),
|
|
'predicted_merit_decrease': .5 * (values['base_norm'] ** 2 - values['linear_prediction_norm'] ** 2)})
|
|
for block, (start, size) in layouts.items():
|
|
br = bm[(sample, d, path, block)]
|
|
check(label + block + ':layout', int(br['offset']) == start and int(br['size']) == size and float(br['alpha']) == a)
|
|
part, _, _ = measurements(f[start:start + size], acts[d][start:start + size], trial[start:start + size], a)
|
|
check_measurements(br, part, check, label + block + ':')
|
|
roundoff = 128 * EPS * (1+part['base_norm'] + a * part['action_norm'] + part['residual_norm'])
|
|
floor = max(8*restoration_error,roundoff)
|
|
reported_floor = float(br['heuristic_roundoff_scale'])
|
|
check(label + block + ':heuristic_floor', math.isfinite(reported_floor) and roundoff*(1-1e-12) <= reported_floor <= floor*(1+1e-12))
|
|
if block == 'all': check(label+'path_floor_matches',close(float(row['heuristic_roundoff_scale']),reported_floor,reported_floor))
|
|
observations.append({'sample': sample, 'alpha': a, 'path': path, 'direction': d, 'block': block,
|
|
'usable': flags['usable'], 'increment_resolved': flags['increment_resolved'], **part, 'floor': floor})
|
|
for path in PATHS:
|
|
usable = all(data[(d, path)] is not None and data[(d, path)]['flags']['usable'] for d in DIRECTIONS)
|
|
for block, (start, size) in layouts.items():
|
|
row, label = mm[(sample, path, block)], f'{sample}:{path}:mixed:{block}:'
|
|
check(label + 'layout', int(row['offset']) == start and int(row['size']) == size and float(row['alpha']) == a)
|
|
check(label + 'honest_usable', flag(row, 'usable', check, label) == usable)
|
|
all_prepared = all(data[(d,path)] is not None for d in DIRECTIONS)
|
|
if not all_prepared:
|
|
check(label+'unavailable_metrics',all(math.isnan(float(row[k])) for k in ('full_remainder_norm','mixed_remainder_norm','linear_dot_mixed','norm_identity_error')))
|
|
continue
|
|
remainders = {d: data[(d, path)]['remainder'][start:start + size] for d in DIRECTIONS}
|
|
remainders['mixed'] = [u - v - w for u, v, w in zip(remainders['full'], remainders['shape'], remainders['fields'])]
|
|
prediction = data[('full', path)]['prediction'][start:start + size]
|
|
scale = norm(prediction) + sum(norm(v) for v in remainders.values())
|
|
projections = {d: dot(prediction, v) for d, v in remainders.items()}
|
|
for d, vals in remainders.items():
|
|
check(label + d + ':norm', close(norm(vals), float(row[d + '_remainder_norm']), scale))
|
|
check(label + d + ':projection', close(projections[d], float(row['linear_dot_' + d]), scale ** 2))
|
|
error = abs(projections['full'] - projections['shape'] - projections['fields'] - projections['mixed'])
|
|
check(label + 'projection_identity', error <= 2048 * EPS * scale ** 2 + 1e-28 and math.isfinite(float(row['projection_identity_error'])) and abs(float(row['projection_identity_error'])) <= 2048*EPS*scale**2+1e-28)
|
|
identity = norm(data[('full',path)]['trial'][start:start+size])**2 - norm(prediction)**2 - 2*(projections['shape']+projections['fields']+projections['mixed']) - norm(remainders['full'])**2
|
|
check(label+'full_merit_identity',abs(identity)<=2048*EPS*scale**2+1e-28 and math.isfinite(float(row['norm_identity_error'])) and abs(float(row['norm_identity_error']))<=2048*EPS*scale**2+1e-28)
|
|
validate_summary(summary, check)
|
|
for obs in observations:
|
|
if obs['path'] == 'curvature': obs['floor'] += float(pm[(obs['sample'], obs['direction'], obs['path'])]['gravity_arithmetic_allowance'])
|
|
passed = all(r['passed'] for r in checks)
|
|
return sanitize({'passed': passed, 'checks': checks, 'observations_valid': passed, 'required_artifacts': sorted(required),
|
|
'metadata': meta, 'summary': summary, 'direction_quality': {'raw_linear_gate': gate, 'backend_converged': converged,
|
|
'verified_relative_defect': defect / rhs_norm, 'passed': gate and converged}, 'paths': outcomes, 'shape_fields_action_cancellation': cancellation,
|
|
'preparation_failures':[r for r in rows(folder/(P+'preparations.csv')) if r['prepared']=='0'],
|
|
'gravity_assessment_scope':'Saved trial vectors independently verify the affine-target defect, not the underlying gravity action used by the reported affine-disagreement allowance. Actual gravity residual norms are reported separately.',
|
|
'vector_order_observations': vector_orders(observations, gate and converged) if passed else [],
|
|
'scope': 'Artifact validity is separate from linear convergence, nonlinear improvement, admissibility and physical validation.',
|
|
'order_scope': 'Orders require usable paths, finite verified J actions, resolved increments and vector remainders exceeding10 times the heuristic floor. Floor=max(8 times maximum restoration drift,128eps times(1+residual/action scales))+gravity arithmetic allowance for corrected paths. Normalized block norms use the configured diagonal Riesz factors, not exact physical L2. Noninteger superlinear order can be consistent with the EOS; derivative-error decline is reported without an order-two pass requirement. Failed outer forcing gates do not invalidate directional Taylor measurements; they preclude Newton-forcing comparisons and eta-based descent guarantees. This is not a certified assembly bound or universal order claim.'})
|
|
|
|
|
|
def validate_summary(summary, check):
|
|
ones = {'accepted_buffers_bitwise_identical','normalization_factors_bitwise_identical',
|
|
'roundoff_scale_is_subtraction_heuristic','path_seconds_include_shared_raw_preparation'}
|
|
zeroes = {'accepted_state_change','accepted_residual_change','accepted_physical_change',
|
|
'accepted_commits','polynomial_direction_repairs','linear_gate_failure_skips_trials'}
|
|
check('required_summary_invariants', ones | zeroes | {'maximum_original_restoration_error','maximum_restored_action_difference'} <= summary.keys())
|
|
for key in ones: check(key,summary.get(key)==1)
|
|
for key in zeroes: check(key,summary.get(key)==0)
|
|
check('supported_schema',summary.get('schema_version')==1 and summary.get('machine_epsilon')==EPS)
|
|
|
|
|
|
def validate_restoration(folder, summary, f, actions, layouts, check):
|
|
restored = vector(folder/(P+'restored_residual.txt'))
|
|
difference = norm(minus(restored,f))
|
|
records = rows(folder/(P+'restorations.csv'))
|
|
grouped = {}
|
|
for row in records: grouped.setdefault((row['sequence'],row['kind']),[]).append(row)
|
|
maximum = 0.0
|
|
for key,group in grouped.items():
|
|
by_block = {r['block']:r for r in group}
|
|
check('restoration:'+str(key)+':complete_blocks',len(by_block)==len(group) and set(by_block)==set(layouts))
|
|
for block,(start,size) in layouts.items():
|
|
row=by_block[block]
|
|
check('restoration:'+str(key)+':'+block, int(row['offset'])==start and int(row['size'])==size and close(float(row['base_norm']),norm(f[start:start+size])) and nonnegative(float(row['difference_norm'])))
|
|
block_norm = norm(float(by_block[b]['difference_norm']) for b in layouts if b!='all')
|
|
check('restoration:'+str(key)+':norm_partition',close(block_norm,float(by_block['all']['difference_norm']),norm(f)))
|
|
maximum=max(maximum,float(by_block['all']['difference_norm']))
|
|
check('restoration_records_present',bool(grouped))
|
|
check('maximum_restoration_recorded',close(maximum,summary['maximum_original_restoration_error'],norm(f)))
|
|
check('final_residual_restored',difference<=maximum+512*EPS*norm(f)+1e-28)
|
|
changes=[]
|
|
for d in DIRECTIONS:
|
|
final=vector(folder/(P+'restored_action_'+d+'.txt'))
|
|
changes.append(norm(minus(final,actions[d])))
|
|
check('maximum_action_change_recorded',close(max(changes),summary['maximum_restored_action_difference'],max(map(norm,actions.values()))))
|
|
# Restoration may be nonzero roundoff, but cannot be arbitrarily large and
|
|
# still certify that these finite differences use one frozen operator.
|
|
check('base_restoration_small',maximum<=2048*EPS*(1+norm(f)))
|
|
check('action_restoration_small',max(changes)<=2048*EPS*(1+max(map(norm,actions.values()))))
|
|
return maximum
|
|
|
|
|
|
def validate_work(folder, summary, linear, inner, paths, check):
|
|
preparations=rows(folder/(P+'preparations.csv'))
|
|
check('preparation_count',len(preparations)==summary['preparations'])
|
|
check('preparation_sequence', [int(r['sequence']) for r in preparations]==list(range(1,len(preparations)+1)))
|
|
check('preparation_times',all(nonnegative(float(r['seconds'])) for r in preparations))
|
|
check('preparation_total_time',close(math.fsum(float(r['seconds']) for r in preparations),summary['preparation_seconds']))
|
|
check('prepared_path_count',sum(r['prepared']=='1' for r in paths)==summary['prepared_paths'])
|
|
for direction in DIRECTIONS:
|
|
for path in PATHS:
|
|
calls=[r for r in preparations if r['kind']==path and r['direction']==direction]
|
|
wanted=[r for r in paths if r['path']==path and r['direction']==direction and (path=='raw' or r['inner_converged']=='1')]
|
|
check(direction+':'+path+':preparation_coverage',len(calls)==len(wanted) and {(float(r['alpha']),r['prepared']) for r in calls}=={(float(r['alpha']),r['prepared']) for r in wanted})
|
|
check('gravity_solve_count',len(inner)==summary['gravity_solves'])
|
|
check('gravity_iteration_total',sum(int(r['iterations']) for r in inner)==summary['gravity_iterations'])
|
|
check('gravity_failure_count',sum(r['converged']!='1' for r in inner)==summary['gravity_failures'])
|
|
check('gravity_solve_time',close(math.fsum(float(r['seconds']) for r in inner),summary['gravity_solve_seconds']))
|
|
check('linear_time_matches',close(float(linear['seconds']),summary['linear_solve_seconds']))
|
|
# Raw and corrected path timers overlap; do not add them to form a cost.
|
|
check('total_time_scope',nonnegative(summary['total_seconds']) and summary['total_seconds']+1e-6>=summary['preparation_seconds']+summary['linear_solve_seconds']+summary['gravity_solve_seconds'])
|
|
|
|
|
|
def inspect_campaign(campaign):
|
|
campaign, checks, results = Path(campaign).resolve(), [], {}
|
|
def check(name, passed): checks.append({'check': name, 'passed': bool(passed)})
|
|
try:
|
|
provenance = json.loads((campaign / 'provenance.json').read_text())
|
|
check('immutable_executable', digest(campaign / 'plateau_diagnostic') == provenance['binary_sha256'])
|
|
check('mesh_hash', digest(Path(provenance['mesh'])) == provenance['mesh_sha256'])
|
|
cases = provenance['cases']
|
|
check('unique_nonempty_cases', bool(cases) and len(cases) == len({c['id'] for c in cases}))
|
|
check('manifest_snapshot', json.loads((campaign / 'cases.json').read_text()) == cases)
|
|
for case in cases:
|
|
name = case['id']; folder = campaign / name
|
|
record = json.loads((campaign / (name + '_run.json')).read_text())
|
|
check(name + ':completed', bool(record.get('finished_utc')) and record.get('exit_code') == 0 and not record.get('timed_out', False))
|
|
args = case['arguments']
|
|
command = [str(campaign / 'plateau_diagnostic'), *args, '--mesh', provenance['mesh'], '--output', str(folder)]
|
|
check(name + ':command', record.get('command') == command and record.get('id') == name)
|
|
expected = set()
|
|
for i, arg in enumerate(args):
|
|
if arg == '--probe-state':
|
|
p = Path(args[i + 1]); p = p if p.is_absolute() else Path(provenance['source']) / p
|
|
expected.add(str(p.resolve()))
|
|
check(name + ':required_input_hashes', expected <= record.get('input_state_hashes', {}).keys())
|
|
for p, value in record.get('input_state_hashes', {}).items(): check(name + ':input:' + p, digest(Path(p)) == value)
|
|
for p, value in record.get('output_hashes', {}).items(): check(name + ':output:' + p, digest(folder / p) == value)
|
|
result = inspect_case(folder)
|
|
check(name + ':required_output_hashes', set(result['required_artifacts']) <= record.get('output_hashes', {}).keys())
|
|
bindings={'--linear-tol':'linear_tol','--max-linear':'max_linear','--restart':'restart',
|
|
'--index':'n','--angular-momentum':'J','--gravity-tol':'gravity_tolerance',
|
|
'--gravity-iterations':'gravity_iterations','--gravity-restart':'gravity_restart',
|
|
'--schur-sweeps':'context_gravity_schur_sweeps','--schur-relaxation':'context_gravity_schur_relaxation'}
|
|
metadata=result.get('metadata',{})
|
|
check(name+':expert_probe_selected','--nonlinear-step-probe' in args and metadata.get('nonlinear_step_probe')=='1')
|
|
for option,key in bindings.items():
|
|
if option in args:check(name+':requested_'+key,key in metadata and float(metadata[key])==float(args[args.index(option)+1]))
|
|
if '--preconditioner-variant' in args:check(name+':requested_inverse',metadata.get('context_preconditioner_variant')==args[args.index('--preconditioner-variant')+1])
|
|
if '--no-central' in args:check(name+':no_central_constraint',metadata.get('central_phase')=='0')
|
|
results[name] = result
|
|
passed = all(c['passed'] for c in checks) and all(r['passed'] for r in results.values())
|
|
if not all(c['passed'] for c in checks):
|
|
for r in results.values(): r.update(passed=False, observations_valid=False, vector_order_observations=[])
|
|
return {'passed': passed, 'source_commit': provenance['commit'], 'provenance_sha256': digest(campaign / 'provenance.json'),
|
|
'checker_sha256': digest(Path(__file__)), 'provenance_checks': checks, 'cases': results,
|
|
'scope': 'Independent vector/provenance audit. A failed numerical gate is a valid observation, not a successful model.'}
|
|
except (OSError, ValueError, KeyError, TypeError, IndexError) as error:
|
|
for r in results.values(): r.update(passed=False, observations_valid=False, vector_order_observations=[])
|
|
return {'passed': False, 'provenance_checks': checks + [{'check': 'complete_readable_campaign', 'passed': False, 'error': str(error)}], 'cases': results}
|
|
|
|
|
|
def compare_same_state(left_folder, left_review, right_folder, right_review):
|
|
"""Compare sampled directions only after caller-provided artifact audits.
|
|
|
|
A small action of their difference is evidence about this one sampled
|
|
response. It is neither a nullspace construction nor a condition estimate.
|
|
"""
|
|
left_folder,right_folder=Path(left_folder),Path(right_folder)
|
|
names=('physical_base','normalized_base','residual','rhs','state_factors','residual_factors')
|
|
identity={name:digest(left_folder/(P+name+'.txt'))==digest(right_folder/(P+name+'.txt')) for name in names}
|
|
identity['layout']=digest(left_folder/(P+'layout.csv'))==digest(right_folder/(P+'layout.csv'))
|
|
available=left_review['passed'] and right_review['passed'] and all(identity.values())
|
|
result={'available':available,'same_input_hashes':identity,
|
|
'eligible_for_newton_forcing_comparison':available and left_review.get('direction_quality',{}).get('passed',False) and right_review.get('direction_quality',{}).get('passed',False),
|
|
'scope':'w=p_right-p_left and Jw=action_right-action_left use identical saved state/RHS/factors/layout. One sampled weak response is not proof of a nullspace, gauge or condition number. Norms use diagonal normalization, not exact physical L2.'}
|
|
if not available:return result
|
|
pa,pb=(vector(folder/(P+'direction_full.txt')) for folder in (left_folder,right_folder))
|
|
ja,jb=(vector(folder/(P+'action_full.txt')) for folder in (left_folder,right_folder))
|
|
w,jw=minus(pb,pa),minus(jb,ja)
|
|
result['direction_difference_norm']=norm(w);result['action_difference_norm']=norm(jw)
|
|
result['sampled_action_over_direction_difference']=norm(jw)/norm(w) if norm(w)>0 else None
|
|
result['direction_cosine']=dot(pa,pb)/(norm(pa)*norm(pb)) if norm(pa)*norm(pb)>0 else None
|
|
result['differences_by_block']={}
|
|
layout=rows(left_folder/(P+'layout.csv'))
|
|
for kind,values in [('value',w),('residual',jw)]:
|
|
partition=layout_for(layout,kind,len(values))
|
|
result['differences_by_block'][kind]={block:norm(values[start:start+size]) for block,(start,size) in partition.items()}
|
|
return result
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument('campaign', type=Path)
|
|
parser.add_argument('--output', type=Path, required=True)
|
|
args = parser.parse_args()
|
|
if args.campaign.resolve() in args.output.resolve().parents:
|
|
parser.error('Write the review outside the immutable campaign.')
|
|
result = inspect_campaign(args.campaign)
|
|
args.output.write_text(json.dumps(result, indent=2, allow_nan=False) + '\n')
|
|
print('PASS' if result['passed'] else 'FAIL', args.output)
|
|
for name, case in result['cases'].items(): print(name, 'artifacts=', case['passed'], 'raw_linear=', case.get('direction_quality', {}).get('raw_linear_gate'))
|
|
return 0 if result['passed'] else 1
|
|
|
|
|
|
if __name__ == '__main__':
|
|
raise SystemExit(main())
|