AUREOLE-R-v3 / tests /test_innovation.py
PureOne's picture
AUREOLE-R 3.0.0-hf.1: standalone public research release
9d6c005 verified
Raw
History Blame Contribute Delete
7.46 kB
import unittest,itertools,tempfile
from pathlib import Path
import numpy as np
from aureole.certificates import CertificateMemory,visibility_certificate,enclosure
from aureole.innovation import prepare,eliminate,exact_risk_two,covariance
from aureole.renderer import Scene,receiver_grid,light_grid
class InnovationTests(unittest.TestCase):
def test_covariance_contraction_all_readouts(self):
rng=np.random.default_rng(121)
for _ in range(200):
q=rng.dirichlet(np.ones(9));r=rng.normal(size=(9,5))
a=np.arange(3);u=np.arange(3,9);mass=q[a].sum()
old=covariance(r,q)
new=covariance(r[u],q[u]/(1-mass))
self.assertGreaterEqual(np.linalg.eigvalsh((1-mass)*old-new).min(),-1e-10)
def test_exact_two_draw_enumeration(self):
rng=np.random.default_rng(12)
for k in (3,4,6):
q=rng.dirichlet(np.ones(k));f=rng.uniform(size=(k,3));h=rng.normal(size=(k,3))
outcomes=[];weights=[]
for a,b in itertools.permutations(range(k),2):
y1=h.sum(0)+(f[a]-h[a])/q[a]
h2=h.copy();h2[a]=f[a]
y2=h2.sum(0)+(f[b]-h2[b])/(q[b]/(1-q[a]))
outcomes.append((y1+y2)/2);weights.append(q[a]*q[b]/(1-q[a]))
outcomes=np.array(outcomes);weights=np.array(weights)
np.testing.assert_allclose(weights@outcomes,f.sum(0),atol=1e-12)
risk=np.sum(weights[:,None]*(outcomes-f.sum(0))**2)/3
self.assertAlmostEqual(risk,exact_risk_two(f[None],h[None],q[None])[0],places=11)
def test_exact_completion_fixed_budget(self):
f=np.arange(9,dtype=float).reshape(1,3,3)
used=[]
def oracle(rows,j):used.extend(j.tolist());return f[rows,j]
y,_=eliminate(np.zeros_like(f),np.full((1,3),1/3),oracle,3,np.random.default_rng(3))
np.testing.assert_array_equal(y,f.sum(1));self.assertEqual(len(set(used)),3)
def test_no_rays_on_complete_state(self):
h=np.ones((4,3,2))
def oracle(*args):raise AssertionError('Should not trace')
y,steps=eliminate(h,np.zeros((4,3)),oracle,2,np.random.default_rng(3))
np.testing.assert_array_equal(y,h.sum(1));self.assertEqual(steps,[])
def test_false_zero_support_rejected_by_audit(self):
with self.assertRaises(ValueError):exact_risk_two(np.ones((1,3,1)),np.zeros((1,3,1)),np.array([[.5,.5,0]]))
def test_upper_uniform_endpoint_never_selects_zero_support(self):
class UpperRng:
def random(self,n):return np.full(n,np.nextafter(1.0,0.0))
q=np.zeros((1000,7));q[:,:5]=np.random.default_rng(41).dirichlet(np.ones(5),size=1000)
def oracle(rows,j):
self.assertTrue(np.all(j<5));return np.ones((len(rows),1))
result,steps=eliminate(np.zeros((1000,7,1)),q,oracle,2,UpperRng())
self.assertTrue(np.isfinite(result).all())
self.assertTrue(np.all(steps[0][1]!=steps[1][1]))
def test_known_only_control_and_support(self):
b=np.ones((1,4,3));v=np.array([[0.,1.,0.,0.]])
h,q=prepare(b,np.full((1,4),.6),v,np.array([[True,True,False,False]]),np.ones((1,4)))
np.testing.assert_array_equal(q,[[0,0,.5,.5]])
np.testing.assert_allclose(h[0,:,0],[0,1,.6,.6])
def test_invalid_budget_and_proposal(self):
with self.assertRaises(ValueError):eliminate(np.ones((1,3,1)),np.full((1,3),1/3),lambda *x:None,True,np.random.default_rng())
with self.assertRaises(ValueError):eliminate(np.ones((1,3,1)),np.array([[0,.1,.1]]),lambda *x:None,1,np.random.default_rng())
def test_float_oracle_matches_independent_quadratic(self):
rng=np.random.default_rng(987)
for sid in range(800,820):
scene=Scene.create(sid)
p=rng.uniform([-1,-1,0],[1,1,0],(200,3));l=rng.uniform([-.9,-.9,2.2],[.9,.9,2.2],(200,3))
v,_=visibility_certificate(scene,p,l)
np.testing.assert_array_equal(v,scene.visibility(p,l))
def test_moving_and_spatial_certificates_no_false_acceptance(self):
rng=np.random.default_rng(982)
for sid in range(820,830):
scene=Scene.create(sid);p=receiver_grid(8,12);l=light_grid(4)
mem=CertificateMemory(p,l,scene.spheres)
ids=np.repeat(np.arange(len(p)),len(l));j=np.tile(np.arange(len(l)),len(p))
v,m=visibility_certificate(scene,p[ids],l[j]);mem.commit(ids,j,v,m)
for _ in range(12):
g=scene.spheres.copy();g[:,:3]+=rng.uniform(-.035,.035,(3,3));g[:,3]*=rng.uniform(.96,1.04,3)
moved=Scene(sid,g);mem.begin_geometry(g)
query=p+rng.uniform(-.012,.012,p.shape);query[:,2]=0
values,known=mem.lookup(np.arange(len(p)),query)
truth=moved.visibility(query[:,None,:],l[None,:,:])
self.assertTrue(np.all(values[known]==truth[known]))
def test_unreported_motion_is_not_protected(self):
scene=Scene.create(833);p=receiver_grid(16,20);l=light_grid(6)
mem=CertificateMemory(p,l,scene.spheres)
ids=np.repeat(np.arange(len(p)),len(l));j=np.tile(np.arange(len(l)),len(p))
v,m=visibility_certificate(scene,p[ids],l[j]);mem.commit(ids,j,v,m)
values,known=mem.lookup(np.arange(len(p)))
changed=scene.changed().visibility(p[:,None,:],l[None,:,:])
self.assertGreater(np.count_nonzero(known & (values!=changed)),0)
def test_epoch_resets_while_margin_can_survive(self):
s=Scene.create(20);p=receiver_grid(4,5);l=light_grid(2)
a=CertificateMemory(p,l,s.spheres);b=CertificateMemory(p,l,s.spheres,mode='epoch')
ids=np.arange(len(p));j=np.zeros(len(p),int);v,m=visibility_certificate(s,p,l[j])
for mem in (a,b):mem.commit(ids,j,v,m)
g=s.spheres.copy();g[0,0]+=1e-7
for mem in (a,b):mem.begin_geometry(g)
self.assertGreater(a.lookup(ids)[1].sum(),0);self.assertEqual(b.lookup(ids)[1].sum(),0)
def test_enclosure_covers_all_binary_completions(self):
b=np.arange(1,10,dtype=float).reshape(1,3,3);v=np.array([[1.,0.,0.]]);known=np.array([[True,False,False]])
lo,hi=enclosure(b,v,known)
for a,c in itertools.product((0,1),repeat=2):
y=(b*np.array([1,a,c])[None,:,None]).sum(1)
self.assertTrue((y>=lo).all() and (y<=hi).all())
def test_roundtrip_and_namespace(self):
s=Scene.create(31);p=receiver_grid(3,4);l=light_grid(2)
a=CertificateMemory(p,l,s.spheres,'alpha');ids=np.arange(len(p));j=np.zeros(len(p),int)
v,m=visibility_certificate(s,p,l[j]);a.commit(ids,j,v,m)
with tempfile.TemporaryDirectory() as d:
path=Path(d)/'memory.npz';a.save(path);b=CertificateMemory.load(path,'alpha')
np.testing.assert_array_equal(a.lookup(ids)[1],b.lookup(ids)[1])
with self.assertRaises(ValueError):CertificateMemory.load(path,'beta')
def test_motion_budget_is_conservative_on_return(self):
s=Scene.create(12);a=CertificateMemory(receiver_grid(2,2),light_grid(2),s.spheres)
g=s.spheres.copy();g[0,0]+=.2;a.begin_geometry(g);a.begin_geometry(s.spheres)
self.assertGreaterEqual(a.budget,.4-1e-14)
def test_readout_cross_covariance_is_psd(self):
rng=np.random.default_rng(22);r=rng.normal(size=(7,12));q=rng.dirichlet(np.ones(7))
self.assertGreaterEqual(np.linalg.eigvalsh(covariance(r,q)).min(),-1e-10)
if __name__=='__main__':unittest.main()