@@ -3,7 +3,7 @@ module BipartiteGraphs
3
3
export BipartiteEdge, BipartiteGraph, DiCMOBiGraph, Unassigned, unassigned
4
4
5
5
export 𝑠vertices, 𝑑vertices, has_𝑠vertex, has_𝑑vertex, 𝑠neighbors, 𝑑neighbors,
6
- 𝑠edges, 𝑑edges, nsrcs, ndsts, SRC, DST
6
+ 𝑠edges, 𝑑edges, nsrcs, ndsts, SRC, DST, set_neighbors!
7
7
8
8
using DocStringExtensions
9
9
using UnPack
20
20
# ##
21
21
# ## Edges & Vertex
22
22
# ##
23
- @enum VertType SRC DST ALL
23
+ @enum VertType SRC DST
24
24
25
25
struct BipartiteEdge{I<: Integer } <: Graphs.AbstractEdge{I}
26
26
src:: I
@@ -189,10 +189,17 @@ function Graphs.add_vertex!(g::BipartiteGraph{T}, type::VertType) where T
189
189
return true # vertex successfully added
190
190
end
191
191
192
+ function set_neighbors! (g:: BipartiteGraph , i:: Integer , new_neighbors:: AbstractVector )
193
+ old_nneighbors = length (g. fadjlist[i])
194
+ new_nneighbors = length (new_neighbors)
195
+ g. fadjlist[i] = new_neighbors
196
+ g. ne += new_nneighbors - old_nneighbors
197
+ end
198
+
192
199
# ##
193
200
# ## Edges iteration
194
201
# ##
195
- Graphs. edges (g:: BipartiteGraph ) = BipartiteEdgeIter (g, Val (ALL ))
202
+ Graphs. edges (g:: BipartiteGraph ) = BipartiteEdgeIter (g, Val (SRC ))
196
203
𝑠edges (g:: BipartiteGraph ) = BipartiteEdgeIter (g, Val (SRC))
197
204
𝑑edges (g:: BipartiteGraph ) = BipartiteEdgeIter (g, Val (DST))
198
205
@@ -202,8 +209,6 @@ struct BipartiteEdgeIter{T,G} <: Graphs.AbstractEdgeIter
202
209
end
203
210
204
211
Base. length (it:: BipartiteEdgeIter ) = ne (it. g)
205
- Base. length (it:: BipartiteEdgeIter{ALL} ) = 2 ne (it. g)
206
-
207
212
Base. eltype (it:: BipartiteEdgeIter ) = edgetype (it. g)
208
213
209
214
function Base. iterate (it:: BipartiteEdgeIter{SRC,<:BipartiteGraph{T}} , state= (1 , 1 , SRC)) where T
@@ -247,21 +252,6 @@ function Base.iterate(it::BipartiteEdgeIter{DST,<:BipartiteGraph{T}}, state=(1,
247
252
return nothing
248
253
end
249
254
250
- function Base. iterate (it:: BipartiteEdgeIter{ALL,<:BipartiteGraph} , state= nothing )
251
- if state === nothing
252
- ss = iterate ((@set it. type = Val (SRC)))
253
- elseif state[3 ] === SRC
254
- ss = iterate ((@set it. type = Val (SRC)), state)
255
- elseif state[3 ] == DST
256
- ss = iterate ((@set it. type = Val (DST)), state)
257
- end
258
- if ss === nothing && state[3 ] == SRC
259
- return iterate ((@set it. type = Val (DST)))
260
- else
261
- return ss
262
- end
263
- end
264
-
265
255
# ##
266
256
# ## Utils
267
257
# ##
@@ -301,13 +291,20 @@ is acyclic if and only if the induced directed graph on the original bipartite
301
291
graph is acyclic.
302
292
303
293
"""
304
- struct DiCMOBiGraph{Transposed, I, G<: BipartiteGraph{I} , M} <: Graphs.AbstractGraph{I}
294
+ mutable struct DiCMOBiGraph{Transposed, I, G<: BipartiteGraph{I} , M} <: Graphs.AbstractGraph{I}
305
295
graph:: G
296
+ ne:: Union{Missing, Int}
306
297
matching:: M
307
- DiCMOBiGraph {Transposed} (g:: G , m:: M ) where {Transposed, I, G<: BipartiteGraph{I} , M} =
308
- new {Transposed, I, G, M} (g, m)
298
+ DiCMOBiGraph {Transposed} (g:: G , ne:: Union{Missing, Int} , m:: M ) where {Transposed, I, G<: BipartiteGraph{I} , M} =
299
+ new {Transposed, I, G, M} (g, ne, m)
300
+ end
301
+ function DiCMOBiGraph {Transposed} (g:: BipartiteGraph ) where {Transposed}
302
+ DiCMOBiGraph {Transposed} (g, 0 , Union{Unassigned, Int}[unassigned for i = 1 : ndsts (g)])
303
+ end
304
+ function DiCMOBiGraph {Transposed} (g:: BipartiteGraph , m:: M ) where {Transposed, M}
305
+ DiCMOBiGraph {Transposed} (g, missing , m)
309
306
end
310
- DiCMOBiGraph {Transposed} (g :: BipartiteGraph ) where {Transposed} = DiCMOBiGraph {Transposed} (g, Union{Unassigned, Int}[unassigned for i = 1 : ndsts (g)])
307
+
311
308
Graphs. is_directed (:: Type{<:DiCMOBiGraph} ) = true
312
309
Graphs. nv (g:: DiCMOBiGraph{Transposed} ) where {Transposed} = Transposed ? ndsts (g. graph) : nsrcs (g. graph)
313
310
Graphs. vertices (g:: DiCMOBiGraph{Transposed} ) where {Transposed} = Transposed ? 𝑑vertices (g. graph) : 𝑠vertices (g. graph)
@@ -318,6 +315,7 @@ struct CMONeighbors{Transposed, V}
318
315
CMONeighbors {Transposed} (g:: DiCMOBiGraph{Transposed} , v:: V ) where {Transposed, V} =
319
316
new {Transposed, V} (g, v)
320
317
end
318
+
321
319
Graphs. outneighbors (g:: DiCMOBiGraph{false} , v) = CMONeighbors {false} (g, v)
322
320
Base. iterate (c:: CMONeighbors{false} ) = iterate (c, (c. g. graph. fadjlist[c. v],))
323
321
function Base. iterate (c:: CMONeighbors{false} , (l, state... ))
@@ -336,12 +334,13 @@ function Base.iterate(c::CMONeighbors{false}, (l, state...))
336
334
end
337
335
end
338
336
337
+ lift (f, x) = (x === unassigned || isnothing (x)) ? nothing : f (x)
338
+
339
+ _vsrc (c:: CMONeighbors{true} ) = c. g. matching[c. v]
340
+ _neighbors (c:: CMONeighbors{true} ) = lift (vsrc-> c. g. graph. fadjlist[vsrc], _vsrc (c))
341
+ Base. length (c:: CMONeighbors{true} ) = something (lift (length, _neighbors (c)), 1 ) - 1
339
342
Graphs. inneighbors (g:: DiCMOBiGraph{true} , v) = CMONeighbors {true} (g, v)
340
- function Base. iterate (c:: CMONeighbors{true} )
341
- vsrc = c. g. matching[c. v]
342
- vsrc === unassigned && return nothing
343
- iterate (c, (c. g. graph. fadjlist[vsrc],))
344
- end
343
+ Base. iterate (c:: CMONeighbors{true} ) = lift (ns-> iterate (c, (ns,)), _neighbors (c))
345
344
function Base. iterate (c:: CMONeighbors{true} , (l, state... ))
346
345
while true
347
346
r = iterate (l, state... )
@@ -354,4 +353,21 @@ function Base.iterate(c::CMONeighbors{true}, (l, state...))
354
353
end
355
354
end
356
355
356
+ _edges (g:: DiCMOBiGraph{Transposed} ) where Transposed = Transposed ?
357
+ ((w=> v for w in inneighbors (g, v)) for v in vertices (g)) :
358
+ ((v=> w for w in outneighbors (g, v)) for v in vertices (g))
359
+ _count (c:: CMONeighbors{true} ) = length (c)
360
+ _count (c:: CMONeighbors{false} ) = count (_-> true , c)
361
+
362
+ Graphs. edges (g:: DiCMOBiGraph ) = (Graphs. SimpleEdge (p) for p in Iterators. flatten (_edges (g)))
363
+ function Graphs. ne (g:: DiCMOBiGraph )
364
+ if g. ne === missing
365
+ g. ne = mapreduce (x-> _count (x. iter), + , _edges (g))
366
+ end
367
+ return g. ne
368
+ end
369
+
370
+ Graphs. has_edge (g:: DiCMOBiGraph{true} , a, b) = a in inneighbors (g, b)
371
+ Graphs. has_edge (g:: DiCMOBiGraph{false} , a, b) = b in outneighbors (g, a)
372
+
357
373
end # module
0 commit comments