{"id":13612400,"url":"https://github.com/aysylu/loom","last_synced_at":"2025-10-21T21:04:19.697Z","repository":{"id":7541833,"uuid":"8894197","full_name":"aysylu/loom","owner":"aysylu","description":"Graph library for Clojure. Mailing list https://groups.google.com/forum/#!forum/loom-clj","archived":false,"fork":false,"pushed_at":"2023-12-30T02:40:37.000Z","size":572,"stargazers_count":888,"open_issues_count":43,"forks_count":109,"subscribers_count":30,"default_branch":"master","last_synced_at":"2025-04-08T06:04:39.231Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://aysy.lu/loom/","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aysylu.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2013-03-20T02:05:51.000Z","updated_at":"2025-03-24T07:59:37.000Z","dependencies_parsed_at":"2024-01-08T18:03:37.625Z","dependency_job_id":"8722dc88-9d73-4a1e-a6df-987a73b1b26d","html_url":"https://github.com/aysylu/loom","commit_stats":{"total_commits":205,"total_committers":41,"mean_commits":5.0,"dds":0.7560975609756098,"last_synced_commit":"d458f0c0dee9021983c64381b90a470f0178cc8e"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aysylu%2Floom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aysylu%2Floom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aysylu%2Floom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aysylu%2Floom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aysylu","download_url":"https://codeload.github.com/aysylu/loom/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248705765,"owners_count":21148586,"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-08-01T20:00:29.323Z","updated_at":"2025-10-21T21:04:14.663Z","avatar_url":"https://github.com/aysylu.png","language":"Clojure","funding_links":[],"categories":["Science and Data Analysis","Clojure"],"sub_categories":[],"readme":"![Loom logo](https://raw.github.com/aysylu/loom/master/doc/loom_logo.png \"Loom\")\n\n[![Build Status](https://travis-ci.org/aysylu/loom.png)](http://travis-ci.org/aysylu/loom)\n[![cljdoc badge](https://cljdoc.org/badge/aysylu/loom)](https://cljdoc.org/d/aysylu/loom/CURRENT)\n\n**IMPORTANT: This repository is no longer actively maintained ([announcement](https://groups.google.com/g/clojure/c/ng4azryzCfs/m/148yAoP4DgAJ)).**\n\n## Video and Slides\n\nWatch the talk on Loom [at Clojure/West 2014](https://www.youtube.com/watch?v=wEEutxTYQQU) and view [slides](http://www.slideshare.net/aysylu/loom-at-clojurewest-32794616). Also, there's a video of the talk at [LispNYC](http://youtu.be/Iev7zavblqg) and [slides](http://www.slideshare.net/aysylu/aysylu-loom).\n\n## Usage\n\n### Leiningen/Clojars [group-id/name version]\n\n[![Clojars Project](http://clojars.org/aysylu/loom/latest-version.svg)](http://clojars.org/aysylu/loom)\n\n### Namespaces\n\n    loom.graph   - records \u0026 constructors\n    loom.alg     - algorithms (see also loom.alg-generic)\n    loom.gen     - graph generators\n    loom.attr    - graph attributes\n    loom.label   - graph labels\n    loom.io      - read, write, and view graphs in external formats\n    loom.derived - derive graphs from existing graphs using maps and filters\n\n### Documentation\n\n[API Reference](https://cljdoc.org/d/aysylu/loom/CURRENT)\n\n[Frequently Asked Questions](http://aysy.lu/loom/faq.html)\n\nFeel free to join [Loom mailing list](https://groups.google.com/forum/#!forum/loom-clj) and ask any questions you may have.\n\n### Basics\n\nCreate a graph:\n```clojure\n;; Initialize with any of: edges, adacency lists, nodes, other graphs\n(def g (graph [1 2] [2 3] {3 [4] 5 [6 7]} 7 8 9))\n(def dg (digraph g))\n(def wg (weighted-graph {:a {:b 10 :c 20} :c {:d 30} :e {:b 5 :d 5}}))\n(def wdg (weighted-digraph [:a :b 10] [:a :c 20] [:c :d 30] [:d :b 10]))\n(def rwg (gen-rand (weighted-graph) 10 20 :max-weight 100))\n(def fg (fly-graph :successors range :weight (constantly 77)))\n```\nIf you have [GraphViz](http://www.graphviz.org) installed, and its binaries are in the path, you can view graphs with \u003ccode\u003eloom.io/view\u003c/code\u003e:\n```clojure\n(view wdg) ;opens image in default image viewer\n```\n\nInspect:\n```clojure\n(nodes g)\n=\u003e #{1 2 3 4 5 6 7 8 9}\n\n(edges wdg)\n=\u003e ([:a :c] [:a :b] [:c :d] [:d :b])\n\n(successors g 3)\n=\u003e #{2 4}\n\n(predecessors wdg :b)\n=\u003e #{:a :d}\n\n(out-degree g 3)\n=\u003e 2\n\n(in-degree wdg :b)\n=\u003e 2\n\n(weight wg :a :c)\n=\u003e 20\n\n(map (juxt graph? directed? weighted?) [g wdg])\n=\u003e ([true false false] [true true true])\n```\nAdd/remove items (graphs are immutable, of course, so these return new graphs):\n```clojure\n(add-nodes g \"foobar\" {:name \"baz\"} [1 2 3])\n\n(add-edges g [10 11] [\"foobar\" {:name \"baz\"}])\n\n(add-edges wg [:e :f 40] [:f :g 50]) ;weighted edges\n\n(remove-nodes g 1 2 3)\n\n(remove-edges g [1 2] [2 3])\n\n(subgraph g [5 6 7])\n```\nTraverse a graph:\n```clojure\n(bf-traverse g) ;lazy\n=\u003e (9 8 5 6 7 1 2 3 4)\n\n(bf-traverse g 1)\n=\u003e (1 2 3 4)\n\n(pre-traverse wdg) ;lazy\n=\u003e (:a :b :c :d)\n\n(post-traverse wdg) ;not lazy\n=\u003e (:b :d :c :a)\n\n(topsort wdg)\n=\u003e (:a :c :d :b)\n```\nPathfinding:\n```clojure\n(bf-path g 1 4)\n=\u003e (1 2 3 4)\n\n(bf-path-bi g 1 4) ;bidirectional, parallel\n=\u003e (1 2 3 4)\n\n(dijkstra-path wg :a :d)\n=\u003e (:a :b :e :d)\n\n(dijkstra-path-dist wg :a :d)\n=\u003e [(:a :b :e :d) 20]\n```\nOther stuff:\n```clojure\n(connected-components g)\n=\u003e [[1 2 3 4] [5 6 7] [8] [9]]\n\n(bf-span wg :a)\n=\u003e {:c [:d], :b [:e], :a [:b :c]}\n\n(pre-span wg :a)\n=\u003e {:a [:b], :b [:e], :e [:d], :d [:c]}\n\n(dijkstra-span wg :a)\n=\u003e {:a {:b 10, :c 20}, :b {:e 15}, :e {:d 20}}\n```\nAttributes on nodes and edges:\n```clojure\n(def attr-graph (-\u003e g\n                (add-attr 1 :label \"node 1\")\n                (add-attr 4 :label \"node 4\")\n                (add-attr-to-nodes :parity \"even\" [2 4])\n                (add-attr-to-edges :label \"edge from node 5\" [[5 6] [5 7]])))\n\n; Return attribute value on node 1 with key :label\n(attr attr-graph 1 :label)\n=\u003e \"node 1\"\n\n; Return attribute value on node 2 with key :parity\n(attr attr-graph 2 :parity)\n=\u003e \"even\"\n\n; Getting an attribute that doesn't exist returns nil\n(attr attr-graph 3 :label)\n=\u003e nil\n\n; Return all attributes for node 4\n; Two attributes found\n(attrs attr-graph 4)\n=\u003e {:parity \"even\", :label \"node 4\"}\n\n; Return attribute value for edge between nodes 5 and 6 with key :label\n(attr attr-graph 5 6 :label)\n=\u003e \"edge from node 5\"\n\n; Return all attributes for edge between nodes 5 and 7\n(attrs attr-graph 5 7)\n=\u003e {:label \"edge from node 5\"}\n\n; Getting an attribute that doesn't exist returns nil\n(attrs attr-graph 3 4)\n=\u003e nil\n\n; Remove the attribute of node 4 with key :label\n(def attr-graph (remove-attr attr-graph 4 :label))\n\n; Return all attributes for node 4\n; One attribute found because the other has been removed\n(attrs attr-graph 4)\n=\u003e {:parity \"even\"}\n```\nDerived graphs:\n```clojure\n; Build a derived graph using a node mapping\n(nodes (mapped-by #(+ 10 %) g))\n=\u003e #{11 12 13 14 15 16 17 18 19}\n\n; Subgraphs of g\n(edges (nodes-filtered-by #{1 2 3 5} dg))\n=\u003e ([1 2] [2 1] [2 3] [3 2])\n\n(edges (subgraph-reachable-from dg 1))\n=\u003e ([1 2] [2 1] [2 3] [3 2] [3 4] [4 3])\n```\n## Dependencies\n\nNothing but Clojure. There is optional support for visualization via [GraphViz](http://graphviz.org).\n\n## TODO\n\nSee [Loom TODO board](https://trello.com/b/VgPZkvjP/loom-todo).\n\n## Testing\n\n```bash\nlein test-all\n```\n\n## Contributors\n\nNames in no particular order:\n\n* [Justin Kramer](https://github.com/jkk/)\n* [Aysylu Greenberg] (https://github.com/aysylu), [aysylu [dot] greenberg [at] gmail [dot] com](mailto:aysylu.greenberg@gmail.com), [@aysylu22](http://twitter.com/aysylu22)\n* [Robert Lachlan](https://github.com/heffalump), [robertlachlan@gmail.com](mailto:robertlachlan@gmail.com)\n* [Stephen Kockentiedt](https://github.com/s-k)\n\n## Namespaces\n\nThe dependency graph of Loom's namespaces, generated by [lein-ns-dep-graph](https://github.com/hilverd/lein-ns-dep-graph).\n\n![Loom namespace dependency graph](./doc/ns-dep-graph.png)\n\n## License\n\nCopyright (C) 2010-2016 Aysylu Greenberg \u0026 Justin Kramer (jkkramer@gmail.com)\n\nDistributed under the [Eclipse Public License](http://opensource.org/licenses/eclipse-1.0.php), the same as Clojure.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faysylu%2Floom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faysylu%2Floom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faysylu%2Floom/lists"}