@@ -615,52 +615,70 @@ subgraph <- function(cg, nodes = NULL, index = NULL) {
615615 stop(" Supply one of `nodes` or `index`." , call. = FALSE )
616616 }
617617
618+ # resolve -> keep_ids0 (0-based), keep_names, preserving order
618619 if (index_supplied ) {
620+ if (! is.numeric(index ) || anyNA(index )) {
621+ stop(" `index` must be numeric without NA." , call. = FALSE )
622+ }
619623 idx1 <- as.integer(index )
620624 if (any(idx1 < 1L ) || any(idx1 > nrow(cg @ nodes ))) {
621625 stop(" `index` out of range (1..n)." , call. = FALSE )
622626 }
627+ keep_ids0 <- idx1 - 1L
623628 keep_names <- cg @ nodes $ name [idx1 ]
624629 } else {
625630 if (! is.character(nodes )) {
626631 stop(" `nodes` must be a character vector." , call. = FALSE )
627632 }
633+ if (anyNA(nodes )) {
634+ stop(" `nodes` contains NA." , call. = FALSE )
635+ }
628636 missing <- setdiff(nodes , cg @ nodes $ name )
629637 if (length(missing )) {
630638 stop(" Unknown node(s): " , paste(missing , collapse = " , " ), call. = FALSE )
631639 }
632640 keep_names <- nodes
641+ keep_ids0 <- vapply(nodes , cg @ name_index_map $ get , integer(1 ))
633642 }
634643
635- if (any(duplicated(keep_names ))) {
636- dups <- unique(keep_names [duplicated(keep_names )])
637- stop(" `nodes`/`index` contains duplicates: " ,
638- paste(dups , collapse = " , " ),
639- call. = FALSE
640- )
644+ # duplicates are an error
645+ if (any(duplicated(keep_ids0 ))) {
646+ dups <- unique(keep_names [duplicated(keep_ids0 ) | duplicated(keep_ids0 , fromLast = TRUE )])
647+ stop(" `nodes`/`index` contains duplicates: " , paste(dups , collapse = " , " ), call. = FALSE )
641648 }
642649
643- # filter edges to the kept nodes; keep constructor’s sort
650+ # call Rust (always reindexed)
651+ ptr_sub <- induced_subgraph_ptr(cg @ ptr , as.integer(keep_ids0 ))
652+
653+ # nodes table in input order
654+ nodes_sub <- tibble :: tibble(name = keep_names )
655+
656+ # filter edges to kept names and sort like constructor
644657 keep_set <- fastmap :: fastmap()
645658 for (nm in keep_names ) keep_set $ set(nm , TRUE )
646659 edges_sub <- cg @ edges | >
647660 dplyr :: filter(keep_set $ has(.data $ from ) & keep_set $ has(.data $ to )) | >
648661 dplyr :: arrange(.data $ from , .data $ to , .data $ edge )
649662
650- # rebuild via constructor: declared nodes contain all edge nodes
651- caugi_graph(
652- from = edges_sub $ from ,
653- edge = edges_sub $ edge ,
654- to = edges_sub $ to ,
655- nodes = keep_names ,
663+ # rebuild name_index_map
664+ name_index_map_sub <- fastmap :: fastmap()
665+ for (i in seq_len(nrow(nodes_sub ))) name_index_map_sub $ set(nodes_sub $ name [i ], i - 1L )
666+
667+ state_sub <- .cg_state(
668+ nodes = nodes_sub ,
669+ edges = edges_sub ,
670+ ptr = ptr_sub ,
671+ built = TRUE ,
656672 simple = cg @ simple ,
657- build = TRUE ,
658- class = cg @ graph_class
673+ class = cg @ graph_class ,
674+ name_index_map = name_index_map_sub
659675 )
676+ caugi_graph(state = state_sub )
660677}
661678
662679
663680
681+
664682# ──────────────────────────────────────────────────────────────────────────────
665683# ──────────────────────────── Relations helpers ───────────────────────────────
666684# ──────────────────────────────────────────────────────────────────────────────
0 commit comments