{"id":17491776,"url":"https://github.com/bitwalker/libgraph","last_synced_at":"2025-05-15T00:09:48.311Z","repository":{"id":43522703,"uuid":"93268741","full_name":"bitwalker/libgraph","owner":"bitwalker","description":"A graph data structure library for Elixir projects","archived":false,"fork":false,"pushed_at":"2024-08-20T18:53:28.000Z","size":1353,"stargazers_count":549,"open_issues_count":31,"forks_count":75,"subscribers_count":13,"default_branch":"main","last_synced_at":"2025-04-11T10:16:57.344Z","etag":null,"topics":["data-structures","elixir","graphs"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bitwalker.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}},"created_at":"2017-06-03T19:08:02.000Z","updated_at":"2025-04-05T01:21:12.000Z","dependencies_parsed_at":"2024-06-18T12:40:56.817Z","dependency_job_id":"255a61b9-d56a-460f-8ed8-b67b6f6b9910","html_url":"https://github.com/bitwalker/libgraph","commit_stats":{"total_commits":161,"total_committers":32,"mean_commits":5.03125,"dds":0.3354037267080745,"last_synced_commit":"460cdfd9a163a533bdab0a160ba7ccf888047927"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitwalker%2Flibgraph","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitwalker%2Flibgraph/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitwalker%2Flibgraph/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitwalker%2Flibgraph/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bitwalker","download_url":"https://codeload.github.com/bitwalker/libgraph/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254249206,"owners_count":22039029,"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":["data-structures","elixir","graphs"],"created_at":"2024-10-19T08:04:55.162Z","updated_at":"2025-05-15T00:09:43.259Z","avatar_url":"https://github.com/bitwalker.png","language":"Elixir","readme":"# libgraph\n\n[![Master](https://travis-ci.org/bitwalker/libgraph.svg?branch=master)](https://travis-ci.org/bitwalker/libgraph)\n[![Hex.pm Version](http://img.shields.io/hexpm/v/libgraph.svg?style=flat)](https://hex.pm/packages/libgraph)\n[![Coverage Status](https://coveralls.io/repos/github/bitwalker/libgraph/badge.svg?branch=master)](https://coveralls.io/github/bitwalker/libgraph?branch=master)\n\n[Documentation](https://hexdocs.pm/libgraph)\n\n## About\n\nThis library provides:\n\n- An implementation of a graph datastructure, `Graph`, designed for both directed and undirected graphs. The API supports\n  undirected graphs, but I'm still getting the tests updated to cover properties of undirected graphs.\n- A priority queue implementation `PriorityQueue`, oriented towards graphs (it prioritizes lower integer values over high),\n  it is the fastest priority queue I know of which allows arbitrary priorities, and is more or less at parity with\n  `pqueue3` from [the pqueue library](https://github.com/okeuday/pqueue/), which supports priorities from 0 to 65535.\n- An idiomatic Elixir API for creating, modifying, and querying its graph structure. Creating and modifying a graph\n  can be done in a single pipeline, and all queries take a Graph as their first parameter (one of my complaints with `:digraph`\n  is that there is some inconsistency with the API between `:digraph` and `:digraph_utils` for no apparent reason).\n- Two \"Reducer\" implementations for mapping/reducing over a graph. I am trying to figure out the best way to make these\nextendable and part of the API, so that you can drop in your own shortest path algorithms, etc - but I have yet to come up with an\napproach that feels good on that front.\n- A `Serializer` behaviour, for defining custom serialization of graphs, with a Graphviz DOT format serializer\n  provided out of the box.\n\nIt is backed by a large suite of tests, including several QuickCheck properties for the graph model. Its\nAPI shares some similarity with `:digraph`, but diverges in favor of a more idiomatic Elixir interface. In\naddition, over time I'm adding new functions to query the graph in ways not previously supported via `:digraph`,\nand introducing support for classifying a graph as undirected if so desired, so that queries over such graphs\nbecome easier.\n\nIf you are interested in reading more about how you can make use of `libgraph`, \nthere is an [excellent blog post](https://medium.com/@tonyhammond/native-graph-data-in-elixir-8c0bb325d451) written by Tony Hammond\nwhich is a very helpful walkthrough of the library and what can be built with it.\n\n## Installation\n\nIf [available in Hex](https://hex.pm/docs/publish), the package can be installed\nby adding `libgraph` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [{:libgraph, \"~\u003e 0.16.0\"}]\nend\n```\n\n## Rationale\n\nThe original motivation for me to start working on this library is the fact that `:digraph` requires a\nminimum of 3 ETS tables per graph, and up to 6 depending on the operations you are performing on the graph.\nIf you are working with a lot of graphs concurrently, as I am, this means you can find yourself in a situation\nwhere you hit the system limit for the maximum number of ETS table, and bring your system down. Seeing as how\nit is ridiculous that trying to use a simple graph could potentially kill my system, and not wanting to hack\naround the problem, I decided to see if I could build an alternative which was competitive performance-wise,\nwithout requiring any ETS tables at all.\n\nThe result turned out better than I hoped - it is possible to build a graph datastructure without ETS that\nis both equally performant (and in many of my benchmarks, better performing), and supports all of the same\nfunctionality.\n\nAdditionally, I also had a few other things I wanted to address:\n\n- Inconsistency with argument order in the API between `:digraph` and `:digraph_utils`\n- The fact that there are two modules to work with the same datastructure to begin with, and trying to remember\n  what lives where.\n- The lack of extensibility, for example, there is no API with which you can implement your own\n  traversal algorithms. This means you are stuck with whatever way the Erlang maintainers decided was\n  ideal, regardless of whether it suits your use case or not. A great example is single-source shortest path\n  algorithms, where you may want a simple breadth-first search, or perhaps you want to use Dijkstra's algorithm -\n  you are stuck with just one approach with `:digraph`, which as I understand it, is a breadth-first search.\n- `:digraph` as the name implies, only supports directed graphs\n- `:digraph` graphs are unweighted, with no way to supported weighted graphs\n- `:digraph` graphs are not \"inspect-friendly\", you get a tuple with the underlying ETS table ids, but that's it,\n  not necessarily a big deal, but it's nice for playing around in the shell if you can see how your code affects the\n  structure.\n  \nMy speculation as to why `:digraph` is the way it is, is that when `:digraph` was originally written, there was\nno efficient key/value datastructure in Erlang that could support large numbers of keys. At that time, maps\nweren't even a speck in the eye of the language maintainers. Even after the initial introduction of maps in OTP 18,\nmaps still weren't efficient enough to work with large numbers of keys. It wasn't until OTP 19 that the performance\nof maps with millions of keys became reasonable. So, it's not that `:digraph` sucks - it was the best possible implementation\nat the time; but now that the language has come so far, we can take advantage of some of the new hotness and reinvent\nit from the ground up :).\n\n## Benchmarks\n\nFeel free to take a look under the `bench` folder in the project root. There a few benchmarks I threw together to\nkeep an eye on a few key areas I wanted to ensure parity with `:digraph` on. You can run them yourself as well, but\nI would encourage you to use them as a template to construct a benchmark based on your own use case, and compare them\nthat way, as it will give you a better basis to make your decision on. However, if you do find that `libgraph` is behind\n`:digraph` with a benchmark, please let me know so that I can improve the library!\n\nNOTE: While this library is primarily focused on the `Graph` data structure it defines, it also contains an implementation\nof a priority queue (you can find it under the `PriorityQueue` module), designed for use with graphs specifically, as it\nconsiders lower integer values higher priority, which is perfect for the kinds of graph algorithms you need a priority queue for.\n\n## Contributing\n\nTo run the test suite you will need to run `mix eqc.install --mini` once you've cloned the repo and fetched dependencies.\n\nIf you have changes in mind that are significant or potentially time consuming, please open a RFC-style PR first, where we\ncan discuss your plans first. I don't want you to spend all your time crafting a PR that I ultimately reject because I don't\nthink it's a good fit or is too large for me to review. Not that I plan to reject PRs in general, but I have to be careful to\nbalance features with maintenance burden, or I will quickly be unable to manage the project.\n\nPlease ensure that you adhere to a commit style where logically related changes are in a single commit, or broken up in a way that\neases review if necessary. Keep commit subject lines informative, but short, and provide additional detail in the extended message text\nif needed. If you can, mention relevant issue numbers in either the subject or the extended message.\n\n## Roadmap\n\nPlease open an issue if you have a feature request!\n\n## License\n\nMIT (See the LICENSE file)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitwalker%2Flibgraph","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbitwalker%2Flibgraph","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitwalker%2Flibgraph/lists"}