Skip to content

Commit 8905574

Browse files
InterdisciplinaryPhysicsTeamClaudMorpitmonticone
committed
Update layer.jl
Co-Authored-By: Claudio Moroni <[email protected]> Co-Authored-By: Pietro Monticone <[email protected]>
1 parent 1e57882 commit 8905574

File tree

1 file changed

+30
-22
lines changed

1 file changed

+30
-22
lines changed

src/subgraphs/layer.jl

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,14 @@ mutable struct Layer{T<:Integer,U<:Real,G<:AbstractGraph{T}} <: AbstractLayer{T,
3030
descriptor::LayerDescriptor{T,U,G}
3131
graph::G
3232
v_V_associations::Bijection{T, <: MultilayerVertex}
33-
3433
# Inner constructor that performs checks on request
3534
function Layer(descriptor::LayerDescriptor{T,U,G}, graph::G, v_V_associations::Bijection{T, <: MultilayerVertex}; check_consistency = true) where {T,U,G}
3635
if check_consistency
36+
# Check that the graph type is the same as the one in the descriptor
3737
typeof(descriptor.null_graph) == typeof(graph) || throw(ErrorException("Graph types between the provided `descriptor` and `graph` cannot differ. Found $(typeof(descriptor.null_graph)) and $(typeof(graph))."))
38-
38+
# Check that the graph vertices are the same as the ones in the association
3939
all(vertices(graph) .== sort(domain(v_V_associations))) || throw(ErrorException("The graph has a different set of vertices w.r.t. the domain of `v_V_associations`. Found $(vertices(graph)) and $(sort(domain(v_V_associations)))."))
4040
end
41-
4241
return new{T,U,G}(descriptor, graph, v_V_associations)
4342
end
4443
end
@@ -62,7 +61,7 @@ Constructor for `Layer`.
6261
- `vertices::Vector{ <: MultilayerVertex}`: The `MultilayerVertex`s of the Layer;
6362
- `edge_list::Vector{ <: MultilayerEdge}`: The list of `MultilayerEdge`s;
6463
- `null_graph::G`: the Layer's underlying graph type, which must be passed as a null graph. If it is not, an error will be thrown;
65-
- `weighttype::Type{U}`: The type of the `MultilayerEdge` weights (evem when the underlying Layer's graph is unweighted, we need to specify a weight type since the `MultilayerGraph`s will always be weighted)
64+
- `weighttype::Type{U}`: The type of the `MultilayerEdge` weights (even when the underlying Layer's graph is unweighted, we need to specify a weight type since the `MultilayerGraph`s will always be weighted)
6665
6766
# KWARGS
6867
@@ -85,24 +84,24 @@ Constructor for `Layer`.
8584
- `edge_list::Vector{<:MultilayerEdge}`;
8685
"""
8786
function Layer(descriptor::LayerDescriptor{T}, vertices::Vector{<: MultilayerVertex}, edge_list::Vector{<:MultilayerEdge}) where {T <: Integer}
88-
87+
# First check that the vertices are of the correct type
8988
if hasproperty(eltype(vertices), :parameters)
9089
par = eltype(vertices).parameters[1]
9190
(isnothing(par) || par == descriptor.name) || throw(ErrorException("`vertices` should be a `Vector{MultilayerVertex{:$(descriptor.name)}}` or a `Vector{MultilayerVertex{nothing}}`. Found $(typeof(vertices))"))
9291
else
92+
# if not, throw an error
9393
throw(ErrorException("`vertices` should be a `Vector{MultilayerVertex{:$(descriptor.name)}}` or a `Vector{MultilayerVertex{nothing}}`. Found $(typeof(vertices))"))
9494
end
95-
95+
# Create the layer
9696
layer = Layer(descriptor, deepcopy(descriptor.null_graph), Bijection{T, MultilayerVertex{descriptor.name}}(), check_consistency = false)
97-
97+
# Add the vertices one by one
9898
for mv in vertices
9999
add_vertex!(layer, mv)
100100
end
101-
101+
# Add the edges
102102
for edge in edge_list
103103
add_edge!(layer, edge)
104104
end
105-
106105
return layer
107106
end
108107

@@ -117,13 +116,13 @@ Return a random `Layer`.
117116
- `vertices::Vector{ <: MultilayerVertex}`: The `MultilayerVertex`s of the Layer
118117
- `ne::Int64`: The number of edges of the Layer
119118
- `null_graph::G`: the Layer's underlying graph type, which must be passed as a null graph. If it is not, an error will be thrown.
120-
- `weighttype::Type{U}`: The type of the `MultilayerEdge` weights (evem when the underlying Layer's graph is unweighted, we need to specify a weight type since the `MultilayerGraph`s will always be weighted);
119+
- `weighttype::Type{U}`: The type of the `MultilayerEdge` weights (even when the underlying Layer's graph is unweighted, we need to specify a weight type since the `MultilayerGraph`s will always be weighted);
121120
122121
# KWARGS
123122
-` default_vertex_metadata::Function`: Function that takes a `MultilayerVertex` and returns a `Tuple` or a `NamedTuple` containing the vertex metadata. defaults to `mv -> NamedTuple()`;
124123
- `default_edge_weight::Function`: Function that takes a pair of `MultilayerVertex`s and returns an edge weight of type `weighttype` or `nothing` (which is compatible with unweighted underlying graphs and corresponds to `one(weighttype)` for weighted underlying graphs). Defaults to `(src, dst) -> nothing`;
125124
- `default_edge_metadata::Function`: Function that takes a pair of `MultilayerVertex`s and returns a `Tuple` or a `NamedTuple` containing the edge metadata, that will be called when `add_edge!(mg,src,dst, args...; kwargs...)` is called without the `metadata` keyword argument, and when generating the edges in this constructor. Defaults to `(src, dst) -> NamedTuple()`;
126-
- `allow_self_loops::Bool`: whether to allow self loops to be geenrated or not. Deafults to `false`.
125+
- `allow_self_loops::Bool`: whether to allow self loops to be generated or not. Defaults to `false`.
127126
"""
128127
function Layer(
129128
name::Symbol,
@@ -142,19 +141,23 @@ function Layer(
142141
edge_list = MultilayerEdge[]
143142

144143
for i in 1:ne
144+
# Generate a random vertex
145145
rand_vertex_1 = rand(vertices)
146+
# Generate another random vertex
146147
rand_vertex_2 = nothing
148+
# If we don't allow self loops, keep generating until we get a vertex that isn't the same as the previous one.
147149
if !allow_self_loops
148150
while isnothing(rand_vertex_2) || rand_vertex_2.node == rand_vertex_1.node
149151
rand_vertex_2 = rand(vertices)
150152
end
151153
else
152154
rand_vertex_2 = rand(vertices)
153155
end
156+
# Add the edge to the edge list
154157
push!(edge_list, MultilayerEdge(MV(rand_vertex_1.node, name), MV(rand_vertex_2.node, name), default_edge_weight(rand_vertex_1,rand_vertex_2), default_edge_metadata(rand_vertex_1,rand_vertex_2 )))
155158
end
156159

157-
edge_list = MultilayerEdge[ rand() < 0.5 ? me : reverse(me) for me in edge_list]
160+
edge_list = MultilayerEdge[rand() < 0.5 ? me : reverse(me) for me in edge_list]
158161
layer = Layer(descriptor, vertices, edge_list)
159162

160163
return layer
@@ -193,19 +196,26 @@ end
193196
Add vertex associated with node `n` to layer `layer`. This method supports the uniform and transparent interfaces. See the [Vertices](@ref) section of the Tutorial.
194197
"""
195198
function Graphs.add_vertex!(layer::L, n::Node, args...; kwargs...) where {T, U, G, L <: Layer{T,U,G}}
199+
# Check if the vertex is already in the layer
196200
has_node(layer, n) && return false
197201

198202
success = false
199203
if isempty(args) && length(kwargs) == 1 && issetequal(Set([:metadata]), Set(keys(kwargs)) )
204+
# If only the metadata is provided, call the standard add_vertex method
200205
success = add_vertex_standard!(layer; metadata = values(kwargs).metadata)
201206
elseif length(args) == length(kwargs) == 0
207+
# If no arguments or keyword arguments are provided, use the layer's default vertex metadata
202208
success = add_vertex_standard!(layer, metadata = layer.default_vertex_metadata(MV(n, layer.name)))
203209
else
210+
# Otherwise, call the generic add_vertex method
204211
success = add_vertex!(layer.graph, args...; kwargs... )
205212
end
206213

214+
# Check if the vertex is already in the layer
207215
if success
216+
# Get the last vertex in the layer
208217
last_vertex = length(layer.v_V_associations) == 0 ? zero(T) : maximum(domain(layer.v_V_associations))
218+
# Add the vertex to the layer
209219
layer.v_V_associations[last_vertex + one(T)] = MV(n, layer.name)
210220
return true
211221
else
@@ -237,16 +247,13 @@ function Graphs.rem_vertex!(layer::Layer, mv::MultilayerVertex)
237247
rem_vertex!(layer, mv.node)
238248
end
239249

240-
241250
"""
242251
rem_vertex!(layer::Layer, n::Node)
243252
244253
Remove node `n` from `layer`. Modify `layer.v_N_associations` according to how `rem_vertex!` works in [Graph.jl](https://juliagraphs.org/Graphs.jl/dev/core_functions/simplegraphs/#Graphs.SimpleGraphs.rem_vertex!-Tuple{Graphs.SimpleGraphs.AbstractSimpleGraph,%20Integer}).
245254
"""
246255
function Graphs.rem_vertex!(layer::Layer, n::Node)
247-
248256
!has_node(layer, n) && return false
249-
250257
success = rem_vertex!(layer, layer.v_V_associations(MV(n, layer.name)))
251258

252259
if success
@@ -287,28 +294,29 @@ Graphs.rem_vertex!(layer::L, v::T) where {T,U,G, L <: Layer{T,U,G}} = rem_vertex
287294
Add edge from vertex `src` to vertex `dst` to layer `layer`. This method supports the uniform and transparent interfaces. See the [Edges](@ref) section of the Tutorial.
288295
"""
289296
function Graphs.add_edge!(layer::L, src::MultilayerVertex, dst::MultilayerVertex, args...; kwargs...) where {L <: Layer}
290-
bare_src = get_bare_mv(src)
291-
bare_dst = get_bare_mv(dst)
292-
297+
# Check if the vertices exist
293298
!has_vertex(layer, src) && throw( ErrorException( "Vertex $(src) does not belong to the layer."))
294299
!has_vertex(layer, dst) && throw( ErrorException( "Vertex $(dst) does not belong to the layer."))
295300

301+
# Check if the edge already exists
296302
if !has_edge(layer, src, dst)
303+
# If the edge doesn't exist, add it
304+
# If the user does not specify any arguments, we use the default values
297305
if isempty(args) && length(kwargs) == 2 && issetequal(Set([:weight, :metadata]), Set(keys(kwargs)) )
298306
success = add_edge_standard!(layer, bare_src, bare_dst, weight = values(kwargs).weight, metadata = values(kwargs).metadata)
299-
307+
# If the user only specifies the weight, we use the default metadata
300308
elseif isempty(args) && length(kwargs) == 1 && issetequal(Set([:weight]), Set(keys(kwargs)) )
301309
success = add_edge_standard!(layer, bare_src, bare_dst, weight = values(kwargs).weight, metadata = layer.default_edge_metadata(bare_src, bare_dst))
302-
310+
# If the user only specifies the metadata, we use the default weight
303311
elseif isempty(args) && length(kwargs) == 1 && issetequal(Set([:metadata]), Set(keys(kwargs)) )
304312
success = add_edge_standard!(layer, bare_src, bare_dst, weight = layer.default_edge_weight(bare_src, bare_dst), metadata = values(kwargs).metadata)
305-
313+
# If the user does not specify any arguments, we use the default values
306314
elseif length(args) == length(kwargs) == 0
307315
success = add_edge_standard!(layer, bare_src, bare_dst, weight = layer.default_edge_weight(bare_src, bare_dst), metadata = layer.default_edge_metadata(bare_src, bare_dst))
308316
else
317+
# If the user specifies arguments, we use those instead of the defaults
309318
success = add_edge!(layer.graph, get_v(layer,bare_src), get_v(layer,bare_dst), args...; kwargs... )
310319
end
311-
312320
return success
313321
else
314322
return false

0 commit comments

Comments
 (0)