@@ -31,9 +31,12 @@ Matching(m::Matching) = m
31
31
Base. size (m:: Matching ) = Base. size (m. match)
32
32
Base. getindex (m:: Matching , i:: Integer ) = m. match[i]
33
33
Base. iterate (m:: Matching , state... ) = iterate (m. match, state... )
34
- function Base. setindex! (m:: Matching , v:: Integer , i:: Integer )
34
+ Base. copy (m:: Matching ) = Matching (copy (m. match), m. inv_match === nothing ? nothing : copy (m. inv_match))
35
+ function Base. setindex! (m:: Matching , v:: Union{Integer, Unassigned} , i:: Integer )
35
36
if m. inv_match != = nothing
36
- m. inv_match[v] = i
37
+ oldv = m. match[i]
38
+ oldv != = unassigned && (m. inv_match[oldv] = unassigned)
39
+ v != = unassigned && (m. inv_match[v] = i)
37
40
end
38
41
return m. match[i] = v
39
42
end
@@ -55,8 +58,11 @@ function complete(m::Matching)
55
58
return Matching (collect (m. match), inv_match)
56
59
end
57
60
58
- function invview (m:: Matching )
61
+ @noinline require_complete (m:: Matching ) =
59
62
m. inv_match === nothing && throw (ArgumentError (" Backwards matching not defined. `complete` the matching first." ))
63
+
64
+ function invview (m:: Matching )
65
+ require_complete (m)
60
66
return Matching (m. inv_match, m. match)
61
67
end
62
68
@@ -122,6 +128,23 @@ mutable struct BipartiteGraph{I<:Integer, M} <: Graphs.AbstractGraph{I}
122
128
end
123
129
BipartiteGraph (ne:: Integer , fadj:: AbstractVector , badj:: Union{AbstractVector,Integer} = maximum (maximum, fadj); metadata= nothing ) = BipartiteGraph (ne, fadj, badj, metadata)
124
130
131
+ @noinline require_complete (g:: BipartiteGraph ) = g. badjlist isa AbstractVector || throw (ArgumentError (" The graph has no back edges. Use `complete`." ))
132
+
133
+ function invview (g:: BipartiteGraph )
134
+ BipartiteGraph (g. ne, g. badjlist, g. fadjlist)
135
+ end
136
+
137
+ function complete (g:: BipartiteGraph{I} ) where {I}
138
+ isa (g. badjlist, AbstractVector) && return g
139
+ badjlist = Vector{I}[Vector {I} () for _ in 1 : g. badjlist]
140
+ for (s, l) in enumerate (g. fadjlist)
141
+ for d in l
142
+ push! (badjlist[d], s)
143
+ end
144
+ end
145
+ BipartiteGraph (g. ne, g. fadjlist, badjlist)
146
+ end
147
+
125
148
"""
126
149
```julia
127
150
Base.isequal(bg1::BipartiteGraph{T}, bg2::BipartiteGraph{T}) where {T<:Integer}
@@ -147,6 +170,7 @@ function BipartiteGraph(nsrcs::T, ndsts::T, backedge::Val{B}=Val(true); metadata
147
170
BipartiteGraph (0 , fadjlist, badjlist, metadata)
148
171
end
149
172
173
+ Base. copy (bg:: BipartiteGraph ) = BipartiteGraph (bg. ne, copy (bg. fadjlist), copy (bg. badjlist), deepcopy (bg. metadata))
150
174
Base. eltype (:: Type{<:BipartiteGraph{I}} ) where I = I
151
175
function Base. empty! (g:: BipartiteGraph )
152
176
foreach (empty!, g. fadjlist)
@@ -159,8 +183,6 @@ function Base.empty!(g::BipartiteGraph)
159
183
end
160
184
Base. length (:: BipartiteGraph ) = error (" length is not well defined! Use `ne` or `nv`." )
161
185
162
- @noinline throw_no_back_edges () = throw (ArgumentError (" The graph has no back edges." ))
163
-
164
186
if isdefined (Graphs, :has_contiguous_vertices )
165
187
Graphs. has_contiguous_vertices (:: Type{<:BipartiteGraph} ) = false
166
188
end
@@ -172,7 +194,7 @@ has_𝑠vertex(g::BipartiteGraph, v::Integer) = v in 𝑠vertices(g)
172
194
has_𝑑vertex (g:: BipartiteGraph , v:: Integer ) = v in 𝑑vertices (g)
173
195
𝑠neighbors (g:: BipartiteGraph , i:: Integer , with_metadata:: Val{M} = Val (false )) where M = M ? zip (g. fadjlist[i], g. metadata[i]) : g. fadjlist[i]
174
196
function 𝑑neighbors (g:: BipartiteGraph , j:: Integer , with_metadata:: Val{M} = Val (false )) where M
175
- g . badjlist isa AbstractVector || throw_no_back_edges ( )
197
+ require_complete (g )
176
198
M ? zip (g. badjlist[j], (g. metadata[i][j] for i in g. badjlist[j])) : g. badjlist[j]
177
199
end
178
200
Graphs. ne (g:: BipartiteGraph ) = g. ne
@@ -348,6 +370,9 @@ function DiCMOBiGraph{Transposed}(g::BipartiteGraph, m::M) where {Transposed, M}
348
370
DiCMOBiGraph {Transposed} (g, missing , m)
349
371
end
350
372
373
+ invview (g:: DiCMOBiGraph{Transposed} ) where {Transposed} =
374
+ DiCMOBiGraph {!Transposed} (invview (g. graph), g. ne, invview (g. matching))
375
+
351
376
Graphs. is_directed (:: Type{<:DiCMOBiGraph} ) = true
352
377
Graphs. nv (g:: DiCMOBiGraph{Transposed} ) where {Transposed} = Transposed ? ndsts (g. graph) : nsrcs (g. graph)
353
378
Graphs. vertices (g:: DiCMOBiGraph{Transposed} ) where {Transposed} = Transposed ? 𝑑vertices (g. graph) : 𝑠vertices (g. graph)
@@ -360,6 +385,8 @@ struct CMONeighbors{Transposed, V}
360
385
end
361
386
362
387
Graphs. outneighbors (g:: DiCMOBiGraph{false} , v) = CMONeighbors {false} (g, v)
388
+ Graphs. inneighbors (g:: DiCMOBiGraph{false} , v) = CMONeighbors {true} (invview (g), v)
389
+ Graphs. all_neighbors (g:: DiCMOBiGraph{true} , v:: Integer ) = 𝑠neighbors (g. graph, v)
363
390
Base. iterate (c:: CMONeighbors{false} ) = iterate (c, (c. g. graph. fadjlist[c. v],))
364
391
function Base. iterate (c:: CMONeighbors{false} , (l, state... ))
365
392
while true
@@ -376,13 +403,16 @@ function Base.iterate(c::CMONeighbors{false}, (l, state...))
376
403
return vsrc, (l, r[2 ])
377
404
end
378
405
end
406
+ Base. length (c:: CMONeighbors{false} ) = count (_-> true , c)
379
407
380
408
lift (f, x) = (x === unassigned || isnothing (x)) ? nothing : f (x)
381
409
382
410
_vsrc (c:: CMONeighbors{true} ) = c. g. matching[c. v]
383
411
_neighbors (c:: CMONeighbors{true} ) = lift (vsrc-> c. g. graph. fadjlist[vsrc], _vsrc (c))
384
412
Base. length (c:: CMONeighbors{true} ) = something (lift (length, _neighbors (c)), 1 ) - 1
385
413
Graphs. inneighbors (g:: DiCMOBiGraph{true} , v) = CMONeighbors {true} (g, v)
414
+ Graphs. outneighbors (g:: DiCMOBiGraph{true} , v) = CMONeighbors {false} (invview (g), v)
415
+ Graphs. all_neighbors (g:: DiCMOBiGraph{true} , v:: Integer ) = 𝑑neighbors (g. graph, v)
386
416
Base. iterate (c:: CMONeighbors{true} ) = lift (ns-> iterate (c, (ns,)), _neighbors (c))
387
417
function Base. iterate (c:: CMONeighbors{true} , (l, state... ))
388
418
while true
@@ -396,16 +426,15 @@ function Base.iterate(c::CMONeighbors{true}, (l, state...))
396
426
end
397
427
end
398
428
429
+
399
430
_edges (g:: DiCMOBiGraph{Transposed} ) where Transposed = Transposed ?
400
431
((w=> v for w in inneighbors (g, v)) for v in vertices (g)) :
401
432
((v=> w for w in outneighbors (g, v)) for v in vertices (g))
402
- _count (c:: CMONeighbors{true} ) = length (c)
403
- _count (c:: CMONeighbors{false} ) = count (_-> true , c)
404
433
405
434
Graphs. edges (g:: DiCMOBiGraph ) = (Graphs. SimpleEdge (p) for p in Iterators. flatten (_edges (g)))
406
435
function Graphs. ne (g:: DiCMOBiGraph )
407
436
if g. ne === missing
408
- g. ne = mapreduce (x-> _count (x. iter), + , _edges (g))
437
+ g. ne = mapreduce (x-> length (x. iter), + , _edges (g))
409
438
end
410
439
return g. ne
411
440
end
0 commit comments