diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 67d993b5..169ddffd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,5 @@ repos: - repo: https://github.com/JuliaEditorSupport/JuliaFormatter.jl - rev: 0935890389c9fbc45f4ee150064c0abe5340b6a9 # v2.4.0 + rev: 2864ae303b091a1a310d8baaf608a5deadf221b6 # v2.8.4 hooks: - id: "jlfmt" \ No newline at end of file diff --git a/benchmark/benchmarks.jl b/benchmark/benchmarks.jl index 89bfc2f5..e77fad58 100644 --- a/benchmark/benchmarks.jl +++ b/benchmark/benchmarks.jl @@ -21,15 +21,13 @@ 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 = 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 in 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 @@ -59,7 +57,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 = 1:nb_samples] + As = [sparse(Symmetric(sprand(StableRNG(i), Bool, n, n, p))) for i in 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 79d4aa76..80d2a23d 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -4,28 +4,24 @@ 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 0894f2fa..ed33eece 100644 --- a/ext/SparseMatrixColoringsCUDAExt.jl +++ b/ext/SparseMatrixColoringsCUDAExt.jl @@ -8,31 +8,22 @@ 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 @@ -44,47 +35,33 @@ 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 @@ -96,14 +73,9 @@ 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 @@ -112,9 +84,7 @@ 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)) @@ -122,9 +92,7 @@ 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)) @@ -136,12 +104,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 @@ -154,12 +122,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 7f42031e..5dde067f 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 ae953d7b..7f844e89 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,14 +53,15 @@ 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) @@ -85,7 +86,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 @@ -270,8 +271,9 @@ function show_colors!( A_ccolor_indices = mod1.(column_colors(res), length(colorscheme)) 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)) + B_rcolor_indices = 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 1bf8fdb9..37574e73 100644 --- a/ext/SparseMatrixColoringsGPUArraysExt.jl +++ b/ext/SparseMatrixColoringsGPUArraysExt.jl @@ -9,8 +9,7 @@ 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) @@ -19,8 +18,7 @@ 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 d22ef31f..7e5c7ff3 100644 --- a/ext/SparseMatrixColoringsJuMPExt.jl +++ b/ext/SparseMatrixColoringsJuMPExt.jl @@ -21,15 +21,15 @@ 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)) model = Model(optimizer) silent && set_silent(model) # one variable per vertex to color, removing some renumbering symmetries - @variable(model, 1 <= color[i=1:n] <= i, Int) + @variable(model, 1 <= color[i = 1:n] <= i, Int) # one variable to count the number of distinct colors @variable(model, ncolors, Int) @constraint(model, [ncolors; color] in MOI.CountDistinct(n + 1)) @@ -66,22 +66,14 @@ 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 7792a898..7c464433 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 cfb73271..3ad11133 100644 --- a/src/check.jl +++ b/src/check.jl @@ -1,7 +1,5 @@ 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 @@ -17,7 +15,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 @@ -54,9 +52,7 @@ 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 @@ -64,7 +60,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 @@ -102,9 +98,7 @@ 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) @@ -116,14 +110,7 @@ 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 @@ -152,7 +139,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 @@ -255,9 +242,7 @@ 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 @@ -266,8 +251,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 + return dropdims(sum(A[:, g]; dims=2); dims=2) end end A_unique = Set(unique(A)) @@ -311,7 +296,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) @@ -323,15 +308,7 @@ 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 @@ -362,7 +339,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 @@ -373,15 +350,7 @@ 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 @@ -487,7 +456,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 @@ -515,7 +484,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 @@ -561,10 +530,10 @@ function rank_nonzeros_from_trees(result::TreeSetColoringResult) counter += 1 rank_nonzeros[i, i] = counter end - for k = 1:nt + for k in 1:nt first = tree_edge_indices[k] - last = tree_edge_indices[k+1] - 1 - for pos = first:last + last = tree_edge_indices[k + 1] - 1 + for pos in first:last (i, j) = reverse_bfs_orders[pos] counter += 1 rank_nonzeros[i, j] = counter @@ -583,21 +552,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 = 1:nt + for k in 1:nt first = tree_edge_indices[k] - last = tree_edge_indices[k+1] - 1 - for pos = first:last + last = tree_edge_indices[k + 1] - 1 + for pos in 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 d01dc804..699dbc64 100644 --- a/src/coloring.jl +++ b/src/coloring.jl @@ -27,17 +27,12 @@ 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 @@ -48,7 +43,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 @@ -115,7 +110,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) @@ -278,9 +273,7 @@ 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) @@ -469,7 +462,7 @@ function TreeSet( nr = 0 # determine the number of edges for each tree and map each root to a tree index - for index_edge = 1:ne + for index_edge in 1:ne root = find_root!(forest, index_edge) # create a mapping between roots and tree indices @@ -482,7 +475,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 @@ -509,10 +502,10 @@ function TreeSet( vertex_position[1] = zero(T) neighbor_position[1] = zero(T) end - for k = 2:nt + for k in 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 @@ -550,21 +543,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 = 2:(nt+1) - tree_edge_indices[k] += tree_edge_indices[k-1] + for k in 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 = 2:(ne+nt+1) - tree_neighbor_indices[k] += tree_neighbor_indices[k-1] + for k in 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 @@ -592,7 +585,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 = 1:nt + for k in 1:nt # Initialize the queue to store the leaves queue_start = 1 queue_end = 0 @@ -601,13 +594,14 @@ 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 = first_vertex:last_vertex + for index_vertex in 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 @@ -621,7 +615,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 @@ -640,10 +634,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 = first_neighbor:last_neighbor + for index_neighbor in 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 c2f7ad75..56bf4101 100644 --- a/src/constant.jl +++ b/src/constant.jl @@ -75,20 +75,17 @@ 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 @@ -96,8 +93,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 @@ -114,24 +111,21 @@ 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 ad796c13..2dcf1847 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 + return 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 + return dropdims(sum(A[:, g]; dims=2); dims=2) end end return B @@ -64,44 +64,43 @@ 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 + return 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 + return 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 + return 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 + return 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 + return 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 + return dropdims(sum(A[:, g]; dims=2); dims=2) end end return Br, Bc @@ -356,10 +355,7 @@ 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 @@ -386,10 +382,7 @@ 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 @@ -424,10 +417,7 @@ 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 @@ -456,10 +446,7 @@ 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 @@ -483,7 +470,7 @@ function decompress_single_color!( b::AbstractVector, c::Integer, result::StarSetColoringResult, - uplo::Symbol = :F, + uplo::Symbol=:F, ) (; ag, compressed_indices, group) = result (; S) = ag @@ -516,10 +503,7 @@ 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 @@ -548,10 +532,7 @@ 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 @@ -574,13 +555,13 @@ function decompress!( end # Recover the off-diagonal coefficients of A - for k = 1:nt + for k in 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 = first:last + for pos in first:last (vertex, _) = reverse_bfs_orders[pos] buffer_right_type[vertex] = zero(R) end @@ -588,7 +569,7 @@ function decompress!( (_, root) = reverse_bfs_orders[last] buffer_right_type[root] = zero(R) - for pos = first:last + for pos in 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 @@ -623,7 +604,7 @@ function decompress_csc!( A_colptr::AbstractVector{<:Integer}, B::AbstractMatrix{R}, result::TreeSetColoringResult, - uplo::Symbol = :F, + uplo::Symbol=:F, ) where {R<:Real} (; ag, @@ -655,7 +636,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 @@ -670,13 +651,13 @@ function decompress_csc!( counter = 0 # Recover the off-diagonal coefficients of A - for k = 1:nt + for k in 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 = first:last + for pos in first:last (vertex, _) = reverse_bfs_orders[pos] buffer_right_type[vertex] = zero(R) end @@ -684,7 +665,7 @@ function decompress_csc!( (_, root) = reverse_bfs_orders[last] buffer_right_type[root] = zero(R) - for pos = first:last + for pos in first:last (i, j) = reverse_bfs_orders[pos] counter += 1 val = B[i, color[j]] - buffer_right_type[i] @@ -733,7 +714,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) @@ -746,7 +727,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 @@ -800,17 +781,16 @@ 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) @@ -822,20 +802,17 @@ function decompress!( decompress!(A_and_noAᵀ, Br_and_Bc, symmetric_result, :L) rvA = rowvals(A_and_noAᵀ) nzA = nonzeros(A_and_noAᵀ) - for j = 1:n + for j in 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 4db4a72d..ec7e505e 100644 --- a/src/forest.jl +++ b/src/forest.jl @@ -38,9 +38,7 @@ 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 c408bb42..94954602 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 = 1:nnzA + for k in 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 = 1:m + for col in 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 = 1:n - for index = A_colptr[j]:(A_colptr[j+1]-1) + for j in 1:n + for index in 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 = m:-1:2 - B_colptr[col] = B_colptr[col-1] + for col in 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 = 1:nnzS + for i in 1:nnzS rowval[i] = S.rowval[i] + n edge_to_index[i] = i end - for j = 1:n + for j in 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 = 1:nnzS + for k in 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 = 1:m - colptr[n+j] = nnzS + S.colptr[j] + for j in 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 = 1:nnzS + for k in 1:nnzS i = S.rowval[k] - colptr[n+i] += 1 + colptr[n + i] += 1 end counter = 1 - for col = (n+1):p + for col in (n + 1):p nnz_col = colptr[col] colptr[col] = nnzS + counter counter += nnz_col end - for j = 1:n - for index = S.colptr[j]:(S.colptr[j+1]-1) + for j in 1:n + for index in 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 = p:-1:(n+2) - colptr[col] = colptr[col-1] + colptr[p + 1] = nnzS + counter + for col in 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,10 +419,7 @@ 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) @@ -436,10 +433,7 @@ 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 d4de1b58..0d183c9c 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,16 +326,18 @@ 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, @@ -345,8 +347,9 @@ 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( @@ -373,12 +376,13 @@ 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, @@ -388,8 +392,9 @@ 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 3dc670a2..453e3062 100644 --- a/src/matrices.jl +++ b/src/matrices.jl @@ -22,10 +22,12 @@ 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), @@ -100,13 +102,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 19a71b11..2a70a59d 100644 --- a/src/optimal.jl +++ b/src/optimal.jl @@ -29,10 +29,6 @@ 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 f5e26d2c..20884c6a 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 = 0:dmax] + buckets = [Vector{T}(undef, deg_count[d + 1]) for d in 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,48 +244,44 @@ 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 @@ -294,18 +290,14 @@ 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 @@ -321,8 +313,7 @@ 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) @@ -350,9 +341,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 π @@ -406,9 +397,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 π @@ -423,7 +414,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 @@ -436,7 +427,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 @@ -449,7 +440,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 @@ -480,12 +471,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 c3a568f5..7b2b58f5 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 = 1:nb_colors + for ci in 1:nb_colors if color_used[ci] offsets[ci] = num_colors_useless else @@ -109,21 +109,19 @@ 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 = 1:nt + for k in 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 @@ -145,12 +143,12 @@ function postprocess_with_tree_set!( # Process the trivial trees (if any) if nb_trivial_trees > 0 - for k = 1:nt + for k in 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 48f12079..29eebaca 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 ddd4c05b..489426c9 100644 --- a/src/result.jl +++ b/src/result.jl @@ -106,9 +106,9 @@ 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) + return view(group_flat, i:j) end return group end @@ -172,9 +172,7 @@ 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) @@ -246,9 +244,7 @@ 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) @@ -331,9 +327,7 @@ 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) @@ -386,11 +380,7 @@ $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 @@ -445,12 +435,12 @@ function TreeSetColoringResult( # Index in lower_triangle_offsets and upper_triangle_offsets index_offsets = 0 - for k = 1:nt + for k in 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 = first:last + for pos in first:last (leaf, neighbor) = reverse_bfs_orders[pos] # Update lower_triangle_offsets and upper_triangle_offsets i = leaf @@ -522,12 +512,7 @@ $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 @@ -607,18 +592,14 @@ 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 = 1:n + for j in 1:n cj = color[j] if cj > 0 # First time that we encounter this column color @@ -635,7 +616,7 @@ function remap_colors( row_color = zeros(T, m) counter = 0 - for i = (n+1):(n+m) + for i in (n + 1):(n + m) ci = color[i] if ci > 0 # First time that we encounter this row color @@ -643,7 +624,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 @@ -721,8 +702,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 bcbfe53c..da0807d3 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 033f07f5..31305e63 100644 --- a/test/allocations.jl +++ b/test/allocations.jl @@ -10,11 +10,10 @@ 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 @@ -23,16 +22,11 @@ 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 @@ -58,21 +52,22 @@ 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 @@ -80,12 +75,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 @@ -94,10 +89,7 @@ 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)), @@ -118,9 +110,7 @@ end @testset "Sparse decompression" begin @testset "$structure - $partition - $decompression" for ( - structure, - partition, - decompression, + structure, partition, decompression ) in [ (:nonsymmetric, :column, :direct), (:nonsymmetric, :row, :direct), @@ -135,12 +125,9 @@ 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 @@ -151,9 +138,7 @@ 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 70274847..8cf2c495 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,23 +67,19 @@ 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 @@ -100,9 +96,7 @@ 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]) @@ -113,7 +107,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) @@ -152,16 +146,10 @@ 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, @@ -170,7 +158,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, @@ -179,7 +167,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, @@ -188,7 +176,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, @@ -197,7 +185,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 @@ -254,7 +242,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 ( @@ -264,7 +252,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 ( @@ -274,7 +262,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 ( @@ -284,7 +272,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 ( @@ -294,7 +282,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 @@ -316,22 +304,16 @@ 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 0a484ea8..97c7f238 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,18 +37,17 @@ 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, + 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) ) - 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 293db938..8ce88bcb 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 136ab44d..8b27e07b 100644 --- a/test/cuda.jl +++ b/test/cuda.jl @@ -21,43 +21,40 @@ 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 944e4e30..732b62ca 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 _ = 1:1000 + for _ in 1:1000 m, n = rand(100:1000), rand(100:1000) p = 0.05 * rand() A = sprand(m, n, p) @@ -31,40 +31,31 @@ using Test end @testset "Bidirectional" begin @testset "symmetric_pattern = false" begin - for _ = 1:1000 + for _ in 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 _ = 1:1000 + for _ in 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 @@ -85,7 +76,7 @@ using Test A = sprand(Bool, 100, 100, 0.1) S = SparsityPatternCSC(A) @test all(zip(axes(S, 1), axes(S, 2))) do (i, j) - A[i, j] == S[i, j] + return A[i, j] == S[i, j] end end end @@ -100,9 +91,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 @@ -134,7 +125,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 @@ -176,7 +167,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/matrices.jl b/test/matrices.jl index fa76946c..e783bb57 100644 --- a/test/matrices.jl +++ b/test/matrices.jl @@ -30,11 +30,11 @@ same_view(::Adjoint, ::Adjoint) = true A0_sparse = sprand(rng, 10, 20, 0.3) @test all(matrix_versions(A0_dense)) do A B = respectful_similar(A) - size(B) == size(A) && same_view(A, B) + return size(B) == size(A) && same_view(A, B) end @test all(matrix_versions(A0_sparse)) do A B = respectful_similar(A) - size(B) == size(A) && same_view(A, B) + return size(B) == size(A) && same_view(A, B) end end diff --git a/test/optimal.jl b/test/optimal.jl index af7257db..36bf91c6 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 = 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 ec247371..9cae16f1 100644 --- a/test/order.jl +++ b/test/order.jl @@ -81,9 +81,7 @@ 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 @@ -92,13 +90,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) @@ -125,9 +123,10 @@ 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)) @@ -159,7 +158,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 = [ @@ -172,7 +171,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 = [ @@ -186,7 +185,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 = [ @@ -200,10 +199,11 @@ 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,9 +233,10 @@ 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 5320231c..406dfea9 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,17 +78,13 @@ 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 @@ -103,17 +99,13 @@ 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 bca58417..70b19667 100644 --- a/test/result.jl +++ b/test/result.jl @@ -3,19 +3,19 @@ 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 = 1:10 + for n in 10 .^ (2, 3, 4), cmax in (1, 2, 10, 100), iteration in 1:10 color = rand(1:cmax, n) group = group_by_color(color) @test length(group) == maximum(color) @test all(1:maximum(color)) do c - all(color[group[c]] .== c) && issorted(group[c]) + return all(color[group[c]] .== c) && issorted(group[c]) end color = rand(0:cmax, n) group = group_by_color(color) @test length(group) == maximum(color) @test all(1:maximum(color)) do c - all(color[group[c]] .== c) && issorted(group[c]) + return all(color[group[c]] .== c) && issorted(group[c]) end end end @@ -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 e96a77d4..ec679d4e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -18,12 +18,11 @@ 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 f466c143..cad07088 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 930a8f31..2e12372c 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,54 +65,52 @@ 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 @@ -120,14 +118,13 @@ 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 @@ -140,28 +137,20 @@ 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 @@ -175,39 +164,35 @@ 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 0f0cb767..0d2a7564 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 = 0:5, u = 0:5 + @testset for (m, n) in [(10, 20), (20, 10)], l in 0:5, u in 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 = 0:3, ub = 0:3, _ = 1:10 + for (mb, nb) in [(10, 20), (20, 10)], lb in 0:3, ub in 0:3, _ in 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,17 +46,13 @@ end; end; @testset "BandedBlockBandedMatrices" begin - for (mb, nb) in [(10, 20), (20, 10)], lb = 0:3, ub = 0:3, _ = 1:10 + for (mb, nb) in [(10, 20), (20, 10)], lb in 0:3, ub in 0:3, _ in 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 73c3c3cd..d69d8a9f 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,8 +32,9 @@ _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) @@ -49,16 +50,16 @@ colpack_table_6_7 = 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" @@ -71,23 +72,23 @@ colpack_table_6_7 = 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 @@ -97,8 +98,9 @@ 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) @@ -126,8 +128,9 @@ 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 71115ace..ab4308da 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 = (-(ρ÷2)):(ρ÷2)]...) + return spdiagm([k => ones(Bool, n - abs(k)) for k in (-(ρ ÷ 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 8872905d..3c6f9f02 100644 --- a/test/type_stability.jl +++ b/test/type_stability.jl @@ -25,9 +25,7 @@ rng = StableRNG(63) end @testset "$structure - $partition - $decompression" for ( - structure, - partition, - decompression, + structure, partition, decompression ) in [ (:nonsymmetric, :column, :direct), (:nonsymmetric, :row, :direct), @@ -90,9 +88,7 @@ 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), @@ -106,7 +102,7 @@ end; A0, ColoringProblem(; structure, partition), GreedyColoringAlgorithm(; decompression); - decompression_eltype = eltype(A), + decompression_eltype=eltype(A), ) if partition == :bidirectional Br, Bc = compress(A, result) @@ -136,10 +132,7 @@ end; B[1, :] end @test_opt decompress_single_color!( - respectful_similar(A), - b, - 1, - result, + respectful_similar(A), b, 1, result ) end end @@ -151,11 +144,7 @@ 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 @@ -192,9 +181,7 @@ 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 1d8d461f..77c88610 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -19,21 +19,17 @@ 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) @@ -41,14 +37,10 @@ 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) @@ -66,7 +58,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 @@ -180,9 +172,7 @@ 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 @@ -197,8 +187,9 @@ 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 @@ -215,20 +206,16 @@ 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) @@ -239,7 +226,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 @@ -247,16 +234,10 @@ 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 @@ -270,10 +251,7 @@ 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 @@ -281,8 +259,9 @@ 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 @@ -296,8 +275,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