@@ -698,4 +698,151 @@ mod tests {
698698 // If Δ ≈ 0 → golden step is the 52°N problem.
699699 // If Δ > 0.05 → golden step captures real structure.
700700 }
701+ #[ test]
702+ #[ ignore] // Requires /tmp/tiny_imagenet_200.json (run with --include-ignored)
703+ fn test_bgz17_on_tiny_imagenet ( ) {
704+ // Load real image feature vectors from tiny-imagenet (binary format).
705+ // Generate with: python3 script that saves [d:u32][n:u32][f32 × d × n]
706+ let bytes = match std:: fs:: read ( "/tmp/tiny_imagenet_200.bin" ) {
707+ Ok ( b) => b,
708+ Err ( _) => {
709+ eprintln ! ( "SKIP: /tmp/tiny_imagenet_200.bin not found" ) ;
710+ return ;
711+ }
712+ } ;
713+
714+ let d = u32:: from_le_bytes ( [ bytes[ 0 ] , bytes[ 1 ] , bytes[ 2 ] , bytes[ 3 ] ] ) as usize ;
715+ let n = u32:: from_le_bytes ( [ bytes[ 4 ] , bytes[ 5 ] , bytes[ 6 ] , bytes[ 7 ] ] ) as usize ;
716+
717+ let mut vectors: Vec < Vec < f64 > > = Vec :: with_capacity ( n) ;
718+ let float_data = & bytes[ 8 ..] ;
719+ for i in 0 ..n {
720+ let v: Vec < f64 > = ( 0 ..d)
721+ . map ( |j| {
722+ let off = ( i * d + j) * 4 ;
723+ f32:: from_le_bytes ( [ float_data[ off] , float_data[ off+1 ] , float_data[ off+2 ] , float_data[ off+3 ] ] ) as f64
724+ } )
725+ . collect ( ) ;
726+ vectors. push ( v) ;
727+ }
728+
729+ let n = vectors. len ( ) ;
730+ eprintln ! ( "Loaded {} vectors of dim {} from tiny-imagenet" , n, d) ;
731+ assert ! ( n >= 50 , "Need at least 50 vectors" ) ;
732+
733+ // Use first 100 for speed
734+ let n = n. min ( 100 ) ;
735+ let vectors = & vectors[ ..n] ;
736+
737+ let base_dim = 17 ;
738+ let golden_step = 11 ;
739+
740+ // Ground truth: pairwise L2 distances
741+ let mut gt_distances = Vec :: new ( ) ;
742+ for i in 0 ..n {
743+ for j in ( i+1 ) ..n {
744+ let dist: f64 = vectors[ i] . iter ( ) . zip ( & vectors[ j] )
745+ . map ( |( a, b) | ( a - b) * ( a - b) )
746+ . sum :: < f64 > ( )
747+ . sqrt ( ) ;
748+ gt_distances. push ( dist) ;
749+ }
750+ }
751+
752+ // Golden-step projection
753+ let golden_projected: Vec < Vec < f64 > > = vectors. iter ( )
754+ . map ( |v| {
755+ let n_octaves = ( d + base_dim - 1 ) / base_dim;
756+ let mut sum = vec ! [ 0.0f64 ; base_dim] ;
757+ let mut count = vec ! [ 0u32 ; base_dim] ;
758+ for octave in 0 ..n_octaves {
759+ for bi in 0 ..base_dim {
760+ let dim = octave * base_dim + ( ( bi * golden_step) % base_dim) ;
761+ if dim < d { sum[ bi] += v[ dim] ; count[ bi] += 1 ; }
762+ }
763+ }
764+ sum. iter ( ) . zip ( & count) . map ( |( & s, & c) | if c > 0 { s / c as f64 } else { 0.0 } ) . collect ( )
765+ } )
766+ . collect ( ) ;
767+
768+ // Random projection
769+ let random_matrix: Vec < Vec < f64 > > = ( 0 ..base_dim)
770+ . map ( |i| ( 0 ..d) . map ( |j| ( ( i * 7919 + j * 104729 ) as f64 * 0.00001 ) . sin ( ) ) . collect ( ) )
771+ . collect ( ) ;
772+ let random_projected: Vec < Vec < f64 > > = vectors. iter ( )
773+ . map ( |v| random_matrix. iter ( ) . map ( |row| row. iter ( ) . zip ( v) . map ( |( r, x) | r * x) . sum :: < f64 > ( ) ) . collect ( ) )
774+ . collect ( ) ;
775+
776+ // Simple mean projection (average every 17 consecutive dims)
777+ let mean_projected: Vec < Vec < f64 > > = vectors. iter ( )
778+ . map ( |v| {
779+ ( 0 ..base_dim) . map ( |bi| {
780+ let chunk: Vec < f64 > = ( bi..d) . step_by ( base_dim) . map ( |i| v[ i] ) . collect ( ) ;
781+ if chunk. is_empty ( ) { 0.0 } else { chunk. iter ( ) . sum :: < f64 > ( ) / chunk. len ( ) as f64 }
782+ } ) . collect ( )
783+ } )
784+ . collect ( ) ;
785+
786+ // Compute projected distances
787+ fn pairwise_l2 ( proj : & [ Vec < f64 > ] ) -> Vec < f64 > {
788+ let n = proj. len ( ) ;
789+ let mut dists = Vec :: new ( ) ;
790+ for i in 0 ..n { for j in ( i+1 ) ..n {
791+ let d: f64 = proj[ i] . iter ( ) . zip ( & proj[ j] ) . map ( |( a, b) | ( a-b) * ( a-b) ) . sum :: < f64 > ( ) . sqrt ( ) ;
792+ dists. push ( d) ;
793+ } }
794+ dists
795+ }
796+
797+ let golden_dists = pairwise_l2 ( & golden_projected) ;
798+ let random_dists = pairwise_l2 ( & random_projected) ;
799+ let mean_dists = pairwise_l2 ( & mean_projected) ;
800+
801+ // Spearman ρ
802+ fn spearman ( a : & [ f64 ] , b : & [ f64 ] ) -> f64 {
803+ fn ranks ( v : & [ f64 ] ) -> Vec < f64 > {
804+ let mut idx: Vec < ( usize , f64 ) > = v. iter ( ) . copied ( ) . enumerate ( ) . collect ( ) ;
805+ idx. sort_by ( |a, b| a. 1 . partial_cmp ( & b. 1 ) . unwrap ( ) ) ;
806+ let mut r = vec ! [ 0.0 ; v. len( ) ] ;
807+ for ( rank, ( i, _) ) in idx. into_iter ( ) . enumerate ( ) { r[ i] = rank as f64 ; }
808+ r
809+ }
810+ let ra = ranks ( a) ; let rb = ranks ( b) ;
811+ let n = a. len ( ) as f64 ;
812+ let ma: f64 = ra. iter ( ) . sum :: < f64 > ( ) / n;
813+ let mb: f64 = rb. iter ( ) . sum :: < f64 > ( ) / n;
814+ let ( mut cov, mut va, mut vb) = ( 0.0 , 0.0 , 0.0 ) ;
815+ for i in 0 ..a. len ( ) {
816+ let ( da, db) = ( ra[ i] - ma, rb[ i] - mb) ;
817+ cov += da * db; va += da * da; vb += db * db;
818+ }
819+ if va < 1e-10 || vb < 1e-10 { 0.0 } else { cov / ( va * vb) . sqrt ( ) }
820+ }
821+
822+ let rho_golden = spearman ( & gt_distances, & golden_dists) ;
823+ let rho_random = spearman ( & gt_distances, & random_dists) ;
824+ let rho_mean = spearman ( & gt_distances, & mean_dists) ;
825+
826+ eprintln ! ( "=== bgz17 on Tiny ImageNet (real pixel data) ===" ) ;
827+ eprintln ! ( " Golden-step 17D: ρ = {:.4}" , rho_golden) ;
828+ eprintln ! ( " Random 17D: ρ = {:.4}" , rho_random) ;
829+ eprintln ! ( " Mean-stride 17D: ρ = {:.4}" , rho_mean) ;
830+ eprintln ! ( " Δ golden-random: {:.4}" , rho_golden - rho_random) ;
831+ eprintln ! ( " Δ golden-mean: {:.4}" , rho_golden - rho_mean) ;
832+ eprintln ! ( ) ;
833+ if ( rho_golden - rho_random) . abs ( ) < 0.02 {
834+ eprintln ! ( " VERDICT: Golden-step ≈ random on pixel data (52°N problem)" ) ;
835+ eprintln ! ( " bgz17's value is NOT in the projection axes" ) ;
836+ eprintln ! ( " bgz17's value IS in the distance table + cascade infrastructure" ) ;
837+ } else if rho_golden > rho_random + 0.02 {
838+ eprintln ! ( " VERDICT: Golden-step > random! The Fibonacci structure captures something." ) ;
839+ } else {
840+ eprintln ! ( " VERDICT: Random > golden-step. Golden-step is WORSE for this data." ) ;
841+ }
842+
843+ // Basic sanity: golden-step should preserve reasonable ranking
844+ assert ! ( rho_golden > 0.3 , "golden ρ too low: {}" , rho_golden) ;
845+ // Random projection CAN be very low on structured data — that's expected
846+ assert ! ( rho_random > -0.5 , "random ρ impossibly low: {}" , rho_random) ;
847+ }
701848}
0 commit comments