{"id":21928118,"url":"https://github.com/depp/metric-tree-demo","last_synced_at":"2025-07-10T15:39:44.371Z","repository":{"id":21429448,"uuid":"24747616","full_name":"depp/metric-tree-demo","owner":"depp","description":"Metric tree demo","archived":false,"fork":false,"pushed_at":"2014-10-03T05:19:04.000Z","size":128,"stargazers_count":14,"open_issues_count":0,"forks_count":12,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-19T19:40:42.234Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/depp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-10-03T05:15:48.000Z","updated_at":"2023-07-15T14:18:04.000Z","dependencies_parsed_at":"2022-08-21T09:11:04.603Z","dependency_job_id":null,"html_url":"https://github.com/depp/metric-tree-demo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/depp/metric-tree-demo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/depp%2Fmetric-tree-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/depp%2Fmetric-tree-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/depp%2Fmetric-tree-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/depp%2Fmetric-tree-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/depp","download_url":"https://codeload.github.com/depp/metric-tree-demo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/depp%2Fmetric-tree-demo/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264599635,"owners_count":23635310,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-28T22:21:17.304Z","updated_at":"2025-07-10T15:39:44.349Z","avatar_url":"https://github.com/depp.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Metric tree sample implementation.\n\nThis was written in response to the Stack Overflow question,\n[Efficiently find binary strings with low Hamming distance in large set][question]\n\n[question]: http://stackoverflow.com/questions/6389841/efficiently-find-binary-strings-with-low-hamming-distance-in-large-set/6390606#6390606\n\nThis generates a bunch of pseudorandom 32-bit integers, inserts them\ninto an index, and queries the index for points within a certain\ndistance of the given point.\n\nThat is,\n\n    Let S = { N pseudorandom 32-bit integers }\n    Let d(x,y) be the (base-2) Hamming distance between x and y\n    Let q(x,r) = { y in S : d(x,y) \u003c= r }\n\nThere are three implementations in here which can be selected at\nruntime.\n\n\"bk\" is a BK-Tree.  Each internal node has a center point, and each\nchild node contains a set of all points a certain distance away from\nthe center.\n\n\"vp\" is a VP-Tree.  Each internal node has a center point and two\nchildren.  The \"near\" child contains all points contained in a closed\nball of a certain radius around the center, and the \"far\" node\ncontains all other points.\n\n\"linear\" is a linear search.\n\nThe tree implementations use a linear search for leaf nodes.  The\nmaximum number of points in a leaf node is configurable at runtime and\nthis parameter will affect performance.  If the number is low, say 1,\nthen the memory usage of the tree implementations will skyrocket to\nunreasonable levels: more than 24 bytes per element.  If the number is\nhigh, say infinity, then the tree will degenerate to a linear search.\n\nNote that VP trees are slightly faster than BK trees for this problem,\nand neither tree implementation significantly outperforms linear\nsearch (that is, by a factor of two or more) for large r (for r \u003e 6,\nit seems).\n\n## Test results\n\nParameters:\n\n* System: 3.2 GHz AMD Phenom II / 6 cores\n* RAM: 4 GiB\n* Database size: 100M points\n* Results: Average # of query hits (very approximate)\n* Speed: Number of queries per second\n* Coverage: Average percentage of database examined per query\n* Sample size: 1000 queries for distance 1..5, 100 for 6..10 and linear\n* Max leaf size: 1000 points\n\nResults:\n\n                -- BK Tree --   -- VP Tree --\t-- Linear --\n    Dist\tResults\tSpeed\tCov\tSpeed\tCov\tSpeed\tCov\n    1\t   0.90\t3800\t 0.048%\t4200\t 0.048%\n    2\t  11\t 300\t 0.68%\t 330\t 0.65%\n    3\t 130\t  56\t 3.8%\t  63\t 3.4%\n    4\t 970\t  18\t12%\t  22\t10%\n    5\t5700\t   8.5\t26%\t  10\t22%\n    6\t2.6e4\t   5.2\t42%\t   6.0\t37%\n    7\t1.1e5\t   3.7\t60%\t   4.1\t54%\n    8\t3.5e5\t   3.0\t74%\t   3.2\t70%\n    9\t1.0e6\t   2.6\t85%\t   2.7\t82%\n    10\t2.5e6\t   2.3\t91%\t   2.4\t90%\n    any\t\t\t\t\t\t2.2\t100%\n\nAbove results were computed by:\n\n    ./tree bk 1000 100000000 1000 1 2 3 4 5\n    ./tree bk 100 100000000 1000 6 7 8 9 10\n    ./tree vp 1000 100000000 1000 1 2 3 4 5\n    ./tree vp 100 100000000 1000 6 7 8 9 10\n    ./tree linear 1000 100000000 \n\nExcept \"results\", which was just grabbed from whatever was convenient.\nIt's just an evaluation of the binomial function, so no need to\ngenerate it specially (and it's not accurate).\n\nConclusion: I think VP is faster than BK because, being \"deeper\"\nrather than \"shallower\", it compares against more points rather than\nusing finer-grained comparisons against fewer points.  I suspect that\nthe differences are more extreme in higher dimensional spaces.\n\nWhat is the correct maximum leaf node size?\n\n    for n in 50 60 64 70 80 90\n    do ./tree vp $n 100000000 1000 3 ; done | grep Rate\n\n    50: Rate: 94.607379 query/sec\n    60: Rate: 95.877277 query/sec\n    64: Rate: 97.656250 query/sec\n    70: Rate: 97.370983 query/sec\n    80: Rate: 96.711799 query/sec\n    90: Rate: 96.618357 query/sec\n\nI had already narrowed it down to 10 \u003c= N \u003c= 100 by exponential\nsearch.  The 64 was added after I saw the results for N*10.  I suspect\nthat 64 plays nicer with malloc than 70 does.\n\nAnswer: Allow up to 64 points per leaf node.\n\nWhat is the speed with the new leaf size?\n\n    ./tree vp 64 100000000 1000 1 2 3 4 5\n    ./tree vp 64 100000000 100 6 7 8 9 10 11 12\n\nTree size: 426725132 (6.7% overhead)\n\n    Dist\tSpeed\tCov\t    Speedup\tBK Speedup\n    1\t9100\t 0.0088%    4200x\n    2\t 580\t 0.18%\t     270x\n    3\t  97\t 1.2%\t      45x\n    4\t  29\t 4.3%\t      13x\n    5\t  12\t11%\t       5.7x\n    6\t   6.6\t21%\t       3.0x\t2.1x\n    7\t   4.1\t34%\t       1.9x\t1.5x\n    8\t   2.9\t50%\t       1.3x\t1.1x\n    9\t   2.3\t64%\t       1.0x\t0.96x\n    10\t   1.9\t77%\t       0.87x\t0.85x\n    11\t   1.7\t87%\t       0.75x\t0.77x\n    12\t   1.5\t93%\t       0.67x\t0.70x\n\nNote: These answers computed with the original high precision numbers,\nthen rounded in the final step to two significant figures.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdepp%2Fmetric-tree-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdepp%2Fmetric-tree-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdepp%2Fmetric-tree-demo/lists"}