gaussian_test.go raw
1 package crypto
2
3 import (
4 "testing"
5
6 "git.mleku.dev/mleku/dendrite/pkg/axiom"
7 "git.mleku.dev/mleku/dendrite/pkg/lattice"
8 "git.mleku.dev/mleku/dendrite/pkg/ratio"
9 )
10
11 type testElem struct {
12 tag string
13 val string
14 }
15
16 func (e testElem) Type() string { return e.tag }
17 func (e testElem) Value() any { return e.val }
18
19 func buildBondedLattice(n int) *lattice.Lattice {
20 l := lattice.New()
21 nodes := make([]*lattice.Node, n)
22 for i := range nodes {
23 nodes[i] = l.AddNode([]axiom.Constraint{tagConstraint{"word"}})
24 }
25 // Ring topology.
26 for i := range nodes {
27 l.Connect(nodes[i], nodes[(i+1)%len(nodes)])
28 }
29 // Bond half the nodes.
30 for i := 0; i < n/2; i++ {
31 nodes[i].Bond(testElem{"word", string(rune('a' + i))})
32 }
33 return l
34 }
35
36 func TestNewSampler(t *testing.T) {
37 l := buildBondedLattice(20)
38 gs := NewSampler(l, ratio.New(4, 10))
39
40 if gs.Lattice != l {
41 t.Error("sampler should reference the lattice")
42 }
43 if !gs.Threshold.Equal(ratio.New(4, 10)) {
44 t.Errorf("threshold = %s, want 4/10", gs.Threshold)
45 }
46 }
47
48 func TestSampleReturnsPattern(t *testing.T) {
49 l := buildBondedLattice(20)
50 gs := NewSampler(l, ratio.New(4, 10))
51
52 marks := gs.Sample()
53 if len(marks) != l.Size() {
54 t.Errorf("sample length = %d, want %d", len(marks), l.Size())
55 }
56
57 // At least some should be occupied (high lock-in survivors).
58 occupied := 0
59 for _, m := range marks {
60 if m.Occupied {
61 occupied++
62 }
63 }
64 // We bonded 10 of 20 nodes. With ring topology each bonded node
65 // has ~1 bonded neighbor out of 2, giving contextual lock-in of
66 // 0.3 + 0.7*(1/2) = 0.65 > 0.4 threshold. Most should survive.
67 if occupied == 0 {
68 t.Error("expected at least some occupied sites after sampling")
69 }
70 }
71
72 func TestNoiseVectorLength(t *testing.T) {
73 l := buildBondedLattice(16)
74 gs := NewSampler(l, ratio.New(8, 10)) // high threshold = more dissolution
75
76 vec, _ := gs.NoiseVector()
77 if len(vec) != l.Size() {
78 t.Errorf("noise vector length = %d, want %d", len(vec), l.Size())
79 }
80 }
81
82 func TestSnapshotConsistency(t *testing.T) {
83 l := buildBondedLattice(10)
84 s1 := snapshot(l)
85 s2 := snapshot(l)
86
87 if len(s1) != len(s2) {
88 t.Fatal("snapshots should have same length")
89 }
90 for i := range s1 {
91 if s1[i].Occupied != s2[i].Occupied {
92 t.Errorf("site %d occupancy mismatch", i)
93 }
94 if s1[i].TypeTag != s2[i].TypeTag {
95 t.Errorf("site %d type tag mismatch", i)
96 }
97 }
98 }
99