{"id":23792485,"url":"https://github.com/se2p/pq-distance","last_synced_at":"2026-02-27T10:41:28.034Z","repository":{"id":260077591,"uuid":"879591922","full_name":"se2p/pq-distance","owner":"se2p","description":"Approximate Tree-Edit Distance for Node.js","archived":false,"fork":false,"pushed_at":"2025-10-24T07:05:28.000Z","size":156,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-24T08:35:48.590Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/se2p.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-10-28T07:43:01.000Z","updated_at":"2025-10-24T07:05:32.000Z","dependencies_parsed_at":null,"dependency_job_id":"e58cafa0-d8ea-4085-b094-3fd4274abad5","html_url":"https://github.com/se2p/pq-distance","commit_stats":null,"previous_names":["se2p/pq-distance"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/se2p/pq-distance","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/se2p%2Fpq-distance","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/se2p%2Fpq-distance/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/se2p%2Fpq-distance/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/se2p%2Fpq-distance/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/se2p","download_url":"https://codeload.github.com/se2p/pq-distance/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/se2p%2Fpq-distance/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29892055,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-27T09:48:51.284Z","status":"ssl_error","status_checked_at":"2026-02-27T09:48:43.992Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":"2025-01-01T18:35:17.975Z","updated_at":"2026-02-27T10:41:28.025Z","avatar_url":"https://github.com/se2p.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pq-distance: Approximate Tree-Edit Distance for Node.js\n\n[![npm version](https://badge.fury.io/js/@se2p%2Fpq-distance.svg)](https://www.npmjs.com/package/@se2p/pq-distance) \n![CI status](https://github.com/se2p/pq-distance/actions/workflows/ci.yml/badge.svg?branch=main)\n\nModern TypeScript implementation of pq-gram distance, an efficient approximation for tree-edit distance. Algorithm based\non academic papers[^1][^2] and thesis[^5]. Implementation ported from LitterBox[^3]. Node.js API inspired by jqgram[^4].\n\n## Installation\n\nThe package can be installed as `@se2p/pq-distance` from npm:\n\n```bash\nnpm install @se2p/pq-distance\n```\n\n## Usage\n\nThe package exports two functions function `pqDistance` and `pqDistanceWindowed`:\n\n```javascript\nconst {pqDistance, pqDistanceWindowed} = require(\"@se2p/pq-distance\");\n```\n\nTypeScript users can also import the `PQTree`, `PQOpts` and `PQWindowedOpts` types:\n\n```typescript\nimport {pqDistance, pqDistanceWindowed, PQTree, PQOpts, PQWindowedOpts} from \"@se2p/pq-distance\";\n```\n\nExample trees:\n\n```\n        a              a\n       /|\\            /|\\\nt1:   a b c    t2:   a b c \n     / \\            / \\\n    e   b          e   x\n```\n\nArbitrary tree-representations are supported. Provide two functions `getLabel()` to extract the label as string from a\nnode, and `getChildren()` that returns a node's children in an array.\n\nFor example:\n\n```typescript\nconst t1 = {\n    label: 'a',\n    children: [\n        {\n            label: 'a',\n            children: [\n                {\n                    label: 'e',\n                    children: []\n                },\n                {\n                    label: 'b',\n                    children: []\n                }\n            ]\n        },\n        {\n            label: 'b',\n            children: []\n        },\n        {\n            label: 'c',\n            children: []\n        }\n    ]\n};\n\nconst t2 = {\n    node: 'A',\n    child: [\n        {\n            node: 'A',\n            child: [\n                {node: 'E'},\n                {node: 'B'}\n            ]\n        },\n        {node: 'B'},\n        {node: 'X'}\n    ]\n};\n```\n\nTo compute the pq-gram distance between `t1` and `t2`, pass them as `PQTree` objects to `pqDistance()`:\n\n```typescript\nconst tree1: PQTree = {\n    root: t1,\n    getLabel: ({label}) =\u003e label,\n    getChildren: ({children}) =\u003e children\n};\n\nconst tree2: PQTree = {\n    root: t2,\n    getLabel: (n) =\u003e n.node.toLowerCase(),\n    getChildren: (n) =\u003e n.child ?? []\n};\n```\n\nFinally:\n\n```typescript\nconst opts: PQOpts = {p: 2, q: 3}; // default values \npqDistance(tree1, tree2, opts); // 0.3076923076923077\n```\n\nThe use is analogous for the windowed pq-gram distance:\n\n```typescript\nconst opts: PQWindowedOpts = {p: 2, w: 3}; // default values \npqDistanceWindowed(tree1, tree2, opts); // 0.3125\n```\n\nThe object `opts` sets the `p` and `q` values for `pqDistance`, and may be omitted to use the default values\n`p=2` and `q=3`. In case of `pqDistanceWindowed`, you must use `w` instead of `q`. The default values are\n`p=2` and `w=3`. Please refer to the academic papers how they affect the distance value.\n\n## License\n\npq-distance is free software: you can redistribute it and/or modify it under the terms of the GNU General Public\nLicense as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later\nversion.\n\npq-distance is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied\nwarranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n\n[^1]: Nikolaus Augsten, Michael H. Böhlen, and Johann Gamper. 2005. Approximate Matching of Hierarchical Data Using\n   pq-Grams. In Proceedings of the 31st International Conference on Very Large Data Bases, Trondheim, Norway, August 30\n   – September 2, 2005\n[^2]: https://github.com/DatabaseGroup/apted\n[^3]: https://github.com/se2p/LitterBox\n[^4]: https://github.com/hoonto/jqgram\n[^5]: https://vbn.aau.dk/en/publications/approximate-matching-of-hierarchial-data\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fse2p%2Fpq-distance","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fse2p%2Fpq-distance","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fse2p%2Fpq-distance/lists"}