2025-08-26 12:32:21 -07:00
import { describe , it , expect , beforeEach , afterEach } from 'vitest'
import { BrainyData } from '../src/index.js'
2025-09-01 15:37:56 -07:00
import { ImprovedNeuralAPI } from '../src/neural/improvedNeuralAPI.js'
2025-08-26 12:32:21 -07:00
describe ( 'Neural Clustering and Analysis' , ( ) = > {
let db : BrainyData | null = null
2025-09-01 15:37:56 -07:00
let neural : ImprovedNeuralAPI | null = null
2025-08-26 12:32:21 -07:00
// Helper to create test vectors with semantic meaning
const createTestVector = ( seed : number = 0 , category : 'tech' | 'food' | 'travel' = 'tech' ) = > {
const base = new Array ( 384 ) . fill ( 0 ) . map ( ( _ , i ) = > Math . sin ( i + seed ) * 0.5 )
// Add category-specific bias to create natural clusters
const bias = category === 'tech' ? 0.1 : category === 'food' ? - 0.1 : 0
return base . map ( v = > v + bias )
}
beforeEach ( async ( ) = > {
db = new BrainyData ( )
await db . init ( )
2025-09-01 15:37:56 -07:00
neural = new ImprovedNeuralAPI ( db )
2025-08-26 12:32:21 -07:00
} )
afterEach ( async ( ) = > {
if ( db ) {
await db . cleanup ? . ( )
db = null
}
neural = null
// Force garbage collection if available
if ( global . gc ) {
global . gc ( )
}
} )
describe ( 'Similarity Calculation' , ( ) = > {
beforeEach ( async ( ) = > {
// Add test data with different categories
await db ! . add ( createTestVector ( 1 , 'tech' ) , { id : 'tech1' , data : 'JavaScript programming' } )
await db ! . add ( createTestVector ( 2 , 'tech' ) , { id : 'tech2' , data : 'Python development' } )
await db ! . add ( createTestVector ( 3 , 'food' ) , { id : 'food1' , data : 'Italian cuisine' } )
await db ! . add ( createTestVector ( 4 , 'food' ) , { id : 'food2' , data : 'French cooking' } )
await db ! . add ( createTestVector ( 5 , 'travel' ) , { id : 'travel1' , data : 'Paris vacation' } )
} )
it ( 'should calculate similarity between IDs' , async ( ) = > {
2025-09-01 15:37:56 -07:00
const similarity = await neural ! . similar ( 'tech1' , 'tech2' )
2025-08-26 12:32:21 -07:00
expect ( typeof similarity ) . toBe ( 'number' )
expect ( similarity ) . toBeGreaterThan ( 0 )
expect ( similarity ) . toBeLessThanOrEqual ( 1 )
// Tech items should be more similar to each other
2025-09-01 15:37:56 -07:00
const crossCategorySim = await neural ! . similar ( 'tech1' , 'food1' )
2025-08-26 12:32:21 -07:00
expect ( similarity ) . toBeGreaterThan ( crossCategorySim )
} )
it ( 'should calculate similarity between text strings' , async ( ) = > {
2025-09-01 15:37:56 -07:00
const similarity = await neural ! . similar (
2025-08-26 12:32:21 -07:00
'JavaScript programming' ,
'TypeScript development'
)
expect ( typeof similarity ) . toBe ( 'number' )
expect ( similarity ) . toBeGreaterThan ( 0.5 ) // Should be somewhat similar
} )
it ( 'should calculate similarity between vectors' , async ( ) = > {
const vector1 = createTestVector ( 10 , 'tech' )
const vector2 = createTestVector ( 11 , 'tech' )
2025-09-01 15:37:56 -07:00
const similarity = await neural ! . similar ( vector1 , vector2 )
2025-08-26 12:32:21 -07:00
expect ( typeof similarity ) . toBe ( 'number' )
expect ( similarity ) . toBeGreaterThan ( 0.8 ) // Similar vectors
} )
it ( 'should return detailed similarity result when requested' , async ( ) = > {
2025-09-01 15:37:56 -07:00
const result = await neural ! . similar ( 'tech1' , 'tech2' , { detailed : true } )
2025-08-26 12:32:21 -07:00
expect ( typeof result ) . toBe ( 'object' )
if ( typeof result === 'object' ) {
expect ( result ) . toHaveProperty ( 'score' )
expect ( result ) . toHaveProperty ( 'confidence' )
expect ( result ) . toHaveProperty ( 'explanation' )
}
} )
} )
describe ( 'Clustering Operations' , ( ) = > {
beforeEach ( async ( ) = > {
// Create natural clusters
// Tech cluster
for ( let i = 0 ; i < 10 ; i ++ ) {
await db ! . add ( createTestVector ( i , 'tech' ) , {
id : ` tech ${ i } ` ,
data : ` Tech item ${ i } ` ,
category : 'technology'
} )
}
// Food cluster
for ( let i = 0 ; i < 8 ; i ++ ) {
await db ! . add ( createTestVector ( i + 100 , 'food' ) , {
id : ` food ${ i } ` ,
data : ` Food item ${ i } ` ,
category : 'cuisine'
} )
}
// Travel cluster
for ( let i = 0 ; i < 6 ; i ++ ) {
await db ! . add ( createTestVector ( i + 200 , 'travel' ) , {
id : ` travel ${ i } ` ,
data : ` Travel item ${ i } ` ,
category : 'destination'
} )
}
} )
it ( 'should find semantic clusters automatically' , async ( ) = > {
const clusters = await neural ! . clusters ( )
expect ( Array . isArray ( clusters ) ) . toBe ( true )
expect ( clusters . length ) . toBeGreaterThan ( 0 )
// Each cluster should have required properties
for ( const cluster of clusters ) {
expect ( cluster ) . toHaveProperty ( 'id' )
expect ( cluster ) . toHaveProperty ( 'centroid' )
expect ( cluster ) . toHaveProperty ( 'members' )
expect ( Array . isArray ( cluster . members ) ) . toBe ( true )
}
} )
it ( 'should cluster specific items' , async ( ) = > {
const techItems = [ 'tech1' , 'tech2' , 'tech3' , 'tech4' ]
const clusters = await neural ! . clusters ( techItems )
expect ( Array . isArray ( clusters ) ) . toBe ( true )
// Should create cluster(s) from provided items
const allMembers = clusters . flatMap ( c = > c . members )
for ( const item of techItems ) {
expect ( allMembers ) . toContain ( item )
}
} )
it ( 'should find clusters near a specific item' , async ( ) = > {
const clusters = await neural ! . clusters ( 'tech1' )
expect ( Array . isArray ( clusters ) ) . toBe ( true )
// Should find cluster containing tech1
const techCluster = clusters . find ( c = > c . members . includes ( 'tech1' ) )
expect ( techCluster ) . toBeDefined ( )
// Tech cluster should contain other tech items
if ( techCluster ) {
expect ( techCluster . members . some ( m = > m . startsWith ( 'tech' ) ) ) . toBe ( true )
}
} )
it ( 'should support fast hierarchical clustering' , async ( ) = > {
const clusters = await neural ! . clusters ( {
algorithm : 'hierarchical' ,
maxClusters : 3
} )
expect ( Array . isArray ( clusters ) ) . toBe ( true )
expect ( clusters . length ) . toBeLessThanOrEqual ( 3 )
} )
it ( 'should handle large-scale clustering with sampling' , async ( ) = > {
// Add more items for large-scale test
for ( let i = 100 ; i < 200 ; i ++ ) {
await db ! . add ( createTestVector ( i ) , { id : ` item ${ i } ` } )
}
const clusters = await neural ! . clusters ( {
algorithm : 'sample' ,
sampleSize : 50
} )
expect ( Array . isArray ( clusters ) ) . toBe ( true )
expect ( clusters . length ) . toBeGreaterThan ( 0 )
} )
} )
describe ( 'Semantic Neighbors' , ( ) = > {
beforeEach ( async ( ) = > {
// Create a semantic network
await db ! . add ( createTestVector ( 1 ) , { id : 'center' , data : 'Center node' } )
// Close neighbors
for ( let i = 1 ; i <= 5 ; i ++ ) {
await db ! . add ( createTestVector ( 1.1 * i ) , {
id : ` close ${ i } ` ,
data : ` Close neighbor ${ i } `
} )
}
// Distant items
for ( let i = 1 ; i <= 3 ; i ++ ) {
await db ! . add ( createTestVector ( 100 * i ) , {
id : ` far ${ i } ` ,
data : ` Distant item ${ i } `
} )
}
} )
it ( 'should find semantic neighbors' , async ( ) = > {
const neighbors = await neural ! . neighbors ( 'center' , { limit : 5 } )
expect ( Array . isArray ( neighbors ) ) . toBe ( true )
expect ( neighbors . length ) . toBeLessThanOrEqual ( 5 )
// Should include close neighbors
const neighborIds = neighbors . map ( n = > n . id )
expect ( neighborIds . some ( id = > id . startsWith ( 'close' ) ) ) . toBe ( true )
// Should not include distant items in top 5
expect ( neighborIds . some ( id = > id . startsWith ( 'far' ) ) ) . toBe ( false )
} )
it ( 'should respect similarity radius' , async ( ) = > {
const neighbors = await neural ! . neighbors ( 'center' , {
radius : 0.1 , // Very tight radius
limit : 10
} )
// Should only include very similar items
for ( const neighbor of neighbors ) {
expect ( neighbor . similarity ) . toBeGreaterThan ( 0.9 )
}
} )
} )
describe ( 'Semantic Hierarchy' , ( ) = > {
beforeEach ( async ( ) = > {
// Create hierarchical structure
await db ! . add ( createTestVector ( 1 ) , { id : 'root' , data : 'Root concept' } )
await db ! . add ( createTestVector ( 2 ) , { id : 'child1' , data : 'Child 1' } )
await db ! . add ( createTestVector ( 3 ) , { id : 'child2' , data : 'Child 2' } )
await db ! . add ( createTestVector ( 4 ) , { id : 'grandchild1' , data : 'Grandchild 1' } )
} )
it ( 'should build semantic hierarchy' , async ( ) = > {
const hierarchy = await neural ! . hierarchy ( 'grandchild1' )
expect ( hierarchy ) . toHaveProperty ( 'self' )
expect ( hierarchy . self . id ) . toBe ( 'grandchild1' )
// Should have parent and potentially grandparent
if ( hierarchy . parent ) {
expect ( hierarchy . parent ) . toHaveProperty ( 'id' )
expect ( hierarchy . parent ) . toHaveProperty ( 'similarity' )
}
} )
it ( 'should find semantic siblings' , async ( ) = > {
const hierarchy = await neural ! . hierarchy ( 'child1' )
if ( hierarchy . siblings ) {
expect ( Array . isArray ( hierarchy . siblings ) ) . toBe ( true )
// child2 should be a sibling
const sibling = hierarchy . siblings . find ( s = > s . id === 'child2' )
expect ( sibling ) . toBeDefined ( )
}
} )
} )
describe ( 'Visualization' , ( ) = > {
beforeEach ( async ( ) = > {
// Add interconnected data
for ( let i = 0 ; i < 20 ; i ++ ) {
await db ! . add ( createTestVector ( i ) , {
id : ` node ${ i } ` ,
data : ` Node ${ i } `
} )
}
} )
it ( 'should generate visualization data' , async ( ) = > {
const viz = await neural ! . visualize ( { maxNodes : 10 } )
expect ( viz ) . toHaveProperty ( 'nodes' )
expect ( viz ) . toHaveProperty ( 'edges' )
expect ( Array . isArray ( viz . nodes ) ) . toBe ( true )
expect ( Array . isArray ( viz . edges ) ) . toBe ( true )
// Should respect maxNodes
expect ( viz . nodes . length ) . toBeLessThanOrEqual ( 10 )
// Each node should have required properties
for ( const node of viz . nodes ) {
expect ( node ) . toHaveProperty ( 'id' )
expect ( node ) . toHaveProperty ( 'x' )
expect ( node ) . toHaveProperty ( 'y' )
}
// Each edge should connect existing nodes
for ( const edge of viz . edges ) {
expect ( edge ) . toHaveProperty ( 'source' )
expect ( edge ) . toHaveProperty ( 'target' )
expect ( edge ) . toHaveProperty ( 'weight' )
const sourceExists = viz . nodes . some ( n = > n . id === edge . source )
const targetExists = viz . nodes . some ( n = > n . id === edge . target )
expect ( sourceExists ) . toBe ( true )
expect ( targetExists ) . toBe ( true )
}
} )
it ( 'should support 3D visualization' , async ( ) = > {
const viz = await neural ! . visualize ( {
maxNodes : 10 ,
dimensions : 3
} )
// Nodes should have z coordinate for 3D
for ( const node of viz . nodes ) {
expect ( node ) . toHaveProperty ( 'z' )
}
} )
} )
describe ( 'Performance and Caching' , ( ) = > {
it ( 'should cache similarity calculations' , async ( ) = > {
await db ! . add ( createTestVector ( 1 ) , { id : 'item1' } )
await db ! . add ( createTestVector ( 2 ) , { id : 'item2' } )
// First calculation
const start1 = performance . now ( )
2025-09-01 15:37:56 -07:00
const sim1 = await neural ! . similar ( 'item1' , 'item2' )
2025-08-26 12:32:21 -07:00
const time1 = performance . now ( ) - start1
// Second calculation (should be cached)
const start2 = performance . now ( )
2025-09-01 15:37:56 -07:00
const sim2 = await neural ! . similar ( 'item1' , 'item2' )
2025-08-26 12:32:21 -07:00
const time2 = performance . now ( ) - start2
expect ( sim1 ) . toBe ( sim2 )
expect ( time2 ) . toBeLessThan ( time1 * 0.5 ) // Cached should be much faster
} )
it ( 'should cache cluster results' , async ( ) = > {
// Add test data
for ( let i = 0 ; i < 50 ; i ++ ) {
await db ! . add ( createTestVector ( i ) , { id : ` item ${ i } ` } )
}
// First clustering
const start1 = performance . now ( )
const clusters1 = await neural ! . clusters ( )
const time1 = performance . now ( ) - start1
// Second clustering (should be cached)
const start2 = performance . now ( )
const clusters2 = await neural ! . clusters ( )
const time2 = performance . now ( ) - start2
expect ( clusters1 . length ) . toBe ( clusters2 . length )
expect ( time2 ) . toBeLessThan ( time1 * 0.5 ) // Cached should be much faster
} )
} )
describe ( 'Error Handling' , ( ) = > {
it ( 'should handle invalid IDs gracefully' , async ( ) = > {
2025-09-01 15:37:56 -07:00
const similarity = await neural ! . similar ( 'nonexistent1' , 'nonexistent2' )
2025-08-26 12:32:21 -07:00
expect ( similarity ) . toBe ( 0 ) // Should return 0 for non-existent items
} )
it ( 'should handle empty clustering gracefully' , async ( ) = > {
2025-09-01 15:37:56 -07:00
const emptyNeural = new ImprovedNeuralAPI ( db ! )
2025-08-26 12:32:21 -07:00
const clusters = await emptyNeural . clusters ( )
expect ( Array . isArray ( clusters ) ) . toBe ( true )
expect ( clusters . length ) . toBe ( 0 )
} )
it ( 'should handle invalid clustering input' , async ( ) = > {
await expect (
neural ! . clusters ( 123 as any ) // Invalid input type
) . rejects . toThrow ( 'Invalid input for clustering' )
} )
} )
} )