From 23ca2ef454f961dd51f0f96343a5858eb58f96ab Mon Sep 17 00:00:00 2001 From: Guillaume Dalle <22795598+gdalle@users.noreply.github.com> Date: Fri, 29 May 2026 11:07:24 +0200 Subject: [PATCH] Format code --- benchmark/benchmarks.jl | 10 +- docs/make.jl | 24 +++-- ext/SparseMatrixColoringsCUDAExt.jl | 72 ++++++++++---- ext/SparseMatrixColoringsCliqueTreesExt.jl | 2 +- ext/SparseMatrixColoringsColorsExt.jl | 25 +++-- ext/SparseMatrixColoringsGPUArraysExt.jl | 6 +- ext/SparseMatrixColoringsJuMPExt.jl | 16 ++- src/adtypes.jl | 4 +- src/check.jl | 81 ++++++++++----- src/coloring.jl | 52 +++++----- src/constant.jl | 22 +++-- src/decompression.jl | 109 +++++++++++++-------- src/forest.jl | 4 +- src/graph.jl | 86 ++++++++-------- src/interface.jl | 59 +++++------ src/matrices.jl | 14 ++- src/optimal.jl | 6 +- src/order.jl | 95 ++++++++++-------- src/postprocessing.jl | 14 +-- src/precompile.jl | 2 +- src/result.jl | 49 ++++++--- test/adtypes.jl | 8 +- test/allocations.jl | 69 ++++++++----- test/check.jl | 66 ++++++++----- test/constant.jl | 25 ++--- test/constructors.jl | 10 +- test/cuda.jl | 23 +++-- test/graph.jl | 31 +++--- test/optimal.jl | 16 +-- test/order.jl | 41 ++++---- test/random.jl | 40 +++++--- test/result.jl | 6 +- test/runtests.jl | 5 +- test/show_colors.jl | 26 ++--- test/small.jl | 93 ++++++++++-------- test/structured.jl | 12 ++- test/suitesparse.jl | 41 ++++---- test/theory.jl | 8 +- test/type_stability.jl | 25 +++-- test/utils.jl | 69 ++++++++----- 40 files changed, 809 insertions(+), 557 deletions(-) diff --git a/benchmark/benchmarks.jl b/benchmark/benchmarks.jl index e77fad58..89bfc2f5 100644 --- a/benchmark/benchmarks.jl +++ b/benchmark/benchmarks.jl @@ -21,13 +21,15 @@ for structure in [:nonsymmetric, :symmetric], problem = ColoringProblem(; structure, partition) algo = GreedyColoringAlgorithm( - RandomOrder(StableRNG(0), 0); decompression, postprocessing=true + RandomOrder(StableRNG(0), 0); + decompression, + postprocessing = true, ) # use several random matrices to reduce variance nb_samples = 5 - As = [sparse(Symmetric(sprand(StableRNG(i), Bool, n, n, p))) for i in 1:nb_samples] - results = [coloring(A, problem, algo; decompression_eltype=Float64) for A in As] + As = [sparse(Symmetric(sprand(StableRNG(i), Bool, n, n, p))) for i = 1:nb_samples] + results = [coloring(A, problem, algo; decompression_eltype = Float64) for A in As] Bs = [compress(Float64.(A), result) for (A, result) in zip(As, results)] bench_col = @benchmarkable begin @@ -57,7 +59,7 @@ for structure in [:nonsymmetric, :symmetric], p in [2 / n, 5 / n, 10 / n] nb_samples = 5 - As = [sparse(Symmetric(sprand(StableRNG(i), Bool, n, n, p))) for i in 1:nb_samples] + As = [sparse(Symmetric(sprand(StableRNG(i), Bool, n, n, p))) for i = 1:nb_samples] if structure == :symmetric gs = [SMC.AdjacencyGraph(A) for A in As] bench_ord = @benchmarkable begin diff --git a/docs/make.jl b/docs/make.jl index 80d2a23d..79d4aa76 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -4,24 +4,28 @@ using SparseMatrixColorings links = InterLinks("ADTypes" => "https://sciml.github.io/ADTypes.jl/stable/") -cp(joinpath(@__DIR__, "..", "README.md"), joinpath(@__DIR__, "src", "index.md"); force=true) +cp( + joinpath(@__DIR__, "..", "README.md"), + joinpath(@__DIR__, "src", "index.md"); + force = true, +) makedocs(; - modules=[SparseMatrixColorings], - authors="Guillaume Dalle and Alexis Montoison", - sitename="SparseMatrixColorings.jl", - format=Documenter.HTML(), - pages=[ + modules = [SparseMatrixColorings], + authors = "Guillaume Dalle and Alexis Montoison", + sitename = "SparseMatrixColorings.jl", + format = Documenter.HTML(), + pages = [ "Home" => "index.md", "tutorial.md", "api.md", "Developer Documentation" => ["dev.md", "vis.md"], ], - plugins=[links], + plugins = [links], ) deploydocs(; - repo="github.com/JuliaDiff/SparseMatrixColorings.jl", - push_preview=true, - devbranch="main", + repo = "github.com/JuliaDiff/SparseMatrixColorings.jl", + push_preview = true, + devbranch = "main", ) diff --git a/ext/SparseMatrixColoringsCUDAExt.jl b/ext/SparseMatrixColoringsCUDAExt.jl index ed33eece..0894f2fa 100644 --- a/ext/SparseMatrixColoringsCUDAExt.jl +++ b/ext/SparseMatrixColoringsCUDAExt.jl @@ -8,22 +8,31 @@ using cuSPARSE: AbstractCuSparseMatrix, CuSparseMatrixCSC, CuSparseMatrixCSR ## CSC Result function SMC.ColumnColoringResult( - A::CuSparseMatrixCSC, bg::SMC.BipartiteGraph{T}, color::Vector{<:Integer} + A::CuSparseMatrixCSC, + bg::SMC.BipartiteGraph{T}, + color::Vector{<:Integer}, ) where {T<:Integer} group = SMC.group_by_color(T, color) compressed_indices = SMC.column_csc_indices(bg, color) - additional_info = (; compressed_indices_gpu_csc=CuVector(compressed_indices)) + additional_info = (; compressed_indices_gpu_csc = CuVector(compressed_indices)) return SMC.ColumnColoringResult( - A, bg, color, group, compressed_indices, additional_info + A, + bg, + color, + group, + compressed_indices, + additional_info, ) end function SMC.RowColoringResult( - A::CuSparseMatrixCSC, bg::SMC.BipartiteGraph{T}, color::Vector{<:Integer} + A::CuSparseMatrixCSC, + bg::SMC.BipartiteGraph{T}, + color::Vector{<:Integer}, ) where {T<:Integer} group = SMC.group_by_color(T, color) compressed_indices = SMC.row_csc_indices(bg, color) - additional_info = (; compressed_indices_gpu_csc=CuVector(compressed_indices)) + additional_info = (; compressed_indices_gpu_csc = CuVector(compressed_indices)) return SMC.RowColoringResult(A, bg, color, group, compressed_indices, additional_info) end @@ -35,33 +44,47 @@ function SMC.StarSetColoringResult( ) where {T<:Integer} group = SMC.group_by_color(T, color) compressed_indices = SMC.star_csc_indices(ag, color, star_set) - additional_info = (; compressed_indices_gpu_csc=CuVector(compressed_indices)) + additional_info = (; compressed_indices_gpu_csc = CuVector(compressed_indices)) return SMC.StarSetColoringResult( - A, ag, color, group, compressed_indices, additional_info + A, + ag, + color, + group, + compressed_indices, + additional_info, ) end ## CSR Result function SMC.ColumnColoringResult( - A::CuSparseMatrixCSR, bg::SMC.BipartiteGraph{T}, color::Vector{<:Integer} + A::CuSparseMatrixCSR, + bg::SMC.BipartiteGraph{T}, + color::Vector{<:Integer}, ) where {T<:Integer} group = SMC.group_by_color(T, color) compressed_indices = SMC.column_csc_indices(bg, color) compressed_indices_csr = SMC.column_csr_indices(bg, color) - additional_info = (; compressed_indices_gpu_csr=CuVector(compressed_indices_csr)) + additional_info = (; compressed_indices_gpu_csr = CuVector(compressed_indices_csr)) return SMC.ColumnColoringResult( - A, bg, color, group, compressed_indices, additional_info + A, + bg, + color, + group, + compressed_indices, + additional_info, ) end function SMC.RowColoringResult( - A::CuSparseMatrixCSR, bg::SMC.BipartiteGraph{T}, color::Vector{<:Integer} + A::CuSparseMatrixCSR, + bg::SMC.BipartiteGraph{T}, + color::Vector{<:Integer}, ) where {T<:Integer} group = SMC.group_by_color(T, color) compressed_indices = SMC.row_csc_indices(bg, color) compressed_indices_csr = SMC.row_csr_indices(bg, color) - additional_info = (; compressed_indices_gpu_csr=CuVector(compressed_indices_csr)) + additional_info = (; compressed_indices_gpu_csr = CuVector(compressed_indices_csr)) return SMC.RowColoringResult(A, bg, color, group, compressed_indices, additional_info) end @@ -73,9 +96,14 @@ function SMC.StarSetColoringResult( ) where {T<:Integer} group = SMC.group_by_color(T, color) compressed_indices = SMC.star_csc_indices(ag, color, star_set) - additional_info = (; compressed_indices_gpu_csr=CuVector(compressed_indices)) + additional_info = (; compressed_indices_gpu_csr = CuVector(compressed_indices)) return SMC.StarSetColoringResult( - A, ag, color, group, compressed_indices, additional_info + A, + ag, + color, + group, + compressed_indices, + additional_info, ) end @@ -84,7 +112,9 @@ end for R in (:ColumnColoringResult, :RowColoringResult) # loop to avoid method ambiguity @eval function SMC.decompress!( - A::CuSparseMatrixCSC, B::CuMatrix, result::SMC.$R{<:CuSparseMatrixCSC} + A::CuSparseMatrixCSC, + B::CuMatrix, + result::SMC.$R{<:CuSparseMatrixCSC}, ) compressed_indices = result.additional_info.compressed_indices_gpu_csc copyto!(A.nzVal, view(B, compressed_indices)) @@ -92,7 +122,9 @@ for R in (:ColumnColoringResult, :RowColoringResult) end @eval function SMC.decompress!( - A::CuSparseMatrixCSR, B::CuMatrix, result::SMC.$R{<:CuSparseMatrixCSR} + A::CuSparseMatrixCSR, + B::CuMatrix, + result::SMC.$R{<:CuSparseMatrixCSR}, ) compressed_indices = result.additional_info.compressed_indices_gpu_csr copyto!(A.nzVal, view(B, compressed_indices)) @@ -104,12 +136,12 @@ function SMC.decompress!( A::CuSparseMatrixCSC, B::CuMatrix, result::SMC.StarSetColoringResult{<:CuSparseMatrixCSC}, - uplo::Symbol=:F, + uplo::Symbol = :F, ) if uplo != :F throw( SMC.UnsupportedDecompressionError( - "Single-triangle decompression is not supported on GPU matrices" + "Single-triangle decompression is not supported on GPU matrices", ), ) end @@ -122,12 +154,12 @@ function SMC.decompress!( A::CuSparseMatrixCSR, B::CuMatrix, result::SMC.StarSetColoringResult{<:CuSparseMatrixCSR}, - uplo::Symbol=:F, + uplo::Symbol = :F, ) if uplo != :F throw( SMC.UnsupportedDecompressionError( - "Single-triangle decompression is not supported on GPU matrices" + "Single-triangle decompression is not supported on GPU matrices", ), ) end diff --git a/ext/SparseMatrixColoringsCliqueTreesExt.jl b/ext/SparseMatrixColoringsCliqueTreesExt.jl index 5dde067f..7f42031e 100644 --- a/ext/SparseMatrixColoringsCliqueTreesExt.jl +++ b/ext/SparseMatrixColoringsCliqueTreesExt.jl @@ -15,7 +15,7 @@ function vertices(g::AdjacencyGraph{T}, order::PerfectEliminationOrder) where {T # construct a perfect elimination order # self-loops are ignored - order, _ = permutation(M; alg=order.elimination_algorithm) + order, _ = permutation(M; alg = order.elimination_algorithm) return reverse!(order) end diff --git a/ext/SparseMatrixColoringsColorsExt.jl b/ext/SparseMatrixColoringsColorsExt.jl index c934b5e9..ae953d7b 100644 --- a/ext/SparseMatrixColoringsColorsExt.jl +++ b/ext/SparseMatrixColoringsColorsExt.jl @@ -37,13 +37,13 @@ const DEFAULT_PAD = 0 function SparseMatrixColorings.show_colors( res::AbstractColoringResult; - colorscheme=nothing, - background_color::Colorant=DEFAULT_BACKGROUND_COLOR, # color used for zero matrix entries and pad - border_color::Colorant=DEFAULT_BORDER_COLOR, # color used for zero matrix entries and pad - scale::Int=DEFAULT_SCALE, # scale size of matrix entries to `scale × scale` pixels - border::Int=DEFAULT_BORDER, # border around matrix entries - pad::Int=DEFAULT_PAD, # pad between matrix entries - warn::Bool=true, + colorscheme = nothing, + background_color::Colorant = DEFAULT_BACKGROUND_COLOR, # color used for zero matrix entries and pad + border_color::Colorant = DEFAULT_BORDER_COLOR, # color used for zero matrix entries and pad + scale::Int = DEFAULT_SCALE, # scale size of matrix entries to `scale × scale` pixels + border::Int = DEFAULT_BORDER, # border around matrix entries + pad::Int = DEFAULT_PAD, # pad between matrix entries + warn::Bool = true, ) scale < 1 && throw(ArgumentError("`scale` has to be ≥ 1.")) border < 0 && throw(ArgumentError("`border` has to be ≥ 0.")) @@ -53,15 +53,14 @@ function SparseMatrixColorings.show_colors( if warn && ncolors(res) > length(colorscheme) @warn "`show_colors` will reuse colors since the provided `colorscheme` has $(length(colorscheme)) colors and the matrix needs $(ncolors(res)). You can turn off this warning via the keyword argument `warn = false`, or choose a larger `colorscheme` from ColorSchemes.jl." end - colorscheme, background_color, border_color = promote_colors( - colorscheme, background_color, border_color - ) + colorscheme, background_color, border_color = + promote_colors(colorscheme, background_color, border_color) else # Sample n distinguishable colors, excluding the background and border color colorscheme = distinguishable_colors( ncolors(res), [convert(RGB, background_color), convert(RGB, border_color)]; - dropseed=true, + dropseed = true, ) end outs = allocate_outputs(res, background_color, border_color, scale, border, pad) @@ -86,7 +85,7 @@ function matrix_entry_area(I::CartesianIndex, scale, border, pad) end function matrix_entry_plus_border_area(I::CartesianIndex, scale, border, pad) - stencil = CartesianIndices((1:(scale + 2border), 1:(scale + 2border))) + stencil = CartesianIndices((1:(scale+2border), 1:(scale+2border))) return CartesianIndex(1, 1) * pad + (I - CartesianIndex(1, 1)) * (scale + 2border + pad) .+ stencil end @@ -272,7 +271,7 @@ function show_colors!( A_rcolor_indices = mod1.(row_shift .+ row_colors(res), length(colorscheme)) B_ccolor_indices = mod1.(1:maximum(column_colors(res)), length(colorscheme)) B_rcolor_indices = - mod1.((row_shift + 1):(row_shift + maximum(row_colors(res))), length(colorscheme)) + mod1.((row_shift+1):(row_shift+maximum(row_colors(res))), length(colorscheme)) A_ccolors = colorscheme[A_ccolor_indices] A_rcolors = colorscheme[A_rcolor_indices] B_ccolors = colorscheme[B_ccolor_indices] diff --git a/ext/SparseMatrixColoringsGPUArraysExt.jl b/ext/SparseMatrixColoringsGPUArraysExt.jl index 37574e73..1bf8fdb9 100644 --- a/ext/SparseMatrixColoringsGPUArraysExt.jl +++ b/ext/SparseMatrixColoringsGPUArraysExt.jl @@ -9,7 +9,8 @@ SMC.matrix_versions(A::AbstractGPUSparseMatrix) = (A,) ## Compression (slow, through CPU) function SMC.compress( - A::AbstractGPUSparseMatrix, result::SMC.AbstractColoringResult{structure,:column} + A::AbstractGPUSparseMatrix, + result::SMC.AbstractColoringResult{structure,:column}, ) where {structure} A_cpu = SparseMatrixCSC(A) B_cpu = SMC.compress(A_cpu, result) @@ -18,7 +19,8 @@ function SMC.compress( end function SMC.compress( - A::AbstractGPUSparseMatrix, result::SMC.AbstractColoringResult{structure,:row} + A::AbstractGPUSparseMatrix, + result::SMC.AbstractColoringResult{structure,:row}, ) where {structure} A_cpu = SparseMatrixCSC(A) B_cpu = SMC.compress(A_cpu, result) diff --git a/ext/SparseMatrixColoringsJuMPExt.jl b/ext/SparseMatrixColoringsJuMPExt.jl index 77b74dbd..d22ef31f 100644 --- a/ext/SparseMatrixColoringsJuMPExt.jl +++ b/ext/SparseMatrixColoringsJuMPExt.jl @@ -21,8 +21,8 @@ function optimal_distance2_coloring( bg::BipartiteGraph, ::Val{side}, optimizer::O; - silent::Bool=true, - assert_solved::Bool=true, + silent::Bool = true, + assert_solved::Bool = true, ) where {side,O} other_side = 3 - side n = nb_vertices(bg, Val(side)) @@ -66,14 +66,22 @@ end function ADTypes.column_coloring(A::AbstractMatrix, algo::OptimalColoringAlgorithm) bg = BipartiteGraph(A) return optimal_distance2_coloring( - bg, Val(2), algo.optimizer; algo.silent, algo.assert_solved + bg, + Val(2), + algo.optimizer; + algo.silent, + algo.assert_solved, ) end function ADTypes.row_coloring(A::AbstractMatrix, algo::OptimalColoringAlgorithm) bg = BipartiteGraph(A) return optimal_distance2_coloring( - bg, Val(1), algo.optimizer; algo.silent, algo.assert_solved + bg, + Val(1), + algo.optimizer; + algo.silent, + algo.assert_solved, ) end diff --git a/src/adtypes.jl b/src/adtypes.jl index 7c464433..7792a898 100644 --- a/src/adtypes.jl +++ b/src/adtypes.jl @@ -4,8 +4,8 @@ function coloring( A::AbstractMatrix, problem::ColoringProblem{structure,partition}, algo::ADTypes.AbstractColoringAlgorithm; - decompression_eltype::Type{R}=Float64, - symmetric_pattern::Bool=false, + decompression_eltype::Type{R} = Float64, + symmetric_pattern::Bool = false, ) where {structure,partition,R} symmetric_pattern = symmetric_pattern || A isa Union{Symmetric,Hermitian} if structure == :nonsymmetric diff --git a/src/check.jl b/src/check.jl index db5c0a34..cfb73271 100644 --- a/src/check.jl +++ b/src/check.jl @@ -1,5 +1,7 @@ function proper_length_coloring( - A::AbstractMatrix, color::AbstractVector{<:Integer}; verbose::Bool=false + A::AbstractMatrix, + color::AbstractVector{<:Integer}; + verbose::Bool = false, ) m, n = size(A) if length(color) != n @@ -15,7 +17,7 @@ function proper_length_bicoloring( A::AbstractMatrix, row_color::AbstractVector{<:Integer}, column_color::AbstractVector{<:Integer}; - verbose::Bool=false, + verbose::Bool = false, ) m, n = size(A) bool = true @@ -52,7 +54,9 @@ A partition of the columns of a matrix `A` is _structurally orthogonal_ if, for > [_What Color Is Your Jacobian? Graph Coloring for Computing Derivatives_](https://epubs.siam.org/doi/10.1137/S0036144504444711), Gebremedhin et al. (2005) """ function structurally_orthogonal_columns( - A::AbstractMatrix, color::AbstractVector{<:Integer}; verbose::Bool=false + A::AbstractMatrix, + color::AbstractVector{<:Integer}; + verbose::Bool = false, ) if !proper_length_coloring(A, color; verbose) return false @@ -60,7 +64,7 @@ function structurally_orthogonal_columns( group = group_by_color(color) for (c, g) in enumerate(group) Ag = view(A, :, g) - nonzeros_per_row = only(eachcol(count(!iszero, Ag; dims=2))) + nonzeros_per_row = only(eachcol(count(!iszero, Ag; dims = 2))) max_nonzeros_per_row, i = findmax(nonzeros_per_row) if max_nonzeros_per_row > 1 if verbose @@ -98,7 +102,9 @@ It is equivalent to a __star coloring__. > [_What Color Is Your Jacobian? Graph Coloring for Computing Derivatives_](https://epubs.siam.org/doi/10.1137/S0036144504444711), Gebremedhin et al. (2005) """ function symmetrically_orthogonal_columns( - A::AbstractMatrix, color::AbstractVector{<:Integer}; verbose::Bool=false + A::AbstractMatrix, + color::AbstractVector{<:Integer}; + verbose::Bool = false, ) checksquare(A) if !proper_length_coloring(A, color; verbose) @@ -110,7 +116,14 @@ function symmetrically_orthogonal_columns( iszero(A[i, j]) && continue ci, cj = color[i], color[j] check = _bilateral_check( - A; i, j, ci, cj, row_group=group, column_group=group, verbose + A; + i, + j, + ci, + cj, + row_group = group, + column_group = group, + verbose, ) !check && return false end @@ -139,7 +152,7 @@ function structurally_biorthogonal( A::AbstractMatrix, row_color::AbstractVector{<:Integer}, column_color::AbstractVector{<:Integer}; - verbose::Bool=false, + verbose::Bool = false, ) if !proper_length_bicoloring(A, row_color, column_color; verbose) return false @@ -242,7 +255,9 @@ Return `true` if coloring the columns of the symmetric matrix `A` with the vecto > [_What Color Is Your Jacobian? Graph Coloring for Computing Derivatives_](https://epubs.siam.org/doi/10.1137/S0036144504444711), Gebremedhin et al. (2005) """ function directly_recoverable_columns( - A::AbstractMatrix, color::AbstractVector{<:Integer}; verbose::Bool=false + A::AbstractMatrix, + color::AbstractVector{<:Integer}; + verbose::Bool = false, ) if !proper_length_coloring(A, color; verbose) return false @@ -251,8 +266,8 @@ function directly_recoverable_columns( B = if isempty(group) similar(A, size(A, 1), 0) else - stack(group; dims=2) do g - dropdims(sum(A[:, g]; dims=2); dims=2) + stack(group; dims = 2) do g + dropdims(sum(A[:, g]; dims = 2); dims = 2) end end A_unique = Set(unique(A)) @@ -296,7 +311,7 @@ function substitutable_columns( A::AbstractMatrix, rank_nonzeros::AbstractMatrix, color::AbstractVector{<:Integer}; - verbose::Bool=false, + verbose::Bool = false, ) checksquare(A) if !proper_length_coloring(A, color; verbose) @@ -308,7 +323,15 @@ function substitutable_columns( iszero(A[i, j]) && continue ci, cj = color[i], color[j] check = _substitutable_check( - A, rank_nonzeros; i, j, ci, cj, row_group=group, column_group=group, verbose + A, + rank_nonzeros; + i, + j, + ci, + cj, + row_group = group, + column_group = group, + verbose, ) !check && return false end @@ -339,7 +362,7 @@ function substitutable_bidirectional( rank_nonzeros::AbstractMatrix, row_color::AbstractVector{<:Integer}, column_color::AbstractVector{<:Integer}; - verbose::Bool=false, + verbose::Bool = false, ) if !proper_length_bicoloring(A, row_color, column_color; verbose) return false @@ -350,7 +373,15 @@ function substitutable_bidirectional( iszero(A[i, j]) && continue ci, cj = row_color[i], column_color[j] check = _substitutable_check( - A, rank_nonzeros; i, j, ci, cj, row_group, column_group, verbose + A, + rank_nonzeros; + i, + j, + ci, + cj, + row_group, + column_group, + verbose, ) !check && return false end @@ -456,7 +487,7 @@ function valid_dynamic_order( for i in eachindex(π) vi = π[i] yet_to_be_ordered = direction == :low2high ? π[i:end] : π[begin:i] - considered_for_degree = degtype == :back ? π[begin:(i - 1)] : π[(i + 1):end] + considered_for_degree = degtype == :back ? π[begin:(i-1)] : π[(i+1):end] di = degree_in_subset(g, vi, considered_for_degree) considered_for_degree_switched = copy(considered_for_degree) for vj in yet_to_be_ordered @@ -484,7 +515,7 @@ function valid_dynamic_order( for i in eachindex(π) vi = π[i] yet_to_be_ordered = direction == :low2high ? π[i:end] : π[begin:i] - considered_for_degree = degtype == :back ? π[begin:(i - 1)] : π[(i + 1):end] + considered_for_degree = degtype == :back ? π[begin:(i-1)] : π[(i+1):end] di = degree_dist2_in_subset(g, Val(side), vi, considered_for_degree) considered_for_degree_switched = copy(considered_for_degree) for vj in yet_to_be_ordered @@ -530,10 +561,10 @@ function rank_nonzeros_from_trees(result::TreeSetColoringResult) counter += 1 rank_nonzeros[i, i] = counter end - for k in 1:nt + for k = 1:nt first = tree_edge_indices[k] - last = tree_edge_indices[k + 1] - 1 - for pos in first:last + last = tree_edge_indices[k+1] - 1 + for pos = first:last (i, j) = reverse_bfs_orders[pos] counter += 1 rank_nonzeros[i, j] = counter @@ -552,21 +583,21 @@ function rank_nonzeros_from_trees(result::BicoloringResult) m, n = size(A) nnzA = nnz(S) ÷ 2 nzval = zeros(Int, nnzA) - colptr = large_colptr[1:(n + 1)] + colptr = large_colptr[1:(n+1)] rowval = large_rowval[1:nnzA] rowval .-= n rank_nonzeros = SparseMatrixCSC(m, n, colptr, rowval, nzval) counter = 0 - for k in 1:nt + for k = 1:nt first = tree_edge_indices[k] - last = tree_edge_indices[k + 1] - 1 - for pos in first:last + last = tree_edge_indices[k+1] - 1 + for pos = first:last (i, j) = reverse_bfs_orders[pos] counter += 1 if i > j - rank_nonzeros[i - n, j] = counter + rank_nonzeros[i-n, j] = counter else - rank_nonzeros[j - n, i] = counter + rank_nonzeros[j-n, i] = counter end end end diff --git a/src/coloring.jl b/src/coloring.jl index 699dbc64..d01dc804 100644 --- a/src/coloring.jl +++ b/src/coloring.jl @@ -27,12 +27,17 @@ function partial_distance2_coloring( bg::BipartiteGraph{T}, ::Val{side}, vertices_in_order::AbstractVector{<:Integer}; - forced_colors::Union{AbstractVector{<:Integer},Nothing}=nothing, + forced_colors::Union{AbstractVector{<:Integer},Nothing} = nothing, ) where {T,side} color = Vector{T}(undef, nb_vertices(bg, Val(side))) forbidden_colors = Vector{T}(undef, nb_vertices(bg, Val(side))) partial_distance2_coloring!( - color, forbidden_colors, bg, Val(side), vertices_in_order; forced_colors + color, + forbidden_colors, + bg, + Val(side), + vertices_in_order; + forced_colors, ) return color end @@ -43,7 +48,7 @@ function partial_distance2_coloring!( bg::BipartiteGraph, ::Val{side}, vertices_in_order::AbstractVector{<:Integer}; - forced_colors::Union{AbstractVector{<:Integer},Nothing}=nothing, + forced_colors::Union{AbstractVector{<:Integer},Nothing} = nothing, ) where {side} color .= 0 forbidden_colors .= 0 @@ -110,7 +115,7 @@ function star_coloring( g::AdjacencyGraph{T}, vertices_in_order::AbstractVector{<:Integer}, postprocessing::Bool; - forced_colors::Union{AbstractVector{<:Integer},Nothing}=nothing, + forced_colors::Union{AbstractVector{<:Integer},Nothing} = nothing, ) where {T<:Integer} # Initialize data structures nv = nb_vertices(g) @@ -273,7 +278,9 @@ If `postprocessing=true`, some colors might be replaced with `0` (the "neutral" > [_New Acyclic and Star Coloring Algorithms with Application to Computing Hessians_](https://epubs.siam.org/doi/abs/10.1137/050639879), Gebremedhin et al. (2007), Algorithm 3.1 """ function acyclic_coloring( - g::AdjacencyGraph{T}, vertices_in_order::AbstractVector{<:Integer}, postprocessing::Bool + g::AdjacencyGraph{T}, + vertices_in_order::AbstractVector{<:Integer}, + postprocessing::Bool, ) where {T<:Integer} # Initialize data structures nv = nb_vertices(g) @@ -462,7 +469,7 @@ function TreeSet( nr = 0 # determine the number of edges for each tree and map each root to a tree index - for index_edge in 1:ne + for index_edge = 1:ne root = find_root!(forest, index_edge) # create a mapping between roots and tree indices @@ -475,7 +482,7 @@ function TreeSet( index_tree = root_to_tree[root] # Update the number of edges for the current tree (shifted by 1 to facilitate the final cumsum) - tree_edge_indices[index_tree + 1] += 1 + tree_edge_indices[index_tree+1] += 1 end # nvmax is the number of vertices in the largest tree of the forest @@ -502,10 +509,10 @@ function TreeSet( vertex_position[1] = zero(T) neighbor_position[1] = zero(T) end - for k in 2:nt + for k = 2:nt # Note: tree_edge_indices[k] is the number of edges in the tree k-1 - vertex_position[k] = vertex_position[k - 1] + tree_edge_indices[k] + 1 - neighbor_position[k] = neighbor_position[k - 1] + 2 * tree_edge_indices[k] + vertex_position[k] = vertex_position[k-1] + tree_edge_indices[k] + 1 + neighbor_position[k] = neighbor_position[k-1] + 2 * tree_edge_indices[k] end # Record the most recent vertex from which each tree is visited @@ -543,21 +550,21 @@ function TreeSet( tree_neighbors[neighbor_index] = i # Increment neighbor count for j in the tree (shifted by 1 to facilitate the final cumsum) - tree_neighbor_indices[vertex_index + 1] += 1 + tree_neighbor_indices[vertex_index+1] += 1 end end end # Compute a shifted cumulative sum of tree_edge_indices, starting from one tree_edge_indices[1] = one(T) - for k in 2:(nt + 1) - tree_edge_indices[k] += tree_edge_indices[k - 1] + for k = 2:(nt+1) + tree_edge_indices[k] += tree_edge_indices[k-1] end # Compute a shifted cumulative sum of tree_neighbor_indices, starting from one tree_neighbor_indices[1] = 1 - for k in 2:(ne + nt + 1) - tree_neighbor_indices[k] += tree_neighbor_indices[k - 1] + for k = 2:(ne+nt+1) + tree_neighbor_indices[k] += tree_neighbor_indices[k-1] end # degrees is a vector of integers that stores the degree of each vertex in a tree @@ -585,7 +592,7 @@ function TreeSet( # edges. We then look at all leaves of the corresponding graphs and repeat # the process until there is only one vertex left. This vertex will then be # a depth-minimizing root. - for k in 1:nt + for k = 1:nt # Initialize the queue to store the leaves queue_start = 1 queue_end = 0 @@ -594,14 +601,13 @@ function TreeSet( # Note: tree_edge_indices contains the positions of the first and last edges, # so we add to add an offset k-1 between edge indices and vertex indices first_vertex = tree_edge_indices[k] + (k - 1) - last_vertex = tree_edge_indices[k + 1] + (k - 1) + last_vertex = tree_edge_indices[k+1] + (k - 1) # compute the degree of each vertex in the tree - for index_vertex in first_vertex:last_vertex + for index_vertex = first_vertex:last_vertex vertex = tree_vertices[index_vertex] degree = - tree_neighbor_indices[index_vertex + 1] - - tree_neighbor_indices[index_vertex] + tree_neighbor_indices[index_vertex+1] - tree_neighbor_indices[index_vertex] degrees[vertex] = degree # store a reverse mapping to get the position of the vertex in tree_vertices @@ -615,7 +621,7 @@ function TreeSet( end # number of vertices in the tree - nv_tree = tree_edge_indices[k + 1] - tree_edge_indices[k] + 1 + nv_tree = tree_edge_indices[k+1] - tree_edge_indices[k] + 1 # Check that no more than one vertex has a degree strictly greater than one # "queue_end" currently represents the number of vertices considered as leaves in the tree before any pruning @@ -634,10 +640,10 @@ function TreeSet( # Positions of the first and last neighbors of the leaf in the current tree first_neighbor = tree_neighbor_indices[index_leaf] - last_neighbor = tree_neighbor_indices[index_leaf + 1] - 1 + last_neighbor = tree_neighbor_indices[index_leaf+1] - 1 # Iterate over all neighbors of the leaf to be pruned - for index_neighbor in first_neighbor:last_neighbor + for index_neighbor = first_neighbor:last_neighbor neighbor = tree_neighbors[index_neighbor] # Check if neighbor is the parent of the leaf or if it was a child before the tree was pruned diff --git a/src/constant.jl b/src/constant.jl index 56bf4101..c2f7ad75 100644 --- a/src/constant.jl +++ b/src/constant.jl @@ -75,17 +75,20 @@ struct ConstantColoringAlgorithm{partition,structure,M<:AbstractMatrix,T<:Intege color::Vector{T} function ConstantColoringAlgorithm{partition,structure}( - matrix_template::AbstractMatrix, color::Vector{<:Integer} + matrix_template::AbstractMatrix, + color::Vector{<:Integer}, ) where {partition,structure} check_valid_problem(structure, partition) return new{partition,structure,typeof(matrix_template),eltype(color)}( - matrix_template, color + matrix_template, + color, ) end end function ConstantColoringAlgorithm{partition}( - matrix_template::AbstractMatrix, color::Vector{<:Integer} + matrix_template::AbstractMatrix, + color::Vector{<:Integer}, ) where {partition} return ConstantColoringAlgorithm{partition,:nonsymmetric}(matrix_template, color) end @@ -93,8 +96,8 @@ end function ConstantColoringAlgorithm( matrix_template::AbstractMatrix, color::Vector{<:Integer}; - structure::Symbol=:nonsymmetric, - partition::Symbol=:column, + structure::Symbol = :nonsymmetric, + partition::Symbol = :column, ) return ConstantColoringAlgorithm{partition,structure}(matrix_template, color) end @@ -111,21 +114,24 @@ function check_template(algo::ConstantColoringAlgorithm, A::AbstractMatrix) end function ADTypes.column_coloring( - A::AbstractMatrix, algo::ConstantColoringAlgorithm{:column,:nonsymmetric} + A::AbstractMatrix, + algo::ConstantColoringAlgorithm{:column,:nonsymmetric}, ) check_template(algo, A) return algo.color end function ADTypes.row_coloring( - A::AbstractMatrix, algo::ConstantColoringAlgorithm{:row,:nonsymmetric} + A::AbstractMatrix, + algo::ConstantColoringAlgorithm{:row,:nonsymmetric}, ) check_template(algo, A) return algo.color end function ADTypes.symmetric_coloring( - A::AbstractMatrix, algo::ConstantColoringAlgorithm{:column,:symmetric} + A::AbstractMatrix, + algo::ConstantColoringAlgorithm{:column,:symmetric}, ) check_template(algo, A) return algo.color diff --git a/src/decompression.jl b/src/decompression.jl index 849f0f6b..ad796c13 100644 --- a/src/decompression.jl +++ b/src/decompression.jl @@ -48,13 +48,13 @@ function compress(A, result::AbstractColoringResult{structure,:column}) where {s group = column_groups(result) if isempty(group) # ensure we get a Matrix and not a SparseMatrixCSC - B_model = stack([Int[]]; dims=2) do g - dropdims(sum(A[:, g]; dims=2); dims=2) + B_model = stack([Int[]]; dims = 2) do g + dropdims(sum(A[:, g]; dims = 2); dims = 2) end B = similar(B_model, size(A, 1), 0) else - B = stack(group; dims=2) do g - dropdims(sum(A[:, g]; dims=2); dims=2) + B = stack(group; dims = 2) do g + dropdims(sum(A[:, g]; dims = 2); dims = 2) end end return B @@ -64,43 +64,44 @@ function compress(A, result::AbstractColoringResult{structure,:row}) where {stru group = row_groups(result) if isempty(group) # ensure we get a Matrix and not a SparseMatrixCSC - B_model = stack([Int[]]; dims=1) do g - dropdims(sum(A[g, :]; dims=1); dims=1) + B_model = stack([Int[]]; dims = 1) do g + dropdims(sum(A[g, :]; dims = 1); dims = 1) end B = similar(B_model, 0, size(A, 2)) else - B = stack(group; dims=1) do g - dropdims(sum(A[g, :]; dims=1); dims=1) + B = stack(group; dims = 1) do g + dropdims(sum(A[g, :]; dims = 1); dims = 1) end end return B end function compress( - A, result::AbstractColoringResult{structure,:bidirectional} + A, + result::AbstractColoringResult{structure,:bidirectional}, ) where {structure} row_group = row_groups(result) column_group = column_groups(result) if isempty(row_group) # ensure we get a Matrix and not a SparseMatrixCSC - Br_model = stack([Int[]]; dims=1) do g - dropdims(sum(A[g, :]; dims=1); dims=1) + Br_model = stack([Int[]]; dims = 1) do g + dropdims(sum(A[g, :]; dims = 1); dims = 1) end Br = similar(Br_model, 0, size(A, 2)) else - Br = stack(row_group; dims=1) do g - dropdims(sum(A[g, :]; dims=1); dims=1) + Br = stack(row_group; dims = 1) do g + dropdims(sum(A[g, :]; dims = 1); dims = 1) end end if isempty(column_group) # ensure we get a Matrix and not a SparseMatrixCSC - Bc_model = stack([Int[]]; dims=2) do g - dropdims(sum(A[:, g]; dims=2); dims=2) + Bc_model = stack([Int[]]; dims = 2) do g + dropdims(sum(A[:, g]; dims = 2); dims = 2) end Bc = similar(Bc_model, size(A, 1), 0) else - Bc = stack(column_group; dims=2) do g - dropdims(sum(A[:, g]; dims=2); dims=2) + Bc = stack(column_group; dims = 2) do g + dropdims(sum(A[:, g]; dims = 2); dims = 2) end end return Br, Bc @@ -355,7 +356,10 @@ function decompress!(A::AbstractMatrix, B::AbstractMatrix, result::ColumnColorin end function decompress_single_color!( - A::AbstractMatrix, b::AbstractVector, c::Integer, result::ColumnColoringResult + A::AbstractMatrix, + b::AbstractVector, + c::Integer, + result::ColumnColoringResult, ) (; bg, group) = result S = bg.S2 @@ -382,7 +386,10 @@ function decompress!(A::SparseMatrixCSC, B::AbstractMatrix, result::ColumnColori end function decompress_single_color!( - A::SparseMatrixCSC, b::AbstractVector, c::Integer, result::ColumnColoringResult + A::SparseMatrixCSC, + b::AbstractVector, + c::Integer, + result::ColumnColoringResult, ) (; bg, group) = result S = bg.S2 @@ -417,7 +424,10 @@ function decompress!(A::AbstractMatrix, B::AbstractMatrix, result::RowColoringRe end function decompress_single_color!( - A::AbstractMatrix, b::AbstractVector, c::Integer, result::RowColoringResult + A::AbstractMatrix, + b::AbstractVector, + c::Integer, + result::RowColoringResult, ) (; bg, group) = result S, Sᵀ = bg.S2, bg.S1 @@ -446,7 +456,10 @@ end ## StarSetColoringResult function decompress!( - A::AbstractMatrix, B::AbstractMatrix, result::StarSetColoringResult, uplo::Symbol=:F + A::AbstractMatrix, + B::AbstractMatrix, + result::StarSetColoringResult, + uplo::Symbol = :F, ) (; ag, compressed_indices) = result (; S) = ag @@ -470,7 +483,7 @@ function decompress_single_color!( b::AbstractVector, c::Integer, result::StarSetColoringResult, - uplo::Symbol=:F, + uplo::Symbol = :F, ) (; ag, compressed_indices, group) = result (; S) = ag @@ -503,7 +516,10 @@ function decompress_single_color!( end function decompress!( - A::SparseMatrixCSC, B::AbstractMatrix, result::StarSetColoringResult, uplo::Symbol=:F + A::SparseMatrixCSC, + B::AbstractMatrix, + result::StarSetColoringResult, + uplo::Symbol = :F, ) (; ag, compressed_indices) = result (; S) = ag @@ -532,7 +548,10 @@ end ## TreeSetColoringResult function decompress!( - A::AbstractMatrix, B::AbstractMatrix, result::TreeSetColoringResult, uplo::Symbol=:F + A::AbstractMatrix, + B::AbstractMatrix, + result::TreeSetColoringResult, + uplo::Symbol = :F, ) (; ag, color, reverse_bfs_orders, tree_edge_indices, nt, diagonal_indices, buffer) = result @@ -555,13 +574,13 @@ function decompress!( end # Recover the off-diagonal coefficients of A - for k in 1:nt + for k = 1:nt # Positions of the first and last edges of the tree first = tree_edge_indices[k] - last = tree_edge_indices[k + 1] - 1 + last = tree_edge_indices[k+1] - 1 # Reset the buffer to zero for all vertices in the tree (except the root) - for pos in first:last + for pos = first:last (vertex, _) = reverse_bfs_orders[pos] buffer_right_type[vertex] = zero(R) end @@ -569,7 +588,7 @@ function decompress!( (_, root) = reverse_bfs_orders[last] buffer_right_type[root] = zero(R) - for pos in first:last + for pos = first:last (i, j) = reverse_bfs_orders[pos] val = B[i, color[j]] - buffer_right_type[i] buffer_right_type[j] = buffer_right_type[j] + val @@ -604,7 +623,7 @@ function decompress_csc!( A_colptr::AbstractVector{<:Integer}, B::AbstractMatrix{R}, result::TreeSetColoringResult, - uplo::Symbol=:F, + uplo::Symbol = :F, ) where {R<:Real} (; ag, @@ -636,7 +655,7 @@ function decompress_csc!( elseif uplo == :U for i in diagonal_indices # A[i, i] is the last element in column i - nzind = A_colptr[i + 1] - 1 + nzind = A_colptr[i+1] - 1 nzA[nzind] = B[i, color[i]] end else # uplo == :F @@ -651,13 +670,13 @@ function decompress_csc!( counter = 0 # Recover the off-diagonal coefficients of A - for k in 1:nt + for k = 1:nt # Positions of the first and last edges of the tree first = tree_edge_indices[k] - last = tree_edge_indices[k + 1] - 1 + last = tree_edge_indices[k+1] - 1 # Reset the buffer to zero for all vertices in the tree (except the root) - for pos in first:last + for pos = first:last (vertex, _) = reverse_bfs_orders[pos] buffer_right_type[vertex] = zero(R) end @@ -665,7 +684,7 @@ function decompress_csc!( (_, root) = reverse_bfs_orders[last] buffer_right_type[root] = zero(R) - for pos in first:last + for pos = first:last (i, j) = reverse_bfs_orders[pos] counter += 1 val = B[i, color[j]] - buffer_right_type[i] @@ -714,7 +733,7 @@ function decompress!( A::SparseMatrixCSC{R}, B::AbstractMatrix{R}, result::TreeSetColoringResult, - uplo::Symbol=:F, + uplo::Symbol = :F, ) where {R<:Real} check_compatible_pattern(A, result.ag, uplo) decompress_csc!(nonzeros(A), A.colptr, B, result, uplo) @@ -727,7 +746,7 @@ function decompress!( A::AbstractMatrix, B::AbstractMatrix, result::LinearSystemColoringResult, - uplo::Symbol=:F, + uplo::Symbol = :F, ) (; ag, color, strict_upper_nonzero_inds, M_factorization, strict_upper_nonzeros_A) = result @@ -781,16 +800,17 @@ function _join_compressed!(result::BicoloringResult, Br::AbstractMatrix, Bc::Abs copyto!(view(Br_and_Bc, 1:n, c), view(Br, symmetric_to_row[c], :)) end if symmetric_to_column[c] > 0 # some columns were colored with the symmetric color c - copyto!( - view(Br_and_Bc, (n + 1):(n + m), c), view(Bc, :, symmetric_to_column[c]) - ) + copyto!(view(Br_and_Bc, (n+1):(n+m), c), view(Bc, :, symmetric_to_column[c])) end end return Br_and_Bc end function decompress!( - A::AbstractMatrix, Br::AbstractMatrix, Bc::AbstractMatrix, result::BicoloringResult + A::AbstractMatrix, + Br::AbstractMatrix, + Bc::AbstractMatrix, + result::BicoloringResult, ) (; large_colptr, large_rowval, symmetric_result) = result m, n = size(A) @@ -802,17 +822,20 @@ function decompress!( decompress!(A_and_noAᵀ, Br_and_Bc, symmetric_result, :L) rvA = rowvals(A_and_noAᵀ) nzA = nonzeros(A_and_noAᵀ) - for j in 1:n + for j = 1:n for k in nzrange(A_and_noAᵀ, j) i = rvA[k] - A[i - n, j] = nzA[k] + A[i-n, j] = nzA[k] end end return A end function decompress!( - A::SparseMatrixCSC, Br::AbstractMatrix, Bc::AbstractMatrix, result::BicoloringResult + A::SparseMatrixCSC, + Br::AbstractMatrix, + Bc::AbstractMatrix, + result::BicoloringResult, ) (; large_colptr, large_rowval, symmetric_result) = result m, n = size(A) diff --git a/src/forest.jl b/src/forest.jl index ec7e505e..4db4a72d 100644 --- a/src/forest.jl +++ b/src/forest.jl @@ -38,7 +38,9 @@ function find_root!(forest::Forest{<:Integer}, index_edge::Integer) end function root_union!( - forest::Forest{T}, index_edge1::Integer, index_edge2::Integer + forest::Forest{T}, + index_edge1::Integer, + index_edge2::Integer, ) where {T<:Integer} parents = forest.parents rks = forest.ranks diff --git a/src/graph.jl b/src/graph.jl index 94954602..c408bb42 100644 --- a/src/graph.jl +++ b/src/graph.jl @@ -30,7 +30,7 @@ Base.axes(S::SparsityPatternCSC, d::Integer) = Base.OneTo(size(S, d)) SparseArrays.nnz(S::SparsityPatternCSC) = length(S.rowval) SparseArrays.rowvals(S::SparsityPatternCSC) = S.rowval -SparseArrays.nzrange(S::SparsityPatternCSC, j::Integer) = S.colptr[j]:(S.colptr[j + 1] - 1) +SparseArrays.nzrange(S::SparsityPatternCSC, j::Integer) = S.colptr[j]:(S.colptr[j+1]-1) # Needed if using `coloring(::SparsityPatternCSC, ...)` function Base.similar(A::SparsityPatternCSC, ::Type{T}) where {T} @@ -54,23 +54,23 @@ function Base.transpose(S::SparsityPatternCSC{T}) where {T} # Count the number of non-zeros for each row of A. # It corresponds to the number of non-zeros for each column of B = Aᵀ. - for k in 1:nnzA + for k = 1:nnzA i = A_rowval[k] B_colptr[i] += 1 end # Compute the cumulative sum to determine the starting positions of rows in B_rowval counter = 1 - for col in 1:m + for col = 1:m nnz_col = B_colptr[col] B_colptr[col] = counter counter += nnz_col end - B_colptr[m + 1] = counter + B_colptr[m+1] = counter # Store the row indices for each column of B = Aᵀ - for j in 1:n - for index in A_colptr[j]:(A_colptr[j + 1] - 1) + for j = 1:n + for index = A_colptr[j]:(A_colptr[j+1]-1) i = A_rowval[index] # Update B_rowval for the non-zero B[j,i]. @@ -82,8 +82,8 @@ function Base.transpose(S::SparsityPatternCSC{T}) where {T} end # Fix offsets of B_colptr to restore correct starting positions - for col in m:-1:2 - B_colptr[col] = B_colptr[col - 1] + for col = m:-1:2 + B_colptr[col] = B_colptr[col-1] end B_colptr[1] = 1 @@ -93,7 +93,7 @@ end # copied from SparseArrays.jl function Base.getindex(S::SparsityPatternCSC, i0::Integer, i1::Integer) r1 = Int(S.colptr[i1]) - r2 = Int(S.colptr[i1 + 1] - 1) + r2 = Int(S.colptr[i1+1] - 1) (r1 > r2) && return false r1 = searchsortedfirst(rowvals(S), i0, r1, r2, Base.Order.Forward) return ((r1 > r2) || (rowvals(S)[r1] != i0)) ? false : true @@ -117,11 +117,11 @@ function bidirectional_pattern(S::SparsityPatternCSC{T}; symmetric_pattern::Bool edge_to_index = Vector{T}(undef, 2 * nnzS) # Update rowval and colptr for the block A - for i in 1:nnzS + for i = 1:nnzS rowval[i] = S.rowval[i] + n edge_to_index[i] = i end - for j in 1:n + for j = 1:n colptr[j] = S.colptr[j] end @@ -131,48 +131,48 @@ function bidirectional_pattern(S::SparsityPatternCSC{T}; symmetric_pattern::Bool offsets = colptr # We use the sparsity pattern of A for Aᵀ - for k in 1:nnzS + for k = 1:nnzS r = S.rowval[k] - rowval[nnzS + k] = r - pos = S.colptr[r] + offsets[n + r] - edge_to_index[nnzS + pos] = edge_to_index[k] - offsets[n + r] += 1 + rowval[nnzS+k] = r + pos = S.colptr[r] + offsets[n+r] + edge_to_index[nnzS+pos] = edge_to_index[k] + offsets[n+r] += 1 end # m and n are identical because symmetric_pattern is true - for j in 1:m - colptr[n + j] = nnzS + S.colptr[j] + for j = 1:m + colptr[n+j] = nnzS + S.colptr[j] end - colptr[p + 1] = 2 * nnzS + 1 + colptr[p+1] = 2 * nnzS + 1 else # We need to determine the sparsity pattern of Aᵀ # We adapt the code of transpose(SparsityPatternCSC) in graph.jl - for k in 1:nnzS + for k = 1:nnzS i = S.rowval[k] - colptr[n + i] += 1 + colptr[n+i] += 1 end counter = 1 - for col in (n + 1):p + for col = (n+1):p nnz_col = colptr[col] colptr[col] = nnzS + counter counter += nnz_col end - for j in 1:n - for index in S.colptr[j]:(S.colptr[j + 1] - 1) + for j = 1:n + for index = S.colptr[j]:(S.colptr[j+1]-1) i = S.rowval[index] - pos = colptr[n + i] + pos = colptr[n+i] rowval[pos] = j edge_to_index[pos] = edge_to_index[index] - colptr[n + i] += 1 + colptr[n+i] += 1 end end - colptr[p + 1] = nnzS + counter - for col in p:-1:(n + 2) - colptr[col] = colptr[col - 1] + colptr[p+1] = nnzS + counter + for col = p:-1:(n+2) + colptr[col] = colptr[col-1] end - colptr[n + 1] = nnzS + 1 + colptr[n+1] = nnzS + 1 end # Create the SparsityPatternCSC of the augmented adjacency matrix @@ -243,21 +243,21 @@ function AdjacencyGraph( S::SparsityPatternCSC{T}, edge_to_index::Vector{T}, nb_self_loops::Int; - augmented_graph::Bool=false, + augmented_graph::Bool = false, ) where {T} return AdjacencyGraph{T,augmented_graph}(S, edge_to_index, nb_self_loops) end -function AdjacencyGraph(S::SparsityPatternCSC; augmented_graph::Bool=false) +function AdjacencyGraph(S::SparsityPatternCSC; augmented_graph::Bool = false) edge_to_index, nb_self_loops = build_edge_to_index(S) return AdjacencyGraph(S, edge_to_index, nb_self_loops; augmented_graph) end -function AdjacencyGraph(A::SparseMatrixCSC; augmented_graph::Bool=false) +function AdjacencyGraph(A::SparseMatrixCSC; augmented_graph::Bool = false) return AdjacencyGraph(SparsityPatternCSC(A); augmented_graph) end -function AdjacencyGraph(A::AbstractMatrix; augmented_graph::Bool=false) +function AdjacencyGraph(A::AbstractMatrix; augmented_graph::Bool = false) return AdjacencyGraph(SparseMatrixCSC(A); augmented_graph) end @@ -281,12 +281,12 @@ function neighbors_with_edge_indices(g::AdjacencyGraph, v::Integer) return zip(neighbors_v, edges_indices_v) end -degree(g::AdjacencyGraph{T,true}, v::Integer) where {T} = g.S.colptr[v + 1] - g.S.colptr[v] +degree(g::AdjacencyGraph{T,true}, v::Integer) where {T} = g.S.colptr[v+1] - g.S.colptr[v] function degree(g::AdjacencyGraph{T,false}, v::Integer) where {T} neigh = neighbors(g, v) has_selfloop = insorted(v, neigh) - return g.S.colptr[v + 1] - g.S.colptr[v] - has_selfloop + return g.S.colptr[v+1] - g.S.colptr[v] - has_selfloop end nb_edges(g::AdjacencyGraph) = (nnz(g.S) - g.nb_self_loops) ÷ 2 @@ -351,11 +351,11 @@ end Base.eltype(::BipartiteGraph{T}) where {T} = T -function BipartiteGraph(A::AbstractMatrix; symmetric_pattern::Bool=false) +function BipartiteGraph(A::AbstractMatrix; symmetric_pattern::Bool = false) return BipartiteGraph(SparseMatrixCSC(A); symmetric_pattern) end -function BipartiteGraph(A::SparseMatrixCSC; symmetric_pattern::Bool=false) +function BipartiteGraph(A::SparseMatrixCSC; symmetric_pattern::Bool = false) S2 = SparsityPatternCSC(A) # columns to rows if symmetric_pattern checksquare(A) # proxy for checking full symmetry @@ -419,7 +419,10 @@ function degree_dist2(bg::BipartiteGraph{T}, ::Val{side}, v::Integer) where {T,s end function has_neighbor_dist2( - bg::BipartiteGraph, ::Val{side}, v::Integer, u::Integer + bg::BipartiteGraph, + ::Val{side}, + v::Integer, + u::Integer, ) where {side} other_side = 3 - side for w1 in neighbors(bg, Val(side), v) @@ -433,7 +436,10 @@ function has_neighbor_dist2( end function degree_dist2_in_subset( - bg::BipartiteGraph, ::Val{side}, v::Integer, subset::AbstractVector{<:Integer} + bg::BipartiteGraph, + ::Val{side}, + v::Integer, + subset::AbstractVector{<:Integer}, ) where {side} d = 0 for u in subset diff --git a/src/interface.jl b/src/interface.jl index 0d183c9c..d4de1b58 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -55,7 +55,7 @@ Matrix coloring is often used in automatic differentiation, and here is the tran """ struct ColoringProblem{structure,partition} end -function ColoringProblem(; structure::Symbol=:nonsymmetric, partition::Symbol=:column) +function ColoringProblem(; structure::Symbol = :nonsymmetric, partition::Symbol = :column) check_valid_problem(structure, partition) return ColoringProblem{structure,partition}() end @@ -100,8 +100,8 @@ struct GreedyColoringAlgorithm{decompression,N,O<:NTuple{N,AbstractOrder}} <: postprocessing::Bool function GreedyColoringAlgorithm{decompression}( - order_or_orders::Union{AbstractOrder,Tuple}=NaturalOrder(); - postprocessing::Bool=false, + order_or_orders::Union{AbstractOrder,Tuple} = NaturalOrder(); + postprocessing::Bool = false, ) where {decompression} check_valid_algorithm(decompression) if order_or_orders isa AbstractOrder @@ -114,9 +114,9 @@ struct GreedyColoringAlgorithm{decompression,N,O<:NTuple{N,AbstractOrder}} <: end function GreedyColoringAlgorithm( - order_or_orders::Union{AbstractOrder,Tuple}=NaturalOrder(); - postprocessing::Bool=false, - decompression::Symbol=:direct, + order_or_orders::Union{AbstractOrder,Tuple} = NaturalOrder(); + postprocessing::Bool = false, + decompression::Symbol = :direct, ) return GreedyColoringAlgorithm{decompression}(order_or_orders; postprocessing) end @@ -190,8 +190,8 @@ function coloring( A::AbstractMatrix, problem::ColoringProblem, algo::GreedyColoringAlgorithm; - decompression_eltype::Type{R}=Float64, - symmetric_pattern::Bool=false, + decompression_eltype::Type{R} = Float64, + symmetric_pattern::Bool = false, ) where {R} return _coloring(WithResult(), A, problem, algo, R, symmetric_pattern) end @@ -219,7 +219,7 @@ function fast_coloring( A::AbstractMatrix, problem::ColoringProblem, algo::GreedyColoringAlgorithm; - symmetric_pattern::Bool=false, + symmetric_pattern::Bool = false, ) return _coloring(WithoutResult(), A, problem, algo, Float64, symmetric_pattern) end @@ -231,7 +231,7 @@ function _coloring( algo::GreedyColoringAlgorithm, decompression_eltype::Type, symmetric_pattern::Bool; - forced_colors::Union{AbstractVector{<:Integer},Nothing}=nothing, + forced_colors::Union{AbstractVector{<:Integer},Nothing} = nothing, ) symmetric_pattern = symmetric_pattern || A isa Union{Symmetric,Hermitian} bg = BipartiteGraph(A; symmetric_pattern) @@ -254,7 +254,7 @@ function _coloring( algo::GreedyColoringAlgorithm, decompression_eltype::Type, symmetric_pattern::Bool; - forced_colors::Union{AbstractVector{<:Integer},Nothing}=nothing, + forced_colors::Union{AbstractVector{<:Integer},Nothing} = nothing, ) symmetric_pattern = symmetric_pattern || A isa Union{Symmetric,Hermitian} bg = BipartiteGraph(A; symmetric_pattern) @@ -277,9 +277,9 @@ function _coloring( algo::GreedyColoringAlgorithm{:direct}, decompression_eltype::Type, symmetric_pattern::Bool; - forced_colors::Union{AbstractVector{<:Integer},Nothing}=nothing, + forced_colors::Union{AbstractVector{<:Integer},Nothing} = nothing, ) - ag = AdjacencyGraph(A; augmented_graph=false) + ag = AdjacencyGraph(A; augmented_graph = false) color_and_star_set_by_order = map(algo.orders) do order vertices_in_order = vertices(ag, order) return star_coloring(ag, vertices_in_order, algo.postprocessing; forced_colors) @@ -300,7 +300,7 @@ function _coloring( decompression_eltype::Type{R}, symmetric_pattern::Bool, ) where {R} - ag = AdjacencyGraph(A; augmented_graph=false) + ag = AdjacencyGraph(A; augmented_graph = false) color_and_tree_set_by_order = map(algo.orders) do order vertices_in_order = vertices(ag, order) return acyclic_coloring(ag, vertices_in_order, algo.postprocessing) @@ -326,18 +326,16 @@ function _coloring( algo::GreedyColoringAlgorithm{:direct}, decompression_eltype::Type{R}, symmetric_pattern::Bool; - forced_colors::Union{AbstractVector{<:Integer},Nothing}=nothing, + forced_colors::Union{AbstractVector{<:Integer},Nothing} = nothing, ) where {R} A_and_Aᵀ, edge_to_index = bidirectional_pattern(A; symmetric_pattern) - ag = AdjacencyGraph(A_and_Aᵀ, edge_to_index, 0; augmented_graph=true) + ag = AdjacencyGraph(A_and_Aᵀ, edge_to_index, 0; augmented_graph = true) outputs_by_order = map(algo.orders) do order vertices_in_order = vertices(ag, order) - _color, _star_set = star_coloring( - ag, vertices_in_order, algo.postprocessing; forced_colors - ) - (_row_color, _column_color, _symmetric_to_row, _symmetric_to_column) = remap_colors( - eltype(ag), _color, maximum(_color), size(A)... - ) + _color, _star_set = + star_coloring(ag, vertices_in_order, algo.postprocessing; forced_colors) + (_row_color, _column_color, _symmetric_to_row, _symmetric_to_column) = + remap_colors(eltype(ag), _color, maximum(_color), size(A)...) return ( _color, _star_set, @@ -347,9 +345,8 @@ function _coloring( _symmetric_to_column, ) end - (color, star_set, row_color, column_color, symmetric_to_row, symmetric_to_column) = argmin( - t -> maximum(t[3]) + maximum(t[4]), outputs_by_order - ) # can't use ncolors without computing the full result + (color, star_set, row_color, column_color, symmetric_to_row, symmetric_to_column) = + argmin(t -> maximum(t[3]) + maximum(t[4]), outputs_by_order) # can't use ncolors without computing the full result if speed_setting isa WithResult symmetric_result = StarSetColoringResult(A_and_Aᵀ, ag, color, star_set) return BicoloringResult( @@ -376,13 +373,12 @@ function _coloring( symmetric_pattern::Bool, ) where {R} A_and_Aᵀ, edge_to_index = bidirectional_pattern(A; symmetric_pattern) - ag = AdjacencyGraph(A_and_Aᵀ, edge_to_index, 0; augmented_graph=true) + ag = AdjacencyGraph(A_and_Aᵀ, edge_to_index, 0; augmented_graph = true) outputs_by_order = map(algo.orders) do order vertices_in_order = vertices(ag, order) _color, _tree_set = acyclic_coloring(ag, vertices_in_order, algo.postprocessing) - (_row_color, _column_color, _symmetric_to_row, _symmetric_to_column) = remap_colors( - eltype(ag), _color, maximum(_color), size(A)... - ) + (_row_color, _column_color, _symmetric_to_row, _symmetric_to_column) = + remap_colors(eltype(ag), _color, maximum(_color), size(A)...) return ( _color, _tree_set, @@ -392,9 +388,8 @@ function _coloring( _symmetric_to_column, ) end - (color, tree_set, row_color, column_color, symmetric_to_row, symmetric_to_column) = argmin( - t -> maximum(t[3]) + maximum(t[4]), outputs_by_order - ) # can't use ncolors without computing the full result + (color, tree_set, row_color, column_color, symmetric_to_row, symmetric_to_column) = + argmin(t -> maximum(t[3]) + maximum(t[4]), outputs_by_order) # can't use ncolors without computing the full result if speed_setting isa WithResult symmetric_result = TreeSetColoringResult(A_and_Aᵀ, ag, color, tree_set, R) return BicoloringResult( diff --git a/src/matrices.jl b/src/matrices.jl index 453e3062..3dc670a2 100644 --- a/src/matrices.jl +++ b/src/matrices.jl @@ -22,12 +22,10 @@ function matrix_versions(A::AbstractMatrix) adjoint(sparse(adjoint(A_sparse))), ] if issymmetric(A) - lower_triangles = [ - Matrix(LowerTriangular(A_dense)), sparse(LowerTriangular(A_sparse)) - ] - upper_triangles = [ - Matrix(UpperTriangular(A_dense)), sparse(UpperTriangular(A_sparse)) - ] + lower_triangles = + [Matrix(LowerTriangular(A_dense)), sparse(LowerTriangular(A_sparse))] + upper_triangles = + [Matrix(UpperTriangular(A_dense)), sparse(UpperTriangular(A_sparse))] symmetric_versions = vcat( Symmetric.(versions), Hermitian.(versions), @@ -102,13 +100,13 @@ function check_compatible_pattern(A::AbstractMatrix, ag::AdjacencyGraph, uplo::S if uplo == :L throw( DimensionMismatch( - "`A` and `tril(ag.S)` must have the same sparsity pattern." + "`A` and `tril(ag.S)` must have the same sparsity pattern.", ), ) elseif uplo == :U throw( DimensionMismatch( - "`A` and `triu(ag.S)` must have the same sparsity pattern." + "`A` and `triu(ag.S)` must have the same sparsity pattern.", ), ) else # uplo == :F diff --git a/src/optimal.jl b/src/optimal.jl index 2a70a59d..19a71b11 100644 --- a/src/optimal.jl +++ b/src/optimal.jl @@ -29,6 +29,10 @@ struct OptimalColoringAlgorithm{O} <: ADTypes.AbstractColoringAlgorithm assert_solved::Bool end -function OptimalColoringAlgorithm(optimizer; silent::Bool=true, assert_solved::Bool=true) +function OptimalColoringAlgorithm( + optimizer; + silent::Bool = true, + assert_solved::Bool = true, +) return OptimalColoringAlgorithm(optimizer, silent, assert_solved) end diff --git a/src/order.jl b/src/order.jl index 20884c6a..f5e26d2c 100644 --- a/src/order.jl +++ b/src/order.jl @@ -82,7 +82,7 @@ struct LargestFirst <: AbstractOrder end function vertices(g::AdjacencyGraph, ::LargestFirst) degrees = map(Base.Fix1(degree, g), vertices(g)) criterion(v) = degrees[v] - return sort(vertices(g); by=criterion, rev=true) + return sort(vertices(g); by = criterion, rev = true) end function vertices(bg::BipartiteGraph{T}, ::Val{side}, ::LargestFirst) where {T,side} @@ -103,7 +103,7 @@ function vertices(bg::BipartiteGraph{T}, ::Val{side}, ::LargestFirst) where {T,s # Recycle the vector visited to store the ordering visited .= 1:n criterion(v) = degrees_dist2[v] - return sort!(visited; by=criterion, rev=true) + return sort!(visited; by = criterion, rev = true) end """ @@ -140,7 +140,7 @@ As a result, the default setting `reproduce_colpack=false` is slightly more memo struct DynamicDegreeBasedOrder{degtype,direction,reproduce_colpack} <: AbstractOrder end function DynamicDegreeBasedOrder{degtype,direction}(; - reproduce_colpack::Bool=false + reproduce_colpack::Bool = false, ) where {degtype,direction} return DynamicDegreeBasedOrder{degtype,direction,reproduce_colpack}() end @@ -165,17 +165,17 @@ function DegreeBucketsColPack(::Type{T}, degrees::Vector{T}, dmax::Integer) wher # number of vertices per degree class deg_count = zeros(T, dmax + 1) for d in degrees - deg_count[d + 1] += 1 + deg_count[d+1] += 1 end # one vector per bucket - buckets = [Vector{T}(undef, deg_count[d + 1]) for d in 0:dmax] + buckets = [Vector{T}(undef, deg_count[d+1]) for d = 0:dmax] positions = similar(degrees, T) # assign each vertex to the correct local position inside its bucket for v in eachindex(positions, degrees) d = degrees[v] - positions[v] = length(buckets[d + 1]) - deg_count[d + 1] + 1 - buckets[d + 1][positions[v]] = v - deg_count[d + 1] -= 1 + positions[v] = length(buckets[d+1]) - deg_count[d+1] + 1 + buckets[d+1][positions[v]] = v + deg_count[d+1] -= 1 end return DegreeBucketsColPack(degrees, buckets, positions) end @@ -184,30 +184,30 @@ function DegreeBucketsSMC(::Type{T}, degrees::Vector{T}, dmax::Integer) where {T # number of vertices per degree class deg_count = zeros(T, dmax + 1) for d in degrees - deg_count[d + 1] += 1 + deg_count[d+1] += 1 end # bucket limits bucket_high = accumulate(+, deg_count) bucket_low = similar(bucket_high) bucket_low[1] = 1 - bucket_low[2:end] .= @view(bucket_high[1:(end - 1)]) .+ 1 + bucket_low[2:end] .= @view(bucket_high[1:(end-1)]) .+ 1 # assign each vertex to the correct global position inside its bucket bucket_storage = similar(degrees, T) positions = similar(degrees, T) for v in eachindex(positions, degrees) d = degrees[v] - positions[v] = bucket_high[d + 1] - deg_count[d + 1] + 1 + positions[v] = bucket_high[d+1] - deg_count[d+1] + 1 bucket_storage[positions[v]] = v - deg_count[d + 1] -= 1 + deg_count[d+1] -= 1 end return DegreeBucketsSMC(degrees, bucket_storage, bucket_low, bucket_high, positions) end function nonempty_bucket(db::DegreeBucketsSMC, d::Integer) - return db.bucket_high[d + 1] >= db.bucket_low[d + 1] + return db.bucket_high[d+1] >= db.bucket_low[d+1] end function nonempty_bucket(db::DegreeBucketsColPack, d::Integer) - return !isempty(db.buckets[d + 1]) + return !isempty(db.buckets[d+1]) end function degree_increasing(; degtype, direction) @@ -229,13 +229,13 @@ function pop_next_candidate!(db::AbstractDegreeBuckets; degree_range::OrdinalRan end if db isa DegreeBucketsColPack (; buckets) = db - bucket = buckets[candidate_degree + 1] + bucket = buckets[candidate_degree+1] candidate = pop!(bucket) else (; bucket_storage, bucket_high) = db - high = bucket_high[candidate_degree + 1] + high = bucket_high[candidate_degree+1] candidate = bucket_storage[high] - bucket_high[candidate_degree + 1] -= 1 + bucket_high[candidate_degree+1] -= 1 end # mark as ordered degrees[candidate] = -1 @@ -244,44 +244,48 @@ function pop_next_candidate!(db::AbstractDegreeBuckets; degree_range::OrdinalRan end function update_bucket!( - db::DegreeBucketsSMC, v::Integer, d::Integer; degtype::Symbol, direction::Symbol + db::DegreeBucketsSMC, + v::Integer, + d::Integer; + degtype::Symbol, + direction::Symbol, ) (; degrees, bucket_storage, bucket_low, bucket_high, positions) = db p = positions[v] # select previous or next bucket for the move if degree_increasing(; degtype, direction) - high = bucket_high[d + 1] + high = bucket_high[d+1] # move the vertex w located at the end of the current bucket to v's position w = bucket_storage[high] bucket_storage[p] = w positions[w] = p # shrink current bucket from the right # morally we put v at the end and then ignore it - bucket_high[d + 1] -= 1 + bucket_high[d+1] -= 1 # move v to the beginning of the next bucket (!= ColPack) d_new = d + 1 - low_new = bucket_low[d_new + 1] - bucket_storage[low_new - 1] = v + low_new = bucket_low[d_new+1] + bucket_storage[low_new-1] = v # grow next bucket to the left - bucket_low[d_new + 1] -= 1 + bucket_low[d_new+1] -= 1 # update v's stats degrees[v] = d_new positions[v] = low_new - 1 else - low = bucket_low[d + 1] + low = bucket_low[d+1] # move the vertex w located at the start of the current bucket to v's position (!= ColPack) w = bucket_storage[low] bucket_storage[p] = w positions[w] = p # shrink current bucket from the left # morally we put v at the start and then ignore it - bucket_low[d + 1] += 1 + bucket_low[d+1] += 1 # move v to the end of the previous bucket d_new = d - 1 - high_new = bucket_high[d_new + 1] - bucket_storage[high_new + 1] = v + high_new = bucket_high[d_new+1] + bucket_storage[high_new+1] = v # grow previous bucket to the right - bucket_high[d_new + 1] += 1 + bucket_high[d_new+1] += 1 # update v's stats degrees[v] = d_new positions[v] = high_new + 1 @@ -290,14 +294,18 @@ function update_bucket!( end function update_bucket!( - db::DegreeBucketsColPack, v::Integer, d::Integer; degtype::Symbol, direction::Symbol + db::DegreeBucketsColPack, + v::Integer, + d::Integer; + degtype::Symbol, + direction::Symbol, ) (; degrees, buckets, positions) = db p = positions[v] - bucket = buckets[d + 1] + bucket = buckets[d+1] # select previous or next bucket for the move d_new = degree_increasing(; degtype, direction) ? d + 1 : d - 1 - bucket_new = buckets[d_new + 1] + bucket_new = buckets[d_new+1] # put v at the end of its bucket by swapping w = bucket[end] bucket[p] = w @@ -313,7 +321,8 @@ function update_bucket!( end function vertices( - g::AdjacencyGraph{T}, ::DynamicDegreeBasedOrder{degtype,direction,reproduce_colpack} + g::AdjacencyGraph{T}, + ::DynamicDegreeBasedOrder{degtype,direction,reproduce_colpack}, ) where {T<:Integer,degtype,direction,reproduce_colpack} degrees = T[degree(g, v) for v in vertices(g)] dmax = maximum(degrees) @@ -341,9 +350,9 @@ function vertices( end # no need to look much further than du next time degree_range = if direction == :low2high - reverse(0:min(du + 1, dmax)) + reverse(0:min(du+1, dmax)) else - max(du - 1, 0):dmax + max(du-1, 0):dmax end end return π @@ -397,9 +406,9 @@ function vertices( end # no need to look much further than du next time degree_range = if direction == :low2high - reverse(0:min(du + 1, dmax)) + reverse(0:min(du+1, dmax)) else - max(du - 1, 0):dmax + max(du-1, 0):dmax end end return π @@ -414,7 +423,7 @@ Instance of [`AbstractOrder`](@ref) which sorts vertices from lowest to highest - [`DynamicDegreeBasedOrder`](@ref) """ -function IncidenceDegree(; reproduce_colpack::Bool=false) +function IncidenceDegree(; reproduce_colpack::Bool = false) return DynamicDegreeBasedOrder{:back,:low2high,reproduce_colpack}() end @@ -427,7 +436,7 @@ Instance of [`AbstractOrder`](@ref) which sorts vertices from highest to lowest - [`DynamicDegreeBasedOrder`](@ref) """ -function SmallestLast(; reproduce_colpack::Bool=false) +function SmallestLast(; reproduce_colpack::Bool = false) return DynamicDegreeBasedOrder{:back,:high2low,reproduce_colpack}() end @@ -440,7 +449,7 @@ Instance of [`AbstractOrder`](@ref) which sorts vertices from lowest to highest - [`DynamicDegreeBasedOrder`](@ref) """ -function DynamicLargestFirst(; reproduce_colpack::Bool=false) +function DynamicLargestFirst(; reproduce_colpack::Bool = false) return DynamicDegreeBasedOrder{:forward,:low2high,reproduce_colpack}() end @@ -471,12 +480,12 @@ function all_orders() RandomOrder(), LargestFirst(), SmallestLast(), - SmallestLast(; reproduce_colpack=true), + SmallestLast(; reproduce_colpack = true), IncidenceDegree(), - IncidenceDegree(; reproduce_colpack=true), + IncidenceDegree(; reproduce_colpack = true), DynamicLargestFirst(), - DynamicLargestFirst(; reproduce_colpack=true), + DynamicLargestFirst(; reproduce_colpack = true), DynamicDegreeBasedOrder{:forward,:high2low}(), - DynamicDegreeBasedOrder{:forward,:high2low}(; reproduce_colpack=true), + DynamicDegreeBasedOrder{:forward,:high2low}(; reproduce_colpack = true), ] end diff --git a/src/postprocessing.jl b/src/postprocessing.jl index 7b2b58f5..c3a568f5 100644 --- a/src/postprocessing.jl +++ b/src/postprocessing.jl @@ -34,7 +34,7 @@ function postprocess!( num_colors_useless = 0 # determine what are the useless colors and compute the offsets - for ci in 1:nb_colors + for ci = 1:nb_colors if color_used[ci] offsets[ci] = num_colors_useless else @@ -109,19 +109,21 @@ function postprocess_with_star_set!( end function postprocess_with_tree_set!( - color_used::Vector{Bool}, color::AbstractVector{<:Integer}, tree_set::TreeSet + color_used::Vector{Bool}, + color::AbstractVector{<:Integer}, + tree_set::TreeSet, ) # only the colors of non-leaf vertices are used (; reverse_bfs_orders, is_star, tree_edge_indices, nt) = tree_set nb_trivial_trees = 0 # Iterate through all non-trivial trees - for k in 1:nt + for k = 1:nt # Position of the first edge in the tree first = tree_edge_indices[k] # Total number of edges in the tree - ne_tree = tree_edge_indices[k + 1] - first + ne_tree = tree_edge_indices[k+1] - first # Check if we have more than one edge in the tree (non-trivial tree) if ne_tree > 1 @@ -143,12 +145,12 @@ function postprocess_with_tree_set!( # Process the trivial trees (if any) if nb_trivial_trees > 0 - for k in 1:nt + for k = 1:nt # Position of the first edge in the tree first = tree_edge_indices[k] # Total number of edges in the tree - ne_tree = tree_edge_indices[k + 1] - first + ne_tree = tree_edge_indices[k+1] - first # Check if we have exactly one edge in the tree if ne_tree == 1 diff --git a/src/precompile.jl b/src/precompile.jl index 29eebaca..48f12079 100644 --- a/src/precompile.jl +++ b/src/precompile.jl @@ -8,7 +8,7 @@ for (structure, partition, decompression) in [ ] A = sparse(Bool[1 0; 0 1]) problem = ColoringProblem(; structure, partition) - algo = GreedyColoringAlgorithm(; decompression, postprocessing=true) + algo = GreedyColoringAlgorithm(; decompression, postprocessing = true) result = coloring(A, problem, algo) if partition == :bidirectional Br, Bc = compress(A, result) diff --git a/src/result.jl b/src/result.jl index 0d47cf13..ddd4c05b 100644 --- a/src/result.jl +++ b/src/result.jl @@ -106,7 +106,7 @@ function group_by_color(::Type{T}, color::AbstractVector) where {T<:Integer} end # Create views into contiguous blocks of the group vector group = map(1:cmax) do c - i = 1 + (c == 1 ? 0 : group_offsets[c - 1]) + i = 1 + (c == 1 ? 0 : group_offsets[c-1]) j = group_offsets[c] view(group_flat, i:j) end @@ -172,7 +172,9 @@ struct ColumnColoringResult{ end function ColumnColoringResult( - A::AbstractMatrix, bg::BipartiteGraph{T}, color::Vector{<:Integer} + A::AbstractMatrix, + bg::BipartiteGraph{T}, + color::Vector{<:Integer}, ) where {T<:Integer} group = group_by_color(T, color) compressed_indices = column_csc_indices(bg, color) @@ -244,7 +246,9 @@ struct RowColoringResult{ end function RowColoringResult( - A::AbstractMatrix, bg::BipartiteGraph{T}, color::Vector{<:Integer} + A::AbstractMatrix, + bg::BipartiteGraph{T}, + color::Vector{<:Integer}, ) where {T<:Integer} group = group_by_color(T, color) compressed_indices = row_csc_indices(bg, color) @@ -327,7 +331,9 @@ function StarSetColoringResult( end function star_csc_indices( - ag::AdjacencyGraph{T}, color::Vector{<:Integer}, star_set + ag::AdjacencyGraph{T}, + color::Vector{<:Integer}, + star_set, ) where {T} (; star, hub) = star_set S = pattern(ag) @@ -380,7 +386,11 @@ $TYPEDFIELDS - [`AbstractColoringResult`](@ref) """ struct TreeSetColoringResult{ - M<:AbstractMatrix,T<:Integer,G<:AdjacencyGraph{T},GT<:AbstractGroups{T},R + M<:AbstractMatrix, + T<:Integer, + G<:AdjacencyGraph{T}, + GT<:AbstractGroups{T}, + R, } <: AbstractColoringResult{:symmetric,:column,:substitution} A::M ag::G @@ -435,12 +445,12 @@ function TreeSetColoringResult( # Index in lower_triangle_offsets and upper_triangle_offsets index_offsets = 0 - for k in 1:nt + for k = 1:nt # Positions of the edges for each tree first = tree_edge_indices[k] - last = tree_edge_indices[k + 1] - 1 + last = tree_edge_indices[k+1] - 1 - for pos in first:last + for pos = first:last (leaf, neighbor) = reverse_bfs_orders[pos] # Update lower_triangle_offsets and upper_triangle_offsets i = leaf @@ -512,7 +522,12 @@ $TYPEDFIELDS - [`AbstractColoringResult`](@ref) """ struct LinearSystemColoringResult{ - M<:AbstractMatrix,T<:Integer,G<:AdjacencyGraph{T},GT<:AbstractGroups{T},R,F + M<:AbstractMatrix, + T<:Integer, + G<:AdjacencyGraph{T}, + GT<:AbstractGroups{T}, + R, + F, } <: AbstractColoringResult{:symmetric,:column,:substitution} A::M ag::G @@ -592,14 +607,18 @@ For all vertex indices `j` between `1` and `n` we have: column_color[j] = symmetric_to_column[color[j]] """ function remap_colors( - ::Type{T}, color::Vector{<:Integer}, num_sym_colors::Integer, m::Integer, n::Integer + ::Type{T}, + color::Vector{<:Integer}, + num_sym_colors::Integer, + m::Integer, + n::Integer, ) where {T<:Integer} # Map symmetric colors to column colors symmetric_to_column = zeros(T, num_sym_colors) column_color = zeros(T, n) counter = 0 - for j in 1:n + for j = 1:n cj = color[j] if cj > 0 # First time that we encounter this column color @@ -616,7 +635,7 @@ function remap_colors( row_color = zeros(T, m) counter = 0 - for i in (n + 1):(n + m) + for i = (n+1):(n+m) ci = color[i] if ci > 0 # First time that we encounter this row color @@ -624,7 +643,7 @@ function remap_colors( counter += 1 symmetric_to_row[ci] = counter end - row_color[i - n] = symmetric_to_row[ci] + row_color[i-n] = symmetric_to_row[ci] end end @@ -702,8 +721,8 @@ function BicoloringResult( row_group = group_by_color(T, row_color) Br_and_Bc = Matrix{R}(undef, n + m, num_sym_colors) large_colptr = copy(ag.S.colptr) - large_colptr[(n + 2):end] .= large_colptr[n + 1] # last few columns are empty - large_rowval = ag.S.rowval[1:(end ÷ 2)] # forget the second half of nonzeros + large_colptr[(n+2):end] .= large_colptr[n+1] # last few columns are empty + large_rowval = ag.S.rowval[1:(end÷2)] # forget the second half of nonzeros return BicoloringResult( A, ag, diff --git a/test/adtypes.jl b/test/adtypes.jl index da0807d3..bcbfe53c 100644 --- a/test/adtypes.jl +++ b/test/adtypes.jl @@ -6,7 +6,7 @@ using Test @testset "NoColoringAlgorithm" begin @testset "Column coloring" begin - problem = ColoringProblem(; structure=:nonsymmetric, partition=:column) + problem = ColoringProblem(; structure = :nonsymmetric, partition = :column) algo = ADTypes.NoColoringAlgorithm() A = sprand(10, 20, 0.3) result = coloring(A, problem, algo) @@ -17,7 +17,7 @@ using Test end @testset "Row coloring" begin - problem = ColoringProblem(; structure=:nonsymmetric, partition=:row) + problem = ColoringProblem(; structure = :nonsymmetric, partition = :row) algo = ADTypes.NoColoringAlgorithm() A = sprand(10, 20, 0.3) result = coloring(A, problem, algo) @@ -28,7 +28,7 @@ using Test end @testset "Symmetric coloring" begin - problem = ColoringProblem(; structure=:symmetric, partition=:column) + problem = ColoringProblem(; structure = :symmetric, partition = :column) algo = ADTypes.NoColoringAlgorithm() A = Symmetric(sprand(20, 20, 0.3)) result = coloring(A, problem, algo) @@ -39,7 +39,7 @@ using Test end @testset "Bicoloring" begin - problem = ColoringProblem(; structure=:nonsymmetric, partition=:bidirectional) + problem = ColoringProblem(; structure = :nonsymmetric, partition = :bidirectional) algo = ADTypes.NoColoringAlgorithm() A = sprand(10, 20, 0.3) result = coloring(A, problem, algo) diff --git a/test/allocations.jl b/test/allocations.jl index 31305e63..033f07f5 100644 --- a/test/allocations.jl +++ b/test/allocations.jl @@ -10,10 +10,11 @@ rng = StableRNG(63) function test_noallocs_distance2_coloring(n) bench = @be (; - bg=BipartiteGraph(sprand(rng, n, n, 5 / n)), - color=Vector{Int}(undef, n), - forbidden_colors=Vector{Int}(undef, n), - ) partial_distance2_coloring!(_.color, _.forbidden_colors, _.bg, Val(1), 1:n) evals = 1 + bg = BipartiteGraph(sprand(rng, n, n, 5 / n)), + color = Vector{Int}(undef, n), + forbidden_colors = Vector{Int}(undef, n), + ) partial_distance2_coloring!(_.color, _.forbidden_colors, _.bg, Val(1), 1:n) evals = + 1 @test minimum(bench).allocs == 0 end @@ -22,11 +23,16 @@ end end function test_noallocs_sparse_decompression( - n::Integer; structure::Symbol, partition::Symbol, decompression::Symbol + n::Integer; + structure::Symbol, + partition::Symbol, + decompression::Symbol, ) A = sparse(Symmetric(sprand(rng, n, n, 5 / n))) result = coloring( - A, ColoringProblem(; structure, partition), GreedyColoringAlgorithm(; decompression) + A, + ColoringProblem(; structure, partition), + GreedyColoringAlgorithm(; decompression), ) if partition == :bidirectional @@ -52,22 +58,21 @@ function test_noallocs_sparse_decompression( else B[1, :] end - bench1_singlecolor = @be similar(A) decompress_single_color!( - _, b, 1, result - ) evals = 1 - bench2_singlecolor = @be similar(Matrix(A)) decompress_single_color!( - _, b, 1, result - ) evals = 1 + bench1_singlecolor = + @be similar(A) decompress_single_color!(_, b, 1, result) evals = 1 + bench2_singlecolor = + @be similar(Matrix(A)) decompress_single_color!(_, b, 1, result) evals = + 1 @test minimum(bench1_singlecolor).allocs == 0 @test minimum(bench2_singlecolor).allocs == 0 end end @testset "Triangle decompression" begin if structure == :symmetric - bench1_triangle = @be similar(triu(A)) decompress!(_, B, result, :U) evals = - 1 - bench2_triangle = @be similar(Matrix(A)) decompress!(_, B, result, :U) evals = - 1 + bench1_triangle = + @be similar(triu(A)) decompress!(_, B, result, :U) evals = 1 + bench2_triangle = + @be similar(Matrix(A)) decompress!(_, B, result, :U) evals = 1 @test minimum(bench1_triangle).allocs == 0 @test minimum(bench2_triangle).allocs == 0 end @@ -75,12 +80,12 @@ function test_noallocs_sparse_decompression( @testset "Single-color triangle decompression" begin if structure == :symmetric && decompression == :direct b = B[:, 1] - bench1_singlecolor_triangle = @be similar(triu(A)) decompress_single_color!( - _, b, 1, result, :U - ) evals = 1 - bench2_singlecolor_triangle = @be similar(Matrix(A)) decompress_single_color!( - _, b, 1, result, :U - ) evals = 1 + bench1_singlecolor_triangle = + @be similar(triu(A)) decompress_single_color!(_, b, 1, result, :U) evals = + 1 + bench2_singlecolor_triangle = + @be similar(Matrix(A)) decompress_single_color!(_, b, 1, result, :U) evals = + 1 @test minimum(bench1_singlecolor_triangle).allocs == 0 @test minimum(bench2_singlecolor_triangle).allocs == 0 end @@ -89,7 +94,10 @@ function test_noallocs_sparse_decompression( end function test_noallocs_structured_decompression( - n::Integer; structure::Symbol, partition::Symbol, decompression::Symbol + n::Integer; + structure::Symbol, + partition::Symbol, + decompression::Symbol, ) @testset "$(nameof(typeof(A)))" for A in [ Diagonal(rand(n)), @@ -110,7 +118,9 @@ end @testset "Sparse decompression" begin @testset "$structure - $partition - $decompression" for ( - structure, partition, decompression + structure, + partition, + decompression, ) in [ (:nonsymmetric, :column, :direct), (:nonsymmetric, :row, :direct), @@ -125,9 +135,12 @@ end @testset "Structured decompression" begin @testset "$structure - $partition - $decompression" for ( - structure, partition, decompression + structure, + partition, + decompression, ) in [ - (:nonsymmetric, :column, :direct), (:nonsymmetric, :row, :direct) + (:nonsymmetric, :column, :direct), + (:nonsymmetric, :row, :direct), ] test_noallocs_structured_decompression(1000; structure, partition, decompression) end @@ -138,7 +151,9 @@ end A64 = sparse(Symmetric(sprand(rng, Float32, 100, 100, 0.1))) A32 = convert(SparseMatrixCSC{Float32,Int32}, A64) @testset "$structure - $partition - $decompression" for ( - structure, partition, decompression + structure, + partition, + decompression, ) in [ (:nonsymmetric, :column, :direct), (:nonsymmetric, :row, :direct), diff --git a/test/check.jl b/test/check.jl index 8cf2c495..70274847 100644 --- a/test/check.jl +++ b/test/check.jl @@ -32,15 +32,15 @@ using Test @test !structurally_orthogonal_columns(A, [1, 2]) log = (:warn, "2 colors provided for 3 columns.") - @test_logs log structurally_orthogonal_columns(A, [1, 2]; verbose=true) + @test_logs log structurally_orthogonal_columns(A, [1, 2]; verbose = true) @test !directly_recoverable_columns(A, [1, 2]) log = (:warn, "2 colors provided for 3 columns.") - @test_logs log !directly_recoverable_columns(A, [1, 2]; verbose=true) + @test_logs log !directly_recoverable_columns(A, [1, 2]; verbose = true) @test !structurally_orthogonal_columns(A, [1, 2, 2]) log = (:warn, "In color 2, columns [2, 3] all have nonzeros in row 3.") - @test_logs log structurally_orthogonal_columns(A, [1, 2, 2]; verbose=true) + @test_logs log structurally_orthogonal_columns(A, [1, 2, 2]; verbose = true) @test !directly_recoverable_columns(A, [1, 2, 2]) log = (:warn, "Coefficients [3, 4] are not directly recoverable.") @@ -67,19 +67,23 @@ end @test !structurally_orthogonal_columns(transpose(A), [1, 2, 2, 3]) log = (:warn, "4 colors provided for 3 columns.") - @test_logs log structurally_orthogonal_columns(transpose(A), [1, 2, 2, 3]; verbose=true) + @test_logs log structurally_orthogonal_columns( + transpose(A), + [1, 2, 2, 3]; + verbose = true, + ) @test !directly_recoverable_columns(transpose(A), [1, 2, 2, 3]) log = (:warn, "4 colors provided for 3 columns.") - @test_logs log directly_recoverable_columns(transpose(A), [1, 2, 2, 3]; verbose=true) + @test_logs log directly_recoverable_columns(transpose(A), [1, 2, 2, 3]; verbose = true) @test !structurally_orthogonal_columns(transpose(A), [1, 2, 2]) log = (:warn, "In color 2, columns [2, 3] all have nonzeros in row 2.") - @test_logs log !structurally_orthogonal_columns(transpose(A), [1, 2, 2]; verbose=true) + @test_logs log !structurally_orthogonal_columns(transpose(A), [1, 2, 2]; verbose = true) @test !directly_recoverable_columns(transpose(A), [1, 2, 2]) log = (:warn, "Coefficients [2, 3] are not directly recoverable.") - @test_logs log directly_recoverable_columns(transpose(A), [1, 2, 2]; verbose=true) + @test_logs log directly_recoverable_columns(transpose(A), [1, 2, 2]; verbose = true) end @testset "Symmetrically orthogonal" begin @@ -96,7 +100,9 @@ end @test !symmetrically_orthogonal_columns(A, [1, 2, 1, 3, 1]) @test_logs (:warn, "5 colors provided for 6 columns.") symmetrically_orthogonal_columns( - A, [1, 2, 1, 3, 1]; verbose=true + A, + [1, 2, 1, 3, 1]; + verbose = true, ) @test !symmetrically_orthogonal_columns(A, [1, 3, 1, 3, 1, 1]) @@ -107,7 +113,7 @@ For coefficient (i=2, j=3) with colors (ci=3, cj=1): - In row color ci=3, rows [2, 4] all have nonzeros in column j=3. - In column color cj=1, columns [1, 3, 5, 6] all have nonzeros in row i=2. """, - ) symmetrically_orthogonal_columns(A, [1, 3, 1, 3, 1, 1]; verbose=true) + ) symmetrically_orthogonal_columns(A, [1, 3, 1, 3, 1, 1]; verbose = true) A = efficient_fig_1().A @test issymmetric(A) @@ -146,10 +152,16 @@ end @test !structurally_biorthogonal(A, [1, 1, 1, 2], [1, 1, 1, 1, 2]) @test_logs (:warn, "4 colors provided for 5 columns.") !structurally_biorthogonal( - A, [1, 2, 2, 3], [1, 2, 2, 2]; verbose=true + A, + [1, 2, 2, 3], + [1, 2, 2, 2]; + verbose = true, ) @test_logs (:warn, "5 colors provided for 4 rows.") !structurally_biorthogonal( - A, [1, 2, 2, 3, 4], [1, 2, 2, 2, 3]; verbose=true + A, + [1, 2, 2, 3, 4], + [1, 2, 2, 2, 3]; + verbose = true, ) @test_logs ( :warn, @@ -158,7 +170,7 @@ For coefficient (i=1, j=1) with colors (ci=1, cj=1): - In row color ci=1, rows [1, 2, 3] all have nonzeros in column j=1. - In column color cj=1, columns [1, 2, 3, 4] all have nonzeros in row i=1. """, - ) !structurally_biorthogonal(A, [1, 1, 1, 2], [1, 1, 1, 1, 2]; verbose=true) + ) !structurally_biorthogonal(A, [1, 1, 1, 2], [1, 1, 1, 1, 2]; verbose = true) @test_logs ( :warn, @@ -167,7 +179,7 @@ For coefficient (i=1, j=2) with colors (ci=0, cj=2): - Row color ci=0 is neutral. - In column color cj=2, columns [2, 3, 4] all have nonzeros in row i=1. """, - ) structurally_biorthogonal(A, [0, 2, 2, 3], [1, 2, 2, 2, 3], verbose=true) + ) structurally_biorthogonal(A, [0, 2, 2, 3], [1, 2, 2, 2, 3], verbose = true) @test_logs ( :warn, @@ -176,7 +188,7 @@ For coefficient (i=2, j=1) with colors (ci=2, cj=0): - In row color ci=2, rows [2, 3] all have nonzeros in column j=1. - Column color cj=0 is neutral. """, - ) structurally_biorthogonal(A, [1, 2, 2, 3], [0, 2, 2, 2, 3], verbose=true) + ) structurally_biorthogonal(A, [1, 2, 2, 3], [0, 2, 2, 2, 3], verbose = true) @test_logs ( :warn, @@ -185,7 +197,7 @@ For coefficient (i=1, j=1) with colors (ci=0, cj=0): - Row color ci=0 is neutral. - Column color cj=0 is neutral. """, - ) structurally_biorthogonal(A, [0, 2, 2, 3], [0, 2, 2, 2, 3], verbose=true) + ) structurally_biorthogonal(A, [0, 2, 2, 3], [0, 2, 2, 2, 3], verbose = true) end @testset "Substitutable columns" begin @@ -242,7 +254,7 @@ end @test !substitutable_columns(A1, B1, [1, 1, 1, 1]) log = (:warn, "4 colors provided for 5 columns.") - @test_logs log substitutable_columns(A1, B1, [1, 1, 1, 1]; verbose=true) + @test_logs log substitutable_columns(A1, B1, [1, 1, 1, 1]; verbose = true) @test !substitutable_columns(A1, B1, [1, 1, 1, 1, 1]) @test_logs ( @@ -252,7 +264,7 @@ For coefficient (i=1, j=1) with colors (ci=1, cj=1): - For the row 5 in row color ci=1, A[5, 1] is ordered after A[1, 1]. - For the column 5 in column color cj=1, A[1, 5] is ordered after A[1, 1]. """, - ) substitutable_columns(A1, B1, [1, 1, 1, 1, 1]; verbose=true) + ) substitutable_columns(A1, B1, [1, 1, 1, 1, 1]; verbose = true) @test !substitutable_columns(A2, B2, [1, 2, 0, 1, 2]) @test_logs ( @@ -262,7 +274,7 @@ For coefficient (i=3, j=3) with colors (ci=0, cj=0): - Row color ci=0 is neutral. - Column color cj=0 is neutral. """, - ) substitutable_columns(A2, B2, [1, 2, 0, 1, 2]; verbose=true) + ) substitutable_columns(A2, B2, [1, 2, 0, 1, 2]; verbose = true) @test !substitutable_columns(A3, B3, [0, 1, 2, 3, 3]) @test_logs ( @@ -272,7 +284,7 @@ For coefficient (i=1, j=4) with colors (ci=0, cj=3): - Row color ci=0 is neutral. - For the column 5 in column color cj=3, A[1, 5] is ordered after A[1, 4]. """, - ) substitutable_columns(A3, B3, [0, 1, 2, 3, 3]; verbose=true) + ) substitutable_columns(A3, B3, [0, 1, 2, 3, 3]; verbose = true) @test !substitutable_columns(A3, B3, [1, 2, 3, 3, 0]) @test_logs ( @@ -282,7 +294,7 @@ For coefficient (i=3, j=5) with colors (ci=3, cj=0): - For the row 4 in row color ci=3, A[4, 5] is ordered after A[3, 5]. - Column color cj=0 is neutral. """, - ) substitutable_columns(A3, B3, [1, 2, 3, 3, 0]; verbose=true) + ) substitutable_columns(A3, B3, [1, 2, 3, 3, 0]; verbose = true) end @testset "Substitutable bidirectional" begin @@ -304,16 +316,22 @@ end # failure log = (:warn, "2 colors provided for 3 columns.") - @test_logs log !substitutable_bidirectional(A, B, [1, 0, 0], [0, 1]; verbose=true) + @test_logs log !substitutable_bidirectional(A, B, [1, 0, 0], [0, 1]; verbose = true) log = (:warn, "4 colors provided for 3 rows.") - @test_logs log !substitutable_bidirectional(A, B, [1, 0, 0, 1], [0, 1, 1]; verbose=true) + @test_logs log !substitutable_bidirectional( + A, + B, + [1, 0, 0, 1], + [0, 1, 1]; + verbose = true, + ) end # See https://github.com/JuliaDiff/SparseMatrixColorings.jl/pull/300 @testset "Empty matrix" begin - problem = ColoringProblem(; structure=:symmetric, partition=:column) - algo = GreedyColoringAlgorithm(; decompression=:substitution) + problem = ColoringProblem(; structure = :symmetric, partition = :column) + algo = GreedyColoringAlgorithm(; decompression = :substitution) S = spzeros(Int, 0, 0) result = coloring(S, problem, algo) @test isempty(result.color) diff --git a/test/constant.jl b/test/constant.jl index 97c7f238..0a484ea8 100644 --- a/test/constant.jl +++ b/test/constant.jl @@ -7,9 +7,9 @@ matrix_template = ones(Bool, 10, 20) sym_matrix_template = ones(Bool, 10, 10) @testset "Column coloring" begin - problem = ColoringProblem(; structure=:nonsymmetric, partition=:column) + problem = ColoringProblem(; structure = :nonsymmetric, partition = :column) color = collect(1:20) - algo = ConstantColoringAlgorithm(matrix_template, color; partition=:column) + algo = ConstantColoringAlgorithm(matrix_template, color; partition = :column) wrong_algo = ConstantColoringAlgorithm{:row}(matrix_template, color) wrong_color = ConstantColoringAlgorithm{:column}(matrix_template, ones(Int, 20)) @test_throws DimensionMismatch coloring(transpose(matrix_template), problem, algo) @@ -22,9 +22,9 @@ sym_matrix_template = ones(Bool, 10, 10) end @testset "Row coloring" begin - problem = ColoringProblem(; structure=:nonsymmetric, partition=:row) + problem = ColoringProblem(; structure = :nonsymmetric, partition = :row) color = collect(1:10) - algo = ConstantColoringAlgorithm(matrix_template, color; partition=:row) + algo = ConstantColoringAlgorithm(matrix_template, color; partition = :row) wrong_algo = ConstantColoringAlgorithm{:column}(matrix_template, color) wrong_color = ConstantColoringAlgorithm{:row}(matrix_template, ones(Int, 10)) @test_throws DimensionMismatch coloring(transpose(matrix_template), problem, algo) @@ -37,17 +37,18 @@ end end @testset "Symmetric coloring" begin - problem = ColoringProblem(; structure=:symmetric, partition=:column) + problem = ColoringProblem(; structure = :symmetric, partition = :column) color = collect(1:10) algo = ConstantColoringAlgorithm( - sym_matrix_template, color; partition=:column, structure=:symmetric - ) - wrong_algo = ConstantColoringAlgorithm{:column,:nonsymmetric}( - sym_matrix_template, color - ) - wrong_color = ConstantColoringAlgorithm{:column,:symmetric}( - sym_matrix_template, ones(Int, 20) + sym_matrix_template, + color; + partition = :column, + structure = :symmetric, ) + wrong_algo = + ConstantColoringAlgorithm{:column,:nonsymmetric}(sym_matrix_template, color) + wrong_color = + ConstantColoringAlgorithm{:column,:symmetric}(sym_matrix_template, ones(Int, 20)) @test_throws DimensionMismatch coloring(matrix_template, problem, algo) @test_throws MethodError coloring(sym_matrix_template, problem, wrong_algo) @test_throws InvalidColoringError coloring(sym_matrix_template, problem, wrong_color) diff --git a/test/constructors.jl b/test/constructors.jl index 8ce88bcb..293db938 100644 --- a/test/constructors.jl +++ b/test/constructors.jl @@ -3,13 +3,13 @@ using Test @test ColoringProblem{:nonsymmetric,:column}() == ColoringProblem() @test ColoringProblem{:symmetric,:column}() == - ColoringProblem(; structure=:symmetric, partition=:column) + ColoringProblem(; structure = :symmetric, partition = :column) -@test_throws ArgumentError ColoringProblem(; structure=:weird, partition=:column) -@test_throws ArgumentError ColoringProblem(; structure=:symmetric, partition=:row) +@test_throws ArgumentError ColoringProblem(; structure = :weird, partition = :column) +@test_throws ArgumentError ColoringProblem(; structure = :symmetric, partition = :row) @test GreedyColoringAlgorithm{:direct}() == GreedyColoringAlgorithm() @test GreedyColoringAlgorithm{:substitution}() == - GreedyColoringAlgorithm(; decompression=:substitution) + GreedyColoringAlgorithm(; decompression = :substitution) -@test_throws ArgumentError GreedyColoringAlgorithm(decompression=:weird) +@test_throws ArgumentError GreedyColoringAlgorithm(decompression = :weird) diff --git a/test/cuda.jl b/test/cuda.jl index 8b27e07b..136ab44d 100644 --- a/test/cuda.jl +++ b/test/cuda.jl @@ -21,40 +21,43 @@ symmetric_params = vcat( ) @testset verbose = true "Column coloring & decompression" begin - problem = ColoringProblem(; structure=:nonsymmetric, partition=:column) - algo = GreedyColoringAlgorithm(; decompression=:direct) + problem = ColoringProblem(; structure = :nonsymmetric, partition = :column) + algo = GreedyColoringAlgorithm(; decompression = :direct) @testset for T in (CuSparseMatrixCSC, CuSparseMatrixCSR) @testset "$((; m, n, p))" for (m, n, p) in asymmetric_params A0 = T(sprand(rng, m, n, p)) - test_coloring_decompression(A0, problem, algo; gpu=true) + test_coloring_decompression(A0, problem, algo; gpu = true) end end end; @testset verbose = true "Row coloring & decompression" begin - problem = ColoringProblem(; structure=:nonsymmetric, partition=:row) - algo = GreedyColoringAlgorithm(; decompression=:direct) + problem = ColoringProblem(; structure = :nonsymmetric, partition = :row) + algo = GreedyColoringAlgorithm(; decompression = :direct) @testset for T in (CuSparseMatrixCSC, CuSparseMatrixCSR) @testset "$((; m, n, p))" for (m, n, p) in asymmetric_params A0 = T(sprand(rng, m, n, p)) - test_coloring_decompression(A0, problem, algo; gpu=true) + test_coloring_decompression(A0, problem, algo; gpu = true) end end end; @testset verbose = true "Symmetric coloring & direct decompression" begin - problem = ColoringProblem(; structure=:symmetric, partition=:column) - algo = GreedyColoringAlgorithm(; postprocessing=false, decompression=:direct) + problem = ColoringProblem(; structure = :symmetric, partition = :column) + algo = GreedyColoringAlgorithm(; postprocessing = false, decompression = :direct) @testset for T in (CuSparseMatrixCSC, CuSparseMatrixCSR) @testset "$((; n, p))" for (n, p) in symmetric_params A0 = T(sparse(Symmetric(sprand(rng, n, n, p)))) - test_coloring_decompression(A0, problem, algo; gpu=true) + test_coloring_decompression(A0, problem, algo; gpu = true) end A0 = T(sparse(Diagonal(ones(10)))) result = coloring(A0, problem, algo) B = compress(A0, result) @test_throws SMC.UnsupportedDecompressionError decompress!( - similar(A0), B, result, :U + similar(A0), + B, + result, + :U, ) end end; diff --git a/test/graph.jl b/test/graph.jl index 773a0206..944e4e30 100644 --- a/test/graph.jl +++ b/test/graph.jl @@ -18,7 +18,7 @@ using Test @test eltype(SparsityPatternCSC(sprand(10, 10, 0.1))) == Bool @test SparseArrays.indtype(SparsityPatternCSC(sprand(10, 10, 0.1))) == Int @testset "Transpose" begin - for _ in 1:1000 + for _ = 1:1000 m, n = rand(100:1000), rand(100:1000) p = 0.05 * rand() A = sprand(m, n, p) @@ -31,31 +31,40 @@ using Test end @testset "Bidirectional" begin @testset "symmetric_pattern = false" begin - for _ in 1:1000 + for _ = 1:1000 m, n = rand(100:1000), rand(100:1000) p = 0.05 * rand() A = sprand(Bool, m, n, p) A_and_Aᵀ = [spzeros(Bool, n, n) transpose(A); A spzeros(Bool, m, m)] - S_and_Sᵀ, edge_to_index = bidirectional_pattern(A; symmetric_pattern=false) + S_and_Sᵀ, edge_to_index = + bidirectional_pattern(A; symmetric_pattern = false) @test S_and_Sᵀ.colptr == A_and_Aᵀ.colptr @test S_and_Sᵀ.rowval == A_and_Aᵀ.rowval M = SparseMatrixCSC( - m + n, m + n, S_and_Sᵀ.colptr, S_and_Sᵀ.rowval, edge_to_index + m + n, + m + n, + S_and_Sᵀ.colptr, + S_and_Sᵀ.rowval, + edge_to_index, ) @test issymmetric(M) end end @testset "symmetric_pattern = true" begin - for _ in 1:1000 + for _ = 1:1000 m = rand(100:1000) p = 0.05 * rand() A = sparse(Symmetric(sprand(Bool, m, m, p))) A_and_Aᵀ = [spzeros(Bool, m, m) transpose(A); A spzeros(Bool, m, m)] - S_and_Sᵀ, edge_to_index = bidirectional_pattern(A; symmetric_pattern=true) + S_and_Sᵀ, edge_to_index = bidirectional_pattern(A; symmetric_pattern = true) @test S_and_Sᵀ.colptr == A_and_Aᵀ.colptr @test S_and_Sᵀ.rowval == A_and_Aᵀ.rowval M = SparseMatrixCSC( - 2 * m, 2 * m, S_and_Sᵀ.colptr, S_and_Sᵀ.rowval, edge_to_index + 2 * m, + 2 * m, + S_and_Sᵀ.colptr, + S_and_Sᵀ.rowval, + edge_to_index, ) @test issymmetric(M) end @@ -91,9 +100,9 @@ end 0 0 0 1 1 1 1 0 ]) - bg = BipartiteGraph(A; symmetric_pattern=false) + bg = BipartiteGraph(A; symmetric_pattern = false) @test eltype(bg) == Int - @test_throws DimensionMismatch BipartiteGraph(A; symmetric_pattern=true) + @test_throws DimensionMismatch BipartiteGraph(A; symmetric_pattern = true) @test nb_vertices(bg, Val(1)) == 4 @test nb_vertices(bg, Val(2)) == 8 # neighbors of rows @@ -125,7 +134,7 @@ end 1 0 1 0 1 1 0 1 ]) - bg = BipartiteGraph(A; symmetric_pattern=true) + bg = BipartiteGraph(A; symmetric_pattern = true) @test nb_vertices(bg, Val(1)) == 4 @test nb_vertices(bg, Val(2)) == 4 # neighbors of rows and columns @@ -167,7 +176,7 @@ end; @test degree(g, 7) == 6 @test degree(g, 8) == 6 - g = AdjacencyGraph(transpose(A) * A; augmented_graph=true) + g = AdjacencyGraph(transpose(A) * A; augmented_graph = true) # wrong degree @test degree(g, 1) == 4 @test degree(g, 2) == 4 diff --git a/test/optimal.jl b/test/optimal.jl index 36bf91c6..af7257db 100644 --- a/test/optimal.jl +++ b/test/optimal.jl @@ -8,17 +8,17 @@ using HiGHS rng = StableRNG(0) -asymmetric_params = vcat( - [(10, 20, p) for p in (0.0:0.1:0.5)], [(20, 10, p) for p in (0.0:0.1:0.5)] -) +asymmetric_params = + vcat([(10, 20, p) for p in (0.0:0.1:0.5)], [(20, 10, p) for p in (0.0:0.1:0.5)]) algo = GreedyColoringAlgorithm() -optalgo = OptimalColoringAlgorithm(() -> MiniZinc.Optimizer{Float64}("highs"); silent=false) +optalgo = + OptimalColoringAlgorithm(() -> MiniZinc.Optimizer{Float64}("highs"); silent = false) # TODO: reactivate tests once https://github.com/jump-dev/MiniZinc.jl/issues/103 is fixed @testset "Column coloring" begin - problem = ColoringProblem(; structure=:nonsymmetric, partition=:column) + problem = ColoringProblem(; structure = :nonsymmetric, partition = :column) for (m, n, p) in asymmetric_params A = sprand(rng, m, n, p) result = coloring(A, problem, algo) @@ -27,7 +27,7 @@ optalgo = OptimalColoringAlgorithm(() -> MiniZinc.Optimizer{Float64}("highs"); s end @testset "Row coloring" begin - problem = ColoringProblem(; structure=:nonsymmetric, partition=:row) + problem = ColoringProblem(; structure = :nonsymmetric, partition = :row) for (m, n, p) in asymmetric_params A = sprand(rng, m, n, p) result = coloring(A, problem, algo) @@ -39,8 +39,8 @@ end A = sprand(rng, Bool, 100, 100, 0.1) optalgo_timelimit = OptimalColoringAlgorithm( optimizer_with_attributes(HiGHS.Optimizer, "time_limit" => 10.0); # 1 second - silent=false, - assert_solved=false, + silent = false, + assert_solved = false, ) @test_throws AssertionError coloring(A, ColoringProblem(), optalgo_timelimit) end diff --git a/test/order.jl b/test/order.jl index 9cae16f1..ec247371 100644 --- a/test/order.jl +++ b/test/order.jl @@ -81,7 +81,9 @@ end; for side in (1, 2) true_order = sort( - vertices(bg, Val(side)); by=v -> degree_dist2(bg, Val(side), v), rev=true + vertices(bg, Val(side)); + by = v -> degree_dist2(bg, Val(side), v), + rev = true, ) @test vertices(bg, Val(side), LargestFirst()) == true_order end @@ -90,13 +92,13 @@ end; @testset "Dynamic degree-based orders" begin @testset "$order" for order in [ SmallestLast(), - SmallestLast(; reproduce_colpack=true), + SmallestLast(; reproduce_colpack = true), IncidenceDegree(), - IncidenceDegree(; reproduce_colpack=true), + IncidenceDegree(; reproduce_colpack = true), DynamicLargestFirst(), - DynamicLargestFirst(; reproduce_colpack=true), + DynamicLargestFirst(; reproduce_colpack = true), DynamicDegreeBasedOrder{:forward,:high2low}(), - DynamicDegreeBasedOrder{:forward,:high2low}(; reproduce_colpack=true), + DynamicDegreeBasedOrder{:forward,:high2low}(; reproduce_colpack = true), ] @testset "AdjacencyGraph" begin for (n, p) in Iterators.product(20:20:100, 0.0:0.1:0.2) @@ -123,10 +125,9 @@ end; end; @testset "PerfectEliminationOrder" begin - problem = ColoringProblem(; structure=:symmetric, partition=:column) - substitution_algo = GreedyColoringAlgorithm( - PerfectEliminationOrder(); decompression=:substitution - ) + problem = ColoringProblem(; structure = :symmetric, partition = :column) + substitution_algo = + GreedyColoringAlgorithm(PerfectEliminationOrder(); decompression = :substitution) # band graphs for (n, m) in ((800, 80), (400, 40), (200, 20), (100, 10)) @@ -158,7 +159,7 @@ end algo = GreedyColoringAlgorithm(NaturalOrder()) better_algo = GreedyColoringAlgorithm((NaturalOrder(), LargestFirst())) @test ncolors(coloring(A, problem, better_algo)) < - ncolors(coloring(A, problem, algo)) + ncolors(coloring(A, problem, algo)) end @testset "Row coloring" begin A = [ @@ -171,7 +172,7 @@ end algo = GreedyColoringAlgorithm(NaturalOrder()) better_algo = GreedyColoringAlgorithm((NaturalOrder(), LargestFirst())) @test ncolors(coloring(A, problem, better_algo)) < - ncolors(coloring(A, problem, algo)) + ncolors(coloring(A, problem, algo)) end @testset "Star coloring" begin A = [ @@ -185,7 +186,7 @@ end algo = GreedyColoringAlgorithm(NaturalOrder()) better_algo = GreedyColoringAlgorithm((NaturalOrder(), LargestFirst())) @test ncolors(coloring(A, problem, better_algo)) < - ncolors(coloring(A, problem, algo)) + ncolors(coloring(A, problem, algo)) end @testset "Acyclic coloring" begin A = [ @@ -199,11 +200,10 @@ end ] problem = ColoringProblem{:symmetric,:column}() algo = GreedyColoringAlgorithm{:substitution}(NaturalOrder()) - better_algo = GreedyColoringAlgorithm{:substitution}(( - NaturalOrder(), LargestFirst() - )) + better_algo = + GreedyColoringAlgorithm{:substitution}((NaturalOrder(), LargestFirst())) @test ncolors(coloring(A, problem, better_algo)) < - ncolors(coloring(A, problem, algo)) + ncolors(coloring(A, problem, algo)) end @testset "Star bicoloring" begin A = [ @@ -217,7 +217,7 @@ end algo = GreedyColoringAlgorithm(NaturalOrder()) better_algo = GreedyColoringAlgorithm((NaturalOrder(), LargestFirst())) @test ncolors(coloring(A, problem, better_algo)) < - ncolors(coloring(A, problem, algo)) + ncolors(coloring(A, problem, algo)) end @testset "Acyclic bicoloring" begin A = [ @@ -233,10 +233,9 @@ end ] problem = ColoringProblem{:nonsymmetric,:bidirectional}() algo = GreedyColoringAlgorithm{:substitution}(NaturalOrder()) - better_algo = GreedyColoringAlgorithm{:substitution}(( - NaturalOrder(), LargestFirst() - )) + better_algo = + GreedyColoringAlgorithm{:substitution}((NaturalOrder(), LargestFirst())) @test ncolors(coloring(A, problem, better_algo)) < - ncolors(coloring(A, problem, algo)) + ncolors(coloring(A, problem, algo)) end end diff --git a/test/random.jl b/test/random.jl index 406dfea9..5320231c 100644 --- a/test/random.jl +++ b/test/random.jl @@ -20,8 +20,8 @@ symmetric_params = vcat( ) @testset "Column coloring & decompression" begin - problem = ColoringProblem(; structure=:nonsymmetric, partition=:column) - algo = GreedyColoringAlgorithm(; decompression=:direct) + problem = ColoringProblem(; structure = :nonsymmetric, partition = :column) + algo = GreedyColoringAlgorithm(; decompression = :direct) @testset "$((; m, n, p))" for (m, n, p) in asymmetric_params A0 = sprand(rng, m, n, p) color0 = column_coloring(A0, algo) @@ -35,8 +35,8 @@ symmetric_params = vcat( end; @testset "Row coloring & decompression" begin - problem = ColoringProblem(; structure=:nonsymmetric, partition=:row) - algo = GreedyColoringAlgorithm(; decompression=:direct) + problem = ColoringProblem(; structure = :nonsymmetric, partition = :row) + algo = GreedyColoringAlgorithm(; decompression = :direct) @testset "$((; m, n, p))" for (m, n, p) in asymmetric_params A0 = sprand(rng, m, n, p) color0 = row_coloring(A0, algo) @@ -50,10 +50,10 @@ end; end; @testset "Symmetric coloring & direct decompression" begin - problem = ColoringProblem(; structure=:symmetric, partition=:column) + problem = ColoringProblem(; structure = :symmetric, partition = :column) @testset for algo in ( - GreedyColoringAlgorithm(; postprocessing=false, decompression=:direct), - GreedyColoringAlgorithm(; postprocessing=true, decompression=:direct), + GreedyColoringAlgorithm(; postprocessing = false, decompression = :direct), + GreedyColoringAlgorithm(; postprocessing = true, decompression = :direct), ) @testset "$((; n, p))" for (n, p) in symmetric_params A0 = sparse(Symmetric(sprand(rng, n, n, p))) @@ -64,10 +64,10 @@ end; end; @testset "Symmetric coloring & substitution decompression" begin - problem = ColoringProblem(; structure=:symmetric, partition=:column) + problem = ColoringProblem(; structure = :symmetric, partition = :column) @testset for algo in ( - GreedyColoringAlgorithm(; postprocessing=false, decompression=:substitution), - GreedyColoringAlgorithm(; postprocessing=true, decompression=:substitution), + GreedyColoringAlgorithm(; postprocessing = false, decompression = :substitution), + GreedyColoringAlgorithm(; postprocessing = true, decompression = :substitution), ) @testset "$((; n, p))" for (n, p) in symmetric_params A0 = sparse(Symmetric(sprand(rng, n, n, p))) @@ -78,13 +78,17 @@ end; end; @testset "Bicoloring & direct decompression" begin - problem = ColoringProblem(; structure=:nonsymmetric, partition=:bidirectional) + problem = ColoringProblem(; structure = :nonsymmetric, partition = :bidirectional) @testset for algo in ( GreedyColoringAlgorithm( - RandomOrder(StableRNG(0), 0); postprocessing=false, decompression=:direct + RandomOrder(StableRNG(0), 0); + postprocessing = false, + decompression = :direct, ), GreedyColoringAlgorithm( - RandomOrder(StableRNG(0), 0); postprocessing=true, decompression=:direct + RandomOrder(StableRNG(0), 0); + postprocessing = true, + decompression = :direct, ), ) @testset "$((; m, n, p))" for (m, n, p) in asymmetric_params @@ -99,13 +103,17 @@ end; end; @testset "Bicoloring & substitution decompression" begin - problem = ColoringProblem(; structure=:nonsymmetric, partition=:bidirectional) + problem = ColoringProblem(; structure = :nonsymmetric, partition = :bidirectional) @testset for algo in ( GreedyColoringAlgorithm( - RandomOrder(StableRNG(0), 0); postprocessing=false, decompression=:substitution + RandomOrder(StableRNG(0), 0); + postprocessing = false, + decompression = :substitution, ), GreedyColoringAlgorithm( - RandomOrder(StableRNG(0), 0); postprocessing=true, decompression=:substitution + RandomOrder(StableRNG(0), 0); + postprocessing = true, + decompression = :substitution, ), ) @testset "$((; m, n, p))" for (m, n, p) in asymmetric_params diff --git a/test/result.jl b/test/result.jl index 49344aab..bca58417 100644 --- a/test/result.jl +++ b/test/result.jl @@ -3,7 +3,7 @@ using SparseMatrixColorings: group_by_color, UnsupportedDecompressionError using Test @testset "Group by color" begin - for n in 10 .^ (2, 3, 4), cmax in (1, 2, 10, 100), iteration in 1:10 + for n in 10 .^ (2, 3, 4), cmax in (1, 2, 10, 100), iteration = 1:10 color = rand(1:cmax, n) group = group_by_color(color) @test length(group) == maximum(color) @@ -24,11 +24,11 @@ end A = zeros(Bool, 10, 10) color = zeros(Int, 10) problem = ColoringProblem{:nonsymmetric,:column}() - algo = ConstantColoringAlgorithm(A, color; partition=:column) + algo = ConstantColoringAlgorithm(A, color; partition = :column) B = compress(A, coloring(A, problem, algo)) @test size(B, 2) == 0 problem = ColoringProblem{:nonsymmetric,:row}() - algo = ConstantColoringAlgorithm(A, color; partition=:row) + algo = ConstantColoringAlgorithm(A, color; partition = :row) B = compress(A, coloring(A, problem, algo)) @test size(B, 1) == 0 end diff --git a/test/runtests.jl b/test/runtests.jl index ec679d4e..e96a77d4 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -18,11 +18,12 @@ include("utils.jl") else @testset verbose = true "Code quality" begin @testset "Aqua" begin - Aqua.test_all(SparseMatrixColorings; undocumented_names=true) + Aqua.test_all(SparseMatrixColorings; undocumented_names = true) end @testset "JET" begin JET.test_package( - SparseMatrixColorings; target_modules=(SparseMatrixColorings,) + SparseMatrixColorings; + target_modules = (SparseMatrixColorings,), ) end @testset "Doctests" begin diff --git a/test/show_colors.jl b/test/show_colors.jl index cad07088..f466c143 100644 --- a/test/show_colors.jl +++ b/test/show_colors.jl @@ -10,10 +10,10 @@ A = sparse([ 0 1 0 0 1 0 0 1 1 0 0 0 ]); -algo = GreedyColoringAlgorithm(; decompression=:direct) +algo = GreedyColoringAlgorithm(; decompression = :direct) @testset "$partition" for partition in (:column, :row, :bidirectional) - problem = ColoringProblem(; structure=:nonsymmetric, partition=partition) + problem = ColoringProblem(; structure = :nonsymmetric, partition = partition) result = coloring(A, problem, algo) if partition != :bidirectional @@ -26,14 +26,14 @@ algo = GreedyColoringAlgorithm(; decompression=:direct) @test B_img isa Matrix{<:Colorant} scale = 3 - A_img, B_img = show_colors(result; scale=scale) + A_img, B_img = show_colors(result; scale = scale) @test size(A_img) == size(A) .* scale @test size(B_img) == size(B) .* scale @test A_img isa Matrix{<:Colorant} pad = 2 border = 3 - A_img, B_img = show_colors(result; scale=scale, border=border, pad=pad) + A_img, B_img = show_colors(result; scale = scale, border = border, pad = pad) @test size(A_img) == size(A) .* (scale + 2border + pad) .+ pad @test size(B_img) == size(B) .* (scale + 2border + pad) .+ pad @test A_img isa Matrix{<:Colorant} @@ -44,7 +44,7 @@ algo = GreedyColoringAlgorithm(; decompression=:direct) @test size(A_img) == size(A) @test A_img isa Matrix{<:Colorant} - A_img, _ = show_colors(result; colorscheme, warn=false) + A_img, _ = show_colors(result; colorscheme, warn = false) @test size(A_img) == size(A) @test A_img isa Matrix{<:Colorant} end @@ -52,7 +52,7 @@ algo = GreedyColoringAlgorithm(; decompression=:direct) Br, Bc = compress(A, result) scale = 3 - Arc_img, Ar_img, Ac_img, Br_img, Bc_img = show_colors(result; scale=scale) + Arc_img, Ar_img, Ac_img, Br_img, Bc_img = show_colors(result; scale = scale) @test size(Arc_img) == size(A) .* scale @test size(Ar_img) == size(A) .* scale @test size(Ac_img) == size(A) .* scale @@ -67,18 +67,18 @@ algo = GreedyColoringAlgorithm(; decompression=:direct) end @testset "Errors" begin - problem = ColoringProblem(; structure=:nonsymmetric, partition=:row) + problem = ColoringProblem(; structure = :nonsymmetric, partition = :row) result = coloring(A, problem, algo) @testset "scale too small" begin - @test_throws ArgumentError show_colors(result; scale=-24) - @test_throws ArgumentError show_colors(result; scale=0) + @test_throws ArgumentError show_colors(result; scale = -24) + @test_throws ArgumentError show_colors(result; scale = 0) end @testset "pad too small" begin - @test_throws ArgumentError show_colors(result; pad=-1) - @test_nowarn show_colors(result; pad=0) + @test_throws ArgumentError show_colors(result; pad = -1) + @test_nowarn show_colors(result; pad = 0) end @testset "border too small" begin - @test_throws ArgumentError show_colors(result; border=-1) - @test_nowarn show_colors(result; border=0) + @test_throws ArgumentError show_colors(result; border = -1) + @test_nowarn show_colors(result; border = 0) end end diff --git a/test/small.jl b/test/small.jl index 2e12372c..930a8f31 100644 --- a/test/small.jl +++ b/test/small.jl @@ -12,8 +12,8 @@ using StableRNGs using Test @testset "Column coloring & decompression" begin - problem = ColoringProblem(; structure=:nonsymmetric, partition=:column) - algo = GreedyColoringAlgorithm(; decompression=:direct) + problem = ColoringProblem(; structure = :nonsymmetric, partition = :column) + algo = GreedyColoringAlgorithm(; decompression = :direct) A0 = sparse([ 1 0 2 0 3 4 @@ -27,12 +27,12 @@ using Test color0 = [1, 1, 2] @test structurally_orthogonal_columns(A0, color0) @test directly_recoverable_columns(A0, color0) - test_coloring_decompression(A0, problem, algo; B0, color0, test_fast=true) + test_coloring_decompression(A0, problem, algo; B0, color0, test_fast = true) end; @testset "Row coloring & decompression" begin - problem = ColoringProblem(; structure=:nonsymmetric, partition=:row) - algo = GreedyColoringAlgorithm(; decompression=:direct) + problem = ColoringProblem(; structure = :nonsymmetric, partition = :row) + algo = GreedyColoringAlgorithm(; decompression = :direct) A0 = sparse([ 1 0 3 0 2 0 @@ -45,19 +45,19 @@ end; color0 = [1, 1, 2] @test structurally_orthogonal_columns(transpose(A0), color0) @test directly_recoverable_columns(transpose(A0), color0) - test_coloring_decompression(A0, problem, algo; B0, color0, test_fast=true) + test_coloring_decompression(A0, problem, algo; B0, color0, test_fast = true) end; @testset "Symmetric coloring & direct decompression" begin - problem = ColoringProblem(; structure=:symmetric, partition=:column) - algo = GreedyColoringAlgorithm(; decompression=:direct) + problem = ColoringProblem(; structure = :symmetric, partition = :column) + algo = GreedyColoringAlgorithm(; decompression = :direct) @testset "Fig 4.1 from 'What color is your Jacobian'" begin example = what_fig_41() A0, B0, color0 = example.A, example.B, example.color @test symmetrically_orthogonal_columns(A0, color0) @test directly_recoverable_columns(A0, color0) - test_coloring_decompression(A0, problem, algo; B0, color0, test_fast=true) + test_coloring_decompression(A0, problem, algo; B0, color0, test_fast = true) end @testset "Fig 1 from 'Efficient computation of sparse hessians using coloring and AD'" begin @@ -65,52 +65,54 @@ end; A0, B0, color0 = example.A, example.B, example.color @test symmetrically_orthogonal_columns(A0, color0) @test directly_recoverable_columns(A0, color0) - test_coloring_decompression(A0, problem, algo; B0, color0, test_fast=true) + test_coloring_decompression(A0, problem, algo; B0, color0, test_fast = true) end end; @testset "Symmetric coloring & substitution decompression" begin - problem = ColoringProblem(; structure=:symmetric, partition=:column) - algo = GreedyColoringAlgorithm(; decompression=:substitution) + problem = ColoringProblem(; structure = :symmetric, partition = :column) + algo = GreedyColoringAlgorithm(; decompression = :substitution) @testset "Fig 6.1 from 'What color is your Jacobian'" begin example = what_fig_61() A0, B0, color0 = example.A, example.B, example.color # our coloring doesn't give the color0 from the example, but that's okay - test_coloring_decompression(A0, problem, algo; test_fast=true) + test_coloring_decompression(A0, problem, algo; test_fast = true) end @testset "Fig 4 from 'Efficient computation of sparse hessians using coloring and AD'" begin example = efficient_fig_4() A0, B0, color0 = example.A, example.B, example.color - test_coloring_decompression(A0, problem, algo; B0, color0, test_fast=true) + test_coloring_decompression(A0, problem, algo; B0, color0, test_fast = true) end end; @testset "Bidirectional coloring" begin - problem = ColoringProblem(; structure=:nonsymmetric, partition=:bidirectional) + problem = ColoringProblem(; structure = :nonsymmetric, partition = :bidirectional) order = RandomOrder(StableRNG(0), 0) @testset "Anti-diagonal" begin A = sparse([0 0 0 1; 0 0 1 0; 0 1 0 0; 1 0 0 0]) - result = coloring( - A, problem, GreedyColoringAlgorithm{:direct}(; postprocessing=false) - ) + result = + coloring(A, problem, GreedyColoringAlgorithm{:direct}(; postprocessing = false)) @test ncolors(result) == 2 - result = coloring( - A, problem, GreedyColoringAlgorithm{:direct}(; postprocessing=true) - ) + result = + coloring(A, problem, GreedyColoringAlgorithm{:direct}(; postprocessing = true)) @test ncolors(result) == 1 result = coloring( - A, problem, GreedyColoringAlgorithm{:substitution}(; postprocessing=false) + A, + problem, + GreedyColoringAlgorithm{:substitution}(; postprocessing = false), ) @test ncolors(result) == 2 result = coloring( - A, problem, GreedyColoringAlgorithm{:substitution}(; postprocessing=true) + A, + problem, + GreedyColoringAlgorithm{:substitution}(; postprocessing = true), ) @test ncolors(result) == 1 end @@ -118,13 +120,14 @@ end; @testset "Triangle" begin A = sparse([1 1 0; 0 1 1; 1 0 1]) - result = coloring( - A, problem, GreedyColoringAlgorithm{:direct}(; postprocessing=true) - ) + result = + coloring(A, problem, GreedyColoringAlgorithm{:direct}(; postprocessing = true)) @test ncolors(result) == 3 result = coloring( - A, problem, GreedyColoringAlgorithm{:substitution}(; postprocessing=true) + A, + problem, + GreedyColoringAlgorithm{:substitution}(; postprocessing = true), ) @test ncolors(result) == 3 end @@ -137,20 +140,28 @@ end; A[end, :] .= 1 result = coloring( - A, problem, GreedyColoringAlgorithm{:direct}(order; postprocessing=false) + A, + problem, + GreedyColoringAlgorithm{:direct}(order; postprocessing = false), ) @test ncolors(result) == 6 # two more than necessary result = coloring( - A, problem, GreedyColoringAlgorithm{:direct}(order; postprocessing=true) + A, + problem, + GreedyColoringAlgorithm{:direct}(order; postprocessing = true), ) @test ncolors(result) == 4 # optimal number result = coloring( - A, problem, GreedyColoringAlgorithm{:substitution}(order; postprocessing=false) + A, + problem, + GreedyColoringAlgorithm{:substitution}(order; postprocessing = false), ) @test ncolors(result) == 6 # two more than necessary result = coloring( - A, problem, GreedyColoringAlgorithm{:substitution}(order; postprocessing=true) + A, + problem, + GreedyColoringAlgorithm{:substitution}(order; postprocessing = true), ) @test ncolors(result) == 4 # optimal number end @@ -164,35 +175,39 @@ end; end result = coloring( - A, problem, GreedyColoringAlgorithm{:direct}(order; postprocessing=true) + A, + problem, + GreedyColoringAlgorithm{:direct}(order; postprocessing = true), ) @test ncolors(coloring(A, problem, GreedyColoringAlgorithm{:substitution}(order))) < - ncolors(coloring(A, problem, GreedyColoringAlgorithm{:direct}(order))) + ncolors(coloring(A, problem, GreedyColoringAlgorithm{:direct}(order))) @test ncolors( coloring( A, problem, - GreedyColoringAlgorithm{:substitution}(order; postprocessing=true), + GreedyColoringAlgorithm{:substitution}(order; postprocessing = true), ), ) < ncolors( coloring( - A, problem, GreedyColoringAlgorithm{:direct}(order; postprocessing=true) + A, + problem, + GreedyColoringAlgorithm{:direct}(order; postprocessing = true), ), ) test_bicoloring_decompression( A, problem, - GreedyColoringAlgorithm{:direct}(order; postprocessing=true); - test_fast=true, + GreedyColoringAlgorithm{:direct}(order; postprocessing = true); + test_fast = true, ) test_bicoloring_decompression( A, problem, - GreedyColoringAlgorithm{:substitution}(order; postprocessing=true); - test_fast=true, + GreedyColoringAlgorithm{:substitution}(order; postprocessing = true); + test_fast = true, ) end end; diff --git a/test/structured.jl b/test/structured.jl index 0d2a7564..0f0cb767 100644 --- a/test/structured.jl +++ b/test/structured.jl @@ -30,14 +30,14 @@ end; end; @testset "BandedMatrices" begin - @testset for (m, n) in [(10, 20), (20, 10)], l in 0:5, u in 0:5 + @testset for (m, n) in [(10, 20), (20, 10)], l = 0:5, u = 0:5 A = brand(m, n, l, u) test_structured_coloring_decompression(A) end end; @testset "BlockBandedMatrices" begin - for (mb, nb) in [(10, 20), (20, 10)], lb in 0:3, ub in 0:3, _ in 1:10 + for (mb, nb) in [(10, 20), (20, 10)], lb = 0:3, ub = 0:3, _ = 1:10 rows = rand(1:5, mb) cols = rand(1:5, nb) A = BlockBandedMatrix{Float64}(rand(sum(rows), sum(cols)), rows, cols, (lb, ub)) @@ -46,13 +46,17 @@ end; end; @testset "BandedBlockBandedMatrices" begin - for (mb, nb) in [(10, 20), (20, 10)], lb in 0:3, ub in 0:3, _ in 1:10 + for (mb, nb) in [(10, 20), (20, 10)], lb = 0:3, ub = 0:3, _ = 1:10 rows = rand(5:10, mb) cols = rand(5:10, nb) λ = rand(0:5) μ = rand(0:5) A = BandedBlockBandedMatrix{Float64}( - rand(sum(rows), sum(cols)), rows, cols, (lb, ub), (λ, μ) + rand(sum(rows), sum(cols)), + rows, + cols, + (lb, ub), + (λ, μ), ) test_structured_coloring_decompression(A) end diff --git a/test/suitesparse.jl b/test/suitesparse.jl index d69d8a9f..73c3c3cd 100644 --- a/test/suitesparse.jl +++ b/test/suitesparse.jl @@ -22,9 +22,9 @@ nbunique(x) = length(unique(x)) _N(args...) = vertices(args..., NaturalOrder()) _LF(args...) = vertices(args..., LargestFirst()) -_SL(args...) = vertices(args..., SmallestLast(; reproduce_colpack=true)) -_ID(args...) = vertices(args..., IncidenceDegree(; reproduce_colpack=true)) -_DLF(args...) = vertices(args..., DynamicLargestFirst(; reproduce_colpack=true)) +_SL(args...) = vertices(args..., SmallestLast(; reproduce_colpack = true)) +_ID(args...) = vertices(args..., IncidenceDegree(; reproduce_colpack = true)) +_DLF(args...) = vertices(args..., DynamicLargestFirst(; reproduce_colpack = true)) ## Distance-2 coloring @@ -32,9 +32,8 @@ _DLF(args...) = vertices(args..., DynamicLargestFirst(; reproduce_colpack=true)) Comparison with Tables VI and VII of the ColPack paper =# -colpack_table_6_7 = CSV.read( - joinpath(@__DIR__, "reference", "colpack_table_6_7.csv"), DataFrame -) +colpack_table_6_7 = + CSV.read(joinpath(@__DIR__, "reference", "colpack_table_6_7.csv"), DataFrame) @testset verbose = true "Distance-2 coloring (ColPack paper)" begin @testset "$(row[:name])" for row in eachrow(colpack_table_6_7) @@ -50,16 +49,16 @@ colpack_table_6_7 = CSV.read( end @testset "Natural" begin @test nbunique(partial_distance2_coloring(bg, Val(1), _N(bg, Val(1)))) == - row[:N1] + row[:N1] @test nbunique(partial_distance2_coloring(bg, Val(2), _N(bg, Val(2)))) == - row[:N2] + row[:N2] end yield() @testset "LargestFirst" begin @test nbunique(partial_distance2_coloring(bg, Val(1), _LF(bg, Val(1)))) == - row[:LF1] + row[:LF1] @test nbunique(partial_distance2_coloring(bg, Val(2), _LF(bg, Val(2)))) == - row[:LF2] + row[:LF2] end yield() if row[:name] == "af23560" @@ -72,23 +71,23 @@ colpack_table_6_7 = CSV.read( end @testset "SmallestLast" begin @test nbunique(partial_distance2_coloring(bg, Val(1), _SL(bg, Val(1)))) == - row[:SL1] + row[:SL1] @test nbunique(partial_distance2_coloring(bg, Val(2), _SL(bg, Val(2)))) == - row[:SL2] + row[:SL2] end yield() @testset "IncidenceDegree" begin @test nbunique(partial_distance2_coloring(bg, Val(1), _ID(bg, Val(1)))) == - row[:ID1] + row[:ID1] @test nbunique(partial_distance2_coloring(bg, Val(2), _ID(bg, Val(2)))) == - row[:ID2] + row[:ID2] end yield() @testset "DynamicLargestFirst" begin @test nbunique(partial_distance2_coloring(bg, Val(1), _DLF(bg, Val(1)))) == - row[:DLF1] + row[:DLF1] @test nbunique(partial_distance2_coloring(bg, Val(2), _DLF(bg, Val(2)))) == - row[:DLF2] + row[:DLF2] end yield() end @@ -98,9 +97,8 @@ end; Comparison with Tables 3.1 and 3.2 of "What color is your Jacobian?" =# -what_table_31_32 = CSV.read( - joinpath(@__DIR__, "reference", "what_table_31_32.csv"), DataFrame -) +what_table_31_32 = + CSV.read(joinpath(@__DIR__, "reference", "what_table_31_32.csv"), DataFrame) @testset "Distance-2 coloring (survey paper)" begin @testset "$(row[:name])" for row in eachrow(what_table_31_32) @@ -128,9 +126,8 @@ end; ## Star coloring -what_table_41_42 = CSV.read( - joinpath(@__DIR__, "reference", "what_table_41_42.csv"), DataFrame -) +what_table_41_42 = + CSV.read(joinpath(@__DIR__, "reference", "what_table_41_42.csv"), DataFrame) @testset "Star coloring (survey paper)" begin @testset "$(row[:name])" for row in eachrow(what_table_41_42) diff --git a/test/theory.jl b/test/theory.jl index ab4308da..71115ace 100644 --- a/test/theory.jl +++ b/test/theory.jl @@ -10,14 +10,14 @@ Per the recovery paper "Efficient computation of sparse Hessians using Coloring - star coloring uses 2⌊ρ/2⌋+1 colors =# -problem = ColoringProblem(; structure=:symmetric, partition=:column) +problem = ColoringProblem(; structure = :symmetric, partition = :column) function banded_matrix(n::Integer, ρ::Integer) - return spdiagm([k => ones(Bool, n - abs(k)) for k in (-(ρ ÷ 2)):(ρ ÷ 2)]...) + return spdiagm([k => ones(Bool, n - abs(k)) for k = (-(ρ÷2)):(ρ÷2)]...) end @testset "Star coloring" begin - algo = GreedyColoringAlgorithm(; decompression=:direct) + algo = GreedyColoringAlgorithm(; decompression = :direct) for n in [5, 10, 20] .* 1000 S = banded_matrix(n, 10) direct_result = coloring(S, problem, algo) @@ -30,7 +30,7 @@ end end @testset "Acyclic coloring" begin - algo = GreedyColoringAlgorithm(; decompression=:substitution) + algo = GreedyColoringAlgorithm(; decompression = :substitution) for n in [5, 10, 20] .* 1000 S = banded_matrix(n, 10) substitution_result = coloring(S, problem, algo) diff --git a/test/type_stability.jl b/test/type_stability.jl index 3c6f9f02..8872905d 100644 --- a/test/type_stability.jl +++ b/test/type_stability.jl @@ -25,7 +25,9 @@ rng = StableRNG(63) end @testset "$structure - $partition - $decompression" for ( - structure, partition, decompression + structure, + partition, + decompression, ) in [ (:nonsymmetric, :column, :direct), (:nonsymmetric, :row, :direct), @@ -88,7 +90,9 @@ end; A0 = sparse(Symmetric(sprand(rng, n, n, 5 / n))) @testset "$structure - $partition - $decompression" for ( - structure, partition, decompression + structure, + partition, + decompression, ) in [ (:nonsymmetric, :column, :direct), (:nonsymmetric, :row, :direct), @@ -102,7 +106,7 @@ end; A0, ColoringProblem(; structure, partition), GreedyColoringAlgorithm(; decompression); - decompression_eltype=eltype(A), + decompression_eltype = eltype(A), ) if partition == :bidirectional Br, Bc = compress(A, result) @@ -132,7 +136,10 @@ end; B[1, :] end @test_opt decompress_single_color!( - respectful_similar(A), b, 1, result + respectful_similar(A), + b, + 1, + result, ) end end @@ -144,7 +151,11 @@ end; @testset "Single-color triangle decompression" begin if structure == :symmetric && decompression == :direct @test_opt decompress_single_color!( - respectful_similar(triu(A)), B[:, 1], 1, result, :U + respectful_similar(triu(A)), + B[:, 1], + 1, + result, + :U, ) end end @@ -181,7 +192,9 @@ end; sparse(Symmetric(sprand(rng, Float32, 100, 100, 0.1))), ) @testset "$structure - $partition - $decompression" for ( - structure, partition, decompression + structure, + partition, + decompression, ) in [ (:nonsymmetric, :column, :direct), (:nonsymmetric, :row, :direct), diff --git a/test/utils.jl b/test/utils.jl index 77c88610..1d8d461f 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -19,17 +19,21 @@ using SparseMatrixColorings: using Test const _ALL_ORDERS = ( - NaturalOrder(), LargestFirst(), SmallestLast(), IncidenceDegree(), DynamicLargestFirst() + NaturalOrder(), + LargestFirst(), + SmallestLast(), + IncidenceDegree(), + DynamicLargestFirst(), ) function test_coloring_decompression( A0::AbstractMatrix, problem::ColoringProblem{structure,partition}, algo::GreedyColoringAlgorithm{decompression}; - B0=nothing, - color0=nothing, - test_fast=false, - gpu=false, + B0 = nothing, + color0 = nothing, + test_fast = false, + gpu = false, ) where {structure,partition,decompression} color_vec = Vector{Int}[] @testset "$(typeof(A))" for A in matrix_versions(A0) @@ -37,10 +41,14 @@ function test_coloring_decompression( if structure == :nonsymmetric && issymmetric(A) result = coloring( - A, problem, algo; decompression_eltype=Float32, symmetric_pattern=true + A, + problem, + algo; + decompression_eltype = Float32, + symmetric_pattern = true, ) else - result = coloring(A, problem, algo; decompression_eltype=Float64) + result = coloring(A, problem, algo; decompression_eltype = Float64) end color = if partition == :column column_colors(result) @@ -58,7 +66,7 @@ function test_coloring_decompression( @test ncolors(result) == size(B, 1) end if test_fast - @test color == fast_coloring(A, problem, algo; symmetric_pattern=false) + @test color == fast_coloring(A, problem, algo; symmetric_pattern = false) end end @@ -172,7 +180,9 @@ function test_coloring_decompression( @test sparsity_pattern(result) === A # identity of objects @test decompress(float.(B), linresult) ≈ A0 @test decompress!( - respectful_similar(A, float(eltype(B))), float.(B), linresult + respectful_similar(A, float(eltype(B))), + float.(B), + linresult, ) ≈ A0 end end @@ -187,9 +197,8 @@ function test_coloring_decompression( @testset "More orders is better" begin more_orders = (algo.orders..., _ALL_ORDERS...) - better_algo = GreedyColoringAlgorithm{decompression}( - more_orders; algo.postprocessing - ) + better_algo = + GreedyColoringAlgorithm{decompression}(more_orders; algo.postprocessing) all_algos = [ GreedyColoringAlgorithm{decompression}(order; algo.postprocessing) for order in more_orders @@ -206,16 +215,20 @@ function test_bicoloring_decompression( A0::AbstractMatrix, problem::ColoringProblem{:nonsymmetric,:bidirectional}, algo::GreedyColoringAlgorithm{decompression}; - test_fast=false, + test_fast = false, ) where {decompression} @testset "$(typeof(A))" for A in matrix_versions(A0) yield() if issymmetric(A) result = coloring( - A, problem, algo; decompression_eltype=Float32, symmetric_pattern=true + A, + problem, + algo; + decompression_eltype = Float32, + symmetric_pattern = true, ) else - result = coloring(A, problem, algo; decompression_eltype=Float64) + result = coloring(A, problem, algo; decompression_eltype = Float64) end Br, Bc = compress(A, result) row_color, column_color = row_colors(result), column_colors(result) @@ -226,7 +239,7 @@ function test_bicoloring_decompression( @test ncolors(result) == size(Br, 1) + size(Bc, 2) if test_fast @test (row_color, column_color) == - fast_coloring(A, problem, algo; symmetric_pattern=false) + fast_coloring(A, problem, algo; symmetric_pattern = false) end end @@ -234,10 +247,16 @@ function test_bicoloring_decompression( @test decompress(Br, Bc, result) ≈ A0 @test decompress(Br, Bc, result) ≈ A0 # check result wasn't modified @test decompress!( - respectful_similar(A, promote_eltype(Br, Bc)), Br, Bc, result + respectful_similar(A, promote_eltype(Br, Bc)), + Br, + Bc, + result, ) ≈ A0 @test decompress!( - respectful_similar(A, promote_eltype(Br, Bc)), Br, Bc, result + respectful_similar(A, promote_eltype(Br, Bc)), + Br, + Bc, + result, ) ≈ A0 end @@ -251,7 +270,10 @@ function test_bicoloring_decompression( @testset "Substitutable" begin rank_nonzeros = rank_nonzeros_from_trees(result) @test substitutable_bidirectional( - A0, rank_nonzeros, row_color, column_color + A0, + rank_nonzeros, + row_color, + column_color, ) end end @@ -259,9 +281,8 @@ function test_bicoloring_decompression( @testset "More orders is better" begin more_orders = (algo.orders..., _ALL_ORDERS...) - better_algo = GreedyColoringAlgorithm{decompression}( - more_orders; algo.postprocessing - ) + better_algo = + GreedyColoringAlgorithm{decompression}(more_orders; algo.postprocessing) all_algos = [ GreedyColoringAlgorithm{decompression}(order; algo.postprocessing) for order in more_orders @@ -275,8 +296,8 @@ function test_bicoloring_decompression( end function test_structured_coloring_decompression(A::AbstractMatrix) - column_problem = ColoringProblem(; structure=:nonsymmetric, partition=:column) - row_problem = ColoringProblem(; structure=:nonsymmetric, partition=:row) + column_problem = ColoringProblem(; structure = :nonsymmetric, partition = :column) + row_problem = ColoringProblem(; structure = :nonsymmetric, partition = :row) algo = GreedyColoringAlgorithm() # Column