diff --git a/R/operators.R b/R/operators.R index 8722413f9a..d1fcca9513 100644 --- a/R/operators.R +++ b/R/operators.R @@ -228,6 +228,30 @@ disjoint_union <- function(...) { ) lapply(graphs, ensure_igraph) + ## Handle mixed named/unnamed graphs by generating generic names + have_names <- sapply(graphs, is_named) + if (sum(have_names) > 0 && sum(have_names) < length(graphs)) { + # Some graphs have names, others don't - generate names for unnamed graphs + existing_names <- unlist(lapply(graphs[have_names], function(g) V(g)$name)) + + # Create a counter for generating new names (check if named graph already has generic names) + prefix <- "V" + name_counter <- if (any(grepl(paste0("^", prefix, "[0-9]+$"), existing_names))) { + max(as.integer(gsub(paste0("^", prefix, "([0-9]+)$"), "\\1", existing_names)), na.rm = TRUE) + 1 + } else { + 1 + } + + for (i in seq_along(graphs)) { + if (!have_names[i]) { + n <- vcount(graphs[[i]]) + num_id <- seq(name_counter, name_counter + n - 1) + V(graphs[[i]])$name <- paste0(prefix, num_id) + name_counter <- name_counter + n + } + } + } + on.exit(.Call(R_igraph_finalizer)) res <- .Call(R_igraph_disjoint_union, graphs) diff --git a/tests/testthat/test-operators.R b/tests/testthat/test-operators.R index afa804d5f1..5a1499ed43 100644 --- a/tests/testthat/test-operators.R +++ b/tests/testthat/test-operators.R @@ -345,6 +345,46 @@ test_that("disjoint union gives warning for non-unique vertex names", { ) }) +test_that("disjoint union handles mixed named/unnamed graphs", { + # Test named + unnamed graphs + g1 <- make_ring(4) + g2 <- make_ring(3) + V(g1)$name <- c("A", "B", "C", "D") + + result <- disjoint_union(g1, g2) + + expect_equal(V(result)$name, c("A", "B", "C", "D", "V1", "V2", "V3")) + expect_equal(vcount(result), 7) + expect_equal(ecount(result), 7) + + # Test with existing V-pattern names + g3 <- make_ring(3) + g4 <- make_ring(2) + V(g3)$name <- c("V1", "V2", "V3") + + result2 <- disjoint_union(g3, g4) + expect_equal(V(result2)$name, c("V1", "V2", "V3", "V4", "V5")) + + # Test unnamed + named graphs (should work the same) + result3 <- disjoint_union(g2, g1) + expect_equal(V(result3)$name, c("V1", "V2", "V3", "A", "B", "C", "D")) + + # Test all unnamed graphs (should not add names) + g5 <- make_ring(2) + g6 <- make_ring(2) + result4 <- disjoint_union(g5, g6) + expect_true(is.null(V(result4)$name) || all(is.na(V(result4)$name))) + + # Test all named graphs (should work as before) + g7 <- make_ring(2) + g8 <- make_ring(2) + V(g7)$name <- c("X", "Y") + V(g8)$name <- c("P", "Q") + + result5 <- disjoint_union(g7, g8) + expect_equal(V(result5)$name, c("X", "Y", "P", "Q")) +}) + test_that("union of unnamed graphs works", { g1 <- make_ring(10)