From e93d6a9c9d7dbb56a15bd73ad8a84137cbcbeb95 Mon Sep 17 00:00:00 2001 From: mtfishman Date: Sun, 14 Apr 2024 17:42:24 -0400 Subject: [PATCH 1/5] Return hash map/set for vertices --- README.md | 26 ++++----- src/abstractnamedgraph.jl | 107 +++++++++++++------------------------- src/distance.jl | 19 +++++-- src/namedgraph.jl | 40 ++++++++++++-- test/test_namedgraph.jl | 6 +-- 5 files changed, 102 insertions(+), 96 deletions(-) diff --git a/README.md b/README.md index 335f11f..5fb375f 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ julia> using NamedGraphs julia> g = NamedGraph(grid((4,)), ["A", "B", "C", "D"]) NamedGraph{String} with 4 vertices: -4-element Vector{String}: +4-element Indices{String} "A" "B" "C" @@ -61,7 +61,7 @@ and 3 edge(s): julia> g = NamedGraph(grid((4,)); vertices=["A", "B", "C", "D"]) # Same as above NamedGraph{String} with 4 vertices: -4-element Vector{String}: +4-element Indices{String} "A" "B" "C" @@ -94,7 +94,7 @@ julia> neighbors(g, "B") julia> g[["A", "B"]] NamedGraph{String} with 2 vertices: -2-element Vector{String}: +2-element Indices{String} "A" "B" @@ -119,7 +119,7 @@ the vertex names label cartesian coordinates: ```julia julia> g = NamedGraph(grid((2, 2)); vertices=(2, 2)) NamedGraph{Tuple{Int64, Int64}} with 4 vertices: -4-element Vector{Tuple{Int64, Int64}}: +4-element Indices{Tuple{Int64, Int64}} (1, 1) (2, 1) (1, 2) @@ -162,7 +162,7 @@ You can use vertex names to get [induced subgraphs](https://juliagraphs.org/Grap ```julia julia> subgraph(v -> v[1] == 1, g) NamedGraph{Tuple{Int64, Int64}} with 2 vertices: -2-element Vector{Tuple{Int64, Int64}}: +2-element Indices{Tuple{Int64, Int64}} (1, 1) (1, 2) @@ -172,7 +172,7 @@ and 1 edge(s): julia> subgraph(v -> v[2] == 2, g) NamedGraph{Tuple{Int64, Int64}} with 2 vertices: -2-element Vector{Tuple{Int64, Int64}}: +2-element Indices{Tuple{Int64, Int64}} (1, 2) (2, 2) @@ -182,7 +182,7 @@ and 1 edge(s): julia> g[[(1, 1), (2, 2)]] NamedGraph{Tuple{Int64, Int64}} with 2 vertices: -2-element Vector{Tuple{Int64, Int64}}: +2-element Indices{Tuple{Int64, Int64}} (1, 1) (2, 2) @@ -200,7 +200,7 @@ You can also take [disjoint unions](https://en.wikipedia.org/wiki/Disjoint_union ```julia julia> g₁ = g NamedGraph{Tuple{Int64, Int64}} with 4 vertices: -4-element Vector{Tuple{Int64, Int64}}: +4-element Indices{Tuple{Int64, Int64}} (1, 1) (2, 1) (1, 2) @@ -215,7 +215,7 @@ and 4 edge(s): julia> g₂ = g NamedGraph{Tuple{Int64, Int64}} with 4 vertices: -4-element Vector{Tuple{Int64, Int64}}: +4-element Indices{Tuple{Int64, Int64}} (1, 1) (2, 1) (1, 2) @@ -230,7 +230,7 @@ and 4 edge(s): julia> disjoint_union(g₁, g₂) NamedGraph{Tuple{Tuple{Int64, Int64}, Int64}} with 8 vertices: -8-element Vector{Tuple{Tuple{Int64, Int64}, Int64}}: +8-element Indices{Tuple{Tuple{Int64, Int64}, Int64}} ((1, 1), 1) ((2, 1), 1) ((1, 2), 1) @@ -253,7 +253,7 @@ and 8 edge(s): julia> g₁ ⊔ g₂ # Same as above NamedGraph{Tuple{Tuple{Int64, Int64}, Int64}} with 8 vertices: -8-element Vector{Tuple{Tuple{Int64, Int64}, Int64}}: +8-element Indices{Tuple{Tuple{Int64, Int64}, Int64}} ((1, 1), 1) ((2, 1), 1) ((1, 2), 1) @@ -293,7 +293,7 @@ The original graphs can be obtained from subgraphs: ```julia julia> rename_vertices(v -> v[1], subgraph(v -> v[2] == 1, g₁ ⊔ g₂)) NamedGraph{Tuple{Int64, Int64}} with 4 vertices: -4-element Vector{Tuple{Int64, Int64}}: +4-element Indices{Tuple{Int64, Int64}} (1, 1) (2, 1) (1, 2) @@ -308,7 +308,7 @@ and 4 edge(s): julia> rename_vertices(v -> v[1], subgraph(v -> v[2] == 2, g₁ ⊔ g₂)) NamedGraph{Tuple{Int64, Int64}} with 4 vertices: -4-element Vector{Tuple{Int64, Int64}}: +4-element Indices{Tuple{Int64, Int64}} (1, 1) (2, 1) (1, 2) diff --git a/src/abstractnamedgraph.jl b/src/abstractnamedgraph.jl index 75add73..fa6bf96 100644 --- a/src/abstractnamedgraph.jl +++ b/src/abstractnamedgraph.jl @@ -12,11 +12,8 @@ parent_graph(graph::AbstractNamedGraph) = not_implemented() # ? parent_graph_type(graph::AbstractNamedGraph) = not_implemented() -function Graphs.has_vertex(graph::AbstractNamedGraph, vertex) - return not_implemented() -end - -parent_vertextype(graph::AbstractNamedGraph) = vertextype(parent_graph(graph)) +rem_vertex!(graph::AbstractNamedGraph, vertex) = not_implemented() +add_vertex!(graph::AbstractNamedGraph, vertex) = not_implemented() # Convert vertex to parent vertex # Inverse map of `parent_vertex_to_vertex`. @@ -24,19 +21,7 @@ vertex_to_parent_vertex(graph::AbstractNamedGraph, vertex) = not_implemented() # Convert parent vertex to vertex. # Use `vertices`, assumes `vertices` is indexed by a parent vertex (a Vector for linear indexed parent vertices, a dictionary in general). -function parent_vertex_to_vertex(graph::AbstractNamedGraph, parent_vertex) - return vertices(graph)[parent_vertex] -end - -Graphs.SimpleDiGraph(graph::AbstractNamedGraph) = SimpleDiGraph(parent_graph(graph)) - -# Convenient shorthands for using in higher order functions like `map`. -function vertex_to_parent_vertex(graph::AbstractNamedGraph) - return Base.Fix1(vertex_to_parent_vertex, graph) -end -function parent_vertex_to_vertex(graph::AbstractNamedGraph) - return Base.Fix1(parent_vertex_to_vertex, graph) -end +parent_vertex_to_vertex(graph::AbstractNamedGraph, parent_vertex) = not_implemented() # TODO: rename `edge_type`? edgetype(graph::AbstractNamedGraph) = not_implemented() @@ -61,6 +46,39 @@ convert_vertextype(::Type, ::AbstractNamedGraph) = not_implemented() # end copy(graph::AbstractNamedGraph) = not_implemented() +# This should be overloaded for multi-dimensional indexing. +# Get the subset of vertices of the graph, for example +# for an input slice `subvertices(graph, "X", :)`. +function subvertices(graph::AbstractNamedGraph, vertices) + return not_implemented() +end + +function merge_vertices!( + graph::AbstractNamedGraph, merge_vertices; merged_vertex=first(merge_vertices) +) + return not_implemented() +end + +# +# Derived interface +# + +function Graphs.has_vertex(graph::AbstractNamedGraph, vertex) + return vertex ∈ vertices(graph) +end + +parent_vertextype(graph::AbstractNamedGraph) = vertextype(parent_graph(graph)) + +Graphs.SimpleDiGraph(graph::AbstractNamedGraph) = SimpleDiGraph(parent_graph(graph)) + +# Convenient shorthands for using in higher order functions like `map`. +function vertex_to_parent_vertex(graph::AbstractNamedGraph) + return Base.Fix1(vertex_to_parent_vertex, graph) +end +function parent_vertex_to_vertex(graph::AbstractNamedGraph) + return Base.Fix1(parent_vertex_to_vertex, graph) +end + zero(G::Type{<:AbstractNamedGraph}) = G() # TODO: Implement using `copyto!`? @@ -78,13 +96,6 @@ eltype(graph::AbstractNamedGraph) = eltype(vertices(graph)) parent_eltype(graph::AbstractNamedGraph) = eltype(parent_graph(graph)) -# This should be overloaded for multi-dimensional indexing. -# Get the subset of vertices of the graph, for example -# for an input slice `subvertices(graph, "X", :)`. -function subvertices(graph::AbstractNamedGraph, vertices) - return not_implemented() -end - function subvertices(graph::AbstractNamedGraph{V}, vertices::Vector{V}) where {V} return vertices end @@ -429,45 +440,6 @@ function union( return union(union(graph1, graph2), graph3, graph_rest...) end -function rem_vertex!(graph::AbstractNamedGraph, vertex) - if vertex ∉ vertices(graph) - return false - end - - parent_vertex = vertex_to_parent_vertex(graph, vertex) - rem_vertex!(parent_graph(graph), parent_vertex) - - # Insert the last vertex into the position of the vertex - # that is being deleted, then remove the last vertex. - last_vertex = last(vertices(graph)) - vertices(graph)[parent_vertex] = last_vertex - last_vertex = pop!(vertices(graph)) - - # Insert the last vertex into the position of the vertex - # that is being deleted, then remove the last vertex. - # TODO: Make this more generic - graph.vertex_to_parent_vertex[last_vertex] = parent_vertex - # TODO: Make this more generic - delete!(graph.vertex_to_parent_vertex, vertex) - - return true -end - -function add_vertex!(graph::AbstractNamedGraph, vertex) - if vertex ∈ vertices(graph) - return false - end - - add_vertex!(parent_graph(graph)) - # Update the vertex list - push!(vertices(graph), vertex) - # Update the reverse map - # TODO: Make this more generic - insert!(graph.vertex_to_parent_vertex, vertex, last(parent_vertices(graph))) - - return true -end - is_directed(G::Type{<:AbstractNamedGraph}) = is_directed(parent_graph_type(G)) is_directed(graph::AbstractNamedGraph) = is_directed(parent_graph(graph)) @@ -508,18 +480,11 @@ function connected_components(graph::AbstractNamedGraph) return map(parent_vertices_to_vertices(graph), parent_connected_components) end -function merge_vertices!( - graph::AbstractNamedGraph, merge_vertices; merged_vertex=first(merge_vertices) -) - return not_implemented() -end - function merge_vertices( graph::AbstractNamedGraph, merge_vertices; merged_vertex=first(merge_vertices) ) merged_graph = copy(graph) add_vertex!(merged_graph, merged_vertex) - for vertex in merge_vertices for e in incident_edges(graph, vertex; dir=:both) merged_edge = rename_vertices(v -> v == vertex ? merged_vertex : v, e) diff --git a/src/distance.jl b/src/distance.jl index db66606..c7fb7cc 100644 --- a/src/distance.jl +++ b/src/distance.jl @@ -27,10 +27,21 @@ function eccentricities(graph::AbstractGraph, vs, distmx=weights(graph)) return map(vertex -> eccentricity(graph, vertex, distmx), vs) end +function eccentricities_center(eccentricities) + rad = eccentricities_radius(eccentricities) + return filter(x -> eccentricities[x] == rad, 1:length(eccentricities)) +end +function eccentricities_periphery(eccentricities) + diam = eccentricities_diameter(eccentricities) + return filter(x -> eccentricities[x] == diam, 1:length(eccentricities)) +end +eccentricities_radius(eccentricities) = minimum(eccentricities) +eccentricities_diameter(eccentricities) = maximum(eccentricities) + function _center(graph::AbstractNamedGraph, distmx) # TODO: Why does this return the parent vertices? return parent_vertices_to_vertices( - graph, center(eccentricities(graph, vertices(graph), distmx)) + graph, eccentricities_center(eccentricities(graph, vertices(graph), distmx)) ) end @@ -44,7 +55,7 @@ function center(graph::AbstractNamedGraph, distmx::AbstractMatrix) end function _radius(graph::AbstractNamedGraph, distmx) - return radius(eccentricities(graph, vertices(graph), distmx)) + return eccentricities_radius(eccentricities(graph, vertices(graph), distmx)) end function radius(graph::AbstractNamedGraph, distmx=weights(graph)) @@ -57,7 +68,7 @@ function radius(graph::AbstractNamedGraph, distmx::AbstractMatrix) end function _diameter(graph::AbstractNamedGraph, distmx) - return diameter(eccentricities(graph, vertices(graph), distmx)) + return eccentricities_diameter(eccentricities(graph, vertices(graph), distmx)) end function diameter(graph::AbstractNamedGraph, distmx=weights(graph)) @@ -72,7 +83,7 @@ end function _periphery(graph::AbstractNamedGraph, distmx) # TODO: Why does this return the parent vertices? return parent_vertices_to_vertices( - graph, periphery(eccentricities(graph, vertices(graph), distmx)) + graph, eccentricities_periphery(eccentricities(graph, vertices(graph), distmx)) ) end diff --git a/src/namedgraph.jl b/src/namedgraph.jl index 6e52c50..53d33f0 100644 --- a/src/namedgraph.jl +++ b/src/namedgraph.jl @@ -1,18 +1,48 @@ struct GenericNamedGraph{V,G<:AbstractSimpleGraph{Int}} <: AbstractNamedGraph{V} parent_graph::G - vertices::Vector{V} + parent_vertex_to_vertex::Vector{V} vertex_to_parent_vertex::Dictionary{V,Int} end # AbstractNamedGraph required interface. parent_graph_type(G::Type{<:GenericNamedGraph}) = fieldtype(G, :parent_graph) parent_graph(graph::GenericNamedGraph) = getfield(graph, :parent_graph) -vertices(graph::GenericNamedGraph) = getfield(graph, :vertices) function vertex_to_parent_vertex(graph::GenericNamedGraph, vertex) return graph.vertex_to_parent_vertex[vertex] end -function Graphs.has_vertex(graph::GenericNamedGraph, vertex) - return haskey(graph.vertex_to_parent_vertex, vertex) +function parent_vertex_to_vertex(graph::GenericNamedGraph, parent_vertex) + return graph.parent_vertex_to_vertex[parent_vertex] +end +vertices(graph::GenericNamedGraph) = keys(graph.vertex_to_parent_vertex) + +function add_vertex!(graph::GenericNamedGraph, vertex) + if vertex ∈ vertices(graph) + return false + end + add_vertex!(graph.parent_graph) + # Update the forward map + push!(graph.parent_vertex_to_vertex, vertex) + # Update the reverse map + insert!(graph.vertex_to_parent_vertex, vertex, nv(graph.parent_graph)) + return true +end + +function rem_vertex!(graph::GenericNamedGraph, vertex) + if vertex ∉ vertices(graph) + return false + end + parent_vertex = graph.vertex_to_parent_vertex[vertex] + rem_vertex!(graph.parent_graph, parent_vertex) + # Insert the last vertex into the position of the vertex + # that is being deleted, then remove the last vertex. + last_vertex = last(graph.parent_vertex_to_vertex) + graph.parent_vertex_to_vertex[parent_vertex] = last_vertex + last_vertex = pop!(graph.parent_vertex_to_vertex) + # Insert the last vertex into the position of the vertex + # that is being deleted, then remove the last vertex. + graph.vertex_to_parent_vertex[last_vertex] = parent_vertex + delete!(graph.vertex_to_parent_vertex, vertex) + return true end function convert_vertextype(V::Type, graph::GenericNamedGraph) @@ -172,7 +202,7 @@ end is_directed(G::Type{<:GenericNamedGraph}) = is_directed(parent_graph_type(G)) # TODO: Implement an edgelist version -function induced_subgraph(graph::AbstractNamedGraph, subvertices::Vector) +function induced_subgraph(graph::AbstractNamedGraph, subvertices) subgraph = typeof(graph)(subvertices) subvertices_set = Set(subvertices) for src in subvertices diff --git a/test/test_namedgraph.jl b/test/test_namedgraph.jl index 37582e6..e293246 100644 --- a/test/test_namedgraph.jl +++ b/test/test_namedgraph.jl @@ -154,11 +154,11 @@ end @test indegree(g, "D") == 0 @test outdegree(g, "D") == 0 - @test degrees(g) == [1, 2, 1, 0] + @test degrees(g) == Dictionary(vertices(g), [1, 2, 1, 0]) @test degrees(g, ["B", "C"]) == [2, 1] @test degrees(g, Indices(["B", "C"])) == Dictionary(["B", "C"], [2, 1]) - @test indegrees(g) == [0, 1, 1, 0] - @test outdegrees(g) == [1, 1, 0, 0] + @test indegrees(g) == Dictionary(vertices(g), [0, 1, 1, 0]) + @test outdegrees(g) == Dictionary(vertices(g), [1, 1, 0, 0]) h = degree_histogram(g) @test h[0] == 1 From 9a944fa498204a7db56daa18ffa1bb51e0968da4 Mon Sep 17 00:00:00 2001 From: mtfishman Date: Sun, 14 Apr 2024 20:01:18 -0400 Subject: [PATCH 2/5] Fix some tests --- src/Graphs/abstractgraph.jl | 3 ++- src/distance.jl | 20 +++++++------------- src/steiner_tree/steiner_tree.jl | 2 +- test/test_namedgraph.jl | 2 +- 4 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/Graphs/abstractgraph.jl b/src/Graphs/abstractgraph.jl index f24e003..c73ecd0 100644 --- a/src/Graphs/abstractgraph.jl +++ b/src/Graphs/abstractgraph.jl @@ -65,8 +65,9 @@ function rename_vertices(g::AbstractGraph, name_map) return rename_vertices(v -> name_map[v], g) end +# TODO: This isn't really a generic `AbstractGraph` function! function permute_vertices(graph::AbstractGraph, permutation::Vector) - return subgraph(graph, vertices(graph)[permutation]) + return subgraph(graph, parent_vertices_to_vertices(graph, permutation)) end # Uniform interface for `outneighbors`, `inneighbors`, and `all_neighbors` diff --git a/src/distance.jl b/src/distance.jl index c7fb7cc..f37ed20 100644 --- a/src/distance.jl +++ b/src/distance.jl @@ -21,28 +21,25 @@ end # function eccentricity(graph::AbstractNamedGraph, ::AbstractMatrix) -eccentricities(graph::AbstractGraph) = eccentricities(graph, Indices(vertices(graph))) +eccentricities(graph::AbstractGraph) = eccentricities(graph, vertices(graph)) function eccentricities(graph::AbstractGraph, vs, distmx=weights(graph)) return map(vertex -> eccentricity(graph, vertex, distmx), vs) end function eccentricities_center(eccentricities) - rad = eccentricities_radius(eccentricities) - return filter(x -> eccentricities[x] == rad, 1:length(eccentricities)) + rad = eccentricities_radius(eccentricities) + return filter(x -> eccentricities[x] == rad, keys(eccentricities)) end function eccentricities_periphery(eccentricities) - diam = eccentricities_diameter(eccentricities) - return filter(x -> eccentricities[x] == diam, 1:length(eccentricities)) + diam = eccentricities_diameter(eccentricities) + return filter(x -> eccentricities[x] == diam, keys(eccentricities)) end eccentricities_radius(eccentricities) = minimum(eccentricities) eccentricities_diameter(eccentricities) = maximum(eccentricities) function _center(graph::AbstractNamedGraph, distmx) - # TODO: Why does this return the parent vertices? - return parent_vertices_to_vertices( - graph, eccentricities_center(eccentricities(graph, vertices(graph), distmx)) - ) + return eccentricities_center(eccentricities(graph, vertices(graph), distmx)) end function center(graph::AbstractNamedGraph, distmx=weights(graph)) @@ -81,10 +78,7 @@ function diameter(graph::AbstractNamedGraph, distmx::AbstractMatrix) end function _periphery(graph::AbstractNamedGraph, distmx) - # TODO: Why does this return the parent vertices? - return parent_vertices_to_vertices( - graph, eccentricities_periphery(eccentricities(graph, vertices(graph), distmx)) - ) + return eccentricities_periphery(eccentricities(graph, vertices(graph), distmx)) end function periphery(graph::AbstractNamedGraph, distmx=weights(graph)) diff --git a/src/steiner_tree/steiner_tree.jl b/src/steiner_tree/steiner_tree.jl index 4bf826f..7b425aa 100644 --- a/src/steiner_tree/steiner_tree.jl +++ b/src/steiner_tree/steiner_tree.jl @@ -6,5 +6,5 @@ vertices_to_parent_vertices(g, term_vert), dist_matrix_to_parent_dist_matrix(g, distmx), ) - return typeof(g)(parent_tree, vertices(g)[1:nv(parent_tree)]) + return typeof(g)(parent_tree, parent_vertices_to_vertices(g, Base.OneTo(nv(parent_tree)))) end diff --git a/test/test_namedgraph.jl b/test/test_namedgraph.jl index e293246..0055b33 100644 --- a/test/test_namedgraph.jl +++ b/test/test_namedgraph.jl @@ -488,7 +488,7 @@ end @test eccentricities(g, Indices([(1, 2), (2, 2)])) == Dictionary([(1, 2), (2, 2)], [3, 2]) @test eccentricities(g) == Dictionary(vertices(g), [4, 3, 4, 3, 2, 3, 4, 3, 4]) - @test center(g) == [(2, 2)] + @test issetequal(center(g), [(2, 2)]) @test radius(g) == 2 @test diameter(g) == 4 @test issetequal(periphery(g), [(1, 1), (3, 1), (1, 3), (3, 3)]) From 61bb29ab7a6448f20d531bf48e5eb4df50aacb22 Mon Sep 17 00:00:00 2001 From: mtfishman Date: Sun, 14 Apr 2024 23:38:09 -0400 Subject: [PATCH 3/5] Fix tests --- README.md | 40 +++++++++---------- examples/Project.toml | 1 + examples/README.jl | 12 +++--- src/Graphs/abstractgraph.jl | 4 +- .../abstractpartitionedgraph.jl | 3 ++ .../partitionedgraphs/partitionedgraph.jl | 23 +++++++---- src/abstractnamedgraph.jl | 25 ++++++++---- src/namedgraph.jl | 25 +++++++++--- src/shortestpaths.jl | 13 ++++-- src/traversals/dfs.jl | 23 +++++++---- test/Project.toml | 1 + test/test_partitionedgraph.jl | 7 +++- test/test_trees_and_forests.jl | 6 +-- 13 files changed, 116 insertions(+), 67 deletions(-) diff --git a/README.md b/README.md index 5fb375f..eed2a84 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ julia> using NamedGraphs julia> g = NamedGraph(grid((4,)), ["A", "B", "C", "D"]) NamedGraph{String} with 4 vertices: -4-element Indices{String} +4-element Dictionaries.Indices{String} "A" "B" "C" @@ -61,7 +61,7 @@ and 3 edge(s): julia> g = NamedGraph(grid((4,)); vertices=["A", "B", "C", "D"]) # Same as above NamedGraph{String} with 4 vertices: -4-element Indices{String} +4-element Dictionaries.Indices{String} "A" "B" "C" @@ -92,9 +92,9 @@ julia> neighbors(g, "B") "A" "C" -julia> g[["A", "B"]] +julia> subgraph(g, ["A", "B"]) NamedGraph{String} with 2 vertices: -2-element Indices{String} +2-element Dictionaries.Indices{String} "A" "B" @@ -113,13 +113,12 @@ Graph operations are implemented by mapping back and forth between the generaliz It is natural to use tuples of integers as the names for the vertices of graphs with grid connectivities. -For this, we use the convention that if a tuple is input, it is interpreted as the grid size and -the vertex names label cartesian coordinates: +For example: ```julia -julia> g = NamedGraph(grid((2, 2)); vertices=(2, 2)) +julia> g = NamedGraph(grid((2, 2)); vertices=Tuple.(CartesianIndices((2, 2)))) NamedGraph{Tuple{Int64, Int64}} with 4 vertices: -4-element Indices{Tuple{Int64, Int64}} +4-element Dictionaries.Indices{Tuple{Int64, Int64}} (1, 1) (2, 1) (1, 2) @@ -134,6 +133,7 @@ and 4 edge(s): ``` +In the future we will provide a shorthand notation for this, such as `cartesian_graph(grid((2, 2)), (2, 2))`. Internally the vertices are all stored as tuples with a label in each dimension. @@ -162,7 +162,7 @@ You can use vertex names to get [induced subgraphs](https://juliagraphs.org/Grap ```julia julia> subgraph(v -> v[1] == 1, g) NamedGraph{Tuple{Int64, Int64}} with 2 vertices: -2-element Indices{Tuple{Int64, Int64}} +2-element Dictionaries.Indices{Tuple{Int64, Int64}} (1, 1) (1, 2) @@ -172,7 +172,7 @@ and 1 edge(s): julia> subgraph(v -> v[2] == 2, g) NamedGraph{Tuple{Int64, Int64}} with 2 vertices: -2-element Indices{Tuple{Int64, Int64}} +2-element Dictionaries.Indices{Tuple{Int64, Int64}} (1, 2) (2, 2) @@ -180,9 +180,9 @@ and 1 edge(s): (1, 2) => (2, 2) -julia> g[[(1, 1), (2, 2)]] +julia> subgraph(g, [(1, 1), (2, 2)]) NamedGraph{Tuple{Int64, Int64}} with 2 vertices: -2-element Indices{Tuple{Int64, Int64}} +2-element Dictionaries.Indices{Tuple{Int64, Int64}} (1, 1) (2, 2) @@ -191,16 +191,12 @@ and 0 edge(s): ``` -Note that this is similar to multidimensional array slicing, and we may support syntax like `subgraph(v, 1, :)` in the future. - - - You can also take [disjoint unions](https://en.wikipedia.org/wiki/Disjoint_union) or concatenations of graphs: ```julia julia> g₁ = g NamedGraph{Tuple{Int64, Int64}} with 4 vertices: -4-element Indices{Tuple{Int64, Int64}} +4-element Dictionaries.Indices{Tuple{Int64, Int64}} (1, 1) (2, 1) (1, 2) @@ -215,7 +211,7 @@ and 4 edge(s): julia> g₂ = g NamedGraph{Tuple{Int64, Int64}} with 4 vertices: -4-element Indices{Tuple{Int64, Int64}} +4-element Dictionaries.Indices{Tuple{Int64, Int64}} (1, 1) (2, 1) (1, 2) @@ -230,7 +226,7 @@ and 4 edge(s): julia> disjoint_union(g₁, g₂) NamedGraph{Tuple{Tuple{Int64, Int64}, Int64}} with 8 vertices: -8-element Indices{Tuple{Tuple{Int64, Int64}, Int64}} +8-element Dictionaries.Indices{Tuple{Tuple{Int64, Int64}, Int64}} ((1, 1), 1) ((2, 1), 1) ((1, 2), 1) @@ -253,7 +249,7 @@ and 8 edge(s): julia> g₁ ⊔ g₂ # Same as above NamedGraph{Tuple{Tuple{Int64, Int64}, Int64}} with 8 vertices: -8-element Indices{Tuple{Tuple{Int64, Int64}, Int64}} +8-element Dictionaries.Indices{Tuple{Tuple{Int64, Int64}, Int64}} ((1, 1), 1) ((2, 1), 1) ((1, 2), 1) @@ -293,7 +289,7 @@ The original graphs can be obtained from subgraphs: ```julia julia> rename_vertices(v -> v[1], subgraph(v -> v[2] == 1, g₁ ⊔ g₂)) NamedGraph{Tuple{Int64, Int64}} with 4 vertices: -4-element Indices{Tuple{Int64, Int64}} +4-element Dictionaries.Indices{Tuple{Int64, Int64}} (1, 1) (2, 1) (1, 2) @@ -308,7 +304,7 @@ and 4 edge(s): julia> rename_vertices(v -> v[1], subgraph(v -> v[2] == 2, g₁ ⊔ g₂)) NamedGraph{Tuple{Int64, Int64}} with 4 vertices: -4-element Indices{Tuple{Int64, Int64}} +4-element Dictionaries.Indices{Tuple{Int64, Int64}} (1, 1) (2, 1) (1, 2) diff --git a/examples/Project.toml b/examples/Project.toml index 295df54..9c9817e 100644 --- a/examples/Project.toml +++ b/examples/Project.toml @@ -1,3 +1,4 @@ [deps] Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6" NamedGraphs = "678767b0-92e7-4007-89e4-4527a8725b19" +Weave = "44d3d7a6-8a23-5bf8-98c5-b353f8df5ec9" diff --git a/examples/README.jl b/examples/README.jl index e3cbe5c..2fa71d7 100644 --- a/examples/README.jl +++ b/examples/README.jl @@ -37,19 +37,19 @@ has_vertex(g, "A") has_edge(g, "A" => "B") has_edge(g, "A" => "C") neighbors(g, "B") -g[["A", "B"]] +subgraph(g, ["A", "B"]) #' Internally, this type wraps a `SimpleGraph`, and stores a `Dictionary` from the [Dictionaries.jl](https://github.com/andyferris/Dictionaries.jl) package that maps the vertex names to the linear indices of the underlying `SimpleGraph`. #' Graph operations are implemented by mapping back and forth between the generalized named vertices and the linear index vertices of the `SimpleGraph`. #' It is natural to use tuples of integers as the names for the vertices of graphs with grid connectivities. -#' For this, we use the convention that if a tuple is input, it is interpreted as the grid size and -#' the vertex names label cartesian coordinates: +#' For example: #+ term=true -g = NamedGraph(grid((2, 2)); vertices=(2, 2)) +g = NamedGraph(grid((2, 2)); vertices=Tuple.(CartesianIndices((2, 2)))) +#' In the future we will provide a shorthand notation for this, such as `cartesian_graph(grid((2, 2)), (2, 2))`. #' Internally the vertices are all stored as tuples with a label in each dimension. #' Vertices can be referred to by their tuples: @@ -65,9 +65,7 @@ neighbors(g, (2, 2)) subgraph(v -> v[1] == 1, g) subgraph(v -> v[2] == 2, g) -g[[(1, 1), (2, 2)]] - -#' Note that this is similar to multidimensional array slicing, and we may support syntax like `subgraph(v, 1, :)` in the future. +subgraph(g, [(1, 1), (2, 2)]) #' You can also take [disjoint unions](https://en.wikipedia.org/wiki/Disjoint_union) or concatenations of graphs: #+ term=true diff --git a/src/Graphs/abstractgraph.jl b/src/Graphs/abstractgraph.jl index c73ecd0..394ecfa 100644 --- a/src/Graphs/abstractgraph.jl +++ b/src/Graphs/abstractgraph.jl @@ -57,9 +57,7 @@ vertextype(graph::AbstractGraph) = vertextype(typeof(graph)) # Function `f` maps original vertices `vᵢ` of `g` # to new vertices `f(vᵢ)` of the output graph. -function rename_vertices(f::Function, g::AbstractGraph) - return set_vertices(g, f.(vertices(g))) -end +rename_vertices(f::Function, g::AbstractGraph) = not_implemented() function rename_vertices(g::AbstractGraph, name_map) return rename_vertices(v -> name_map[v], g) diff --git a/src/Graphs/partitionedgraphs/abstractpartitionedgraph.jl b/src/Graphs/partitionedgraphs/abstractpartitionedgraph.jl index 169c3fb..74d82df 100644 --- a/src/Graphs/partitionedgraphs/abstractpartitionedgraph.jl +++ b/src/Graphs/partitionedgraphs/abstractpartitionedgraph.jl @@ -31,6 +31,9 @@ parent_graph(pg::AbstractPartitionedGraph) = parent_graph(unpartitioned_graph(pg function vertex_to_parent_vertex(pg::AbstractPartitionedGraph, vertex) return vertex_to_parent_vertex(unpartitioned_graph(pg), vertex) end +function parent_vertex_to_vertex(pg::AbstractPartitionedGraph, parent_vertex) + return parent_vertex_to_vertex(unpartitioned_graph(pg), parent_vertex) +end edgetype(pg::AbstractPartitionedGraph) = edgetype(unpartitioned_graph(pg)) parent_graph_type(pg::AbstractPartitionedGraph) = parent_graph_type(unpartitioned_graph(pg)) nv(pg::AbstractPartitionedGraph, pv::AbstractPartitionVertex) = length(vertices(pg, pv)) diff --git a/src/Graphs/partitionedgraphs/partitionedgraph.jl b/src/Graphs/partitionedgraphs/partitionedgraph.jl index 61984ec..23c5a3e 100644 --- a/src/Graphs/partitionedgraphs/partitionedgraph.jl +++ b/src/Graphs/partitionedgraphs/partitionedgraph.jl @@ -53,7 +53,7 @@ function partitionvertex(pg::PartitionedGraph, vertex) return PartitionVertex(which_partition(pg)[vertex]) end -function partitionvertices(pg::PartitionedGraph, verts::Vector) +function partitionvertices(pg::PartitionedGraph, verts) return unique(partitionvertex(pg, v) for v in verts) end @@ -94,9 +94,7 @@ function edges(pg::PartitionedGraph, partitionedges::Vector{<:PartitionEdge}) return unique(reduce(vcat, [edges(pg, pe) for pe in partitionedges])) end -function boundary_partitionedges( - pg::PartitionedGraph, partitionvertices::Vector{<:PartitionVertex}; kwargs... -) +function boundary_partitionedges(pg::PartitionedGraph, partitionvertices; kwargs...) return PartitionEdge.( boundary_edges(partitioned_graph(pg), parent.(partitionvertices); kwargs...) ) @@ -150,7 +148,7 @@ function delete_from_vertex_map!( end ### PartitionedGraph Specific Functions -function induced_subgraph(pg::PartitionedGraph, vertices::Vector) +function partitionedgraph_induced_subgraph(pg::PartitionedGraph, vertices::Vector) sub_pg_graph, _ = induced_subgraph(unpartitioned_graph(pg), vertices) sub_partitioned_vertices = copy(partitioned_vertices(pg)) for pv in NamedGraphs.vertices(partitioned_graph(pg)) @@ -165,8 +163,17 @@ function induced_subgraph(pg::PartitionedGraph, vertices::Vector) return PartitionedGraph(sub_pg_graph, sub_partitioned_vertices), nothing end -function induced_subgraph( - pg::PartitionedGraph, partitionverts::Vector{V} -) where {V<:PartitionVertex} +function partitionedgraph_induced_subgraph( + pg::PartitionedGraph, partitionverts::Vector{<:PartitionVertex} +) return induced_subgraph(pg, vertices(pg, partitionverts)) end + +function Graphs.induced_subgraph(pg::PartitionedGraph, vertices) + return partitionedgraph_induced_subgraph(pg, vertices) +end + +# Fixes ambiguity error with `Graphs.jl`. +function Graphs.induced_subgraph(pg::PartitionedGraph, vertices::Vector{<:Integer}) + return partitionedgraph_induced_subgraph(pg, vertices) +end diff --git a/src/abstractnamedgraph.jl b/src/abstractnamedgraph.jl index fa6bf96..df82183 100644 --- a/src/abstractnamedgraph.jl +++ b/src/abstractnamedgraph.jl @@ -15,6 +15,8 @@ parent_graph_type(graph::AbstractNamedGraph) = not_implemented() rem_vertex!(graph::AbstractNamedGraph, vertex) = not_implemented() add_vertex!(graph::AbstractNamedGraph, vertex) = not_implemented() +rename_vertices(f::Function, g::AbstractNamedGraph) = not_implemented() + # Convert vertex to parent vertex # Inverse map of `parent_vertex_to_vertex`. vertex_to_parent_vertex(graph::AbstractNamedGraph, vertex) = not_implemented() @@ -521,29 +523,38 @@ function tree(graph::AbstractNamedGraph, parents) return t end -function _bfs_tree(graph::AbstractNamedGraph, vertex; kwargs...) +function namedgraph_bfs_tree(graph::AbstractNamedGraph, vertex; kwargs...) return tree(graph, bfs_parents(graph, vertex; kwargs...)) end # Disambiguation from Graphs.bfs_tree function bfs_tree(graph::AbstractNamedGraph, vertex::Integer; kwargs...) - return _bfs_tree(graph, vertex; kwargs...) + return namedgraph_bfs_tree(graph, vertex; kwargs...) +end +function bfs_tree(graph::AbstractNamedGraph, vertex; kwargs...) + return namedgraph_bfs_tree(graph, vertex; kwargs...) end -bfs_tree(graph::AbstractNamedGraph, vertex; kwargs...) = _bfs_tree(graph, vertex; kwargs...) # Returns a Dictionary mapping a vertex to it's parent # vertex in the traversal/spanning tree. -function _bfs_parents(graph::AbstractNamedGraph, vertex; kwargs...) +function namedgraph_bfs_parents(graph::AbstractNamedGraph, vertex; kwargs...) parent_bfs_parents = bfs_parents( parent_graph(graph), vertex_to_parent_vertex(graph, vertex); kwargs... ) - return Dictionary(vertices(graph), parent_vertices_to_vertices(graph, parent_bfs_parents)) + # Works around issue in this `Dictionary` constructor: + # https://github.com/andyferris/Dictionaries.jl/blob/v0.4.1/src/Dictionary.jl#L139-L145 + # when `inds` has holes. This removes the holes. + # TODO: Raise an issue with `Dictionaries.jl`. + ## vertices_graph = Indices(collect(vertices(graph))) + # This makes the vertices ordered according to the parent vertices. + vertices_graph = parent_vertices_to_vertices(graph, parent_vertices(graph)) + return Dictionary(vertices_graph, parent_vertices_to_vertices(graph, parent_bfs_parents)) end # Disambiguation from Graphs.bfs_tree function bfs_parents(graph::AbstractNamedGraph, vertex::Integer; kwargs...) - return _bfs_parents(graph, vertex; kwargs...) + return namedgraph_bfs_parents(graph, vertex; kwargs...) end function bfs_parents(graph::AbstractNamedGraph, vertex; kwargs...) - return _bfs_parents(graph, vertex; kwargs...) + return namedgraph_bfs_parents(graph, vertex; kwargs...) end # diff --git a/src/namedgraph.jl b/src/namedgraph.jl index 53d33f0..bf68953 100644 --- a/src/namedgraph.jl +++ b/src/namedgraph.jl @@ -13,6 +13,8 @@ end function parent_vertex_to_vertex(graph::GenericNamedGraph, parent_vertex) return graph.parent_vertex_to_vertex[parent_vertex] end + +# TODO: Order them according to the internal ordering? vertices(graph::GenericNamedGraph) = keys(graph.vertex_to_parent_vertex) function add_vertex!(graph::GenericNamedGraph, vertex) @@ -38,15 +40,20 @@ function rem_vertex!(graph::GenericNamedGraph, vertex) last_vertex = last(graph.parent_vertex_to_vertex) graph.parent_vertex_to_vertex[parent_vertex] = last_vertex last_vertex = pop!(graph.parent_vertex_to_vertex) - # Insert the last vertex into the position of the vertex - # that is being deleted, then remove the last vertex. graph.vertex_to_parent_vertex[last_vertex] = parent_vertex delete!(graph.vertex_to_parent_vertex, vertex) return true end +function rename_vertices(f::Function, g::GenericNamedGraph) + # TODO: Could be `set_vertices(g, f.(g.parent_vertex_to_vertex))`. + return GenericNamedGraph(g.parent_graph, f.(g.parent_vertex_to_vertex)) +end + function convert_vertextype(V::Type, graph::GenericNamedGraph) - return GenericNamedGraph(parent_graph(graph), convert(Vector{V}, vertices(graph))) + return GenericNamedGraph( + parent_graph(graph), convert(Vector{V}, graph.parent_vertex_to_vertex) + ) end # @@ -182,7 +189,7 @@ end # graph = set_parent_graph(graph, copy(parent_graph(graph))) # graph = set_vertices(graph, copy(vertices(graph))) function copy(graph::GenericNamedGraph) - return GenericNamedGraph(copy(parent_graph(graph)), copy(vertices(graph))) + return GenericNamedGraph(copy(graph.parent_graph), copy(graph.parent_vertex_to_vertex)) end edgetype(G::Type{<:GenericNamedGraph}) = NamedEdge{vertextype(G)} @@ -202,7 +209,7 @@ end is_directed(G::Type{<:GenericNamedGraph}) = is_directed(parent_graph_type(G)) # TODO: Implement an edgelist version -function induced_subgraph(graph::AbstractNamedGraph, subvertices) +function namedgraph_induced_subgraph(graph::AbstractGraph, subvertices) subgraph = typeof(graph)(subvertices) subvertices_set = Set(subvertices) for src in subvertices @@ -215,6 +222,14 @@ function induced_subgraph(graph::AbstractNamedGraph, subvertices) return subgraph, nothing end +function induced_subgraph(graph::AbstractNamedGraph, subvertices) + return namedgraph_induced_subgraph(graph, subvertices) +end + +function induced_subgraph(graph::AbstractNamedGraph, subvertices::Vector{<:Integer}) + return namedgraph_induced_subgraph(graph, subvertices) +end + # # Type aliases # diff --git a/src/shortestpaths.jl b/src/shortestpaths.jl index 21f0fe4..a7fc997 100644 --- a/src/shortestpaths.jl +++ b/src/shortestpaths.jl @@ -28,13 +28,20 @@ function parent_path_state_to_path_state( pᵢ = parent_path_state.parents[i] return iszero(pᵢ) ? i : pᵢ end + # Works around issue in this `Dictionary` constructor: + # https://github.com/andyferris/Dictionaries.jl/blob/v0.4.1/src/Dictionary.jl#L139-L145 + # when `inds` has holes. This removes the holes. + # TODO: Raise an issue with `Dictionaries.jl`. + ## vertices_graph = Indices(collect(vertices(graph))) + # This makes the vertices ordered according to the parent vertices. + vertices_graph = parent_vertices_to_vertices(graph, parent_vertices(graph)) return NamedDijkstraState( Dictionary( - vertices(graph), parent_vertices_to_vertices(graph, parent_path_state_parents) + vertices_graph, parent_vertices_to_vertices(graph, parent_path_state_parents) ), - Dictionary(vertices(graph), parent_path_state.dists), + Dictionary(vertices_graph, parent_path_state.dists), map(x -> parent_vertices_to_vertices(graph, x), parent_path_state.predecessors), - Dictionary(vertices(graph), parent_path_state.pathcounts), + Dictionary(vertices_graph, parent_path_state.pathcounts), parent_vertices_to_vertices(graph, parent_path_state.closest_vertices), ) end diff --git a/src/traversals/dfs.jl b/src/traversals/dfs.jl index 44033fc..84b1b9d 100644 --- a/src/traversals/dfs.jl +++ b/src/traversals/dfs.jl @@ -2,26 +2,35 @@ return parent_vertices_to_vertices(g, topological_sort_by_dfs(parent_graph(g))) end -function _dfs_tree(graph::AbstractNamedGraph, vertex; kwargs...) +function namedgraph_dfs_tree(graph::AbstractNamedGraph, vertex; kwargs...) return tree(graph, dfs_parents(graph, vertex; kwargs...)) end function dfs_tree(graph::AbstractNamedGraph, vertex::Integer; kwargs...) - return _dfs_tree(graph, vertex; kwargs...) + return namedgraph_dfs_tree(graph, vertex; kwargs...) +end +function dfs_tree(graph::AbstractNamedGraph, vertex; kwargs...) + return namedgraph_dfs_tree(graph, vertex; kwargs...) end -dfs_tree(graph::AbstractNamedGraph, vertex; kwargs...) = _dfs_tree(graph, vertex; kwargs...) # Returns a Dictionary mapping a vertex to it's parent # vertex in the traversal/spanning tree. -function _dfs_parents(graph::AbstractNamedGraph, vertex; kwargs...) +function namedgraph_dfs_parents(graph::AbstractNamedGraph, vertex; kwargs...) parent_dfs_parents = dfs_parents( parent_graph(graph), vertex_to_parent_vertex(graph, vertex); kwargs... ) - return Dictionary(vertices(graph), parent_vertices_to_vertices(graph, parent_dfs_parents)) + # Works around issue in this `Dictionary` constructor: + # https://github.com/andyferris/Dictionaries.jl/blob/v0.4.1/src/Dictionary.jl#L139-L145 + # when `inds` has holes. This removes the holes. + # TODO: Raise an issue with `Dictionaries.jl`. + ## vertices_graph = Indices(collect(vertices(graph))) + # This makes the vertices ordered according to the parent vertices. + vertices_graph = parent_vertices_to_vertices(graph, parent_vertices(graph)) + return Dictionary(vertices_graph, parent_vertices_to_vertices(graph, parent_dfs_parents)) end # Disambiguation from Graphs.dfs_tree function dfs_parents(graph::AbstractNamedGraph, vertex::Integer; kwargs...) - return _dfs_parents(graph, vertex; kwargs...) + return namedgraph_dfs_parents(graph, vertex; kwargs...) end function dfs_parents(graph::AbstractNamedGraph, vertex; kwargs...) - return _dfs_parents(graph, vertex; kwargs...) + return namedgraph_dfs_parents(graph, vertex; kwargs...) end diff --git a/test/Project.toml b/test/Project.toml index 82b72d8..073d95f 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -2,6 +2,7 @@ Dictionaries = "85a47980-9c8c-11e8-2b9f-f7ca1fa99fb4" Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6" GraphsFlows = "06909019-6f44-4949-96fc-b9d9aaa02889" +ITensorUnicodePlots = "73163f41-4a9e-479f-8353-73bf94dbd758" KaHyPar = "2a6221f6-aa48-11e9-3542-2d9e0ef01880" Metis = "2679e427-3c69-5b7f-982b-ece356f1e94b" NamedGraphs = "678767b0-92e7-4007-89e4-4527a8725b19" diff --git a/test/test_partitionedgraph.jl b/test/test_partitionedgraph.jl index a551ada..c103a48 100644 --- a/test/test_partitionedgraph.jl +++ b/test/test_partitionedgraph.jl @@ -23,7 +23,7 @@ using Graphs pg = PartitionedGraph(g, partitions) @test vertextype(partitioned_graph(pg)) == Int64 @test vertextype(unpartitioned_graph(pg)) == vertextype(g) - @test isa(partitionvertices(pg), Vector{PartitionVertex{Int64}}) + @test isa(partitionvertices(pg), Dictionary{Int64,PartitionVertex{Int64}}) @test isa(partitionedges(pg), Vector{PartitionEdge{Int64,NamedEdge{Int64}}}) @test is_tree(partitioned_graph(pg)) @test nv(pg) == nx * ny @@ -36,7 +36,10 @@ using Graphs pg = PartitionedGraph(g, partition_dict) @test vertextype(partitioned_graph(pg)) == vertextype(g) @test vertextype(unpartitioned_graph(pg)) == vertextype(g) - @test isa(partitionvertices(pg), Vector{PartitionVertex{Tuple{Int64,Int64}}}) + @test isa( + partitionvertices(pg), + Dictionary{Tuple{Int64,Int64},PartitionVertex{Tuple{Int64,Int64}}}, + ) @test isa( partitionedges(pg), Vector{PartitionEdge{Tuple{Int64,Int64},NamedEdge{Tuple{Int64,Int64}}}}, diff --git a/test/test_trees_and_forests.jl b/test/test_trees_and_forests.jl index ac84342..a42a775 100644 --- a/test/test_trees_and_forests.jl +++ b/test/test_trees_and_forests.jl @@ -1,7 +1,7 @@ using Test using Graphs using NamedGraphs -using NamedGraphs: forest_cover, spanning_tree +using NamedGraphs: all_edges, forest_cover, spanning_tree module TestTreesAndForests using NamedGraphs @@ -22,8 +22,8 @@ end s_tree = spanning_tree(g; alg) @test is_tree(s_tree) - @test Set(vertices(s_tree)) == Set(vertices(g)) - @test issubset(Set(edges(s_tree)), Set(edges(g))) + @test issetequal(vertices(s_tree), vertices(g)) + @test issubset(all_edges(s_tree), all_edges(g)) end @testset "Test Forest Cover $g_string" for (g_string, g) in TestTreesAndForests.gs From 68da3fe2f6baa4d3cec56aabbe7ffa39f8c8d0ee Mon Sep 17 00:00:00 2001 From: mtfishman Date: Sun, 14 Apr 2024 23:44:57 -0400 Subject: [PATCH 4/5] Bump to v0.2 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 633bd4d..0742256 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "NamedGraphs" uuid = "678767b0-92e7-4007-89e4-4527a8725b19" authors = ["Matthew Fishman and contributors"] -version = "0.1.25" +version = "0.2.0" [deps] AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c" From c223a00bf559e5ab35b422c7d105cfb37df78141 Mon Sep 17 00:00:00 2001 From: mtfishman Date: Mon, 15 Apr 2024 09:00:05 -0400 Subject: [PATCH 5/5] Remove ITensorUnicodePlots test dependency --- test/Project.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/test/Project.toml b/test/Project.toml index 073d95f..82b72d8 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -2,7 +2,6 @@ Dictionaries = "85a47980-9c8c-11e8-2b9f-f7ca1fa99fb4" Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6" GraphsFlows = "06909019-6f44-4949-96fc-b9d9aaa02889" -ITensorUnicodePlots = "73163f41-4a9e-479f-8353-73bf94dbd758" KaHyPar = "2a6221f6-aa48-11e9-3542-2d9e0ef01880" Metis = "2679e427-3c69-5b7f-982b-ece356f1e94b" NamedGraphs = "678767b0-92e7-4007-89e4-4527a8725b19"