"""Meaningful algebraic/counterexample checks, independent of the benchmark data.""" import unittest import numpy as np from aureole_core import * class TheoryChecks(unittest.TestCase): def setUp(self): self.rng=np.random.default_rng(20260919) b=self.rng.normal(size=(7,7)); self.p=b@b.T+.2*np.eye(7) c=self.rng.normal(size=(5,7)); self.w=c.T@c self.h=self.rng.normal(size=7) def test_value_matches_direct_risk_reduction(self): _,p2=observe(np.zeros(7),self.p,self.h,2.,.6) self.assertAlmostEqual(risk(self.p,self.w)-risk(p2,self.w),query_value(self.p,self.w,self.h,.6),places=10) def test_update_psd_and_information_order(self): _,p2=observe(np.zeros(7),self.p,self.h,2.,.6) self.assertGreater(np.linalg.eigvalsh(p2).min(),0) self.assertGreater(np.linalg.eigvalsh(self.p-p2).min(),-1e-10) def test_batch_equals_sequential_independent_samples(self): h=self.rng.normal(size=(3,7)); r=np.diag([.2,.5,.7]); p=self.p.copy() for hi,ri in zip(h,np.diag(r)): _,p=observe(np.zeros(7),p,hi,0.,ri) np.testing.assert_allclose(p,batch_covariance(self.p,h,r),atol=1e-10) def test_task_additivity(self): w1=np.diag([1.,2.,3.,0.,0.,0.,0.]); w2=self.w self.assertAlmostEqual(query_value(self.p,w1+w2,self.h,.3),query_value(self.p,w1,self.h,.3)+query_value(self.p,w2,self.h,.3),places=10) def test_future_metric_matches_explicit_loss(self): a=self.rng.normal(size=(7,7))*.1; cs=[self.rng.normal(size=(4,7)) for _ in range(6)]; weights=.9**np.arange(6) w=future_metric(a,cs,weights); x=self.rng.normal(size=7); total=0.; z=x.copy() for c,weight in zip(cs,weights): total+=weight*np.linalg.norm(c@z)**2; z=a@z self.assertAlmostEqual(total,x@w@x,places=10) def test_transform_tail(self): for rank in [0,1,4,7]: u,e,p=transform_coding(self.p,self.w,rank) self.assertAlmostEqual(risk(p,self.w),sum(e[rank:]),places=9) def test_nuisance_query_expands_basis(self): u=closed_observation_basis([np.eye(2)],[[1,0],[1,1]]) self.assertEqual(u.shape[1],2) def test_dynamic_closure(self): a=np.array([[.9,1.,0.],[0,.8,0.],[0,0,.7]]) u=closed_observation_basis([a],[[1,0,0]]) self.assertEqual(u.shape[1],2) np.testing.assert_allclose((np.eye(3)-u@u.T)@a.T@u,0.,atol=1e-10) def test_projection_preserves_linear_future_channels(self): a=np.array([[.9,1.,0.],[0,.8,0.],[0,0,.7]]); c=np.array([[1.,0.,0.]]) u=closed_observation_basis([a],c); x=self.rng.normal(size=3); z=u.T@x for _ in range(15): np.testing.assert_allclose(c@x,c@u@z,atol=1e-9) x=a@x; z=u.T@a@u@z def test_sampling_not_generally_submodular(self): p=np.eye(2); w=np.diag([1.,0.]); h1=np.array([1.,1.]); h2=np.array([0.,1.]) _,p1=observe(np.zeros(2),p,h1,0,.1) self.assertEqual(query_value(p,w,h2,.1),0.) self.assertGreater(query_value(p1,w,h2,.1),.3) def test_optical_area_mixture_passive_reciprocal(self): ops=[] for _ in range(4): b=self.rng.random((6,6)); b=sym(b); b/=b.sum(0).max()*1.1; ops.append(b) k=area_mixture(np.array(ops),[.1,.2,.3,.4]) self.assertGreaterEqual(k.min(),0.); self.assertLessEqual(k.sum(0).max(),1.) np.testing.assert_allclose(k,k.T) def test_measurement_information_does_not_increase_while_absent(self): q=np.diag(np.linspace(.01,.07,7)); p2=self.p+500*q self.assertGreaterEqual(np.linalg.eigvalsh(p2-self.p).min(),0.) def test_forgetting_has_nonnegative_bayes_risk(self): _,posterior=observe(np.zeros(7),self.p,self.h,0.,.1) self.assertGreaterEqual(risk(self.p-posterior,self.w),-1e-10) def test_impossible_future_bit(self): # E[(B-a)^2] = 1+a^2, uniquely minimized at a=0. for a in [-2.,-.5,0.,.5,2.]: self.assertAlmostEqual(.5*(1-a)**2+.5*(-1-a)**2,1+a*a) if __name__=="__main__": unittest.main(verbosity=2)