diff --git a/NAMESPACE b/NAMESPACE index 29c0ec2cb02..90131d991fd 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -504,6 +504,7 @@ export(hrg.predict) export(hrg_tree) export(hub.score) export(hub_score) +export(hypercube) export(identical_graphs) export(igraph.console) export(igraph.drl.coarsen) @@ -665,6 +666,7 @@ export(make_full_citation_graph) export(make_full_graph) export(make_full_multipartite) export(make_graph) +export(make_hypercube) export(make_kautz_graph) export(make_lattice) export(make_line_graph) diff --git a/R/make.R b/R/make.R index b4a7d94f2b0..b2ed747c2a6 100644 --- a/R/make.R +++ b/R/make.R @@ -2028,6 +2028,42 @@ lattice <- function(...) constructor_spec(make_lattice, ...) ## ----------------------------------------------------------------- +#' Create a hypercube graph +#' +#' `r lifecycle::badge("experimental")` +#' +#' The n-dimensional hypercube graph has \eqn{2^n} vertices and +#' \eqn{2^{n-1} n} edges. +#' Two vertices are connected if the binary representations of their vertex +#' IDs (minus one, to make them zero-based) differ in precisely one bit. +#' +#' @param n The dimension of the hypercube graph. +#' Must be non-negative and not greater than 57. +#' @param directed Logical scalar, whether the graph should be directed. +#' If `TRUE`, edges point from vertices with lower IDs toward vertices +#' with higher IDs. +#' @return An igraph graph. +#' +#' @concept hypercube +#' @family deterministic constructors +#' @export +#' @examples +#' # 3-dimensional hypercube (cube) +#' print_all(make_hypercube(3)) +#' # 4-dimensional hypercube (tesseract) +#' print_all(make_hypercube(4)) +#' @cdocs igraph_hypercube +make_hypercube <- function(n, directed = FALSE) { + hypercube_impl(n = n, directed = directed) +} + +#' @rdname make_hypercube +#' @param ... Passed to `make_hypercube()`. +#' @export +hypercube <- function(...) constructor_spec(make_hypercube, ...) + +## ----------------------------------------------------------------- + #' Create a ring graph #' #' A ring is a one-dimensional lattice and this function is a special case diff --git a/man/graph_from_atlas.Rd b/man/graph_from_atlas.Rd index eb3b3d7885e..c5ffd889c83 100644 --- a/man/graph_from_atlas.Rd +++ b/man/graph_from_atlas.Rd @@ -50,6 +50,7 @@ Other deterministic constructors: \code{\link{make_full_graph}()}, \code{\link{make_full_multipartite}()}, \code{\link{make_graph}()}, +\code{\link{make_hypercube}()}, \code{\link{make_lattice}()}, \code{\link{make_ring}()}, \code{\link{make_star}()}, diff --git a/man/graph_from_edgelist.Rd b/man/graph_from_edgelist.Rd index 198a7635439..2bba73f0d03 100644 --- a/man/graph_from_edgelist.Rd +++ b/man/graph_from_edgelist.Rd @@ -46,6 +46,7 @@ Other deterministic constructors: \code{\link{make_full_graph}()}, \code{\link{make_full_multipartite}()}, \code{\link{make_graph}()}, +\code{\link{make_hypercube}()}, \code{\link{make_lattice}()}, \code{\link{make_ring}()}, \code{\link{make_star}()}, diff --git a/man/graph_from_literal.Rd b/man/graph_from_literal.Rd index c17966e3bcb..ab85d88e25c 100644 --- a/man/graph_from_literal.Rd +++ b/man/graph_from_literal.Rd @@ -137,6 +137,7 @@ Other deterministic constructors: \code{\link{make_full_graph}()}, \code{\link{make_full_multipartite}()}, \code{\link{make_graph}()}, +\code{\link{make_hypercube}()}, \code{\link{make_lattice}()}, \code{\link{make_ring}()}, \code{\link{make_star}()}, diff --git a/man/make_.Rd b/man/make_.Rd index 1dbd908e674..0f2ce2b0a51 100644 --- a/man/make_.Rd +++ b/man/make_.Rd @@ -53,6 +53,7 @@ Other deterministic constructors: \code{\link{make_full_graph}()}, \code{\link{make_full_multipartite}()}, \code{\link{make_graph}()}, +\code{\link{make_hypercube}()}, \code{\link{make_lattice}()}, \code{\link{make_ring}()}, \code{\link{make_star}()}, diff --git a/man/make_chordal_ring.Rd b/man/make_chordal_ring.Rd index 8633eec00f2..aac39e72658 100644 --- a/man/make_chordal_ring.Rd +++ b/man/make_chordal_ring.Rd @@ -53,6 +53,7 @@ Other deterministic constructors: \code{\link{make_full_graph}()}, \code{\link{make_full_multipartite}()}, \code{\link{make_graph}()}, +\code{\link{make_hypercube}()}, \code{\link{make_lattice}()}, \code{\link{make_ring}()}, \code{\link{make_star}()}, diff --git a/man/make_circulant.Rd b/man/make_circulant.Rd index f3d3afcb949..b2d46537068 100644 --- a/man/make_circulant.Rd +++ b/man/make_circulant.Rd @@ -51,6 +51,7 @@ Other deterministic constructors: \code{\link{make_full_graph}()}, \code{\link{make_full_multipartite}()}, \code{\link{make_graph}()}, +\code{\link{make_hypercube}()}, \code{\link{make_lattice}()}, \code{\link{make_ring}()}, \code{\link{make_star}()}, diff --git a/man/make_empty_graph.Rd b/man/make_empty_graph.Rd index f59cbc19e41..23fbcddd367 100644 --- a/man/make_empty_graph.Rd +++ b/man/make_empty_graph.Rd @@ -38,6 +38,7 @@ Other deterministic constructors: \code{\link{make_full_graph}()}, \code{\link{make_full_multipartite}()}, \code{\link{make_graph}()}, +\code{\link{make_hypercube}()}, \code{\link{make_lattice}()}, \code{\link{make_ring}()}, \code{\link{make_star}()}, diff --git a/man/make_full_citation_graph.Rd b/man/make_full_citation_graph.Rd index 85d301f9098..9d1f8eb7d33 100644 --- a/man/make_full_citation_graph.Rd +++ b/man/make_full_citation_graph.Rd @@ -39,6 +39,7 @@ Other deterministic constructors: \code{\link{make_full_graph}()}, \code{\link{make_full_multipartite}()}, \code{\link{make_graph}()}, +\code{\link{make_hypercube}()}, \code{\link{make_lattice}()}, \code{\link{make_ring}()}, \code{\link{make_star}()}, diff --git a/man/make_full_graph.Rd b/man/make_full_graph.Rd index ea9bcda9cab..113a73deede 100644 --- a/man/make_full_graph.Rd +++ b/man/make_full_graph.Rd @@ -40,6 +40,7 @@ Other deterministic constructors: \code{\link{make_full_citation_graph}()}, \code{\link{make_full_multipartite}()}, \code{\link{make_graph}()}, +\code{\link{make_hypercube}()}, \code{\link{make_lattice}()}, \code{\link{make_ring}()}, \code{\link{make_star}()}, diff --git a/man/make_full_multipartite.Rd b/man/make_full_multipartite.Rd index e0cedcb7102..0f45c9dbd9d 100644 --- a/man/make_full_multipartite.Rd +++ b/man/make_full_multipartite.Rd @@ -53,6 +53,7 @@ Other deterministic constructors: \code{\link{make_full_citation_graph}()}, \code{\link{make_full_graph}()}, \code{\link{make_graph}()}, +\code{\link{make_hypercube}()}, \code{\link{make_lattice}()}, \code{\link{make_ring}()}, \code{\link{make_star}()}, diff --git a/man/make_graph.Rd b/man/make_graph.Rd index a3c78f6328f..c823147a821 100644 --- a/man/make_graph.Rd +++ b/man/make_graph.Rd @@ -249,6 +249,7 @@ Other deterministic constructors: \code{\link{make_full_citation_graph}()}, \code{\link{make_full_graph}()}, \code{\link{make_full_multipartite}()}, +\code{\link{make_hypercube}()}, \code{\link{make_lattice}()}, \code{\link{make_ring}()}, \code{\link{make_star}()}, diff --git a/man/make_hypercube.Rd b/man/make_hypercube.Rd new file mode 100644 index 00000000000..72d36054b61 --- /dev/null +++ b/man/make_hypercube.Rd @@ -0,0 +1,62 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/make.R +\name{make_hypercube} +\alias{make_hypercube} +\alias{hypercube} +\title{Create a hypercube graph} +\usage{ +make_hypercube(n, directed = FALSE) + +hypercube(...) +} +\arguments{ +\item{n}{The dimension of the hypercube graph. +Must be non-negative and not greater than 57.} + +\item{directed}{Logical scalar, whether the graph should be directed. +If \code{TRUE}, edges point from vertices with lower IDs toward vertices +with higher IDs.} + +\item{...}{Passed to \code{make_hypercube()}.} +} +\value{ +An igraph graph. +} +\description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}} +} +\details{ +The n-dimensional hypercube graph has \eqn{2^n} vertices and +\eqn{2^{n-1} n} edges. +Two vertices are connected if the binary representations of their vertex +IDs (minus one, to make them zero-based) differ in precisely one bit. +} +\examples{ +# 3-dimensional hypercube (cube) +print_all(make_hypercube(3)) +# 4-dimensional hypercube (tesseract) +print_all(make_hypercube(4)) +} +\seealso{ +Other deterministic constructors: +\code{\link{graph_from_atlas}()}, +\code{\link{graph_from_edgelist}()}, +\code{\link{graph_from_literal}()}, +\code{\link{make_}()}, +\code{\link{make_chordal_ring}()}, +\code{\link{make_circulant}()}, +\code{\link{make_empty_graph}()}, +\code{\link{make_full_citation_graph}()}, +\code{\link{make_full_graph}()}, +\code{\link{make_full_multipartite}()}, +\code{\link{make_graph}()}, +\code{\link{make_lattice}()}, +\code{\link{make_ring}()}, +\code{\link{make_star}()}, +\code{\link{make_tree}()}, +\code{\link{make_turan}()} +} +\concept{deterministic constructors} +\concept{hypercube} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Generators.html#igraph_hypercube}{\code{hypercube()}}.} + diff --git a/man/make_lattice.Rd b/man/make_lattice.Rd index 8a9c80bc0d3..dcefa424fea 100644 --- a/man/make_lattice.Rd +++ b/man/make_lattice.Rd @@ -70,6 +70,7 @@ Other deterministic constructors: \code{\link{make_full_graph}()}, \code{\link{make_full_multipartite}()}, \code{\link{make_graph}()}, +\code{\link{make_hypercube}()}, \code{\link{make_ring}()}, \code{\link{make_star}()}, \code{\link{make_tree}()}, diff --git a/man/make_ring.Rd b/man/make_ring.Rd index f02131b9341..f54ff0ac58e 100644 --- a/man/make_ring.Rd +++ b/man/make_ring.Rd @@ -47,6 +47,7 @@ Other deterministic constructors: \code{\link{make_full_graph}()}, \code{\link{make_full_multipartite}()}, \code{\link{make_graph}()}, +\code{\link{make_hypercube}()}, \code{\link{make_lattice}()}, \code{\link{make_star}()}, \code{\link{make_tree}()}, diff --git a/man/make_star.Rd b/man/make_star.Rd index 27b1d5ab7ef..4f7abc48162 100644 --- a/man/make_star.Rd +++ b/man/make_star.Rd @@ -46,6 +46,7 @@ Other deterministic constructors: \code{\link{make_full_graph}()}, \code{\link{make_full_multipartite}()}, \code{\link{make_graph}()}, +\code{\link{make_hypercube}()}, \code{\link{make_lattice}()}, \code{\link{make_ring}()}, \code{\link{make_tree}()}, diff --git a/man/make_tree.Rd b/man/make_tree.Rd index 3999a4e725a..ae87dae5bed 100644 --- a/man/make_tree.Rd +++ b/man/make_tree.Rd @@ -47,6 +47,7 @@ Other deterministic constructors: \code{\link{make_full_graph}()}, \code{\link{make_full_multipartite}()}, \code{\link{make_graph}()}, +\code{\link{make_hypercube}()}, \code{\link{make_lattice}()}, \code{\link{make_ring}()}, \code{\link{make_star}()}, diff --git a/man/make_turan.Rd b/man/make_turan.Rd index 6431e0f76ba..a8766750c74 100644 --- a/man/make_turan.Rd +++ b/man/make_turan.Rd @@ -53,6 +53,7 @@ Other deterministic constructors: \code{\link{make_full_graph}()}, \code{\link{make_full_multipartite}()}, \code{\link{make_graph}()}, +\code{\link{make_hypercube}()}, \code{\link{make_lattice}()}, \code{\link{make_ring}()}, \code{\link{make_star}()}, diff --git a/tests/testthat/test-make.R b/tests/testthat/test-make.R index eafcc645d31..0dbe59dcb22 100644 --- a/tests/testthat/test-make.R +++ b/tests/testthat/test-make.R @@ -205,6 +205,59 @@ test_that("make_lattice prints a warning for fractional length)", { expect_identical_graphs(lattice_rounded, lattice_integer) }) +test_that("make_hypercube works", { + # 0-dimensional hypercube has 1 vertex and 0 edges + hc0 <- make_hypercube(0) + expect_vcount(hc0, 1) + expect_ecount(hc0, 0) + + # 1-dimensional hypercube (line segment) has 2 vertices and 1 edge + hc1 <- make_hypercube(1) + expect_vcount(hc1, 2) + expect_ecount(hc1, 1) + + # 2-dimensional hypercube (square) has 4 vertices and 4 edges + hc2 <- make_hypercube(2) + expect_vcount(hc2, 4) + expect_ecount(hc2, 4) + + # 3-dimensional hypercube (cube) has 8 vertices and 12 edges + hc3 <- make_hypercube(3) + expect_vcount(hc3, 8) + expect_ecount(hc3, 12) + + # Verify edges for 3D hypercube + # Vertices should be connected if their IDs (minus 1) differ in exactly one bit + # IDs: 1(000), 2(001), 3(010), 4(011), 5(100), 6(101), 7(110), 8(111) + expected_edges <- make_empty_graph(n = 8) + + edges(c( + 1, 2, # 000 - 001 + 1, 3, # 000 - 010 + 1, 5, # 000 - 100 + 2, 4, # 001 - 011 + 2, 6, # 001 - 101 + 3, 4, # 010 - 011 + 3, 7, # 010 - 110 + 4, 8, # 011 - 111 + 5, 6, # 100 - 101 + 5, 7, # 100 - 110 + 6, 8, # 101 - 111 + 7, 8 # 110 - 111 + )) + expect_equal(as_edgelist(hc3), as_edgelist(expected_edges)) + + # Test directed hypercube + hc3_directed <- make_hypercube(3, directed = TRUE) + expect_true(is_directed(hc3_directed)) + expect_ecount(hc3_directed, 12) +}) + +test_that("make_hypercube can be used with make_()", { + hc1 <- make_hypercube(3) + hc2 <- make_(hypercube(3)) + expect_identical_graphs(hc1, hc2) +}) + test_that("make_graph works", { graph_make <- make_graph(1:10) graph_elist <- make_empty_graph(n = 10) + edges(1:10)