Orientação gerada a partir de informações públicas. Apenas para referência.
Um pacote Dart que fornece grafos direcionados genéricos e grafos direcionados com pesos, com algoritmos integrados para ordenação de vértices e ordenação topológica. Permite percorrimento eficiente de grafos e resolução de dependências, sendo ideal para modelar relações hierárquicas ou sequenciais. O pacote suporta múltiplas plataformas, incluindo Android, iOS, Web, macOS, Windows e Linux. Foi projetado para desenvolvedores que precisam de estruturas de grafos robustas sem dependências externas. Os algoritmos são otimizados para correção e desempenho em casos de uso comuns.
Casos de uso
Resolução de dependência
Agendamento de tarefas
análise de fluxo de dados
Modelagem de topologia de rede
Ordem de compilação de código
visualização de gráficos
Principais recursos
Suporta grafos direcionados e ponderados
algoritmos de ordenação topológica
Ferramentas de ordenação de vértices
Compatibilidade multiplataforma
Leve e sem dependências
Suporte a tipos genéricos
Indicado para
Desenvolvedores construindo agendadores de tarefas
Engenheiros gerenciando dependências
Projetos educacionais sobre teoria dos grafos
Aplicações que exigem orquestração de fluxo de trabalho
Ferramentas para análise de código ou sistemas de compilação
Considerações
Não otimizado para gráficos muito grandes
Limitado a operações de grafo direcionado
Sem visualização embutida
Requer manipulação manual da detecção de ciclo
Mais adequado para conjuntos de dados de tamanho moderado
README original
Snapshot do README original do repositório-fonte vinculado. Consulte o repositório para o conteúdo mais recente.
Directed Graph
Introduction
An integral part of storing, manipulating, and retrieving numerical data are data structures or as they are called in Dart: collections.
Arguably the most common data structure is the list. It enables efficient storage and retrieval of sequential data that can be associated with an index.
A 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.
Graphs are useful when keeping track of elements that are linked to or are dependent on other elements.
Examples 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.
The package directed_graph contains an implementation of a Dart graph that follows the
recommendations found in graphs-examples and is compatible with the algorithms provided by graphs.
It includes methods that enable:
adding/removing vertices and edges,
sorting of vertices and edges.
The library provides access to algorithms
for finding:
the shortest path between vertices,
the path with the lowest/highest weight (for weighted directed graphs),
all paths connecting two vertices,
the shortest paths from a vertex to all connected vertices,
cycles,
a topological ordering of the graph vertices,
a reverse topological ordering of the graph vertices.
The class GraphCrawler can be used to retrieve paths or walks connecting two vertices.
Terminology
Elements of a graph are called vertices (or nodes) and neighbouring vertices are connected by edges.
The figure below shows a directed graph with unidirectional edges depicted as arrows.
Graph edges are emanating from a vertex and ending at a vertex. In a weighted directed graph each
edge is assigned a weight.
In-degree of a vertex: Number of edges ending at this vertex. For example, vertex H has in-degree 3.
Out-degree of a vertex: Number of edges starting at this vertex. For example, vertex F has out-degree 1.
Source: A vertex with in-degree zero is called (local) source. Vertices A and D in the graph above are local sources.
Directed Edge: An ordered pair of connected vertices (vi, vj). For example, the edge (A, C) starts at vertex A and ends at vertex C.
Path: A path [vi, ..., vn] is an ordered list of at least two connected vertices where each inner vertex is distinct.
The path [A, E, G] starts at vertex A and ends at vertex G.
Cycle: A cycle is an ordered list of connected vertices where each inner vertex is distinct and the
first and last vertices are identical. The sequence [F, I, K, F] completes a cycle.
Walk: A walk is an ordered list of at least two connected vertices.
[D, F, I, K, F] is a walk but not a path since the vertex F is listed twice.
DAG: An acronym for Directed Acyclic Graph, a directed graph without cycles.
Topological ordering: An ordered set of all vertices in a graph such that vi
occurs before vj if there is a directed edge (vi, vj).
A topological ordering of the graph above is: {A, D, B, C, E, K, F, G, H, I, L}.
Hereby, dashed edges were disregarded since a cyclic graph does not have a topological ordering.
Quasi-topological ordering: An ordered sub-set of graph vertices
such that vi
occurs before vj if there is a directed edge (vi, vj).
For example, the set { A, D, E, G } represents a valid quasi-topological ordering,
even though the edges (I, K) and (L, L) render the total graph cyclic.
For a quasi-topological ordering to exist, any two vertices belonging to the sub-set
must not be mutually connected. That is, if there is a path [vi, ..., vj]
then there must not be a path [vj, ..., vi] and vice versa. Note:
The paths [vi, ..., vj] and
[vj, ..., vi] may include vertices that are not in
the sub-set, but belong to the graph.
A quasi-topological ordering many exist even if the
total graph is cyclic.
Note: In the context of this package, the definition of edge might be more lax compared to a
rigorous mathematical definition.
For example, self-loops, that is edges connecting a vertex to itself are explicitly allowed.
Usage
To use this library include directed_graph as a dependency in your pubspec.yaml file. The
example below shows how to construct an object of type DirectedGraph.
The graph classes provided by this library are generic with type argument
T extends Object (that is T must be non-nullable). The graphs
extend Iterable making it possible to iterate over the graph vertices.
Graph vertices can be sorted if T is Comparable or
if a custom comparator function is provided.
Note: If T is Comparable and no comparator is provided, then
the following default comparator is automatically provided:
(T left, T right) => (left asComparable).compareTo(right);
In the example below, a custom
comparator is used to sort vertices in lexicographical order.
$ dart example/bin/directed_graph_example.dart
Example Directed Graph...
graph.toString():
{
'a': {'b', 'h', 'c', 'e'},
'b': {'h'},
'h': {},
'c': {'h', 'g'},
'e': {'g'},
'g': {},
'd': {'e', 'f'},
'f': {'i'},
'i': {'l'},
'l': {},
'k': {'g', 'f'},
}
Is Acylic:
true
Strongly connected components:
[{h}, {b}, {g}, {c}, {e}, {a}, {l}, {i}, {f}, {d}, {k}]
Local sources:
[{a, d, k}, {b, c, e, f}, {g, h, i}, {l}]
shortestPath(d, l):
[d, f, i, l]
shortestPaths(a)
{b: [b], h: [h], c: [c], e: [e], g: [c, g]}
InDegree(C):
1
OutDegree(C)
2
Vertices sorted in lexicographical order:
{a, b, c, d, e, f, g, h, i, k, l}
Vertices sorted in inverse lexicographical order:
{l, k, i, h, g, f, e, d, c, b, a}
InDegreeMap:
{a: 0, b: 1, h: 3, c: 1, e: 2, g: 3, d: 0, f: 2, i: 1, l: 1, k: 0}
Sorted Topological Ordering:
{a, b, c, d, e, h, k, f, g, i, l}
Topological Ordering:
{a, b, c, d, e, h, k, f, i, g, l}
Reverse Topological Ordering:
{l, g, i, f, k, h, e, d, c, b, a}
Reverse Topological Ordering, sorted: true
{h, b, g, c, e, a, l, i, f, d, k}
Local Sources:
[{a, d, k}, {b, c, e, f}, {g, h, i}, {l}]
Adding edges: i -> k and i -> d
Cyclic graph:
{
'a': {'b', 'h', 'c', 'e'},
'b': {'h'},
'h': {},
'c': {'h', 'g'},
'e': {'g'},
'g': {},
'd': {'e', 'f'},
'f': {'i'},
'i': {'l', 'k', 'd'},
'l': {},
'k': {'g', 'f'},
}
Cycle:
[f, i, k, f]
Cycle vertex:
f
graph.isAcyclic:
false
Shortest Paths:
{b: [b], h: [h], c: [c], e: [e], g: [c, g]}
Edge exists: a->b
true
Strongly connected components:
[{h}, {b}, {g}, {c}, {e}, {a}, {l}, {k, i, f, d}]
Strongly connected components, sorted:
[{h}, {b}, {g}, {c}, {e}, {a}, {l}, {d, f, i, k}]
Strongly connected components, sorted, inverse:
[{l}, {g}, {e}, {k, i, f, d}, {h}, {c}, {b}, {a}]
Quasi-Topological Ordering:
{d, a, e, g}
Quasi-Topological Ordering, sorted:
{a, d, e, g}
Reverse-Quasi-Topological Ordering, sorted:
{g, e, a, d}
Weighted Directed Graphs
The example below shows how to construct an object of type WeightedDirectedGraph.
Initial graph edges are specified in the form of map of type Map<T, Map<T, W>>. The vertex type T extends
Object and therefore must be a non-nullable. The type associated with the edge weight W extends Comparable
to enable sorting of vertices by their edge weight.
The constructor takes an optional comparator function
as parameter. Vertices may be sorted if
a comparator function is provided
or if T implements Comparator.
import'package:directed_graph/directed_graph.dart';
voidmain(List<String> args) {
intcomparator(String s1, String s2) {
return s1.compareTo(s2);
}
final a = 'a';
final b = 'b';
final c = 'c';
final d = 'd';
final e = 'e';
final f = 'f';
final g = 'g';
final h = 'h';
final i = 'i';
final k = 'k';
final l = 'l';
intsum(int left, int right) => left + right;
var graph = WeightedDirectedGraph<String, int>(
{
a: {b: 1, h: 7, c: 2, e: 40, g: 7},
b: {h: 6},
c: {h: 5, g: 4},
d: {e: 1, f: 2},
e: {g: 2},
f: {i: 3},
i: {l: 3, k: 2},
k: {g: 4, f: 5},
l: {l: 0},
},
summation: sum,
zero: 0,
comparator: comparator,
);
print('Weighted Graph:');
print(graph);
print('\nNeighbouring vertices sorted by weight:');
print(graph..sortEdgesByWeight());
final lightestPath = graph.lightestPath(a, g);
print('\nLightest path a -> g');
print('$lightestPath weight: ${graph.weightAlong(lightestPath)}');
final heaviestPath = graph.heaviestPath(a, g);
print('\nHeaviest path a -> g');
print('$heaviestPath weigth: ${graph.weightAlong(heaviestPath)}');
final shortestPath = graph.shortestPath(a, g);
print('\nShortest path a -> g');
print('$shortestPath weight: ${graph.weightAlong(shortestPath)}');
print('\nTransitive Closure');
print(WeightedDirectedGraph.transitiveClosure(graph));
print('\nTransitive Weighted Edges:');
print(graph.transitiveWeightedEdges);
print('\nVertices reachable from d:');
print(graph.reachableVertices(d));
print('\nUpdate weight of edge (a,b) with value 101:');
graph.updateEdgeWeight(vertex: a, connectedVertex: b, weight: 101);
print('graph.weightedEdges(a): ${graph.weightedEdges(a)}');
}