Skip to content

Commit 5a255a4

Browse files
cecileanegdalle
andauthored
fix #69 and #70 (#71)
* fix #69 and #70 * v0.7.0 because breaking change * arrange: no more codes as arguments * more testing * add_edge! modifies edge data if edge already present * Update src/graphs.jl --------- Co-authored-by: Guillaume Dalle <[email protected]>
1 parent 5eb369b commit 5a255a4

File tree

8 files changed

+35
-37
lines changed

8 files changed

+35
-37
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "MetaGraphsNext"
22
uuid = "fa8bd995-216d-47f1-8a91-f3b68fbeb377"
3-
version = "0.6.0"
3+
version = "0.7.0"
44

55
[deps]
66
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"

src/dict_utils.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ function _copy_props!(old_meta_graph::MetaGraph, new_meta_graph::MetaGraph, code
114114
code_1, code_2 = Tuple(new_edge)
115115
label_1 = vertex_labels[code_1]
116116
label_2 = vertex_labels[code_2]
117-
new_meta_graph.edge_data[arrange(new_meta_graph, label_1, label_2, code_1, code_2)] = old_meta_graph.edge_data[arrange(
117+
new_meta_graph.edge_data[arrange(new_meta_graph, label_1, label_2)] = old_meta_graph.edge_data[arrange(
118118
old_meta_graph, label_1, label_2
119119
)]
120120
end

src/directedness.jl

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,19 @@ end
1212
arrange(graph, label_1, label_2)
1313
1414
Sort two vertex labels in a default order (useful to uniquely express undirected edges).
15+
For undirected graphs, the default order is based on the labels themselves
16+
to be robust to vertex re-coding, so the labels need to support `<`.
1517
"""
1618
function arrange end
1719

18-
@traitfn function arrange(
19-
::MG, label_1, label_2, _drop...
20-
) where {MG <: MetaGraph; IsDirected{MG}}
20+
@traitfn function arrange(::MG, label_1, label_2) where {MG <: MetaGraph; IsDirected{MG}}
2121
return label_1, label_2
2222
end
2323

24-
@traitfn function arrange(
25-
::MG, label_1, label_2, code_1, code_2
26-
) where {MG <: MetaGraph; !IsDirected{MG}}
27-
if code_1 < code_2
24+
@traitfn function arrange(::MG, label_1, label_2) where {MG <: MetaGraph; !IsDirected{MG}}
25+
if label_1 < label_2
2826
(label_1, label_2)
2927
else
3028
(label_2, label_1)
3129
end
3230
end
33-
34-
@traitfn function arrange(
35-
meta_graph::MG, label_1, label_2
36-
) where {MG <: MetaGraph; !IsDirected{MG}}
37-
return arrange(
38-
meta_graph,
39-
label_1,
40-
label_2,
41-
code_for(meta_graph, label_1),
42-
code_for(meta_graph, label_2),
43-
)
44-
end

src/graphs.jl

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -174,14 +174,18 @@ Add an edge `(label_1, label_2)` to MetaGraph `meta_graph` with metadata `data`.
174174
If the `EdgeData` type of `meta_graph` is `Nothing`, `data` can be omitted.
175175
176176
Return `true` if the edge has been added, `false` otherwise.
177+
If `(label_1, label_2)` already existed, its data is updated to `data` and `false` is returned nonetheless.
177178
"""
178179
function Graphs.add_edge!(meta_graph::MetaGraph, label_1, label_2, data)
179180
if !haskey(meta_graph, label_1) || !haskey(meta_graph, label_2)
180181
return false
181182
end
182183
code_1, code_2 = code_for(meta_graph, label_1), code_for(meta_graph, label_2)
183-
label_tup = arrange(meta_graph, label_1, label_2, code_1, code_2)
184+
label_tup = arrange(meta_graph, label_1, label_2)
184185
meta_graph.edge_data[label_tup] = data
186+
if has_edge(meta_graph.graph, code_1, code_2)
187+
return false
188+
end
185189
ne_prev = ne(meta_graph.graph)
186190
add_edge!(meta_graph.graph, code_1, code_2)
187191
if ne(meta_graph.graph) == ne_prev # undo
@@ -206,16 +210,10 @@ function _rem_vertex!(meta_graph::MetaGraph, label, code)
206210
edge_data = meta_graph.edge_data
207211
last_vertex_code = nv(meta_graph)
208212
for out_neighbor in outneighbors(meta_graph, code)
209-
delete!(
210-
edge_data,
211-
arrange(meta_graph, label, vertex_labels[out_neighbor], code, out_neighbor),
212-
)
213+
delete!(edge_data, arrange(meta_graph, label, vertex_labels[out_neighbor]))
213214
end
214215
for in_neighbor in inneighbors(meta_graph, code)
215-
delete!(
216-
edge_data,
217-
arrange(meta_graph, vertex_labels[in_neighbor], label, in_neighbor, code),
218-
)
216+
delete!(edge_data, arrange(meta_graph, vertex_labels[in_neighbor], label))
219217
end
220218
removed = rem_vertex!(meta_graph.graph, code)
221219
if removed
@@ -244,9 +242,9 @@ end
244242

245243
function Graphs.rem_edge!(meta_graph::MetaGraph, code_1::Integer, code_2::Integer)
246244
removed = rem_edge!(meta_graph.graph, code_1, code_2)
247-
if removed
245+
if removed # assume that vertex codes were not modified by edge removal
248246
label_1, label_2 = label_for(meta_graph, code_1), label_for(meta_graph, code_2)
249-
delete!(meta_graph.edge_data, arrange(meta_graph, label_1, label_2, code_1, code_2))
247+
delete!(meta_graph.edge_data, arrange(meta_graph, label_1, label_2))
250248
end
251249
return removed
252250
end

src/weights.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ function Base.getindex(meta_weights::MetaWeights, code_1::Integer, code_2::Integ
6565
labels = meta_graph.vertex_labels
6666
weight_function = get_weight_function(meta_graph)
6767
arranged_label_1, arranged_label_2 = arrange(
68-
meta_graph, labels[code_1], labels[code_2], code_1, code_2
68+
meta_graph, labels[code_1], labels[code_2]
6969
)
7070
return weight_function(meta_graph[arranged_label_1, arranged_label_2])
7171
else

test/misc.jl

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ function test_labels_codes(mg::MetaGraph)
88
for (label_1, label_2) in edge_labels(mg)
99
@test has_edge(mg, code_for(mg, label_1), code_for(mg, label_2))
1010
end
11+
# below: arrange(edges) ⊆ keys of mg.edge_data. then = because same length
12+
for e in edge_labels(mg)
13+
@test_logs mg[e...] # no log, no error
14+
end
15+
@test length(keys(mg.edge_data)) == ne(mg)
1116
for label_1 in labels(mg)
1217
for label_2 in outneighbor_labels(mg, label_1)
1318
@test has_edge(mg, code_for(mg, label_1), code_for(mg, label_2))
@@ -24,17 +29,24 @@ end
2429
:red => (255, 0, 0), :green => (0, 255, 0), :blue => (0, 0, 255)
2530
]
2631
edges_description = [
27-
(:red, :green) => :yellow, (:red, :blue) => :magenta, (:green, :blue) => :cyan
32+
(:green, :red) => :yellow, (:blue, :red) => :magenta, (:blue, :green) => :cyan
2833
]
2934

3035
colors = MetaGraph(graph, vertices_description, edges_description, "additive colors")
3136
test_labels_codes(colors)
3237

38+
# attempt to add an existing edge: non-standard order, different data
39+
@test !add_edge!(colors, :green, :blue, :teal)
40+
@test length(colors.edge_data) == ne(colors)
41+
@test colors[:blue, :green] == :teal
42+
3343
# Delete vertex in a copy and test again
3444

3545
colors_copy = copy(colors)
3646
rem_vertex!(colors_copy, 1)
37-
test_labels_codes(colors)
47+
test_labels_codes(colors_copy)
48+
@test ne(colors_copy) == 1
49+
@test colors_copy[:blue, :green] == :teal
3850
end
3951

4052
@testset verbose = true "Short-form add_vertex!/add_edge!" begin
@@ -45,6 +57,7 @@ end
4557
@test add_vertex!(mg, :A)
4658
@test add_vertex!(mg, :B)
4759
@test add_edge!(mg, :A, :B)
60+
@test !add_edge!(mg, :A, :C)
4861

4962
# long-form
5063
mg2 = MetaGraph(

test/tutorial/1_basics.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ colors = MetaGraph(
1616
graph_data="additive colors", # tag for the whole graph
1717
)
1818

19-
# The `label_type` argument defines how vertices will be referred to, it can be anything you want (although integer types are generally discouraged, to avoid confusion with the vertex codes used by Graphs.jl). The `vertex_data_type` and `edge_data_type` type determine what kind of data will be associated with each vertex and edge. Finally, `graph_data` can contain an arbitrary object associated with the graph as a whole.
19+
# The `label_type` argument defines how vertices will be referred to. It can be anything you want, provided that pairs of labels can be compared with `<`. Integer types are generally discouraged, to avoid confusion with the vertex codes used by Graphs.jl. The `vertex_data_type` and `edge_data_type` type determine what kind of data will be associated with each vertex and edge. Finally, `graph_data` can contain an arbitrary object associated with the graph as a whole.
2020

2121
# If you don't care about labels at all, using the integer vertex codes as labels may be reasonable. Just keep in mind that labels do not change with vertex deletion, whereas vertex codes get decreased, so the coherence will be broken.
2222

test/tutorial/2_graphs.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ cities[:Paris, :Berlin] = 878;
3535
is_directed(cities)
3636
@test @inferred !is_directed(cities) #src
3737
@test !istrait(IsDirected{typeof(cities)}) #src
38-
@test MetaGraphsNext.arrange(cities, :London, :Paris) == (:Paris, :London) #src
38+
@test MetaGraphsNext.arrange(cities, :London, :Paris) == (:London, :Paris) #src
39+
@test MetaGraphsNext.arrange(cities, :Paris, :London) == (:London, :Paris) #src
3940
#-
4041
eltype(cities)
4142
@test @inferred eltype(cities) == Int #src

0 commit comments

Comments
 (0)