Skip to content

Commit b344414

Browse files
committed
Fix tests
1 parent 6cdcbf8 commit b344414

4 files changed

Lines changed: 45 additions & 21 deletions

File tree

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
module SparseMatrixColoringsJuMPExt
22

33
using ADTypes: ADTypes
4-
using JuMP
5-
using LinearAlgebra
4+
using JuMP:
5+
Model,
6+
assert_is_solved_and_feasible,
7+
optimize!,
8+
set_silent,
9+
value,
10+
@variable,
11+
@constraint,
12+
@objective
613
import MathOptInterface as MOI
7-
using SparseArrays
814
using SparseMatrixColorings:
915
BipartiteGraph, OptimalColoringAlgorithm, nb_vertices, neighbors, pattern, vertices
1016

1117
function optimal_distance2_coloring(
12-
bg::BipartiteGraph, ::Val{side}, optimizer::Type{O}
13-
) where {side,O<:MOI.AbstractOptimizer}
18+
bg::BipartiteGraph, ::Val{side}, optimizer::O; silent::Bool=true
19+
) where {side,O}
1420
other_side = 3 - side
1521
n = nb_vertices(bg, Val(side))
1622
model = Model(optimizer)
17-
set_silent(model)
23+
silent && set_silent(model)
1824
@variable(model, 1 <= color[i=1:n] <= i, Int)
1925
@variable(model, ncolors, Int)
2026
@constraint(model, [ncolors; color] in MOI.CountDistinct(n + 1))
@@ -25,17 +31,27 @@ function optimal_distance2_coloring(
2531
@objective(model, Min, ncolors)
2632
optimize!(model)
2733
assert_is_solved_and_feasible(model)
28-
return round.(Int, value.(color))
34+
color_int = round.(Int, value.(color))
35+
# remap to 1:cmax
36+
true_ncolors = 0
37+
remap = fill(0, maximum(color_int))
38+
for c in color_int
39+
if remap[c] == 0
40+
true_ncolors += 1
41+
remap[c] = true_ncolors
42+
end
43+
end
44+
return remap[color_int]
2945
end
3046

3147
function ADTypes.column_coloring(A::AbstractMatrix, algo::OptimalColoringAlgorithm)
3248
bg = BipartiteGraph(A)
33-
return optimal_distance2_coloring(bg, Val(2), algo.optimizer)
49+
return optimal_distance2_coloring(bg, Val(2), algo.optimizer; algo.silent)
3450
end
3551

3652
function ADTypes.row_coloring(A::AbstractMatrix, algo::OptimalColoringAlgorithm)
3753
bg = BipartiteGraph(A)
38-
return optimal_distance2_coloring(bg, Val(1), algo.optimizer)
54+
return optimal_distance2_coloring(bg, Val(1), algo.optimizer; algo.silent)
3955
end
4056

4157
end

src/optimal.jl

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,22 @@ Coloring algorithm that relies on mathematical programming with [JuMP](https://j
66
!!! warning
77
This algorithm is only available when JuMP is loaded. If you encounter a method error, run `import JuMP` in your REPL and try again.
88
9+
!!! danger
10+
The coloring problem is NP-hard, so it is unreasonable to expect an optimal solution in reasonable time for large instances.
11+
912
# Constructor
1013
11-
OptimalColoringAlgorithm(optimizer)
14+
OptimalColoringAlgorithm(optimizer; silent::Bool=true)
1215
13-
The `optimizer` argument can be any JuMP-compatible optimizer, like `HiGHS.Optimizer`.
16+
The `optimizer` argument can be any JuMP-compatible optimizer.
17+
However, the problem formulation is best suited to CP-SAT optimizers like [MiniZinc](https://github.com/jump-dev/MiniZinc.jl).
1418
You can use [`optimizer_with_attributes`](https://jump.dev/JuMP.jl/stable/api/JuMP/#optimizer_with_attributes) to set solver-specific parameters.
1519
"""
16-
struct OptimalColoringAlgorithm{S} <: ADTypes.AbstractColoringAlgorithm
17-
optimizer::S
20+
struct OptimalColoringAlgorithm{O} <: ADTypes.AbstractColoringAlgorithm
21+
optimizer::O
22+
silent::Bool
23+
end
24+
25+
function OptimalColoringAlgorithm(optimizer; silent::Bool=true)
26+
return OptimalColoringAlgorithm(optimizer, silent)
1827
end

test/Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
1818
JuliaFormatter = "98e50ef6-434e-11e9-1051-2b60c6c9e899"
1919
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
2020
MatrixDepot = "b51810bb-c9f3-55da-ae3c-350fc1fbce05"
21+
MiniZinc = "a7f392d2-6c35-496e-b8cc-0974fbfcbf91"
2122
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
2223
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
2324
SparseMatrixColorings = "0a514795-09f3-496d-8182-132a7b665d35"

test/optimal.jl

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@ using SparseArrays
22
using SparseMatrixColorings
33
using StableRNGs
44
using Test
5+
using JuMP
6+
using MiniZinc
57

68
rng = StableRNG(0)
79

810
asymmetric_params = vcat(
9-
[(10, 20, p) for p in (0.0:0.1:0.5)],
10-
[(20, 10, p) for p in (0.0:0.1:0.5)],
11-
[(100, 200, p) for p in (0.01:0.01:0.05)],
12-
[(200, 100, p) for p in (0.01:0.01:0.05)],
11+
[(10, 20, p) for p in (0.0:0.1:0.5)], [(20, 10, p) for p in (0.0:0.1:0.5)]
1312
)
1413

14+
algo = GreedyColoringAlgorithm()
15+
optalgo = OptimalColoringAlgorithm(() -> MiniZinc.Optimizer{Float64}("highs"); silent=false)
16+
1517
@testset "Column coloring" begin
1618
problem = ColoringProblem(; structure=:nonsymmetric, partition=:column)
17-
algo = GreedyColoringAlgorithm()
18-
optalgo = OptimalColoringAlgorithm(HiGHS.Optimizer)
1919
for (m, n, p) in asymmetric_params
2020
A = sprand(rng, m, n, p)
2121
result = coloring(A, problem, algo)
@@ -26,8 +26,6 @@ end
2626

2727
@testset "Row coloring" begin
2828
problem = ColoringProblem(; structure=:nonsymmetric, partition=:row)
29-
algo = GreedyColoringAlgorithm()
30-
optalgo = OptimalColoringAlgorithm(HiGHS.Optimizer)
3129
for (m, n, p) in asymmetric_params
3230
A = sprand(rng, m, n, p)
3331
result = coloring(A, problem, algo)

0 commit comments

Comments
 (0)