Skip to content

Commit

Permalink
Remove NamedDimGraph, refactor and simplify
Browse files Browse the repository at this point in the history
  • Loading branch information
mtfishman authored Nov 28, 2022
2 parents 62a5751 + be9798b commit fa74ea8
Show file tree
Hide file tree
Showing 21 changed files with 604 additions and 705 deletions.
6 changes: 3 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
name = "NamedGraphs"
uuid = "678767b0-92e7-4007-89e4-4527a8725b19"
authors = ["Matthew Fishman <[email protected]> and contributors"]
version = "0.0.1"
version = "0.1.0"

[deps]
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
Dictionaries = "85a47980-9c8c-11e8-2b9f-f7ca1fa99fb4"
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
MultiDimDictionaries = "87ff4268-a46e-478f-b30a-76b83dd64e3c"
SimpleTraits = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"

[compat]
AbstractTrees = "0.3, 0.4"
Dictionaries = "0.3"
Graphs = "1"
MultiDimDictionaries = "0.0.1"
SimpleTraits = "0.9"
julia = "1.7"

[extras]
Expand Down
88 changes: 35 additions & 53 deletions examples/README.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#' This packages introduces graph types with named edges, which are built on top of the `Graph`/`SimpleGraph` type in the [Graphs.jl](https://github.com/JuliaGraphs/Graphs.jl) package that only have contiguous integer edges (i.e. linear indexing).

#' There is a supertype `AbstractNamedGraph` that defines an interface and fallback implementations of standard
#' Graphs.jl operations, and two implementations: `NamedGraph` and `NamedDimGraph`.
#' Graphs.jl operations, and two implementations: `NamedGraph` and `NamedDiGraph`.

#' ## `NamedGraph`

Expand All @@ -28,6 +28,7 @@
using Graphs
using NamedGraphs
g = NamedGraph(grid((4,)), ["A", "B", "C", "D"])
g = NamedGraph(grid((4,)); vertices=["A", "B", "C", "D"]) # Same as above

#'Common operations are defined as you would expect:
#+ term=true
Expand All @@ -42,84 +43,65 @@ g[["A", "B"]]

#' Graph operations are implemented by mapping back and forth between the generalized named vertices and the linear index vertices of the `SimpleGraph`.

#' ## `NamedDimGraph`

#' `NamedDimGraph` is very similar to a `NamedGraph` but a bit more sophisticated. It has generalized
#' multi-dimensional array indexing, mixed with named dimensions like [NamedDims.jl](https://github.com/invenia/NamedDims.jl).

#' This allows for more sophisticated behavior, such as slicing dimensions and [disjoint unions](https://en.wikipedia.org/wiki/Disjoint_union) (generalizations of array concatenations).

#' We start out by making a multi-dimensional graph where we specify the dimensions, which
#' assigns vertex labels based on cartesian coordinates:
#' 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:
#+ term=true

g = NamedDimGraph(grid((2, 2)); dims=(2, 2))
g = NamedGraph(grid((2, 2)); vertices=(2, 2))

#' Internally the vertices are all stored as tuples with a label in each dimension.

#' Vertices can be referred to by their tuples or splatted indices in each dimension:
#' Vertices can be referred to by their tuples:
#+ term=true

has_vertex(g, (1, 1))
has_vertex(g, 1, 1)
has_edge(g, (1, 1) => (2, 1))
has_edge(g, (1, 1) => (2, 2))
neighbors(g, (2, 2))

#' This allows the graph to be treated partially as a set of named vertices and
#' partially with multi-dimensional array indexing syntax. For example
#' you can slice a dimension to get the [induced subgraph](https://juliagraphs.org/Graphs.jl/dev/core_functions/operators/#Graphs.induced_subgraph-Union{Tuple{T},%20Tuple{U},%20Tuple{T,%20AbstractVector{U}}}%20where%20{U%3C:Integer,%20T%3C:AbstractGraph}):
#' You can use vertex names to get [induced subgraphs](https://juliagraphs.org/Graphs.jl/dev/core_functions/operators/#Graphs.induced_subgraph-Union{Tuple{T},%20Tuple{U},%20Tuple{T,%20AbstractVector{U}}}%20where%20{U%3C:Integer,%20T%3C:AbstractGraph}):
#+ term=true

g[1, :]
g[:, 2]
subgraph(v -> v[1] == 1, g)
subgraph(v -> v[2] == 2, g)
g[[(1, 1), (2, 2)]]

#' Note that slicing drops the dimensions of single indices, just like Julia Array slicing:

#+ echo=false

using Random
Random.seed!(1234);
#' 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:
#+ term=true

x = randn(2, 2)
x[1, :]

#' Graphs can also take [disjoint unions](https://en.wikipedia.org/wiki/Disjoint_union) or concatenations of graphs:
#+ term=true

disjoint_union(g, g)
g g
g₁ = g
g₂ = g
disjoint_union(g₁, g₂)
g₁ g₂ # Same as above

#' The symbol `⊔` is just an alias for `disjoint_union` and can be written in the terminal
#' or in your favorite [ide with the appropriate Julia extension](https://julialang.org/) with `\sqcup<tab>`

#' Note that by default this introduces new dimension names (which by default are contiguous integers
#' starting from 1) in the first dimension of the graph, so we can get back
#' the original graphs by slicing and setting the first dimension:
#+ term=true
#' By default, this maps the vertices `v₁ ∈ vertices(g₁)` to `(v₁, 1)` and the vertices `v₂ ∈ vertices(g₂)`
#' to `(v₂, 1)`, so the resulting vertices of the unioned graph will always be unique.
#' The resulting graph will have no edges between vertices `(v₁, 1)` and `(v₂, 1)`, these would have to
#' be added manually.

(g g)[1, :]
(g g)[2, :]

#' or slice across the graphs that we disjoint unioned:
#+ term=true

(g g)[:, 1, :]

#' Additionally, we can use standard array concatenation syntax, such as:
#' The original graphs can be obtained from subgraphs:
#+ term=true

[g; g]

#' which is equivalent to `vcat(g, g)` or:
#+ term=true

[g;; g]

#' which is the same as `hcat(g, g)`.
rename_vertices(v -> v[1], subgraph(v -> v[2] == 1, g₁ g₂))
rename_vertices(v -> v[1], subgraph(v -> v[2] == 2, g₁ g₂))

## #' Additionally, we can use standard array concatenation syntax, such as:
## #+ term=true
##
## [g; g]
##
## #' which is equivalent to `vcat(g, g)` or:
## #+ term=true
##
## [g;; g]
##
## #' which is the same as `hcat(g, g)`.

#' ## Generating this README

Expand Down
10 changes: 5 additions & 5 deletions examples/disjoint_union.jl
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using Graphs
using NamedGraphs

g1 = NamedDimGraph(grid((2, 2)); dims=(2, 2))
g2 = NamedDimGraph(grid((2, 2)); dims=(2, 2))
g = (g1, g2; new_dim_names=("X", "Y"))
g1 = NamedGraph(grid((2, 2)); vertices=(2, 2))
g2 = NamedGraph(grid((2, 2)); vertices=(2, 2))
g = ("X" => g1, "Y" => g2)

@show g1
@show g2
@show g
@show g["X", :]
@show g["Y", :]
@show subgraph(v -> v[1] == "X", g)
@show subgraph(v -> v[1] == "Y", g)
30 changes: 16 additions & 14 deletions examples/multidimgraph_1d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ using Graphs
using NamedGraphs

parent_graph = grid((4,))
vertices = ["A", "B", "C", "D"]
g = NamedDimGraph(parent_graph, vertices)
vs = ["A", "B", "C", "D"]
g = NamedGraph(parent_graph, vs)

@show has_vertex(g, "A")
@show !has_vertex(g, "E")
Expand All @@ -26,26 +26,28 @@ g_sub = g[["A", "B"]]

@show has_edge(g_sub, "A" => "B")

g_sub = g[:]
g_sub = subgraph(Returns(true), g)

@show has_vertex(g_sub, "A")
@show has_vertex(g_sub, "B")
@show has_vertex(g_sub, "C")
@show has_vertex(g_sub, "D")

# Error: vertex names are the same
# g_vcat = [g; g]

g_hcat = [g;; g]

@show nv(g_hcat) == 8
@show ne(g_hcat) == 6

@show has_vertex(g_hcat, "A", 1)

g_union = g g

@show nv(g_union) == 8
@show ne(g_union) == 6

@show has_vertex(g_union, 1, "A")
@show has_vertex(g_union, ("A", 1))
@show has_vertex(g_union, ("A", 2))

# Error: vertex names are the same
# g_vcat = [g; g]

# TODO: Implement
## g_hcat = [g;; g]
##
## @show nv(g_hcat) == 8
## @show ne(g_hcat) == 6
##
## @show has_vertex(g_hcat, ("A", 1))
64 changes: 33 additions & 31 deletions examples/multidimgraph_2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,57 @@ using Graphs
using NamedGraphs

parent_graph = grid((2, 2))
vertices = [("X", 1), ("X", 2), ("Y", 1), ("Y", 2)]
vs = [("X", 1), ("X", 2), ("Y", 1), ("Y", 2)]

g = NamedDimGraph(parent_graph, vertices)
g = NamedGraph(parent_graph, vs)

@show has_vertex(g, "X", 1)
@show has_vertex(g, ("X", 1))
@show has_edge(g, ("X", 1) => ("X", 2))
@show !has_edge(g, ("X", 2) => ("Y", 1))
@show has_edge(g, ("X", 2) => ("Y", 2))

g_sub = g[[("X", 1)]]

@show has_vertex(g_sub, "X", 1)
@show !has_vertex(g_sub, "X", 2)
@show !has_vertex(g_sub, "Y", 1)
@show !has_vertex(g_sub, "Y", 2)
@show has_vertex(g_sub, ("X", 1))
@show !has_vertex(g_sub, ("X", 2))
@show !has_vertex(g_sub, ("Y", 1))
@show !has_vertex(g_sub, ("Y", 2))

g_sub = g[[("X", 1), ("X", 2)]]

@show has_vertex(g_sub, "X", 1)
@show has_vertex(g_sub, "X", 2)
@show !has_vertex(g_sub, "Y", 1)
@show !has_vertex(g_sub, "Y", 2)
@show has_vertex(g_sub, ("X", 1))
@show has_vertex(g_sub, ("X", 2))
@show !has_vertex(g_sub, ("Y", 1))
@show !has_vertex(g_sub, ("Y", 2))

g_sub = g["X", :]
# g_sub = g["X", :]
g_sub = subgraph(v -> v[1] == "X", g)

@show has_vertex(g_sub, "X", 1)
@show has_vertex(g_sub, "X", 2)
@show !has_vertex(g_sub, "Y", 1)
@show !has_vertex(g_sub, "Y", 2)
@show has_vertex(g_sub, ("X", 1))
@show has_vertex(g_sub, ("X", 2))
@show !has_vertex(g_sub, ("Y", 1))
@show !has_vertex(g_sub, ("Y", 2))

g_sub = g[:, 2]
# g_sub = g[:, 2]
g_sub = subgraph(v -> v[2] == 2, g)

@show !has_vertex(g_sub, "X", 1)
@show has_vertex(g_sub, "X", 2)
@show !has_vertex(g_sub, "Y", 1)
@show has_vertex(g_sub, "Y", 2)
@show !has_vertex(g_sub, ("X", 1))
@show has_vertex(g_sub, ("X", 2))
@show !has_vertex(g_sub, ("Y", 1))
@show has_vertex(g_sub, ("Y", 2))

parent_graph = grid((2, 2))
g1 = NamedDimGraph(parent_graph; dims=(2, 2))
g2 = NamedDimGraph(parent_graph; dims=(2, 2))

g_vcat = [g1; g2]

@show nv(g_vcat) == 8

g_hcat = [g1;; g2]

@show nv(g_hcat) == 8
g1 = NamedGraph(parent_graph; vertices=(2, 2))
g2 = NamedGraph(parent_graph; vertices=(2, 2))

g_disjoint_union = g1 g2

@show nv(g_disjoint_union) == 8

## g_vcat = [g1; g2]
##
## @show nv(g_vcat) == 8
##
## g_hcat = [g1;; g2]
##
## @show nv(g_hcat) == 8
1 change: 1 addition & 0 deletions examples/namedgraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ g_sub = g[["A", "B"]]
@show has_vertex(g_sub, "B")
@show !has_vertex(g_sub, "C")
@show !has_vertex(g_sub, "D")
@show has_edge(g_sub, "A" => "B")
Loading

2 comments on commit fa74ea8

@mtfishman
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/73051

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.1.0 -m "<description of version>" fa74ea8725264757097e2e854a8042fd95839e73
git push origin v0.1.0

Please sign in to comment.