|
1 | 1 | module AMDExt |
2 | 2 |
|
3 | | -using AMD: AMD as AMDLib |
| 3 | +using Base: oneto |
4 | 4 | using CliqueTrees |
5 | 5 | using Graphs |
6 | 6 |
|
| 7 | +import AMD as AMDLib |
| 8 | + |
| 9 | +const AMD_DENSE = AMDLib.AMD_DENSE |
| 10 | +const AMD_AGGRESSIVE = AMDLib.AMD_AGGRESSIVE |
| 11 | +const COLAMD_DENSE_ROW = AMDLib.COLAMD_DENSE_ROW |
| 12 | +const COLAMD_DENSE_COL = AMDLib.COLAMD_DENSE_COL |
| 13 | +const COLAMD_AGGRESSIVE = AMDLib.COLAMD_AGGRESSIVE |
| 14 | + |
7 | 15 | function CliqueTrees.permutation(graph, alg::Union{AMD, SymAMD}) |
8 | 16 | return permutation(BipartiteGraph(graph), alg) |
9 | 17 | end |
10 | 18 |
|
11 | | -function CliqueTrees.permutation(graph::BipartiteGraph{V}, alg::AMD) where {V} |
| 19 | +function CliqueTrees.permutation(graph::AbstractGraph, alg::Union{AMD, SymAMD}) |
| 20 | + order = amd(graph, alg) |
| 21 | + return order, invperm(order) |
| 22 | +end |
| 23 | + |
| 24 | +function amd(graph::AbstractGraph{V}, alg::Union{AMD, SymAMD}) where {V} |
| 25 | + new = BipartiteGraph{Cint, Cint}(graph) |
| 26 | + order::Vector{V} = amd(new, alg) |
| 27 | + return order |
| 28 | +end |
| 29 | + |
| 30 | +function amd(graph::AbstractGraph{Int64}, alg::Union{AMD, SymAMD}) |
| 31 | + new = BipartiteGraph{Int64, Int64}(graph) |
| 32 | + return amd(new, alg) |
| 33 | +end |
| 34 | + |
| 35 | +function amd(graph::BipartiteGraph{Cint, Cint, Vector{Cint}, Vector{Cint}}, alg::AMD) |
| 36 | + n = nv(graph); m = ne(graph); nn = n + one(Cint) |
| 37 | + |
12 | 38 | # set parameters |
13 | 39 | meta = AMDLib.Amd() |
14 | | - meta.control[AMDLib.AMD_DENSE] = alg.dense |
15 | | - meta.control[AMDLib.AMD_AGGRESSIVE] = alg.aggressive |
| 40 | + setmeta!(meta, alg) |
16 | 41 |
|
17 | 42 | # construct AMD graph |
18 | | - nrow = convert(Cint, nv(graph)) |
19 | | - colptr = Vector{Cint}(pointers(graph)) |
20 | | - rowval = Vector{Cint}(targets(graph)) |
21 | | - colptr .-= one(Cint) # 0-based indexing |
22 | | - rowval .-= one(Cint) # 0-based indexing |
| 43 | + xadj = pointers(graph) |
| 44 | + adjncy = targets(graph) |
| 45 | + |
| 46 | + @inbounds for v in oneto(nn) |
| 47 | + xadj[v] -= one(Cint) |
| 48 | + end |
| 49 | + |
| 50 | + @inbounds for v in oneto(m) |
| 51 | + adjncy[v] -= one(Cint) |
| 52 | + end |
23 | 53 |
|
24 | 54 | # construct permutation |
25 | | - p = zeros(Cint, nv(graph)) |
26 | | - AMDLib.amd_order(nrow, colptr, rowval, p, meta.control, meta.info) |
27 | | - p .+= one(Cint) # 1-based indexing |
| 55 | + order = zeros(Cint, n) |
| 56 | + AMDLib.amd_order(n, xadj, adjncy, order, meta.control, meta.info) |
28 | 57 |
|
29 | | - # restore vertex type |
30 | | - order::Vector{V} = p |
31 | | - return order, invperm(order) |
| 58 | + @inbounds for v in oneto(n) |
| 59 | + xadj[v] += one(Cint) |
| 60 | + order[v] += one(Cint) |
| 61 | + end |
| 62 | + |
| 63 | + xadj[nn] += one(Cint) |
| 64 | + |
| 65 | + @inbounds for v in oneto(m) |
| 66 | + adjncy[v] += one(Cint) |
| 67 | + end |
| 68 | + |
| 69 | + return order |
32 | 70 | end |
33 | 71 |
|
34 | | -function CliqueTrees.permutation(graph::BipartiteGraph{Int64}, alg::AMD) |
| 72 | + |
| 73 | +function amd(graph::BipartiteGraph{Int64, Int64, Vector{Int64}, Vector{Int64}}, alg::AMD) |
| 74 | + n = nv(graph); m = ne(graph); nn = n + one(Int64) |
| 75 | + |
35 | 76 | # set parameters |
36 | 77 | meta = AMDLib.Amd() |
37 | | - meta.control[AMDLib.AMD_DENSE] = alg.dense |
38 | | - meta.control[AMDLib.AMD_AGGRESSIVE] = alg.aggressive |
| 78 | + setmeta!(meta, alg) |
39 | 79 |
|
40 | 80 | # construct AMD graph |
41 | | - nrow = nv(graph) |
42 | | - colptr = Vector{Int64}(pointers(graph)) |
43 | | - rowval = Vector{Int64}(targets(graph)) |
44 | | - colptr .-= one(Int64) # 0-based indexing |
45 | | - rowval .-= one(Int64) # 0-based indexing |
| 81 | + xadj = pointers(graph) |
| 82 | + adjncy = targets(graph) |
| 83 | + |
| 84 | + @inbounds for v in oneto(nn) |
| 85 | + xadj[v] -= one(Int64) |
| 86 | + end |
| 87 | + |
| 88 | + @inbounds for v in oneto(m) |
| 89 | + adjncy[v] -= one(Int64) |
| 90 | + end |
46 | 91 |
|
47 | 92 | # construct permutation |
48 | | - p = zeros(Int64, nv(graph)) |
49 | | - AMDLib.amd_l_order(nrow, colptr, rowval, p, meta.control, meta.info) |
50 | | - p .+= one(Int64) # 1-based indexing |
| 93 | + order = zeros(Int64, n) |
| 94 | + AMDLib.amd_l_order(n, xadj, adjncy, order, meta.control, meta.info) |
51 | 95 |
|
52 | | - # restore vertex type |
53 | | - order = p |
54 | | - return order, invperm(order) |
| 96 | + @inbounds for v in oneto(n) |
| 97 | + xadj[v] += one(Int64) |
| 98 | + order[v] += one(Int64) |
| 99 | + end |
| 100 | + |
| 101 | + xadj[nn] += one(Int64) |
| 102 | + |
| 103 | + @inbounds for v in oneto(m) |
| 104 | + adjncy[v] += one(Int64) |
| 105 | + end |
| 106 | + |
| 107 | + return order |
55 | 108 | end |
56 | 109 |
|
57 | | -function CliqueTrees.permutation(graph::BipartiteGraph{V}, alg::SymAMD) where {V} |
| 110 | +function amd(graph::BipartiteGraph{Cint, Cint, Vector{Cint}, Vector{Cint}}, alg::SymAMD) |
| 111 | + n = nv(graph); m = ne(graph); nn = n + one(Cint) |
| 112 | + |
58 | 113 | # set parameters |
59 | 114 | meta = AMDLib.Colamd{Cint}() |
60 | | - meta.knobs[AMDLib.COLAMD_DENSE_ROW] = alg.dense_row |
61 | | - meta.knobs[AMDLib.COLAMD_DENSE_COL] = alg.dense_col |
62 | | - meta.knobs[AMDLib.COLAMD_AGGRESSIVE] = alg.aggressive |
| 115 | + setmeta!(meta, alg) |
63 | 116 |
|
64 | 117 | # construct AMD graph |
65 | | - nrow = convert(Cint, nv(graph)) |
66 | | - colptr = Vector{Cint}(pointers(graph)) |
67 | | - rowval = Vector{Cint}(targets(graph)) |
68 | | - colptr .-= one(Cint) # 0-based indexing |
69 | | - rowval .-= one(Cint) # 0-based indexing |
| 118 | + xadj = pointers(graph) |
| 119 | + adjncy = targets(graph) |
| 120 | + |
| 121 | + @inbounds for v in oneto(nn) |
| 122 | + xadj[v] -= one(Cint) |
| 123 | + end |
| 124 | + |
| 125 | + @inbounds for v in oneto(m) |
| 126 | + adjncy[v] -= one(Cint) |
| 127 | + end |
70 | 128 |
|
71 | 129 | # construct permutation |
72 | | - p = zeros(Cint, nv(graph) + 1) |
| 130 | + order = zeros(Cint, nn) |
73 | 131 | cfun_calloc = @cfunction(Base.Libc.calloc, Ptr{Cvoid}, (Cint, Cint)) |
74 | 132 | cfun_free = @cfunction(Base.Libc.free, Cvoid, (Ptr{Cvoid},)) |
75 | | - AMDLib.symamd(nrow, rowval, colptr, p, meta.knobs, meta.stats, cfun_calloc, cfun_free) |
76 | | - p .+= one(Cint) # 1-based indexing |
| 133 | + AMDLib.symamd(n, adjncy, xadj, order, meta.knobs, meta.stats, cfun_calloc, cfun_free) |
77 | 134 |
|
78 | | - # restore vertex type |
79 | | - order::Vector{V} = @view p[begin:(end - 1)] |
80 | | - return order, invperm(order) |
| 135 | + @inbounds for v in oneto(n) |
| 136 | + xadj[v] += one(Cint) |
| 137 | + order[v] += one(Cint) |
| 138 | + end |
| 139 | + |
| 140 | + xadj[nn] += one(Cint) |
| 141 | + |
| 142 | + @inbounds for v in oneto(m) |
| 143 | + adjncy[v] += one(Cint) |
| 144 | + end |
| 145 | + |
| 146 | + return resize!(order, n) |
81 | 147 | end |
82 | 148 |
|
83 | | -function CliqueTrees.permutation(graph::BipartiteGraph{Int64}, alg::SymAMD) |
| 149 | +function amd(graph::BipartiteGraph{Int64, Int64, Vector{Int64}, Vector{Int64}}, alg::SymAMD) |
| 150 | + n = nv(graph); m = ne(graph); nn = n + one(Int64) |
| 151 | + |
84 | 152 | # set parameters |
85 | 153 | meta = AMDLib.Colamd{Int64}() |
86 | | - meta.knobs[AMDLib.COLAMD_DENSE_ROW] = alg.dense_row |
87 | | - meta.knobs[AMDLib.COLAMD_DENSE_COL] = alg.dense_col |
88 | | - meta.knobs[AMDLib.COLAMD_AGGRESSIVE] = alg.aggressive |
| 154 | + setmeta!(meta, alg) |
89 | 155 |
|
90 | 156 | # construct AMD graph |
91 | | - nrow = nv(graph) |
92 | | - colptr = Vector{Int64}(pointers(graph)) |
93 | | - rowval = Vector{Int64}(targets(graph)) |
94 | | - colptr .-= one(Int64) # 0-based indexing |
95 | | - rowval .-= one(Int64) # 0-based indexing |
| 157 | + xadj = pointers(graph) |
| 158 | + adjncy = targets(graph) |
| 159 | + |
| 160 | + @inbounds for v in oneto(nn) |
| 161 | + xadj[v] -= one(Int64) |
| 162 | + end |
| 163 | + |
| 164 | + @inbounds for v in oneto(m) |
| 165 | + adjncy[v] -= one(Int64) |
| 166 | + end |
96 | 167 |
|
97 | 168 | # construct permutation |
98 | | - p = zeros(Int64, nv(graph) + 1) |
| 169 | + order = zeros(Int64, nn) |
99 | 170 | cfun_calloc = @cfunction(Base.Libc.calloc, Ptr{Cvoid}, (Int64, Int64)) |
100 | 171 | cfun_free = @cfunction(Base.Libc.free, Cvoid, (Ptr{Cvoid},)) |
101 | | - AMDLib.symamd_l(nrow, rowval, colptr, p, meta.knobs, meta.stats, cfun_calloc, cfun_free) |
102 | | - p .+= one(Int64) # 1-based indexing |
| 172 | + AMDLib.symamd_l(n, adjncy, xadj, order, meta.knobs, meta.stats, cfun_calloc, cfun_free) |
103 | 173 |
|
104 | | - # restore vertex type |
105 | | - order = p[begin:(end - 1)] |
106 | | - return order, invperm(order) |
| 174 | + @inbounds for v in oneto(n) |
| 175 | + xadj[v] += one(Int64) |
| 176 | + order[v] += one(Int64) |
| 177 | + end |
| 178 | + |
| 179 | + xadj[nn] += one(Int64) |
| 180 | + |
| 181 | + @inbounds for v in oneto(m) |
| 182 | + adjncy[v] += one(Int64) |
| 183 | + end |
| 184 | + |
| 185 | + return resize!(order, n) |
| 186 | +end |
| 187 | + |
| 188 | +function setmeta!(meta::AMDLib.Amd, alg::AMD) |
| 189 | + meta.control[AMD_DENSE] = alg.dense |
| 190 | + meta.control[AMD_AGGRESSIVE] = alg.aggressive |
| 191 | + return |
| 192 | +end |
| 193 | + |
| 194 | +function setmeta!(meta::AMDLib.Colamd, alg::SymAMD) |
| 195 | + meta.knobs[COLAMD_DENSE_ROW] = alg.dense_row |
| 196 | + meta.knobs[COLAMD_DENSE_COL] = alg.dense_col |
| 197 | + meta.knobs[COLAMD_AGGRESSIVE] = alg.aggressive |
| 198 | + return |
107 | 199 | end |
108 | 200 |
|
109 | 201 | end |
0 commit comments