From 961c3b213c6bf68e410e7601346ea7ee13a0808a Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 11 Oct 2023 15:44:41 +0200 Subject: [PATCH 1/7] feat: keep_results can be character vector of IDs This can be useful when wanting access to an object that is not an output node of the graph, i.e. we don't have to add a `PipeOpNOP` (or keep all results) to achieve this. --- NEWS.md | 3 +++ R/Graph.R | 5 +++-- R/PipeOp.R | 2 +- man/Graph.Rd | 3 ++- man/PipeOp.Rd | 2 +- man/mlr_pipeops_nmf.Rd | 2 +- tests/testthat/test_Graph.R | 11 +++++++++++ 7 files changed, 22 insertions(+), 6 deletions(-) diff --git a/NEWS.md b/NEWS.md index a1074398a..7b147489e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,8 @@ # mlr3pipelines 0.5.0-9000 +* Feature: The `Graph`'s `keep_results` can now also be a character vector +containing the IDs of the `PipeOp`s whose results are being stored. + # mlr3pipelines 0.5.0-1 * Bugfix: `PipeOpTuneThreshold` was not overloading the correct `.train` and `.predict` functions. diff --git a/R/Graph.R b/R/Graph.R index 8cc95a0ae..b9070ffc1 100644 --- a/R/Graph.R +++ b/R/Graph.R @@ -59,8 +59,9 @@ #' * `phash` :: `character(1)` \cr #' Stores a checksum calculated on the [`Graph`] configuration, which includes all [`PipeOp`] hashes #' *except* their `$param_set$values`, and a hash of `$edges`. -#' * `keep_results` :: `logical(1)` \cr +#' * `keep_results` :: `logical(1)` or `character()` \cr #' Whether to store intermediate results in the [`PipeOp`]'s `$.result` slot, mostly for debugging purposes. Default `FALSE`. +#' Can also be a character vector of IDs, in which case only the results of the selected `PipeOp`s are stored. #' * `man` :: `character(1)`\cr #' Identifying string of the help page that shows with `help()`. #' @@ -642,7 +643,7 @@ graph_reduce = function(self, input, fun, single_input) { lg$debug("Running PipeOp '%s$%s()'", id, fun, pipeop = op, input = input) output = op[[fun]](input) - if (self$keep_results) { + if (isTRUE(self$keep_results) || op$id %in% self$keep_results) { op$.result = output } diff --git a/R/PipeOp.R b/R/PipeOp.R index 24a12ab6c..c9b393e70 100644 --- a/R/PipeOp.R +++ b/R/PipeOp.R @@ -130,7 +130,7 @@ #' [`PipeOp`]'s functionality may change depending on more than these values, it should inherit the `$hash` active #' binding and calculate the hash as `digest(list(super$hash, ), algo = "xxhash64")`. #' * `.result` :: `list` \cr -#' If the [`Graph`]'s `$keep_results` flag is set to `TRUE`, then the intermediate Results of `$train()` and `$predict()` +#' If the [`Graph`]'s `$keep_results` flag is set to `TRUE` or contains the ID of this `PipeOp`, then the intermediate Results of `$train()` and `$predict()` #' are saved to this slot, exactly as they are returned by these functions. This is mainly for debugging purposes #' and done, if requested, by the [`Graph`] backend itself; it should *not* be done explicitly by `private$.train()` or `private$.predict()`. #' * `man` :: `character(1)`\cr diff --git a/man/Graph.Rd b/man/Graph.Rd index 8da82dac3..fa51c234e 100644 --- a/man/Graph.Rd +++ b/man/Graph.Rd @@ -69,8 +69,9 @@ Stores a checksum calculated on the \code{\link{Graph}} configuration, which inc \item \code{phash} :: \code{character(1)} \cr Stores a checksum calculated on the \code{\link{Graph}} configuration, which includes all \code{\link{PipeOp}} hashes \emph{except} their \verb{$param_set$values}, and a hash of \verb{$edges}. -\item \code{keep_results} :: \code{logical(1)} \cr +\item \code{keep_results} :: \code{logical(1)} or \code{character()} \cr Whether to store intermediate results in the \code{\link{PipeOp}}'s \verb{$.result} slot, mostly for debugging purposes. Default \code{FALSE}. +Can also be a character vector of IDs, in which case only the results of the selected \code{PipeOp}s are stored. \item \code{man} :: \code{character(1)}\cr Identifying string of the help page that shows with \code{help()}. } diff --git a/man/PipeOp.Rd b/man/PipeOp.Rd index 4292943b1..553ca0301 100644 --- a/man/PipeOp.Rd +++ b/man/PipeOp.Rd @@ -137,7 +137,7 @@ Checksum calculated on the \code{\link{PipeOp}}, depending on the \code{\link{Pi \code{\link{PipeOp}}'s functionality may change depending on more than these values, it should inherit the \verb{$hash} active binding and calculate the hash as \verb{digest(list(super$hash, ), algo = "xxhash64")}. \item \code{.result} :: \code{list} \cr -If the \code{\link{Graph}}'s \verb{$keep_results} flag is set to \code{TRUE}, then the intermediate Results of \verb{$train()} and \verb{$predict()} +If the \code{\link{Graph}}'s \verb{$keep_results} flag is set to \code{TRUE} or contains the ID of this \code{PipeOp}, then the intermediate Results of \verb{$train()} and \verb{$predict()} are saved to this slot, exactly as they are returned by these functions. This is mainly for debugging purposes and done, if requested, by the \code{\link{Graph}} backend itself; it should \emph{not} be done explicitly by \code{private$.train()} or \code{private$.predict()}. \item \code{man} :: \code{character(1)}\cr diff --git a/man/mlr_pipeops_nmf.Rd b/man/mlr_pipeops_nmf.Rd index 5e967fab2..3c8a75c9a 100644 --- a/man/mlr_pipeops_nmf.Rd +++ b/man/mlr_pipeops_nmf.Rd @@ -96,7 +96,7 @@ See \code{\link[NMF:nmf]{nmf()}}. \section{Internals}{ -Uses the \code{\link[NMF:nmf]{nmf()}} function as well as \code{\link[NMF:basis-coef-methods]{basis()}}, \code{\link[NMF:basis-coef-methods]{coef()}} and +Uses the \code{\link[NMF:nmf]{nmf()}} function as well as \code{\link[NMF:basis]{basis()}}, \code{\link[NMF:coef]{coef()}} and \code{\link[MASS:ginv]{ginv()}}. } diff --git a/tests/testthat/test_Graph.R b/tests/testthat/test_Graph.R index ed6f900d8..af40c8f15 100644 --- a/tests/testthat/test_Graph.R +++ b/tests/testthat/test_Graph.R @@ -501,3 +501,14 @@ test_that("Same output into multiple channels does not cause a bug", { expect_true(res$po3.output1 == 2) expect_true(res$po4.output1 == 2) }) + +test_that("keep_results can be a character vector", { + graph = po("pca") %>>% po("ica") + + graph$keep_results = "pca" + + graph$train(tsk("iris")) + + expect_true(is.null(graph$pipeops$ica$.result)) + expect_class(graph$pipeops$pca$.result[[1L]], "Task") +}) From 6af2a0525f947354b1084cf93ce0fdfee36b86ba Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Fri, 27 Oct 2023 17:39:30 +0200 Subject: [PATCH 2/7] fix(POFU): columns named "x" were sometimes dropped The "vodoo" variable was named "x". When another variable was named "x", the subsetting of unique names kept only the first occuranc of "x". --- R/PipeOpFeatureUnion.R | 1 + 1 file changed, 1 insertion(+) diff --git a/R/PipeOpFeatureUnion.R b/R/PipeOpFeatureUnion.R index 8a2c1b4ce..bbc1e890b 100644 --- a/R/PipeOpFeatureUnion.R +++ b/R/PipeOpFeatureUnion.R @@ -202,6 +202,7 @@ cbind_tasks = function(inputs, assert_targets_equal, inprefix) { # again done by reference new_features = unlist(c(list(data.table(x = vector(length = task$nrow))), map(tail(inputs, -1L), .f = function(y) y$data(ids, cols = y$feature_names))), recursive = FALSE) + names(new_features)[1] = make.unique(rev(names(new_features)))[[length(new_features)]] # we explicitly have to subset to the unique column names, otherwise task$cbind() complains for data.table backends new_features = new_features[unique(names(new_features))] From 3ff31a4ec98ed91522ef2cd85e3525a8af20338a Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 31 Oct 2023 20:16:16 +0100 Subject: [PATCH 3/7] tests: add test for pofu dropping 'x' --- tests/testthat/test_pipeop_featureunion.R | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/testthat/test_pipeop_featureunion.R b/tests/testthat/test_pipeop_featureunion.R index 9687d1afb..f408fb196 100644 --- a/tests/testthat/test_pipeop_featureunion.R +++ b/tests/testthat/test_pipeop_featureunion.R @@ -257,3 +257,18 @@ test_that("featureunion - cbind_tasks - duplicates", { expect_equal(output$data(cols = "x"), inputs[[1L]]$data(cols = "x")) expect_equivalent(output$data(cols = c("Species", new_iris_names)), task1$data()) }) + +test_that("featureunion - does not drop 'x' column", { + task1 = as_task_regr(data.table( + z = 1:10, + y = 1:10 + ), target = "y") + + task2 = as_task_regr(data.table( + x = 1:10, + y = 1:10 + ), target = "y") + + taskout = po("featureunion")$train(list(task1, task2))[[1L]] + expect_permutation(taskout$feature_names, c("x", "z")) +}) From bed0f07d294b73b863b8d5e3ce984a81d7638d73 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 8 Nov 2023 18:00:40 +0100 Subject: [PATCH 4/7] feat(Graph): add_pipeop gets argument 'clone' --- NEWS.md | 3 +++ R/Graph.R | 11 ++++++----- man/Graph.Rd | 7 ++++--- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/NEWS.md b/NEWS.md index 7b147489e..940986bc2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,6 +2,9 @@ * Feature: The `Graph`'s `keep_results` can now also be a character vector containing the IDs of the `PipeOp`s whose results are being stored. +* Feature: The `$add_pipeop()` method got an argument `clone` that is `TRUE` by +default (previously `PipeOp`s were always cloned) +* Bugfix: `PipeOpFeatureUnion` in some rare cases dropped variables called `"x"` # mlr3pipelines 0.5.0-1 diff --git a/R/Graph.R b/R/Graph.R index b9070ffc1..f4fc796ad 100644 --- a/R/Graph.R +++ b/R/Graph.R @@ -70,13 +70,14 @@ #' (`logical(1)`) -> `character` \cr #' Get IDs of all [`PipeOp`]s. This is in order that [`PipeOp`]s were added if #' `sorted` is `FALSE`, and topologically sorted if `sorted` is `TRUE`. -#' * `add_pipeop(op)` \cr -#' ([`PipeOp`] | [`Learner`][mlr3::Learner] | [`Filter`][mlr3filters::Filter] | `...`) -> `self` \cr +#' * `add_pipeop(op, clone = TRUE)` \cr +#' ([`PipeOp`] | [`Learner`][mlr3::Learner] | [`Filter`][mlr3filters::Filter] | `...`, `logical(1)`) -> `self` \cr #' Mutates [`Graph`] by adding a [`PipeOp`] to the [`Graph`]. This does not add any edges, so the new [`PipeOp`] #' will not be connected within the [`Graph`] at first.\cr #' Instead of supplying a [`PipeOp`] directly, an object that can naturally be converted to a [`PipeOp`] can also #' be supplied, e.g. a [`Learner`][mlr3::Learner] or a [`Filter`][mlr3filters::Filter]; see [`as_pipeop()`]. -#' The argument given as `op` is always cloned; to access a `Graph`'s [`PipeOp`]s by-reference, use `$pipeops`.\cr +#' The argument given as `op` is cloned if `clone` is `TRUE` (default); to access a `Graph`'s [`PipeOp`]s +#' by-reference, use `$pipeops`.\cr #' Note that `$add_pipeop()` is a relatively low-level operation, it is recommended to build graphs using [`%>>%`]. #' * `add_edge(src_id, dst_id, src_channel = NULL, dst_channel = NULL)` \cr #' (`character(1)`, `character(1)`, @@ -182,8 +183,8 @@ Graph = R6Class("Graph", topo_sort(tmp)$id }, - add_pipeop = function(op) { - op = as_pipeop(op, clone = TRUE) + add_pipeop = function(op, clone = TRUE) { + op = as_pipeop(op, clone = assert_flag(clone)) if (op$id %in% names(self$pipeops)) { stopf("PipeOp with id '%s' already in Graph", op$id) } diff --git a/man/Graph.Rd b/man/Graph.Rd index fa51c234e..0db8e24a6 100644 --- a/man/Graph.Rd +++ b/man/Graph.Rd @@ -84,13 +84,14 @@ Identifying string of the help page that shows with \code{help()}. (\code{logical(1)}) -> \code{character} \cr Get IDs of all \code{\link{PipeOp}}s. This is in order that \code{\link{PipeOp}}s were added if \code{sorted} is \code{FALSE}, and topologically sorted if \code{sorted} is \code{TRUE}. -\item \code{add_pipeop(op)} \cr -(\code{\link{PipeOp}} | \code{\link[mlr3:Learner]{Learner}} | \code{\link[mlr3filters:Filter]{Filter}} | \code{...}) -> \code{self} \cr +\item \code{add_pipeop(op, clone = TRUE)} \cr +(\code{\link{PipeOp}} | \code{\link[mlr3:Learner]{Learner}} | \code{\link[mlr3filters:Filter]{Filter}} | \code{...}, \code{logical(1)}) -> \code{self} \cr Mutates \code{\link{Graph}} by adding a \code{\link{PipeOp}} to the \code{\link{Graph}}. This does not add any edges, so the new \code{\link{PipeOp}} will not be connected within the \code{\link{Graph}} at first.\cr Instead of supplying a \code{\link{PipeOp}} directly, an object that can naturally be converted to a \code{\link{PipeOp}} can also be supplied, e.g. a \code{\link[mlr3:Learner]{Learner}} or a \code{\link[mlr3filters:Filter]{Filter}}; see \code{\link[=as_pipeop]{as_pipeop()}}. -The argument given as \code{op} is always cloned; to access a \code{Graph}'s \code{\link{PipeOp}}s by-reference, use \verb{$pipeops}.\cr +The argument given as \code{op} is cloned if \code{clone} is \code{TRUE} (default); to access a \code{Graph}'s \code{\link{PipeOp}}s +by-reference, use \verb{$pipeops}.\cr Note that \verb{$add_pipeop()} is a relatively low-level operation, it is recommended to build graphs using \code{\link{\%>>\%}}. \item \code{add_edge(src_id, dst_id, src_channel = NULL, dst_channel = NULL)} \cr (\code{character(1)}, \code{character(1)}, From 5c98e886c9c7ac1b01fa2ce0b4b0e34d384ee79a Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 8 Nov 2023 18:23:40 +0100 Subject: [PATCH 5/7] fix: as_graph respects clone argument for PipeOp method --- R/assert_graph.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/assert_graph.R b/R/assert_graph.R index 03c723e14..828f4b4fc 100644 --- a/R/assert_graph.R +++ b/R/assert_graph.R @@ -40,7 +40,7 @@ as_graph = function(x, clone = FALSE) { #' @export as_graph.default = function(x, clone = FALSE) { - Graph$new()$add_pipeop(x) # add_pipeop always clones and checks automatically for convertability + Graph$new()$add_pipeop(x, clone = clone) } #' @export From 13e00e4efeb924fc00681b554e089da8ea7fd2f6 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 17:45:36 +0100 Subject: [PATCH 6/7] revert keep_results --- DESCRIPTION | 2 +- NAMESPACE | 1 + NEWS.md | 5 ++--- R/Graph.R | 5 ++--- R/PipeOp.R | 2 +- man/Graph.Rd | 3 +-- man/PipeOp.Rd | 2 +- man/mlr_pipeops_nmf.Rd | 2 +- tests/testthat/test_Graph.R | 11 ----------- 9 files changed, 10 insertions(+), 23 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 5e6b8a1ef..10fb81ecd 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -93,7 +93,7 @@ Config/testthat/edition: 3 Config/testthat/parallel: true NeedsCompilation: no Roxygen: list(markdown = TRUE, r6 = FALSE) -RoxygenNote: 7.2.3 +RoxygenNote: 7.2.3.9000 VignetteBuilder: knitr Collate: 'Graph.R' diff --git a/NAMESPACE b/NAMESPACE index a40fd7b44..c0b0975d9 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -148,6 +148,7 @@ import(mlr3) import(mlr3misc) import(paradox) importFrom(R6,R6Class) +importFrom(data.table,as.data.table) importFrom(digest,digest) importFrom(stats,setNames) importFrom(utils,bibentry) diff --git a/NEWS.md b/NEWS.md index 940986bc2..f2dbc84a6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,10 +1,9 @@ # mlr3pipelines 0.5.0-9000 -* Feature: The `Graph`'s `keep_results` can now also be a character vector -containing the IDs of the `PipeOp`s whose results are being stored. * Feature: The `$add_pipeop()` method got an argument `clone` that is `TRUE` by default (previously `PipeOp`s were always cloned) -* Bugfix: `PipeOpFeatureUnion` in some rare cases dropped variables called `"x"` +* Bugfix: `PipeOpFeatureUnion` in some rare cases dropped variables called +`"x"`, this is no longer the case # mlr3pipelines 0.5.0-1 diff --git a/R/Graph.R b/R/Graph.R index f4fc796ad..7df319808 100644 --- a/R/Graph.R +++ b/R/Graph.R @@ -59,9 +59,8 @@ #' * `phash` :: `character(1)` \cr #' Stores a checksum calculated on the [`Graph`] configuration, which includes all [`PipeOp`] hashes #' *except* their `$param_set$values`, and a hash of `$edges`. -#' * `keep_results` :: `logical(1)` or `character()` \cr +#' * `keep_results` :: `logical(1)`\cr #' Whether to store intermediate results in the [`PipeOp`]'s `$.result` slot, mostly for debugging purposes. Default `FALSE`. -#' Can also be a character vector of IDs, in which case only the results of the selected `PipeOp`s are stored. #' * `man` :: `character(1)`\cr #' Identifying string of the help page that shows with `help()`. #' @@ -644,7 +643,7 @@ graph_reduce = function(self, input, fun, single_input) { lg$debug("Running PipeOp '%s$%s()'", id, fun, pipeop = op, input = input) output = op[[fun]](input) - if (isTRUE(self$keep_results) || op$id %in% self$keep_results) { + if (self$keep_results) { op$.result = output } diff --git a/R/PipeOp.R b/R/PipeOp.R index c9b393e70..24a12ab6c 100644 --- a/R/PipeOp.R +++ b/R/PipeOp.R @@ -130,7 +130,7 @@ #' [`PipeOp`]'s functionality may change depending on more than these values, it should inherit the `$hash` active #' binding and calculate the hash as `digest(list(super$hash, ), algo = "xxhash64")`. #' * `.result` :: `list` \cr -#' If the [`Graph`]'s `$keep_results` flag is set to `TRUE` or contains the ID of this `PipeOp`, then the intermediate Results of `$train()` and `$predict()` +#' If the [`Graph`]'s `$keep_results` flag is set to `TRUE`, then the intermediate Results of `$train()` and `$predict()` #' are saved to this slot, exactly as they are returned by these functions. This is mainly for debugging purposes #' and done, if requested, by the [`Graph`] backend itself; it should *not* be done explicitly by `private$.train()` or `private$.predict()`. #' * `man` :: `character(1)`\cr diff --git a/man/Graph.Rd b/man/Graph.Rd index 0db8e24a6..ab76b20c8 100644 --- a/man/Graph.Rd +++ b/man/Graph.Rd @@ -69,9 +69,8 @@ Stores a checksum calculated on the \code{\link{Graph}} configuration, which inc \item \code{phash} :: \code{character(1)} \cr Stores a checksum calculated on the \code{\link{Graph}} configuration, which includes all \code{\link{PipeOp}} hashes \emph{except} their \verb{$param_set$values}, and a hash of \verb{$edges}. -\item \code{keep_results} :: \code{logical(1)} or \code{character()} \cr +\item \code{keep_results} :: \code{logical(1)}\cr Whether to store intermediate results in the \code{\link{PipeOp}}'s \verb{$.result} slot, mostly for debugging purposes. Default \code{FALSE}. -Can also be a character vector of IDs, in which case only the results of the selected \code{PipeOp}s are stored. \item \code{man} :: \code{character(1)}\cr Identifying string of the help page that shows with \code{help()}. } diff --git a/man/PipeOp.Rd b/man/PipeOp.Rd index 553ca0301..4292943b1 100644 --- a/man/PipeOp.Rd +++ b/man/PipeOp.Rd @@ -137,7 +137,7 @@ Checksum calculated on the \code{\link{PipeOp}}, depending on the \code{\link{Pi \code{\link{PipeOp}}'s functionality may change depending on more than these values, it should inherit the \verb{$hash} active binding and calculate the hash as \verb{digest(list(super$hash, ), algo = "xxhash64")}. \item \code{.result} :: \code{list} \cr -If the \code{\link{Graph}}'s \verb{$keep_results} flag is set to \code{TRUE} or contains the ID of this \code{PipeOp}, then the intermediate Results of \verb{$train()} and \verb{$predict()} +If the \code{\link{Graph}}'s \verb{$keep_results} flag is set to \code{TRUE}, then the intermediate Results of \verb{$train()} and \verb{$predict()} are saved to this slot, exactly as they are returned by these functions. This is mainly for debugging purposes and done, if requested, by the \code{\link{Graph}} backend itself; it should \emph{not} be done explicitly by \code{private$.train()} or \code{private$.predict()}. \item \code{man} :: \code{character(1)}\cr diff --git a/man/mlr_pipeops_nmf.Rd b/man/mlr_pipeops_nmf.Rd index 3c8a75c9a..5e967fab2 100644 --- a/man/mlr_pipeops_nmf.Rd +++ b/man/mlr_pipeops_nmf.Rd @@ -96,7 +96,7 @@ See \code{\link[NMF:nmf]{nmf()}}. \section{Internals}{ -Uses the \code{\link[NMF:nmf]{nmf()}} function as well as \code{\link[NMF:basis]{basis()}}, \code{\link[NMF:coef]{coef()}} and +Uses the \code{\link[NMF:nmf]{nmf()}} function as well as \code{\link[NMF:basis-coef-methods]{basis()}}, \code{\link[NMF:basis-coef-methods]{coef()}} and \code{\link[MASS:ginv]{ginv()}}. } diff --git a/tests/testthat/test_Graph.R b/tests/testthat/test_Graph.R index af40c8f15..ed6f900d8 100644 --- a/tests/testthat/test_Graph.R +++ b/tests/testthat/test_Graph.R @@ -501,14 +501,3 @@ test_that("Same output into multiple channels does not cause a bug", { expect_true(res$po3.output1 == 2) expect_true(res$po4.output1 == 2) }) - -test_that("keep_results can be a character vector", { - graph = po("pca") %>>% po("ica") - - graph$keep_results = "pca" - - graph$train(tsk("iris")) - - expect_true(is.null(graph$pipeops$ica$.result)) - expect_class(graph$pipeops$pca$.result[[1L]], "Task") -}) From c75b598aa6f9176e254ed6b289d0597416795441 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Sat, 27 Jan 2024 18:49:21 +0100 Subject: [PATCH 7/7] change default for backwards compatability --- R/assert_graph.R | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/R/assert_graph.R b/R/assert_graph.R index 828f4b4fc..fadaa22b7 100644 --- a/R/assert_graph.R +++ b/R/assert_graph.R @@ -39,7 +39,9 @@ as_graph = function(x, clone = FALSE) { } #' @export -as_graph.default = function(x, clone = FALSE) { +as_graph.default = function(x, clone = TRUE) { + # different default than other methods for backwards compatibility + # previously $add_pipeop() always cloned its input Graph$new()$add_pipeop(x, clone = clone) }