baseline: the published sim-numerics artifact as it stands (490 tests, verify_article.py checks all 72 paper numbers against sweep_full.json)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
"""The similarity family for the NLMS step size, and what it settled.
|
||||
|
||||
Two corrections came from outside and both were right:
|
||||
|
||||
1. mu should be a SIMILARITY, not a variance estimate. The filter can only
|
||||
remove what correlates with its input, so the quantity is the cosine
|
||||
between the error and the filtered reference. It beats the variance
|
||||
formulation on eleven of twelve cells.
|
||||
|
||||
2. Testing one similarity function is as incomplete here as it would have
|
||||
been in the root-finding work. The whole family must be run, and when it
|
||||
is, the best member is not the cosine.
|
||||
|
||||
And the law of the first domain - that the slope of (1 - S) at the origin
|
||||
decides, not the shape of S - orders this family too, monotonically and
|
||||
without exception. That is a prediction made in one domain and confirmed in
|
||||
another.
|
||||
|
||||
What it did not settle: even the best member loses to a constant tuned per
|
||||
scenario, on all twelve cells.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
import os
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from anc.rules import CosineSimilarity, Fixed, Measured
|
||||
from simroot.pure import PURE_SIMS
|
||||
from stage20_prediction import FLAT_15, FLAT_30, STEP_25, sig_cabin, sig_tonal, \
|
||||
score
|
||||
|
||||
SEEDS = 3
|
||||
CELLS = [(sig_tonal, FLAT_30), (sig_tonal, STEP_25),
|
||||
(sig_cabin, FLAT_15), (sig_cabin, STEP_25)]
|
||||
|
||||
|
||||
def make(name):
|
||||
r = CosineSimilarity()
|
||||
r.S = None if name is None else PURE_SIMS[name]
|
||||
return r
|
||||
|
||||
|
||||
def mean(rule):
|
||||
vals = [score(rule, gen, prof, seeds=SEEDS) for gen, prof in CELLS]
|
||||
return sum(vals) / len(vals)
|
||||
|
||||
|
||||
def test_the_similarity_formulation_beats_the_variance_one():
|
||||
"""Correction 1. mu as 'how much of the error resembles what the filter
|
||||
can remove' against mu as 'one minus the noise-power fraction'.
|
||||
|
||||
Stated carefully, because the first version of this test was not: what
|
||||
beats the variance rule on eleven of twelve cells is the best member of
|
||||
the FAMILY, not the raw cosine. The raw cosine can lose to it - on this
|
||||
subset it does, 14.04 against 14.32 - which is precisely why correction 2
|
||||
(run the whole family) was needed before the claim could be made at all.
|
||||
"""
|
||||
best_member = max(mean(make(n)) for n in (None, "ratio", "exp_abs",
|
||||
"rational", "ratio_soft",
|
||||
"sqrt", "cbrt"))
|
||||
assert best_member > mean(Measured()), best_member
|
||||
|
||||
|
||||
def test_the_raw_cosine_is_not_the_best_member():
|
||||
"""Correction 2. A single member is not the family: the identity
|
||||
S(d) = 1 - d is beaten by members with a steeper approach to 1."""
|
||||
raw = mean(make(None))
|
||||
best = max(mean(make(n)) for n in ("sqrt", "cbrt", "ratio_soft"))
|
||||
assert best > raw, (best, raw)
|
||||
|
||||
|
||||
def test_two_code_paths_for_the_same_function_agree():
|
||||
"""S = None takes mu = |cos| directly; S = ratio computes
|
||||
max(0, 1 - d) with d = 1 - |cos|. They are the same function on [0,1]
|
||||
and reach it by different code, so they must score identically."""
|
||||
a = mean(make(None))
|
||||
b = mean(make("ratio"))
|
||||
assert abs(a - b) < 1e-9, (a, b)
|
||||
|
||||
|
||||
def test_the_law_of_the_first_domain_orders_this_family_too():
|
||||
"""The prediction carried across domains: slope of (1 - S) at 0 decides.
|
||||
Every slope-1 member must beat every slope-0 member."""
|
||||
slope1 = [mean(make(n)) for n in ("ratio", "exp_abs", "rational")]
|
||||
slope0 = [mean(make(n)) for n in ("rat_sq", "exp_sq", "cosine")]
|
||||
assert min(slope1) > max(slope0), (slope1, slope0)
|
||||
|
||||
|
||||
def test_and_it_still_loses_to_a_tuned_constant():
|
||||
"""The half that did not work, pinned so the claim is never overstated.
|
||||
The competitor knows the scenario; no deployable controller does - and it
|
||||
is still ahead."""
|
||||
losses = 0
|
||||
for gen, prof in CELLS:
|
||||
best_member = max(score(make(n), gen, prof, seeds=SEEDS)
|
||||
for n in (None, "cbrt", "sqrt", "ratio"))
|
||||
oracle = max(score(Fixed(mu), gen, prof, seeds=SEEDS)
|
||||
for mu in (0.05, 0.1, 0.2, 0.5, 1.0))
|
||||
losses += best_member < oracle
|
||||
assert losses == len(CELLS), losses
|
||||
Reference in New Issue
Block a user