Skip to content

Commit

Permalink
feat: Adds find_path_one_to_many
Browse files Browse the repository at this point in the history
  • Loading branch information
andyquinterom committed Oct 17, 2024
1 parent 3611c8a commit 54cc929
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 1 deletion.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ BugReports: https://github.com/ixpantia/orbweaver-r/issues
License: MIT + file LICENSE
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.1
RoxygenNote: 7.3.2
Config/rextendr/version: 0.3.1.9000
SystemRequirements: Cargo (Rust's package manager) >= 1.70, rustc >= 1.70
Depends:
Expand Down
3 changes: 3 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ S3method(find_all_paths,DirectedAcyclicGraph)
S3method(find_all_paths,DirectedGraph)
S3method(find_path,DirectedAcyclicGraph)
S3method(find_path,DirectedGraph)
S3method(find_path_one_to_many,DirectedAcyclicGraph)
S3method(find_path_one_to_many,DirectedGraph)
S3method(get_all_leaves,DirectedAcyclicGraph)
S3method(get_all_leaves,DirectedGraph)
S3method(get_all_roots,DirectedAcyclicGraph)
Expand Down Expand Up @@ -47,6 +49,7 @@ export(build_directed)
export(children)
export(find_all_paths)
export(find_path)
export(find_path_one_to_many)
export(get_all_leaves)
export(get_all_roots)
export(get_leaves_under)
Expand Down
4 changes: 4 additions & 0 deletions R/extendr-wrappers.R
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ DirectedGraph$length <- function() .Call(wrap__DirectedGraph__length, self)

DirectedGraph$find_all_paths <- function(from, to) .Call(wrap__DirectedGraph__find_all_paths, self, from, to)

DirectedGraph$find_path_one_to_many <- function(from, to) .Call(wrap__DirectedGraph__find_path_one_to_many, self, from, to)

#' @export
`$.DirectedGraph` <- function (self, name) { func <- DirectedGraph[[name]]; environment(func) <- environment(); func }

Expand Down Expand Up @@ -98,6 +100,8 @@ DirectedAcyclicGraph$length <- function() .Call(wrap__DirectedAcyclicGraph__leng

DirectedAcyclicGraph$find_all_paths <- function(from, to) .Call(wrap__DirectedAcyclicGraph__find_all_paths, self, from, to)

DirectedAcyclicGraph$find_path_one_to_many <- function(from, to) .Call(wrap__DirectedAcyclicGraph__find_path_one_to_many, self, from, to)

#' @export
`$.DirectedAcyclicGraph` <- function (self, name) { func <- DirectedAcyclicGraph[[name]]; environment(func) <- environment(); func }

Expand Down
26 changes: 26 additions & 0 deletions R/find_path.R
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,29 @@ find_all_paths.DirectedGraph <- function(graph, from, to) {
find_all_paths.DirectedAcyclicGraph <- function(graph, from, to) {
graph$find_all_paths(from, to)
}

#' @title Find the shortest path from one node to many
#'
#' @description
#' Find the shortest path from one node to many
#'
#' Not all graphs support this function. Currently only
#' `DirectedAcyclicGraph` supports this.
#' @param graph A graph object
#' @param from The starting node of the path
#' @param to A character vector of nodes
#' @return A list of paths
#' @export
find_path_one_to_many <- function(graph, from, to) {
UseMethod("find_path_one_to_many")
}

#' @export
find_path_one_to_many.DirectedGraph <- function(graph, from, to) {
graph$find_path_one_to_many(from, to)
}

#' @export
find_path_one_to_many.DirectedAcyclicGraph <- function(graph, from, to) {
graph$find_path_one_to_many(from, to)
}
24 changes: 24 additions & 0 deletions man/find_path_one_to_many.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ impl DirectedGraphBuilder {

pub trait RImplDirectedGraph: Sized {
fn find_path(&self, from: &str, to: &str) -> Result<NodeVec>;
fn find_path_one_to_many(&self, from: &str, to: Strings) -> Result<List>;
fn children(&self, nodes: RNodesIn) -> Result<NodeVec>;
fn parents(&self, nodes: RNodesIn) -> Result<NodeVec>;
fn has_parents(&self, nodes: RNodesIn) -> Result<Vec<bool>>;
Expand Down
10 changes: 10 additions & 0 deletions src/rust/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ macro_rules! impl_directed_graph {
.map(NodeVec)
.collect())
}

fn find_path_one_to_many(&self, from: &str, to: Strings) -> Result<List> {
Ok(self
.0
.find_path_one_to_many(from, to.iter())
.map_err(to_r_error)?
.into_iter()
.map(NodeVec)
.collect())
}
}

impl $ty {
Expand Down
34 changes: 34 additions & 0 deletions tests/testthat/test-find_path.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,37 @@ test_that("find all paths on directed acyclic graph", {
list(c("A", "Z", "C"), c("A", "B", "C"))
)
})

test_that("find path from one node to many nodes", {

edges <- tibble::tibble(
Parent = c("A", "A", "B", "C", "D", "Z"),
Child = c("B", "C", "Z", "D", "Z", "F")
)

graph <- graph_builder() |>
populate_edges(edges, Parent, Child) |>
build_acyclic()

edges$path_ow <- find_path_one_to_many(graph, "A", edges$Child)
edges$level <- sapply(edges$path_ow, length)
edges$path <- sapply(edges$path_ow, \(path) paste(as.character(path), collapse = "|"))

expect_equal(
edges$level,
c(2, 2, 5, 3, 5, 6)
)

expect_equal(
edges$path,
c(
"A|B",
"A|C",
"A|B|C|D|Z",
"A|C|D",
"A|B|C|D|Z",
"A|B|C|D|Z|F"
)
)

})

0 comments on commit 54cc929

Please sign in to comment.