Skip to content

Commit a181862

Browse files
fredrikekrerocarvaj
andcommitted
Add support for edge weights using SimpleWeightedGraphs
This patch adds support for edge weights based on the SimpleWeightedGraphs package. This is implemented as a package extension, and thus requires Julia 1.9 or newer. Closes #37. Co-authored-by: Rodolfo Carvajal <[email protected]> Co-authored-by: Fredrik Ekre <[email protected]>
1 parent 905ab8b commit a181862

File tree

4 files changed

+39
-5
lines changed

4 files changed

+39
-5
lines changed

Project.toml

+5-1
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,27 @@ SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
1313
[weakdeps]
1414
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
1515
LightGraphs = "093fc24a-ae57-5d10-9952-331d41423f4d"
16+
SimpleWeightedGraphs = "47aef6b3-ad0c-573a-a1e2-d07658019622"
1617

1718
[extensions]
1819
MetisGraphs = "Graphs"
1920
MetisLightGraphs = "LightGraphs"
21+
MetisSimpleWeightedGraphs = ["SimpleWeightedGraphs", "Graphs"]
2022

2123
[compat]
2224
CEnum = "0.4"
2325
Graphs = "1"
2426
LightGraphs = "1"
2527
METIS_jll = "5.1"
28+
SimpleWeightedGraphs = "1"
2629
julia = "1.6"
2730

2831
[extras]
2932
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
3033
LightGraphs = "093fc24a-ae57-5d10-9952-331d41423f4d"
3134
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
35+
SimpleWeightedGraphs = "47aef6b3-ad0c-573a-a1e2-d07658019622"
3236
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
3337

3438
[targets]
35-
test = ["Graphs", "LightGraphs", "Random", "Test"]
39+
test = ["Graphs", "LightGraphs", "Random", "SimpleWeightedGraphs", "Test"]

ext/GraphsCommon.jl

+12-2
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66
using Metis.LibMetis: idx_t
77
using Metis: Graph
88

9-
function graph(G)
9+
function graph(G; weights::Bool=false, kwargs...)
1010
N = nv(G)
1111
xadj = Vector{idx_t}(undef, N+1)
1212
xadj[1] = 1
1313
adjncy = Vector{idx_t}(undef, 2*ne(G))
14+
vwgt = C_NULL # TODO: Vertex weights could be passed as an input argument
15+
adjwgt = weights ? Vector{idx_t}(undef, 2*ne(G)) : C_NULL
1416
adjncy_i = 0
1517
for j in 1:N
1618
ne = 0
@@ -19,9 +21,17 @@ function graph(G)
1921
ne += 1
2022
adjncy_i += 1
2123
adjncy[adjncy_i] = i
24+
if weights
25+
weight = get_weight(G, i, j)
26+
if !(isinteger(weight) && weight > 0)
27+
error("weights must be positive integers, got weight $(weight) for edge ($(i), $(j))")
28+
end
29+
adjwgt[adjncy_i] = weight
30+
end
2231
end
2332
xadj[j+1] = xadj[j] + ne
2433
end
2534
resize!(adjncy, adjncy_i)
26-
return Graph(idx_t(N), xadj, adjncy)
35+
weights && resize!(adjwgt, adjncy_i)
36+
return Graph(idx_t(N), xadj, adjncy, vwgt, adjwgt)
2737
end

src/Metis.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,10 @@ function partition(G::Graph, nparts::Integer; alg = :KWAY)
102102
nparts == 1 && return fill!(part, 1) # https://github.com/JuliaSparse/Metis.jl/issues/49
103103
edgecut = fill(idx_t(0), 1)
104104
if alg === :RECURSIVE
105-
@check METIS_PartGraphRecursive(Ref{idx_t}(G.nvtxs), Ref{idx_t}(1), G.xadj, G.adjncy, G.vwgt, C_NULL, C_NULL,
105+
@check METIS_PartGraphRecursive(Ref{idx_t}(G.nvtxs), Ref{idx_t}(1), G.xadj, G.adjncy, G.vwgt, C_NULL, G.adjwgt,
106106
Ref{idx_t}(nparts), C_NULL, C_NULL, options, edgecut, part)
107107
elseif alg === :KWAY
108-
@check METIS_PartGraphKway(Ref{idx_t}(G.nvtxs), Ref{idx_t}(1), G.xadj, G.adjncy, G.vwgt, C_NULL, C_NULL,
108+
@check METIS_PartGraphKway(Ref{idx_t}(G.nvtxs), Ref{idx_t}(1), G.xadj, G.adjncy, G.vwgt, C_NULL, G.adjwgt,
109109
Ref{idx_t}(nparts), C_NULL, C_NULL, options, edgecut, part)
110110
else
111111
throw(ArgumentError("unknown algorithm $(repr(alg))"))

test/runtests.jl

+20
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,26 @@ end
4040
@test extrema(partition) == (1, nparts)
4141
@test all(x -> findfirst(==(x), partition) !== nothing, 1:nparts)
4242
end
43+
# With weights
44+
if isdefined(Base, :get_extension)
45+
import SimpleWeightedGraphs
46+
G1 = SimpleWeightedGraphs.SimpleWeightedGraph(Graphs.nv(T))
47+
G2 = SimpleWeightedGraphs.SimpleWeightedGraph(Graphs.nv(T))
48+
for edge in Graphs.edges(T)
49+
i, j = Tuple(edge)
50+
SimpleWeightedGraphs.add_edge!(G1, i, j, 1)
51+
SimpleWeightedGraphs.add_edge!(G2, i, j, i+j)
52+
end
53+
for alg in (:RECURSIVE, :KWAY), nparts in (3, 4)
54+
unwpartition = Metis.partition(T, nparts, alg = alg)
55+
partition = Metis.partition(G1, nparts, alg = alg)
56+
@test partition == unwpartition
57+
partition = Metis.partition(G2, nparts, alg = alg)
58+
@test partition != unwpartition
59+
@test extrema(partition) == (1, nparts)
60+
@test all(x -> findfirst(==(x), partition) !== nothing, 1:nparts)
61+
end
62+
end
4363
end
4464

4565
@testset "Metis.separator" begin

0 commit comments

Comments
 (0)