import { DIR } from "@/core/interfaces" ; import { Similarity } from "@/similarities/interfaces" ; import { sim , simSource , simPairwise , sortFuncs , knnNodeArray , viaSharedPrefs } from "@/similarities/SimilarityCommons" ; import { setSimFuncs as simFuncs } from "@/similarities/SetSimilarities" ; import { TypedGraph } from "@/core/typed/TypedGraph" ; import { JSONInput } from "@/io/input/JSONInput" ; import { JSON_SIM_PATH } from "_/config/test_paths" ; /**
 *
 */ describe ( "JACCARD base similarity tests" , ( ) => { const a = [ 1 , 2 , 3 ] , b = [ 1 , 2 , 4 , 5 ] , c = [ ] , d = [ ] , SUPER_SIZE = 1e5 ; let i = SUPER_SIZE ; while ( i -- >= SUPER_SIZE / 3 ) d . push ( i ) ; while ( i -- ) c . push ( i ) ; let s_a = new Set ( a ) , s_b = new Set ( b ) , s_c = new Set ( c ) , s_d = new Set ( d ) , t_ai = new Uint32Array ( a ) , t_bi = new Uint32Array ( b ) , t_ci = new Uint32Array ( c ) , t_di = new Uint32Array ( d ) ; it ( "should compute jaccard between two simple SETS" , ( ) => { const jexp = { isect : 2 , sim : 0.4 } ; expect ( sim ( simFuncs . jaccard , s_a , s_b ) ) . toEqual ( jexp ) ; } ) ; it ( "should compute jaccard between two LARGE sets" , ( ) => { const jexp = { isect : 0 , sim : 0 } ; expect ( sim ( simFuncs . jaccard , s_c , s_d ) ) . toEqual ( jexp ) ; } ) ; } ) ; description describe ( "JACCARD tests on neo4j sample graph" , ( ) => { const gFile = JSON_SIM_PATH + "/cuisine.json" , g = new JSONInput ( ) . readFromJSONFile ( gFile , new TypedGraph ( "CuisineSimilarities" ) ) as TypedGraph , arya = g . n ( "Arya" ) , karin = g . n ( "Karin" ) ; /**
       * Cuisine preference similarity of Karin & Arya
       *
       * MATCH (p1:Person {name: 'Karin'})-[:LIKES]->(cuisine1)
           WITH p1, collect(id(cuisine1)) AS p1Cuisine
           MATCH (p2:Person {name: "Arya"})-[:LIKES]->(cuisine2)
           WITH p1, p1Cuisine, p2, collect(id(cuisine2)) AS p2Cuisine
           RETURN
                  p1.name AS from,
                  p2.name AS to,
                  algo.similarity.jaccard(p1Cuisine, p2Cuisine) AS similarity
       */ it ( "should compute the correct culinary similarity of Karin & Arya" , ( ) => { const kc = g . outs ( karin , "LIKES" ) ; const ac = g . outs ( arya , "LIKES" ) ; const jexp = { isect : 2 , sim : 0.66667 } ; const jres = sim ( simFuncs . jaccard , kc , ac ) ; expect ( jres ) . toEqual ( jexp ) ; } ) ; it ( "should compute the correct culinary similarities for Karin" , ( ) => { const jexp = [ { from : "Karin" , to : "Arya" , isect : 2 , sim : 0.66667 } , { from : "Karin" , to : "Michael" , isect : 1 , sim : 0.25 } , { from : "Karin" , to : "Zhen" , isect : 0 , sim : 0 } , { from : "Karin" , to : "Praveena" , isect : 0 , sim : 0 } , ] ; const start = karin . label ; const allSets = { } ; g . getNodesT ( "Person" ) . forEach ( n => { allSets [ n . label ] = g . expand ( n , DIR . out , "LIKES" ) . set ; } ) ; const jres = simSource ( simFuncs . jaccard , start , allSets ) ; expect ( jres ) . toEqual ( jexp ) ; } ) ; it ( "should compute the pairwise culinary similarity" , ( ) => { const jexp = [ { from : "Michael" , to : "Zhen" , isect : 2 , sim : 0.66667 } , { from : "Karin" , to : "Arya" , isect : 2 , sim : 0.66667 } , { from : "Praveena" , to : "Zhen" , isect : 1 , sim : 0.33333 } , { from : "Michael" , to : "Praveena" , isect : 1 , sim : 0.25 } , { from : "Arya" , to : "Praveena" , isect : 1 , sim : 0.25 } , { from : "Karin" , to : "Michael" , isect : 1 , sim : 0.25 } , { from : "Arya" , to : "Michael" , isect : 1 , sim : 0.2 } , { from : "Arya" , to : "Zhen" , isect : 0 , sim : 0 } , { from : "Karin" , to : "Zhen" , isect : 0 , sim : 0 } , { from : "Karin" , to : "Praveena" , isect : 0 , sim : 0 } , ] ; const allSets = { } ; g . getNodesT ( "Person" ) . forEach ( n => { allSets [ n . label ] = g . expand ( n , DIR . out , "LIKES" ) . set ; } ) ; const jres = simPairwise ( simFuncs . jaccard , allSets ) ; expect ( jres . length ) . toBe ( 10 ) ; expect ( jres ) . toEqual ( jexp ) ; } ) ; it ( "should compute the top-K per node" , ( ) => { const topKExp = [ { from : "Zhen" , to : "Michael" , isect : 2 , sim : 0.66667 } , { from : "Michael" , to : "Zhen" , isect : 2 , sim : 0.66667 } , { from : "Arya" , to : "Karin" , isect : 2 , sim : 0.66667 } , { from : "Karin" , to : "Arya" , isect : 2 , sim : 0.66667 } , { from : "Praveena" , to : "Zhen" , isect : 1 , sim : 0.33333 } , ] ; const allSets = { } ; g . getNodesT ( "Person" ) . forEach ( n => { allSets [ n . label ] = g . expand ( n , DIR . out , "LIKES" ) . set ; } ) ; const topK = knnNodeArray ( simFuncs . jaccard , allSets , { knn : 1 , dup : true } ) ; expect ( topK ) . toEqual ( topKExp ) ; } ) ; todo it ( "should find similarities between recipes and people depending on shared cuisine" , ( ) => { const simExp = [ { from : "Peri Peri Naan" , to : "Praveena" , isect : 2 , sim : 1 } , { from : "Shrimp Bolognese" , to : "Michael" , isect : 2 , sim : 0.66667 } , { from : "Saltimbocca alla roman" , to : "Michael" , isect : 2 , sim : 0.66667 } , { from : "Shrimp Bolognese" , to : "Zhen" , isect : 1 , sim : 0.33333 } , { from : "Shrimp Bolognese" , to : "Praveena" , isect : 1 , sim : 0.33333 } , { from : "Shrimp Bolognese" , to : "Karin" , isect : 1 , sim : 0.33333 } , { from : "Saltimbocca alla roman" , to : "Zhen" , isect : 1 , sim : 0.33333 } , { from : "Saltimbocca alla roman" , to : "Karin" , isect : 1 , sim : 0.33333 } , { from : "Peri Peri Naan" , to : "Zhen" , isect : 1 , sim : 0.33333 } , { from : "Shrimp Bolognese" , to : "Arya" , isect : 1 , sim : 0.25 } , { from : "Saltimbocca alla roman" , to : "Arya" , isect : 1 , sim : 0.25 } , { from : "Peri Peri Naan" , to : "Michael" , isect : 1 , sim : 0.25 } , { from : "Peri Peri Naan" , to : "Arya" , isect : 1 , sim : 0.25 } , ] ; const tic = process . hrtime ( ) [ 1 ] ; const sims = viaSharedPrefs ( g , simFuncs . jaccard , { t1 : "Recipe" , t2 : "Person" , d1 : DIR . out , d2 : DIR . out , e1 : "Type" , e2 : "Likes" , } ) ; const toc = process . hrtime ( ) [ 1 ] ; console . log ( `Computing Jaccard similarity based on shared preferences took ${ toc - tic } nanos.` ) ; expect ( sims ) . toEqual ( simExp ) ; } ) ; description it ( "should find the most similar Person to Karin & Arya" , ( ) => { const allSets = { } ; g . getNodesT ( "Person" ) . forEach ( n => { allSets [ n . label ] = g . expand ( n , DIR . out , "LIKES" ) ; } ) ; console . log ( simSource ( simFuncs . jaccard , "Karin" , allSets , { knn : 1 } ) [ 0 ] ) ; console . log ( simSource ( simFuncs . jaccard , "Arya" , allSets , { knn : 1 } ) [ 0 ] ) ; } ) ; /**
     * let's say (French, Lebanese) vs. (Italian, Portuguese)
     */ it . todo ( "should compute group similarity" ) ; } ) ;