{"id":18521749,"url":"https://github.com/simphotonics/directed_graph","last_synced_at":"2025-06-24T08:38:58.091Z","repository":{"id":53717511,"uuid":"251678453","full_name":"simphotonics/directed_graph","owner":"simphotonics","description":"Dart implementation of a directed graph. Provides algorithms for sorting vertices, retrieving a topological ordering or detecting cycles.","archived":false,"fork":false,"pushed_at":"2024-11-04T07:24:28.000Z","size":1949,"stargazers_count":58,"open_issues_count":0,"forks_count":4,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-09T16:15:45.266Z","etag":null,"topics":["cycle","dart","directed-acyclic-graph","directed-graph","graph","graph-theory","shortest-paths","sorting","topological-sort","vertex","vertices","weighted","weighted-graphs"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/directed_graph","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simphotonics.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2020-03-31T17:23:38.000Z","updated_at":"2025-02-28T06:00:54.000Z","dependencies_parsed_at":"2024-04-15T22:46:15.666Z","dependency_job_id":"8bd41cd8-07ac-49cf-b473-96aa426fc76f","html_url":"https://github.com/simphotonics/directed_graph","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simphotonics%2Fdirected_graph","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simphotonics%2Fdirected_graph/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simphotonics%2Fdirected_graph/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simphotonics%2Fdirected_graph/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simphotonics","download_url":"https://codeload.github.com/simphotonics/directed_graph/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248065283,"owners_count":21041872,"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":["cycle","dart","directed-acyclic-graph","directed-graph","graph","graph-theory","shortest-paths","sorting","topological-sort","vertex","vertices","weighted","weighted-graphs"],"created_at":"2024-11-06T17:27:20.835Z","updated_at":"2025-04-09T16:15:49.570Z","avatar_url":"https://github.com/simphotonics.png","language":"Dart","readme":"\n# Directed Graph\n\n[![Dart](https://github.com/simphotonics/directed_graph/actions/workflows/dart.yml/badge.svg)](https://github.com/simphotonics/directed_graph/actions/workflows/dart.yml)\n\n## Introduction\n\nAn integral part of storing, manipulating, and retrieving numerical data are *data structures* or as they are called in Dart: [collections].\nArguably the most common data structure is the *list*. It enables efficient storage and retrieval of sequential data that can be associated with an index.\n\nA more general (non-linear) data structure where an element may be connected to one, several, or none of the other elements is called a **graph**.\n\nGraphs are useful when keeping track of elements that are linked to or are dependent on other elements.\nExamples include: network connections, links in a document pointing to other paragraphs or documents, foreign keys in a relational database, file dependencies in a build system, etc.\n\nThe package [`directed_graph`][directed_graph] contains an implementation of a Dart graph that follows the\nrecommendations found in [graphs-examples] and is compatible with the algorithms provided by [`graphs`][graphs].\nIt includes methods that enable:\n* adding/removing vertices and edges,\n* sorting of vertices.\n\nThe library provides access to algorithms\nfor finding:\n* the shortest path between vertices,\n* the path with the lowest/highest weight (for weighted directed graphs),\n* all paths connecting two vertices,\n* the shortest paths from a vertex to all connected vertices,\n* cycles,\n* a topological ordering of the graph vertices.\n\nThe class [`GraphCrawler`][GraphCrawler] can be used to retrieve *paths* or *walks* connecting two vertices.\n\n## Terminology\n\nElements of a graph are called **vertices** (or nodes) and neighbouring vertices are connected by **edges**.\nThe figure below shows a **directed graph** with unidirectional edges depicted as arrows.\nGraph edges are emanating from a vertex and ending at a vertex. In a **weighted directed graph** each\nedge is assigned a weight.\n\n![Directed Graph Image](https://github.com/simphotonics/directed_graph/raw/main/images/directed_graph.svg?sanitize=true)\n\n- **In-degree** of a vertex: Number of edges ending at this vertex. For example, vertex H has in-degree 3.\n- **Out-degree** of a vertex: Number of edges starting at this vertex. For example, vertex F has out-degree 1.\n- **Source**: A vertex with in-degree zero is called (local) source. Vertices A and D in the graph above are local sources.\n- **Directed Edge**: An ordered pair of connected vertices (v\u003csub\u003ei\u003c/sub\u003e, v\u003csub\u003ej\u003c/sub\u003e). For example, the edge (A, C) starts at vertex A and ends at vertex C.\n- **Path**: A path \\[v\u003csub\u003ei\u003c/sub\u003e, ...,   v\u003csub\u003en\u003c/sub\u003e\\] is an ordered list of at least two connected vertices where each **inner** vertex is **distinct**.\n   The path \\[A, E, G\\] starts at vertex A and ends at vertex G.\n- **Cycle**: A cycle is an ordered *list* of connected vertices where each inner vertex is distinct and the\nfirst and last vertices are identical. The sequence \\[F, I, K, F\\] completes a cycle.\n- **Walk**: A walk is an ordered *list* of at least two connected vertices.\n\\[D, F, I, K, F\\] is a walk but not a path since the vertex F is listed twice.\n- **DAG**: An acronym for **Directed Acyclic Graph**, a directed graph without cycles.\n- **Topological ordering**: An ordered *set* of all vertices in a graph such that v\u003csub\u003ei\u003c/sub\u003e\noccurs before v\u003csub\u003ej\u003c/sub\u003e if there is a directed edge (v\u003csub\u003ei\u003c/sub\u003e, v\u003csub\u003ej\u003c/sub\u003e).\nA topological ordering of the graph above is: \\{A, D, B, C, E, K, F, G, H, I, L\\}.\nHereby, dashed edges were disregarded since a cyclic graph does not have a topological ordering.\n\n**Note**: In the context of this package the definition of *edge* might be more lax compared to a\nrigorous mathematical definition.\nFor example, self-loops, that is edges connecting a vertex to itself are explicitly allowed.\n\n## Usage\n\nTo use this library include [`directed_graph`][directed_graph] as a dependency in your pubspec.yaml file. The\nexample below shows how to construct an object of type [`DirectedGraph`][DirectedGraph].\n\nThe graph classes provided by this library are generic with type argument\n`T extends Object`, that is `T` must be non-nullable.\nGraph vertices can be sorted if `T is Comparable` or\nif a custom comparator function is provided. In the example below, a custom\ncomparator is used to sort vertices in inverse lexicographical order.\n\n```Dart\nimport 'package:directed_graph/directed_graph.dart';\n// To run this program navigate to\n// the folder 'directed_graph/example'\n// in your terminal and type:\n//\n// # dart bin/directed_graph_example.dart\n//\n// followed by enter.\nvoid main() {\n\n  int comparator(String s1, String s2) =\u003e s1.compareTo(s2);\n  int inverseComparator(String s1, String s2) =\u003e -comparator(s1, s2);\n\n  // Constructing a graph from vertices.\n  final graph = DirectedGraph\u003cString\u003e(\n    {\n      'a': {'b', 'h', 'c', 'e'},\n      'b': {'h'},\n      'c': {'h', 'g'},\n      'd': {'e', 'f'},\n      'e': {'g'},\n      'f': {'i'},\n      'i': {'l'},\n      'k': {'g', 'f'}\n    },\n    // Custom comparators can be specified here:\n    // comparator: comparator,\n  );\n\n  print('Example Directed Graph...');\n  print('graph.toString():');\n  print(graph);\n\n  print('\\nIs Acylic:');\n  print(graph.isAcyclic);\n\n  print('\\nStrongly connected components:');\n  print(graph.stronglyConnectedComponents);\n\n  print('\\nShortestPath(d, l):');\n  print(graph.shortestPath('d', 'l');\n\n  print('\\nInDegree(C):');\n  print(graph.inDegree('c'));\n\n  print('\\nOutDegree(C)');\n  print(graph.outDegree('c'));\n\n  print('\\nVertices sorted in lexicographical order:');\n  print(graph.sortedVertices);\n\n  print('\\nVertices sorted in inverse lexicographical order:');\n  graph.comparator = inverseComparator;\n  print(graph.sortedVertices);\n  graph.comparator = comparator;\n\n  print('\\nInDegreeMap:');\n  print(graph.inDegreeMap);\n\n  print('\\nSorted Topological Ordering:');\n  print(graph.sortedTopologicalOrdering);\n\n  print('\\nTopological Ordering:');\n  print(graph.topologicalOrdering);\n\n  print('\\nLocal Sources:');\n  print(graph.localSources);\n\n  // Add edge to render the graph cyclic\n  graph.addEdges('i', {'k'});\n  graph.addEdges('l', {'l'});\n  graph.addEdges('i', {'d'});\n\n  print('\\nCycle:');\n  print(graph.cycle);\n\n  print('\\nShortest Paths:');\n  print(graph.shortestPaths('a'));\n\n  print('\\nEdge exists: a-\u003eb');\n  print(graph.edgeExists('a', 'b'));\n}\n\n```\n\n\u003cdetails\u003e \u003csummary\u003e Click to show the console output. \u003c/summary\u003e\n\n```Console\n$ dart example/bin/directed_graph_example.dart\nExample Directed Graph...\ngraph.toString():\n{\n 'a': {'b', 'h', 'c', 'e'},\n 'b': {'h'},\n 'c': {'h', 'g'},\n 'd': {'e', 'f'},\n 'e': {'g'},\n 'f': {'i'},\n 'g': {},\n 'h': {},\n 'i': {'l'},\n 'k': {'g', 'f'},\n 'l': {},\n}\n\nIs Acylic:\ntrue\n\nStrongly connected components:\n[[h], [b], [g], [c], [e], [a], [l], [i], [f], [d], [k]]\n\nShortestPath(d, l):\n[d, f, i, l]\n\nInDegree(C):\n1\n\nOutDegree(C)\n2\n\nVertices sorted in lexicographical order:\n[a, b, c, d, e, f, g, h, i, k, l]\n\nVertices sorted in inverse lexicographical order:\n[l, k, i, h, g, f, e, d, c, b, a]\n\nInDegreeMap:\n{a: 0, b: 1, h: 3, c: 1, e: 2, g: 3, d: 0, f: 2, i: 1, l: 1, k: 0}\n\nSorted Topological Ordering:\n{a, b, c, d, e, h, k, f, g, i, l}\n\nTopological Ordering:\n{a, b, c, d, e, h, k, f, i, g, l}\n\nLocal Sources:\n[[a, d, k], [b, c, e, f], [g, h, i], [l]]\n\nCycle:\n[l, l]\n\nShortest Paths:\n{e: (e), c: (c), h: (h), a: (), g: (c, g), b: (b)}\n\nEdge exists: a-\u003eb\ntrue\n\n```\n\u003c/details\u003e\n\n## Weighted Directed Graphs\n\nThe example below shows how to construct an object of type [`WeightedDirectedGraph`][WeightedDirectedGraph].\nInitial graph edges are specified in the form of map of type `Map\u003cT, Map\u003cT, W\u003e\u003e`. The vertex type `T` extends\n`Object` and therefore must be a non-nullable. The type associated with the edge weight `W` extends `Comparable`\nto enable sorting of vertices by their edge weight.\n\nThe constructor takes an optional comparator function\nas parameter. Vertices may be sorted if\na [comparator] function is provided\nor if `T` implements [`Comparator`][Comparator].\n\n```Dart\n\nimport 'package:directed_graph/directed_graph.dart';\n\nvoid main(List\u003cString\u003e args) {\n  int comparator(\n    String s1,\n    String s2,\n  ) {\n    return s1.compareTo(s2);\n  }\n\n  final a = 'a';\n  final b = 'b';\n  final c = 'c';\n  final d = 'd';\n  final e = 'e';\n  final f = 'f';\n  final g = 'g';\n  final h = 'h';\n  final i = 'i';\n  final k = 'k';\n  final l = 'l';\n\n  int sum(int left, int right) =\u003e left + right;\n\n  var graph = WeightedDirectedGraph\u003cString, int\u003e(\n    {\n      a: {b: 1, h: 7, c: 2, e: 40, g:7},\n      b: {h: 6},\n      c: {h: 5, g: 4},\n      d: {e: 1, f: 2},\n      e: {g: 2},\n      f: {i: 3},\n      i: {l: 3, k: 2},\n      k: {g: 4, f: 5},\n      l: {l: 0}\n    },\n    summation: sum,\n    zero: 0,\n    comparator: comparator,\n  );\n\n  print('Weighted Graph:');\n  print(graph);\n\n  print('\\nNeighbouring vertices sorted by weight:');\n  print(graph..sortEdgesByWeight());\n\n  final lightestPath = graph.lightestPath(a, g);\n  print('\\nLightest path a -\u003e g');\n  print('$lightestPath weight: ${graph.weightAlong(lightestPath)}');\n\n  final heaviestPath = graph.heaviestPath(a, g);\n  print('\\nHeaviest path a -\u003e g');\n  print('$heaviestPath weigth: ${graph.weightAlong(heaviestPath)}');\n\n  final shortestPath = graph.shortestPath(a, g);\n  print('\\nShortest path a -\u003e g');\n  print('$shortestPath weight: ${graph.weightAlong(shortestPath)}');\n}\n```\n\n\u003cdetails\u003e \u003csummary\u003e Click to show the console output. \u003c/summary\u003e\n\n```Console\n$ dart example/bin/weighted_graph_example.dart\nWeighted Graph:\n{\n 'a': {'b': 1, 'h': 7, 'c': 2, 'e': 40, 'g': 7},\n 'b': {'h': 6},\n 'c': {'h': 5, 'g': 4},\n 'd': {'e': 1, 'f': 2},\n 'e': {'g': 2},\n 'f': {'i': 3},\n 'g': {},\n 'h': {},\n 'i': {'l': 3, 'k': 2},\n 'k': {'g': 4, 'f': 5},\n 'l': {'l': 0},\n}\n\nNeighbouring vertices sorted by weight\n{\n 'a': {'b': 1, 'c': 2, 'h': 7, 'g': 7, 'e': 40},\n 'b': {'h': 6},\n 'c': {'g': 4, 'h': 5},\n 'd': {'e': 1, 'f': 2},\n 'e': {'g': 2},\n 'f': {'i': 3},\n 'g': {},\n 'h': {},\n 'i': {'k': 2, 'l': 3},\n 'k': {'g': 4, 'f': 5},\n 'l': {'l': 0},\n}\n\nLightest path a -\u003e g\n[a, c, g] weight: 6\n\nHeaviest path a -\u003e g\n[a, e, g] weigth: 42\n\nShortest path a -\u003e g\n[a, g] weight: 7\n```\n\u003c/details\u003e\n\n## Examples\n\nFor further information on how to generate a topological sorting of vertices see [example].\n\n## Features and bugs\n\nPlease file feature requests and bugs at the [issue tracker].\n\n[comparator]: https://api.dart.dev/stable/dart-core/Comparator.html\n\n[issue tracker]: https://github.com/simphotonics/directed_graph/issues\n\n[collections]: https://api.dart.dev/stable/dart-collection/dart-collection-library.html\n\n[example]: https://github.com/simphotonics/directed_graph/tree/main/example\n\n[graphs-examples]: https://pub.dev/packages/graphs#-example-tab-\n\n[graphs]: https://pub.dev/packages/graphs\n\n[directed_graph]: https://pub.dev/packages/directed_graph\n\n[GraphCrawler]: https://pub.dev/documentation/directed_graph/latest/directed_graph/GraphCrawler-class.html\n\n[DirectedGraph]: https://pub.dev/documentation/directed_graph/latest/directed_graph/DirectedGraph-class.html\n\n[WeightedDirectedGraph]: https://pub.dev/documentation/directed_graph/latest/directed_graph/WeightedDirectedGraph-class.html\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimphotonics%2Fdirected_graph","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimphotonics%2Fdirected_graph","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimphotonics%2Fdirected_graph/lists"}