Skip to content

Commit 39cbe06

Browse files
committedJan 24, 2019
Initial version
1 parent 6a26086 commit 39cbe06

26 files changed

+1484
-0
lines changed
 

‎.Rbuildignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
^docs$
2+
^_pkgdown\.yml$
3+
^LICENSE\.md$
4+
^.*\.Rproj$
5+
^\.Rproj\.user$

‎.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.Rhistory
2+
.RData
3+
.Rproj.user

‎LICENSE.md

+595
Large diffs are not rendered by default.

‎NAMESPACE

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Generated by roxygen2: do not edit by hand
2+
3+
S3method(py_str,pm4py.objects.log.log.Trace)
4+
S3method(py_str,pm4py.objects.log.log.TraceLog)
5+
S3method(py_to_r,pm4py.objects.log.log.EventLog)
6+
S3method(py_to_r,pm4py.objects.log.log.TraceLog)
7+
S3method(py_to_r,pm4py.objects.petri.petrinet.Marking)
8+
S3method(py_to_r,pm4py.objects.petri.petrinet.PetriNet)
9+
S3method(r_to_py,eventlog)
10+
S3method(r_to_py,petrinet)
11+
export(conformance_alignment)
12+
export(discovery_alpha)
13+
export(discovery_inductive)
14+
export(install_pm4py)
15+
export(param_activity_key)
16+
export(param_attribute_key)
17+
export(param_caseid_key)
18+
export(param_resource_key)
19+
export(param_timestamp_key)
20+
export(petrinet_synchronous_product)
21+
export(pm4py)
22+
export(variant_alpha_classic)
23+
export(variant_inductive_only_dfg)
24+
export(variant_state_equation_a_star)
25+
export(version)
26+
import(dplyr)
27+
import(reticulate)
28+
importFrom(magrittr,"%>%")
29+
importFrom(reticulate,iterate)
30+
importFrom(reticulate,py_str)
31+
importFrom(reticulate,py_to_r)
32+
importFrom(reticulate,r_to_py)

‎R/alignments.R

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#' Alignment between an Event Log and a Petri net
2+
#'
3+
#' @param eventlog A bupaR or PM4PY event log.
4+
#' @param petrinet A bupaR or PM4PY Petri net.
5+
#' @param initial_marking A R vector with the place identifiers of the initial marking or a PM4PY marking.
6+
#' By default the initial marking of the bupaR Petri net will be used if available.
7+
#' @param final_marking A R vector with the place identifiers of the final marking or a PM4PY marking.
8+
#' @param parameters PM4PY alignment parameter.
9+
#' By default the `activity_key` from the bupaR event log is specified using \link{param_activity_key}.
10+
#' @param variant The alignment variant to be used.
11+
#' @param convert `TRUE` to automatically convert Python objects to their R equivalent. If you pass `FALSE` you can do manual conversion using the \link[reticulate]{r-py-conversion} function.
12+
#'
13+
#' @return A `data.frame` describing the alignment in terms of log and model moves.
14+
#' @export
15+
#'
16+
#' @examples
17+
#' \dontrun{
18+
#' net <- discovery_inductive(patients)
19+
#'
20+
#' a <- conformance_alignment(patients,
21+
#' net$petrinet,
22+
#' net$initial_marking,
23+
#' net$final_marking)
24+
#' }
25+
#'
26+
#' @import dplyr
27+
#' @importFrom magrittr "%>%"
28+
conformance_alignment <- function(eventlog,
29+
petrinet,
30+
initial_marking,
31+
final_marking,
32+
parameters = param_activity_key(bupaR::activity_id(eventlog)),
33+
variant = variant_state_equation_a_star(),
34+
convert = TRUE) {
35+
36+
pm4py_alignments <- import("pm4py.algo.conformance.alignments.factory", convert = convert)
37+
if (is.null(initial_marking) && inherits(petrinet, "petrinet")) {
38+
initial_marking <- petrinet$marking
39+
}
40+
41+
py_pn <- as_py_value(petrinet)
42+
py_log <- as_py_value(eventlog)
43+
44+
alignment <- pm4py_alignments$apply(obj = py_log,
45+
petri_net = py_pn,
46+
initial_marking = as_pm4py_marking(initial_marking, py_pn),
47+
final_marking = as_pm4py_marking(final_marking, py_pn),
48+
parameters = parameters,
49+
version = variant)
50+
51+
if (convert) {
52+
53+
case_ids <- eventlog %>% as.data.frame() %>%
54+
distinct(!!as.symbol(bupaR::case_id(eventlog))) %>%
55+
pull()
56+
57+
purrr::map2_dfr(alignment, case_ids, function(trace, case_id) {
58+
59+
align_mat <- t(sapply(trace$alignment, c)) # convert nested lists to matrix
60+
align_mat[vapply(align_mat, is.null, TRUE)] <- NA_character_
61+
align_lst <- apply(align_mat, 2, unlist) # remove wrapper lists from elements
62+
63+
trace_df <- data.frame(align_lst, stringsAsFactors = FALSE)
64+
names(trace_df) <- c("logmove", "modelmove")
65+
66+
cbind(case_id, trace_df, trace[-1], # add meta information by duplicating it since we don't have a trace object
67+
stringsAsFactors = FALSE)
68+
})
69+
} else {
70+
alignment
71+
}
72+
}
73+
74+
#'A* search using the state equation as heuristic
75+
#'
76+
#' @export
77+
variant_state_equation_a_star <- function() {
78+
pm4py$algo$conformance$alignments$factory$VERSION_STATE_EQUATION_A_STAR
79+
}
80+
81+

‎R/bridge.R

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#' @export
2+
#' @importFrom reticulate r_to_py
3+
r_to_py.eventlog <- function(x, convert = FALSE) {
4+
5+
pm4py_log <- import("pm4py.objects.log", convert = convert)
6+
conversion_factory <- import("pm4py.objects.conversion.log.factory", convert = convert)
7+
8+
p_df <- r_to_py(as.data.frame(x), convert = convert)
9+
p_eventlog <- pm4py_log$log$EventLog(p_df$to_dict('records'))
10+
11+
case_glue <- py_to_r(pm4py_log$util$general$PARAMETER_KEY_CASE_GLUE)
12+
conversion_factory$apply(p_eventlog,
13+
parameters = py_dict(case_glue, bupaR::case_id(x)),
14+
version = conversion_factory$TO_TRACE_LOG)
15+
}
16+
17+
#' @export
18+
#' @importFrom reticulate py_to_r
19+
py_to_r.pm4py.objects.log.log.EventLog <- function(x) {
20+
pm4py$objects$log$exporter$csv$versions$pandas_csv_exp$get_dataframe_from_log(x)
21+
}
22+
23+
#' @export
24+
#' @importFrom reticulate py_to_r
25+
py_to_r.pm4py.objects.log.log.TraceLog <- function(x) {
26+
pm4py$objects$log$exporter$csv$versions$pandas_csv_exp$get_dataframe_from_log(x)
27+
}
28+
29+
#' @importFrom reticulate py_str
30+
#' @export
31+
py_str.pm4py.objects.log.log.TraceLog <- function(object, ...) {
32+
pm4py_str_sequence("TraceLog", object, ...)
33+
}
34+
35+
#' @importFrom reticulate py_str
36+
#' @export
37+
py_str.pm4py.objects.log.log.Trace <- function(object, ...) {
38+
pm4py_str_sequence("Trace", object, ...)
39+
}
40+
41+
pm4py_str_sequence <- function(name, x, ...) {
42+
len <- py_len(x)
43+
cat(name, " (", len, " items)", "\n",
44+
paste0(lapply(1:(min(10,len)), function(i) py_str(x[i])), collapse = ",\n"), sep = "")
45+
if (len > 10) {
46+
cat("\n... with ", len-10," more items")
47+
}
48+
}
49+
50+
#' @export
51+
#' @importFrom reticulate r_to_py
52+
r_to_py.petrinet <- function(x, convert = FALSE) {
53+
54+
pm4py_petrinet <- import("pm4py.objects.petri.petrinet", convert = convert)
55+
py_builtins <- import_builtins(convert = convert)
56+
57+
if ("label" %in% names(x$transitions)) {
58+
t_labels <- x$transitions$label
59+
} else {
60+
t_labels <- rep(NA, nrow(x$transitions))
61+
}
62+
63+
t_list <- Map(function(name, label) {
64+
if (is.na(label)) {
65+
label <- NULL
66+
}
67+
pm4py_petrinet$PetriNet$Transition(name, label)
68+
}, x$transitions$id, t_labels)
69+
70+
p_list <- Map(function(p) pm4py_petrinet$PetriNet$Place(p), x$places$id)
71+
72+
a_list <- Map(function(from, to) {
73+
if (from %in% names(t_list)) {
74+
source <- t_list[[from]]
75+
target <- p_list[[to]]
76+
} else {
77+
source <- p_list[[from]]
78+
target <- t_list[[to]]
79+
}
80+
81+
a <- pm4py_petrinet$PetriNet$Arc(source, target)
82+
83+
source$out_arcs$add(a)
84+
target$in_arcs$add(a)
85+
86+
return(a)
87+
88+
}, x$flows$from, x$flows$to)
89+
90+
pm4py_petrinet$PetriNet(
91+
places = unname(unlist(p_list)),
92+
transitions = unname(unlist(t_list)),
93+
arcs = py_builtins$set(unname(unlist(a_list)))
94+
)
95+
}
96+
97+
#' @export
98+
#' @importFrom reticulate iterate
99+
#' @importFrom reticulate py_to_r
100+
py_to_r.pm4py.objects.petri.petrinet.PetriNet <- function(x) {
101+
102+
places <- unlist(iterate(x$places, function(p) ensure_str(p$name)))
103+
transitions <- unlist(iterate(x$transitions, function(t) ensure_str(t$name)))
104+
105+
arcs_from <- unlist(iterate(x$arcs, function(a) ensure_str(a$source$name)))
106+
arcs_to <- unlist(iterate(x$arcs,function(a) ensure_str(a$target$name)))
107+
108+
flows <- data.frame(from = arcs_from, to = arcs_to,
109+
stringsAsFactors = F)
110+
111+
pn <- petrinetR::create_PN(places, transitions, flows,
112+
c()) # pm4py Petri net does not know about marking
113+
114+
# Make sure that labels are strings since PM4PY sometimes uses tuples or other objects
115+
# Also, replace NULL by NA to avoid issues with R removing elements
116+
pn$transitions$label <- iterate(x$transitions, function(t) ensure_str(t$label))
117+
118+
pn
119+
}
120+
121+
#' @export
122+
#' @importFrom reticulate iterate
123+
#' @importFrom reticulate py_to_r
124+
py_to_r.pm4py.objects.petri.petrinet.Marking <- function(x) {
125+
iterate(x$elements(), function(p) ensure_str(p$name))
126+
}

‎R/discovery.R

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#' Petri net discovery algorithms
2+
#'
3+
#' PM4PY discovery algorithms that discover a Petri net and its initial and final marking. Currently the Inductive Miner and the Alpha Miner are implemented.
4+
#'
5+
#' @param eventlog A bupaR event log.
6+
#' @param parameters A named list of PM4PY parameters, by default the `activity_key` from the bupaR event log is used. Use \link{param_activity_key} to specifiy a different key.
7+
#' @param variant The variant of the discovery algorithm to be used. For Inductive Miner currently only `variant_inductive_only_dfg` is supported.
8+
#' @param convert TRUE to automatically convert Python objects to their R equivalent. If you pass FALSE you can do manual conversion using the \link[reticulate]{r-py-conversion} function.
9+
#'
10+
#' @return A named list with elements `petrinet`, `initial_marking`, and `final_marking` or the original Python object.
11+
#'
12+
#' @examples
13+
#' \dontrun{
14+
#' data(patients)
15+
#' net <- discovery_inductive(patients)
16+
#'
17+
#' # Show details of the obtained bupaR Petri net
18+
#' print(net$petrinet)
19+
#'
20+
#' # initial marking is a character vector
21+
#' print(net$initial_marking)
22+
#'
23+
#' # final marking is a character vector
24+
#' print(net$final_marking)
25+
#'
26+
#' # Petri net can be used with other bupaR functions
27+
#' petrinetR::render_PN(net$petrinet)
28+
#'
29+
#' # Keep an unconverted PM4PY Petri net for use in other PM4PY functions
30+
#' py_net <- discovery_inductive(patients, convert = FALSE)
31+
#' }
32+
#'
33+
#' @name discovery
34+
NULL
35+
36+
#' @rdname discovery
37+
#' @import reticulate
38+
#' @export
39+
discovery_inductive <- function(eventlog,
40+
parameters = param_activity_key(bupaR::activity_id(eventlog)),
41+
variant = variant_inductive_only_dfg(),
42+
convert = TRUE) {
43+
pm4py_inductive <- import("pm4py.algo.discovery.inductive.factory", convert = convert)
44+
model <- pm4py_inductive$apply(as_py_value(eventlog),
45+
parameters = parameters,
46+
variant = variant)
47+
prepare_pn_with_markings(model, convert)
48+
}
49+
50+
#' @rdname discovery
51+
#' @export
52+
variant_inductive_only_dfg <- function() {
53+
pm4py$algo$discovery$inductive$factory$INDUCTIVE_ONLY_DFG
54+
}
55+
56+
#' @rdname discovery
57+
#' @import reticulate
58+
#' @export
59+
discovery_alpha <- function(eventlog,
60+
parameters = param_activity_key(bupaR::activity_id(eventlog)),
61+
variant = variant_alpha_classic(),
62+
convert = TRUE) {
63+
pm4py_alpha <- import("pm4py.algo.discovery.alpha.factory", convert = convert)
64+
model <- pm4py_alpha$apply(as_py_value(eventlog),
65+
parameters = parameters,
66+
version = variant)
67+
prepare_pn_with_markings(model, convert)
68+
}
69+
70+
#' @rdname discovery
71+
#' @export
72+
variant_alpha_classic <- function() {
73+
pm4py$algo$discovery$alpha$factory$ALPHA_VERSION_CLASSIC
74+
}

‎R/install.R

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#' Install pm4py library
2+
#'
3+
#' Installs the pm4py into a virtualenv or conda env.
4+
#'
5+
#' @param method Installation method. By default, "auto" automatically finds a method that will work in the local environment. Change the default to force a specific installation method. Note that the "virtualenv" method is not available on Windows.
6+
#' @param conda Path to conda executable (or "auto" to find conda using the PATH and other conventional install locations).
7+
#' @param ... Additional arguments passed to py_install().
8+
#'
9+
#' @export
10+
#'
11+
#' @examples
12+
#' \dontrun{
13+
#' install_pm4py()
14+
#' }
15+
#'
16+
install_pm4py <- function(method = "auto", conda = "auto", ...) {
17+
reticulate::py_install("pm4py", method = method, conda = conda, pip = TRUE, ...)
18+
}

‎R/package.R

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#' @import reticulate
2+
NULL
3+
4+
.onLoad <- function(libname, pkgname) {
5+
# use superassignment to update global reference to pm4py
6+
pm4py <<- import("pm4py", delay_load = TRUE)
7+
}
8+
9+
#' Returns pm4py version used
10+
#'
11+
#' @return package_version S3 class
12+
#' @export
13+
#'
14+
#' @examples
15+
#' \dontrun{
16+
#' # Prints PM4PY version used
17+
#' version()
18+
#' }
19+
version <- function() {
20+
ver <- pm4py$`__version__`
21+
ver <- regmatches(ver, regexec("^([0-9\\.]+).*$", ver))[[1]][[2]]
22+
package_version(ver)
23+
}

‎R/parameters.R

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#' PM4PY parameter keys
2+
#'
3+
#' Convenience methods to use PM4PY parameter keys.
4+
#'
5+
#' @param value The value to add to the list.
6+
#'
7+
#' @return a list with the parameter key/value pair
8+
#'
9+
#' @name parameters
10+
NULL
11+
12+
#' @rdname parameters
13+
#' @export
14+
param_activity_key <- function(value) {
15+
l <- list(value)
16+
names(l) <- pm4py_parameters$activity_key
17+
l
18+
}
19+
20+
#' @rdname parameters
21+
#' @export
22+
param_attribute_key <- function(value) {
23+
l <- list(value)
24+
names(l) <- pm4py_parameters$attribute_key
25+
l
26+
}
27+
28+
#' @rdname parameters
29+
#' @export
30+
param_timestamp_key <- function(value) {
31+
l <- list(value)
32+
names(l) <- pm4py_parameters$timestamp_key
33+
l
34+
}
35+
36+
#' @rdname parameters
37+
#' @export
38+
param_caseid_key <- function(value) {
39+
l <- list(value)
40+
names(l) <- pm4py_parameters$caseid_key
41+
l
42+
}
43+
44+
#' @rdname parameters
45+
#' @export
46+
param_resource_key <- function(value) {
47+
l <- list(value)
48+
names(l) <- pm4py_parameters$resource_key
49+
l
50+
}
51+
52+
pm4py_parameters <- list(
53+
activity_key = "pm4py:param:activity_key",
54+
attribute_key = "pm4py:param:attribute_key",
55+
timestamp_key = "pm4py:param:timestamp_key",
56+
caseid_key = "case_id_glue",
57+
resource_key = "pm4py:param:resource_key"
58+
)

‎R/petrinet.R

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#' Constructs the synchronous product net of two given Petri nets.
2+
#'
3+
#' @param pn1 First Petri net
4+
#' @param im1 Initial marking of the first Petri net
5+
#' @param fm1 Final marking of the first Petri net
6+
#' @param pn2 Second Petri net
7+
#' @param im2 Initial marking of the second Petri net
8+
#' @param fm2 Final marking of the second Petri net
9+
#' @param skip Symbol to be used as skip
10+
#' @param convert `TRUE` to automatically convert Python objects to their R equivalent. If you pass `FALSE` you can do manual conversion using the \link[reticulate]{r-py-conversion} function.
11+
#'
12+
#' @import reticulate
13+
#' @export
14+
petrinet_synchronous_product <- function(pn1,
15+
im1,
16+
fm1,
17+
pn2,
18+
im2,
19+
fm2,
20+
skip = ">>",
21+
convert = TRUE) {
22+
23+
pm4py_sync <- import("pm4py.objects.petri.synchronous_product", convert = convert)
24+
25+
pn1 <- as_py_value(pn1)
26+
pn2 <- as_py_value(pn2)
27+
28+
sync_net <- pm4py_sync$construct(pn1,
29+
as_pm4py_marking(im1, pn1),
30+
as_pm4py_marking(fm1, pn1),
31+
pn2,
32+
as_pm4py_marking(im2, pn2),
33+
as_pm4py_marking(fm2, pn2),
34+
skip)
35+
36+
prepare_pn_with_markings(sync_net, convert)
37+
}

‎R/pm4py.R

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#' PM4PY for R
2+
#'
3+
#' This package provides acces to the Python Process Mining library PM4PY in R
4+
#' and provides conversion between bupaR and PM4PY data structures.
5+
#'
6+
#' The object `pm4py` provides the interface to the main PM4PY module .
7+
#' Use `$` to access sub modules of PM4PY as described in the `reticulate`
8+
#' documentation:
9+
#' \code{vignette("calling_python", package = "reticulate")}
10+
#'
11+
#' @examples
12+
#' \dontrun{
13+
#' # Print the PM4PY version loaded
14+
#' pm4py$`__version__`
15+
#' }
16+
#'
17+
#' @export
18+
pm4py <- NULL

‎R/utils.R

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
2+
prepare_pn_with_markings <- function(model, convert = FALSE) {
3+
if (convert) {
4+
if (inherits(model, "python.builtin.object")) {
5+
model <- py_to_r(model) # Python tuple was not auto-converted
6+
}
7+
model <- lapply(model, py_to_r)
8+
names(model) <- c("petrinet","initial_marking", "final_marking")
9+
model$petrinet$marking <- model$initial_marking
10+
}
11+
model
12+
}
13+
14+
ensure_str <- function(x) {
15+
# Taking the Python string representation, but bupaR does not like ' in names
16+
# TODO fix in bupaR
17+
if (is.null(x)) {
18+
NA_character_
19+
} else {
20+
stringr::str_remove_all(py_str(as_py_value(x)), stringr::fixed("'"))
21+
}
22+
}
23+
24+
as_pm4py_marking <- function(x, petrinet) {
25+
26+
if (inherits(x, "pm4py.objects.petri.petrinet.Marking")) {
27+
return(x)
28+
}
29+
30+
pm4py_petrinet <- import("pm4py.objects.petri.petrinet", convert = FALSE)
31+
marking <- pm4py_petrinet$Marking()
32+
33+
found <- rep(FALSE, length(x))
34+
py <- import_builtins()
35+
iter <- py$iter(petrinet$places)
36+
37+
while (TRUE) {
38+
item <- iter_next(iter)
39+
if (is.null(item))
40+
break
41+
42+
loc <- which(x == item$name)
43+
if (any(loc)) {
44+
found[loc] <- TRUE
45+
marking[item] = length(loc)
46+
}
47+
}
48+
49+
if (all(found)) {
50+
return(marking)
51+
} else {
52+
stop(paste0("Places ",
53+
paste0(x[!found], collapse = ","),
54+
" not found in ",
55+
py_str(petrinet$places)))
56+
}
57+
}
58+
59+
as_r_value <- function(x) {
60+
61+
if (inherits(x, "python.builtin.object"))
62+
py_to_r(x)
63+
else
64+
x
65+
}
66+
67+
as_py_value <- function(x) {
68+
69+
if (inherits(x, "python.builtin.object"))
70+
x
71+
else
72+
r_to_py(x)
73+
}
74+
75+
skip_if_no_pm4py <- function() {
76+
have_pm4py <- py_module_available("pm4py")
77+
if (!have_pm4py)
78+
testthat::skip("pm4py not available for testing")
79+
}

‎README.md

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# pm4py
2+
3+
The goal of pm4py is to provide a bridge to the Python library PM4PY developed at: http://pm4py.org/
4+
5+
## Installation
6+
7+
You can install the development version of pm4py with:
8+
9+
``` r
10+
remotes::install_github("fmannhardt/pm4py")
11+
```
12+
13+
## Example
14+
15+
``` r
16+
library(pm4py)
17+
library(bupaR)
18+
19+
#
20+
# Discovery with Inductive Miner
21+
#
22+
pn <- discovery_inductive(patients)
23+
24+
# result is auto converted to petrinetR object plus markings
25+
str(pn)
26+
class(pn$petrinet)
27+
28+
# Render with bupaR
29+
render_PN(pn$petrinet)
30+
31+
#
32+
# Render with PM4PY and DiagrammeR
33+
#
34+
library(DiagrammeR)
35+
viz <- import("pm4py.visualization.petrinet")
36+
37+
# Convert back to Python
38+
py_pn <- r_to_py(pn$petrinet)
39+
class(py_pn)
40+
41+
# Render to DOT with PMP4Y
42+
dot <- viz$factory$apply(py_pn)$source
43+
grViz(diagram = dot)
44+
```
45+

‎_pkgdown.yml

Whitespace-only changes.

‎man/conformance_alignment.Rd

+44
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/discovery.Rd

+59
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/install_pm4py.Rd

+24
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/parameters.Rd

+30
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/petrinet_synchronous_product.Rd

+29
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/pm4py.Rd

+28
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/variant_state_equation_a_star.Rd

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎man/version.Rd

+20
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎pm4py.Rproj

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Version: 1.0
2+
3+
RestoreWorkspace: No
4+
SaveWorkspace: No
5+
AlwaysSaveHistory: Default
6+
7+
EnableCodeIndexing: Yes
8+
UseSpacesForTab: Yes
9+
NumSpacesForTab: 2
10+
Encoding: ISO8859-1
11+
12+
RnwWeave: Sweave
13+
LaTeX: pdfLaTeX
14+
15+
AutoAppendNewline: Yes
16+
StripTrailingWhitespace: Yes
17+
18+
BuildType: Package
19+
PackageUseDevtools: Yes
20+
PackageInstallArgs: --no-multiarch --with-keep.source
21+
PackageRoxygenize: rd,collate,namespace,vignette

‎tests/testthat.R

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
library(testthat)
2+
library(pm4py)
3+
4+
test_check("pm4py")

‎tests/testthat/test_discovery.R

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
context("Discovery")
2+
3+
library(bupaR)
4+
5+
test_that("Inductive miner", {
6+
skip_if_no_pm4py()
7+
8+
data("patients")
9+
10+
net <- expect_silent(discovery_inductive(patients, convert = FALSE))
11+
expect_true("pm4py.objects.petri.petrinet.PetriNet" %in% class(net[0]))
12+
expect_true("pm4py.objects.petri.petrinet.Marking" %in% class(net[1]))
13+
expect_true("pm4py.objects.petri.petrinet.Marking" %in% class(net[2]))
14+
15+
net <- expect_silent(discovery_inductive(patients, convert = TRUE))
16+
expect_s3_class(net$petrinet, "petrinet")
17+
expect_length(net$initial_marking, 1)
18+
expect_length(net$final_marking, 1)
19+
20+
})

0 commit comments

Comments
 (0)
Please sign in to comment.