From aa54dac35dafb00fe40cb237491d09342d78b1e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Mon, 11 Nov 2024 13:58:12 +0000 Subject: [PATCH 1/4] feat: `is_complete()` checks if a graph is complete --- NAMESPACE | 1 + R/cliques.R | 23 +++++++++++++++++++++++ man/cliques.Rd | 1 + man/is_complete.Rd | 40 ++++++++++++++++++++++++++++++++++++++++ man/ivs.Rd | 1 + man/weighted_cliques.Rd | 1 + 6 files changed, 67 insertions(+) create mode 100644 man/is_complete.Rd diff --git a/NAMESPACE b/NAMESPACE index c5abce1fd93..734d077aded 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -552,6 +552,7 @@ export(is_acyclic) export(is_biconnected) export(is_bipartite) export(is_chordal) +export(is_complete) export(is_connected) export(is_dag) export(is_degseq) diff --git a/R/cliques.R b/R/cliques.R index 3b4866cde91..9e39e86d300 100644 --- a/R/cliques.R +++ b/R/cliques.R @@ -526,3 +526,26 @@ clique_size_counts <- function(graph, min = 0, max = 0, maximal = FALSE) { clique_size_hist_impl(graph, min, max) } } + +#' Is this a complete graph? +#' +#' A graph is considered complete if there is an edge between all distinct +#' directed pairs of vertices. igraph considers both the singleton graph +#' and the null graph complete. +#' +#' @param graph The input graph. +#' @return True if the graph is complete. +#' @family cliques +#' @keywords graphs +#' @seealso [make_full_graph()] +#' @export +#' @cdocs igraph_is_complete +#' @examples +#' +#' g <- make_full_graph(6, directed = TRUE) +#' is_complete(g) +#' g <- delete_edges(g, 1) +#' is_complete(g) +#' g <- as_undirected(g) +#' is_complete(g) +is_complete <- is_complete_impl diff --git a/man/cliques.Rd b/man/cliques.Rd index 278ca805830..5b8c5994090 100644 --- a/man/cliques.Rd +++ b/man/cliques.Rd @@ -116,6 +116,7 @@ in Sparse Graphs in Near-optimal Time. \url{https://arxiv.org/abs/1006.5440} } \seealso{ Other cliques: +\code{\link{is_complete}()}, \code{\link{ivs}()}, \code{\link{weighted_cliques}()} } diff --git a/man/is_complete.Rd b/man/is_complete.Rd new file mode 100644 index 00000000000..17871af6c16 --- /dev/null +++ b/man/is_complete.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/cliques.R +\name{is_complete} +\alias{is_complete} +\title{Is this a complete graph?} +\usage{ +is_complete(graph) +} +\arguments{ +\item{graph}{The input graph.} +} +\value{ +True if the graph is complete. +} +\description{ +A graph is considered complete if there is an edge between all distinct +directed pairs of vertices. igraph considers both the singleton graph +and the null graph complete. +} +\examples{ + +g <- make_full_graph(6, directed = TRUE) +is_complete(g) +g <- delete_edges(g, 1) +is_complete(g) +g <- as_undirected(g) +is_complete(g) +} +\seealso{ +\code{\link[=make_full_graph]{make_full_graph()}} + +Other cliques: +\code{\link{cliques}()}, +\code{\link{ivs}()}, +\code{\link{weighted_cliques}()} +} +\concept{cliques} +\keyword{graphs} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_is_complete}{\code{igraph_is_complete()}}.} + diff --git a/man/ivs.Rd b/man/ivs.Rd index 667c3d3df7d..74fbc9a8a22 100644 --- a/man/ivs.Rd +++ b/man/ivs.Rd @@ -86,6 +86,7 @@ Computing}, 6:505--517, 1977. \seealso{ Other cliques: \code{\link{cliques}()}, +\code{\link{is_complete}()}, \code{\link{weighted_cliques}()} } \author{ diff --git a/man/weighted_cliques.Rd b/man/weighted_cliques.Rd index 87620a75a82..cfa579448ab 100644 --- a/man/weighted_cliques.Rd +++ b/man/weighted_cliques.Rd @@ -67,6 +67,7 @@ weighted_clique_num(g) \seealso{ Other cliques: \code{\link{cliques}()}, +\code{\link{is_complete}()}, \code{\link{ivs}()} } \author{ From 18101bc859a24bf63f4cf518e50c9ade487722da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Mon, 11 Nov 2024 14:10:41 +0000 Subject: [PATCH 2/4] feat: `is_clique()` and `is_ivs()` test whether a set of vertices forms a clique or an independent set --- NAMESPACE | 2 ++ R/cliques.R | 34 ++++++++++++++++++++++++++ man/clique.number.Rd | 3 +-- man/cliques.Rd | 23 ++++++++++++++--- man/independence.number.Rd | 3 +-- man/independent.vertex.sets.Rd | 3 +-- man/ivs.Rd | 15 ++++++++++-- man/largest.cliques.Rd | 3 +-- man/largest.independent.vertex.sets.Rd | 3 +-- man/maximal.cliques.Rd | 3 +-- man/maximal.cliques.count.Rd | 3 +-- man/maximal.independent.vertex.sets.Rd | 3 +-- man/maximal_ivs.Rd | 3 +-- 13 files changed, 78 insertions(+), 23 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 734d077aded..4a29070d777 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -552,6 +552,7 @@ export(is_acyclic) export(is_biconnected) export(is_bipartite) export(is_chordal) +export(is_clique) export(is_complete) export(is_connected) export(is_dag) @@ -562,6 +563,7 @@ export(is_graphical) export(is_hierarchical) export(is_igraph) export(is_isomorphic_to) +export(is_ivs) export(is_matching) export(is_max_matching) export(is_min_separator) diff --git a/R/cliques.R b/R/cliques.R index 9e39e86d300..6093623bc8b 100644 --- a/R/cliques.R +++ b/R/cliques.R @@ -163,6 +163,8 @@ clique.number <- function(graph) { # nocov start #' `clique_size_counts()` returns a numeric vector representing a histogram #' of clique sizes, between the given minimum and maximum clique size. #' +#' `is_clique()` tests whether all pairs within a vertex set are connected. +#' #' @inheritParams weighted_cliques #' @param graph The input graph, directed graphs will be considered as #' undirected ones, multiple edges and loops are ignored. @@ -204,6 +206,9 @@ clique.number <- function(graph) { # nocov start #' # To have a bit less maximal cliques, about 100-200 usually #' g <- sample_gnp(100, 0.03) #' max_cliques(g) +#' +#' # Check that all returned vertex sets are indeed cliques +#' all(sapply(max_cliques(g), function (c) is_clique(g, c))) #' @cdocs igraph_cliques cliques <- cliques_impl @@ -394,6 +399,8 @@ weighted_clique_num <- weighted_clique_number_impl #' These functions use the algorithm described by Tsukiyama et al., see #' reference below. #' +#' `is_ivs()` tests if no pairs within a vertex set are connected. +#' #' @param graph The input graph, directed graphs are considered as undirected, #' loop edges and multiple edges are ignored. #' @param min Numeric constant, limit for the minimum size of the independent @@ -549,3 +556,30 @@ clique_size_counts <- function(graph, min = 0, max = 0, maximal = FALSE) { #' g <- as_undirected(g) #' is_complete(g) is_complete <- is_complete_impl + +#' @rdname cliques +#' +#' @description +#' Tests if all pairs within a set of vertices are adjacent, i.e. whether they +#' form a clique. An empty set and singleton set are considered to be a clique. +#' +#' @param graph The input graph. +#' @param candidate The vertex set to test for being a clique. +#' @param directed Whether to consider edge directions. +#' @return `is_clique()` returns `TRUE` if the candidate vertex set forms +#' a clique. +#' @keywords graphs +#' @export +#' @cdocs igraph_is_clique +is_clique <- is_clique_impl + +#' @rdname ivs +#' +#' @param graph The input graph. +#' @param candidate The vertex set to test for being an independent set. +#' @return `is_ivs()` returns `TRUE` if the candidate vertex set forms an +#' independent set. +#' @keywords graphs +#' @export +#' @cdocs igraph_is_independent_vertex_set +is_ivs <- is_independent_vertex_set_impl diff --git a/man/clique.number.Rd b/man/clique.number.Rd index 19de05ff156..ae8343274cc 100644 --- a/man/clique.number.Rd +++ b/man/clique.number.Rd @@ -7,8 +7,7 @@ clique.number(graph) } \arguments{ -\item{graph}{The input graph, directed graphs will be considered as -undirected ones, multiple edges and loops are ignored.} +\item{graph}{The input graph.} } \description{ \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} diff --git a/man/cliques.Rd b/man/cliques.Rd index 5b8c5994090..dff5707cc2f 100644 --- a/man/cliques.Rd +++ b/man/cliques.Rd @@ -9,6 +9,7 @@ \alias{largest_weighted_cliques} \alias{weighted_clique_num} \alias{clique_size_counts} +\alias{is_clique} \title{Functions to find cliques, i.e. complete subgraphs in a graph} \usage{ cliques(graph, min = 0, max = 0) @@ -26,10 +27,11 @@ largest_weighted_cliques(graph, vertex.weights = NULL) weighted_clique_num(graph, vertex.weights = NULL) clique_size_counts(graph, min = 0, max = 0, maximal = FALSE) + +is_clique(graph, candidate, directed = FALSE) } \arguments{ -\item{graph}{The input graph, directed graphs will be considered as -undirected ones, multiple edges and loops are ignored.} +\item{graph}{The input graph.} \item{min}{Numeric constant, lower limit on the size of the cliques to find. \code{NULL} means no limit, i.e. it is the same as 0.} @@ -57,6 +59,10 @@ of the weighted clique finder supports positive integer weights only.} \item{maximal}{Specifies whether to look for all weighted cliques (\code{FALSE}) or only the maximal ones (\code{TRUE}).} + +\item{candidate}{The vertex set to test for being a clique.} + +\item{directed}{Whether to consider edge directions.} } \value{ \code{cliques()}, \code{largest_cliques()} and \code{clique_num()} @@ -73,10 +79,16 @@ scalar. \code{clique_size_counts()} returns a numeric vector with the clique sizes such that the i-th item belongs to cliques of size i. Trailing zeros are currently truncated, but this might change in future versions. + +\code{is_clique()} returns \code{TRUE} if the candidate vertex set forms +a clique. } \description{ These functions find all, the largest or all the maximal cliques in an undirected graph. The size of the largest clique can also be calculated. + +Tests if all pairs within a set of vertices are adjacent, i.e. whether they +form a clique. An empty set and singleton set are considered to be a clique. } \details{ \code{cliques()} find all complete subgraphs in the input graph, obeying the @@ -96,6 +108,8 @@ largest. \code{clique_size_counts()} returns a numeric vector representing a histogram of clique sizes, between the given minimum and maximum clique size. + +\code{is_clique()} tests whether all pairs within a vertex set are connected. } \examples{ @@ -108,6 +122,9 @@ largest_cliques(g) # To have a bit less maximal cliques, about 100-200 usually g <- sample_gnp(100, 0.03) max_cliques(g) + +# Check that all returned vertex sets are indeed cliques +all(sapply(max_cliques(g), function (c) is_clique(g, c))) } \references{ For maximal cliques the following algorithm is implemented: @@ -126,5 +143,5 @@ Tamas Nepusz \email{ntamas@gmail.com} and Gabor Csardi } \concept{cliques} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_cliques}{\code{cliques()}}, \href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_largest_cliques}{\code{largest_cliques()}}, \href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_clique_number}{\code{clique_number()}}, \href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_largest_weighted_cliques}{\code{largest_weighted_cliques()}}, \href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_weighted_clique_number}{\code{weighted_clique_number()}}, \href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_maximal_cliques_hist}{\code{maximal_cliques_hist()}}, \href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_clique_size_hist}{\code{clique_size_hist()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_cliques}{\code{cliques()}}, \href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_largest_cliques}{\code{largest_cliques()}}, \href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_clique_number}{\code{clique_number()}}, \href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_largest_weighted_cliques}{\code{largest_weighted_cliques()}}, \href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_weighted_clique_number}{\code{weighted_clique_number()}}, \href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_maximal_cliques_hist}{\code{maximal_cliques_hist()}}, \href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_clique_size_hist}{\code{clique_size_hist()}}, \href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_is_clique}{\code{is_clique()}}.} diff --git a/man/independence.number.Rd b/man/independence.number.Rd index 0c31fbea555..23d7d3f3360 100644 --- a/man/independence.number.Rd +++ b/man/independence.number.Rd @@ -7,8 +7,7 @@ independence.number(graph) } \arguments{ -\item{graph}{The input graph, directed graphs are considered as undirected, -loop edges and multiple edges are ignored.} +\item{graph}{The input graph.} } \description{ \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} diff --git a/man/independent.vertex.sets.Rd b/man/independent.vertex.sets.Rd index c1c2b5f3007..a400e074a2c 100644 --- a/man/independent.vertex.sets.Rd +++ b/man/independent.vertex.sets.Rd @@ -7,8 +7,7 @@ independent.vertex.sets(graph, min = NULL, max = NULL) } \arguments{ -\item{graph}{The input graph, directed graphs are considered as undirected, -loop edges and multiple edges are ignored.} +\item{graph}{The input graph.} \item{min}{Numeric constant, limit for the minimum size of the independent vertex sets to find. \code{NULL} means no limit.} diff --git a/man/ivs.Rd b/man/ivs.Rd index 74fbc9a8a22..30240daf592 100644 --- a/man/ivs.Rd +++ b/man/ivs.Rd @@ -6,6 +6,7 @@ \alias{max_ivs} \alias{ivs_size} \alias{independence_number} +\alias{is_ivs} \title{Independent vertex sets} \usage{ ivs(graph, min = NULL, max = NULL) @@ -17,16 +18,19 @@ max_ivs(graph) ivs_size(graph) independence_number(graph) + +is_ivs(graph, candidate) } \arguments{ -\item{graph}{The input graph, directed graphs are considered as undirected, -loop edges and multiple edges are ignored.} +\item{graph}{The input graph.} \item{min}{Numeric constant, limit for the minimum size of the independent vertex sets to find. \code{NULL} means no limit.} \item{max}{Numeric constant, limit for the maximum size of the independent vertex sets to find. \code{NULL} means no limit.} + +\item{candidate}{The vertex set to test for being an independent set.} } \value{ \code{ivs()}, @@ -35,6 +39,9 @@ vertex sets to find. \code{NULL} means no limit.} vertex ids, each list element is an independent vertex set. \code{ivs_size()} returns an integer constant. + +\code{is_ivs()} returns \code{TRUE} if the candidate vertex set forms an +independent set. } \description{ A vertex set is called independent if there no edges between any two @@ -62,6 +69,8 @@ vertex set(s). These functions use the algorithm described by Tsukiyama et al., see reference below. + +\code{is_ivs()} tests if no pairs within a vertex set are connected. } \examples{ @@ -97,3 +106,5 @@ page. } \concept{cliques} \keyword{graphs} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_is_independent_vertex_set}{\code{igraph_is_independent_vertex_set()}}.} + diff --git a/man/largest.cliques.Rd b/man/largest.cliques.Rd index 53de3293670..7ad65f633f6 100644 --- a/man/largest.cliques.Rd +++ b/man/largest.cliques.Rd @@ -7,8 +7,7 @@ largest.cliques(graph) } \arguments{ -\item{graph}{The input graph, directed graphs will be considered as -undirected ones, multiple edges and loops are ignored.} +\item{graph}{The input graph.} } \description{ \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} diff --git a/man/largest.independent.vertex.sets.Rd b/man/largest.independent.vertex.sets.Rd index 384fd15f547..0e57e435b70 100644 --- a/man/largest.independent.vertex.sets.Rd +++ b/man/largest.independent.vertex.sets.Rd @@ -7,8 +7,7 @@ largest.independent.vertex.sets(graph) } \arguments{ -\item{graph}{The input graph, directed graphs are considered as undirected, -loop edges and multiple edges are ignored.} +\item{graph}{The input graph.} } \description{ \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} diff --git a/man/maximal.cliques.Rd b/man/maximal.cliques.Rd index 191e3aa9092..f00d9668cdd 100644 --- a/man/maximal.cliques.Rd +++ b/man/maximal.cliques.Rd @@ -7,8 +7,7 @@ maximal.cliques(graph, min = NULL, max = NULL, subset = NULL, file = NULL) } \arguments{ -\item{graph}{The input graph, directed graphs will be considered as -undirected ones, multiple edges and loops are ignored.} +\item{graph}{The input graph.} \item{min}{Numeric constant, lower limit on the size of the cliques to find. \code{NULL} means no limit, i.e. it is the same as 0.} diff --git a/man/maximal.cliques.count.Rd b/man/maximal.cliques.count.Rd index 840a7e0db14..718282e0ae6 100644 --- a/man/maximal.cliques.count.Rd +++ b/man/maximal.cliques.count.Rd @@ -7,8 +7,7 @@ maximal.cliques.count(graph, min = NULL, max = NULL, subset = NULL) } \arguments{ -\item{graph}{The input graph, directed graphs will be considered as -undirected ones, multiple edges and loops are ignored.} +\item{graph}{The input graph.} \item{min}{Numeric constant, lower limit on the size of the cliques to find. \code{NULL} means no limit, i.e. it is the same as 0.} diff --git a/man/maximal.independent.vertex.sets.Rd b/man/maximal.independent.vertex.sets.Rd index c1cfd4ccecc..8384d3a8c63 100644 --- a/man/maximal.independent.vertex.sets.Rd +++ b/man/maximal.independent.vertex.sets.Rd @@ -7,8 +7,7 @@ maximal.independent.vertex.sets(graph) } \arguments{ -\item{graph}{The input graph, directed graphs are considered as undirected, -loop edges and multiple edges are ignored.} +\item{graph}{The input graph.} } \description{ \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} diff --git a/man/maximal_ivs.Rd b/man/maximal_ivs.Rd index d469785305b..f7cff3d19b1 100644 --- a/man/maximal_ivs.Rd +++ b/man/maximal_ivs.Rd @@ -7,8 +7,7 @@ maximal_ivs(graph) } \arguments{ -\item{graph}{The input graph, directed graphs are considered as undirected, -loop edges and multiple edges are ignored.} +\item{graph}{The input graph.} } \description{ \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} From f4220446cd3c316e2d21d8cf39712a070ce110c8 Mon Sep 17 00:00:00 2001 From: szhorvat Date: Sun, 30 Mar 2025 14:11:18 +0000 Subject: [PATCH 3/4] chore: Auto-update from GitHub Actions Run: https://github.com/igraph/rigraph/actions/runs/14156789214 --- man/is_complete.Rd | 2 +- man/ivs.Rd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/man/is_complete.Rd b/man/is_complete.Rd index 17871af6c16..75e6e5c21c2 100644 --- a/man/is_complete.Rd +++ b/man/is_complete.Rd @@ -36,5 +36,5 @@ Other cliques: } \concept{cliques} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_is_complete}{\code{igraph_is_complete()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_is_complete}{\code{is_complete()}}.} diff --git a/man/ivs.Rd b/man/ivs.Rd index 30240daf592..a7b11abde99 100644 --- a/man/ivs.Rd +++ b/man/ivs.Rd @@ -106,5 +106,5 @@ page. } \concept{cliques} \keyword{graphs} -\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_is_independent_vertex_set}{\code{igraph_is_independent_vertex_set()}}.} +\section{Related documentation in the C library}{\href{https://igraph.org/c/html/latest/igraph-Cliques.html#igraph_is_independent_vertex_set}{\code{is_independent_vertex_set()}}.} From 56b3ddde5675e92a5b7ef02f9d66d77dba186dc0 Mon Sep 17 00:00:00 2001 From: schochastics Date: Sun, 30 Mar 2025 21:02:52 +0200 Subject: [PATCH 4/4] added tests --- tests/testthat/test-cliques.R | 38 +++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/testthat/test-cliques.R b/tests/testthat/test-cliques.R index 363ec9d8b53..5063560033b 100644 --- a/tests/testthat/test-cliques.R +++ b/tests/testthat/test-cliques.R @@ -287,3 +287,41 @@ test_that("largest_cliques works", { lc_ring <- largest_cliques(make_ring(10)) expect_equal(max(sapply(lc_ring, length)), 2) }) + +test_that("is_clique works", { + withr::local_seed(42) + + g <- make_full_graph(5) + expect_true(is_clique(g, V(g))) + + g <- sample_gnp(15, 0.5) + max_cl <- max_cliques(g) + all_are_cliques <- all(sapply(max_cl, function(x) is_clique(g, x))) + expect_true(all_are_cliques) +}) + +test_that("is_ivs works", { + withr::local_seed(42) + + g <- make_full_bipartite_graph(5, 5) + expect_true(is_ivs(g, V(g)[V(g)$type])) + + g <- sample_gnp(15, 0.5) + max_ivs <- max_ivs(g) + all_are_ivs <- all(sapply(max_ivs, function(x) is_ivs(g, x))) + expect_true(all_are_ivs) +}) + +test_that("is_complete works", { + g1 <- make_full_graph(5) + expect_true(is_complete(g1)) + + g2 <- make_full_graph(5, directed = TRUE) + expect_true(is_complete(g1)) + + g3 <- delete_edges(g2, 1) + expect_false(is_complete(g3)) + + g4 <- as_undirected(g3) + expect_true(is_complete(g4)) +})