diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..d60f0707f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" # Location of package manifests + schedule: + interval: "monthly" diff --git a/.github/workflows/TagBot.yml b/.github/workflows/TagBot.yml index f49313b66..90dc1009d 100644 --- a/.github/workflows/TagBot.yml +++ b/.github/workflows/TagBot.yml @@ -4,6 +4,22 @@ on: types: - created workflow_dispatch: + inputs: + lookback: + default: 3 +permissions: + actions: read + checks: read + contents: write + deployments: read + issues: read + discussions: read + packages: read + pages: read + pull-requests: read + repository-projects: read + security-events: read + statuses: read jobs: TagBot: if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot' @@ -12,4 +28,6 @@ jobs: - uses: JuliaRegistries/TagBot@v1 with: token: ${{ secrets.GITHUB_TOKEN }} + # Edit the following line to reflect the actual name of the GitHub Secret containing your private key ssh: ${{ secrets.DOCUMENTER_KEY }} + # ssh: ${{ secrets.NAME_OF_MY_SSH_PRIVATE_KEY_SECRET }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dc264a3ef..b03ecdca5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,12 +35,12 @@ jobs: - version: '1.6' allow_failure: false steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: julia-actions/setup-julia@v1 with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} - - uses: actions/cache@v1 + - uses: actions/cache@v4 env: cache-name: cache-artifacts with: @@ -53,14 +53,16 @@ jobs: - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 - uses: julia-actions/julia-processcoverage@v1 - - uses: codecov/codecov-action@v1 + - uses: codecov/codecov-action@v4 with: file: lcov.info + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: false docs: name: Documentation runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: julia-actions/setup-julia@v1 with: version: '1' diff --git a/.gitignore b/.gitignore index c5724c2b6..e62f96992 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,7 @@ benchmark/Manifest.toml *.cov /Manifest.toml notes +/docs/Manifest.toml +/docs/src/index.md +/docs/src/contributing.md +/docs/src/license.md diff --git a/Project.toml b/Project.toml index 454327fef..a9fd907c9 100644 --- a/Project.toml +++ b/Project.toml @@ -17,7 +17,7 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" [compat] Aqua = "0.6" -ArnoldiMethod = "0.1, 0.2" +ArnoldiMethod = "0.3" Compat = "3.40, 4" DataStructures = "0.17, 0.18" Documenter = "0.27" diff --git a/benchmark/benchmarks.jl b/benchmark/benchmarks.jl index ecec72cc5..e9c220a24 100644 --- a/benchmark/benchmarks.jl +++ b/benchmark/benchmarks.jl @@ -1,7 +1,7 @@ using BenchmarkTools using Graphs -const benchdir = dirname(@__FILE__) +const BENCHDIR = dirname(@__FILE__) const DIGRAPHS = Dict{String,DiGraph}( "complete100" => complete_digraph(100), "path500" => path_digraph(500) @@ -33,7 +33,7 @@ parallelbenchmarks = [ ] foreach(parallelbenchmarks) do bm - include(joinpath(benchdir, bm)) + include(joinpath(BENCHDIR, bm)) end nothing diff --git a/benchmark/tune.json b/benchmark/tune.json index 14c07c593..ed04988e2 100644 --- a/benchmark/tune.json +++ b/benchmark/tune.json @@ -1,558 +1,588 @@ [ - { - "Julia": "1.9.4", - "BenchmarkTools": "1.0.0" - }, + { + "Julia": "1.10.1", + "BenchmarkTools": "1.0.0" + }, + [ [ - [ + "BenchmarkGroup", + { + "data": { + "centrality": [ "BenchmarkGroup", { - "data": { - "centrality": [ - "BenchmarkGroup", + "data": { + "graphs": [ + "BenchmarkGroup", + { + "data": { + "closeness_centrality": [ + "Parameters", { - "data": { - "graphs": [ - "BenchmarkGroup", - { - "data": { - "closeness_centrality": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ], - "betweenness_centrality": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ], - "katz_centrality": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ], - "degree_centrality": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 15, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ] - }, - "tags": [] - } - ], - "digraphs": [ - "BenchmarkGroup", - { - "data": { - "closeness_centrality": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ], - "betweenness_centrality": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ], - "katz_centrality": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ], - "degree_centrality": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 10, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ], - "pagerank": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ] - }, - "tags": [] - } - ] - }, - "tags": [] + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 } - ], - "parallel": [ - "BenchmarkGroup", + ], + "betweenness_centrality": [ + "Parameters", { - "data": { - "egonet": [ - "BenchmarkGroup", - { - "data": { - "vertexfunction": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ], - "twohop": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ] - }, - "tags": [] - } - ] - }, - "tags": [] + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 } - ], - "core": [ - "BenchmarkGroup", + ], + "katz_centrality": [ + "Parameters", { - "data": { - "nv": [ - "BenchmarkGroup", - { - "data": { - "graphs": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 723, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ], - "digraphs": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 784, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ] - }, - "tags": [] - } - ], - "edges": [ - "BenchmarkGroup", - { - "data": { - "graphs": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 7, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ], - "digraphs": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 8, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ] - }, - "tags": [] - } - ], - "has_edge": [ - "BenchmarkGroup", - { - "data": { - "graphs": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 7, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ], - "digraphs": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 8, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ] - }, - "tags": [] - } - ] - }, - "tags": [] + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 } - ], - "connectivity": [ - "BenchmarkGroup", + ], + "degree_centrality": [ + "Parameters", { - "data": { - "graphs": [ - "BenchmarkGroup", - { - "data": { - "connected_components": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ] - }, - "tags": [] - } - ], - "digraphs": [ - "BenchmarkGroup", - { - "data": { - "strongly_connected_components": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ] - }, - "tags": [] - } - ] - }, - "tags": [] + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 28, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 } - ], - "insertions": [ - "BenchmarkGroup", + ] + }, + "tags": [] + } + ], + "digraphs": [ + "BenchmarkGroup", + { + "data": { + "closeness_centrality": [ + "Parameters", { - "data": { - "SG(n,e) Generation": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ] - }, - "tags": [] + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 } - ], - "traversals": [ - "BenchmarkGroup", + ], + "betweenness_centrality": [ + "Parameters", { - "data": { - "graphs": [ - "BenchmarkGroup", - { - "data": { - "bfs_tree": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ], - "dfs_tree": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ] - }, - "tags": [] - } - ], - "digraphs": [ - "BenchmarkGroup", - { - "data": { - "bfs_tree": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ], - "dfs_tree": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ] - }, - "tags": [] - } - ] - }, - "tags": [] + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 } - ], - "serial": [ - "BenchmarkGroup", + ], + "katz_centrality": [ + "Parameters", { - "data": { - "egonet": [ - "BenchmarkGroup", - { - "data": { - "vertexfunction": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ], - "twohop": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ] - }, - "tags": [] - } - ] - }, - "tags": [] + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 } - ], - "edges": [ - "BenchmarkGroup", + ], + "degree_centrality": [ + "Parameters", { - "data": { - "fillp": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ], - "fille": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ], - "tsume": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ], - "tsump": [ - "Parameters", - { - "gctrial": true, - "time_tolerance": 0.05, - "samples": 10000, - "evals": 1, - "gcsample": false, - "seconds": 5.0, - "overhead": 0.0, - "memory_tolerance": 0.01 - } - ] - }, - "tags": [] + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 10, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 } - ] - }, - "tags": [] + ], + "pagerank": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ] + }, + "tags": [] + } + ] + }, + "tags": [] + } + ], + "parallel": [ + "BenchmarkGroup", + { + "data": { + "egonet": [ + "BenchmarkGroup", + { + "data": { + "vertexfunction": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ], + "twohop": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ] + }, + "tags": [] + } + ] + }, + "tags": [] + } + ], + "core": [ + "BenchmarkGroup", + { + "data": { + "nv": [ + "BenchmarkGroup", + { + "data": { + "graphs": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 807, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ], + "digraphs": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 846, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ] + }, + "tags": [] + } + ], + "edges": [ + "BenchmarkGroup", + { + "data": { + "graphs": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 7, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ], + "digraphs": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 7, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ] + }, + "tags": [] + } + ], + "has_edge": [ + "BenchmarkGroup", + { + "data": { + "graphs": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 8, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ], + "digraphs": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 8, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ] + }, + "tags": [] + } + ] + }, + "tags": [] + } + ], + "connectivity": [ + "BenchmarkGroup", + { + "data": { + "graphs": [ + "BenchmarkGroup", + { + "data": { + "connected_components": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ] + }, + "tags": [] + } + ], + "digraphs": [ + "BenchmarkGroup", + { + "data": { + "strongly_connected_components": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ] + }, + "tags": [] + } + ] + }, + "tags": [] + } + ], + "insertions": [ + "BenchmarkGroup", + { + "data": { + "SG(n,e) Generation": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ] + }, + "tags": [] + } + ], + "traversals": [ + "BenchmarkGroup", + { + "data": { + "graphs": [ + "BenchmarkGroup", + { + "data": { + "bfs_tree": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ], + "dfs_tree": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ] + }, + "tags": [] + } + ], + "digraphs": [ + "BenchmarkGroup", + { + "data": { + "bfs_tree": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ], + "dfs_tree": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ] + }, + "tags": [] + } + ] + }, + "tags": [] + } + ], + "serial": [ + "BenchmarkGroup", + { + "data": { + "egonet": [ + "BenchmarkGroup", + { + "data": { + "vertexfunction": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ], + "twohop": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ] + }, + "tags": [] + } + ] + }, + "tags": [] + } + ], + "edges": [ + "BenchmarkGroup", + { + "data": { + "fillp": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ], + "fille": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ], + "tsume": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ], + "tsump": [ + "Parameters", + { + "gctrial": true, + "time_tolerance": 0.05, + "evals_set": false, + "samples": 10000, + "evals": 1, + "gcsample": false, + "seconds": 5, + "overhead": 0, + "memory_tolerance": 0.01 + } + ] + }, + "tags": [] } - ] + ] + }, + "tags": [] + } ] + ] ] diff --git a/docs/Manifest.toml b/docs/Manifest.toml deleted file mode 100644 index 8f505d321..000000000 --- a/docs/Manifest.toml +++ /dev/null @@ -1,292 +0,0 @@ -# This file is machine-generated - editing it directly is not advised - -julia_version = "1.9.3" -manifest_format = "2.0" -project_hash = "f938aa9ae045c73618c84d5b3b75f85a7cb9262d" - -[[deps.ANSIColoredPrinters]] -git-tree-sha1 = "574baf8110975760d391c710b6341da1afa48d8c" -uuid = "a4c015fc-c6ff-483c-b24f-f7ea428134e9" -version = "0.0.1" - -[[deps.ArgTools]] -uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" -version = "1.1.1" - -[[deps.ArnoldiMethod]] -deps = ["LinearAlgebra", "Random", "StaticArrays"] -git-tree-sha1 = "62e51b39331de8911e4a7ff6f5aaf38a5f4cc0ae" -uuid = "ec485272-7323-5ecc-a04f-4719b315124d" -version = "0.2.0" - -[[deps.Artifacts]] -uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" - -[[deps.Base64]] -uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" - -[[deps.Compat]] -deps = ["UUIDs"] -git-tree-sha1 = "e460f044ca8b99be31d35fe54fc33a5c33dd8ed7" -uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "4.9.0" -weakdeps = ["Dates", "LinearAlgebra"] - - [deps.Compat.extensions] - CompatLinearAlgebraExt = "LinearAlgebra" - -[[deps.CompilerSupportLibraries_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" -version = "1.0.5+0" - -[[deps.DataStructures]] -deps = ["Compat", "InteractiveUtils", "OrderedCollections"] -git-tree-sha1 = "3dbd312d370723b6bb43ba9d02fc36abade4518d" -uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" -version = "0.18.15" - -[[deps.Dates]] -deps = ["Printf"] -uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" - -[[deps.Distributed]] -deps = ["Random", "Serialization", "Sockets"] -uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" - -[[deps.DocStringExtensions]] -deps = ["LibGit2"] -git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d" -uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" -version = "0.9.3" - -[[deps.Documenter]] -deps = ["ANSIColoredPrinters", "Base64", "Dates", "DocStringExtensions", "IOCapture", "InteractiveUtils", "JSON", "LibGit2", "Logging", "Markdown", "REPL", "Test", "Unicode"] -git-tree-sha1 = "39fd748a73dce4c05a9655475e437170d8fb1b67" -uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -version = "0.27.25" - -[[deps.Downloads]] -deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] -uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" -version = "1.6.0" - -[[deps.FileWatching]] -uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" - -[[deps.Graphs]] -deps = ["ArnoldiMethod", "Compat", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"] -path = ".." -uuid = "86223c79-3864-5bf0-83f7-82e725a168b6" -version = "1.8.0" - -[[deps.IOCapture]] -deps = ["Logging", "Random"] -git-tree-sha1 = "d75853a0bdbfb1ac815478bacd89cd27b550ace6" -uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89" -version = "0.2.3" - -[[deps.Inflate]] -git-tree-sha1 = "5cd07aab533df5170988219191dfad0519391428" -uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9" -version = "0.1.3" - -[[deps.InteractiveUtils]] -deps = ["Markdown"] -uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" - -[[deps.JSON]] -deps = ["Dates", "Mmap", "Parsers", "Unicode"] -git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a" -uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" -version = "0.21.4" - -[[deps.LibCURL]] -deps = ["LibCURL_jll", "MozillaCACerts_jll"] -uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" -version = "0.6.3" - -[[deps.LibCURL_jll]] -deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] -uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" -version = "7.84.0+0" - -[[deps.LibGit2]] -deps = ["Base64", "NetworkOptions", "Printf", "SHA"] -uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" - -[[deps.LibSSH2_jll]] -deps = ["Artifacts", "Libdl", "MbedTLS_jll"] -uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" -version = "1.10.2+0" - -[[deps.Libdl]] -uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" - -[[deps.LinearAlgebra]] -deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] -uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" - -[[deps.Logging]] -uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" - -[[deps.MacroTools]] -deps = ["Markdown", "Random"] -git-tree-sha1 = "9ee1618cbf5240e6d4e0371d6f24065083f60c48" -uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" -version = "0.5.11" - -[[deps.Markdown]] -deps = ["Base64"] -uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" - -[[deps.MbedTLS_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" -version = "2.28.2+0" - -[[deps.Mmap]] -uuid = "a63ad114-7e13-5084-954f-fe012c677804" - -[[deps.MozillaCACerts_jll]] -uuid = "14a3606d-f60d-562e-9121-12d972cd8159" -version = "2022.10.11" - -[[deps.NetworkOptions]] -uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" -version = "1.2.0" - -[[deps.OpenBLAS_jll]] -deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] -uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" -version = "0.3.21+4" - -[[deps.OrderedCollections]] -git-tree-sha1 = "2e73fe17cac3c62ad1aebe70d44c963c3cfdc3e3" -uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" -version = "1.6.2" - -[[deps.Parsers]] -deps = ["Dates", "PrecompileTools", "UUIDs"] -git-tree-sha1 = "716e24b21538abc91f6205fd1d8363f39b442851" -uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" -version = "2.7.2" - -[[deps.Pkg]] -deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] -uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" -version = "1.9.2" - -[[deps.PrecompileTools]] -deps = ["Preferences"] -git-tree-sha1 = "03b4c25b43cb84cee5c90aa9b5ea0a78fd848d2f" -uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" -version = "1.2.0" - -[[deps.Preferences]] -deps = ["TOML"] -git-tree-sha1 = "7eb1686b4f04b82f96ed7a4ea5890a4f0c7a09f1" -uuid = "21216c6a-2e73-6563-6e65-726566657250" -version = "1.4.0" - -[[deps.Printf]] -deps = ["Unicode"] -uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" - -[[deps.REPL]] -deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] -uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" - -[[deps.Random]] -deps = ["SHA", "Serialization"] -uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" - -[[deps.SHA]] -uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" -version = "0.7.0" - -[[deps.Serialization]] -uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" - -[[deps.SharedArrays]] -deps = ["Distributed", "Mmap", "Random", "Serialization"] -uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383" - -[[deps.SimpleTraits]] -deps = ["InteractiveUtils", "MacroTools"] -git-tree-sha1 = "5d7e3f4e11935503d3ecaf7186eac40602e7d231" -uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d" -version = "0.9.4" - -[[deps.Sockets]] -uuid = "6462fe0b-24de-5631-8697-dd941f90decc" - -[[deps.SparseArrays]] -deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"] -uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" - -[[deps.StaticArrays]] -deps = ["LinearAlgebra", "Random", "StaticArraysCore"] -git-tree-sha1 = "51621cca8651d9e334a659443a74ce50a3b6dfab" -uuid = "90137ffa-7385-5640-81b9-e52037218182" -version = "1.6.3" -weakdeps = ["Statistics"] - - [deps.StaticArrays.extensions] - StaticArraysStatisticsExt = "Statistics" - -[[deps.StaticArraysCore]] -git-tree-sha1 = "36b3d696ce6366023a0ea192b4cd442268995a0d" -uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" -version = "1.4.2" - -[[deps.Statistics]] -deps = ["LinearAlgebra", "SparseArrays"] -uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" -version = "1.9.0" - -[[deps.SuiteSparse_jll]] -deps = ["Artifacts", "Libdl", "Pkg", "libblastrampoline_jll"] -uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" -version = "5.10.1+6" - -[[deps.TOML]] -deps = ["Dates"] -uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" -version = "1.0.3" - -[[deps.Tar]] -deps = ["ArgTools", "SHA"] -uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" -version = "1.10.0" - -[[deps.Test]] -deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] -uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" - -[[deps.UUIDs]] -deps = ["Random", "SHA"] -uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" - -[[deps.Unicode]] -uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" - -[[deps.Zlib_jll]] -deps = ["Libdl"] -uuid = "83775a58-1f1d-513f-b197-d71354ab007a" -version = "1.2.13+0" - -[[deps.libblastrampoline_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" -version = "5.8.0+0" - -[[deps.nghttp2_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" -version = "1.48.0+0" - -[[deps.p7zip_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" -version = "17.4.0+0" diff --git a/docs/Project.toml b/docs/Project.toml index dbc6c90d0..dea978a5e 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -3,4 +3,4 @@ Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6" [compat] -Documenter = "~0.27" +Documenter = "1" diff --git a/docs/make.jl b/docs/make.jl index d7f62b704..4a407f687 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -69,6 +69,7 @@ pages_files = [ ], "For advanced users" => [ "advanced/errorhandling.md", + "advanced/test.md", "advanced/experimental.md", "advanced/parallel.md", "contributing.md", diff --git a/docs/src/advanced/test.md b/docs/src/advanced/test.md new file mode 100644 index 000000000..36f74c646 --- /dev/null +++ b/docs/src/advanced/test.md @@ -0,0 +1,16 @@ +# Test graphs + +`Graphs.Test` is a module containing generic graph structures which make as few hypotheses as possible beyond the basic interface. +It is not part of the public API and may break unexpectedly. + +## Index + +```@index +Pages = ["test.md"] +``` + +## Full docs + +```@autodocs +Modules = [Graphs.Test] +``` diff --git a/src/Experimental/vf2.jl b/src/Experimental/vf2.jl index c7b235e1c..8b66f7126 100644 --- a/src/Experimental/vf2.jl +++ b/src/Experimental/vf2.jl @@ -658,7 +658,7 @@ function all_isomorph( edge_relation::Union{Nothing,Function}=nothing, )::Channel{Vector{Tuple{eltype(g1),eltype(g2)}}} T = Vector{Tuple{eltype(g1),eltype(g2)}} - !could_have_isomorph(g1, g2) && return Channel(_ -> nothing, ctype = T) # TODO: fix problem with JuliaFormatter, right now the whole file is ignored + !could_have_isomorph(g1, g2) && return Channel(_ -> nothing, ctype = T) make_callback(c) = vmap -> (put!(c, collect(zip(vmap, 1:length(vmap)))), return true) ch::Channel{T} = Channel(; ctype=T) do c vf2( diff --git a/src/Parallel/centrality/stress.jl b/src/Parallel/centrality/stress.jl index 3a87289b1..58844af8d 100644 --- a/src/Parallel/centrality/stress.jl +++ b/src/Parallel/centrality/stress.jl @@ -52,7 +52,9 @@ function threaded_stress_centrality(g::AbstractGraph, vs=vertices(g))::Vector{In @sync for (t, task_range) in enumerate(Iterators.partition(1:k, task_size)) Threads.@spawn for s in @view(vs[task_range]) if degree(g, s) > 0 # this might be 1? - state = Graphs.dijkstra_shortest_paths(g, s; allpaths=true, trackvertices=true) + state = Graphs.dijkstra_shortest_paths( + g, s; allpaths=true, trackvertices=true + ) Graphs._stress_accumulate_basic!(local_stress[t], state, g, s) end end diff --git a/src/SimpleGraphs/generators/randgraphs.jl b/src/SimpleGraphs/generators/randgraphs.jl index 68716ed50..b9b5520c2 100644 --- a/src/SimpleGraphs/generators/randgraphs.jl +++ b/src/SimpleGraphs/generators/randgraphs.jl @@ -127,11 +127,16 @@ function randbn( end """ - erdos_renyi(n, p) + erdos_renyi(n, p::Real) Create an [Erdős–Rényi](http://en.wikipedia.org/wiki/Erdős–Rényi_model) random graph with `n` vertices. Edges are added between pairs of vertices with -probability `p`. +probability `p`. + +Note that there exists another definition of the Erdös-Rényi model in which the +total number of edges is kept constant, rather than the probability `p`. +To access this definition, use `erdos_renyi(n, ne::Integer)` +(specifically: `erdos_renyi(n, 1) != erdos_renyi(n, 1.0)`). ### Optional Arguments - `is_directed=false`: if true, return a directed graph. @@ -170,7 +175,7 @@ function erdos_renyi( end """ - erdos_renyi(n, ne) + erdos_renyi(n, ne::Integer) Create an [Erdős–Rényi](http://en.wikipedia.org/wiki/Erdős–Rényi_model) random graph with `n` vertices and `ne` edges. @@ -443,7 +448,9 @@ function newman_watts_strogatz( rng::Union{Nothing,AbstractRNG}=nothing, seed::Union{Nothing,Integer}=nothing, ) - return watts_strogatz(n, k, β; is_directed=is_directed, remove_edges=false, rng=rng, seed=seed) + return watts_strogatz( + n, k, β; is_directed=is_directed, remove_edges=false, rng=rng, seed=seed + ) end function _suitable(edges::Set{SimpleEdge{T}}, potential_edges::Dict{T,T}) where {T<:Integer} diff --git a/src/SimpleGraphs/simpleedge.jl b/src/SimpleGraphs/simpleedge.jl index 9ac8ca167..6b79a5887 100644 --- a/src/SimpleGraphs/simpleedge.jl +++ b/src/SimpleGraphs/simpleedge.jl @@ -34,4 +34,6 @@ function ==(e1::AbstractSimpleEdge, e2::AbstractSimpleEdge) return (src(e1) == src(e2) && dst(e1) == dst(e2)) end hash(e::AbstractSimpleEdge, h::UInt) = hash(src(e), hash(dst(e), h)) -isless(e1::AbstractSimpleEdge, e2::AbstractSimpleEdge) = (src(e1) < src(e2)) || ((src(e1) == src(e2)) && (dst(e1) < dst(e2))) +function isless(e1::AbstractSimpleEdge, e2::AbstractSimpleEdge) + return (src(e1) < src(e2)) || ((src(e1) == src(e2)) && (dst(e1) < dst(e2))) +end diff --git a/src/centrality/stress.jl b/src/centrality/stress.jl index 90ef320d1..0ca728544 100644 --- a/src/centrality/stress.jl +++ b/src/centrality/stress.jl @@ -51,7 +51,9 @@ function stress_centrality( rng::Union{Nothing,AbstractRNG}=nothing, seed::Union{Nothing,Integer}=nothing, ) - return stress_centrality(g, sample(collect_if_not_vector(vertices(g)), k; rng=rng, seed=seed)) + return stress_centrality( + g, sample(collect_if_not_vector(vertices(g)), k; rng=rng, seed=seed) + ) end function _stress_accumulate_basic!( diff --git a/src/core.jl b/src/core.jl index 93b61f0bb..cb8abd175 100644 --- a/src/core.jl +++ b/src/core.jl @@ -136,7 +136,6 @@ end degree(g::AbstractGraph, vs=vertices(g)) = [degree(g, x) for x in vs] - """ Δout(g) diff --git a/src/graphcut/normalized_cut.jl b/src/graphcut/normalized_cut.jl index 9dabf8d10..b6e9aa376 100644 --- a/src/graphcut/normalized_cut.jl +++ b/src/graphcut/normalized_cut.jl @@ -118,7 +118,7 @@ end function _recursive_normalized_cut(W, thres, num_cuts) m, n = size(W) (m <= 1) && return ones(Int, m) # trivial - D = Diagonal(vec(sum(W, dims=2))) + D = Diagonal(vec(sum(W; dims=2))) # check that the diagonal is not degenerated as otherwise invDroot errors dnz = abs.(diag(D)) .>= 1E-16 @@ -137,7 +137,7 @@ function _recursive_normalized_cut(W, thres, num_cuts) # At least some versions of ARPACK have a bug, this is a workaround invDroot = sqrt.(inv(D)) # equal to Cholesky factorization for diagonal D if n > 12 - _, Q = eigs(invDroot' * (D - W) * invDroot, nev=12, which=SR()) + _, Q = eigs(invDroot' * (D - W) * invDroot; nev=12, which=SR()) (size(Q, 2) <= 1) && return collect(1:m) # no 2nd eigenvector ret = convert(Vector, real(view(Q, :, 2))) else @@ -149,7 +149,7 @@ function _recursive_normalized_cut(W, thres, num_cuts) min_cost = Inf best_thres = -1 vmin, vmax = extrema(v) - for t in range(vmin, stop=vmax, length=num_cuts) + for t in range(vmin; stop=vmax, length=num_cuts) cut = v .> t cost = _normalized_cut_cost(cut, W, D) if cost < min_cost diff --git a/src/linalg/LinAlg.jl b/src/linalg/LinAlg.jl index 3d4cd31d7..37bf655bc 100644 --- a/src/linalg/LinAlg.jl +++ b/src/linalg/LinAlg.jl @@ -52,7 +52,7 @@ function eigs(A; kwargs...) vals, vectors = partialeigen(schr[1]) reved = (kwargs[:which] == LR() || kwargs[:which] == LM()) k = min(get(kwargs, :nev, length(vals))::Int, length(vals)) - perm = sortperm(vals, by=real, rev=reved)[1:k] + perm = sortperm(vals; by=real, rev=reved)[1:k] λ = vals[perm] Q = vectors[:, perm] return λ, Q diff --git a/src/traversals/dfs.jl b/src/traversals/dfs.jl index 03eaca158..a18fa9e5c 100644 --- a/src/traversals/dfs.jl +++ b/src/traversals/dfs.jl @@ -53,7 +53,7 @@ end end else pop!(vertex_stack) - if vcolor[u] == 1 + if vcolor[u] == 1 vcolor[u] = 2 end end @@ -107,10 +107,10 @@ function topological_sort_by_dfs end push!(vertex_stack, n) end end - else + else pop!(vertex_stack) # if vcolor[u] == 2, the vertex was already explored and added to verts - if vcolor[u] == 1 + if vcolor[u] == 1 vcolor[u] = 2 pushfirst!(verts, u) end diff --git a/src/traversals/eulerian.jl b/src/traversals/eulerian.jl index c70d8d1cf..7d27da4ae 100644 --- a/src/traversals/eulerian.jl +++ b/src/traversals/eulerian.jl @@ -17,7 +17,7 @@ cycle, the path starts _and_ ends at vertex `u`. """ function eulerian(g::AbstractGraph{T}, u::T=first(vertices(g))) where {T} is_directed(g) && error("`eulerian` is not yet implemented for directed graphs") - + _check_eulerian_input(g, u) # perform basic sanity checks g′ = SimpleGraph{T}(nv(g)) # copy `g` (mutated in `_eulerian!`) @@ -28,7 +28,7 @@ function eulerian(g::AbstractGraph{T}, u::T=first(vertices(g))) where {T} return _eulerian!(g′, u) end -@traitfn function _eulerian!(g::AG::(!IsDirected), u::T) where {T, AG<:AbstractGraph{T}} +@traitfn function _eulerian!(g::AG::(!IsDirected), u::T) where {T,AG<:AbstractGraph{T}} # TODO: This uses Fleury's algorithm which is O(|E|²) in the number of edges |E|. # Hierholzer's algorithm [https://en.wikipedia.org/wiki/Eulerian_path#Hierholzer's_algorithm] # is presumably faster, running in O(|E|) time, but requires needing to keep track @@ -67,7 +67,7 @@ end end end end - error("unreachable reached") + return error("unreachable reached") end @inline function _excludes_edge(u, w, e::AbstractEdge) @@ -82,7 +82,7 @@ function _check_eulerian_input(g, u) end # special case: if any vertex has degree zero - if any(x->degree(g, x) == 0, vertices(g)) + if any(x -> degree(g, x) == 0, vertices(g)) error("some vertices have degree zero (are isolated) and cannot be reached") end @@ -90,14 +90,18 @@ function _check_eulerian_input(g, u) du = degree(g, u) if iseven(du) # cycle: start (u) == stop (v) - all nodes must have even degree if any(x -> isodd(degree(g, x)), vertices(g)) - error("starting vertex has even degree but there are other vertices with odd degree: a eulerian cycle does not exist") + error( + "starting vertex has even degree but there are other vertices with odd degree: a eulerian cycle does not exist", + ) end else # isodd(du) # trail: start (u) != stop (v) - all nodes, except u and v, must have even degree if count(x -> iseven(degree(g, x)), vertices(g)) != 2 - error("starting vertex has odd degree but the total number of vertices of odd degree is not equal to 2: a eulerian trail does not exist") + error( + "starting vertex has odd degree but the total number of vertices of odd degree is not equal to 2: a eulerian trail does not exist", + ) end end # to reduce cost, the graph connectivity check is performed in `_eulerian!` rather # than through `is_connected(g)` -end \ No newline at end of file +end diff --git a/src/traversals/maxadjvisit.jl b/src/traversals/maxadjvisit.jl index 0b3bbf5b4..7ebcd36f2 100644 --- a/src/traversals/maxadjvisit.jl +++ b/src/traversals/maxadjvisit.jl @@ -16,8 +16,9 @@ weight of the cut that makes this partition. An optional `distmx` matrix of non-negative weights may be specified; if omitted, edge distances are assumed to be 1. """ -@traitfn function mincut(g::::(!IsDirected), distmx::AbstractMatrix{T}=weights(g)) where {T <: Real} - +@traitfn function mincut( + g::::(!IsDirected), distmx::AbstractMatrix{T}=weights(g) +) where {T<:Real} nvg = nv(g) U = eltype(g) @@ -25,18 +26,26 @@ assumed to be 1. # in which case we'll return immediately. (nvg > one(U)) || return (Vector{Int8}([1]), zero(T)) + # to avoid reallocating lists in fadjlist, we have some already merged vertices + # still appearing in fadjlist. When iterating neighbors, is_merged makes sure we + # don't consider them is_merged = falses(nvg) merged_vertices = IntDisjointSets(U(nvg)) graph_size = nvg # We need to mutate the weight matrix, # and we need it clean (0 for non edges) w = zeros(T, nvg, nvg) - size(distmx) != (nvg, nvg) && throw(ArgumentError("Adjacency / distance matrix size should match the number of vertices")) + size(distmx) != (nvg, nvg) && throw( + ArgumentError( + "Adjacency / distance matrix size should match the number of vertices" + ), + ) @inbounds for e in edges(g) d = distmx[src(e), dst(e)] (d < 0) && throw(DomainError(w, "weigths should be non-negative")) w[src(e), dst(e)] = d - (d != distmx[dst(e), src(e)]) && throw(ArgumentError("Adjacency / distance matrix must be symmetric")) + (d != distmx[dst(e), src(e)]) && + throw(ArgumentError("Adjacency / distance matrix must be symmetric")) w[dst(e), src(e)] = d end # we also need to mutate neighbors when merging vertices @@ -48,7 +57,6 @@ assumed to be 1. is_processed = falses(nvg) @inbounds while graph_size > 1 - cutweight = zero(T) is_processed .= false is_processed[u] = true # initialize pq @@ -58,34 +66,25 @@ assumed to be 1. pq[v] = zero(T) end for v in fadjlist[u] - (is_merged[v] || v == u ) && continue + (is_merged[v] || v == u) && continue pq[v] = w[u, v] - cutweight += w[u, v] end # Minimum cut phase + local cutweight while true last_vertex = u - u, adj_cost = first(pq) - dequeue!(pq) + u, cutweight = dequeue_pair!(pq) isempty(pq) && break for v in fadjlist[u] - (is_merged[v] || u == v) && continue - # if the target of e is already marked then decrease cutweight - # otherwise, increase it - ew = w[u, v] - if is_processed[v] - cutweight -= ew - else - cutweight += ew - pq[v] += ew - end + (is_processed[v] || is_merged[v] || u == v) && continue + pq[v] += w[u, v] end is_processed[u] = true - # adj_cost is a lower bound on the cut separating the two last vertices - # encountered, so if adj_cost >= bestweight, we can already merge these + # cutweight is a lower bound on the cut separating the two last vertices + # encountered, so if cutweight >= bestweight, we can already merge these # vertices to save one phase. - if adj_cost >= bestweight - _merge_vertex!(merged_vertices, fadjlist, is_merged, w, u, last_vertex) + if cutweight >= bestweight + u = _merge_vertex!(merged_vertices, fadjlist, is_merged, w, u, last_vertex) graph_size -= 1 end end @@ -99,14 +98,14 @@ assumed to be 1. end # merge u and last_vertex - root = _merge_vertex!(merged_vertices, fadjlist, is_merged, w, u, last_vertex) + u = _merge_vertex!(merged_vertices, fadjlist, is_merged, w, u, last_vertex) graph_size -= 1 - u = root # we are sure this vertex was not merged, so the next phase start from it end return (convert(Vector{Int8}, parities) .+ one(Int8), bestweight) end function _merge_vertex!(merged_vertices, fadjlist, is_merged, w, u, v) + # root is kept, non-root is discarded root = union!(merged_vertices, u, v) non_root = (root == u) ? v : u is_merged[non_root] = true @@ -116,7 +115,7 @@ function _merge_vertex!(merged_vertices, fadjlist, is_merged, w, u, v) w[v2, root] = w[root, v2] end # update neighbors - fadjlist[root] = union(fadjlist[root], fadjlist[non_root]) + union!(fadjlist[root], fadjlist[non_root]) for v in fadjlist[non_root] if root ∉ fadjlist[v] push!(fadjlist[v], root) diff --git a/test/biconnectivity/articulation.jl b/test/biconnectivity/articulation.jl index d674c675a..0ebaff9bd 100644 --- a/test/biconnectivity/articulation.jl +++ b/test/biconnectivity/articulation.jl @@ -33,7 +33,7 @@ hint = blockdiag(wheel_graph(5), wheel_graph(5)) add_edge!(hint, 5, 6) - for h in test_generic_graphs(hint, eltypes=[Int, UInt8, Int16]) + for h in test_generic_graphs(hint; eltypes=[Int, UInt8, Int16]) @test @inferred(articulation(h)) == [5, 6] end end diff --git a/test/centrality/betweenness.jl b/test/centrality/betweenness.jl index d05454be5..1a7fdf520 100644 --- a/test/centrality/betweenness.jl +++ b/test/centrality/betweenness.jl @@ -1,8 +1,8 @@ @testset "Betweenness" begin rng = StableRNG(1) # self loops - s1 = GenericGraph(SimpleGraph(Edge.([(1,2), (2,3), (3, 3)]))) - s2 = GenericDiGraph(SimpleDiGraph(Edge.([(1,2), (2,3), (3, 3)]))) + s1 = GenericGraph(SimpleGraph(Edge.([(1, 2), (2, 3), (3, 3)]))) + s2 = GenericDiGraph(SimpleDiGraph(Edge.([(1, 2), (2, 3), (3, 3)]))) g3 = GenericGraph(path_graph(5)) diff --git a/test/cycles/limited_length.jl b/test/cycles/limited_length.jl index 051c06671..8c24170eb 100644 --- a/test/cycles/limited_length.jl +++ b/test/cycles/limited_length.jl @@ -50,8 +50,10 @@ # This is probably because it uses induced_subgraph which fails on that graph type. octalengths, _ = simplecycleslength(octadg) for k in 1:6 - @test sum(octalengths[1:k]) == length(simplecycles_limited_length(GenericGraph(octag), k)) - @test sum(octalengths[1:k]) == length(simplecycles_limited_length(GenericDiGraph(octadg), k)) + @test sum(octalengths[1:k]) == + length(simplecycles_limited_length(GenericGraph(octag), k)) + @test sum(octalengths[1:k]) == + length(simplecycles_limited_length(GenericDiGraph(octadg), k)) end end end diff --git a/test/degeneracy.jl b/test/degeneracy.jl index 48378bd23..0022e21df 100644 --- a/test/degeneracy.jl +++ b/test/degeneracy.jl @@ -22,7 +22,6 @@ @test @inferred(k_crust(g, 2)) == k_crust(g, 2; corenum=corenum) == [9:21;] @test @inferred(k_crust(g, 4, corenum=corenum)) == [1:21;] end - end # TODO k_corona does not work yet with generic graphs diff --git a/test/edit_distance.jl b/test/edit_distance.jl index adc505b22..952f23889 100644 --- a/test/edit_distance.jl +++ b/test/edit_distance.jl @@ -14,7 +14,9 @@ edge_delete_cost = e -> 5.0 edge_subst_cost = (e1, e2) -> 6.0 - @testset "undirected edit_distance" for G1 in test_generic_graphs(g1), G2 in test_generic_graphs(g2) + @testset "undirected edit_distance" for G1 in test_generic_graphs(g1), + G2 in test_generic_graphs(g2) + d, λ = @inferred(edit_distance(G1, G2)) @test d == 2.0 d, λ = @inferred( @@ -44,7 +46,9 @@ add_edge!(g2, e) end - @testset "directed edit_distance" for G1 in test_generic_graphs(g1), G2 in test_generic_graphs(g2) + @testset "directed edit_distance" for G1 in test_generic_graphs(g1), + G2 in test_generic_graphs(g2) + d, λ = @inferred(edit_distance(G1, G2)) @test d == 4.0 end diff --git a/test/runtests.jl b/test/runtests.jl index 289c5136c..5e47f7407 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -28,23 +28,6 @@ function get_pkg_version(name::AbstractString) return error("Dependency not available") end -@testset "Code quality (JET.jl)" begin - if VERSION >= v"1.9" - @assert get_pkg_version("JET") >= v"0.8.4" - JET.test_package(Graphs; target_defined_modules=true, ignore_missing_comparison=true) - end -end - -@testset verbose = true "Code quality (Aqua.jl)" begin - Aqua.test_all(Graphs; ambiguities=false) -end - -@testset verbose = true "Code formatting (JuliaFormatter.jl)" begin - @test format(Graphs; verbose=false, overwrite=false, ignore="vf2.jl") # TODO: remove ignore kwarg once the file is formatted correctly -end - -doctest(Graphs) - function testgraphs(g) return if is_directed(g) [g, DiGraph{UInt8}(g), DiGraph{Int16}(g)] @@ -70,7 +53,7 @@ function test_generic_graphs(g; eltypes=[UInt8, Int16], skip_if_too_large::Bool= SG = is_directed(g) ? SimpleDiGraph : SimpleGraph GG = is_directed(g) ? GenericDiGraph : GenericGraph result = GG[] - for T in eltypes + for T in eltypes if skip_if_too_large && nv(g) > typemax(T) continue end @@ -79,10 +62,15 @@ function test_generic_graphs(g; eltypes=[UInt8, Int16], skip_if_too_large::Bool= return result end -test_generic_graphs(gs...; kwargs...) = vcat((test_generic_graphs(g; kwargs...) for g in gs)...) - -test_large_generic_graphs(g; skip_if_too_large::Bool=false) = test_generic_graphs(g; eltypes=[UInt16, Int32], skip_if_too_large=skip_if_too_large) +function test_generic_graphs(gs...; kwargs...) + return vcat((test_generic_graphs(g; kwargs...) for g in gs)...) +end +function test_large_generic_graphs(g; skip_if_too_large::Bool=false) + return test_generic_graphs( + g; eltypes=[UInt16, Int32], skip_if_too_large=skip_if_too_large + ) +end tests = [ "simplegraphs/runtests", @@ -157,9 +145,30 @@ tests = [ ] @testset verbose = true "Graphs" begin - for t in tests - tp = joinpath(testdir, "$(t).jl") - include(tp) + @testset "Code quality (JET.jl)" begin + if VERSION >= v"1.9" + @assert get_pkg_version("JET") >= v"0.8.4" + JET.test_package( + Graphs; target_defined_modules=true, ignore_missing_comparison=true + ) + end + end + + @testset "Code quality (Aqua.jl)" begin + Aqua.test_all(Graphs; ambiguities=false) + end + + @testset "Code formatting (JuliaFormatter.jl)" begin + @test format(Graphs; verbose=false, overwrite=false) + end + + doctest(Graphs) + + @testset verbose = true "Actual tests" begin + for t in tests + tp = joinpath(testdir, "$(t).jl") + include(tp) + end end end; diff --git a/test/shortestpaths/astar.jl b/test/shortestpaths/astar.jl index b1af146ff..3eb6d1f71 100644 --- a/test/shortestpaths/astar.jl +++ b/test/shortestpaths/astar.jl @@ -10,7 +10,10 @@ @inferred(a_star(g, 1, 4, d2)) @test isempty(@inferred(a_star(dg, 4, 1))) end - @testset "GenericGraph and GenricDiGraph with SimpleEdge" for g in test_generic_graphs(g3), dg in test_generic_graphs(g4) + @testset "GenericGraph and GenricDiGraph with SimpleEdge" for g in + test_generic_graphs(g3), + dg in test_generic_graphs(g4) + zero_heuristic = n -> 0 Eg = SimpleEdge{eltype(g)} Edg = SimpleEdge{eltype(dg)} @@ -30,5 +33,6 @@ s::Int d::Int end - @test eltype(a_star(GenericGraph(g), 1, 4, w, n -> 0, MyFavoriteEdgeType)) == MyFavoriteEdgeType + @test eltype(a_star(GenericGraph(g), 1, 4, w, n -> 0, MyFavoriteEdgeType)) == + MyFavoriteEdgeType end diff --git a/test/shortestpaths/dijkstra.jl b/test/shortestpaths/dijkstra.jl index a4f0f21b2..59937244c 100644 --- a/test/shortestpaths/dijkstra.jl +++ b/test/shortestpaths/dijkstra.jl @@ -103,12 +103,14 @@ end #maximum distance setting limits paths found - G = cycle_graph(6) - add_edge!(G, 1, 3) - m = float([0 2 2 0 0 1; 2 0 1 0 0 0; 2 1 0 4 0 0; 0 0 4 0 1 0; 0 0 0 1 0 1; 1 0 0 0 1 0]) + G = cycle_graph(6) + add_edge!(G, 1, 3) + m = float( + [0 2 2 0 0 1; 2 0 1 0 0 0; 2 1 0 4 0 0; 0 0 4 0 1 0; 0 0 0 1 0 1; 1 0 0 0 1 0] + ) - for g in test_generic_graphs(G) - ds = @inferred(dijkstra_shortest_paths(g, 3, m;maxdist=3.0)) - @test ds.dists == [2, 1, 0, Inf, Inf, 3] - end + for g in test_generic_graphs(G) + ds = @inferred(dijkstra_shortest_paths(g, 3, m; maxdist=3.0)) + @test ds.dists == [2, 1, 0, Inf, Inf, 3] + end end diff --git a/test/shortestpaths/yen.jl b/test/shortestpaths/yen.jl index 2014f6ccb..af1dfb393 100644 --- a/test/shortestpaths/yen.jl +++ b/test/shortestpaths/yen.jl @@ -113,16 +113,16 @@ w[1, 4] = 3 w[4, 1] = 3 for g in testdigraphs(G) - ds = @inferred(yen_k_shortest_paths(g, 1, 6, w, 100)) + ds = @inferred(yen_k_shortest_paths(g, 1, 6, w, 100)) @test ds.dists == [4.0, 5.0, 7.0, 7.0, 8.0, 8.0, 8.0, 11.0, 11.0] - - ds = @inferred(yen_k_shortest_paths(g, 1, 6, w, 100, maxdist=7.)) + + ds = @inferred(yen_k_shortest_paths(g, 1, 6, w, 100, maxdist=7.0)) @test ds.dists == [4.0, 5.0, 7.0, 7.0] - end + end - # Test that no paths are returned if every path is longer than maxdist + # Test that no paths are returned if every path is longer than maxdist for g in testdigraphs(cycle_digraph(10)) ds = @inferred(yen_k_shortest_paths(g, 2, 1, weights(g), 2, maxdist=2)) @test isempty(ds.paths) - end + end end diff --git a/test/simplegraphs/simpleedge.jl b/test/simplegraphs/simpleedge.jl index 8f8f895d7..e92b4a2b2 100644 --- a/test/simplegraphs/simpleedge.jl +++ b/test/simplegraphs/simpleedge.jl @@ -37,7 +37,7 @@ end @testset "comparison" begin - @test SimpleEdge(1, 2) < SimpleEdge(1, 3) + @test SimpleEdge(1, 2) < SimpleEdge(1, 3) @test SimpleEdge(1, 2) < SimpleEdge(2, 3) @test SimpleEdge(1, 2) < SimpleEdge(2, 1) @test SimpleEdge(1, 2) <= SimpleEdge(1, 2) diff --git a/test/traversals/dfs.jl b/test/traversals/dfs.jl index a77f649b1..53ef3b6de 100644 --- a/test/traversals/dfs.jl +++ b/test/traversals/dfs.jl @@ -31,7 +31,7 @@ add_edge!(g6, 4, 3) g7 = copy(g6) add_edge!(g7, 3, 4) - + @testset "dfs_tree" begin for g in testdigraphs(g5) z = @inferred(dfs_tree(GenericDiGraph(g), 1)) diff --git a/test/traversals/eulerian.jl b/test/traversals/eulerian.jl index bea337a26..88c9bf00a 100644 --- a/test/traversals/eulerian.jl +++ b/test/traversals/eulerian.jl @@ -1,36 +1,68 @@ @testset "Eulerian tours/cycles" begin # a cycle (identical start/end) - g0 = GenericGraph(SimpleGraph([Edge(1,2), Edge(2,3), Edge(3,1)])) + g0 = GenericGraph(SimpleGraph([Edge(1, 2), Edge(2, 3), Edge(3, 1)])) @test eulerian(g0, 1) == eulerian(g0) @test last(eulerian(g0, 1)) == 1 # a cycle # a tour (different start/end) - g1 = GenericGraph(SimpleGraph([Edge(1,2), Edge(2,3), Edge(3,4)])) - @test eulerian(g1, 1) == [1,2,3,4] - @test_throws ErrorException("starting vertex has even degree but there are other vertices with odd degree: a eulerian cycle does not exist") eulerian(g1, 2) - + g1 = GenericGraph(SimpleGraph([Edge(1, 2), Edge(2, 3), Edge(3, 4)])) + @test eulerian(g1, 1) == [1, 2, 3, 4] + @test_throws ErrorException( + "starting vertex has even degree but there are other vertices with odd degree: a eulerian cycle does not exist", + ) eulerian(g1, 2) + # a cycle with a node (vertex 2) with multiple neighbors - g2 = GenericGraph(SimpleGraph([Edge(1,2), Edge(2,3), Edge(3,4), Edge(4,1), Edge(2,5), Edge(5,6), Edge(6,2)])) + g2 = GenericGraph( + SimpleGraph([ + Edge(1, 2), + Edge(2, 3), + Edge(3, 4), + Edge(4, 1), + Edge(2, 5), + Edge(5, 6), + Edge(6, 2), + ]), + ) @test eulerian(g2) == eulerian(g2, 1) == [1, 2, 5, 6, 2, 3, 4, 1] # graph with odd-degree vertices - g3 = GenericGraph(SimpleGraph([Edge(1,2), Edge(2,3), Edge(3,4), Edge(2,4), Edge(4,1), Edge(4,2)])) - @test_throws ErrorException("starting vertex has even degree but there are other vertices with odd degree: a eulerian cycle does not exist") eulerian(g3, 1) + g3 = GenericGraph( + SimpleGraph([ + Edge(1, 2), Edge(2, 3), Edge(3, 4), Edge(2, 4), Edge(4, 1), Edge(4, 2) + ]), + ) + @test_throws ErrorException( + "starting vertex has even degree but there are other vertices with odd degree: a eulerian cycle does not exist", + ) eulerian(g3, 1) # start/end point not in graph @test_throws ErrorException("starting vertex is not in the graph") eulerian(g3, 5) # disconnected components - g4 = GenericGraph(SimpleGraph([Edge(1,2), Edge(2,3), Edge(3,1), # component 1 - Edge(4,5), Edge(5,6), Edge(6,4)])) # component 2 - @test_throws ErrorException("graph is not connected: a eulerian cycle/trail does not exist") eulerian(g4) + g4 = GenericGraph( + SimpleGraph([ + Edge(1, 2), + Edge(2, 3), + Edge(3, 1), # component 1 + Edge(4, 5), + Edge(5, 6), + Edge(6, 4), + ]), + ) # component 2 + @test_throws ErrorException( + "graph is not connected: a eulerian cycle/trail does not exist" + ) eulerian(g4) # zero-degree nodes g5′ = SimpleGraph(4) - add_edge!(g5′, Edge(1,2)); add_edge!(g5′, Edge(2,3)); add_edge!(g5′, Edge(3,1)) + add_edge!(g5′, Edge(1, 2)) + add_edge!(g5′, Edge(2, 3)) + add_edge!(g5′, Edge(3, 1)) g5 = GenericGraph(g5′) - @test_throws ErrorException("some vertices have degree zero (are isolated) and cannot be reached") eulerian(g5) + @test_throws ErrorException( + "some vertices have degree zero (are isolated) and cannot be reached" + ) eulerian(g5) # not yet implemented for directed graphs - @test_broken eulerian(GenericDiGraph([Edge(1,2), Edge(2,3), Edge(3,1)])) + @test_broken eulerian(GenericDiGraph([Edge(1, 2), Edge(2, 3), Edge(3, 1)])) end diff --git a/test/traversals/maxadjvisit.jl b/test/traversals/maxadjvisit.jl index e76359140..fa1306393 100644 --- a/test/traversals/maxadjvisit.jl +++ b/test/traversals/maxadjvisit.jl @@ -78,6 +78,6 @@ @test parity == [1, 1, 1, 1, 2, 2, 2, 2] @test bestcut == 6 - w[6,7] = -1 + w[6, 7] = -1 @test_throws DomainError mincut(g, w) end diff --git a/test/utils.jl b/test/utils.jl index 01277f748..d829018cf 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -84,7 +84,6 @@ end end @testset "collect_if_not_vector" begin - vectors = [["ab", "cd"], 1:2:9, BitVector([0, 1, 0])] not_vectors = [Set([1, 2]), (x for x in Int8[3, 4]), "xyz"]