Skip to content

Commit 4f94319

Browse files
Merge pull request #36 from frederikfabriciusbjerre/copilot/fix-igraph-name-scramble
Fix vertex order scrambling when converting unnamed igraph to caugi_graph
2 parents 3a9db0b + 1fe81a2 commit 4f94319

2 files changed

Lines changed: 48 additions & 3 deletions

File tree

R/as_caugi.R

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ S7::method(
7575

7676
n_edges <- igraph::ecount(x)
7777
directed <- igraph::is_directed(x)
78+
has_names <- !is.null(igraph::V(x)$name)
7879
nm <- igraph::V(x)$name
7980
if (is.null(nm)) nm <- paste0("V", seq_len(igraph::vcount(x)))
8081

@@ -93,11 +94,19 @@ S7::method(
9394
))
9495
}
9596

96-
e <- igraph::ends(x, igraph::E(x), names = TRUE)
97+
# Use names = FALSE when graph has no names to get numeric indices,
98+
# then map to our generated names. This preserves vertex order.
99+
e <- igraph::ends(x, igraph::E(x), names = has_names)
97100
glyph <- if (directed) "-->" else "---"
98101

99-
from <- e[, 1]
100-
to <- e[, 2]
102+
if (has_names) {
103+
from <- e[, 1]
104+
to <- e[, 2]
105+
} else {
106+
# Map numeric indices to our generated names
107+
from <- nm[e[, 1]]
108+
to <- nm[e[, 2]]
109+
}
101110
edge <- rep_len(glyph, length.out = nrow(e))
102111

103112
# collapse symmetrical edges

tests/testthat/test-as_caugi.R

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,18 @@ test_that("igraph with no edges, but with nodes, works", {
219219
expect_setequal(nodes(cg0)[["name"]], c("A", "B", "C"))
220220
})
221221

222+
test_that("igraph with no edges and no names preserves order", {
223+
skip_if_not_installed("igraph")
224+
g0 <- igraph::make_empty_graph(n = 5, directed = TRUE)
225+
# Verify no names
226+
expect_null(igraph::V(g0)$name)
227+
228+
cg0 <- as_caugi(g0, class = "DAG")
229+
expect_equal(nrow(as.data.frame(edges(cg0))), 0L)
230+
# Should generate V1, V2, V3, V4, V5 in order
231+
expect_equal(cg0@nodes$name, paste0("V", 1:5))
232+
})
233+
222234
test_that("igraph vertex order is preserved when converting to caugi", {
223235
skip_if_not_installed("igraph")
224236

@@ -236,6 +248,30 @@ test_that("igraph vertex order is preserved when converting to caugi", {
236248
expect_equal(V(cg)$name, paste0("V", 1:10))
237249
})
238250

251+
test_that("igraph without names: vertex order is preserved (issue #XX)", {
252+
skip_if_not_installed("igraph")
253+
254+
# Create igraph WITHOUT names - this is the exact issue scenario
255+
# When no name is given to igraph, the order should not be scrambled
256+
set.seed(1023)
257+
ig <- igraph::sample_gnm(100, 500) |> igraph::as_directed(mode = "acyclic")
258+
# Verify the graph has no names
259+
expect_null(igraph::V(ig)$name)
260+
261+
# Convert to caugi - names should be generated in order V1, V2, ..., V100
262+
cg <- as_caugi(ig, class = "DAG")
263+
264+
# The nodes should be in sequential order V1, V2, ..., V100
265+
expected_names <- paste0("V", 1:100)
266+
expect_equal(cg@nodes$name, expected_names)
267+
268+
# Also verify edges use the correct node names
269+
edges_df <- as.data.frame(edges(cg))
270+
# All from/to values should be valid names from expected_names
271+
expect_true(all(edges_df$from %in% expected_names))
272+
expect_true(all(edges_df$to %in% expected_names))
273+
})
274+
239275
# ──────────────────────────────────────────────────────────────────────────────
240276
# ─────────────────────────── graphNEL conversion ──────────────────────────────
241277
# ──────────────────────────────────────────────────────────────────────────────

0 commit comments

Comments
 (0)