"""前缀不变检测及三种不同的未来数据依赖。""" import json def causal(xs): return [int(i >= 2 and x > sum(xs[i - 2:i + 1]) / 3) for i, x in enumerate(xs)] def future_shift(xs): return [int(xs[i + 1] > x) if i + 1 < len(xs) else 0 for i, x in enumerate(xs)] def full_mean(xs): return [int(x > sum(xs) / len(xs)) for x in xs] def centered(xs): return [int(x > sum(xs[max(0, i - 1):i + 2]) / len(xs[max(0, i - 1):i + 2])) for i, x in enumerate(xs)] def repaired_future_shift(xs): return [int(i > 0 and x > xs[i - 1]) for i, x in enumerate(xs)] def repaired_full_mean(xs): return [int(x > sum(xs[:i + 1]) / (i + 1)) for i, x in enumerate(xs)] def repaired_centered(xs): return causal(xs) def failures(fn, xs): result = [] full = fn(xs) for cutoff in range(3, len(xs)): prefix = fn(xs[:cutoff]) changed = [i for i in range(cutoff) if prefix[i] != full[i]] if changed: result.append({'cutoff': cutoff, 'rows': changed}) return result xs = [10, 10, 10, 12, 1000, 1, 500] report = {fn.__name__: failures(fn, xs) for fn in [causal, future_shift, full_mean, centered]} assert not report['causal'] assert all(report[name] for name in ['future_shift', 'full_mean', 'centered']) mutated = xs[:4] + [13, 9, 8] assert causal(xs)[:4] == causal(mutated)[:4] assert full_mean(xs)[:4] != full_mean(mutated)[:4] repairs = {fn.__name__: failures(fn, xs) for fn in [repaired_future_shift, repaired_full_mean, repaired_centered]} assert all(not failed for failed in repairs.values()) for fn in [repaired_future_shift, repaired_full_mean, repaired_centered]: assert fn(xs)[:4] == fn(mutated)[:4] print(json.dumps({'prefix_failures': report, 'future_mutation_causal_equal': True, 'future_mutation_global_equal': False, 'repaired_prefix_failures': repairs}))