Skip to content

Commit 69a48e4

Browse files
committed
Merge package:graphs into shared tool repository
2 parents 5a57b3a + 345ea30 commit 69a48e4

27 files changed

+2651
-0
lines changed

.github/workflows/graphs.yml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: CI
2+
3+
on:
4+
# Run on PRs and pushes to the default branch.
5+
push:
6+
branches: [ master ]
7+
paths:
8+
- '.github/workflows/graphs.yml'
9+
- 'pkgs/graphs/**'
10+
pull_request:
11+
branches: [ master ]
12+
paths:
13+
- '.github/workflows/graphs.yml'
14+
- 'pkgs/graphs/**'
15+
schedule:
16+
- cron: "0 0 * * 0"
17+
18+
env:
19+
PUB_ENVIRONMENT: bot.github
20+
21+
jobs:
22+
# Check code formatting and static analysis on a single OS (linux)
23+
# against Dart beta.
24+
analyze:
25+
runs-on: ubuntu-latest
26+
defaults:
27+
run:
28+
working-directory: pkgs/graphs/
29+
strategy:
30+
fail-fast: false
31+
matrix:
32+
sdk: [dev]
33+
steps:
34+
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab
35+
- uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
36+
with:
37+
sdk: ${{ matrix.sdk }}
38+
- id: install
39+
run: dart pub get
40+
- run: dart format --output=none --set-exit-if-changed .
41+
if: always() && steps.install.outcome == 'success'
42+
- run: dart analyze --fatal-infos
43+
if: always() && steps.install.outcome == 'success'
44+
45+
test:
46+
needs: analyze
47+
runs-on: ${{ matrix.os }}
48+
defaults:
49+
run:
50+
working-directory: pkgs/graphs/
51+
strategy:
52+
fail-fast: false
53+
matrix:
54+
os: [ubuntu-latest]
55+
sdk: [2.18.0, dev]
56+
steps:
57+
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab
58+
- uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
59+
with:
60+
sdk: ${{ matrix.sdk }}
61+
- id: install
62+
run: dart pub get
63+
- run: dart test --platform vm
64+
if: always() && steps.install.outcome == 'success'
65+
- run: dart test --platform chrome
66+
if: always() && steps.install.outcome == 'success'

pkgs/graphs/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.dart_tool/
2+
.packages
3+
.pub/
4+
build/
5+
pubspec.lock

pkgs/graphs/CHANGELOG.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# 2.3.0
2+
3+
- Add a `transitiveClosure` function.
4+
- Make `stronglyConnectedComponents` and `topologicalSort` iterative rather than
5+
recursive to avoid stack overflows on very large graphs.
6+
- Require Dart 2.18
7+
8+
# 2.2.0
9+
10+
- Add a `secondarySort` parameter to the `topologicalSort()` function which
11+
applies an additional lexical sort where that doesn't break the topological
12+
sort.
13+
14+
# 2.1.0
15+
16+
- Add a `topologicalSort()` function.
17+
18+
# 2.0.0
19+
20+
- **Breaking**: `crawlAsync` will no longer ignore a node from the graph if the
21+
`readNode` callback returns null.
22+
23+
# 1.0.0
24+
25+
- Migrate to null safety.
26+
- **Breaking**: Paths from `shortestPath[s]` are now returned as iterables to
27+
reduce memory consumption of the algorithm to O(n).
28+
29+
# 0.2.0
30+
31+
- **BREAKING** `shortestPath`, `shortestPaths` and `stronglyConnectedComponents`
32+
now have one generic parameter and have replaced the `key` parameter with
33+
optional params: `{bool equals(T key1, T key2), int hashCode(T key)}`.
34+
This follows the pattern used in `dart:collection` classes `HashMap` and
35+
`LinkedHashMap`. It improves the usability and performance of the case where
36+
the source values are directly usable in a hash data structure.
37+
38+
# 0.1.3+1
39+
40+
- Fixed a bug with non-identity `key` in `shortestPath` and `shortestPaths`.
41+
42+
# 0.1.3
43+
44+
- Added `shortestPath` and `shortestPaths` functions.
45+
- Use `HashMap` and `HashSet` from `dart:collection` for
46+
`stronglyConnectedComponents`. Improves runtime performance.
47+
48+
# 0.1.2+1
49+
50+
- Allow using non-dev Dart 2 SDK.
51+
52+
# 0.1.2
53+
54+
- `crawlAsync` surfaces exceptions while crawling through the result stream
55+
rather than as uncaught asynchronous errors.
56+
57+
# 0.1.1
58+
59+
- `crawlAsync` will now ignore nodes that are resolved to `null`.
60+
61+
# 0.1.0
62+
63+
- Initial release with an implementation of `stronglyConnectedComponents` and
64+
`crawlAsync`.

pkgs/graphs/CONTRIBUTING.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
Want to contribute? Great! First, read this page (including the small print at
2+
the end).
3+
4+
### Before you contribute
5+
Before we can use your code, you must sign the
6+
[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual)
7+
(CLA), which you can do online. The CLA is necessary mainly because you own the
8+
copyright to your changes, even after your contribution becomes part of our
9+
codebase, so we need your permission to use and distribute your code. We also
10+
need to be sure of various other things—for instance that you'll tell us if you
11+
know that your code infringes on other people's patents. You don't have to sign
12+
the CLA until after you've submitted your code for review and a member has
13+
approved it, but you must do it before we can put your code into our codebase.
14+
15+
Before you start working on a larger contribution, you should get in touch with
16+
us first through the issue tracker with your idea so that we can help out and
17+
possibly guide you. Coordinating up front makes it much easier to avoid
18+
frustration later on.
19+
20+
### Code reviews
21+
All submissions, including submissions by project members, require review.
22+
23+
### File headers
24+
All files in the project must start with the following header.
25+
26+
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
27+
// for details. All rights reserved. Use of this source code is governed by a
28+
// BSD-style license that can be found in the LICENSE file.
29+
30+
### The small print
31+
Contributions made by corporations are covered by a different agreement than the
32+
one above, the
33+
[Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate).

pkgs/graphs/LICENSE

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
Copyright 2017, the Dart project authors.
2+
3+
Redistribution and use in source and binary forms, with or without
4+
modification, are permitted provided that the following conditions are
5+
met:
6+
7+
* Redistributions of source code must retain the above copyright
8+
notice, this list of conditions and the following disclaimer.
9+
* Redistributions in binary form must reproduce the above
10+
copyright notice, this list of conditions and the following
11+
disclaimer in the documentation and/or other materials provided
12+
with the distribution.
13+
* Neither the name of Google LLC nor the names of its
14+
contributors may be used to endorse or promote products derived
15+
from this software without specific prior written permission.
16+
17+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

pkgs/graphs/README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
[![CI](https://github.com/dart-lang/tools/actions/workflows/graphs.yml/badge.svg)](https://github.com/dart-lang/tools/actions/workflows/graphs.yml)
2+
[![pub package](https://img.shields.io/pub/v/graphs.svg)](https://pub.dev/packages/graphs)
3+
[![package publisher](https://img.shields.io/pub/publisher/graphs.svg)](https://pub.dev/packages/graphs/publisher)
4+
5+
Graph algorithms that do not specify a particular approach for representing a
6+
Graph.
7+
8+
Functions in this package will take arguments that provide the mechanism for
9+
traversing the graph. For example two common approaches for representing a
10+
graph:
11+
12+
```dart
13+
class Graph {
14+
Map<Node, List<Node>> nodes;
15+
}
16+
class Node {
17+
// Interesting data
18+
}
19+
```
20+
21+
```dart
22+
class Graph {
23+
Node root;
24+
}
25+
class Node {
26+
List<Node> edges;
27+
// Interesting data
28+
}
29+
```
30+
31+
Any representation can be adapted to the needs of the algorithm:
32+
33+
- Some algorithms need to associate data with each node in the graph. If the
34+
node type `T` does not correctly or efficiently implement `hashCode` or `==`,
35+
you may provide optional `equals` and/or `hashCode` functions are parameters.
36+
- Algorithms which need to traverse the graph take a `edges` function which provides the reachable nodes.
37+
- `(node) => graph[node]`
38+
- `(node) => node.edges`
39+
40+
41+
Graphs that are resolved asynchronously will have similar functions which
42+
return `FutureOr`.

pkgs/graphs/analysis_options.yaml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# https://dart.dev/guides/language/analysis-options
2+
include: package:lints/recommended.yaml
3+
4+
analyzer:
5+
language:
6+
strict-casts: true
7+
strict-inference: true
8+
strict-raw-types: true
9+
10+
linter:
11+
rules:
12+
- always_declare_return_types
13+
- avoid_bool_literals_in_conditional_expressions
14+
- avoid_catching_errors
15+
- avoid_classes_with_only_static_members
16+
- avoid_dynamic_calls
17+
- avoid_private_typedef_functions
18+
- avoid_redundant_argument_values
19+
- avoid_returning_null
20+
- avoid_returning_null_for_future
21+
- avoid_returning_this
22+
- avoid_unused_constructor_parameters
23+
- avoid_void_async
24+
- cancel_subscriptions
25+
- comment_references
26+
- directives_ordering
27+
- join_return_with_assignment
28+
- lines_longer_than_80_chars
29+
- literal_only_boolean_expressions
30+
- missing_whitespace_between_adjacent_strings
31+
- no_adjacent_strings_in_list
32+
- no_runtimeType_toString
33+
- omit_local_variable_types
34+
- only_throw_errors
35+
- package_api_docs
36+
- prefer_asserts_in_initializer_lists
37+
- prefer_const_constructors
38+
- prefer_const_declarations
39+
- prefer_expression_function_bodies
40+
- prefer_final_locals
41+
- prefer_relative_imports
42+
- prefer_single_quotes
43+
- require_trailing_commas
44+
- test_types_in_equals
45+
- throw_in_finally
46+
- type_annotate_public_apis
47+
- unawaited_futures
48+
- unnecessary_await_in_return
49+
- unnecessary_lambdas
50+
- unnecessary_parenthesis
51+
- unnecessary_raw_strings
52+
- unnecessary_statements
53+
- use_if_null_to_convert_nulls_to_bools
54+
- use_raw_strings
55+
- use_string_buffers
56+
- use_super_parameters
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:collection';
6+
import 'dart:math' show Random;
7+
8+
import 'package:graphs/graphs.dart';
9+
10+
void main() {
11+
final rnd = Random(0);
12+
const size = 2000;
13+
final graph = HashMap<int, List<int>>();
14+
15+
for (var i = 0; i < size * 3; i++) {
16+
final toList = graph.putIfAbsent(rnd.nextInt(size), () => <int>[]);
17+
18+
final toValue = rnd.nextInt(size);
19+
if (!toList.contains(toValue)) {
20+
toList.add(toValue);
21+
}
22+
}
23+
24+
var maxCount = 0;
25+
var maxIteration = 0;
26+
27+
const duration = Duration(milliseconds: 100);
28+
29+
for (var i = 1;; i++) {
30+
var count = 0;
31+
final watch = Stopwatch()..start();
32+
while (watch.elapsed < duration) {
33+
count++;
34+
final length =
35+
stronglyConnectedComponents(graph.keys, (e) => graph[e] ?? <Never>[])
36+
.length;
37+
assert(length == 244, '$length');
38+
}
39+
40+
if (count > maxCount) {
41+
maxCount = count;
42+
maxIteration = i;
43+
}
44+
45+
if (maxIteration == i || (i - maxIteration) % 20 == 0) {
46+
print('max iterations in ${duration.inMilliseconds}ms: $maxCount\t'
47+
'after $maxIteration of $i iterations');
48+
}
49+
}
50+
}

0 commit comments

Comments
 (0)