Repository: gonum/gonum
Pull request #1946 (2024-03-06 20:16:09)

graph: merge set.Ints and set.Int64s into one generic set
This PR introduces a single modernization change from https://github.com/gonum/gonum/pull/1934. Benchmarks will follow.

Follow-on to https://github.com/gonum/gonum/pull/1934, which was my first attempt at this but was too large to properly benchmark.

Blocked by https://github.com/gonum/gonum/pull/1940.
<!--
Checklist:

- API changes have been discussed
- code is goformated correctly (goimports)
- packages with generated code have had code generation run
- tests pass locally
- linked to relevant issues

Please make sure your commit message summary line and pull request
title match the Go convention; a one-line summary of the change,
prefixed by the primary affected package that should complete the
sentence, "This change modifies Gonum to _____."
-->


jbduncan: I'll double check that all affected code has benchmarks and write any new benchmarks as needed, as discussed in https://github.com/gonum/gonum/pull/1956#issuecomment-1988326786.
kortschak: This needs to pick up the changes in master.
jbduncan: > This needs to pick up the changes in master.

Done.
codecov-commenter: ## [Codecov](https://app.codecov.io/gh/gonum/gonum/pull/1946?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gonum) Report
Attention: Patch coverage is `90.90909%` with `4 lines` in your changes are missing coverage. Please review.
> Project coverage is 72.20%. Comparing base [(`43d122b`)](https://app.codecov.io/gh/gonum/gonum/commit/43d122ba357012c9bf66038e4b9d1cac21094aa3?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gonum) to head [(`929a9a3`)](https://app.codecov.io/gh/gonum/gonum/pull/1946?dropdown=coverage&src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gonum).
> Report is 2 commits behind head on master.

| [Files](https://app.codecov.io/gh/gonum/gonum/pull/1946?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gonum) | Patch % | Lines |
|---|---|---|
| [graph/coloring/coloring.go](https://app.codecov.io/gh/gonum/gonum/pull/1946?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gonum#diff-Z3JhcGgvY29sb3JpbmcvY29sb3JpbmcuZ28=) | 90.90% | [1 Missing :warning: ](https://app.codecov.io/gh/gonum/gonum/pull/1946?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gonum) |
| [graph/community/louvain\_directed\_multiplex.go](https://app.codecov.io/gh/gonum/gonum/pull/1946?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gonum#diff-Z3JhcGgvY29tbXVuaXR5L2xvdXZhaW5fZGlyZWN0ZWRfbXVsdGlwbGV4Lmdv) | 75.00% | [0 Missing and 1 partial :warning: ](https://app.codecov.io/gh/gonum/gonum/pull/1946?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gonum) |
| [graph/community/louvain\_undirected\_multiplex.go](https://app.codecov.io/gh/gonum/gonum/pull/1946?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gonum#diff-Z3JhcGgvY29tbXVuaXR5L2xvdXZhaW5fdW5kaXJlY3RlZF9tdWx0aXBsZXguZ28=) | 75.00% | [0 Missing and 1 partial :warning: ](https://app.codecov.io/gh/gonum/gonum/pull/1946?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gonum) |
| [graph/encoding/dot/decode.go](https://app.codecov.io/gh/gonum/gonum/pull/1946?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gonum#diff-Z3JhcGgvZW5jb2RpbmcvZG90L2RlY29kZS5nbw==) | 0.00% | [1 Missing :warning: ](https://app.codecov.io/gh/gonum/gonum/pull/1946?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gonum) |

:exclamation: Your organization needs to install the [Codecov GitHub app](https://github.com/apps/codecov/installations/select_target) to enable full functionality.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #1946      +/-   ##
==========================================
- Coverage   72.34%   72.20%   -0.14%     
==========================================
  Files         555      538      -17     
  Lines       65005    64483     -522     
==========================================
- Hits        47026    46561     -465     
+ Misses      15380    15345      -35     
+ Partials     2599     2577      -22     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/gonum/gonum/pull/1946?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gonum).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gonum).

jbduncan: There's a few benchmarks to add (which I'll add TODO comments for in a TODO commit to keep track of), and once they're added, I'll run all `graph` benchmarks to see the general impact of generifying the sets.
jbduncan: Here are the latest benchmarks for `graph`.

They seem to be a bit all over the place, but in summary the geomeans seem to have gone up by 0-1%.

@kortschak Let me know what you think.

<details>
  <summary>Benchmarks</summary>

```
goos: darwin
goarch: arm64
pkg: gonum.org/v1/gonum/graph/coloring
                                                       │ benchmarks_graph_old.txt │       benchmarks_graph_new.txt        │
                                                       │          sec/op          │    sec/op      vs base                │
Coloring/empty/Dsatur-8                                             3.134n ±   0%    3.159n ±  1%   +0.80% (p=0.000 n=10)
Coloring/empty/DsaturExact-8                                        3.132n ±   1%    3.175n ±  1%   +1.34% (p=0.004 n=10)
Coloring/empty/Randomized-8                                         3.142n ±   1%    3.170n ±  0%   +0.89% (p=0.001 n=10)
Coloring/empty/RecursiveLargestFirst-8                              3.147n ±   0%    3.172n ±  0%   +0.78% (p=0.000 n=10)
Coloring/empty/SanSegundo-8                                         3.145n ±   0%    3.175n ±  0%   +0.95% (p=0.000 n=10)
Coloring/empty/WelshPowell-8                                        3.151n ±   0%    3.174n ±  0%   +0.71% (p=0.001 n=10)
Coloring/singleton/Dsatur-8                                         407.3n ±   0%    410.0n ±  0%   +0.68% (p=0.001 n=10)
Coloring/singleton/DsaturExact-8                                    942.8n ±   0%    945.8n ±  0%   +0.32% (p=0.003 n=10)
Coloring/singleton/Randomized-8                                     232.3n ±   0%    233.6n ±  0%   +0.60% (p=0.000 n=10)
Coloring/singleton/RecursiveLargestFirst-8                          293.8n ±   1%    293.1n ±  0%   -0.22% (p=0.005 n=10)
Coloring/singleton/SanSegundo-8                                     407.2n ±   0%    409.4n ±  0%   +0.53% (p=0.000 n=10)
Coloring/singleton/WelshPowell-8                                    284.3n ±   0%    285.9n ±  0%   +0.56% (p=0.000 n=10)
Coloring/kite/Dsatur-8                                              3.269µ ±   0%    3.275µ ±  0%   +0.18% (p=0.005 n=10)
Coloring/kite/DsaturExact-8                                         17.61µ ±   0%    17.66µ ±  0%        ~ (p=0.063 n=10)
Coloring/kite/Randomized-8                                          1.157µ ±   0%    1.157µ ±  1%        ~ (p=0.154 n=10)
Coloring/kite/RecursiveLargestFirst-8                               2.217µ ±   0%    2.221µ ±  0%   +0.20% (p=0.023 n=10)
Coloring/kite/SanSegundo-8                                          3.967µ ±   0%    3.981µ ±  0%   +0.37% (p=0.005 n=10)
Coloring/kite/WelshPowell-8                                         1.387µ ±   0%    1.390µ ±  0%   +0.25% (p=0.005 n=10)
Coloring/triangle+1/Dsatur-8                                        2.070µ ±   0%    2.071µ ±  0%        ~ (p=0.358 n=10)
Coloring/triangle+1/DsaturExact-8                                   9.930µ ±   0%    9.967µ ±  0%   +0.37% (p=0.000 n=10)
Coloring/triangle+1/Randomized-8                                    903.1n ±  67%    807.2n ±  1%  -10.61% (p=0.014 n=10)
Coloring/triangle+1/RecursiveLargestFirst-8                         1.525µ ± 114%    1.418µ ±  0%   -7.02% (p=0.000 n=10)
Coloring/triangle+1/SanSegundo-8                                    2.412µ ±   1%    2.409µ ±  0%        ~ (p=0.641 n=10)
Coloring/triangle+1/WelshPowell-8                                   966.6n ±   0%    972.4n ±  0%   +0.59% (p=0.000 n=10)
Coloring/bipartite_halves/Dsatur-8                                  7.911µ ±   0%    7.948µ ±  0%   +0.47% (p=0.000 n=10)
Coloring/bipartite_halves/DsaturExact-8                             32.67µ ±   0%    32.75µ ±  0%        ~ (p=0.066 n=10)
Coloring/bipartite_halves/Randomized-8                              2.162µ ±   0%    2.162µ ±  0%        ~ (p=0.718 n=10)
Coloring/bipartite_halves/RecursiveLargestFirst-8                   3.957µ ±   0%    3.962µ ±  0%        ~ (p=0.077 n=10)
Coloring/bipartite_halves/SanSegundo-8                              15.50µ ±   3%    15.01µ ±  0%   -3.17% (p=0.003 n=10)
Coloring/bipartite_halves/WelshPowell-8                             2.435µ ±   2%    2.379µ ±  1%   -2.28% (p=0.001 n=10)
Coloring/bipartite_alternating/Dsatur-8                             7.828µ ±   2%    7.834µ ±  0%        ~ (p=0.424 n=10)
Coloring/bipartite_alternating/DsaturExact-8                        32.60µ ±   1%    32.64µ ±  0%        ~ (p=0.315 n=10)
Coloring/bipartite_alternating/Randomized-8                         2.143µ ±   0%    2.145µ ±  0%        ~ (p=0.157 n=10)
Coloring/bipartite_alternating/RecursiveLargestFirst-8              3.919µ ±   0%    3.928µ ±  1%   +0.23% (p=0.006 n=10)
Coloring/bipartite_alternating/SanSegundo-8                         15.12µ ±   0%    15.09µ ±  0%   -0.15% (p=0.037 n=10)
Coloring/bipartite_alternating/WelshPowell-8                        2.471µ ±   0%    2.466µ ±  0%        ~ (p=0.638 n=10)
Coloring/3/4_bipartite/Dsatur-8                                     6.362µ ±   0%    6.371µ ±  0%        ~ (p=0.254 n=10)
Coloring/3/4_bipartite/DsaturExact-8                                30.01µ ±   0%    30.04µ ±  0%        ~ (p=0.210 n=10)
Coloring/3/4_bipartite/Randomized-8                                 1.844µ ±   0%    1.843µ ±  0%        ~ (p=0.654 n=10)
Coloring/3/4_bipartite/RecursiveLargestFirst-8                      3.505µ ±   0%    3.507µ ±  0%        ~ (p=0.138 n=10)
Coloring/3/4_bipartite/SanSegundo-8                                 13.22µ ±   1%    13.26µ ±  1%        ~ (p=0.739 n=10)
Coloring/3/4_bipartite/WelshPowell-8                                2.220µ ±   0%    2.232µ ±  0%   +0.56% (p=0.000 n=10)
Coloring/cubical/Dsatur-8                                           7.957µ ±   0%    8.015µ ±  0%   +0.72% (p=0.000 n=10)
Coloring/cubical/DsaturExact-8                                      33.04µ ±   0%    33.08µ ±  0%        ~ (p=0.060 n=10)
Coloring/cubical/Randomized-8                                       2.175µ ±   1%    2.178µ ±  0%        ~ (p=0.090 n=10)
Coloring/cubical/RecursiveLargestFirst-8                            4.037µ ±   0%    4.035µ ±  0%        ~ (p=0.494 n=10)
Coloring/cubical/SanSegundo-8                                       15.20µ ±   0%    15.17µ ±  0%        ~ (p=0.072 n=10)
Coloring/cubical/WelshPowell-8                                      2.498µ ±   0%    2.495µ ±  1%        ~ (p=0.445 n=10)
Coloring/HoG33106/Dsatur-8                                          18.94µ ±   0%    18.96µ ±  0%        ~ (p=0.078 n=10)
Coloring/HoG33106/DsaturExact-8                                     72.85µ ±   0%    72.68µ ±  0%        ~ (p=0.075 n=10)
Coloring/HoG33106/Randomized-8                                      3.999µ ±   0%    4.001µ ±  0%        ~ (p=0.158 n=10)
Coloring/HoG33106/RecursiveLargestFirst-8                           8.790µ ±   1%    8.767µ ±  0%   -0.26% (p=0.002 n=10)
Coloring/HoG33106/SanSegundo-8                                      68.30µ ±   0%    67.94µ ±  0%   -0.54% (p=0.000 n=10)
Coloring/HoG33106/WelshPowell-8                                     4.975µ ±   1%    4.964µ ±  0%        ~ (p=0.143 n=10)
Coloring/HoG41237/Dsatur-8                                          214.5m ±   0%    214.1m ±  1%        ~ (p=0.247 n=10)
Coloring/HoG41237/DsaturExact-8                                     234.5m ±   1%    238.1m ±  1%   +1.54% (p=0.000 n=10)
Coloring/HoG41237/Randomized-8                                      2.403m ±   0%    2.422m ±  1%   +0.76% (p=0.000 n=10)
Coloring/HoG41237/RecursiveLargestFirst-8                           8.914m ±   1%    8.934m ±  1%        ~ (p=0.143 n=10)
Coloring/HoG41237/SanSegundo-8                                      504.6m ±   1%    503.0m ±  0%   -0.31% (p=0.019 n=10)
Coloring/HoG41237/WelshPowell-8                                     3.652m ±   1%    3.609m ±  0%   -1.18% (p=0.000 n=10)
Coloring/exams/Dsatur-8                                             4.636µ ±   1%    4.637µ ±  0%        ~ (p=0.868 n=10)
Coloring/exams/DsaturExact-8                                        26.41µ ±   0%    26.41µ ±  0%        ~ (p=0.870 n=10)
Coloring/exams/Randomized-8                                         1.508µ ±   0%    1.509µ ±  0%        ~ (p=0.187 n=10)
Coloring/exams/RecursiveLargestFirst-8                              3.044µ ±   0%    3.040µ ±  0%        ~ (p=0.109 n=10)
Coloring/exams/SanSegundo-8                                         7.403µ ±   1%    7.408µ ±  0%        ~ (p=0.324 n=10)
Coloring/exams/WelshPowell-8                                        1.823µ ±   0%    1.823µ ±  0%        ~ (p=0.867 n=10)
Coloring/exam_scheduler_1/Dsatur-8                                  17.83µ ±   0%    17.84µ ±  0%        ~ (p=0.128 n=10)
Coloring/exam_scheduler_1/DsaturExact-8                             98.82µ ±   0%    98.68µ ±  1%        ~ (p=0.315 n=10)
Coloring/exam_scheduler_1/Randomized-8                              4.232µ ±   0%    4.237µ ±  0%        ~ (p=0.065 n=10)
Coloring/exam_scheduler_1/RecursiveLargestFirst-8                   11.35µ ±   0%    11.33µ ±  0%   -0.17% (p=0.022 n=10)
Coloring/exam_scheduler_1/SanSegundo-8                              27.35µ ±   0%    27.32µ ±  1%        ~ (p=0.494 n=10)
Coloring/exam_scheduler_1/WelshPowell-8                             4.717µ ±   0%    4.716µ ±  0%        ~ (p=0.867 n=10)
Coloring/exam_scheduler_2/Dsatur-8                                  8.313µ ±   0%    8.315µ ±  0%        ~ (p=0.867 n=10)
Coloring/exam_scheduler_2/DsaturExact-8                             47.73µ ±   0%    47.75µ ±  0%        ~ (p=0.971 n=10)
Coloring/exam_scheduler_2/Randomized-8                              2.324µ ±   0%    2.326µ ±  0%        ~ (p=0.118 n=10)
Coloring/exam_scheduler_2/RecursiveLargestFirst-8                   5.167µ ±   0%    5.168µ ±  1%        ~ (p=0.288 n=10)
Coloring/exam_scheduler_2/SanSegundo-8                              12.70µ ±   0%    12.70µ ±  0%        ~ (p=0.644 n=10)
Coloring/exam_scheduler_2/WelshPowell-8                             2.729µ ±   0%    2.729µ ±  0%        ~ (p=0.267 n=10)
Coloring/Brélaz/Dsatur-8                                            12.02µ ±   0%    12.04µ ±  0%   +0.12% (p=0.025 n=10)
Coloring/Brélaz/DsaturExact-8                                       59.18µ ±   0%    59.18µ ±  0%        ~ (p=0.971 n=10)
Coloring/Brélaz/Randomized-8                                        3.052µ ±   0%    3.062µ ±  0%   +0.33% (p=0.000 n=10)
Coloring/Brélaz/RecursiveLargestFirst-8                             7.577µ ±   0%    7.552µ ±  0%   -0.34% (p=0.002 n=10)
Coloring/Brélaz/SanSegundo-8                                        18.30µ ±   0%    18.29µ ±  0%        ~ (p=0.870 n=10)
Coloring/Brélaz/WelshPowell-8                                       3.699µ ±   0%    3.695µ ±  0%        ~ (p=0.054 n=10)
Coloring/Lima_Carmo/Dsatur-8                                        7.529µ ±   2%    7.520µ ±  0%        ~ (p=0.392 n=10)
Coloring/Lima_Carmo/DsaturExact-8                                   32.60µ ±   0%    32.52µ ±  0%   -0.25% (p=0.024 n=10)
Coloring/Lima_Carmo/Randomized-8                                    2.076µ ±   0%    2.071µ ±  0%   -0.26% (p=0.027 n=10)
Coloring/Lima_Carmo/RecursiveLargestFirst-8                         4.184µ ±   0%    4.162µ ±  0%   -0.54% (p=0.000 n=10)
Coloring/Lima_Carmo/SanSegundo-8                                    11.18µ ±   0%    11.16µ ±  0%   -0.20% (p=0.002 n=10)
Coloring/Lima_Carmo/WelshPowell-8                                   2.476µ ±   0%    2.470µ ±  1%   -0.26% (p=0.033 n=10)
Coloring/San_Segundo/Dsatur-8                                       12.73µ ±   0%    12.70µ ±  0%   -0.27% (p=0.002 n=10)
Coloring/San_Segundo/DsaturExact-8                                  119.2µ ±   0%    118.9µ ±  0%   -0.24% (p=0.019 n=10)
Coloring/San_Segundo/Randomized-8                                   3.417µ ±   0%    3.415µ ±  1%        ~ (p=0.725 n=10)
Coloring/San_Segundo/RecursiveLargestFirst-8                        9.219µ ±   0%    9.184µ ±  0%   -0.39% (p=0.008 n=10)
Coloring/San_Segundo/SanSegundo-8                                   22.45µ ±   0%    22.40µ ±  0%        ~ (p=0.172 n=10)
Coloring/San_Segundo/WelshPowell-8                                  3.588µ ±   0%    3.587µ ±  0%        ~ (p=0.752 n=10)
Coloring/tetrahedron/Dsatur-8                                       2.373µ ±   1%    2.372µ ±  0%        ~ (p=0.360 n=10)
Coloring/tetrahedron/DsaturExact-8                                  13.52µ ±   0%    13.49µ ±  0%   -0.25% (p=0.000 n=10)
Coloring/tetrahedron/Randomized-8                                   927.4n ±   0%    926.2n ±  0%        ~ (p=0.343 n=10)
Coloring/tetrahedron/RecursiveLargestFirst-8                        1.853µ ±   0%    1.845µ ±  0%   -0.43% (p=0.000 n=10)
Coloring/tetrahedron/SanSegundo-8                                   3.312µ ±   1%    3.309µ ±  0%        ~ (p=0.469 n=10)
Coloring/tetrahedron/WelshPowell-8                                  1.064µ ±   0%    1.060µ ±  0%   -0.33% (p=0.001 n=10)
Coloring/triangle/Dsatur-8                                          1.473µ ±   0%    1.475µ ±  0%        ~ (p=0.116 n=10)
Coloring/triangle/DsaturExact-8                                     7.213µ ±   0%    7.241µ ±  1%   +0.40% (p=0.000 n=10)
Coloring/triangle/Randomized-8                                      636.5n ±   0%    635.8n ±  0%        ~ (p=0.109 n=10)
Coloring/triangle/RecursiveLargestFirst-8                           1.152µ ±   1%    1.147µ ±  0%   -0.48% (p=0.000 n=10)
Coloring/triangle/SanSegundo-8                                      1.813µ ±   0%    1.815µ ±  0%        ~ (p=0.665 n=10)
Coloring/triangle/WelshPowell-8                                     769.1n ±   0%    767.8n ±  1%        ~ (p=0.085 n=10)
Coloring/square/Dsatur-8                                            2.190µ ±   0%    2.191µ ±  0%        ~ (p=0.322 n=10)
Coloring/square/DsaturExact-8                                       10.79µ ±   1%    10.77µ ±  0%        ~ (p=0.165 n=10)
Coloring/square/Randomized-8                                        856.4n ±   0%    852.8n ±  0%   -0.42% (p=0.001 n=10)
Coloring/square/RecursiveLargestFirst-8                             1.438µ ±   0%    1.415µ ±  0%   -1.63% (p=0.001 n=10)
Coloring/square/SanSegundo-8                                        2.808µ ±   0%    2.797µ ±  0%   -0.41% (p=0.000 n=10)
Coloring/square/WelshPowell-8                                       1.020µ ±   0%    1.016µ ±  0%   -0.39% (p=0.000 n=10)
Coloring/cycle-5/Dsatur-8                                           3.222µ ±   1%    3.209µ ±  0%   -0.39% (p=0.000 n=10)
Coloring/cycle-5/DsaturExact-8                                      19.10µ ±   0%    19.03µ ±  0%   -0.38% (p=0.002 n=10)
Coloring/cycle-5/Randomized-8                                       1.127µ ±   0%    1.123µ ±  0%   -0.35% (p=0.003 n=10)
Coloring/cycle-5/RecursiveLargestFirst-8                            2.119µ ±   0%    2.109µ ±  0%   -0.45% (p=0.000 n=10)
Coloring/cycle-5/SanSegundo-8                                       4.142µ ±   0%    4.134µ ±  0%   -0.18% (p=0.005 n=10)
Coloring/cycle-5/WelshPowell-8                                      1.359µ ±   0%    1.358µ ±  0%   -0.07% (p=0.019 n=10)
Coloring/cycle-6/Dsatur-8                                           4.303µ ±   0%    4.290µ ±  0%   -0.29% (p=0.002 n=10)
Coloring/cycle-6/DsaturExact-8                                      18.22µ ±   0%    18.26µ ±  1%   +0.20% (p=0.003 n=10)
Coloring/cycle-6/Randomized-8                                       1.376µ ±   0%    1.371µ ±  0%   -0.36% (p=0.000 n=10)
Coloring/cycle-6/RecursiveLargestFirst-8                            2.490µ ±   0%    2.481µ ±  0%   -0.38% (p=0.000 n=10)
Coloring/cycle-6/SanSegundo-8                                       5.572µ ±   0%    5.550µ ±  0%   -0.40% (p=0.000 n=10)
Coloring/cycle-6/WelshPowell-8                                      1.665µ ±   0%    1.660µ ±  0%   -0.33% (p=0.001 n=10)
Coloring/wheel-5/Dsatur-8                                           3.446µ ±   0%    3.432µ ±  0%   -0.41% (p=0.003 n=10)
Coloring/wheel-5/DsaturExact-8                                      22.82µ ±   0%    22.72µ ±  0%   -0.44% (p=0.009 n=10)
Coloring/wheel-5/Randomized-8                                       1.227µ ±   1%    1.221µ ±  0%   -0.49% (p=0.000 n=10)
Coloring/wheel-5/RecursiveLargestFirst-8                            2.395µ ±   0%    2.379µ ±  0%   -0.65% (p=0.000 n=10)
Coloring/wheel-5/SanSegundo-8                                       5.155µ ±   0%    5.155µ ±  0%        ~ (p=0.617 n=10)
Coloring/wheel-5/WelshPowell-8                                      1.391µ ±   0%    1.391µ ±  0%        ~ (p=0.869 n=10)
Coloring/wheel-6/Dsatur-8                                           4.816µ ±   0%    4.824µ ±  0%   +0.16% (p=0.004 n=10)
Coloring/wheel-6/DsaturExact-8                                      37.64µ ±   0%    37.65µ ±  0%        ~ (p=0.926 n=10)
Coloring/wheel-6/Randomized-8                                       1.586µ ±   0%    1.592µ ±  0%   +0.35% (p=0.000 n=10)
Coloring/wheel-6/RecursiveLargestFirst-8                            3.311µ ±   0%    3.313µ ±  0%        ~ (p=0.208 n=10)
Coloring/wheel-6/SanSegundo-8                                       7.499µ ±   0%    7.521µ ±  0%   +0.29% (p=0.001 n=10)
Coloring/wheel-6/WelshPowell-8                                      1.800µ ±   0%    1.801µ ±  0%        ~ (p=0.526 n=10)
Coloring/wheel-7/Dsatur-8                                           6.295µ ±   0%    6.298µ ±  0%        ~ (p=0.381 n=10)
Coloring/wheel-7/DsaturExact-8                                      39.04µ ±   0%    39.11µ ±  0%   +0.16% (p=0.002 n=10)
Coloring/wheel-7/Randomized-8                                       1.930µ ±   0%    1.941µ ±  0%   +0.54% (p=0.000 n=10)
Coloring/wheel-7/RecursiveLargestFirst-8                            3.937µ ±   0%    3.946µ ±  0%   +0.24% (p=0.005 n=10)
Coloring/wheel-7/SanSegundo-8                                       10.10µ ±   1%    10.14µ ±  0%   +0.37% (p=0.009 n=10)
Coloring/wheel-7/WelshPowell-8                                      2.169µ ±   0%    2.171µ ±  0%        ~ (p=0.089 n=10)
Coloring/sudoku_board/Dsatur-8                                      21.54m ±   0%    21.61m ±  0%   +0.34% (p=0.043 n=10)
Coloring/sudoku_board/DsaturExact-8                                 86.12m ±   1%    86.51m ±  0%        ~ (p=0.280 n=10)
Coloring/sudoku_board/Randomized-8                                  585.7µ ±   0%    584.9µ ±  0%        ~ (p=0.165 n=10)
Coloring/sudoku_board/RecursiveLargestFirst-8                       3.907m ±   0%    3.874m ±  0%   -0.86% (p=0.000 n=10)
Coloring/sudoku_board/SanSegundo-8                                  25.67m ±   0%    25.72m ±  0%   +0.21% (p=0.015 n=10)
Coloring/sudoku_board/WelshPowell-8                                 691.3µ ±   0%    694.1µ ±  0%   +0.40% (p=0.000 n=10)
Coloring/sudoku_problem/Dsatur-8                                    32.68m ±   0%    32.94m ±  0%   +0.80% (p=0.000 n=10)
Coloring/sudoku_problem/DsaturExact-8                                6.988 ±  45%     6.543 ± 65%        ~ (p=0.631 n=10)
Coloring/sudoku_problem/Randomized-8                                833.7µ ±   0%    831.1µ ±  0%   -0.31% (p=0.011 n=10)
Coloring/sudoku_problem/RecursiveLargestFirst-8                     5.831m ±   0%    5.750m ±  0%   -1.39% (p=0.000 n=10)
Coloring/sudoku_problem/SanSegundo-8                                35.74m ±   0%    35.99m ±  0%   +0.71% (p=0.000 n=10)
Coloring/sudoku_problem/WelshPowell-8                               971.7µ ±   1%    969.7µ ±  0%        ~ (p=0.143 n=10)
Coloring/cs_shc/Dsatur-8                                            3.343µ ±   0%    3.348µ ±  0%   +0.15% (p=0.044 n=10)
Coloring/cs_shc/DsaturExact-8                                       20.27µ ±   0%    20.28µ ±  0%        ~ (p=0.108 n=10)
Coloring/cs_shc/Randomized-8                                        1.198µ ±   0%    1.200µ ±  0%   +0.21% (p=0.006 n=10)
Coloring/cs_shc/RecursiveLargestFirst-8                             2.374µ ±   0%    2.376µ ±  0%        ~ (p=0.071 n=10)
Coloring/cs_shc/SanSegundo-8                                        5.082µ ±   1%    5.103µ ±  0%   +0.42% (p=0.042 n=10)
Coloring/cs_shc/WelshPowell-8                                       1.415µ ±   0%    1.417µ ±  0%        ~ (p=0.171 n=10)
Coloring/gis_hc/Dsatur-8                                            3.951µ ±   0%    3.972µ ±  0%   +0.53% (p=0.000 n=10)
Coloring/gis_hc/DsaturExact-8                                       16.68µ ±   0%    16.73µ ±  0%   +0.31% (p=0.000 n=10)
Coloring/gis_hc/Randomized-8                                        1.284µ ±   1%    1.291µ ±  1%   +0.58% (p=0.002 n=10)
Coloring/gis_hc/RecursiveLargestFirst-8                             2.303µ ±   1%    2.305µ ±  0%        ~ (p=0.202 n=10)
Coloring/gis_hc/SanSegundo-8                                        7.415µ ±   0%    7.428µ ±  0%   +0.18% (p=0.017 n=10)
Coloring/gis_hc/WelshPowell-8                                       1.643µ ±   0%    1.649µ ±  1%   +0.37% (p=0.000 n=10)
Coloring/gis_shc|rs_shc/Dsatur-8                                    2.060µ ±   0%    2.069µ ±  0%   +0.44% (p=0.001 n=10)
Coloring/gis_shc|rs_shc/DsaturExact-8                               9.652µ ±   0%    9.692µ ±  0%   +0.41% (p=0.000 n=10)
Coloring/gis_shc|rs_shc/Randomized-8                                812.1n ±   1%    814.0n ±  0%   +0.23% (p=0.041 n=10)
Coloring/gis_shc|rs_shc/RecursiveLargestFirst-8                     1.336µ ±   0%    1.338µ ±  0%   +0.15% (p=0.017 n=10)
Coloring/gis_shc|rs_shc/SanSegundo-8                                2.686µ ±   0%    2.699µ ±  0%   +0.48% (p=0.000 n=10)
Coloring/gis_shc|rs_shc/WelshPowell-8                               1.011µ ±   0%    1.013µ ±  0%        ~ (p=0.058 n=10)
Coloring/lf_hc/Dsatur-8                                             6.077µ ±   1%    6.102µ ±  1%   +0.41% (p=0.008 n=10)
Coloring/lf_hc/DsaturExact-8                                        32.06µ ±   0%    32.15µ ±  0%   +0.29% (p=0.001 n=10)
Coloring/lf_hc/Randomized-8                                         1.864µ ±   0%    1.868µ ±  0%   +0.21% (p=0.000 n=10)
Coloring/lf_hc/RecursiveLargestFirst-8                              3.701µ ±   0%    3.713µ ±  0%   +0.31% (p=0.004 n=10)
Coloring/lf_hc/SanSegundo-8                                         10.18µ ±   0%    10.23µ ±  0%   +0.45% (p=0.000 n=10)
Coloring/lf_hc/WelshPowell-8                                        2.057µ ±   1%    2.063µ ±  0%   +0.32% (p=0.019 n=10)
Coloring/lf_shc/Dsatur-8                                            4.046µ ±   0%    4.064µ ±  0%   +0.44% (p=0.000 n=10)
Coloring/lf_shc/DsaturExact-8                                       16.66µ ±   0%    16.72µ ±  0%   +0.36% (p=0.000 n=10)
Coloring/lf_shc/Randomized-8                                        1.316µ ±   0%    1.323µ ±  1%   +0.53% (p=0.000 n=10)
Coloring/lf_shc/RecursiveLargestFirst-8                             2.404µ ±   0%    2.411µ ±  0%   +0.29% (p=0.000 n=10)
Coloring/lf_shc/SanSegundo-8                                        4.420µ ±   0%    4.444µ ±  0%   +0.53% (p=0.001 n=10)
Coloring/lf_shc/WelshPowell-8                                       1.586µ ±   0%    1.591µ ±  0%   +0.32% (p=0.000 n=10)
Coloring/lfi_hc/Dsatur-8                                            10.39µ ±   0%    10.44µ ±  0%   +0.50% (p=0.000 n=10)
Coloring/lfi_hc/DsaturExact-8                                       66.70µ ±   0%    66.91µ ±  0%   +0.31% (p=0.009 n=10)
Coloring/lfi_hc/Randomized-8                                        2.694µ ±   1%    2.695µ ±  0%        ~ (p=0.340 n=10)
Coloring/lfi_hc/RecursiveLargestFirst-8                             5.895µ ±   0%    5.915µ ±  0%   +0.35% (p=0.000 n=10)
Coloring/lfi_hc/SanSegundo-8                                        13.85µ ±   0%    13.91µ ±  0%   +0.40% (p=0.000 n=10)
Coloring/lfi_hc/WelshPowell-8                                       3.100µ ±   0%    3.108µ ±  0%   +0.26% (p=0.001 n=10)
Coloring/lfi_shc|slf_shc/Dsatur-8                                   6.155µ ±   0%    6.199µ ±  0%   +0.72% (p=0.000 n=10)
Coloring/lfi_shc|slf_shc/DsaturExact-8                              38.57µ ±   0%    38.81µ ±  0%   +0.63% (p=0.001 n=10)
Coloring/lfi_shc|slf_shc/Randomized-8                               1.815µ ±   0%    1.822µ ±  0%   +0.39% (p=0.000 n=10)
Coloring/lfi_shc|slf_shc/RecursiveLargestFirst-8                    3.516µ ±   0%    3.531µ ±  0%   +0.43% (p=0.000 n=10)
Coloring/lfi_shc|slf_shc/SanSegundo-8                               7.087µ ±   0%    7.134µ ±  0%   +0.67% (p=0.000 n=10)
Coloring/lfi_shc|slf_shc/WelshPowell-8                              2.119µ ±   0%    2.129µ ±  0%   +0.45% (p=0.003 n=10)
Coloring/no_solo/Dsatur-8                                           16.65µ ±   0%    16.74µ ±  1%   +0.55% (p=0.000 n=10)
Coloring/no_solo/DsaturExact-8                                      53.95µ ±   0%    54.13µ ±  0%   +0.32% (p=0.000 n=10)
Coloring/no_solo/Randomized-8                                       3.432µ ±   0%    3.442µ ±  0%   +0.29% (p=0.000 n=10)
Coloring/no_solo/RecursiveLargestFirst-8                            7.645µ ±   0%    7.665µ ±  0%   +0.26% (p=0.000 n=10)
Coloring/no_solo/SanSegundo-8                                       25.06µ ±   0%    25.08µ ±  0%        ~ (p=0.255 n=10)
Coloring/no_solo/WelshPowell-8                                      4.375µ ±   0%    4.385µ ±  0%   +0.23% (p=0.000 n=10)
Coloring/sl_hc/Dsatur-8                                             8.701µ ±   0%    8.728µ ±  0%   +0.30% (p=0.000 n=10)
Coloring/sl_hc/DsaturExact-8                                        73.62µ ±   0%    73.81µ ±  0%   +0.26% (p=0.000 n=10)
Coloring/sl_hc/Randomized-8                                         2.421µ ±   0%    2.432µ ±  0%   +0.45% (p=0.002 n=10)
Coloring/sl_hc/RecursiveLargestFirst-8                              5.232µ ±   0%    5.249µ ±  0%   +0.32% (p=0.017 n=10)
Coloring/sl_hc/SanSegundo-8                                         11.89µ ±   0%    11.95µ ±  0%   +0.54% (p=0.000 n=10)
Coloring/sl_hc/WelshPowell-8                                        2.668µ ±   0%    2.676µ ±  0%   +0.28% (p=0.001 n=10)
Coloring/sl_shc/Dsatur-8                                            4.751µ ±   0%    4.778µ ±  0%   +0.57% (p=0.000 n=10)
Coloring/sl_shc/DsaturExact-8                                       25.04µ ±   0%    25.10µ ±  0%        ~ (p=0.063 n=10)
Coloring/sl_shc/Randomized-8                                        1.520µ ±   0%    1.530µ ±  0%   +0.66% (p=0.000 n=10)
Coloring/sl_shc/RecursiveLargestFirst-8                             2.972µ ±   0%    2.981µ ±  0%   +0.30% (p=0.000 n=10)
Coloring/sl_shc/SanSegundo-8                                        6.927µ ±   0%    6.958µ ±  0%   +0.44% (p=0.000 n=10)
Coloring/sl_shc/WelshPowell-8                                       1.745µ ±   0%    1.754µ ±  0%   +0.52% (p=0.000 n=10)
Coloring/slf_hc/Dsatur-8                                            7.853µ ±   0%    7.899µ ±  0%   +0.59% (p=0.001 n=10)
Coloring/slf_hc/DsaturExact-8                                       49.34µ ±   0%    49.52µ ±  0%   +0.37% (p=0.000 n=10)
Coloring/slf_hc/Randomized-8                                        2.165µ ±   0%    2.175µ ±  0%   +0.46% (p=0.000 n=10)
Coloring/slf_hc/RecursiveLargestFirst-8                             4.609µ ±   0%    4.635µ ±  1%   +0.56% (p=0.000 n=10)
Coloring/slf_hc/SanSegundo-8                                        13.05µ ±   1%    13.13µ ±  0%   +0.63% (p=0.003 n=10)
Coloring/slf_hc/WelshPowell-8                                       2.544µ ±   0%    2.554µ ±  0%   +0.43% (p=0.000 n=10)
Coloring/sli_hc/Dsatur-8                                            12.26µ ±   0%    12.35µ ±  0%   +0.71% (p=0.000 n=10)
Coloring/sli_hc/DsaturExact-8                                       126.5µ ±   0%    126.8µ ±  0%   +0.27% (p=0.000 n=10)
Coloring/sli_hc/Randomized-8                                        3.226µ ±   0%    3.243µ ±  1%   +0.51% (p=0.000 n=10)
Coloring/sli_hc/RecursiveLargestFirst-8                             8.382µ ±   0%    8.385µ ±  0%        ~ (p=0.514 n=10)
Coloring/sli_hc/SanSegundo-8                                        16.55µ ±   0%    16.59µ ±  0%   +0.30% (p=0.000 n=10)
Coloring/sli_hc/WelshPowell-8                                       3.366µ ±   0%    3.377µ ±  0%   +0.33% (p=0.000 n=10)
Coloring/sli_shc/Dsatur-8                                           6.228µ ±   0%    6.258µ ±  0%   +0.48% (p=0.001 n=10)
Coloring/sli_shc/DsaturExact-8                                      30.78µ ±   1%    30.86µ ±  0%   +0.27% (p=0.022 n=10)
Coloring/sli_shc/Randomized-8                                       1.869µ ±   0%    1.876µ ±  0%   +0.37% (p=0.000 n=10)
Coloring/sli_shc/RecursiveLargestFirst-8                            3.783µ ±   0%    3.793µ ±  0%   +0.25% (p=0.000 n=10)
Coloring/sli_shc/SanSegundo-8                                       10.08µ ±   0%    10.11µ ±  0%   +0.31% (p=0.000 n=10)
Coloring/sli_shc/WelshPowell-8                                      2.139µ ±   0%    2.146µ ±  0%   +0.33% (p=0.000 n=10)
Coloring/rsi_shc/Dsatur-8                                           4.529µ ±   0%    4.545µ ±  1%   +0.36% (p=0.004 n=10)
Coloring/rsi_shc/DsaturExact-8                                      23.30µ ±   0%    23.36µ ±  0%   +0.27% (p=0.000 n=10)
Coloring/rsi_shc/Randomized-8                                       1.468µ ±   0%    1.472µ ±  0%   +0.27% (p=0.007 n=10)
Coloring/rsi_shc/RecursiveLargestFirst-8                            2.870µ ±   0%    2.873µ ±  0%        ~ (p=0.446 n=10)
Coloring/rsi_shc/SanSegundo-8                                       5.577µ ±   0%    5.600µ ±  0%   +0.41% (p=0.000 n=10)
Coloring/rsi_shc/WelshPowell-8                                      1.710µ ±   0%    1.715µ ±  0%   +0.26% (p=0.013 n=10)
Coloring/V_plus_not_in_A_cal/Dsatur-8                               8.847µ ±   0%    8.884µ ±  0%   +0.42% (p=0.000 n=10)
Coloring/V_plus_not_in_A_cal/DsaturExact-8                          32.67µ ±   0%    32.78µ ±  0%   +0.32% (p=0.001 n=10)
Coloring/V_plus_not_in_A_cal/Randomized-8                           2.278µ ±   0%    2.282µ ±  0%   +0.18% (p=0.000 n=10)
Coloring/V_plus_not_in_A_cal/RecursiveLargestFirst-8                4.847µ ±   0%    4.855µ ±  1%   +0.17% (p=0.002 n=10)
Coloring/V_plus_not_in_A_cal/SanSegundo-8                           10.61µ ±   0%    10.65µ ±  0%   +0.33% (p=0.005 n=10)
Coloring/V_plus_not_in_A_cal/WelshPowell-8                          2.790µ ±   0%    2.796µ ±  0%   +0.22% (p=0.003 n=10)
Coloring/queen5_5/Dsatur-8                                          284.1µ ±   0%    283.7µ ±  0%        ~ (p=0.165 n=10)
Coloring/queen5_5/DsaturExact-8                                     2.444m ±   0%    2.455m ±  0%   +0.46% (p=0.000 n=10)
Coloring/queen5_5/Randomized-8                                      28.44µ ±   1%    28.56µ ±  0%   +0.40% (p=0.022 n=10)
Coloring/queen5_5/RecursiveLargestFirst-8                           99.80µ ±   0%   100.00µ ±  0%   +0.21% (p=0.043 n=10)
Coloring/queen5_5/SanSegundo-8                                      582.9µ ±   0%    584.2µ ±  0%   +0.22% (p=0.011 n=10)
Coloring/queen5_5/WelshPowell-8                                     31.96µ ±   0%    32.03µ ±  0%   +0.23% (p=0.002 n=10)
Coloring/queen6_6/Dsatur-8                                          1.149m ±   1%    1.158m ±  0%   +0.82% (p=0.003 n=10)
Coloring/queen6_6/DsaturExact-8                                     172.2m ±  14%    160.5m ± 39%        ~ (p=0.853 n=10)
Coloring/queen6_6/Randomized-8                                      75.03µ ±   0%    75.75µ ±  0%   +0.95% (p=0.000 n=10)
Coloring/queen6_6/RecursiveLargestFirst-8                           373.7µ ±   0%    377.2µ ±  1%   +0.94% (p=0.000 n=10)
Coloring/queen6_6/SanSegundo-8                                      1.448m ±   0%    1.454m ±  0%   +0.38% (p=0.000 n=10)
Coloring/queen6_6/WelshPowell-8                                     86.52µ ±   0%    86.39µ ±  0%   -0.16% (p=0.015 n=10)
Coloring/queen7_7/Dsatur-8                                          3.625m ±   1%    3.651m ±  1%   +0.72% (p=0.023 n=10)
Coloring/queen7_7/DsaturExact-8                                      1.112 ±  50%     2.016 ± 19%  +81.35% (p=0.000 n=10)
Coloring/queen7_7/Randomized-8                                      169.9µ ±   0%    170.6µ ±  0%   +0.43% (p=0.000 n=10)
Coloring/queen7_7/RecursiveLargestFirst-8                           980.4µ ±   1%    989.2µ ±  1%   +0.90% (p=0.007 n=10)
Coloring/queen7_7/SanSegundo-8                                      4.277m ±   0%    4.301m ±  0%   +0.57% (p=0.000 n=10)
Coloring/queen7_7/WelshPowell-8                                     196.7µ ±   0%    196.4µ ±  0%   -0.17% (p=0.002 n=10)
Coloring/queen8_8/Dsatur-8                                          10.24m ±   0%    10.31m ±  0%   +0.67% (p=0.000 n=10)
Coloring/queen8_8/Randomized-8                                      367.5µ ±   0%    367.8µ ±  0%        ~ (p=0.063 n=10)
Coloring/queen8_8/RecursiveLargestFirst-8                           2.327m ±   0%    2.313m ±  0%   -0.64% (p=0.000 n=10)
Coloring/queen8_8/SanSegundo-8                                      11.56m ±   0%    11.64m ±  0%   +0.70% (p=0.000 n=10)
Coloring/queen8_8/WelshPowell-8                                     428.9µ ±   0%    428.8µ ±  0%        ~ (p=0.353 n=10)
geomean                                                             11.12µ           11.15µ         +0.24%

pkg: gonum.org/v1/gonum/graph/community
                                                    │ benchmarks_graph_old.txt │      benchmarks_graph_new.txt      │
                                                    │          sec/op          │   sec/op     vs base               │
KCliqueCommunities/simple-k=3-8                                    33.89µ ± 1%   33.79µ ± 1%       ~ (p=0.138 n=10)
KCliqueCommunities/Batagelj-Zaversnik_Graph-k=3-8                  102.5µ ± 0%   102.1µ ± 1%  -0.42% (p=0.043 n=10)
KCliqueCommunities/Batagelj-Zaversnik_Graph-k=4-8                  102.7µ ± 0%   102.0µ ± 1%  -0.70% (p=0.007 n=10)
LouvainDirectedMultiplex-8                                         11.68m ± 0%   11.65m ± 0%  -0.25% (p=0.043 n=10)
NewDirectedLayers/graphSize=1,numGraphs=1-8                        135.1n ± 0%   134.5n ± 0%  -0.41% (p=0.006 n=10)
NewDirectedLayers/graphSize=1,numGraphs=10-8                       1.724µ ± 0%   1.709µ ± 0%  -0.90% (p=0.000 n=10)
NewDirectedLayers/graphSize=10,numGraphs=1-8                       502.8n ± 1%   503.3n ± 1%       ~ (p=0.579 n=10)
NewDirectedLayers/graphSize=10,numGraphs=10-8                      7.665µ ± 1%   7.679µ ± 1%       ~ (p=0.912 n=10)
NewDirectedLayers/graphSize=1000,numGraphs=1-8                     64.21µ ± 1%   64.37µ ± 1%       ~ (p=0.353 n=10)
NewDirectedLayers/graphSize=1000,numGraphs=10-8                    847.2µ ± 0%   851.1µ ± 0%  +0.45% (p=0.007 n=10)
NewDirectedLayers/graphSize=100000,numGraphs=1-8                   6.358m ± 0%   6.408m ± 0%  +0.79% (p=0.002 n=10)
NewDirectedLayers/graphSize=100000,numGraphs=10-8                  92.23m ± 0%   92.94m ± 0%  +0.77% (p=0.000 n=10)
LouvainDirected-8                                                  10.06m ± 0%   10.08m ± 0%       ~ (p=0.089 n=10)
LouvainMultiplex-8                                                 7.714m ± 0%   7.717m ± 0%       ~ (p=0.796 n=10)
NewUndirectedLayers/graphSize=1,numGraphs=1-8                      135.6n ± 0%   134.3n ± 0%  -0.96% (p=0.000 n=10)
NewUndirectedLayers/graphSize=1,numGraphs=10-8                     2.091µ ± 0%   2.077µ ± 0%  -0.67% (p=0.000 n=10)
NewUndirectedLayers/graphSize=10,numGraphs=1-8                     503.0n ± 1%   502.8n ± 1%       ~ (p=0.853 n=10)
NewUndirectedLayers/graphSize=10,numGraphs=10-8                    8.098µ ± 1%   8.095µ ± 1%       ~ (p=0.985 n=10)
NewUndirectedLayers/graphSize=1000,numGraphs=1-8                   63.94µ ± 0%   64.44µ ± 1%  +0.78% (p=0.001 n=10)
NewUndirectedLayers/graphSize=1000,numGraphs=10-8                  853.0µ ± 0%   860.2µ ± 1%  +0.85% (p=0.001 n=10)
NewUndirectedLayers/graphSize=100000,numGraphs=1-8                 6.343m ± 0%   6.405m ± 0%  +0.97% (p=0.002 n=10)
NewUndirectedLayers/graphSize=100000,numGraphs=10-8                92.51m ± 0%   93.14m ± 1%  +0.68% (p=0.000 n=10)
Louvain-8                                                          6.582m ± 1%   6.592m ± 0%       ~ (p=0.247 n=10)
geomean                                                            126.6µ        126.6µ       +0.07%

pkg: gonum.org/v1/gonum/graph/encoding/dot
                                    │ benchmarks_graph_old.txt │      benchmarks_graph_new.txt      │
                                    │          sec/op          │   sec/op     vs base               │
UnmarshalGnp_10_tenth-8                            16.69µ ± 1%   16.80µ ± 1%       ~ (p=0.172 n=10)
UnmarshalGnp_100_tenth-8                           1.067m ± 2%   1.081m ± 1%  +1.34% (p=0.043 n=10)
UnmarshalGnp_1000_tenth-8                          104.4m ± 1%   104.9m ± 1%       ~ (p=0.315 n=10)
UnmarshalGnp_10_half-8                             51.06µ ± 2%   51.25µ ± 1%       ~ (p=0.853 n=10)
UnmarshalGnp_100_half-8                            4.889m ± 1%   4.915m ± 2%       ~ (p=0.123 n=10)
UnmarshalGnp_1000_half-8                           533.9m ± 3%   537.1m ± 0%       ~ (p=0.353 n=10)
UnmarshalMultiPowerLaw_10_tenth-8                  21.95µ ± 1%   22.08µ ± 2%       ~ (p=0.436 n=10)
UnmarshalMultiPowerLaw_100_tenth-8                 1.497m ± 1%   1.506m ± 0%  +0.59% (p=0.035 n=10)
UnmarshalMultiPowerLaw_1000_tenth-8                149.2m ± 1%   151.6m ± 1%  +1.64% (p=0.019 n=10)
UnmarshalMultiPowerLaw_10_half-8                   66.80µ ± 2%   67.44µ ± 1%       ~ (p=0.280 n=10)
UnmarshalMultiPowerLaw_100_half-8                  6.761m ± 3%   6.762m ± 1%       ~ (p=1.000 n=10)
UnmarshalMultiPowerLaw_1000_half-8                 722.4m ± 1%   727.4m ± 1%  +0.69% (p=0.011 n=10)
geomean                                            2.927m        2.948m       +0.71%

pkg: gonum.org/v1/gonum/graph/flow
                                              │ benchmarks_graph_old.txt │      benchmarks_graph_new.txt      │
                                              │          sec/op          │   sec/op     vs base               │
RandomGraphDominators/gnm-n=1e3-m=1e3-8                      707.7µ ± 0%   711.2µ ± 0%  +0.49% (p=0.001 n=10)
RandomGraphDominators/gnm-n=1e3-m=3e3-8                      899.3µ ± 0%   901.0µ ± 0%       ~ (p=0.315 n=10)
RandomGraphDominators/gnm-n=1e3-m=1e4-8                      1.586m ± 1%   1.630m ± 1%  +2.74% (p=0.000 n=10)
RandomGraphDominators/gnm-n=1e3-m=3e4-8                      3.010m ± 0%   3.001m ± 0%  -0.31% (p=0.043 n=10)
RandomGraphDominators/gnm-n=1e4-m=1e4-8                      7.752m ± 1%   7.720m ± 1%  -0.41% (p=0.043 n=10)
RandomGraphDominators/gnm-n=1e4-m=3e4-8                      10.66m ± 0%   10.53m ± 1%  -1.27% (p=0.000 n=10)
RandomGraphDominators/gnm-n=1e4-m=1e5-8                      19.42m ± 1%   19.58m ± 1%       ~ (p=0.063 n=10)
RandomGraphDominators/gnm-n=1e4-m=3e5-8                      40.52m ± 1%   40.68m ± 1%       ~ (p=0.353 n=10)
RandomGraphDominators/gnm-n=1e5-m=1e5-8                      114.5m ± 1%   116.0m ± 1%  +1.33% (p=0.007 n=10)
RandomGraphDominators/gnm-n=1e5-m=3e5-8                      186.4m ± 2%   190.4m ± 3%  +2.10% (p=0.001 n=10)
RandomGraphDominators/gnm-n=1e5-m=1e6-8                      339.5m ± 2%   341.7m ± 1%       ~ (p=0.315 n=10)
RandomGraphDominators/gnm-n=1e5-m=3e6-8                      691.1m ± 5%   710.8m ± 1%  +2.85% (p=0.023 n=10)
RandomGraphDominators/gnm-n=1e6-m=1e6-8                       1.821 ± 1%    1.829 ± 1%       ~ (p=0.075 n=10)
RandomGraphDominators/gnm-n=1e6-m=3e6-8                       3.407 ± 9%    3.443 ± 9%       ~ (p=0.218 n=10)
RandomGraphDominators/gnm-n=1e6-m=1e7-8                       6.366 ± 1%    6.430 ± 1%  +1.01% (p=0.000 n=10)
RandomGraphDominators/gnm-n=1e6-m=3e7-8                       15.15 ± 1%    15.31 ± 0%  +1.06% (p=0.002 n=10)
RandomGraphDominators/dup-n=1e3-d=0.8-a=0.1-8                858.5µ ± 0%   846.9µ ± 1%  -1.35% (p=0.002 n=10)
RandomGraphDominators/dup-n=1e3-d=0.5-a=0.2-8                1.894m ± 0%   1.899m ± 1%       ~ (p=0.123 n=10)
RandomGraphDominators/dup-n=1e4-d=0.8-a=0.1-8                9.244m ± 1%   9.377m ± 1%  +1.43% (p=0.000 n=10)
RandomGraphDominators/dup-n=1e4-d=0.5-a=0.2-8                50.12m ± 1%   50.24m ± 0%       ~ (p=0.393 n=10)
RandomGraphDominators/dup-n=1e5-d=0.8-a=0.1-8                131.9m ± 1%   133.0m ± 2%  +0.84% (p=0.023 n=10)
RandomGraphDominators/dup-n=1e5-d=0.5-a=0.2-8                 2.193 ± 0%    2.251 ± 1%  +2.63% (p=0.002 n=10)
geomean                                                      53.99m        54.41m       +0.78%

pkg: gonum.org/v1/gonum/graph/formats/rdf
                                                │ benchmarks_graph_old.txt │      benchmarks_graph_new.txt      │
                                                │          sec/op          │   sec/op     vs base               │
IsoCanonicalHashes/test019-in.nq/decomp=false-8                13.39µ ± 0%   13.44µ ± 0%  +0.37% (p=0.009 n=10)
IsoCanonicalHashes/test019-in.nq/decomp=true-8                 14.68µ ± 0%   14.71µ ± 0%  +0.20% (p=0.009 n=10)
IsoCanonicalHashes/test044-in.nq/decomp=false-8                236.6m ± 0%   237.0m ± 1%       ~ (p=0.579 n=10)
IsoCanonicalHashes/test044-in.nq/decomp=true-8                 248.2m ± 0%   249.2m ± 0%  +0.43% (p=0.005 n=10)
URNA/test019-in.nq/URDNA2015-8                                 3.239µ ± 0%   3.246µ ± 0%  +0.22% (p=0.003 n=10)
URNA/test019-in.nq/URGNA2012-8                                 3.275µ ± 0%   3.291µ ± 0%  +0.49% (p=0.000 n=10)
URNA/test044-in.nq/URDNA2015-8                                 2.740m ± 0%   2.743m ± 0%       ~ (p=0.105 n=10)
URNA/test044-in.nq/URGNA2012-8                                 2.665m ± 0%   2.669m ± 0%  +0.17% (p=0.043 n=10)
geomean                                                        415.8µ        416.9µ       +0.27%

pkg: gonum.org/v1/gonum/graph/path
                                                      │ benchmarks_graph_old.txt │      benchmarks_graph_new.txt       │
                                                      │          sec/op          │   sec/op     vs base                │
AStarUndirected/GNP_Undirected_10_tenth-8                            2.128µ ± 1%   2.112µ ± 0%   -0.73% (p=0.011 n=10)
AStarUndirected/GNP_Undirected_100_tenth-8                           138.7µ ± 0%   135.0µ ± 0%   -2.69% (p=0.000 n=10)
AStarUndirected/GNP_Undirected_1000_tenth-8                          6.999m ± 6%   7.151m ± 4%        ~ (p=0.063 n=10)
AStarUndirected/GNP_Undirected_10_half-8                             5.487µ ± 0%   5.471µ ± 0%        ~ (p=0.072 n=10)
AStarUndirected/GNP_Undirected_100_half-8                            457.6µ ± 0%   469.9µ ± 0%   +2.70% (p=0.000 n=10)
AStarUndirected/GNP_Undirected_1000_half-8                           14.83m ± 5%   15.07m ± 8%        ~ (p=0.796 n=10)
AStarUndirected/NSW_Undirected_10_2_2_2-8                            33.07µ ± 1%   38.63µ ± 0%  +16.84% (p=0.000 n=10)
AStarUndirected/NSW_Undirected_10_2_2_2_heuristic-8                  6.462µ ± 0%   6.492µ ± 0%   +0.46% (p=0.007 n=10)
AStarUndirected/NSW_Undirected_10_2_5_2-8                            43.92µ ± 1%   49.56µ ± 1%  +12.85% (p=0.000 n=10)
AStarUndirected/NSW_Undirected_10_2_5_2_heuristic-8                  6.594µ ± 0%   6.742µ ± 0%   +2.25% (p=0.000 n=10)
AStarUndirected/NSW_Undirected_100_5_10_2-8                          749.9µ ± 2%   835.5µ ± 3%  +11.42% (p=0.000 n=10)
AStarUndirected/NSW_Undirected_100_5_10_2_heuristic-8                30.95µ ± 1%   30.88µ ± 1%        ~ (p=0.143 n=10)
AStarUndirected/NSW_Undirected_100_5_20_2-8                          2.481m ± 2%   2.382m ± 4%   -4.02% (p=0.005 n=10)
AStarUndirected/NSW_Undirected_100_5_20_2_heuristic-8                62.15µ ± 0%   62.21µ ± 0%        ~ (p=0.247 n=10)
BellmanFordFrom/500_tenth-8                                          2.310m ± 0%   2.310m ± 1%        ~ (p=0.971 n=10)
BellmanFordFrom/500_tenth_incremental-8                              2.340m ± 0%   2.341m ± 0%        ~ (p=0.315 n=10)
BellmanFordFrom/1000_tenth-8                                         9.247m ± 0%   9.253m ± 0%        ~ (p=0.912 n=10)
BellmanFordFrom/1000_tenth_incremental-8                             9.342m ± 0%   9.363m ± 0%   +0.23% (p=0.001 n=10)
BellmanFordFrom/2000_tenth-8                                         41.48m ± 0%   41.64m ± 0%   +0.40% (p=0.000 n=10)
BellmanFordFrom/2000_tenth_incremental-8                             41.99m ± 0%   42.32m ± 0%   +0.78% (p=0.000 n=10)
BellmanFordFrom/500_half-8                                           9.751m ± 1%   9.722m ± 1%   -0.30% (p=0.011 n=10)
BellmanFordFrom/500_half_incremental-8                               9.861m ± 0%   9.836m ± 0%   -0.25% (p=0.000 n=10)
BellmanFordFrom/1000_half-8                                          36.59m ± 0%   36.66m ± 0%        ~ (p=0.436 n=10)
BellmanFordFrom/1000_half_incremental-8                              37.12m ± 0%   37.22m ± 0%        ~ (p=0.052 n=10)
BellmanFordFrom/2000_half-8                                          171.9m ± 0%   171.7m ± 0%        ~ (p=0.796 n=10)
BellmanFordFrom/2000_half_incremental-8                              174.4m ± 0%   175.2m ± 0%   +0.47% (p=0.000 n=10)
BellmanFordFrom/500_full-8                                           16.60m ± 0%   16.62m ± 0%        ~ (p=0.190 n=10)
BellmanFordFrom/500_full_incremental-8                               16.81m ± 0%   16.88m ± 0%   +0.43% (p=0.000 n=10)
BellmanFordFrom/1000_full-8                                          59.36m ± 0%   59.06m ± 0%   -0.50% (p=0.002 n=10)
BellmanFordFrom/1000_full_incremental-8                              60.02m ± 0%   59.82m ± 0%   -0.34% (p=0.043 n=10)
BellmanFordFrom/2000_full-8                                          331.8m ± 0%   332.5m ± 0%   +0.23% (p=0.035 n=10)
BellmanFordFrom/2000_full_incremental-8                              337.0m ± 0%   338.2m ± 0%   +0.37% (p=0.000 n=10)
ShortestAlts/AllTo_100×2|0.5(17)-8                                   4.413µ ± 3%   4.363µ ± 2%        ~ (p=0.796 n=10)
ShortestAlts/AllToFunc_100×2|0.5(17)-8                               3.044µ ± 2%   3.022µ ± 1%        ~ (p=0.481 n=10)
ShortestAlts/AllTo_1000×2|0.5(51)-8                                  27.56µ ± 2%   27.80µ ± 3%        ~ (p=0.579 n=10)
ShortestAlts/AllToFunc_1000×2|0.5(51)-8                              25.43µ ± 2%   25.31µ ± 4%        ~ (p=0.739 n=10)
ShortestAlts/AllTo_100×4|0.25(53)-8                                  7.350µ ± 1%   7.357µ ± 1%        ~ (p=0.986 n=10)
ShortestAlts/AllToFunc_100×4|0.25(53)-8                              4.625µ ± 1%   4.660µ ± 1%        ~ (p=0.066 n=10)
ShortestAlts/AllTo_1000×4|0.25(574)-8                                152.9µ ± 1%   154.2µ ± 1%   +0.83% (p=0.015 n=10)
ShortestAlts/AllToFunc_1000×4|0.25(574)-8                            122.9µ ± 2%   123.2µ ± 2%        ~ (p=0.353 n=10)
ShortestAlts/AllTo_100×16|0.1(76)-8                                  10.51µ ± 2%   10.53µ ± 1%        ~ (p=0.565 n=10)
ShortestAlts/AllToFunc_100×16|0.1(76)-8                              6.498µ ± 1%   6.512µ ± 1%        ~ (p=0.109 n=10)
ShortestAlts/AllTo_1000×16|0.1(822)-8                                221.7µ ± 2%   223.0µ ± 2%        ~ (p=0.684 n=10)
ShortestAlts/AllToFunc_1000×16|0.1(822)-8                            179.9µ ± 1%   181.0µ ± 2%        ~ (p=0.315 n=10)
AllShortest/AllBetween_100×2|0.5(17)-8                               3.831µ ± 2%   3.860µ ± 4%        ~ (p=0.325 n=10)
AllShortest/AllBetweenFunc_100×2|0.5(17)-8                           2.643µ ± 1%   2.643µ ± 0%        ~ (p=0.897 n=10)
AllShortest/AllBetween_1000×2|0.5(51)-8                              27.59µ ± 2%   27.13µ ± 2%        ~ (p=0.063 n=10)
AllShortest/AllBetweenFunc_1000×2|0.5(51)-8                          23.20µ ± 1%   23.22µ ± 1%        ~ (p=0.853 n=10)
AllShortest/AllBetween_100×4|0.25(53)-8                              7.070µ ± 1%   7.095µ ± 1%        ~ (p=0.579 n=10)
AllShortest/AllBetweenFunc_100×4|0.25(53)-8                          4.402µ ± 3%   4.398µ ± 0%        ~ (p=0.699 n=10)
AllShortest/AllBetween_1000×4|0.25(574)-8                            155.7µ ± 1%   155.9µ ± 2%        ~ (p=0.684 n=10)
AllShortest/AllBetweenFunc_1000×4|0.25(574)-8                        121.7µ ± 2%   122.5µ ± 1%        ~ (p=0.143 n=10)
AllShortest/AllBetween_100×16|0.1(76)-8                              10.22µ ± 1%   10.26µ ± 2%        ~ (p=0.137 n=10)
AllShortest/AllBetweenFunc_100×16|0.1(76)-8                          6.242µ ± 1%   6.264µ ± 1%        ~ (p=0.363 n=10)
AllShortest/AllBetween_1000×16|0.1(822)-8                            214.6µ ± 2%   214.5µ ± 1%        ~ (p=0.853 n=10)
AllShortest/AllBetweenFunc_1000×16|0.1(822)-8                        177.3µ ± 1%   177.9µ ± 2%        ~ (p=0.971 n=10)
geomean                                                              329.0µ        331.6µ        +0.81%

pkg: gonum.org/v1/gonum/graph/product
                                        │ benchmarks_graph_old.txt │      benchmarks_graph_new.txt       │
                                        │          sec/op          │    sec/op     vs base               │
Product/Cartesian_50-0.05-8                           5.941m ±  8%   5.964m ±  8%       ~ (p=0.912 n=10)
Product/Cartesian_100-0.05-8                          45.03m ±  8%   45.32m ±  5%       ~ (p=0.912 n=10)
Product/Cartesian_50-0.25-8                           25.75m ±  3%   26.07m ±  4%       ~ (p=0.631 n=10)
Product/Cartesian_100-0.25-8                          228.5m ±  5%   234.9m ±  5%       ~ (p=0.393 n=10)
Product/Cartesian_50-0.50-8                           50.07m ±  5%   50.34m ±  2%       ~ (p=0.796 n=10)
Product/Cartesian_100-0.50-8                          454.9m ±  3%   458.1m ±  2%       ~ (p=0.631 n=10)
Product/Cartesian_50-0.75-8                           78.06m ±  2%   78.76m ±  2%       ~ (p=0.353 n=10)
Product/Cartesian_100-0.75-8                          716.9m ±  2%   723.6m ±  2%       ~ (p=0.089 n=10)
Product/Cartesian_50-0.95-8                           93.71m ±  1%   93.56m ±  1%       ~ (p=0.971 n=10)
Product/Cartesian_100-0.95-8                          851.1m ±  2%   857.0m ±  2%       ~ (p=0.481 n=10)
Product/Cartesian_naive_50-0.05-8                     211.2m ±  2%   210.2m ±  2%       ~ (p=0.631 n=10)
Product/Cartesian_naive_100-0.05-8                     3.348 ±  1%    3.344 ±  1%       ~ (p=0.796 n=10)
Product/Cartesian_naive_50-0.25-8                     341.6m ±  4%   344.5m ±  2%       ~ (p=0.579 n=10)
Product/Cartesian_naive_100-0.25-8                     5.399 ±  2%    5.427 ±  1%       ~ (p=0.631 n=10)
Product/Cartesian_naive_50-0.50-8                     488.4m ±  3%   488.0m ±  2%       ~ (p=0.912 n=10)
Product/Cartesian_naive_100-0.50-8                     7.279 ±  1%    7.284 ±  1%       ~ (p=0.393 n=10)
Product/Cartesian_naive_50-0.75-8                     603.5m ±  1%   602.6m ±  2%       ~ (p=0.971 n=10)
Product/Cartesian_naive_100-0.75-8                     8.719 ±  0%    8.748 ±  1%       ~ (p=0.105 n=10)
Product/Cartesian_naive_50-0.95-8                     686.5m ±  1%   688.1m ±  1%       ~ (p=0.052 n=10)
Product/Cartesian_naive_100-0.95-8                     9.901 ±  0%    9.945 ±  0%  +0.44% (p=0.004 n=10)
Product/CoNormal_50-0.05-8                            192.7m ±  7%   190.8m ± 12%       ~ (p=0.912 n=10)
Product/CoNormal_50-0.25-8                             1.118 ±  6%    1.135 ±  6%       ~ (p=0.684 n=10)
Product/CoNormal_50-0.50-8                             2.387 ±  2%    2.429 ±  5%       ~ (p=0.481 n=10)
Product/CoNormal_50-0.75-8                             3.433 ±  3%    3.473 ±  1%       ~ (p=0.436 n=10)
Product/CoNormal_50-0.95-8                             4.242 ±  1%    4.218 ±  4%       ~ (p=0.579 n=10)
Product/CoNormal_naive_50-0.05-8                      420.9m ±  8%   423.4m ±  9%       ~ (p=0.529 n=10)
Product/CoNormal_naive_50-0.25-8                       1.534 ±  2%    1.545 ±  3%       ~ (p=0.481 n=10)
Product/CoNormal_naive_50-0.50-8                       2.685 ±  4%    2.672 ±  5%       ~ (p=0.796 n=10)
Product/CoNormal_naive_50-0.75-8                       3.148 ±  2%    3.211 ±  2%  +2.01% (p=0.023 n=10)
Product/CoNormal_naive_50-0.95-8                       3.293 ±  2%    3.335 ±  2%       ~ (p=0.143 n=10)
Product/Lexicographical_50-0.05-8                     94.48m ± 14%   98.23m ± 14%       ~ (p=0.529 n=10)
Product/Lexicographical_50-0.25-8                     517.1m ±  6%   527.5m ±  6%       ~ (p=0.393 n=10)
Product/Lexicographical_50-0.50-8                      1.139 ±  3%    1.149 ±  5%       ~ (p=0.579 n=10)
Product/Lexicographical_50-0.75-8                      1.833 ±  2%    1.874 ±  4%       ~ (p=0.218 n=10)
Product/Lexicographical_50-0.95-8                      2.299 ±  2%    2.293 ±  5%       ~ (p=0.684 n=10)
Product/Lexicographical_naive_50-0.05-8               308.5m ±  7%   308.7m ±  5%       ~ (p=1.000 n=10)
Product/Lexicographical_naive_50-0.25-8               928.7m ±  8%   953.4m ±  7%       ~ (p=0.393 n=10)
Product/Lexicographical_naive_50-0.50-8                1.816 ±  3%    1.824 ±  5%       ~ (p=0.529 n=10)
Product/Lexicographical_naive_50-0.75-8                2.731 ±  4%    2.744 ±  4%       ~ (p=0.853 n=10)
Product/Lexicographical_naive_50-0.95-8                3.302 ±  2%    3.268 ±  3%       ~ (p=0.481 n=10)
Product/Modular_50-0.05-8                              2.714 ±  2%    2.777 ±  3%  +2.34% (p=0.035 n=10)
Product/Modular_50-0.25-8                              1.946 ±  4%    1.981 ±  4%       ~ (p=0.143 n=10)
Product/Modular_50-0.50-8                              1.856 ±  1%    1.866 ±  2%       ~ (p=0.579 n=10)
Product/Modular_50-0.75-8                              2.201 ±  3%    2.198 ±  2%       ~ (p=1.000 n=10)
Product/Modular_50-0.95-8                              3.129 ±  1%    3.166 ±  2%       ~ (p=0.063 n=10)
Product/Modular_naive_50-0.05-8                        2.700 ±  4%    2.744 ±  3%       ~ (p=0.105 n=10)
Product/Modular_naive_50-0.25-8                        1.953 ±  3%    1.979 ±  3%       ~ (p=0.280 n=10)
Product/Modular_naive_50-0.50-8                        1.876 ±  2%    1.879 ±  3%       ~ (p=0.796 n=10)
Product/Modular_naive_50-0.75-8                        2.168 ±  3%    2.200 ±  1%       ~ (p=0.105 n=10)
Product/Modular_naive_50-0.95-8                        3.201 ±  2%    3.210 ±  3%       ~ (p=0.631 n=10)
Product/Strong_50-0.05-8                              13.58m ± 17%   13.53m ± 17%       ~ (p=0.912 n=10)
Product/Strong_50-0.25-8                              189.5m ±  8%   190.6m ±  8%       ~ (p=0.912 n=10)
Product/Strong_50-0.50-8                              713.4m ±  8%   719.1m ±  6%       ~ (p=0.971 n=10)
Product/Strong_50-0.75-8                               1.593 ±  3%    1.611 ±  2%       ~ (p=0.165 n=10)
Product/Strong_50-0.95-8                               2.648 ±  2%    2.686 ±  2%       ~ (p=0.075 n=10)
Product/Strong_naive_50-0.05-8                        215.4m ±  2%   216.5m ±  1%       ~ (p=0.631 n=10)
Product/Strong_naive_50-0.25-8                        495.2m ±  4%   497.3m ±  6%       ~ (p=0.853 n=10)
Product/Strong_naive_50-0.50-8                         1.158 ±  3%    1.159 ±  3%       ~ (p=0.481 n=10)
Product/Strong_naive_50-0.75-8                         2.106 ±  2%    2.098 ±  4%       ~ (p=0.579 n=10)
Product/Strong_naive_50-0.95-8                         3.241 ±  1%    3.271 ±  4%       ~ (p=0.436 n=10)
Product/Tensor_50-0.05-8                              7.177m ± 17%   7.328m ± 16%       ~ (p=0.631 n=10)
Product/Tensor_50-0.25-8                              160.2m ±  9%   157.5m ±  8%       ~ (p=1.000 n=10)
Product/Tensor_50-0.50-8                              642.7m ±  3%   640.5m ±  5%       ~ (p=0.971 n=10)
Product/Tensor_50-0.75-8                               1.470 ±  4%    1.485 ±  3%       ~ (p=0.971 n=10)
Product/Tensor_50-0.95-8                               2.525 ±  3%    2.534 ±  2%       ~ (p=0.436 n=10)
Product/Tensor_naive_50-0.05-8                        194.5m ±  4%   194.2m ±  2%       ~ (p=0.912 n=10)
Product/Tensor_naive_50-0.25-8                        450.3m ±  4%   449.7m ±  4%       ~ (p=0.971 n=10)
Product/Tensor_naive_50-0.50-8                         1.056 ±  4%    1.063 ±  4%       ~ (p=0.684 n=10)
Product/Tensor_naive_50-0.75-8                         1.990 ±  3%    2.012 ±  4%       ~ (p=0.393 n=10)
Product/Tensor_naive_50-0.95-8                         3.070 ±  2%    3.139 ±  3%       ~ (p=0.052 n=10)
geomean                                               801.3m         807.0m        +0.71%

pkg: gonum.org/v1/gonum/graph/topo
                                        │ benchmarks_graph_old.txt │      benchmarks_graph_new.txt      │
                                        │          sec/op          │   sec/op     vs base               │
TarjanSCCGnp_10_tenth-8                                3.845µ ± 0%   3.806µ ± 1%  -1.01% (p=0.000 n=10)
TarjanSCCGnp_100_tenth-8                               154.2µ ± 0%   154.3µ ± 1%       ~ (p=0.481 n=10)
TarjanSCCGnp_1000_tenth-8                              8.801m ± 0%   8.795m ± 0%       ~ (p=0.912 n=10)
TarjanSCCGnp_10_half-8                                 8.267µ ± 0%   8.354µ ± 0%  +1.06% (p=0.000 n=10)
TarjanSCCGnp_100_half-8                                593.1µ ± 0%   595.4µ ± 0%  +0.38% (p=0.023 n=10)
TarjanSCCGnp_1000_half-8                               40.04m ± 0%   40.13m ± 1%       ~ (p=0.218 n=10)
DirectedCyclesInGnp_10_tenth-8                         13.41µ ± 1%   13.43µ ± 1%       ~ (p=0.280 n=10)
DirectedCyclesInGnp_10_half-8                          2.464m ± 0%   2.474m ± 0%  +0.38% (p=0.005 n=10)
UndirectedCyclesInGnp_10_tenth-8                       2.245µ ± 1%   2.281µ ± 0%  +1.58% (p=0.000 n=10)
UndirectedCyclesInGnp_100_tenth-8                      217.9µ ± 1%   219.4µ ± 1%  +0.69% (p=0.019 n=10)
UndirectedCyclesInGnp_10_half-8                        9.213µ ± 0%   9.220µ ± 0%       ~ (p=0.118 n=10)
UndirectedCyclesInGnp_100_half-8                       788.2µ ± 1%   789.5µ ± 1%       ~ (p=0.353 n=10)
BronKerbosch/wikipedia_example-8                       11.23µ ± 0%   11.10µ ± 1%  -1.19% (p=0.001 n=10)
BronKerbosch/Batagelj-Zaversnik_Graph-8                59.41µ ± 0%   59.22µ ± 1%       ~ (p=0.315 n=10)
CliqueGraph/simple-8                                   31.64µ ± 1%   31.48µ ± 2%       ~ (p=0.190 n=10)
CliqueGraph/Batagelj-Zaversnik_Graph-8                 84.98µ ± 0%   85.63µ ± 0%  +0.77% (p=0.000 n=10)
geomean                                                104.9µ        105.1µ       +0.15%

pkg: gonum.org/v1/gonum/graph/traverse
                                    │ benchmarks_graph_old.txt │      benchmarks_graph_new.txt      │
                                    │          sec/op          │   sec/op     vs base               │
WalkAllBreadthFirstGnp_10_tenth-8                  1.630µ ± 2%   1.637µ ± 0%       ~ (p=0.065 n=10)
WalkAllBreadthFirstGnp_100_tenth-8                 73.87µ ± 0%   74.54µ ± 0%  +0.90% (p=0.000 n=10)
WalkAllBreadthFirstGnp_1000_tenth-8                5.746m ± 0%   5.767m ± 0%  +0.37% (p=0.002 n=10)
WalkAllBreadthFirstGnp_10_half-8                   4.114µ ± 0%   4.122µ ± 0%  +0.19% (p=0.034 n=10)
WalkAllBreadthFirstGnp_100_half-8                  323.2µ ± 0%   323.2µ ± 0%       ~ (p=0.631 n=10)
WalkAllBreadthFirstGnp_1000_half-8                 25.46m ± 0%   25.35m ± 0%  -0.45% (p=0.005 n=10)
WalkAllDepthFirstGnp_10_tenth-8                    1.662µ ± 0%   1.661µ ± 1%       ~ (p=0.725 n=10)
WalkAllDepthFirstGnp_100_tenth-8                   77.28µ ± 0%   77.72µ ± 0%  +0.57% (p=0.000 n=10)
WalkAllDepthFirstGnp_1000_tenth-8                  5.744m ± 1%   5.707m ± 1%  -0.65% (p=0.003 n=10)
WalkAllDepthFirstGnp_10_half-8                     4.080µ ± 0%   4.104µ ± 1%  +0.59% (p=0.000 n=10)
WalkAllDepthFirstGnp_100_half-8                    349.8µ ± 0%   347.8µ ± 0%  -0.57% (p=0.000 n=10)
WalkAllDepthFirstGnp_1000_half-8                   25.07m ± 1%   24.90m ± 0%  -0.70% (p=0.000 n=10)
geomean                                            170.8µ        170.9µ       +0.05%
```
</details>
jbduncan: I've rebased and dropped the TODO commit to stop polluting the history.
kortschak: Can you run some cases of Coloring/queen7_7/DsaturExact-8? This benchmark is a little brittle. Re-ordering the commits in this PR would be helpful — benchmarks precede change in implementation — so that the change in performance can be confirmed.
kortschak: ```
goos: linux
goarch: amd64
pkg: gonum.org/v1/gonum/graph/coloring
cpu: Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz
                                │ old.bench  │           new.bench           │
                                │   sec/op   │   sec/op    vs base           │
Coloring/queen7_7/DsaturExact-8   1.530 ± 7%   1.579 ± 8%  ~ (p=0.665 n=500)
```
I think we are good.
jbduncan: @kortschak Sorry for the delay, IRL things got in the way!

I believe I've addressed your most recent feedback, so let me know how you'd like to proceed.
jbduncan: > LGTM after nits. Please squash this all into one commit. The PR title is a good commit title.

Perfect! I've just squashed and pushed everything after applying your feedback. Let's hope CI passes. :crossed_fingers: 

Patch:
diff --git a/graph/coloring/coloring.go b/graph/coloring/coloring.go
index 9159ea27..98f5fc75 100644
--- a/graph/coloring/coloring.go
+++ b/graph/coloring/coloring.go
@@ -128,13 +128,13 @@ func DsaturExact(term Terminator, g graph.Undirected) (k int, colors map[int64]i
 // dSaturColoring is a partial graph coloring.
 type dSaturColoring struct {
 	colors    map[int64]int
-	uncolored set.Int64s
+	uncolored set.Ints[int64]
 }
 
 // newDsaturColoring returns a dSaturColoring representing a partial coloring
 // of a graph with the given nodes and colors.
 func newDsaturColoring(nodes []graph.Node, colors map[int64]int) dSaturColoring {
-	uncolored := make(set.Int64s)
+	uncolored := make(set.Ints[int64])
 	for _, v := range nodes {
 		vid := v.ID()
 		if _, ok := colors[vid]; !ok {
@@ -193,7 +193,7 @@ func dSaturExact(term Terminator, selector *saturationDegree, cand dSaturColorin
 			if best == nil {
 				return -1, nil, term.Err()
 			}
-			colors := make(set.Ints)
+			colors := make(set.Ints[int])
 			for _, c := range best {
 				colors.Add(c)
 			}
@@ -215,7 +215,7 @@ func dSaturExact(term Terminator, selector *saturationDegree, cand dSaturColorin
 	adjColors := selector.adjColors[selector.indexOf[vid]]
 
 	// Collect all feasible existing colors plus one, remembering it.
-	feasible := make(set.Ints)
+	feasible := make(set.Ints[int])
 	for _, c := range cand.colors {
 		if adjColors.Has(c) {
 			continue
@@ -293,7 +293,7 @@ func bestMaximumClique(g graph.Undirected, cliques [][]graph.Node) (colors map[i
 
 // cliqueDegree returns the degree of the clique to nodes outside the clique.
 func cliqueDegree(g graph.Undirected, clique []graph.Node) int {
-	n := make(set.Int64s)
+	n := make(set.Ints[int64])
 	for _, u := range clique {
 		to := g.From(u.ID())
 		for to.Next() {
@@ -584,7 +584,7 @@ func greedyColoringOf(g graph.Undirected, order graph.Nodes, partial map[int64]i
 	if !constrained {
 		return k + 1, colors
 	}
-	seen := make(set.Ints)
+	seen := make(set.Ints[int])
 	for _, c := range colors {
 		seen.Add(c)
 	}
@@ -593,8 +593,8 @@ func greedyColoringOf(g graph.Undirected, order graph.Nodes, partial map[int64]i
 
 // colorsOf returns all the colors in the coloring that are used by the
 // given nodes.
-func colorsOf(nodes graph.Nodes, coloring map[int64]int) set.Ints {
-	c := make(set.Ints, nodes.Len())
+func colorsOf(nodes graph.Nodes, coloring map[int64]int) set.Ints[int] {
+	c := make(set.Ints[int], nodes.Len())
 	for nodes.Next() {
 		used, ok := coloring[nodes.Node().ID()]
 		if ok {
@@ -692,7 +692,7 @@ type saturationDegree struct {
 	// colors of each node.
 	indexOf   map[int64]int
 	degrees   []int
-	adjColors []set.Ints
+	adjColors []set.Ints[int]
 
 	// g and colors are the graph coloring.
 	// colors is held by both the iterator
@@ -712,13 +712,13 @@ func newSaturationDegree(it graph.Nodes, g graph.Undirected, colors map[int64]in
 		nodes:     nodes,
 		indexOf:   make(map[int64]int, len(nodes)),
 		degrees:   make([]int, len(nodes)),
-		adjColors: make([]set.Ints, len(nodes)),
+		adjColors: make([]set.Ints[int], len(nodes)),
 		g:         g,
 		colors:    colors,
 	}
 	for i, u := range nodes {
 		sd.degrees[i] = g.From(u.ID()).Len()
-		sd.adjColors[i] = make(set.Ints)
+		sd.adjColors[i] = make(set.Ints[int])
 		sd.indexOf[u.ID()] = i
 	}
 	for uid, c := range colors {
@@ -734,7 +734,7 @@ func newSaturationDegree(it graph.Nodes, g graph.Undirected, colors map[int64]in
 func (sd *saturationDegree) reset(colors map[int64]int) {
 	sd.colors = colors
 	for i := range sd.nodes {
-		sd.adjColors[i] = make(set.Ints)
+		sd.adjColors[i] = make(set.Ints[int])
 	}
 	for uid, c := range colors {
 		to := sd.g.From(uid)
@@ -804,8 +804,8 @@ func (sd *saturationDegree) pass() int {
 }
 
 // same implements the same function from San Segundo doi:10.1016/j.cor.2011.10.008.
-func (sd *saturationDegree) same(vi, vj set.Ints) int {
-	valid := make(set.Ints)
+func (sd *saturationDegree) same(vi, vj set.Ints[int]) int {
+	valid := make(set.Ints[int])
 	for _, c := range sd.colors {
 		if !vi.Has(c) {
 			valid.Add(c)
@@ -823,7 +823,7 @@ func saturationDegreeOf(vid int64, g graph.Undirected, colors map[int64]int) int
 	if _, ok := colors[vid]; ok {
 		panic("coloring: saturation degree not defined for colored node")
 	}
-	adjColors := make(set.Ints)
+	adjColors := make(set.Ints[int])
 	to := g.From(vid)
 	for to.Next() {
 		if c, ok := colors[to.Node().ID()]; ok {
diff --git a/graph/community/louvain_common.go b/graph/community/louvain_common.go
index c54d33bf..e8fad4b2 100644
--- a/graph/community/louvain_common.go
+++ b/graph/community/louvain_common.go
@@ -342,7 +342,7 @@ type slice struct {
 }
 
 // newSlice returns a new slice of elements from s, sorted ascending.
-func newSlice(s set.Ints) *slice {
+func newSlice(s set.Ints[int]) *slice {
 	elems := make([]int, 0, len(s))
 	for i := range s {
 		elems = append(elems, i)
diff --git a/graph/community/louvain_directed.go b/graph/community/louvain_directed.go
index ac070f35..4b2fe371 100644
--- a/graph/community/louvain_directed.go
+++ b/graph/community/louvain_directed.go
@@ -593,7 +593,7 @@ func (l *directedLocalMover) deltaQ(n graph.Node) (deltaQ float64, dst int, src
 	gamma := l.resolution
 
 	// Find communities connected to n.
-	connected := make(set.Ints)
+	connected := make(set.Ints[int])
 	// The following for loop is equivalent to:
 	//
 	//  for _, v := range l.g.From(n) {
diff --git a/graph/community/louvain_directed_multiplex.go b/graph/community/louvain_directed_multiplex.go
index 6bd988ca..f466eb70 100644
--- a/graph/community/louvain_directed_multiplex.go
+++ b/graph/community/louvain_directed_multiplex.go
@@ -133,18 +133,18 @@ func NewDirectedLayers(layers ...graph.Directed) (DirectedLayers, error) {
 	if len(layers) == 0 {
 		return nil, nil
 	}
-	base := make(set.Int64s)
+	base := make(set.Ints[int64])
 	nodes := layers[0].Nodes()
 	for nodes.Next() {
 		base.Add(nodes.Node().ID())
 	}
 	for i, l := range layers[1:] {
-		next := make(set.Int64s)
+		next := make(set.Ints[int64])
 		nodes := l.Nodes()
 		for nodes.Next() {
 			next.Add(nodes.Node().ID())
 		}
-		if !set.Int64sEqual(base, next) {
+		if !set.IntsEqual(base, next) {
 			return nil, fmt.Errorf("community: layer ID mismatch between layers: %d", i+1)
 		}
 	}
@@ -796,7 +796,7 @@ func (l *directedMultiplexLocalMover) deltaQ(n graph.Node) (deltaQ float64, dst
 		iterator = &dense{n: len(l.communities)}
 	} else {
 		// Find communities connected to n.
-		connected := make(set.Ints)
+		connected := make(set.Ints[int])
 		// The following for loop is equivalent to:
 		//
 		//  for i := 0; i < l.g.Depth(); i++ {
diff --git a/graph/community/louvain_undirected.go b/graph/community/louvain_undirected.go
index 60f6a092..e3ed53ba 100644
--- a/graph/community/louvain_undirected.go
+++ b/graph/community/louvain_undirected.go
@@ -536,7 +536,7 @@ func (l *undirectedLocalMover) deltaQ(n graph.Node) (deltaQ float64, dst int, sr
 	gamma := l.resolution
 
 	// Find communities connected to n.
-	connected := make(set.Ints)
+	connected := make(set.Ints[int])
 	// The following for loop is equivalent to:
 	//
 	//  for _, v := range l.g.From(n) {
diff --git a/graph/community/louvain_undirected_multiplex.go b/graph/community/louvain_undirected_multiplex.go
index 0a8af3ca..8a4ce140 100644
--- a/graph/community/louvain_undirected_multiplex.go
+++ b/graph/community/louvain_undirected_multiplex.go
@@ -129,18 +129,18 @@ func NewUndirectedLayers(layers ...graph.Undirected) (UndirectedLayers, error) {
 	if len(layers) == 0 {
 		return nil, nil
 	}
-	base := make(set.Int64s)
+	base := make(set.Ints[int64])
 	nodes := layers[0].Nodes()
 	for nodes.Next() {
 		base.Add(nodes.Node().ID())
 	}
 	for i, l := range layers[1:] {
-		next := make(set.Int64s)
+		next := make(set.Ints[int64])
 		nodes := l.Nodes()
 		for nodes.Next() {
 			next.Add(nodes.Node().ID())
 		}
-		if !set.Int64sEqual(next, base) {
+		if !set.IntsEqual(next, base) {
 			return nil, fmt.Errorf("community: layer ID mismatch between layers: %d", i+1)
 		}
 	}
@@ -735,7 +735,7 @@ func (l *undirectedMultiplexLocalMover) deltaQ(n graph.Node) (deltaQ float64, ds
 		iterator = &dense{n: len(l.communities)}
 	} else {
 		// Find communities connected to n.
-		connected := make(set.Ints)
+		connected := make(set.Ints[int])
 		// The following for loop is equivalent to:
 		//
 		//  for i := 0; i < l.g.Depth(); i++ {
diff --git a/graph/encoding/dot/decode.go b/graph/encoding/dot/decode.go
index 17dd9d68..6b78269d 100644
--- a/graph/encoding/dot/decode.go
+++ b/graph/encoding/dot/decode.go
@@ -358,7 +358,7 @@ func (gen *generator) popSubgraph() []graph.Node {
 // unique returns the set of unique nodes contained within ns.
 func unique(ns []graph.Node) []graph.Node {
 	var nodes []graph.Node
-	seen := make(set.Int64s)
+	seen := make(set.Ints[int64])
 	for _, n := range ns {
 		id := n.ID()
 		if seen.Has(id) {
diff --git a/graph/internal/set/same.go b/graph/internal/set/same.go
index a7031e4a..90189f09 100644
--- a/graph/internal/set/same.go
+++ b/graph/internal/set/same.go
@@ -23,15 +23,6 @@ func same(a, b Nodes) bool {
 // hash maps are passed as a pointer to a runtime Hmap struct. A map is
 // not seen by the runtime as a pointer though, so we use unsafe to get
 // the maps' pointer values to compare.
-func intsSame(a, b Ints) bool {
-	return *(*uintptr)(unsafe.Pointer(&a)) == *(*uintptr)(unsafe.Pointer(&b))
-}
-
-// int64sSame determines whether two sets are backed by the same store. In the
-// current implementation using hash maps it makes use of the fact that
-// hash maps are passed as a pointer to a runtime Hmap struct. A map is
-// not seen by the runtime as a pointer though, so we use unsafe to get
-// the maps' pointer values to compare.
-func int64sSame(a, b Int64s) bool {
+func intsSame[T Int](a, b Ints[T]) bool {
 	return *(*uintptr)(unsafe.Pointer(&a)) == *(*uintptr)(unsafe.Pointer(&b))
 }
diff --git a/graph/internal/set/same_appengine.go b/graph/internal/set/same_appengine.go
index 368823d4..ae8aa4d7 100644
--- a/graph/internal/set/same_appengine.go
+++ b/graph/internal/set/same_appengine.go
@@ -23,15 +23,6 @@ func same(a, b Nodes) bool {
 // hash maps are passed as a pointer to a runtime Hmap struct. A map is
 // not seen by the runtime as a pointer though, so we use reflect to get
 // the maps' pointer values to compare.
-func intsSame(a, b Ints) bool {
-	return reflect.ValueOf(a).Pointer() == reflect.ValueOf(b).Pointer()
-}
-
-// int64sSame determines whether two sets are backed by the same store. In the
-// current implementation using hash maps it makes use of the fact that
-// hash maps are passed as a pointer to a runtime Hmap struct. A map is
-// not seen by the runtime as a pointer though, so we use reflect to get
-// the maps' pointer values to compare.
-func int64sSame(a, b Int64s) bool {
+func intsSame[T Int](a, b Ints[T]) bool {
 	return reflect.ValueOf(a).Pointer() == reflect.ValueOf(b).Pointer()
 }
diff --git a/graph/internal/set/set.go b/graph/internal/set/set.go
index 8067e281..2175e480 100644
--- a/graph/internal/set/set.go
+++ b/graph/internal/set/set.go
@@ -6,36 +6,34 @@ package set
 
 import "gonum.org/v1/gonum/graph"
 
-// Ints is a set of int identifiers.
-type Ints map[int]struct{}
+type Int interface{ ~int | ~int64 }
 
-// The simple accessor methods for Ints are provided to allow ease of
-// implementation change should the need arise.
+type Ints[T Int] map[T]struct{}
 
 // Add inserts an element into the set.
-func (s Ints) Add(e int) {
+func (s Ints[T]) Add(e T) {
 	s[e] = struct{}{}
 }
 
 // Has reports the existence of the element in the set.
-func (s Ints) Has(e int) bool {
+func (s Ints[T]) Has(e T) bool {
 	_, ok := s[e]
 	return ok
 }
 
 // Remove deletes the specified element from the set.
-func (s Ints) Remove(e int) {
+func (s Ints[T]) Remove(e T) {
 	delete(s, e)
 }
 
 // Count reports the number of elements stored in the set.
-func (s Ints) Count() int {
+func (s Ints[T]) Count() int {
 	return len(s)
 }
 
 // IntsEqual reports set equality between the parameters. Sets are equal if
 // and only if they have the same elements.
-func IntsEqual(a, b Ints) bool {
+func IntsEqual[T Int](a, b Ints[T]) bool {
 	if intsSame(a, b) {
 		return true
 	}
@@ -53,53 +51,6 @@ func IntsEqual(a, b Ints) bool {
 	return true
 }
 
-// Int64s is a set of int64 identifiers.
-type Int64s map[int64]struct{}
-
-// The simple accessor methods for Ints are provided to allow ease of
-// implementation change should the need arise.
-
-// Add inserts an element into the set.
-func (s Int64s) Add(e int64) {
-	s[e] = struct{}{}
-}
-
-// Has reports the existence of the element in the set.
-func (s Int64s) Has(e int64) bool {
-	_, ok := s[e]
-	return ok
-}
-
-// Remove deletes the specified element from the set.
-func (s Int64s) Remove(e int64) {
-	delete(s, e)
-}
-
-// Count reports the number of elements stored in the set.
-func (s Int64s) Count() int {
-	return len(s)
-}
-
-// Int64sEqual reports set equality between the parameters. Sets are equal if
-// and only if they have the same elements.
-func Int64sEqual(a, b Int64s) bool {
-	if int64sSame(a, b) {
-		return true
-	}
-
-	if len(a) != len(b) {
-		return false
-	}
-
-	for e := range a {
-		if _, ok := b[e]; !ok {
-			return false
-		}
-	}
-
-	return true
-}
-
 // Nodes is a set of nodes keyed in their integer identifiers.
 type Nodes map[int64]graph.Node
 
diff --git a/graph/path/a_star.go b/graph/path/a_star.go
index 27adb501..efb75069 100644
--- a/graph/path/a_star.go
+++ b/graph/path/a_star.go
@@ -47,7 +47,7 @@ func AStar(s, t graph.Node, g traverse.Graph, h Heuristic) (path Shortest, expan
 	path = newShortestFrom(s, []graph.Node{s, t})
 	tid := t.ID()
 
-	visited := make(set.Int64s)
+	visited := make(set.Ints[int64])
 	open := &aStarQueue{indexOf: make(map[int64]int)}
 	heap.Push(open, aStarNode{node: s, gscore: 0, fscore: h(s, t)})
 
diff --git a/graph/set/uid/uid.go b/graph/set/uid/uid.go
index ce14c765..75074425 100644
--- a/graph/set/uid/uid.go
+++ b/graph/set/uid/uid.go
@@ -17,12 +17,12 @@ const Max = math.MaxInt64
 // Set implements available ID storage.
 type Set struct {
 	maxID      int64
-	used, free set.Int64s
+	used, free set.Ints[int64]
 }
 
 // NewSet returns a new Set.
 func NewSet() *Set {
-	return &Set{maxID: -1, used: make(set.Int64s), free: make(set.Int64s)}
+	return &Set{maxID: -1, used: make(set.Ints[int64]), free: make(set.Ints[int64])}
 }
 
 // NewID returns a new unique ID. The ID returned is not considered used
diff --git a/graph/topo/johnson_cycles.go b/graph/topo/johnson_cycles.go
index 6c90f60a..3433a63e 100644
--- a/graph/topo/johnson_cycles.go
+++ b/graph/topo/johnson_cycles.go
@@ -17,8 +17,8 @@ import (
 // Comments in the johnson methods are kept in sync with the comments
 // and labels from the paper.
 type johnson struct {
-	adjacent johnsonGraph // SCC adjacency list.
-	b        []set.Ints   // Johnson's "B-list".
+	adjacent johnsonGraph    // SCC adjacency list.
+	b        []set.Ints[int] // Johnson's "B-list".
 	blocked  []bool
 	s        int
 
@@ -32,7 +32,7 @@ func DirectedCyclesIn(g graph.Directed) [][]graph.Node {
 	jg := johnsonGraphFrom(g)
 	j := johnson{
 		adjacent: jg,
-		b:        make([]set.Ints, len(jg.orig)),
+		b:        make([]set.Ints[int], len(jg.orig)),
 		blocked:  make([]bool, len(jg.orig)),
 	}
 
@@ -57,7 +57,7 @@ func DirectedCyclesIn(g graph.Directed) [][]graph.Node {
 			}
 			if len(j.adjacent.succ[v.ID()]) > 0 {
 				j.blocked[i] = false
-				j.b[i] = make(set.Ints)
+				j.b[i] = make(set.Ints[int])
 			}
 		}
 		//L3:
@@ -125,8 +125,8 @@ type johnsonGraph struct {
 	orig  []graph.Node
 	index map[int64]int
 
-	nodes set.Int64s
-	succ  map[int64]set.Int64s
+	nodes set.Ints[int64]
+	succ  map[int64]set.Ints[int64]
 }
 
 // johnsonGraphFrom returns a deep copy of the graph g.
@@ -137,8 +137,8 @@ func johnsonGraphFrom(g graph.Directed) johnsonGraph {
 		orig:  nodes,
 		index: make(map[int64]int, len(nodes)),
 
-		nodes: make(set.Int64s, len(nodes)),
-		succ:  make(map[int64]set.Int64s),
+		nodes: make(set.Ints[int64], len(nodes)),
+		succ:  make(map[int64]set.Ints[int64]),
 	}
 	for i, u := range nodes {
 		uid := u.ID()
@@ -147,7 +147,7 @@ func johnsonGraphFrom(g graph.Directed) johnsonGraph {
 		for to.Next() {
 			v := to.Node()
 			if c.succ[uid] == nil {
-				c.succ[uid] = make(set.Int64s)
+				c.succ[uid] = make(set.Ints[int64])
 				c.nodes.Add(uid)
 			}
 			c.nodes.Add(v.ID())
@@ -207,8 +207,8 @@ func (g johnsonGraph) sccSubGraph(sccs [][]graph.Node, min int) johnsonGraph {
 	sub := johnsonGraph{
 		orig:  g.orig,
 		index: g.index,
-		nodes: make(set.Int64s),
-		succ:  make(map[int64]set.Int64s),
+		nodes: make(set.Ints[int64]),
+		succ:  make(map[int64]set.Ints[int64]),
 	}
 
 	var n int
@@ -221,7 +221,7 @@ func (g johnsonGraph) sccSubGraph(sccs [][]graph.Node, min int) johnsonGraph {
 			for _, v := range scc {
 				if _, ok := g.succ[u.ID()][v.ID()]; ok {
 					if sub.succ[u.ID()] == nil {
-						sub.succ[u.ID()] = make(set.Int64s)
+						sub.succ[u.ID()] = make(set.Ints[int64])
 						sub.nodes.Add(u.ID())
 					}
 					sub.nodes.Add(v.ID())
diff --git a/graph/topo/paton_cycles.go b/graph/topo/paton_cycles.go
index 525f2983..2e1ce4cb 100644
--- a/graph/topo/paton_cycles.go
+++ b/graph/topo/paton_cycles.go
@@ -17,7 +17,7 @@ func UndirectedCyclesIn(g graph.Undirected) [][]graph.Node {
 	// https://doi.org/10.1145/363219.363232
 
 	var cycles [][]graph.Node
-	done := make(set.Int64s)
+	done := make(set.Ints[int64])
 	var tree linear.NodeStack
 	nodes := g.Nodes()
 	for nodes.Next() {
@@ -30,7 +30,7 @@ func UndirectedCyclesIn(g graph.Undirected) [][]graph.Node {
 
 		tree = tree[:0]
 		tree.Push(n)
-		from := sets{id: set.Int64s{}}
+		from := sets{id: set.Ints[int64]{}}
 		to := map[int64]graph.Node{id: n}
 
 		for tree.Len() != 0 {
@@ -68,12 +68,12 @@ func UndirectedCyclesIn(g graph.Undirected) [][]graph.Node {
 	return cycles
 }
 
-type sets map[int64]set.Int64s
+type sets map[int64]set.Ints[int64]
 
 func (s sets) add(uid, vid int64) {
 	e, ok := s[vid]
 	if !ok {
-		e = make(set.Int64s)
+		e = make(set.Ints[int64])
 		s[vid] = e
 	}
 	e.Add(uid)
diff --git a/graph/topo/tarjan.go b/graph/topo/tarjan.go
index 325e9524..2007d004 100644
--- a/graph/topo/tarjan.go
+++ b/graph/topo/tarjan.go
@@ -115,7 +115,7 @@ func tarjanSCCstabilized(g graph.Directed, order func([]graph.Node)) [][]graph.N
 
 		indexTable: make(map[int64]int, len(nodes)),
 		lowLink:    make(map[int64]int, len(nodes)),
-		onStack:    make(set.Int64s),
+		onStack:    make(set.Ints[int64]),
 	}
 	for _, v := range nodes {
 		if t.indexTable[v.ID()] == 0 {
@@ -135,7 +135,7 @@ type tarjan struct {
 	index      int
 	indexTable map[int64]int
 	lowLink    map[int64]int
-	onStack    set.Int64s
+	onStack    set.Ints[int64]
 
 	stack []graph.Node
 
diff --git a/graph/traverse/traverse.go b/graph/traverse/traverse.go
index 2a4efb66..bc4f9596 100644
--- a/graph/traverse/traverse.go
+++ b/graph/traverse/traverse.go
@@ -39,7 +39,7 @@ type BreadthFirst struct {
 	Traverse func(graph.Edge) bool
 
 	queue   linear.NodeQueue
-	visited set.Int64s
+	visited set.Ints[int64]
 }
 
 // Walk performs a breadth-first traversal of the graph g starting from the given node,
@@ -49,7 +49,7 @@ type BreadthFirst struct {
 // non-nil, it is called with each node the first time it is visited.
 func (b *BreadthFirst) Walk(g Graph, from graph.Node, until func(n graph.Node, d int) bool) graph.Node {
 	if b.visited == nil {
-		b.visited = make(set.Int64s)
+		b.visited = make(set.Ints[int64])
 	}
 	b.queue.Enqueue(from)
 	if b.Visit != nil && !b.visited.Has(from.ID()) {
@@ -147,7 +147,7 @@ type DepthFirst struct {
 	Traverse func(graph.Edge) bool
 
 	stack   linear.NodeStack
-	visited set.Int64s
+	visited set.Ints[int64]
 }
 
 // Walk performs a depth-first traversal of the graph g starting from the given node,
@@ -157,7 +157,7 @@ type DepthFirst struct {
 // is called with each node the first time it is visited.
 func (d *DepthFirst) Walk(g Graph, from graph.Node, until func(graph.Node) bool) graph.Node {
 	if d.visited == nil {
-		d.visited = make(set.Int64s)
+		d.visited = make(set.Ints[int64])
 	}
 	d.stack.Push(from)
 	for d.stack.Len() != 0 {


Test patch:
diff --git a/graph/coloring/coloring_test.go b/graph/coloring/coloring_test.go
index 7af504f3..81d07b5c 100644
--- a/graph/coloring/coloring_test.go
+++ b/graph/coloring/coloring_test.go
@@ -29,11 +29,11 @@ var coloringTests = []struct {
 
 	partial map[int64]int
 
-	dsatur      set.Ints
-	randomized  set.Ints
-	rlf         set.Ints
-	sanSegundo  set.Ints
-	welshPowell set.Ints
+	dsatur      set.Ints[int]
+	randomized  set.Ints[int]
+	rlf         set.Ints[int]
+	sanSegundo  set.Ints[int]
+	welshPowell set.Ints[int]
 }{
 	{
 		name:   "empty",
@@ -411,8 +411,8 @@ var coloringTests = []struct {
 	},
 }
 
-func setOf(vals ...int) set.Ints {
-	s := make(set.Ints)
+func setOf(vals ...int) set.Ints[int] {
+	s := make(set.Ints[int])
 	for _, v := range vals {
 		s.Add(v)
 	}
@@ -767,6 +767,16 @@ func BenchmarkColoring(b *testing.B) {
 					}
 				})
 			}
+			b.Run("Randomized", func(b *testing.B) {
+				rnd := rand.NewSource(1)
+				b.ResetTimer()
+				for i := 0; i < b.N; i++ {
+					_, _, err := Randomized(bench.g, nil, rnd)
+					if err != nil {
+						b.Fatalf("coloring failed: %v", err)
+					}
+				}
+			})
 			b.Run("RecursiveLargestFirst", func(b *testing.B) {
 				for i := 0; i < b.N; i++ {
 					RecursiveLargestFirst(bench.g)
diff --git a/graph/community/louvain_directed_multiplex_test.go b/graph/community/louvain_directed_multiplex_test.go
index 03791ccd..bbbd433c 100644
--- a/graph/community/louvain_directed_multiplex_test.go
+++ b/graph/community/louvain_directed_multiplex_test.go
@@ -5,6 +5,7 @@
 package community
 
 import (
+	"fmt"
 	"math"
 	"reflect"
 	"sort"
@@ -722,3 +723,30 @@ func directedMultiplexFrom(raw []layer) (DirectedLayers, []float64, error) {
 	}
 	return g, weights, nil
 }
+
+func BenchmarkNewDirectedLayers(b *testing.B) {
+	for _, graphSize := range []int{1e0, 1e1, 1e3, 1e5} {
+		for _, numGraphs := range []int{1e0, 1e1} {
+			b.Run(
+				fmt.Sprintf("graphSize=%d,numGraphs=%d", graphSize, numGraphs),
+				func(b *testing.B) {
+					g := simple.NewDirectedGraph()
+					for i := 0; i < graphSize; i++ {
+						g.AddNode(g.NewNode())
+					}
+					gs := make([]graph.Directed, numGraphs)
+					for i := 0; i < numGraphs; i++ {
+						gs[i] = g
+					}
+
+					b.ResetTimer()
+					for i := 0; i < b.N; i++ {
+						_, err := NewDirectedLayers(gs...)
+						if err != nil {
+							b.Fatalf("NewDirectedLayers failed: %v", err)
+						}
+					}
+				})
+		}
+	}
+}
diff --git a/graph/community/louvain_undirected_multiplex_test.go b/graph/community/louvain_undirected_multiplex_test.go
index a76a87a5..286cc993 100644
--- a/graph/community/louvain_undirected_multiplex_test.go
+++ b/graph/community/louvain_undirected_multiplex_test.go
@@ -5,6 +5,7 @@
 package community
 
 import (
+	"fmt"
 	"math"
 	"reflect"
 	"sort"
@@ -691,3 +692,30 @@ func undirectedMultiplexFrom(raw []layer) (UndirectedLayers, []float64, error) {
 	}
 	return g, weights, nil
 }
+
+func BenchmarkNewUndirectedLayers(b *testing.B) {
+	for _, graphSize := range []int{1e0, 1e1, 1e3, 1e5} {
+		for _, numGraphs := range []int{1e0, 1e1} {
+			b.Run(
+				fmt.Sprintf("graphSize=%d,numGraphs=%d", graphSize, numGraphs),
+				func(b *testing.B) {
+					g := simple.NewUndirectedGraph()
+					for i := 0; i < graphSize; i++ {
+						g.AddNode(g.NewNode())
+					}
+					gs := make([]graph.Undirected, numGraphs)
+					for i := 0; i < numGraphs; i++ {
+						gs[i] = g
+					}
+
+					b.ResetTimer()
+					for i := 0; i < b.N; i++ {
+						_, err := NewUndirectedLayers(gs...)
+						if err != nil {
+							b.Fatalf("NewUndirectedLayers failed: %v", err)
+						}
+					}
+				})
+		}
+	}
+}
diff --git a/graph/encoding/dot/bench_test.go b/graph/encoding/dot/bench_test.go
new file mode 100644
index 00000000..1ac21a32
--- /dev/null
+++ b/graph/encoding/dot/bench_test.go
@@ -0,0 +1,117 @@
+// Copyright ©2024 The Gonum Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package dot
+
+import (
+	"fmt"
+	"testing"
+
+	"golang.org/x/exp/rand"
+
+	"gonum.org/v1/gonum/graph"
+	"gonum.org/v1/gonum/graph/graphs/gen"
+	"gonum.org/v1/gonum/graph/multi"
+	"gonum.org/v1/gonum/graph/simple"
+)
+
+var (
+	gnpDirected_10_tenth   = gnpDirected(10, 0.1)
+	gnpDirected_100_tenth  = gnpDirected(100, 0.1)
+	gnpDirected_1000_tenth = gnpDirected(1000, 0.1)
+	gnpDirected_10_half    = gnpDirected(10, 0.5)
+	gnpDirected_100_half   = gnpDirected(100, 0.5)
+	gnpDirected_1000_half  = gnpDirected(1000, 0.5)
+
+	powerLawMultiDirected_10_tenth   = powerLawMultiDirected(10, 1)
+	powerLawMultiDirected_100_tenth  = powerLawMultiDirected(100, 10)
+	powerLawMultiDirected_1000_tenth = powerLawMultiDirected(1000, 100)
+	powerLawMultiDirected_10_half    = powerLawMultiDirected(10, 5)
+	powerLawMultiDirected_100_half   = powerLawMultiDirected(100, 50)
+	powerLawMultiDirected_1000_half  = powerLawMultiDirected(1000, 500)
+)
+
+func gnpDirected(n int, p float64) graph.Directed {
+	g := simple.NewDirectedGraph()
+	err := gen.Gnp(g, n, p, rand.NewSource(1))
+	if err != nil {
+		panic(fmt.Sprintf("dot: bad test: %v", err))
+	}
+	return g
+}
+
+func powerLawMultiDirected(n, d int) graph.DirectedMultigraph {
+	g := multi.NewDirectedGraph()
+	err := gen.PowerLaw(g, n, d, rand.NewSource(1))
+	if err != nil {
+		panic(fmt.Sprintf("dot: bad test: %v", err))
+	}
+	return g
+}
+
+func benchmarkUnmarshal(b *testing.B, g graph.Directed) {
+	marshalled, err := Marshal(g, "g", "", "")
+	if err != nil {
+		b.Fatalf("dot: bad Marshal input: %v", err)
+	}
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		if err := Unmarshal(marshalled, simple.NewDirectedGraph()); err != nil {
+			b.Fatalf("dot: bad Unmarshal input: %v", err)
+		}
+	}
+}
+
+func BenchmarkUnmarshalGnp_10_tenth(b *testing.B) {
+	benchmarkUnmarshal(b, gnpDirected_10_tenth)
+}
+func BenchmarkUnmarshalGnp_100_tenth(b *testing.B) {
+	benchmarkUnmarshal(b, gnpDirected_100_tenth)
+}
+func BenchmarkUnmarshalGnp_1000_tenth(b *testing.B) {
+	benchmarkUnmarshal(b, gnpDirected_1000_tenth)
+}
+func BenchmarkUnmarshalGnp_10_half(b *testing.B) {
+	benchmarkUnmarshal(b, gnpDirected_10_half)
+}
+func BenchmarkUnmarshalGnp_100_half(b *testing.B) {
+	benchmarkUnmarshal(b, gnpDirected_100_half)
+}
+func BenchmarkUnmarshalGnp_1000_half(b *testing.B) {
+	benchmarkUnmarshal(b, gnpDirected_1000_half)
+}
+
+func benchmarkUnmarshalMulti(b *testing.B, g graph.DirectedMultigraph) {
+	marshalled, err := MarshalMulti(g, "g", "", "")
+	if err != nil {
+		b.Fatalf("dot: bad Marshal input: %v", err)
+	}
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		if err := UnmarshalMulti(marshalled, multi.NewDirectedGraph()); err != nil {
+			b.Fatalf("dot: bad Unmarshal input: %v", err)
+		}
+	}
+}
+
+func BenchmarkUnmarshalMultiPowerLaw_10_tenth(b *testing.B) {
+	benchmarkUnmarshalMulti(b, powerLawMultiDirected_10_tenth)
+}
+func BenchmarkUnmarshalMultiPowerLaw_100_tenth(b *testing.B) {
+	benchmarkUnmarshalMulti(b, powerLawMultiDirected_100_tenth)
+}
+func BenchmarkUnmarshalMultiPowerLaw_1000_tenth(b *testing.B) {
+	benchmarkUnmarshalMulti(b, powerLawMultiDirected_1000_tenth)
+}
+func BenchmarkUnmarshalMultiPowerLaw_10_half(b *testing.B) {
+	benchmarkUnmarshalMulti(b, powerLawMultiDirected_10_half)
+}
+func BenchmarkUnmarshalMultiPowerLaw_100_half(b *testing.B) {
+	benchmarkUnmarshalMulti(b, powerLawMultiDirected_100_half)
+}
+func BenchmarkUnmarshalMultiPowerLaw_1000_half(b *testing.B) {
+	benchmarkUnmarshalMulti(b, powerLawMultiDirected_1000_half)
+}
diff --git a/graph/internal/set/set_test.go b/graph/internal/set/set_test.go
index 465d0b2e..e8a68d13 100644
--- a/graph/internal/set/set_test.go
+++ b/graph/internal/set/set_test.go
@@ -13,149 +13,16 @@ type node int64
 
 func (n node) ID() int64 { return int64(n) }
 
-// TestSame tests the assumption that pointer equality via unsafe conversion
+// TestSameInts tests the assumption that pointer equality via unsafe conversion
 // of a map[int]struct{} to uintptr is a valid test for perfect identity between
 // set values. If any of the tests in TestSame fail, the package is broken and same
 // must be reimplemented to conform to the runtime map implementation. The relevant
 // code to look at (at least for gc) is the hmap type in runtime/map.go.
 
-func TestSameInt64s(t *testing.T) {
-	var (
-		a = make(Int64s)
-		b = make(Int64s)
-		c = a
-	)
-
-	if int64sSame(a, b) {
-		t.Error("Independently created sets test as same")
-	}
-	if !int64sSame(a, c) {
-		t.Error("Set copy and original test as not same.")
-	}
-	a.Add(1)
-	if !int64sSame(a, c) {
-		t.Error("Set copy and original test as not same after addition.")
-	}
-	if !int64sSame(nil, nil) {
-		t.Error("nil sets test as not same.")
-	}
-	if int64sSame(b, nil) {
-		t.Error("nil and empty sets test as same.")
-	}
-}
-
-func TestAddInt64s(t *testing.T) {
-	s := make(Int64s)
-	if s.Count() != 0 {
-		t.Error("Set somehow contains new elements upon creation")
-	}
-
-	s.Add(1)
-	s.Add(3)
-	s.Add(5)
-
-	if s.Count() != 3 {
-		t.Error("Incorrect number of set elements after adding")
-	}
-
-	if !s.Has(1) || !s.Has(3) || !s.Has(5) {
-		t.Error("Set doesn't contain element that was added")
-	}
-
-	s.Add(1)
-
-	if s.Count() > 3 {
-		t.Error("Set double-adds element (element not unique)")
-	} else if s.Count() < 3 {
-		t.Error("Set double-add lowered len")
-	}
-
-	if !s.Has(1) {
-		t.Error("Set doesn't contain double-added element")
-	}
-
-	if !s.Has(3) || !s.Has(5) {
-		t.Error("Set removes element on double-add")
-	}
-}
-
-func TestRemoveInt64s(t *testing.T) {
-	s := make(Int64s)
-
-	s.Add(1)
-	s.Add(3)
-	s.Add(5)
-
-	s.Remove(1)
-
-	if s.Count() != 2 {
-		t.Error("Incorrect number of set elements after removing an element")
-	}
-
-	if s.Has(1) {
-		t.Error("Element present after removal")
-	}
-
-	if !s.Has(3) || !s.Has(5) {
-		t.Error("Set remove removed wrong element")
-	}
-
-	s.Remove(1)
-
-	if s.Count() != 2 || s.Has(1) {
-		t.Error("Double set remove does something strange")
-	}
-
-	s.Add(1)
-
-	if s.Count() != 3 || !s.Has(1) {
-		t.Error("Cannot add element after removal")
-	}
-}
-
-func TestSelfEqualInt64s(t *testing.T) {
-	s := make(Int64s)
-
-	if !Int64sEqual(s, s) {
-		t.Error("Set is not equal to itself")
-	}
-
-	s.Add(1)
-
-	if !Int64sEqual(s, s) {
-		t.Error("Set ceases self equality after adding element")
-	}
-}
-
-func TestEqualInt64s(t *testing.T) {
-	a := make(Int64s)
-	b := make(Int64s)
-
-	if !Int64sEqual(a, b) {
-		t.Error("Two different empty sets not equal")
-	}
-
-	a.Add(1)
-	if Int64sEqual(a, b) {
-		t.Error("Two different sets with different sizes equal")
-	}
-
-	b.Add(1)
-	if !Int64sEqual(a, b) {
-		t.Error("Two sets with same element not equal")
-	}
-
-	b.Remove(1)
-	b.Add(2)
-	if Int64sEqual(a, b) {
-		t.Error("Two different sets with different elements equal")
-	}
-}
-
 func TestSameInts(t *testing.T) {
 	var (
-		a = make(Ints)
-		b = make(Ints)
+		a = make(Ints[int64])
+		b = make(Ints[int64])
 		c = a
 	)
 
@@ -163,13 +30,13 @@ func TestSameInts(t *testing.T) {
 		t.Error("Independently created sets test as same")
 	}
 	if !intsSame(a, c) {
-		t.Error("Set copy and original test as not same.")
+		t.Error("Ints copy and original test as not same.")
 	}
 	a.Add(1)
 	if !intsSame(a, c) {
-		t.Error("Set copy and original test as not same after addition.")
+		t.Error("Ints copy and original test as not same after addition.")
 	}
-	if !intsSame(nil, nil) {
+	if !intsSame[int64](nil, nil) {
 		t.Error("nil sets test as not same.")
 	}
 	if intsSame(b, nil) {
@@ -178,9 +45,9 @@ func TestSameInts(t *testing.T) {
 }
 
 func TestAddInts(t *testing.T) {
-	s := make(Ints)
+	s := make(Ints[int64])
 	if s.Count() != 0 {
-		t.Error("Set somehow contains new elements upon creation")
+		t.Error("Ints somehow contains new elements upon creation")
 	}
 
 	s.Add(1)
@@ -192,28 +59,28 @@ func TestAddInts(t *testing.T) {
 	}
 
 	if !s.Has(1) || !s.Has(3) || !s.Has(5) {
-		t.Error("Set doesn't contain element that was added")
+		t.Error("Ints doesn't contain element that was added")
 	}
 
 	s.Add(1)
 
 	if s.Count() > 3 {
-		t.Error("Set double-adds element (element not unique)")
+		t.Error("Ints double-adds element (element not unique)")
 	} else if s.Count() < 3 {
-		t.Error("Set double-add lowered len")
+		t.Error("Ints double-add lowered len")
 	}
 
 	if !s.Has(1) {
-		t.Error("Set doesn't contain double-added element")
+		t.Error("Ints doesn't contain double-added element")
 	}
 
 	if !s.Has(3) || !s.Has(5) {
-		t.Error("Set removes element on double-add")
+		t.Error("Ints removes element on double-add")
 	}
 }
 
 func TestRemoveInts(t *testing.T) {
-	s := make(Ints)
+	s := make(Ints[int64])
 
 	s.Add(1)
 	s.Add(3)
@@ -230,7 +97,7 @@ func TestRemoveInts(t *testing.T) {
 	}
 
 	if !s.Has(3) || !s.Has(5) {
-		t.Error("Set remove removed wrong element")
+		t.Error("Ints remove removed wrong element")
 	}
 
 	s.Remove(1)
@@ -247,22 +114,22 @@ func TestRemoveInts(t *testing.T) {
 }
 
 func TestSelfEqualInts(t *testing.T) {
-	s := make(Ints)
+	s := make(Ints[int64])
 
 	if !IntsEqual(s, s) {
-		t.Error("Set is not equal to itself")
+		t.Error("Ints is not equal to itself")
 	}
 
 	s.Add(1)
 
 	if !IntsEqual(s, s) {
-		t.Error("Set ceases self equality after adding element")
+		t.Error("Ints ceases self equality after adding element")
 	}
 }
 
 func TestEqualInts(t *testing.T) {
-	a := make(Ints)
-	b := make(Ints)
+	a := make(Ints[int64])
+	b := make(Ints[int64])
 
 	if !IntsEqual(a, b) {
 		t.Error("Two different empty sets not equal")
@@ -296,11 +163,11 @@ func TestSameNodes(t *testing.T) {
 		t.Error("Independently created sets test as same")
 	}
 	if !same(a, c) {
-		t.Error("Set copy and original test as not same.")
+		t.Error("Ints copy and original test as not same.")
 	}
 	a.Add(node(1))
 	if !same(a, c) {
-		t.Error("Set copy and original test as not same after addition.")
+		t.Error("Ints copy and original test as not same after addition.")
 	}
 	if !same(nil, nil) {
 		t.Error("nil sets test as not same.")
@@ -313,11 +180,11 @@ func TestSameNodes(t *testing.T) {
 func TestAddNodes(t *testing.T) {
 	s := NewNodes()
 	if s == nil {
-		t.Fatal("Set cannot be created successfully")
+		t.Fatal("Ints cannot be created successfully")
 	}
 
 	if s.Count() != 0 {
-		t.Error("Set somehow contains new elements upon creation")
+		t.Error("Ints somehow contains new elements upon creation")
 	}
 
 	s.Add(node(1))
@@ -329,23 +196,23 @@ func TestAddNodes(t *testing.T) {
 	}
 
 	if !s.Has(node(1)) || !s.Has(node(3)) || !s.Has(node(5)) {
-		t.Error("Set doesn't contain element that was added")
+		t.Error("Ints doesn't contain element that was added")
 	}
 
 	s.Add(node(1))
 
 	if s.Count() > 3 {
-		t.Error("Set double-adds element (element not unique)")
+		t.Error("Ints double-adds element (element not unique)")
 	} else if s.Count() < 3 {
-		t.Error("Set double-add lowered len")
+		t.Error("Ints double-add lowered len")
 	}
 
 	if !s.Has(node(1)) {
-		t.Error("Set doesn't contain double-added element")
+		t.Error("Ints doesn't contain double-added element")
 	}
 
 	if !s.Has(node(3)) || !s.Has(node(5)) {
-		t.Error("Set removes element on double-add")
+		t.Error("Ints removes element on double-add")
 	}
 
 	for e, n := range s {
@@ -373,7 +240,7 @@ func TestRemoveNodes(t *testing.T) {
 	}
 
 	if !s.Has(node(3)) || !s.Has(node(5)) {
-		t.Error("Set remove removed wrong element")
+		t.Error("Ints remove removed wrong element")
 	}
 
 	s.Remove(node(1))
@@ -393,13 +260,13 @@ func TestSelfEqualNodes(t *testing.T) {
 	s := NewNodes()
 
 	if !Equal(s, s) {
-		t.Error("Set is not equal to itself")
+		t.Error("Ints is not equal to itself")
 	}
 
 	s.Add(node(1))
 
 	if !Equal(s, s) {
-		t.Error("Set ceases self equality after adding element")
+		t.Error("Ints ceases self equality after adding element")
 	}
 }
 
diff --git a/graph/path/shortest.go b/graph/path/shortest.go
index 4fcd2397..43299193 100644
--- a/graph/path/shortest.go
+++ b/graph/path/shortest.go
@@ -159,7 +159,7 @@ func (p Shortest) To(vid int64) (path []graph.Node, weight float64) {
 	path = []graph.Node{p.nodes[to]}
 	weight = math.Inf(1)
 	if p.hasNegativeCycle {
-		seen := make(set.Ints)
+		seen := make(set.Ints[int])
 		seen.Add(from)
 		for to != from {
 			next := p.next[to]
@@ -348,7 +348,7 @@ func (p ShortestAlts) To(vid int64) (path []graph.Node, weight float64, unique b
 	path = []graph.Node{p.nodes[to]}
 	if p.hasNegativeCycle {
 		weight = math.Inf(1)
-		seen := make(set.Ints)
+		seen := make(set.Ints[int])
 		seen.Add(from)
 		for to != from {
 			c := p.next[to]
diff --git a/graph/testgraph/testgraph.go b/graph/testgraph/testgraph.go
index 89b080f4..13e99cd0 100644
--- a/graph/testgraph/testgraph.go
+++ b/graph/testgraph/testgraph.go
@@ -2102,7 +2102,7 @@ type RandomNodes struct {
 	curr int64
 
 	state *rand.Rand
-	seen  set.Int64s
+	seen  set.Ints[int64]
 	count int
 }
 
@@ -2118,7 +2118,7 @@ func NewRandomNodes(n int, seed uint64, new func(id int64) graph.Node) *RandomNo
 		newNode: new,
 
 		state: rand.New(rand.NewSource(seed)),
-		seen:  make(set.Int64s),
+		seen:  make(set.Ints[int64]),
 		count: 0,
 	}
 }
@@ -2159,7 +2159,7 @@ func (n *RandomNodes) Node() graph.Node {
 // Reset returns the iterator to its initial state.
 func (n *RandomNodes) Reset() {
 	n.state = rand.New(rand.NewSource(n.seed))
-	n.seen = make(set.Int64s)
+	n.seen = make(set.Ints[int64])
 	n.count = 0
 }
 
diff --git a/graph/topo/bench_test.go b/graph/topo/bench_test.go
index 44ea48f3..82cdd600 100644
--- a/graph/topo/bench_test.go
+++ b/graph/topo/bench_test.go
@@ -8,6 +8,8 @@ import (
 	"fmt"
 	"testing"
 
+	"golang.org/x/exp/rand"
+
 	"gonum.org/v1/gonum/graph"
 	"gonum.org/v1/gonum/graph/graphs/gen"
 	"gonum.org/v1/gonum/graph/simple"
@@ -20,11 +22,25 @@ var (
 	gnpDirected_10_half    = gnpDirected(10, 0.5)
 	gnpDirected_100_half   = gnpDirected(100, 0.5)
 	gnpDirected_1000_half  = gnpDirected(1000, 0.5)
+
+	gnpUndirected_10_tenth  = gnpUndirected(10, 0.1)
+	gnpUndirected_100_tenth = gnpUndirected(100, 0.1)
+	gnpUndirected_10_half   = gnpUndirected(10, 0.5)
+	gnpUndirected_100_half  = gnpUndirected(100, 0.5)
 )
 
 func gnpDirected(n int, p float64) graph.Directed {
 	g := simple.NewDirectedGraph()
-	err := gen.Gnp(g, n, p, nil)
+	err := gen.Gnp(g, n, p, rand.NewSource(1))
+	if err != nil {
+		panic(fmt.Sprintf("topo: bad test: %v", err))
+	}
+	return g
+}
+
+func gnpUndirected(n int, p float64) graph.Undirected {
+	g := simple.NewUndirectedGraph()
+	err := gen.Gnp(g, n, p, rand.NewSource(1))
 	if err != nil {
 		panic(fmt.Sprintf("topo: bad test: %v", err))
 	}
@@ -59,3 +75,35 @@ func BenchmarkTarjanSCCGnp_100_half(b *testing.B) {
 func BenchmarkTarjanSCCGnp_1000_half(b *testing.B) {
 	benchmarkTarjanSCC(b, gnpDirected_1000_half)
 }
+
+func benchmarkDirectedCyclesIn(b *testing.B, g graph.Directed) {
+	for i := 0; i < b.N; i++ {
+		DirectedCyclesIn(g)
+	}
+}
+
+func BenchmarkDirectedCyclesInGnp_10_tenth(b *testing.B) {
+	benchmarkDirectedCyclesIn(b, gnpDirected_10_tenth)
+}
+func BenchmarkDirectedCyclesInGnp_10_half(b *testing.B) {
+	benchmarkDirectedCyclesIn(b, gnpDirected_10_half)
+}
+
+func benchmarkUndirectedCyclesIn(b *testing.B, g graph.Undirected) {
+	for i := 0; i < b.N; i++ {
+		UndirectedCyclesIn(g)
+	}
+}
+
+func BenchmarkUndirectedCyclesInGnp_10_tenth(b *testing.B) {
+	benchmarkUndirectedCyclesIn(b, gnpUndirected_10_tenth)
+}
+func BenchmarkUndirectedCyclesInGnp_100_tenth(b *testing.B) {
+	benchmarkUndirectedCyclesIn(b, gnpUndirected_100_tenth)
+}
+func BenchmarkUndirectedCyclesInGnp_10_half(b *testing.B) {
+	benchmarkUndirectedCyclesIn(b, gnpUndirected_10_half)
+}
+func BenchmarkUndirectedCyclesInGnp_100_half(b *testing.B) {
+	benchmarkUndirectedCyclesIn(b, gnpUndirected_100_half)
+}