diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..c5cc4eb9 --- /dev/null +++ b/.nojekyll @@ -0,0 +1 @@ +3637c0db \ No newline at end of file diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..8dfdf3dd --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +mlr-org.com \ No newline at end of file diff --git a/benchmark.html b/benchmark.html new file mode 100644 index 00000000..e44629cd --- /dev/null +++ b/benchmark.html @@ -0,0 +1,689 @@ + + + + + + + + + +benchmark – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + +
+ + + + + + + +
+ +
+ + + + + + \ No newline at end of file diff --git a/blogroll.html b/blogroll.html new file mode 100644 index 00000000..6d9b8b8e --- /dev/null +++ b/blogroll.html @@ -0,0 +1,731 @@ + + + + + + + + + +Blogroll – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ +
+
+
+

Blogroll

+
+
+ + +
+ + + + +
+ + +
+ + + + + + +
+ +
+ + + + + + \ No newline at end of file diff --git a/book.html b/book.html new file mode 100644 index 00000000..788e4c10 --- /dev/null +++ b/book.html @@ -0,0 +1,711 @@ + + + + + + + + + +Book – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + +
+ +
+
+
+

Book

+
+
+ + +
+ + + + +
+ + +
+ + +

The “mlr3book” is a free manual written in an online-book style available in two versions.

+

It is the main reference for the mlr3 ecosystem.

+ + + + +
+ +
+ + + + + + \ No newline at end of file diff --git a/contributing.html b/contributing.html new file mode 100644 index 00000000..4aca0e9e --- /dev/null +++ b/contributing.html @@ -0,0 +1,712 @@ + + + + + + + + + +Contributing – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + +
+ +
+
+
+

Contributing

+
+
+ + +
+ + + + +
+ + +
+ + +

You are welcome to open a Pull Request on GitHub. Before doing so, please read our PR Guidelines.

+

If you

+ +

Additional developer information lives in the mlr3 GitHub Wiki.

+ + + +
+ +
+ + + + + + \ No newline at end of file diff --git a/dependencies.html b/dependencies.html new file mode 100644 index 00000000..53b387e5 --- /dev/null +++ b/dependencies.html @@ -0,0 +1,722 @@ + + + + + + + + + +Dependencies – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + +
+ +
+
+
+

Dependencies

+
+
+ + +
+ + + + +
+ + +
+ + +

mlr3 tries to be light on dependencies. The following packages are at runtime:

+ + + + +
+ +
+ + + + + + \ No newline at end of file diff --git a/documentation-listings/book.html b/documentation-listings/book.html new file mode 100644 index 00000000..f36f7145 --- /dev/null +++ b/documentation-listings/book.html @@ -0,0 +1,736 @@ + + + + + + + + + + +Book – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ +
+
+
+

Book

+
+
+ Central entrypoint to the mlr3verse +
+
+ +
+ + +
+ + + + +
+ + +
+ + + + + +
+ +
+ + + + + + \ No newline at end of file diff --git a/documentation-listings/gallery.html b/documentation-listings/gallery.html new file mode 100644 index 00000000..9f9e41f0 --- /dev/null +++ b/documentation-listings/gallery.html @@ -0,0 +1,735 @@ + + + + + + + + + + +Gallery – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ +
+
+
+

Gallery

+
+
+ test +
+
+
+
+ + +
+ + + + +
+ + +
+ + +

foo

+ + + +
+ +
+ + + + + + \ No newline at end of file diff --git a/ecosystem.html b/ecosystem.html new file mode 100644 index 00000000..71398b5b --- /dev/null +++ b/ecosystem.html @@ -0,0 +1,1553 @@ + + + + + + + + + +Ecosystem – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + +
+ +
+
+
+

Ecosystem

+
+
+ + +
+ + + + +
+ + +
+ + +

The mlr3 ecosystem is a collection of R packages for machine learning. The base package mlr3 only provides the basic building blocks for machine learning. The extensions packages extent mlr3 with functionality for additional task types, learning algorithms, tuning algorithms, feature selection strategies, visualizations or preprocessing capabilities. The packages are listed bellow with a short description. For more information about the packages, check out their respective homepages.

+

The dot next to the package name indicates the lifecycle stage.

+ +
+
+

+
Graph of Extension Packages
+
+
+

If you use our packages in your research, please cite our articles on mlr3 (Lang et al. 2019), mlr3proba (Sonabend et al. 2021) or mlr3pipelines (Binder et al. 2021). To get the citation information of other packages, call

+
+
citation("[package]")
+
+
+

Core

+
+
+
+
+

+mlr3 + +

+ + +
+
+

+mlr3verse + +

+ + +
+
+

+mlr3pipelines + +

+ + +
+
+
+
+
+
+

Learners

+
+
+
+
+

+mlr3learners + +

+ + +
+
+

+mlr3extralearners + +

+ + +
+
+

+mlr3torch + +

+ + +
+
+
+
+
+
+

Tuning & Optimization

+
+
+
+
+

+mlr3tuning + +

+ + +
+
+

+mlr3tuningspaces + +

+ + +
+
+

+mlr3hyperband + +

+ + +
+
+

+mlr3mbo + +

+ + +
+
+

+miesmuschel + +

+ + +
+
+

+bbotk + +

+ + +
+
+

+mlr3automl + +

+ + +
+
+
+
+
+
+

Tasks and Datatypes

+
+
+
+
+

+mlr3spatiotempcv + +

+ + +
+
+

+mlr3cluster + +

+ + +
+
+

+mlr3proba + +

+ + +
+
+

+mlr3spatial + +

+ + +
+
+

+mlr3fda + +

+ + +
+
+

+mlr3fairness + +

+ + +
+
+

+mlr3temporal + +

+ + +
+
+
+
+
+
+

Feature Selection

+
+
+
+
+

+mlr3filters + +

+ + +
+
+

+mlr3fselect + +

+ + +
+
+
+
+
+
+

Data

+
+
+
+
+

+mlr3db + +

+ + +
+
+

+mlr3oml + +

+ + +
+
+

+mlr3data + +

+ + +
+
+
+
+
+
+

Analysis

+
+
+
+
+

+mlr3viz + +

+ + +
+
+

+mlr3benchmark + +

+ + +
+
+

+mlr3inferr + +

+ + +
+
+

+mlr3summary + +

+ + +
+
+
+
+
+
+

Other

+
+
+
+
+

+paradox + +

+ + +
+
+

+mlr3misc + +

+ + +
+
+

+mlr3measures + +

+ + +
+
+
+
+
+
+

Parallelization

+
+
+
+
+

+mlr3batchmark + +

+ + +
+
+

+rush + +

+ + +
+
+
+
+ + + +
+ +

References

+
+Binder, Martin, Florian Pfisterer, Michel Lang, Lennart Schneider, Lars Kotthoff, and Bernd Bischl. 2021. mlr3pipelines - Flexible Machine Learning Pipelines in R.” Journal of Machine Learning Research 22 (184): 1–7. https://jmlr.org/papers/v22/21-0281.html. +
+
+Lang, Michel, Martin Binder, Jakob Richter, Patrick Schratz, Florian Pfisterer, Stefan Coors, Quay Au, Giuseppe Casalicchio, Lars Kotthoff, and Bernd Bischl. 2019. mlr3: A Modern Object-Oriented Machine Learning Framework in R.” Journal of Open Source Software, December. https://doi.org/10.21105/joss.01903. +
+
+Sonabend, Raphael, Franz J Király, Andreas Bender, Bernd Bischl, and Michel Lang. 2021. mlr3proba: An R Package for Machine Learning in Survival Analysis.” Bioinformatics, February. https://doi.org/10.1093/bioinformatics/btab039. +
+
+ +
+ + + + + + \ No newline at end of file diff --git a/faq.html b/faq.html new file mode 100644 index 00000000..3ce62e1b --- /dev/null +++ b/faq.html @@ -0,0 +1,844 @@ + + + + + + + + + +Frequently Asked Questions – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + +
+ +
+
+
+

Frequently Asked Questions

+
+
+ + +
+ + + + +
+ + +
+ + + +
+

Why is there only the rpart learner?

+

The base package mlr3 ships only with regression and classification trees from the rpart package and some learners for debugging. A selection of popular learners can be found in the extension package mlr3learners. Survival learners are provided by mlr3proba, cluster learners via mlr3cluster. Additional learners can be found in the extension packages mlr3extralearners. If your favorite learner is missing, please open a learner request. An overview of all learners can be found on our website.

+
+
+

How can I use parallelization?

+

Parallelization is supported when training learners, resampling, tuning and predicting. We recommend reading the section about Parallelization in the mlr3book.

+
+
+

Why is the parallelization with the future package slow?

+

Starting and terminating workers as well as possible communication between workers comes at a price in the form of additionally required runtime which is called parallelization overhead. This overhead strongly varies between parallelization backends and must be carefully weighed against the runtime of the sequential execution to determine if parallelization is worth the effort. When resampling or tuning a fast-fitting learner, it helps to chunk multiple resampling iterations into a single computational job. The option mlr3.exec_chunk_bins determines the number of chunks to split the resampling iterations into. For example, when running a benchmark with 100 resampling iterations, options("mlr3.exec_chunk_bins" = 4) creates 4 computational jobs with 25 resampling iterations each. This reduces the parallelization overhead and speeds up the execution.

+
+
+

Why is the parallelization of tuning slow?

+

Tuning can also suffer from the parallelization overhead described above. Additionally, the batch size of the tuner can have a large impact on the runtime. Setting an optimal batch size is explained in the section Parallelization of Tuning of the mlr3book.

+
+
+

Why are the CPUs on my system not fully utilized when using parallelization?

+

If there are few jobs with dissimilar runtimes, the system may end up waiting for the last chunk to finish, while other resources are idle. This is referred to as synchronization overhead. When minimizing the synchronization overhead, a too large chunk size can lead to a situation where the last chunk takes much longer than the others. This can be avoided by setting mlr3.exec_chunk_bins to a smaller value than the number of cores available on the system.

+
+
+

How can I use time constraints when tuning?

+

Time constraints can be set for individual learners, tuning processes, and nested resampling. The gallery post Time constraints in the mlr3 ecosystem provides an overview of the different options.

+
+
+

Why is method X slower when used via mlr3?

+

By default, we set the number of threads of learners to 1 to avoid conflicts with parallelization. Therefore, the default configuration of a learner may be significantly slower than the default configuration of the method when used directly.

+
+
+

Preprocessing factor levels

+

When working with mlr3, it is important to avoid using special characters in the levels of factor variables. The presence of symbols such as +, -, <, >, =, or spaces in the factor levels can cause errors during model training (depends on the learner used and if the formula interface is utilized, e.g. as in the surv.parametric learner). While underscores (_) and dots (.) are generally safe to use, other special characters should be avoided. To ensure smooth operation and prevent errors, please follow these guidelines:

+
    +
  1. Use descriptive labels with no special characters: Assign meaningful and descriptive labels to factor levels that do not include special characters. For example, instead of 60+ for a factor level of an age feature, use 60_above.
  2. +
  3. Use factor encoding: Incorporate a pre-processing step in your data pipeline (e.g. see mlr_pipeops_encode to make sure factors are one-hot encoded, alleviating problems that may arise from factor levels that incorporate strange symbols.
  4. +
+
+
+

Memory Problems

+

One explanation for why mlr3 might in some cases use an unusual amount of memory, is when packages are installed with the --with-keep.source flag. This configuration option is enabled by default when managing dependencies via renv, see issue #1713. To opt out of this default run the code below, e.g. by adding it to your .Rprofile:

+
+
options("install.opts" = "--without-keep.source")
+
+
+
+

How can I suppress logging output of learners on the R console

+

Some learners are quite verbose during their train or predict step, and this clutters the R console. Note that this is different than controlling the generic mlr3 logger, which is covered under Logging. Most of these learners provide some option in their paramset to control output behavior. Another option is to simply use Encapsulation, likely in the evaluate mode, running the learner in the same R session, but with caught exceptions and redirected output.

+
+
library(mlr3)
+library(mlr3learners)
+mytask = tsk("iris")
+# manual option
+mylearner = lrn("classif.nnet", trace = TRUE)
+# generic option
+mylearner$encapsulate = c(train = "evaluate", predict = "evaluate")
+mylearner$train(mytask)
+
+
+
+

A learner trained with an old mlr3 version does not work anymore

+

It is possible that a saved Learner that was trained with an old mlr3 version does not work with a different version of mlr3. In general, we recommend saving the computational environment using a tool like renv so this can later be restored and avoiding such situations alltogether. If this is not an option, a possible workaround is to construct the same learner in the currently used mlr3 version and manually set its $state to the one of the saved learner. This is illustrated below:

+
    +
  1. Using an old mlr3 version:

    +
    +
    learner = lrn("classif.rpart")
    +learner$train(tsk("iris"))
    +saveRDS(learner, "learner.rds")
    +
  2. +
  3. With a subsequent mlr3 version:

    +
    +
    learner = lrn("classif.rpart")
    +learner_old = readRDS("learner.rds")
    +learner$state = learner_old$state
    +
  4. +
+

Note that this is risky and not guaranteed to work because of various reasons: * You might have now loaded a different version of the learner library (in this case the rpart pacakge). * The internals (such as the structure of the internal $state) might have changed between the versions.

+

Therefore, be careful when attempting this solution and double-check that the learner behaves sensibly.

+
+
+

Caching of knitr/rmarkdown chunks does not work with mlr3

+

{knitr} per default uses R’s lazy-load database to store the results of individual chunks. The lazy-load database is an internal feature of R, and has issues handling active bindings (https://github.com/r-lib/R6/issues/152). Fortunately, it is possible to disable lazy-loading by setting the chunk option cache.lazy to FALSE:

+
+
knitr::opts_chunk$set(cache = TRUE, cache.lazy = FALSE)
+
+
+
+

How to keep all mlr3 packages up-to-date?

+

Either run R’s update.packages() to update all installed packages, or run

+
devtools::update_packages("mlr3verse", dependencies = TRUE)
+

to update only packages from the mlr3verse. Note that this also updates recursive dependencies not listed as a direct import.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/filters.html b/filters.html new file mode 100644 index 00000000..5d556c72 --- /dev/null +++ b/filters.html @@ -0,0 +1,811 @@ + + + + + + + + + +filters – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + +
+ + + + +
+

Feature Selection Filter

+

Feature Filters quantify the importance of each feature of a Task by assigning them a numerical score. In a second step, features can be selected by either selecting a fixed absolute or relative frequency of the best features, or by thresholding on the score value.

+

The Filter PipeOp allows to use filters as a preprocessing step.

+
+
+
+ +
+
+
+

Example Usage

+

Use the \(-\log_{10}()\)-transformed \(p\)-values of a Kruskal-Wallis rank sum test (implemented in kruskal.test()) for filtering features of the Pima Indian Diabetes tasks.

+
+
library("mlr3verse")
+
+
Loading required package: mlr3
+
+
# retrieve a task
+task = tsk("pima")
+
+# retrieve a filter
+filter = flt("kruskal_test")
+
+# calculate scores
+filter$calculate(task)
+
+# access scores
+filter$scores
+
+
  glucose       age      mass   insulin   triceps  pregnant  pedigree  pressure 
+39.885381 16.942901 16.740864 13.127828  9.158113  7.426955  5.922431  5.788607 
+
+
# plot scores
+autoplot(filter)
+
+
+
+

+
+
+
+
# subset task to 3 most important features
+task$select(head(names(filter$scores), 3))
+task$feature_names
+
+
[1] "age"     "glucose" "mass"   
+
+
+ + +
+
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/filters_files/figure-html/unnamed-chunk-4-1.png b/filters_files/figure-html/unnamed-chunk-4-1.png new file mode 100644 index 00000000..cf434489 Binary files /dev/null and b/filters_files/figure-html/unnamed-chunk-4-1.png differ diff --git a/fselectors.html b/fselectors.html new file mode 100644 index 00000000..b74f9a04 --- /dev/null +++ b/fselectors.html @@ -0,0 +1,789 @@ + + + + + + + + + +fselectors – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + +
+ + + + +
+

Feature Selection Wrapper

+

Feature selection wrappers can be found in the mlr3fselect packages. The goal is to find the best subset of features with respect to a performance measure in an iterative fashion.

+
+
+
+ +
+
+
+

Example Usage

+

Run a sequential feature selection on the Pima Indian Diabetes data set.

+
+
library(mlr3verse)
+
+# retrieve task
+task = tsk("pima")
+
+# load learner
+learner = lrn("classif.rpart")
+
+# feature selection on the pima indians diabetes data set
+instance = fselect(
+  fselector = fs("sequential"),
+  task = task,
+  learner = learner,
+  resampling = rsmp("holdout"),
+  measure = msr("classif.ce")
+)
+
+# best performing feature subset
+instance$result
+
+
      age glucose insulin   mass pedigree pregnant pressure triceps
+   <lgcl>  <lgcl>  <lgcl> <lgcl>   <lgcl>   <lgcl>   <lgcl>  <lgcl>
+1:  FALSE    TRUE   FALSE  FALSE    FALSE     TRUE     TRUE    TRUE
+                            features n_features classif.ce
+                              <list>      <int>      <num>
+1: glucose,pregnant,pressure,triceps          4  0.2304688
+
+
# subset the task and fit the final model
+task$select(instance$result_feature_set)
+learner$train(task)
+
+print(learner)
+
+
<LearnerClassifRpart:classif.rpart>: Classification Tree
+* Model: rpart
+* Parameters: xval=0
+* Packages: mlr3, rpart
+* Predict Types:  [response], prob
+* Feature Types: logical, integer, numeric, factor, ordered
+* Properties: importance, missings, multiclass, selected_features,
+  twoclass, weights
+
+
+ + +
+
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery-all-basic.html b/gallery-all-basic.html new file mode 100644 index 00000000..069352df --- /dev/null +++ b/gallery-all-basic.html @@ -0,0 +1,859 @@ + + + + + + + + + +gallery-all-basic – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + +
+ + + + +
+

Train and Evaluate Models

+ + + + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery-all-optimization.html b/gallery-all-optimization.html new file mode 100644 index 00000000..8a952796 --- /dev/null +++ b/gallery-all-optimization.html @@ -0,0 +1,873 @@ + + + + + + + + + +gallery-all-optimization – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + +
+ + + + +
+

Optimize Models

+ + + + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery-all-pipelines.html b/gallery-all-pipelines.html new file mode 100644 index 00000000..ea76a05f --- /dev/null +++ b/gallery-all-pipelines.html @@ -0,0 +1,824 @@ + + + + + + + + + +gallery-all-pipelines – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + +
+ + + + +
+

Build Pipelines

+ + + + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery-all-technical.html b/gallery-all-technical.html new file mode 100644 index 00000000..cb1150b3 --- /dev/null +++ b/gallery-all-technical.html @@ -0,0 +1,803 @@ + + + + + + + + + +gallery-all-technical – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + +
+ + + + +
+

Customize and Apply Technical Tools

+ + + + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery-all.html b/gallery-all.html new file mode 100644 index 00000000..4928cfa6 --- /dev/null +++ b/gallery-all.html @@ -0,0 +1,1080 @@ + + + + + + + + + +gallery-all – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + +
+ + + + +
+

All Posts

+ + + + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery-all.xml b/gallery-all.xml new file mode 100644 index 00000000..f5c12a88 --- /dev/null +++ b/gallery-all.xml @@ -0,0 +1,16269 @@ + + + +mlr-org +https://mlr-org.com/gallery-all.html + +Website of the mlr organization +quarto-1.6.4 +Thu, 21 Dec 2023 00:00:00 GMT + + Time constraints in the mlr3 ecosystem + Marc Becker + https://mlr-org.com/gallery/technical/2023-12-21-time-constraints/ + +

Scope

+

Setting time limits is an important consideration when tuning unreliable or unstable learning algorithms and when working on shared computing resources. The mlr3 ecosystem provides several mechanisms for setting time constraints for individual learners, tuning processes, and nested resampling.

+ +
+

Learner

+

This section demonstrates how to impose time constraints using a support vector machine (SVM) as an illustrative example.

+
+
library(mlr3verse)
+
+learner = lrn("classif.svm")
+
+

Applying timeouts to the $train() and $predict() functions is essential for managing learners that may operate indefinitely. These time constraints are set independently for both the training and prediction stages. Generally, training a learner consumes more time than prediction. Certain learners, like k-nearest neighbors, lack a distinct training phase and require a timeout only during prediction. For the SVM’s training, we set a 10-second limit.

+
+
learner$timeout = c(train = 10, predict = Inf)
+
+

To effectively terminate the process if necessary, it’s important to run the training and prediction within a separate R process. The callr package is recommended for this encapsulation, as it tends to be more reliable than the evaluate package, especially for terminating externally compiled code.

+
+
learner$encapsulate = c(train = "callr", predict = "callr")
+
+

Note that using callr increases the runtime due to the overhead of starting an R process. Additionally, it’s advisable to specify a fallback learner, such as "classif.featureless", to provide baseline predictions in case the primary learner is terminated.

+
+
learner$fallback = lrn("classif.featureless")
+
+

These time constraints are now integrated into the training, resampling, and benchmarking processes. For more information on encapsulation and fallback learners, see the mlr3book. The next section will focus on setting time limits for the entire tuning process.

+
+
+

Tuning

+

When working with high-performance computing clusters, jobs are often bound by strict time constraints. Exceeding these limits results in the job being terminated and the loss of any results generated. Therefore, it’s important to ensure that the tuning process is designed to adhere to these time constraints.

+

The trm("runtime") controls the duration of the tuning process. We must take into account that the terminator can only check if the time limit is reached between batches. We must therefore set the time lower than the runtime of the job. How much lower depends on the runtime or time limit of the individual learners. The last batch should be able to finish before the time limit of the cluster is reached.

+
+
terminator = trm("run_time", secs = 60)
+
+instance = ti(
+  task = tsk("sonar"),
+  learner = learner,
+  resampling = rsmp("cv", folds = 3),
+  measures = msr("classif.ce"),
+  terminator = terminator
+)
+
+

With these settings, our tuning operation is configured to run for 60 seconds, while individual learners are set to terminate after 10 seconds. This approach ensures the tuning process is efficient and adheres to the constraints imposed by the high-performance computing cluster.

+
+
+

Nested Resampling

+

When using nested resampling, time constraints become more complex as they are applied across various levels. As before, the time limit for an individual learner during the tuning is set with $timeout. The time limit for the tuning processes in the auto tuners is controlled with the trm("runtime"). It’s important to note that once the auto tuner enters the final phase of fitting the model and making predictions on the outer test set, the time limit governed by the terminator no longer applies. Additionally, the time limit previously set on the learner is temporarily deactivated, allowing the auto tuner to complete its task uninterrupted. However, a separate time limit can be assigned to each auto tuner using $timeout. This limit encompasses not only the tuning phase but also the time required for fitting the final model and predictions on the outer test set.

+

The best way to show this is with an example. We set the time limit for an individual learner to 10 seconds.

+
+
learner$timeout = c(train = 10, predict = Inf)
+learner$encapsulate = c(train = "callr", predict = "callr")
+learner$fallback = lrn("classif.featureless")
+
+

Next, we give each auto tuner 60 seconds to finish the tuning process.

+
+
terminator = trm("run_time", secs = 60)
+
+

Furthermore, we impose a 120-second limit for resampling each auto tuner. This effectively divides the time allocation, with around 60 seconds for tuning and another 60 seconds for final model fitting and predictions on the outer test set.

+
+
at = auto_tuner(
+  tuner = tnr("random_search"),
+  learner = learner,
+  resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce"),
+  terminator = trm("run_time", secs = 60)
+)
+
+at$timeout = c(train = 100, predict = 20)
+at$encapsulate = c(train = "callr", predict = "callr")
+at$fallback = lrn("classif.featureless")
+
+

In total, the entire nested resampling process is designed to be completed within 10 minutes (120 seconds multiplied by 5 folds).

+
+
rr = resample(task, at, rsmp("cv", folds = 5))
+
+
+
+

Conclusion

+

We delved into the setting of time constraints across different levels in the mlr3 ecosystem. From individual learners to the complexities of nested resampling, we’ve seen how effectively managing time limits can significantly enhance the efficiency and reliability of machine learning workflows. By utilizing the trm("runtime") for tuning processes and setting $timeout for individual learners and auto tuners, we can ensure that our machine learning tasks are not only effective but also adhere to the practical time constraints of shared computational resources. For more information, see also the error handling section in the mlr3book.

+ + +
+ + ]]>
+ https://mlr-org.com/gallery/technical/2023-12-21-time-constraints/ + Thu, 21 Dec 2023 00:00:00 GMT + +
+ + Analyzing the Runtime Performance of tidymodels and mlr3 + Marc Becker + https://mlr-org.com/gallery/technical/2023-10-30-tidymodels/ + +

Scope

+

In the realm of data science, machine learning frameworks play an important role in streamlining and accelerating the development of analytical workflows. Among these, tidymodels and mlr3 stand out as prominent tools within the R community. They provide a unified interface for data preprocessing, model training, resampling and tuning. The streamlined and accelerated development process, while efficient, typically results in a trade-off concerning runtime performance. This article undertakes a detailed comparison of the runtime efficiency of tidymodels and mlr3, focusing on their performance in training, resampling, and tuning machine learning models. Specifically, we assess the time efficiency of these frameworks in running the rpart::rpart() and ranger::ranger() models, using the Sonar dataset as a test case. Additionally, the study delves into analyzing the runtime overhead of these frameworks by comparing their performance against training the models without a framework. Through this comparative analysis, the article aims to provide valuable insights into the operational trade-offs of using these advanced machine learning frameworks in practical data science applications.

+ +
+

Setup

+

We employ the microbenchmark package to measure the time required for training, resampling, and tuning models. This benchmarking process is applied to the Sonar dataset using the rpart and ranger algorithms.

+
+
library("mlr3verse")
+library("tidymodels")
+library("microbenchmark")
+
+task = tsk("sonar")
+data = task$data()
+formula = Class ~ .
+
+

To ensure the robustness of our results, each function call within the benchmark is executed 100 times in a randomized sequence. The microbenchmark package then provides us with detailed insights, including the median, lower quartile, and upper quartile of the runtimes. To further enhance the reliability of our findings, we execute the benchmark on a cluster. Each run of microbenchmark is repeated 100 times, with different seeds applied for each iteration. Resulting in a total of 10,000 function calls of each command. The computing environment for each worker in the cluster consists of 3 cores and 12 GB of RAM. For transparency and reproducibility, the examples of the code used for this experiment are provided as snippets in the article. The complete code, along with all details of the experiment, is available in our public repository, mlr-org/mlr-benchmark.

+

It’s important to note that our cluster setup is not specifically optimized for single-core performance. Consequently, executing the same benchmark on a local machine with might yield faster results.

+
+
+

Benchmark

+
+

Train the Models

+

Our benchmark starts with the fundamental task of model training. To facilitate a direct comparison, we have structured our presentation into two distinct segments. On the left, we demonstrate the initialization of the rpart model, employing both mlr3 and tidymodels frameworks. The rpart model is a decision tree classifier, which is a simple and fast-fitting algorithm for classification tasks. Simultaneously, on the right, we turn our attention to the initialization of the ranger model, known for its efficient implementation of the random forest algorithm. Our aim is to mirror the configuration as closely as possible across both frameworks, maintaining consistency in parameters and settings.

+
# tidymodels
+tm_mod = decision_tree() %>%
+  set_engine("rpart",
+    xval = 0L) %>%
+  set_mode("classification")
+
+# mlr3
+learner = lrn("classif.rpart",
+  xval = 0L)
+# tidymodels
+tm_mod = rand_forest(trees = 1000L) %>%
+  set_engine("ranger",
+    num.threads = 1L,
+    seed = 1) %>%
+  set_mode("classification")
+
+# mlr3
+learner = lrn("classif.ranger",
+  num.trees = 1000L,
+  num.threads = 1L,
+  seed = 1,
+  verbose = FALSE,
+  predict_type = "prob")
+
+
+ +
+
+

We measure the runtime for the train functions within each framework. The result of the train function is a trained model in both frameworks. In addition, we invoke the rpart() and ranger() functions to establish a baseline for the minimum achievable runtime. This allows us to not only assess the efficiency of the train functions in each framework but also to understand how they perform relative to the base packages.

+
+
# tidymodels train
+fit(tm_mod, formula, data = data)
+
+# mlr3 train
+learner$train(task)
+
+

When training an rpart model, tidymodels demonstrates superior speed, outperforming mlr3 (Table 1). Notably, the mlr3 package requires approximately twice the time compared to the baseline.

+

A key observation from our results is the significant relative overhead when using a framework for rpart model training. Given that rpart inherently requires a shorter training time, the additional processing time introduced by the frameworks becomes more pronounced. This aspect highlights the trade-off between the convenience offered by these frameworks and their impact on runtime for quicker tasks.

+

Conversely, when we shift our focus to training a ranger model, the scenario changes (Table 2). Here, the runtime performance of ranger is strikingly similar across both tidymodels and mlr3. This equality in execution time can be attributed to the inherently longer training duration required by ranger models. As a result, the relative overhead introduced by either framework becomes minimal, effectively diminishing in the face of the more time-intensive training process. This pattern suggests that for more complex or time-consuming tasks, the choice of framework may have a less significant impact on overall runtime performance.

+
+ +
+
+
+
+
+
+
+Table 1: Average runtime in milliseconds of training rpart depending on the framework. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FrameworkLQMedianUQ
base111112
mlr3232324
tidymodels181819
+
+
+
+
+
+
+
+
+
+Table 2: Average runtime in milliseconds of training ranger depending on the framework. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FrameworkLQMedianUQ
base286322347
mlr3301335357
tidymodels310342362
+
+
+
+
+
+
+
+
+
+

Resample Sequential

+

We proceed to evaluate the runtime performance of the resampling functions within both frameworks, specifically under conditions without parallelization. This step involves the generation of resampling splits, including 3-fold, 6-fold, and 9-fold cross-validation. Additionally, we run a 100 times repeated 3-fold cross-validation.

+

We generate the same resampling splits for both frameworks. This consistency is key to ensuring that any observed differences in runtime are attributable to the frameworks themselves, rather than variations in the resampling process.

+

In our pursuit of a fair and balanced comparison, we address certain inherent differences between the two frameworks. Notably, tidymodels inherently includes scoring of the resampling results as part of its process. To align the comparison, we replicate this scoring step in mlr3, thus maintaining a level field for evaluation. Furthermore, mlr3 inherently saves predictions during the resampling process. To match this, we activate the saving of the predictions in tidymodels.

+
+
# tidymodels resample
+control = control_grid(save_pred = TRUE)
+metrics = metric_set(accuracy)
+
+tm_wf =
+  workflow() %>%
+  add_model(tm_mod) %>%
+  add_formula(formula)
+
+fit_resamples(tm_wf, folds, metrics = metrics, control = control)
+
+# mlr3 resample
+measure = msr("classif.acc")
+
+rr = resample(task, learner, resampling)
+rr$score(measure)
+
+

When resampling the fast-fitting rpart model, mlr3 demonstrates a notable edge in speed, as detailed in Table 3. In contrast, when it comes to resampling the more computationally intensive ranger models, the performance of tidymodels and mlr3 converges closely (Table 4). This parity in performance is particularly noteworthy, considering the differing internal mechanisms and optimizations of tidymodels and mlr3. A consistent trend observed across both frameworks is a linear increase in runtime proportional to the number of folds in cross-validation (Figure 1).

+
+ +
+
+
+
+
+
+
+Table 3: Average runtime in milliseconds of rpart depending on the framework and resampling strategy. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FrameworkResamplingLQMedianUQ
mlr3cv3188196210
tidymodelscv3233242257
mlr3cv6343357379
tidymodelscv6401415436
mlr3cv9500520548
tidymodelscv9568588616
mlr3rcv100155261602316777
tidymodelsrcv100164091687617527
+
+
+
+
+
+
+
+
+
+Table 4: Average runtime in milliseconds of ranger depending on the framework and resampling strategy. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FrameworkResamplingLQMedianUQ
mlr3cv392310041062
tidymodelscv39169811023
mlr3cv6199021592272
tidymodelscv6208921762239
mlr3cv9307432793441
tidymodelscv9326033733453
mlr3rcv100859098864291381
tidymodelsrcv100878288882289843
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+Figure 1: Average runtime, measured in milliseconds, for cross-validations using rpart (displayed on the left) and ranger (on the right). The comparison encompasses variations across different frameworks and the number of folds in the cross-validation. +
+
+
+
+
+
+
+

Resample Parallel

+

We conducted a second set of resampling function tests, this time incorporating parallelization to explore its impact on runtime efficiency. In this phase, we utilized doFuture and doParallel as the primary parallelization packages for tidymodels, recognizing their robust support and compatibility. Meanwhile, for mlr3, the future package was employed to facilitate parallel processing.

+

Our findings, as presented in the respective tables (Table 5 and Table 6), reveal interesting dynamics about parallelization within the frameworks. When the number of folds in the resampling process is doubled, we observe only a marginal increase in the average runtime. This pattern suggests a significant overhead associated with initializing the parallel workers, a factor that becomes particularly influential in the overall efficiency of the parallelization process.

+

In the case of the rpart model, the parallelization overhead appears to outweigh the potential speedup benefits, as illustrated in the left section of Figure 2. This result indicates that for less complex models like rpart, where individual training times are relatively short, the initialization cost of parallel workers may not be sufficiently offset by the reduced processing time per fold.

+

Conversely, for the ranger model, the utilization of parallelization demonstrates a clear advantage over the sequential version, as evidenced in the right section of Figure 2. This finding underscores that for more computationally intensive models like ranger, which have longer individual training times, the benefits of parallel processing significantly overcome the initial overhead of worker setup. This differentiation highlights the importance of considering the complexity and inherent processing time of models when deciding to implement parallelization strategies in these frameworks.

+
+ +
+
+
+
+
+
+
+Table 5: Average runtime in milliseconds of mlr3 with future and rpart depending on the resampling strategy. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ResamplingLQMedianUQ
cv3625655703
cv6738771817
cv9831875923
rcv100862090439532
+
+
+
+
+
+
+
+
+
+Table 6: Average runtime in milliseconds of mlr3 with future and ranger depending on the resampling strategy. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ResamplingLQMedianUQ
cv3836884943
cv6120012491314
cv9157716341706
rcv100320473248333022
+
+
+
+
+
+
+
+

When paired with doFuture, tidymodels exhibits significantly slower runtime compared to the mlr3 package utilizing future (Table 7 and Table 8). We observed that tidymodels exports more data to the parallel workers, which notably exceeds that of mlr3. This substantial difference in data export could plausibly account for the observed slower runtime when using tidymodels on small tasks.

+
+ +
+
+
+
+
+
+
+Table 7: Average runtime in milliseconds of tidymodels with doFuture and rpart depending on the resampling strategy. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ResamplingLQMedianUQ
cv3277828173019
cv6280828563033
cv9293529753170
rcv100915493029489
+
+
+
+
+
+
+
+
+
+Table 8: Average runtime in milliseconds of tidymodels with doFuture and ranger depending on the resampling strategy. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ResamplingLQMedianUQ
cv3298230463234
cv6328233663543
cv9356836953869
rcv100275462784328166
+
+
+
+
+
+
+
+

The utilization of the doParallel package demonstrates a notable improvement in handling smaller resampling tasks. In these scenarios, the resampling process consistently outperforms the mlr3 framework in terms of speed. However, it’s important to note that even with this enhanced performance, the doParallel package does not always surpass the efficiency of the sequential version, especially when working with the rpart model. This specific observation is illustrated in the left section of Figure 2.

+
+ +
+
+
+
+
+
+
+Table 9: Average runtime in milliseconds of tidymodels with doParallel and rpart depending on the resampling strategy. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ResamplingLQMedianUQ
cv3557649863
cv6602714910
cv9661772968
rcv100106091082011071
+
+
+
+
+
+
+
+
+
+Table 10: Average runtime in milliseconds of tidymodels with doParallel and ranger depending on the resampling strategy. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ResamplingLQMedianUQ
cv3684756948
cv6100710991272
cv9136014611625
rcv100312053148631793
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+Figure 2: Average runtime, measured in milliseconds, for cross-validations using rpart (displayed on the left) and ranger (on the right). The comparison encompasses variations across different frameworks, the number of folds in the cross-validation, and the implementation of parallelization. +
+
+
+
+
+

In the context of repeated cross-validation, our findings underscore the efficacy of parallelization (Figure 3). Across all frameworks tested, the adoption of parallel processing techniques yields a significant increase in speed. This enhancement is particularly noticeable in larger resampling tasks, where the demands on computational resources are more substantial.

+

Interestingly, within these more extensive resampling scenarios, the doFuture package emerges as a more efficient option compared to doParallel. This distinction is important, as it highlights the relative strengths of different parallelization packages under varying workload conditions. While doParallel shows proficiency in smaller tasks, doFuture demonstrates its capability to handle larger, more complex resampling processes with greater speed and efficiency.

+
+
+
+
+
+ +
+
+Figure 3: Average runtime, measured in seconds, of a 100 times repeated 3-fold cross-validation using rpart (displayed on the left) and ranger (on the right). The comparison encompasses variations across different frameworks and the implementation of parallelization. +
+
+
+
+
+
+
+

Tune Sequential

+

We then shift our focus to assessing the runtime performance of the tuning functions. In this phase, the tidymodels package is utilized to evaluate a predefined grid, comprising a specific set of hyperparameter configurations. To ensure a balanced and comparable analysis, we employ the "design_points" tuner from the mlr3tuning package. This approach allows us to evaluate the same grid within the mlr3 framework, maintaining consistency across both platforms. The grid used for this comparison contains 200 hyperparameter configurations each, for both the rpart and ranger models. This approach helps us to understand how each framework handles the optimization of model hyperparameters, a key aspect of building effective and efficient machine learning models.

+
# tidymodels
+tm_mod = decision_tree(
+  cost_complexity = tune()) %>%
+  set_engine("rpart",
+    xval = 0) %>%
+  set_mode("classification")
+
+tm_design = data.table(
+  cost_complexity = seq(0.1, 0.2, length.out = 200))
+
+# mlr3
+learner = lrn("classif.rpart",
+  xval = 0,
+  cp = to_tune())
+
+mlr3_design = data.table(
+  cp = seq(0.1, 0.2, length.out = 200))
+# tidymodels
+tm_mod = rand_forest(
+  trees = tune()) %>%
+  set_engine("ranger",
+    num.threads = 1L,
+    seed = 1) %>%
+  set_mode("classification")
+
+tm_design = data.table(
+  trees = seq(1000, 1199))
+
+# mlr3
+learner = lrn("classif.ranger",
+  num.trees = to_tune(1, 10000),
+  num.threads = 1L,
+  seed = 1,
+  verbose = FALSE,
+  predict_type = "prob")
+
+mlr3_design = data.table(
+  num.trees = seq(1000, 1199))
+
+
+ +
+
+

We measure the runtime of the tune functions within each framework. Both the tidymodels and mlr3 frameworks are tasked with identifying the optimal hyperparameter configuration.

+
+
# tidymodels tune
+tune::tune_grid(
+  tm_wf,
+  resamples = resamples,
+  grid = design,
+  metrics = metrics)
+
+# mlr3 tune
+tuner = tnr("design_points", design = design, batch_size = nrow(design))
+mlr3tuning::tune(
+  tuner = tuner,
+  task = task,
+  learner = learner,
+  resampling = resampling,
+  measures = measure,
+  store_benchmark_result = FALSE)
+
+

In our sequential tuning tests, mlr3 demonstrates a notable advantage in terms of speed. This finding is clearly evidenced in our results, as shown in Table Table 11 for the rpart model and Table Table 12 for the ranger model. The faster performance of mlr3 in these sequential runs highlights its efficiency in handling the tuning process without parallelization.

+
+ +
+
+
+
+
+
+
+Table 11: Average runtime in seconds of tuning 200 points of rpart depending on the framework. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
FrameworkLQMedianUQ
mlr3272728
tidymodels373739
+
+
+
+
+
+
+
+
+
+Table 12: Average runtime in seconds of tuning 200 points of ranger depending on the framework. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
FrameworkLQMedianUQ
mlr3167171175
tidymodels194195196
+
+
+
+
+
+
+
+
+
+

Tune Parallel

+

Concluding our analysis, we proceed to evaluate the runtime performance of the tune functions, this time implementing parallelization to enhance efficiency. For these runs, parallelization is executed on 3 cores.

+

In the case of mlr3, we opt for the largest possible chunk size. This strategic choice means that all points within the tuning grid are sent to the workers in a single batch, effectively minimizing the overhead typically associated with parallelization. This approach is crucial in reducing the time spent in distributing tasks across multiple cores, thereby streamlining the tuning process. On the other hand, the tidymodels package also operates with the same chunk size, but this setting is determined and managed internally within the framework.

+

By conducting these parallelization tests, we aim to provide a deeper understanding of how each framework handles the distribution and management of computational tasks during the tuning process, particularly in a parallel computing environment. This final set of measurements is important in painting a complete picture of the runtime performance of the tune functions across both tidymodels and mlr3 under different operational settings.

+
+
options("mlr3.exec_chunk_size" = 200)
+
+

Our analysis of the parallelized tuning functions reveals that the runtimes for mlr3 and tidymodels are remarkably similar. However, subtle differences emerge upon closer inspection. For instance, the mlr3 package exhibits a slightly faster performance when tuning the rpart model, as indicated in Table 13. In contrast, it falls marginally behind tidymodels in tuning the ranger model, as shown in Table 14.

+

Interestingly, when considering the specific context of a 3-fold cross-validation, the doParallel package outperforms doFuture in terms of speed, as demonstrated in Figure 4. This outcome suggests that the choice of parallelization package can have a significant impact on tuning efficiency, particularly in scenarios with a smaller number of folds.

+

A key takeaway from our study is the clear benefit of enabling parallelization, regardless of the chosen framework-backend combination. Activating parallelization consistently enhances performance, making it a highly recommended strategy for tuning machine learning models, especially in tasks involving extensive hyperparameter exploration or larger datasets. This conclusion underscores the value of parallel processing in modern machine learning workflows, offering a practical solution for accelerating model tuning across various computational settings.

+
+ +
+
+
+
+
+
+
+Table 13: Average runtime in seconds of tuning 200 points of rpart depending on the framework. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FrameworkBackendLQMedianUQ
mlr3future111212
tidymodelsdoFuture171717
tidymodelsdoParallel131313
+
+
+
+
+
+
+
+
+
+Table 14: Average runtime in seconds of tuning 200 points of ranger depending on the framework. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FrameworkBackendLQMedianUQ
mlr3future545555
tidymodelsdoFuture585859
tidymodelsdoParallel545455
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+Figure 4: Average runtime, measured in seconds, of a tuning 200 hyperparameter configurations of rpart (displayed on the left) and ranger (on the right). The comparison encompasses variations across different frameworks and the implementation of parallelization. +
+
+
+
+
+
+
+
+

Conclusion

+

Our analysis reveals that both tidymodels and mlr3 exhibit comparable runtimes across key processes such as training, resampling, and tuning, each displaying its own set of strengths and efficiencies.

+

A notable observation is the relative overhead associated with using either framework, particularly when working with fast-fitting models like rpart. In these cases, the additional processing time introduced by the frameworks is more pronounced due to the inherently short training time of rpart models. This results in a higher relative overhead, reflecting the trade-offs between the convenience of a comprehensive framework and the directness of more basic approaches.

+

Conversely, when dealing with slower-fitting models such as ranger, the scenario shifts. For these more time-intensive models, the relative overhead introduced by the frameworks diminishes significantly. In such instances, the extended training times of the models absorb much of the frameworks’ inherent overhead, rendering it relatively negligible.

+

In summary, while there is no outright winner in terms of overall performance, the decision to use tidymodels or mlr3 should be informed by the specific requirements of the task at hand.

+ + +
+ + ]]>
+ https://mlr-org.com/gallery/technical/2023-10-30-tidymodels/ + Mon, 30 Oct 2023 00:00:00 GMT + +
+ + Survival modeling in mlr3 using Bayesian Additive Regression Trees (BART) + John Zobolas + https://mlr-org.com/gallery/technical/2023-10-25-bart-survival/ + +

Intro

+

Here are some interesting reads regarding BART:

+
    +
  • The first BART paper (Chipman, George, and McCulloch 2010).
  • +
  • The first implementation of BART for survival data (Bonato et al. 2011). This includes fully parametric AFT and Weibull models and the semi-parametric CoxPH regression model.
  • +
  • The first non-parametric implementation of BART for survival data (R. A. Sparapani et al. 2016)
  • +
  • BART R package tutorial (R. Sparapani, Spanbauer, and McCulloch 2021)
  • +
+

We incorporated the survival BART model in mlr3extralearners and in this tutorial we will demonstrate how we can use packages like mlr3, mlr3proba and distr6 to more easily manipulate the output predictions to assess model convergence, validate our model (via several survival metrics), as well as perform model interpretation via PDPs (Partial Dependence Plots).

+ +
+

Libraries

+
+
library(mlr3extralearners)
+library(mlr3pipelines)
+library(mlr3proba)
+library(distr6)
+library(BART) # 2.9.4
+library(dplyr)
+library(tidyr)
+library(tibble)
+library(ggplot2)
+
+
+
+

Data

+

We will use the Lung Cancer Dataset. We convert the time variable from days to months to ease the computational burden:

+
+
task_lung = tsk('lung')
+
+d = task_lung$data()
+# in case we want to select specific columns to keep
+# d = d[ ,colnames(d) %in% c("time", "status", "age", "sex", "ph.karno"), with = FALSE]
+d$time = ceiling(d$time/30.44)
+task_lung = as_task_surv(d, time = 'time', event = 'status', id = 'lung')
+task_lung$label = "Lung Cancer"
+
+
+
+
+ +
+
+Note +
+
+
+
    +
  1. The original BART implementation supports categorical features (factors). This results in different importance scores per each dummy level which doesn’t work well with mlr3. So features of type factor or character are not allowed and we leave it to the user to encode them as they please.
  2. +
  3. The original BART implementation supports features with missing values. This is totally fine with mlr3 as well! In this example, we impute the features to show good ML practice.
  4. +
+
+
+

In our lung dataset, we encode the sex feature and perform model-based imputation with the rpart regression learner:

+
+
po_encode = po('encode', method = 'treatment')
+po_impute = po('imputelearner', lrn('regr.rpart'))
+pre = po_encode %>>% po_impute
+task = pre$train(task_lung)[[1]]
+task
+
+
<TaskSurv:lung> (228 x 10): Lung Cancer
+* Target: time, status
+* Properties: -
+* Features (8):
+  - int (7): age, inst, meal.cal, pat.karno, ph.ecog, ph.karno, wt.loss
+  - dbl (1): sex
+
+
+

No missing values in our data:

+
+
task$missings()
+
+
     time    status       age       sex      inst  meal.cal pat.karno   ph.ecog  ph.karno   wt.loss 
+        0         0         0         0         0         0         0         0         0         0 
+
+
+

We partition the data to train and test sets:

+
+
set.seed(42)
+part = partition(task, ratio = 0.9)
+
+
+
+

Train and Test

+

We train the BART model and predict on the test set:

+
+
# default `ndpost` value: 1000. We reduce it to 50 to speed up calculations in this tutorial
+learner = lrn("surv.bart", nskip = 250, ndpost = 50, keepevery = 10, mc.cores = 10)
+learner$train(task, row_ids = part$train)
+p = learner$predict(task, row_ids = part$test)
+p
+
+
<PredictionSurv> for 23 observations:
+    row_ids time status    crank     distr
+          9    8   TRUE 66.19326 <list[1]>
+         10    6   TRUE 98.43005 <list[1]>
+         21   10   TRUE 54.82313 <list[1]>
+---                                       
+        160   13  FALSE 37.82089 <list[1]>
+        163   10  FALSE 69.63534 <list[1]>
+        194    8  FALSE 81.13678 <list[1]>
+
+
+

See more details about BART’s parameters on the online documentation.

+
+

distr

+

What kind of object is the predicted distr?

+
+
p$distr
+
+
Arrdist(23x31x50) 
+
+
+
+
+
+ +
+
+Arrdist dimensions: +
+
+
+
    +
  1. Patients (observations)
  2. +
  3. Time points (months)
  4. +
  5. Number of posterior draws
  6. +
+
+
+

Actually the $distr is an active R6 field - this means that some computation is required to create it. What the prediction object actually stores internally is a 3d survival array (can be used directly with no performance overhead):

+
+
dim(p$data$distr)
+
+
[1] 23 31 50
+
+
+

This is a more easy-to-understand and manipulate form of the full posterior survival matrix prediction from the BART package ((R. Sparapani, Spanbauer, and McCulloch 2021), pages 34-35).

+
+
+
+ +
+
+Warning +
+
+
+

Though we have optimized with C++ code the way the Arrdist object is constructed, calling the $distr field can be computationally taxing if the product of the sizes of the 3 dimensions above exceeds ~1 million. In our case, so the conversion to an Arrdist via $distr will certainly not create performance issues.

+
+
+

An example using the internal prediction data: get all the posterior probabilities of the 3rd patient in the test set, at 12 months (1 year):

+
+
p$data$distr[3, 12, ]
+
+
 [1] 0.26546909 0.27505937 0.21151435 0.46700513 0.26178380 0.24040003 0.29946469 0.52357780 0.40833108 0.40367780
+[11] 0.27027392 0.31781286 0.54151844 0.34460027 0.41826554 0.41866367 0.33694401 0.34511270 0.47244492 0.49423660
+[21] 0.42069678 0.20095489 0.48696980 0.48409357 0.35649439 0.47969355 0.16355660 0.33728105 0.40245228 0.42418033
+[31] 0.36336145 0.48181667 0.51858238 0.49635078 0.37238179 0.26694030 0.52219952 0.48992897 0.08572207 0.30306005
+[41] 0.33881682 0.33463870 0.29102074 0.43176131 0.38554545 0.38053756 0.36808776 0.13772665 0.21898264 0.14552514
+
+
+

Working with the $distr interface and Arrdist objects is very efficient as we will see later for predicting survival estimates.

+
+
+
+ +
+
+Tip +
+
+
+

In survival analysis, , where the survival function and the cumulative distribution function (cdf). The latter can be interpreted as risk or probability of death up to time .

+

We can verify the above from the prediction object:

+
+
surv_array = 1 - distr6::gprm(p$distr, "cdf") # 3d array
+testthat::expect_equal(p$data$distr, surv_array)
+
+
+
+
+
+

crank

+

crank is the expected mortality (Sonabend, Bender, and Vollmer 2022) which is the sum of the predicted cumulative hazard function (as is done in random survival forest models). Higher values denote larger risk. To calculate crank, we need a survival matrix. So we have to choose which 3rd dimension we should use from the predicted survival array. This is what the which.curve parameter of the learner does:

+
+
learner$param_set$get_values()$which.curve
+
+
[1] 0.5
+
+
+

The default value ( quantile) is the median survival probability. It could be any other quantile (e.g. ). Other possible values for which.curve are mean or a number denoting the exact posterior draw to extract (e.g. the last one, which.curve = 50).

+
+
+
+

Feature importance

+

Default score is the observed count of each feature in the trees (so the higher the score, the more important the feature):

+
+
learner$param_set$values$importance
+
+
[1] "count"
+
+
learner$importance()
+
+
      sex  meal.cal      inst pat.karno  ph.karno   wt.loss       age   ph.ecog 
+     7.84      7.46      7.08      6.76      6.60      6.46      5.48      5.42 
+
+
+
+
+

MCMC Diagnostics

+

BART uses internally MCMC (Markov Chain Monte Carlo) to sample from the posterior survival distribution. We need to check that MCMC has converged, meaning that the chains have reached a stationary distribution that approximates the true posterior survival distribution (otherwise the predictions may be inaccurate, misleading and unreliable).

+

We use Geweke’s convergence diagnostic test as it is implemented in the BART R package. We choose 10 random patients from the train set to evaluate the MCMC convergence.

+
+
# predictions on the train set
+p_train = learner$predict(task, row_ids = part$train)
+
+# choose 10 patients from the train set randomly and make a list
+ids = as.list(sample(length(part$train), 10))
+
+z_list = lapply(ids, function(id) {
+  # matrix with columns => time points and rows => posterior draws
+  post_surv = 1 - t(distr6::gprm(p_train$distr[id], "cdf")[1,,])
+  BART::gewekediag(post_surv)$z # get the z-scores
+})
+
+# plot the z scores vs time for all patients
+dplyr::bind_rows(z_list) %>%
+  tidyr::pivot_longer(cols = everything()) %>%
+  mutate(name = as.numeric(name)) %>%
+  ggplot(aes(x = name, y = value)) +
+  geom_point() +
+  labs(x = "Time (months)", y = "Z-scores") +
+  # add critical values for a = 0.05
+  geom_hline(yintercept = 1.96, linetype = 'dashed', color = "red") +
+  geom_hline(yintercept = -1.96, linetype = 'dashed', color = "red") +
+  theme_bw(base_size = 14)
+
+
+
+

+
Geweke plot for MCMC diagnostics. Z-scores for the difference in the mean survival prediction between the first 10% and last 50% part of a Markov chain. The predictions are taken from 10 random patients in the train set. Red lines indicate the a = 0.05 critical line. Only a few z-scores exceed the 95% limits so we conclude that convergence has been attained.
+
+
+
+
+
+
+

Performance (test set)

+

We will use the following survival metrics:

+
    +
  1. Integrated Brier Score (requires a survival distribution prediction - distr)
  2. +
  3. Right-Censored Log loss (requires a survival distribution prediction - distr)
  4. +
  5. Uno’s C-index (requires a continuous ranking score prediction - crank)
  6. +
+

For the first two measures we will use the ERV (Explained Residual Variation) version, which standardizes the scores against a Kaplan-Meier (KM) baseline (Sonabend et al. 2022). This means that values close to represent performance similar to a KM model, negative values denote worse performance than KM and is the absolute best possible score.

+
+
measures = list(
+  msr("surv.graf", ERV = TRUE),
+  msr("surv.rcll", ERV = TRUE),
+  msr("surv.cindex", weight_meth = "G2", id = "surv.cindex.uno")
+)
+
+for (measure in measures) {
+  print(p$score(measure, task = task, train_set = part$train))
+}
+
+
  surv.graf 
+-0.09950096 
+  surv.rcll 
+-0.02622117 
+surv.cindex.uno 
+       0.551951 
+
+
+
+
+
+ +
+
+Note +
+
+
+

All metrics use by default the median survival distribution from the 3d array, no matter what is the which.curve argument during the learner’s construction.

+
+
+
+
+

Resampling

+

Performing resampling with the BART learner is very easy using mlr3.

+

We first stratify the data by status, so that in each resampling the proportion of censored vs un-censored patients remains the same:

+
+
task$col_roles$stratum = 'status'
+task$strata
+
+
       N                row_id
+   <int>                <list>
+1:   165       1,2,4,5,7,8,...
+2:    63  3, 6,38,68,71,83,...
+
+
+
+
rr = resample(task, learner, resampling = rsmp("cv", folds = 5), store_backends = TRUE)
+
+
INFO  [11:41:53.078] [mlr3] Applying learner 'surv.bart' on task 'lung' (iter 1/5)
+INFO  [11:41:55.545] [mlr3] Applying learner 'surv.bart' on task 'lung' (iter 2/5)
+INFO  [11:41:57.937] [mlr3] Applying learner 'surv.bart' on task 'lung' (iter 3/5)
+INFO  [11:42:00.417] [mlr3] Applying learner 'surv.bart' on task 'lung' (iter 4/5)
+INFO  [11:42:03.357] [mlr3] Applying learner 'surv.bart' on task 'lung' (iter 5/5)
+
+
+

No errors or warnings:

+
+
rr$errors
+
+
Empty data.table (0 rows and 2 cols): iteration,msg
+
+
rr$warnings
+
+
Empty data.table (0 rows and 2 cols): iteration,msg
+
+
+

Performance in each fold:

+
+
rr$score(measures)
+
+
   task_id learner_id resampling_id iteration    surv.graf    surv.rcll surv.cindex.uno
+    <char>     <char>        <char>     <int>        <num>        <num>           <num>
+1:    lung  surv.bart            cv         1 -0.312614598 -0.102013166       0.5869665
+2:    lung  surv.bart            cv         2 -0.103181391 -0.009579343       0.5502903
+3:    lung  surv.bart            cv         3  0.001448263  0.338851363       0.6178001
+4:    lung  surv.bart            cv         4 -0.044161171  0.003691073       0.6157215
+5:    lung  surv.bart            cv         5 -0.043129352  0.157902047       0.5688389
+Hidden columns: task, learner, resampling, prediction
+
+
+

Mean cross-validation performance:

+
+
rr$aggregate(measures)
+
+
      surv.graf       surv.rcll surv.cindex.uno 
+     -0.1003276       0.0777704       0.5879235 
+
+
+
+
+

Uncertainty Quantification in Survival Prediction

+

We will choose two patients from the test set and plot their survival prediction posterior estimates.

+

Let’s choose the patients with the worst and the best survival time:

+
+
death_times = p$truth[,1]
+sort(death_times)
+
+
 [1]  3  5  5  6  6  6  7  8  8  8  8 10 10 10 12 12 12 13 15 16 17 18 27
+
+
worst_indx = which(death_times == min(death_times))[1] # died first
+best_indx  = which(death_times == max(death_times))[1] # died last
+
+patient_ids = c(worst_indx, best_indx)
+patient_ids # which patient IDs
+
+
[1]  5 18
+
+
death_times = death_times[patient_ids]
+death_times # 1st is worst, 2nd is best
+
+
[1]  3 27
+
+
+

Subset Arrdist to only the above 2 patients:

+
+
arrd = p$distr[patient_ids]
+arrd
+
+
Arrdist(2x31x50) 
+
+
+

We choose time points (in months) for the survival estimates:

+
+
months = seq(1, 36) # 1 month - 3 years
+
+

We use the $distr interface and the $survival property to get survival probabilities from an Arrdist object as well as the quantile credible intervals (CIs). The median survival probabilities can be extracted as follows:

+
+
med = arrd$survival(months) # 'med' for median
+
+colnames(med) = paste0(patient_ids, "_med")
+med = as_tibble(med) %>% add_column(month = months)
+head(med)
+
+
# A tibble: 6 × 3
+  `5_med` `18_med` month
+    <dbl>    <dbl> <int>
+1   0.874    0.981     1
+2   0.767    0.962     2
+3   0.670    0.945     3
+4   0.569    0.927     4
+5   0.465    0.901     5
+6   0.366    0.869     6
+
+
+

We can briefly verify model’s predictions: 1st patient survival probabilities on any month are lower (worst) compared to the 2nd patient.

+

Note that subsetting an Arrdist (3d array) creates a Matdist (2d matrix), for example we can explicitly get the median survival probabilities:

+
+
matd_median = arrd[, 0.5] # median
+head(matd_median$survival(months)) # same as with `arrd`
+
+
       [,1]      [,2]
+1 0.8741127 0.9808363
+2 0.7670382 0.9621618
+3 0.6701276 0.9450867
+4 0.5688809 0.9272284
+5 0.4647686 0.9007042
+6 0.3660939 0.8687270
+
+
+

Using the mean posterior survival probabilities or the ones from the last posterior draw is also possible and can be done as follows:

+
+
matd_mean = arrd[, "mean"] # mean (if needed)
+head(matd_mean$survival(months))
+
+
       [,1]      [,2]
+1 0.8652006 0.9748463
+2 0.7533538 0.9521817
+3 0.6560050 0.9293229
+4 0.5623555 0.9051549
+5 0.4750038 0.8758896
+6 0.3815333 0.8360373
+
+
matd_50draw = arrd[, 50] # the 50th posterior draw
+head(matd_50draw$survival(months))
+
+
       [,1]      [,2]
+1 0.9178342 0.9920982
+2 0.8424195 0.9842589
+3 0.7732014 0.9764815
+4 0.7096707 0.9687656
+5 0.6029119 0.9495583
+6 0.5122132 0.9307318
+
+
+

To get the CIs we will subset the Arrdist using a quantile number (0-1), which extracts a Matdist based on the cdf. The survival function is 1 - cdf, so low and upper bounds are reversed:

+
+
low  = arrd[, 0.975]$survival(months) # 2.5% bound
+high = arrd[, 0.025]$survival(months) # 97.5% bound
+colnames(low)  = paste0(patient_ids, "_low")
+colnames(high) = paste0(patient_ids, "_high")
+low  = as_tibble(low)
+high = as_tibble(high)
+
+

The median posterior survival probabilities for the two patient of interest and the corresponding CI bounds in a tidy format are:

+
+
surv_tbl =
+  bind_cols(low, med, high) %>%
+  pivot_longer(cols = !month, values_to = "surv",
+    names_to = c("patient_id", ".value"), names_sep = "_") %>%
+  relocate(patient_id)
+surv_tbl
+
+
# A tibble: 72 × 5
+   patient_id month   low   med  high
+   <chr>      <int> <dbl> <dbl> <dbl>
+ 1 5              1 0.713 0.874 0.953
+ 2 18             1 0.929 0.981 0.996
+ 3 5              2 0.508 0.767 0.903
+ 4 18             2 0.863 0.962 0.991
+ 5 5              3 0.362 0.670 0.855
+ 6 18             3 0.801 0.945 0.985
+ 7 5              4 0.244 0.569 0.804
+ 8 18             4 0.734 0.927 0.977
+ 9 5              5 0.146 0.465 0.748
+10 18             5 0.654 0.901 0.969
+# ℹ 62 more rows
+
+
+

We draw survival curves with the uncertainty for the survival probability quantified:

+
+
my_colors = c("#E41A1C", "#4DAF4A")
+names(my_colors) = patient_ids
+
+surv_tbl %>%
+  ggplot(aes(x = month, y = med)) +
+  geom_step(aes(color = patient_id), linewidth = 1) +
+  xlab('Time (Months)') +
+  ylab('Survival Probability') +
+  geom_ribbon(aes(ymin = low, ymax = high, fill = patient_id),
+    alpha = 0.3, show.legend = F) +
+  geom_vline(xintercept = death_times[1], linetype = 'dashed', color = my_colors[1]) +
+  geom_vline(xintercept = death_times[2], linetype = 'dashed', color = my_colors[2]) +
+  theme_bw(base_size = 14) +
+  scale_color_manual(values = my_colors) +
+  scale_fill_manual(values = my_colors) +
+  guides(color = guide_legend(title = "Patient ID"))
+
+
+
+

+
Uncertainty quantification for the survival prediction of two patients in the test set using 95% credible intervals. The two vertical lines correspond to the reported time of death (in months) for the two patients.
+
+
+
+
+
+
+

Partial Dependence Plot

+

We will use a Partial Dependence Plot (PDP) (Friedman 2001) to visualize how much different are males vs females in terms of their average survival predictions across time.

+
+
+
+ +
+
+Note +
+
+
+

PDPs assume that features are independent. In our case we need to check that sex doesn’t correlate with any of the other features used for training the BART learner. Since sex is a categorical feature, we fit a linear model using as target variable every other feature in the data () and conduct an ANOVA (ANalysis Of VAriance) to get the variance explained or . The square root of that value is the correlation measure we want.

+
+
+
+
# code from https://christophm.github.io/interpretable-ml-book/ale.html
+mycor = function(cnames, data) {
+  x.num = data[, cnames[1], with = FALSE][[1]]
+  x.cat = data[, cnames[2], with = FALSE][[1]]
+  # R^2 = Cor(X, Y)^2 in simple linear regression
+  sqrt(summary(lm(x.num ~ x.cat))$r.squared)
+}
+
+cnames = c("sex")
+combs = expand.grid(y = setdiff(colnames(d), "sex"), x = cnames)
+combs$cor = apply(combs, 1, mycor, data = task$data()) # use the train set
+combs
+
+
          y   x        cor
+1      time sex 0.12941337
+2    status sex 0.24343282
+3       age sex 0.12216709
+4      inst sex 0.07826337
+5  meal.cal sex 0.18389545
+6 pat.karno sex 0.04132443
+7   ph.ecog sex 0.02564987
+8  ph.karno sex 0.01702471
+9   wt.loss sex 0.13431983
+
+
+

sex doesn’t correlate strongly with any other feature, so we can compute the PDP:

+
+
# create two datasets: one with males and one with females
+# all other features remain the same (use train data, 205 patients)
+d = task$data(rows = part$train) # `rows = part$test` to use the test set
+
+d$sex = 1
+task_males = as_task_surv(d, time = 'time', event = 'status', id = 'lung-males')
+d$sex = 0
+task_females = as_task_surv(d, time = 'time', event = 'status', id = 'lung-females')
+
+# make predictions
+p_males   = learner$predict(task_males)
+p_females = learner$predict(task_females)
+
+# take the median posterior survival probability
+surv_males   = p_males$distr$survival(months) # patients x times
+surv_females = p_females$distr$survival(months) # patients x times
+
+# tidy up data: average and quantiles across patients
+data_males =
+  apply(surv_males, 1, function(row) {
+    tibble(
+      low = quantile(row, probs = 0.025),
+      avg = mean(row),
+      high = quantile(row, probs = 0.975)
+    )
+  }) %>%
+  bind_rows() %>%
+  add_column(sex = 'male', month = months, .before = 1)
+
+data_females =
+  apply(surv_females, 1, function(row) {
+    tibble(
+      low = quantile(row, probs = 0.025),
+      avg = mean(row),
+      high = quantile(row, probs = 0.975)
+    )
+  }) %>%
+  bind_rows() %>%
+  add_column(sex = 'female', month = months, .before = 1)
+
+pdp_tbl = bind_rows(data_males, data_females)
+pdp_tbl
+
+
# A tibble: 72 × 5
+   sex   month    low   avg  high
+   <chr> <int>  <dbl> <dbl> <dbl>
+ 1 male      1 0.836  0.942 0.981
+ 2 male      2 0.704  0.889 0.963
+ 3 male      3 0.587  0.839 0.943
+ 4 male      4 0.488  0.788 0.924
+ 5 male      5 0.392  0.732 0.897
+ 6 male      6 0.304  0.663 0.860
+ 7 male      7 0.234  0.601 0.829
+ 8 male      8 0.172  0.550 0.799
+ 9 male      9 0.130  0.503 0.766
+10 male     10 0.0945 0.455 0.733
+# ℹ 62 more rows
+
+
+
+
my_colors = c("#E41A1C", "#4DAF4A")
+names(my_colors) = c('male', 'female')
+
+pdp_tbl %>%
+  ggplot(aes(x = month, y = avg)) +
+  geom_step(aes(color = sex), linewidth = 1) +
+  xlab('Time (Months)') +
+  ylab('Survival Probability') +
+  geom_ribbon(aes(ymin = low, ymax = high, fill = sex), alpha = 0.2, show.legend = F) +
+  theme_bw(base_size = 14) +
+  scale_color_manual(values = my_colors) +
+  scale_fill_manual(values = my_colors)
+
+
+
+

+
Friedman’s partial dependence function with 95% prediction intervals: males vs females. Females show on average larger survival estimates compared to men, across all time points. Overlapping shaded area represents men and women that have similar survival characteristics.
+
+
+
+
+
+
+ + + + +
+ +

References

+
+Bonato, Vinicius, Veerabhadran Baladandayuthapani, Bradley M. Broom, Erik P. Sulman, Kenneth D. Aldape, and Kim Anh Do. 2011. Bayesian ensemble methods for survival prediction in gene expression data.” Bioinformatics 27 (3): 359–67. https://doi.org/10.1093/BIOINFORMATICS/BTQ660. +
+
+Chipman, Hugh A, Edward I George, and Robert E McCulloch. 2010. BART: BAYESIAN ADDITIVE REGRESSION TREES.” The Annals of Applied Statistics 4 (1): 266–98. http://www.jstor.org/stable/27801587. +
+
+Friedman, Jerome H. 2001. Greedy function approximation: a gradient boosting machine.” Annals of Statistics, 1189–1232. https://doi.org/10.1214/aos/1013203451. +
+
+Sonabend, Raphael, Andreas Bender, and Sebastian Vollmer. 2022. Avoiding C-hacking when evaluating survival distribution predictions with discrimination measures.” Edited by Zhiyong Lu. Bioinformatics, July. https://doi.org/10.1093/BIOINFORMATICS/BTAC451. +
+
+Sonabend, Raphael, Florian Pfisterer, Alan Mishler, Moritz Schauer, Lukas Burk, Sumantrak Mukherjee, and Sebastian Vollmer. 2022. Flexible Group Fairness Metrics for Survival Analysis,” May. https://doi.org/10.48550/arxiv.2206.03256. +
+
+Sparapani, Rodney A., Brent R. Logan, Robert E. McCulloch, and Purushottam W. Laud. 2016. Nonparametric survival analysis using Bayesian Additive Regression Trees (BART).” Statistics in Medicine 35 (16): 2741–53. https://doi.org/10.1002/SIM.6893. +
+
+Sparapani, Rodney, Charles Spanbauer, and Robert McCulloch. 2021. Nonparametric Machine Learning and Efficient Computation with Bayesian Additive Regression Trees: The BART R Package.” Journal of Statistical Software 97 (1): 1–66. https://doi.org/10.18637/JSS.V097.I01. +
+
]]>
+ https://mlr-org.com/gallery/technical/2023-10-25-bart-survival/ + Wed, 25 Oct 2023 00:00:00 GMT +
+ + Spatial Data in the mlr3 Ecosystem + Marc Becker + https://mlr-org.com/gallery/technical/2023-02-27-land-cover-classification/ + +

Scope

+

Working with spatial data in R requires a lot of data wrangling e.g. reading from different file formats, converting between spatial formats, creating tables from point layers, and predicting spatial raster images. The goal of mlr3spatial is to simplify these workflows within the mlr3 ecosystem. As a practical example, we will perform a land cover classification for the city of Leipzig, Germany. Figure 1 illustrates the typical workflow for this type of task: Load the training data, create a spatial task, train a learner with it, and predict the final raster image.

+
+
+
+
+
+
+
%%{ init: { 'flowchart': { 'curve': 'bump' } } }%%
+
+flowchart LR
+    subgraph files[Files]
+    vector[Vector]
+    raster[Raster]
+    end
+    subgraph load[Load Data]
+    sf
+    terra
+    end
+    vector --> sf
+    raster --> terra
+    subgraph train_model[Train Model]
+    task[Task]
+    learner[Learner]
+    end
+    terra --> prediction_raster
+    task --> learner
+    sf --> task
+    subgraph predict[Spatial Prediction]
+    prediction_raster[Raster Image]
+    end
+    learner --> prediction_raster
+
+
+
+
+Figure 1: Spatial prediction workflow in mlr3spatial. +
+
+
+
+
+

We assume that you are familiar with the mlr3 ecosystem and know the basic concepts of remote sensing. If not, we recommend reading the mlr3book first. If you are interested in spatial resampling, check out the book chapter on spatial analysis.

+ +
+

Land Cover Classification

+

Land cover is the physical material or vegetation that covers the surface of the earth, including both natural and human-made features. Understanding land cover patterns and changes over time is critical for addressing global environmental challenges, such as climate change, land degradation, and loss of biodiversity. Land cover classification is the process of assigning land cover classes to pixels in a raster image. With mlr3spatial, we can easily perform a land cover classification within the mlr3 ecosystem.

+

Before we can start the land cover classification, we need to load the necessary packages. The mlr3spatial package relies on terra for processing raster data and sf for vector data. These widely used packages read all common raster and vector formats. Additionally, the stars and raster packages are supported.

+
+
library(mlr3verse)
+library(mlr3spatial)
+library(terra, exclude = "resample")
+library(sf)
+
+

We will work with a Sentinel-2 scene of the city of Leipzig which consists of 7 bands with a 10 or 20m spatial resolution and an NDVI band. The data is included in the mlr3spatial package. We use the terra::rast() to load the TIFF raster file.

+
+
leipzig_raster = rast(system.file("extdata", "leipzig_raster.tif", package = "mlr3spatial"))
+leipzig_raster
+
+
class       : SpatRaster 
+dimensions  : 206, 154, 8  (nrow, ncol, nlyr)
+resolution  : 10, 10  (x, y)
+extent      : 731810, 733350, 5692030, 5694090  (xmin, xmax, ymin, ymax)
+coord. ref. : WGS 84 / UTM zone 32N (EPSG:32632) 
+source      : leipzig_raster.tif 
+names       :  b02,  b03,  b04,  b06,  b07,  b08, ... 
+min values  :  846,  645,  366,  375,  401,  374, ... 
+max values  : 4705, 4880, 5451, 4330, 5162, 5749, ... 
+
+
+

The training data is a GeoPackage point layer with land cover labels and spectral features. We load the file and create a simple feature point layer.

+
+
leipzig_vector = read_sf(system.file("extdata", "leipzig_points.gpkg", package = "mlr3spatial"), stringsAsFactors = TRUE)
+leipzig_vector
+
+
Simple feature collection with 97 features and 9 fields
+Geometry type: POINT
+Dimension:     XY
+Bounding box:  xmin: 731930.5 ymin: 5692136 xmax: 733220.3 ymax: 5693968
+Projected CRS: WGS 84 / UTM zone 32N
+# A tibble: 97 × 10
+     b02   b03   b04   b06   b07   b08   b11    ndvi land_cover               geom
+   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>   <dbl> <fct>             <POINT [m]>
+ 1   903   772   426  2998  4240  4029  1816  0.809  forest     (732480.1 5693957)
+ 2  1270  1256  1081  1998  2493  2957  2073  0.465  urban      (732217.4 5692769)
+ 3  1033   996   777  2117  2748  2799  1595  0.565  urban      (732737.2 5692469)
+ 4   962   773   500   465   505   396   153 -0.116  water      (733169.3 5692777)
+ 5  1576  1527  1626  1715  1745  1768  1980  0.0418 urban      (732202.2 5692644)
+ 6  1125  1185   920  3058  3818  3758  2682  0.607  pasture      (732153 5693059)
+ 7   880   746   424  2502  3500  3397  1469  0.778  forest     (731937.9 5693722)
+ 8  1332  1251  1385  1663  1799  1640  1910  0.0843 urban      (732416.2 5692324)
+ 9   940   741   475   452   515   400   139 -0.0857 water      (732933.7 5693344)
+10   902   802   454  2764  3821  3666  1567  0.780  forest     (732411.3 5693352)
+# ℹ 87 more rows
+
+
+

We plot both layers to get an overview of the data. The training points are located in the districts of Lindenau and Zentrum West.

+
+
+Code +
library(ggplot2)
+library(tidyterra, exclude = "filter")
+
+ggplot() +
+  geom_spatraster_rgb(data = leipzig_raster, r = 3, g = 2, b = 1, max_col_value = 5451) +
+  geom_spatvector(data = leipzig_vector, aes(color = land_cover)) +
+  scale_color_viridis_d(name = "Land cover", labels = c("Forest", "Pastures", "Urban", "Water")) +
+  theme_minimal()
+
+
+
+
+

+
+
+
+
+

The as_task_classif_st() function directly creates a spatial task from the point layer. This makes it unnecessary to transform the point layer to a data.frame with coordinates. Spatial tasks additionally store the coordinates of the training points. The coordinates are useful when estimating the performance of the model with spatial resampling.

+
+
task = as_task_classif_st(leipzig_vector, target = "land_cover")
+task
+
+
<TaskClassifST:leipzig_vector> (97 x 9)
+* Target: land_cover
+* Properties: multiclass
+* Features (8):
+  - dbl (8): b02, b03, b04, b06, b07, b08, b11, ndvi
+* Coordinates:
+           X       Y
+ 1: 732480.1 5693957
+ 2: 732217.4 5692769
+ 3: 732737.2 5692469
+ 4: 733169.3 5692777
+ 5: 732202.2 5692644
+---                 
+93: 733018.7 5692342
+94: 732551.4 5692887
+95: 732520.4 5692589
+96: 732542.2 5692204
+97: 732437.8 5692300
+
+
+

Now we can train a model with the task. We use a simple decision tree learner from the rpart package. The "classif_st" task is a specialization of the "classif" task and therefore works with all "classif" learners.

+
+
learner = lrn("classif.rpart")
+learner$train(task)
+
+

To get a complete land cover classification of Leipzig, we have to predict on each pixel and return a raster image with these predictions. The $predict() method of the learner only works for tabular data. To predict a raster image, we use the predict_spatial() function.

+
+
# predict land cover map
+land_cover = predict_spatial(leipzig_raster, learner)
+
+
+
+Code +
ggplot() +
+  geom_spatraster(data = land_cover) +
+  scale_fill_viridis_d(name = "Land cover", labels = c("Forest", "Pastures", "Urban", "Water")) +
+  theme_minimal()
+
+
+
+
+

+
+
+
+
+
+
+

Conclusion

+

Working with spatial data in R is very easy with the mlr3spatial package. You can quickly train a model with a point layer and predict a raster image. The mlr3spatial package is still in development and we are looking forward to your feedback and contributions.

+ + +
+ + ]]>
+ https://mlr-org.com/gallery/technical/2023-02-27-land-cover-classification/ + Mon, 27 Feb 2023 00:00:00 GMT + +
+ + Recursive Feature Elimination on the Sonar Data Set + Marc Becker + https://mlr-org.com/gallery/optimization/2023-02-07-recursive-feature-elimination/ + +

Scope

+

Feature selection is the process of finding an optimal subset of features in order to improve the performance, interpretability and robustness of machine learning algorithms. In this article, we introduce the wrapper feature selection method Recursive Feature Elimination. Wrapper methods iteratively select features that optimize a performance measure. As an example, we will search for the optimal set of features for a gradient boosting machine and support vector machine on the Sonar data set. We assume that you are already familiar with the basic building blocks of the mlr3 ecosystem. If you are new to feature selection, we recommend reading the feature selection chapter of the mlr3book first.

+ +
+

Recursive Feature Elimination

+

Recursive Feature Elimination (RFE) is a widely used feature selection method for high-dimensional data sets. The idea is to iteratively remove the least predictive feature from a model until the desired number of features is reached. This feature is determined by the built-in feature importance method of the model. Currently, RFE works with support vector machines (SVM), decision tree algorithms and gradient boosting machines (GBM). Supported learners are tagged with the "importance" property. For a full list of supported learners, see the learner page on the mlr-org website and search for "importance".

+

Guyon et al. (2002) developed the RFE algorithm for SVMs (SVM-RFE) to select informative genes in cancer classification. The importance of the features is given by the weight vector of a linear support vector machine. This method was later extended to other machine learning algorithms. The only requirement is that the models can internally measure the feature importance. The random forest algorithm offers multiple options for measuring feature importance. The commonly used methods are the mean decrease in accuracy (MDA) and the mean decrease in impurity (MDI). The MDA measures the decrease in accuracy for a feature if it was randomly permuted in the out-of-bag sample. The MDI is the total reduction in node impurity when the feature is used for splitting. Gradient boosting algorithms like XGBoost, LightGBM and GBM use similar methods to measure the importance of the features.

+

Resampling strategies can be combined with the algorithm in different ways. The frameworks scikit-learn (Pedregosa et al. 2011) and caret (Kuhn 2008) implement a variant called recursive feature elimination with cross-validation (RFE-CV) that estimates the optimal number of features with cross-validation first. Then one more RFE is carried out on the complete dataset with the optimal number of features as the final feature set size. The RFE implementation in mlr3 can rank and aggregate importance scores across resampling iterations. We will explore both variants in more detail below.

+

mlr3fselect is the feature selection package of the mlr3 ecosystem. It implements the RFE and RFE-CV algorithm. We load all packages of the ecosystem with the mlr3verse package.

+
+
library(mlr3verse)
+
+

We retrieve the RFE optimizer with the fs() function.

+
+
optimizer = fs("rfe",
+  n_features = 1,
+  feature_number = 1,
+  aggregation = "rank")
+
+

The algorithm has multiple control parameters. The optimizer stops when the number of features equals n_features. The parameters feature_number, feature_fraction and subset_size determine the number of features that are removed in each iteration. The feature_number option removes a fixed number of features in each iteration, whereas feature_fraction removes a fraction of the features. The subset_size argument is a vector that specifies exactly how many features are removed in each iteration. The parameters are mutually exclusive and the default is feature_fraction = 0.5. Usually, RFE fits a new model in each resampling iteration and calculates the feature importance again. We can deactivate this behavior by setting recursive = FALSE. The selection of feature subsets in all iterations is then based solely on the importance scores of the first model trained with all features. When running an RFE with a resampling strategy like cross-validation, multiple models and importance scores are generated. The aggregation parameter determines how the importance scores are aggregated. The option "rank" ranks the importance scores in each iteration and then averages the ranks of the features. The feature with the lowest average rank is removed. The option "mean" averages the importance scores of the features across the iterations. The "mean" should only be used if the learner’s importance scores can be reasonably averaged.

+
+
+

Task

+

The objective of the Sonar data set is to predict whether a sonar signal bounced off a metal cylinder or a rock. The data set includes 60 numerical features (see Figure 1).

+
+
task = tsk("sonar")
+
+
+
+Code +
library(ggplot2)
+library(data.table)
+
+data = melt(as.data.table(task), id.vars = task$target_names, measure.vars = task$feature_names)
+data = data[c("V1", "V10", "V11", "V12", "V13", "V14"), , on = "variable"]
+
+ggplot(data, aes(x = value, fill = Class)) +
+  geom_density(alpha = 0.5) +
+  facet_wrap(~ variable, ncol = 6, scales = "free") +
+  scale_fill_viridis_d(end = 0.8) +
+  theme_minimal() +
+  theme(axis.title.x = element_blank())
+
+
+
+
+
+ +
+
+Figure 1: Distribution of the first 5 features in the Sonar dataset. +
+
+
+
+
+
+
+

Gradient Boosting Machine

+

We start with the GBM learner and set the predict type to "prob" to obtain class probabilities.

+
+
learner = lrn("classif.gbm",
+  distribution = "bernoulli",
+  predict_type = "prob")
+
+

Now we define the feature selection problem by using the fsi() function that constructs an FSelectInstanceSingleCrit. In addition to the task and learner, we have to select a resampling strategy and performance measure to determine how the performance of a feature subset is evaluated. We pass the "none" terminator because the n_features parameter of the optimizer determines when the feature selection stops.

+
+
instance = fsi(
+  task = task,
+  learner = learner,
+  resampling = rsmp("cv", folds = 6),
+  measures = msr("classif.auc"),
+  terminator = trm("none"))
+
+

We are now ready to start the RFE. To do this, we simply pass the instance to the $optimize() method of the optimizer.

+
+
optimizer$optimize(instance)
+
+

The optimizer saves the best feature set and the corresponding estimated performance in instance$result.

+

Figure 2 shows the optimization path of the feature selection. We observe that the performance increases first as the number of features decreases. As soon as informative features are removed, the performance drops.

+
+
+Code +
library(viridisLite)
+library(mlr3misc)
+
+data = as.data.table(instance$archive)
+data[, n:= map_int(importance, length)]
+
+ggplot(data, aes(x = n, y = classif.auc)) +
+  geom_line(
+    color = viridis(1, begin = 0.5),
+    linewidth = 1) +
+  geom_point(
+    fill = viridis(1, begin = 0.5),
+    shape = 21,
+    size = 3,
+    stroke = 0.5,
+    alpha = 0.8) +
+  xlab("Number of Features") +
+  scale_x_reverse() +
+  theme_minimal()
+
+
+
+
+
+ +
+
+Figure 2: Performance of the gradient-boosting models depending on the number of features. +
+
+
+
+
+

The importance scores of the feature sets are recorded in the archive.

+
+
as.data.table(instance$archive)[, list(features, classif.auc, importance)]
+
+
                      features classif.auc                                                importance
+ 1: V1,V10,V11,V12,V13,V14,...   0.8929304 58.83333,58.83333,54.50000,54.00000,53.33333,52.50000,...
+ 2: V1,V10,V11,V12,V13,V15,...   0.9177811 57.33333,56.00000,54.00000,53.66667,50.50000,50.00000,...
+ 3: V1,V10,V11,V12,V13,V15,...   0.9045253 54.83333,54.66667,54.66667,53.00000,51.83333,51.33333,...
+ 4: V1,V10,V11,V12,V13,V15,...   0.8927833 56.00000,55.83333,53.00000,52.00000,50.16667,50.00000,...
+ 5: V1,V10,V11,V12,V13,V15,...   0.9016274 55.50000,53.50000,51.33333,50.00000,49.00000,48.50000,...
+---                                                                                                 
+56:         V11,V12,V16,V48,V9   0.8311625              4.166667,3.333333,2.833333,2.500000,2.166667
+57:             V11,V12,V16,V9   0.8216772                       3.833333,2.666667,2.000000,1.500000
+58:                V11,V12,V16   0.8065807                                2.833333,1.833333,1.333333
+59:                    V11,V12   0.8023780                                         1.833333,1.166667
+60:                        V11   0.7515904                                                         1
+
+
+
+
+

Support Vector Machine

+

Now we will select the optimal feature set for an SVM with a linear kernel. The importance scores are the weights of the model.

+
+
learner = lrn("classif.svm",
+  type = "C-classification",
+  kernel = "linear",
+  predict_type = "prob")
+
+

The SVM learner does not support the calculation of importance scores at first. The reason is that importance scores cannot be determined with all kernels. This can be seen by the missing "importance" property.

+
+
learner$properties
+
+
[1] "multiclass" "twoclass"  
+
+
+

Using the "mlr3fselect.svm_rfe" callback however makes it possible to use a linear SVM with the RFE optimizer. The callback adds the $importance() method internally to the learner. We load the callback with the clbk() function and pass it as the "callback" argument to fsi().

+
+
instance = fsi(
+  task = task,
+  learner = learner,
+  resampling = rsmp("cv", folds = 6),
+  measures = msr("classif.auc"),
+  terminator = trm("none"),
+  callback = clbk("mlr3fselect.svm_rfe"))
+
+

We start the feature selection.

+
+
optimizer$optimize(instance)
+
+

Figure 3 shows the average performance of the SVMs depending on the number of features. We can see that the performance increases significantly with a reduced feature set.

+
+
+Code +
library(viridisLite)
+library(mlr3misc)
+
+data = as.data.table(instance$archive)
+data[, n:= map_int(importance, length)]
+
+ggplot(data, aes(x = n, y = classif.auc)) +
+  geom_line(
+    color = viridis(1, begin = 0.5),
+    linewidth = 1) +
+  geom_point(
+    fill = viridis(1, begin = 0.5),
+    shape = 21,
+    size = 3,
+    stroke = 0.5,
+    alpha = 0.8) +
+  xlab("Number of Features") +
+  scale_x_reverse() +
+  theme_minimal()
+
+
+
+
+
+ +
+
+Figure 3: Performance of the support vector machines depending on the number of features. +
+
+
+
+
+

For datasets with a lot of features, it is more efficient to remove several features per iteration. We show an example where 25% of the features are removed in each iteration.

+
+
optimizer = fs("rfe", n_features = 1, feature_fraction = 0.75)
+
+instance = fsi(
+  task = task,
+  learner = learner,
+  resampling = rsmp("cv", folds = 6),
+  measures = msr("classif.auc"),
+  terminator = trm("none"),
+  callback = clbk("mlr3fselect.svm_rfe"))
+
+optimizer$optimize(instance)
+
+

Figure 4 shows a similar optimization curve as Figure 3 but with fewer evaluated feature sets.

+
+
+Code +
library(viridisLite)
+library(mlr3misc)
+
+data = as.data.table(instance$archive)
+data[, n:= map_int(importance, length)]
+
+ggplot(data, aes(x = n, y = classif.auc)) +
+  geom_line(
+    color = viridis(1, begin = 0.5),
+    linewidth = 1) +
+  geom_point(
+    fill = viridis(1, begin = 0.5),
+    shape = 21,
+    size = 3,
+    stroke = 0.5,
+    alpha = 0.8) +
+  xlab("Number of Features") +
+  scale_x_reverse() +
+  theme_minimal()
+
+
+
+
+
+ +
+
+Figure 4: Optimization path of the feature selection. +
+
+
+
+
+
+
+

Recursive Feature Elimination with Cross Validation

+

RFE-CV estimates the optimal number of features before selecting a feature set. For this, an RFE is run in each resampling iteration and the number of features with the best mean performance is selected (see Figure 5). Then one more RFE is carried out on the complete dataset with the optimal number of features as the final feature set size.

+
+
+
+
+
+
+
%%{ init: { 'flowchart': { 'curve': 'bump' } } }%%
+flowchart TB
+    cross-validation[3-Fold Cross-Validation]
+    cross-validation-->rfe-1
+    cross-validation-->rfe-2
+    cross-validation-->rfe-3
+    subgraph rfe-1[RFE 1]
+    direction TB
+    f14[4 Features]
+    f13[3 Features]
+    f12[2 Features]
+    f11[1 Features]
+    f14-->f13-->f12-->f11
+    style f13 fill:#ccea84
+    end
+    subgraph rfe-2[RFE 2]
+    direction TB
+    f24[4 Features]
+    f23[3 Features]
+    f22[2 Features]
+    f21[1 Features]
+    f24-->f23-->f22-->f21
+    style f23 fill:#ccea84
+    end
+    subgraph rfe-3[RFE 3]
+    direction TB
+    f34[4 Features]
+    f33[3 Features]
+    f32[2 Features]
+    f31[1 Features]
+    f34-->f33-->f32-->f31
+    style f33 fill:#ccea84
+    end
+    all_obs[All Observations]
+    rfe-1-->all_obs
+    rfe-2-->all_obs
+    rfe-3-->all_obs
+    all_obs --> rfe
+    subgraph rfe[RFE]
+    direction TB
+    f54[4 Features]
+    f53[3 Features]
+    f54-->f53
+    style f53 fill:#8e6698
+    end
+
+
+
+
+Figure 5: Example of an RFE-CV. The optimal number of features is estimated with a 3-fold cross-validation. One RFE is executed with each train-test split (RFE 1 to RFE 3). The number of features with the best mean performance (green rectangles) is used as the size of the final feature set. A final RFE is performed on all observations. The algorithm stops when the optimal feature set size is reached (purple rectangle) and the optimized feature set is returned. +
+
+
+
+
+

We retrieve the RFE-CV optimizer. RFE-CV has almost the same control parameters as the RFE optimizer. The only difference is that no aggregation is needed.

+
+
optimizer = fs("rfecv",
+  n_features = 1,
+  feature_number = 1)
+
+

The chosen resampling strategy is used to estimate the optimal number of features. The 6-fold cross-validation results in 6 RFE runs. You can choose any other resampling strategy with multiple iterations. Let’s start the feature selection.

+
+
learner = lrn("classif.svm",
+  type = "C-classification",
+  kernel = "linear",
+  predict_type = "prob")
+
+instance = fsi(
+  task = task,
+  learner = learner,
+  resampling = rsmp("cv", folds = 6),
+  measures = msr("classif.auc"),
+  terminator = trm("none"),
+  callback = clbk("mlr3fselect.svm_rfe"))
+
+optimizer$optimize(instance)
+
+
+
+
+ +
+
+Warning +
+
+
+

The performance of the optimal feature set is calculated on the complete data set and should not be reported as the performance of the final model. Estimate the performance of the final model with nested resampling.

+
+
+

We visualize the selection of the optimal number of features. Each point is the mean performance of the number of features. We achieved the best performance with 19 features.

+
+
+Code +
library(ggplot2)
+library(viridisLite)
+library(mlr3misc)
+
+data = as.data.table(instance$archive)[!is.na(iteration), ]
+aggr = data[, list("y" = mean(unlist(.SD))), by = "batch_nr", .SDcols = "classif.auc"]
+aggr[, batch_nr := 61 - batch_nr]
+
+data[, n:= map_int(importance, length)]
+
+ggplot(aggr, aes(x = batch_nr, y = y)) +
+  geom_line(
+    color = viridis(1, begin = 0.5),
+    linewidth = 1) +
+  geom_point(
+    fill = viridis(1, begin = 0.5),
+    shape = 21,
+    size = 3,
+    stroke = 0.5,
+    alpha = 0.8) +
+  geom_vline(
+    xintercept = aggr[y == max(y)]$batch_nr,
+    colour = viridis(1, begin = 0.33),
+    linetype = 3
+  ) +
+  xlab("Number of Features") +
+  ylab("Mean AUC") +
+  scale_x_reverse() +
+  theme_minimal()
+
+
+
+
+
+ +
+
+Figure 6: Estimation of the optimal number of features. The best mean performance is achieved with 19 features (blue line). +
+
+
+
+
+

The archive contains the extra column "iteration" that indicates in which resampling iteration the feature set was evaluated. The feature subsets of the final RFE run have no value in the "iteration" column because they were evaluated on the complete data set.

+
+
as.data.table(instance$archive)[, list(features, classif.auc, iteration, importance)]
+
+
                       features classif.auc iteration                                                      importance
+  1: V1,V10,V11,V12,V13,V14,...   0.8782895         1       2.864018,1.532774,1.408485,1.399930,1.326165,1.167745,...
+  2: V1,V10,V11,V12,V13,V14,...   0.7026144         2       2.056442,1.706077,1.258703,1.191762,1.190752,1.178514,...
+  3: V1,V10,V11,V12,V13,V14,...   0.8790850         3       1.950412,1.887710,1.820891,1.616219,1.231928,1.138675,...
+  4: V1,V10,V11,V12,V13,V14,...   0.8125000         4 2.6958580,1.5623759,1.4990138,1.3902109,0.9385757,0.9232132,...
+  5: V1,V10,V11,V12,V13,V14,...   0.8807018         5       2.487483,1.470778,1.356517,1.033764,0.635383,0.575074,...
+ ---                                                                                                                 
+398:  V1,V11,V12,V16,V23,V3,...   0.9605275        NA 2.0089739,1.1047492,1.0011253,0.6602411,0.6015470,0.5431803,...
+399:  V1,V12,V16,V23,V3,V30,...   0.9595988        NA 1.8337471,1.1937962,0.9853467,0.7751384,0.7296726,0.6222569,...
+400:  V1,V12,V16,V23,V3,V30,...   0.9589486        NA 1.8824952,1.2468164,1.0106654,0.8090618,0.6983925,0.6568389,...
+401:  V1,V12,V16,V23,V3,V30,...   0.9559766        NA 2.3872902,0.9094028,0.8809098,0.8277941,0.7841591,0.7792772,...
+402:  V1,V12,V16,V23,V3,V30,...   0.9521687        NA 1.9485133,1.1482257,1.1098823,0.9591012,0.8234140,0.8118616,...
+
+
+
+
+

Final Model

+

The learner we use to make predictions on new data is called the final model. The final model is trained with the optimal feature set on the full data set. The optimal set consists of 19 features and is stored in instance$result_feature_set. We subset the task to the optimal feature set and train the learner.

+
+
task$select(instance$result_feature_set)
+learner$train(task)
+
+

The trained model can now be used to predict new, external data.

+
+
+

Conclusion

+

The RFE algorithm is a valuable feature selection method, especially for high-dimensional datasets with only a few observations. The numerous settings of the algorithm in mlr3 make it possible to apply it to many datasets and learners. If you want to know more about feature selection in general, we recommend having a look at our book.

+ + + +
+ +

References

+
+Guyon, Isabelle, Jason Weston, Stephen Barnhill, and Vladimir Vapnik. 2002. “Gene Selection for Cancer Classification Using Support Vector Machines.” Machine Learning 46 (1): 389–422. https://doi.org/10.1023/A:1012487302797. +
+
+Kuhn, Max. 2008. “Building Predictive Models in r Using the Caret Package.” Journal of Statistical Software 28 (November): 1–26. https://doi.org/10.18637/jss.v028.i05. +
+
+Pedregosa, Fabian, Gaël Varoquaux, Alexandre Gramfort, Vincent Michel, Bertrand Thirion, Olivier Grisel, Mathieu Blondel, et al. 2011. “Scikit-Learn: Machine Learning in Python.” Journal of Machine Learning Research 12 (85): 2825–30. http://jmlr.org/papers/v12/pedregosa11a.html. +
+
]]>
+ feature selection + classification + https://mlr-org.com/gallery/optimization/2023-02-07-recursive-feature-elimination/ + Tue, 07 Feb 2023 00:00:00 GMT + +
+ + Shadow Variable Search on the Pima Indian Diabetes Data Set + Marc Becker + Sebastian Fischer + https://mlr-org.com/gallery/optimization/2023-02-01-shadow-variable-search/ + +

Scope

+

Feature selection is the process of finding an optimal set of features to improve the performance, interpretability and robustness of machine learning algorithms. In this article, we introduce the Shadow Variable Search algorithm which is a wrapper method for feature selection. Wrapper methods iteratively add features to the model that optimize a performance measure. As an example, we will search for the optimal set of features for a support vector machine on the Pima Indian Diabetes data set. We assume that you are already familiar with the basic building blocks of the mlr3 ecosystem. If you are new to feature selection, we recommend reading the feature selection chapter of the mlr3book first. Some knowledge about mlr3pipelines is beneficial but not necessary to understand the example.

+ + +
+

Task and Learner

+

The objective of the Pima Indian Diabetes data set is to predict whether a person has diabetes or not. The data set includes 768 patients with 8 measurements (see Figure 1).

+
+
task = tsk("pima")
+
+
+
+Code +
library(ggplot2)
+library(data.table)
+
+data = melt(as.data.table(task), id.vars = task$target_names, measure.vars = task$feature_names)
+
+ggplot(data, aes(x = value, fill = diabetes)) +
+  geom_density(alpha = 0.5) +
+  facet_wrap(~ variable, ncol = 8, scales = "free") +
+  scale_fill_viridis_d(end = 0.8) +
+  theme_minimal() +
+  theme(axis.title.x = element_blank())
+
+
+
+
+
+ +
+
+Figure 1: Distribution of the features in the Pima Indian Diabetes data set. +
+
+
+
+
+

The data set contains missing values.

+
+
task$missings()
+
+
diabetes      age  glucose  insulin     mass pedigree pregnant pressure  triceps 
+       0        0        5      374       11        0        0       35      227 
+
+
+

Support vector machines cannot handle missing values. We impute the missing values with the histogram imputation method.

+
+
learner = po("imputehist") %>>% lrn("classif.svm", predict_type = "prob")
+
+
+
+

Feature Selection

+

Now we define the feature selection problem by using the fsi() function that constructs an FSelectInstanceSingleCrit. In addition to the task and learner, we have to select a resampling strategy and performance measure to determine how the performance of a feature subset is evaluated. We pass the "none" terminator because the shadow variable search algorithm terminates by itself.

+
+
instance = fsi(
+  task = task,
+  learner = learner,
+  resampling = rsmp("cv", folds = 3),
+  measures = msr("classif.auc"),
+  terminator = trm("none")
+)
+
+

We are now ready to start the shadow variable search. To do this, we simply pass the instance to the $optimize() method of the optimizer.

+
+
optimizer$optimize(instance)
+
+
    age glucose insulin mass pedigree pregnant pressure triceps                  features classif.auc
+1: TRUE    TRUE   FALSE TRUE     TRUE    FALSE    FALSE   FALSE age,glucose,mass,pedigree    0.835165
+
+
+

The optimizer returns the best feature set and the corresponding estimated performance.

+

Figure 2 shows the optimization path of the feature selection. The feature glucose was selected first and in the following iterations age, mass and pedigree. Then a shadow variable was selected and the feature selection was terminated.

+
+
+Code +
library(data.table)
+library(ggplot2)
+library(mlr3misc)
+library(viridisLite)
+
+data = as.data.table(instance$archive)[order(-classif.auc), head(.SD, 1), by = batch_nr][order(batch_nr)]
+data[, features := map_chr(features, str_collapse)]
+data[, batch_nr := as.character(batch_nr)]
+
+ggplot(data, aes(x = batch_nr, y = classif.auc)) +
+  geom_bar(
+    stat = "identity",
+    width = 0.5,
+    fill = viridis(1, begin = 0.5),
+    alpha = 0.8) +
+  geom_text(
+    data = data,
+    mapping = aes(x = batch_nr, y = 0, label = features),
+    hjust = 0,
+    nudge_y = 0.05,
+    color = "white",
+    size = 5
+    ) +
+  coord_flip() +
+  xlab("Iteration") +
+  theme_minimal()
+
+
+
+
+
+ +
+
+Figure 2: Optimization path of the shadow variable search. +
+
+
+
+
+

The archive contains all evaluated feature sets. We can see that each feature has a corresponding shadow variable. We only show the variables age, glucose and insulin and their shadow variables here.

+
+
as.data.table(instance$archive)[, .(age, glucose, insulin, permuted__age, permuted__glucose, permuted__insulin, classif.auc)]
+
+
      age glucose insulin permuted__age permuted__glucose permuted__insulin classif.auc
+ 1:  TRUE   FALSE   FALSE         FALSE             FALSE             FALSE   0.6437052
+ 2: FALSE    TRUE   FALSE         FALSE             FALSE             FALSE   0.7598155
+ 3: FALSE   FALSE    TRUE         FALSE             FALSE             FALSE   0.4900280
+ 4: FALSE   FALSE   FALSE         FALSE             FALSE             FALSE   0.6424026
+ 5: FALSE   FALSE   FALSE         FALSE             FALSE             FALSE   0.5690107
+---                                                                                    
+54:  TRUE    TRUE   FALSE         FALSE             FALSE             FALSE   0.8266713
+55:  TRUE    TRUE   FALSE         FALSE             FALSE             FALSE   0.8063568
+56:  TRUE    TRUE   FALSE         FALSE             FALSE             FALSE   0.8244232
+57:  TRUE    TRUE   FALSE         FALSE             FALSE             FALSE   0.8234605
+58:  TRUE    TRUE   FALSE         FALSE             FALSE             FALSE   0.8164784
+
+
+
+
+

Final Model

+

The learner we use to make predictions on new data is called the final model. The final model is trained with the optimal feature set on the full data set. We subset the task to the optimal feature set and train the learner.

+
+
task$select(instance$result_feature_set)
+learner$train(task)
+
+

The trained model can now be used to predict new, external data.

+
+
+

Conclusion

+

The shadow variable search is a fast feature selection method that is easy to use. More information on the theoretical background can be found in Wu, Boos, and Stefanski (2007) and Thomas et al. (2017). If you want to know more about feature selection in general, we recommend having a look at our book.

+ + + +
+ +

References

+
+Thomas, Janek, Tobias Hepp, Andreas Mayr, and Bernd Bischl. 2017. “Probing for Sparse and Fast Variable Selection with Model-Based Boosting.” Computational and Mathematical Methods in Medicine 2017 (July): e1421409. https://doi.org/10.1155/2017/1421409. +
+
+Wu, Yujun, Dennis D Boos, and Leonard A Stefanski. 2007. “Controlling Variable Selection by the Addition of Pseudovariables.” Journal of the American Statistical Association 102 (477): 235–43. https://doi.org/10.1198/016214506000000843. +
+
]]>
+ feature selection + classification + https://mlr-org.com/gallery/optimization/2023-02-01-shadow-variable-search/ + Wed, 01 Feb 2023 00:00:00 GMT + +
+ + Default Hyperparameter Configuration + Marc Becker + https://mlr-org.com/gallery/optimization/2023-01-31-default-configuration/ + +

Scope

+

The predictive performance of modern machine learning algorithms is highly dependent on the choice of their hyperparameter configuration. Options for setting hyperparameters are tuning, manual selection by the user, and using the default configuration of the algorithm. The default configurations are chosen to work with a wide range of data sets but they usually do not achieve the best predictive performance. When tuning a learner in mlr3, we can run the default configuration as a baseline. Seeing how well it performs will tell us whether tuning pays off. If the optimized configurations perform worse, we could expand the search space or try a different optimization algorithm. Of course, it could also be that tuning on the given data set is simply not worth it.

+

Probst, Boulesteix, and Bischl (2019) studied the tunability of machine learning algorithms. They found that the tunability of algorithms varies widely. Algorithms like glmnet and XGBoost are highly tunable, while algorithms like random forests work well with their default configuration. The highly tunable algorithms should thus beat their baselines more easily with optimized hyperparameters. In this article, we will tune the hyperparameters of a random forest and compare the performance of the default configuration with the optimized configurations.

+ +
+

Example

+

We tune the hyperparameters of the ranger learner on the spam data set. The search space is taken from Bischl et al. (2021).

+
+
library(mlr3verse)
+
+learner = lrn("classif.ranger",
+  mtry.ratio      = to_tune(0, 1),
+  replace         = to_tune(),
+  sample.fraction = to_tune(1e-1, 1),
+  num.trees       = to_tune(1, 2000)
+)
+
+

When creating the tuning instance, we set evaluate_default = TRUE to test the default hyperparameter configuration. The default configuration is evaluated in the first batch of the tuning run. The other batches use the specified tuning method. In this example, they are randomly drawn configurations.

+
+
instance = tune(
+  tuner = tnr("random_search", batch_size = 5),
+  task = tsk("spam"),
+  learner = learner,
+  resampling = rsmp ("holdout"),
+  measures = msr("classif.ce"),
+  term_evals = 51,
+  evaluate_default = TRUE
+)
+
+

The default configuration is recorded in the first row of the archive. The other rows contain the results of the random search.

+
+
as.data.table(instance$archive)[, .(batch_nr, mtry.ratio, replace, sample.fraction, num.trees, classif.ce)]
+
+
    batch_nr  mtry.ratio replace sample.fraction num.trees classif.ce
+ 1:        1 0.122807018    TRUE       1.0000000       500 0.04954368
+ 2:        2 0.285388074    TRUE       0.1794772       204 0.06584094
+ 3:        2 0.097424099   FALSE       0.9475526      1441 0.04237288
+ 4:        2 0.008888587   FALSE       0.3216562      1868 0.08409387
+ 5:        2 0.335543330    TRUE       0.8122653       106 0.05345502
+---                                                                  
+47:       11 0.788995735   FALSE       0.3692454       344 0.06258149
+48:       11 0.459305038    TRUE       0.3153485      1354 0.06258149
+49:       11 0.220334408    TRUE       0.9357554       817 0.05345502
+50:       11 0.868385877    TRUE       0.6743246      1040 0.06127771
+51:       11 0.015417312   FALSE       0.5627943      1836 0.08213820
+
+
+

We plot the performances of the evaluated hyperparameter configurations. The blue line connects the best configuration of each batch. We see that the default configuration already performs well and the optimized configurations can not beat it.

+
+
library(mlr3viz)
+
+autoplot(instance, type = "performance")
+
+
+
+

+
+
+
+
+
+
+

Conlcusion

+

The time required to test the default configuration is negligible compared to the time required to run the hyperparameter optimization. It gives us a valuable indication of whether our tuning is properly configured. Running the default configuration as a baseline is a good practice that should be used in every tuning run.

+ + + +
+ +

References

+
+Bischl, Bernd, Martin Binder, Michel Lang, Tobias Pielok, Jakob Richter, Stefan Coors, Janek Thomas, et al. 2021. “Hyperparameter Optimization: Foundations, Algorithms, Best Practices and Open Challenges.” arXiv:2107.05847 [Cs, Stat], July. http://arxiv.org/abs/2107.05847. +
+
+Probst, Philipp, Anne-Laure Boulesteix, and Bernd Bischl. 2019. “Tunability: Importance of Hyperparameters of Machine Learning Algorithms.” Journal of Machine Learning Research 20 (53): 1–32. http://jmlr.org/papers/v20/18-444.html. +
+
]]>
+ tuning + classification + https://mlr-org.com/gallery/optimization/2023-01-31-default-configuration/ + Tue, 31 Jan 2023 00:00:00 GMT + +
+ + Hyperband Series - Data Set Subsampling + Marc Becker + Sebastian Fischer + https://mlr-org.com/gallery/optimization/2023-01-16-hyperband-subsampling/ + +

Scope

+

We continue working with the Hyperband optimization algorithm (Li et al. 2018). The previous post used the number of boosting iterations of an XGBoost model as the resource. However, Hyperband is not limited to machine learning algorithms that are trained iteratively. The resource can also be the number of features, the training time of a model, or the size of the training data set. In this post, we will tune a support vector machine and use the size of the training data set as the fidelity parameter. The time to train a support vector machine and the performance increases with the size of the data set. This makes the data set size a suitable fidelity parameter for Hyperband. This is the second part of the Hyperband series. The first part can be found here Hyperband Series - Iterative Training. If you don’t know much about Hyperband, check out the first post which explains the algorithm in detail. We assume that you are already familiar with tuning in the mlr3 ecosystem. If not, you should start with the book chapter on optimization or the Hyperparameter Optimization on the Palmer Penguins Data Set post. A little knowledge about mlr3pipelines is beneficial but not necessary to understand the example.

+ +
+

Hyperparameter Optimization

+

In this post, we will optimize the hyperparameters of the support vector machine on the Sonar data set. We begin by constructing a classification machine by setting type to "C-classification".

+
+
library("mlr3verse")
+
+learner = lrn("classif.svm", id = "svm", type = "C-classification")
+
+

The mlr3pipelines package features a PipeOp for subsampling.

+
+
po("subsample")
+
+
PipeOp: <subsample> (not trained)
+values: <frac=0.6321, stratify=FALSE, replace=FALSE>
+Input channels <name [train type, predict type]>:
+  input [Task,Task]
+Output channels <name [train type, predict type]>:
+  output [Task,Task]
+
+
+

The PipeOp controls the size of the training data set with the frac parameter. We connect the PipeOp with the learner and get a GraphLearner.

+
+
graph_learner = as_learner(
+  po("subsample") %>>%
+  learner
+)
+
+

The graph learner subsamples and then fits a support vector machine on the data subset. The parameter set of the graph learner is a combination of the parameter sets of the PipeOp and learner.

+
+
as.data.table(graph_learner$param_set)[, .(id, lower, upper, levels)]
+
+
                    id lower upper                             levels
+ 1:     subsample.frac     0   Inf                                   
+ 2: subsample.stratify    NA    NA                         TRUE,FALSE
+ 3:  subsample.replace    NA    NA                         TRUE,FALSE
+ 4:      svm.cachesize  -Inf   Inf                                   
+ 5:  svm.class.weights    NA    NA                                   
+---                                                                  
+15:             svm.nu  -Inf   Inf                                   
+16:          svm.scale    NA    NA                                   
+17:      svm.shrinking    NA    NA                         TRUE,FALSE
+18:      svm.tolerance     0   Inf                                   
+19:           svm.type    NA    NA C-classification,nu-classification
+
+
+

Next, we create the search space. We use TuneToken to mark which hyperparameters should be tuned. We have to prefix the hyperparameters with the id of the PipeOps. The subsample.frac is the fidelity parameter that must be tagged with "budget" in the search space. The data set size is increased from 3.7% to 100%. For the other hyperparameters, we took the search space for support vector machines from the Kuehn et al. (2018) article. This search space works for a wide range of data sets.

+
+
graph_learner$param_set$set_values(
+  subsample.frac  = to_tune(p_dbl(3^-3, 1, tags = "budget")),
+  svm.kernel      = to_tune(c("linear", "polynomial", "radial")),
+  svm.cost        = to_tune(1e-4, 1e3, logscale = TRUE),
+  svm.gamma       = to_tune(1e-4, 1e3, logscale = TRUE),
+  svm.tolerance   = to_tune(1e-4, 2, logscale = TRUE),
+  svm.degree      = to_tune(2, 5)
+)
+
+

Support vector machines often crash or never finish the training with certain hyperparameter configurations. We set a timeout of 30 seconds and a fallback learner to handle these cases.

+
+
graph_learner$encapsulate = c(train = "evaluate", predict = "evaluate")
+graph_learner$timeout = c(train = 30, predict = 30)
+graph_learner$fallback = lrn("classif.featureless")
+
+

Let’s create the tuning instance. We use the "none" terminator because Hyperband controls the termination itself.

+
+
instance = ti(
+  task = tsk("sonar"),
+  learner = graph_learner,
+  resampling = rsmp("cv", folds = 3),
+  measures = msr("classif.ce"),
+  terminator = trm("none")
+)
+instance
+
+
<TuningInstanceSingleCrit>
+* State:  Not optimized
+* Objective: <ObjectiveTuning:subsample.svm_on_sonar>
+* Search Space:
+               id    class       lower     upper nlevels
+1: subsample.frac ParamDbl  0.03703704 1.0000000     Inf
+2:       svm.cost ParamDbl -9.21034037 6.9077553     Inf
+3:     svm.degree ParamInt  2.00000000 5.0000000       4
+4:      svm.gamma ParamDbl -9.21034037 6.9077553     Inf
+5:     svm.kernel ParamFct          NA        NA       3
+6:  svm.tolerance ParamDbl -9.21034037 0.6931472     Inf
+* Terminator: <TerminatorNone>
+
+
+

We load the Hyperband tuner and set eta = 3.

+
+
library("mlr3hyperband")
+
+tuner = tnr("hyperband", eta = 3)
+
+

Using eta = 3 and a lower bound of 3.7% for the data set size, results in the following schedule. Configurations with the same data set size are evaluated in parallel.

+
+
+
+ +
+
+

Now we are ready to start the tuning.

+
+
tuner$optimize(instance)
+
+

The best model is a support vector machine with a polynomial kernel.

+
+
instance$result[, .(subsample.frac, svm.cost, svm.degree, svm.gamma, svm.kernel, svm.tolerance, classif.ce)]
+
+
   subsample.frac svm.cost svm.degree svm.gamma svm.kernel svm.tolerance classif.ce
+1:              1 1.871535          3  -2.60663 polynomial     -4.573951  0.1491373
+
+
+

The archive contains all evaluated configurations. We look at the 8 configurations that were evaluated on the complete data set. The configuration with the best classification error on the full data set was sampled in bracket 2. The classification error was estimated to be 26% on 33% of the data set and increased to 19% on the full data set (see green line in Figure 1).

+
+
+
+
+
+ +
+
+Figure 1: Optimization path of the 8 configurations evaluated on the complete data set. +
+
+
+
+
+
+
+

Conclusion

+

Using the data set size as the budget parameter in Hyperband allows the tuning of machine learning models that are not trained iteratively. We have tried to keep the runtime of the example low. For your optimization, you should use cross-validation and run multiple iterations of Hyperband.

+
+
+ + + + +
+ +

References

+
+Kuehn, Daniel, Philipp Probst, Janek Thomas, and Bernd Bischl. 2018. “Automatic Exploration of Machine Learning Experiments on OpenML.” https://arxiv.org/abs/1806.10961. +
+
+Li, Lisha, Kevin Jamieson, Giulia DeSalvo, Afshin Rostamizadeh, and Ameet Talwalkar. 2018. “Hyperband: A Novel Bandit-Based Approach to Hyperparameter Optimization.” Journal of Machine Learning Research 18 (185): 1–52. https://jmlr.org/papers/v18/16-558.html. +
+
]]>
+ tuning + classification + https://mlr-org.com/gallery/optimization/2023-01-16-hyperband-subsampling/ + Mon, 16 Jan 2023 00:00:00 GMT + +
+ + Hotstarting + Marc Becker + Sebastian Fischer + https://mlr-org.com/gallery/optimization/2023-01-16-hotstart/ + +

Scope

+

Hotstarting a learner resumes the training from an already fitted model. An example would be to train an already fit XGBoost model for an additional 500 boosting iterations. In mlr3, we call this process Hotstarting, where a learner has access to a cache of already trained models which is called a mlr3::HoststartStack We distinguish between forward and backward hotstarting. We start this post with backward hotstarting and then talk about the less efficient forward hotstarting.

+ +
+

Backward Hotstarting

+

In this example, we optimize the hyperparameters of a random forest and use hotstarting to reduce the runtime. Hotstarting a random forest backwards is very simple. The model remains unchanged and only a subset of the trees is used for prediction i.e. a new model is not fitted. For example, a random forest is trained with 1000 trees and a specific hyperparameter configuration. If another random forest with 500 trees but with the same hyperparameter configuration has to be trained, the model with 1000 trees is copied and only 500 trees are used for prediction.

+

We load the ranger learner and set the search space from the Bischl et al. (2021) article.

+
+
library(mlr3verse)
+
+learner = lrn("classif.ranger",
+  mtry.ratio      = to_tune(0, 1),
+  replace         = to_tune(),
+  sample.fraction = to_tune(1e-1, 1),
+  num.trees       = to_tune(1, 2000)
+)
+
+

We activate hotstarting with the allow_hotstart option. When running a grid search with hotstarting, the grid is sorted by the hot start parameter. This means the models with 2000 trees are trained first. The models with less than 2000 trees hot start on the 2000 trees models which allows the training to be completed immediately.

+
+
instance = tune(
+  tuner = tnr("grid_search", resolution = 5, batch_size = 5),
+  task = tsk("spam"),
+  learner = learner,
+  resampling = rsmp("holdout"),
+  measure = msr("classif.ce"),
+  allow_hotstart = TRUE
+)
+
+

For comparison, we perform the same tuning without hotstarting.

+
+
instance_2 = tune(
+  tuner = tnr("grid_search", resolution = 5, batch_size = 5),
+  task = tsk("spam"),
+  learner = learner,
+  resampling = rsmp("holdout"),
+  measure = msr("classif.ce"),
+  allow_hotstart = FALSE
+)
+
+

We plot the time of completion of each batch (see Figure 1). Each batch includes 5 configurations. We can see that tuning with hotstarting is slower at first. As soon as all models are fitted with 2000 trees, the tuning runs much faster and overtakes the tuning without hotstarting.

+
+
+
+
+
+ +
+
+Figure 1: Time of completion of each batch with and without hotstarting. +
+
+
+
+
+
+
+

Forward Hotstarting

+

Forward hotstarting is currently only supported by XGBoost. However, we have observed that hotstarting only provides a speed advantage for very large datasets and models with more than 5000 boosting rounds. The reason is that copying the models from the main process to the workers is a major bottleneck. The parallelization package future copies the models sequentially to the workers. Consequently, it takes a long time until the last worker can even start. Moreover, copying itself consumes a lot of time, and copying the model back from the worker blocks the main process again. During the development process, we overestimated the speed benefits of hotstarting and underestimated the overhead of parallelization. We can therefore only advise against using forward hotstarting during tuning. It is much more efficient to use the internal early-stopping mechanism of XGBoost. This eliminates the need to copy models to the worker. See the gallery post on early stopping for an example. We might improve the efficiency of the hotstarting mechanism in the future, if there are convincing use cases.

+
+
+

Manual Hotstarting

+

Nevertheless, forward hotstarting can be useful without parallelization. If you have an already trained model and want to add more boosting iteration to it. In this example, the learner_5000 is the already trained model. We create a new learner with the same hyperparameters but double the number of boosting iteration. To activate hotstarting, we create a HotstartStack and copy it to the $hotstart_stack slot of the new learner.

+
+
task = tsk("spam")
+
+learner_5000 = lrn("classif.xgboost", nrounds = 5000, eta = 0.1)
+learner_5000$train(task)
+
+learner_10000 = lrn("classif.xgboost", nrounds = 10000, eta = 0.1)
+learner_10000$hotstart_stack = HotstartStack$new(learner_5000)
+learner_10000$train(task)
+
+

Training the initial model took 59.885 seconds.

+
+
learner_5000$state$train_time
+
+
[1] 59.885
+
+
+

Adding 5000 boosting rounds took 46.837 seconds.

+
+
learner_10000$state$train_time - learner_5000$state$train_time
+
+
[1] 46.837
+
+
+

Training the model from the beginning would have taken about two minutes. This means, without parallelization, we get the expected speed advantage.

+
+
+

Conclusion

+

We have seen how mlr3 enables to reduce the training time, by building on a hotstart stack of already trained learners. One has to be careful, however, when using forward hotstarting during tuning because of the high parallelization overhead that arises from copying the models between the processes. If a model has an internal early stopping implementation, it should usually be relied upon instead of using the mlr3 hotstarting mechanism. However, manual forward hotstarting can be helpful in some situations when we do not want to train a large model from the beginning.

+ + + +
+ +

References

+
+Bischl, Bernd, Martin Binder, Michel Lang, Tobias Pielok, Jakob Richter, Stefan Coors, Janek Thomas, et al. 2021. “Hyperparameter Optimization: Foundations, Algorithms, Best Practices and Open Challenges.” arXiv:2107.05847 [Cs, Stat], July. http://arxiv.org/abs/2107.05847. +
+
]]>
+ tuning + classification + https://mlr-org.com/gallery/optimization/2023-01-16-hotstart/ + Mon, 16 Jan 2023 00:00:00 GMT + +
+ + Hyperband Series - Iterative Training + Marc Becker + Sebastian Fischer + https://mlr-org.com/gallery/optimization/2023-01-15-hyperband-xgboost/ + +

Scope

+

Increasingly large data sets and search spaces make hyperparameter optimization a time-consuming task. Hyperband (Li et al. 2018) solves this by approximating the performance of a configuration on a simplified version of the problem such as a small subset of the training data, with just a few training epochs in a neural network, or with only a small number of iterations in a gradient-boosting model. After starting randomly sampled configurations, Hyperband iteratively allocates more resources to promising configurations and terminates low-performing ones. This type of optimization is called multi-fidelity optimization. The fidelity parameter is part of the search space and controls the tradeoff between the runtime and accuracy of the performance approximation. In this post, we will optimize XGBoost and use the number of boosting iterations as the fidelity parameter. This means Hyperband will allocate more boosting iterations to well-performing configurations. The number of boosting iterations increases the time to train a model and improves the performance until the model is overfitting to the training data. It is therefore a suitable fidelity parameter. We assume that you are already familiar with tuning in the mlr3 ecosystem. If not, you should start with the book chapter on optimization or the Hyperparameter Optimization on the Palmer Penguins Data Set post. This is the first part of the Hyperband series. The second part can be found here Hyperband Series - Data Set Subsampling.

+ +
+

Hyperband

+

Hyperband is an advancement of the Successive Halving algorithm by Jamieson and Talwalkar (2016). Successive Halving is initialized with the number of starting configurations , the proportion of configurations discarded in each stage , and the minimum and maximum budget of a single evaluation. The algorithm starts by sampling random configurations and allocating the minimum budget to them. The configurations are evaluated and of the worst-performing configurations are discarded. The remaining configurations are promoted to the next stage and evaluated on a larger budget. This continues until one or more configurations are evaluated on the maximum budget and the best performing configuration is selected. The number of stages is calculated so that each stage consumes approximately the same budget. This sometimes results in the minimum budget having to be slightly adjusted by the algorithm. Successive Halving has the disadvantage that is not clear whether we should choose a large and try many configurations on a small budget or choose a small and train more configurations on the full budget.

+

Hyperband solves this problem by running Successive Halving with different numbers of stating configurations. The algorithm is initialized with the same parameters as Successive Halving but without . Each run of Successive Halving is called a bracket and starts with a different budget . A smaller starting budget means that more configurations can be tried out. The most explorative bracket allocated the minimum budget . The next bracket increases the starting budget by a factor of . In each bracket, the starting budget increases further until the last bracket essentially performs a random search with the full budget . The number of brackets is calculated with . Under the condition that increases by with each bracket, sometimes has to be adjusted slightly in order not to use more than resources in the last bracket. The number of configurations in the base stages is calculated so that each bracket uses approximately the same amount of budget. The following table shows a full run of the Hyperband algorithm. The bracket is the most explorative bracket and performance a random search on the full budget.

+
+
+
+
+
+ +
+
+Figure 1: Hyperband schedule with , and +
+
+
+
+

The Hyperband implementation in mlr3hyperband evaluates configurations with the same budget in parallel. This results in all brackets finishing at approximately the same time. The colors in Figure 1 indicate batches that are evaluated in parallel.

+
+
+

Hyperparameter Optimization

+

In this practical example, we will optimize the hyperparameters of XGBoost on the Spam data set. We begin by loading the XGBoost learner..

+
+
library("mlr3verse")
+
+learner = lrn("classif.xgboost")
+
+

The next thing we do is define the search space. The nrounds parameter controls the number of boosting iterations. We set a range from 16 to 128 boosting iterations. This is used as and by the Hyperband algorithm. We need to tag the parameter with "budget" to identify it as a fidelity parameter. For the other hyperparameters, we take the search space for XGBoost from the Bischl et al. (2021) article. This search space works for a wide range of data sets.

+
+
learner$param_set$set_values(
+  nrounds           = to_tune(p_int(16, 128, tags = "budget")),
+  eta               = to_tune(1e-4, 1, logscale = TRUE),
+  max_depth         = to_tune(1, 20),
+  colsample_bytree  = to_tune(1e-1, 1),
+  colsample_bylevel = to_tune(1e-1, 1),
+  lambda            = to_tune(1e-3, 1e3, logscale = TRUE),
+  alpha             = to_tune(1e-3, 1e3, logscale = TRUE),
+  subsample         = to_tune(1e-1, 1)
+)
+
+

We construct the tuning instance. We use the "none" terminator because Hyperband terminates itself when all brackets are evaluated.

+
+
instance = ti(
+  task = tsk("spam"),
+  learner = learner,
+  resampling = rsmp("holdout"),
+  measures = msr("classif.ce"),
+  terminator = trm("none")
+)
+instance
+
+
<TuningInstanceSingleCrit>
+* State:  Not optimized
+* Objective: <ObjectiveTuning:classif.xgboost_on_spam>
+* Search Space:
+                  id    class     lower      upper nlevels
+              <char>   <char>     <num>      <num>   <num>
+1:           nrounds ParamInt 16.000000 128.000000     113
+2:               eta ParamDbl -9.210340   0.000000     Inf
+3:         max_depth ParamInt  1.000000  20.000000      20
+4:  colsample_bytree ParamDbl  0.100000   1.000000     Inf
+5: colsample_bylevel ParamDbl  0.100000   1.000000     Inf
+6:            lambda ParamDbl -6.907755   6.907755     Inf
+7:             alpha ParamDbl -6.907755   6.907755     Inf
+8:         subsample ParamDbl  0.100000   1.000000     Inf
+* Terminator: <TerminatorNone>
+
+
+

We load the Hyperband tuner and set eta = 2. Hyperband can start from the beginning when the last bracket is evaluated. We control the number of Hyperband runs with the repetition argument. The setting repetition = Inf is useful when a terminator should stop the optimization.

+
+
library("mlr3hyperband")
+
+tuner = tnr("hyperband", eta = 2, repetitions = 1)
+
+

The Hyperband implementation in mlr3hyperband evaluates configurations with the same budget in parallel. This results in all brackets finishing at approximately the same time. You can think of it as going diagonally through Figure 1. Using eta = 2 and a range from 16 to 128 boosting iterations results in the following schedule.

+
+
+
+ +
+
+

Now we are ready to start the tuning.

+
+
tuner$optimize(instance)
+
+

The result of a run is the configuration with the best performance. This does not necessarily have to be a configuration evaluated with the highest budget since we can overfit the data with too many boosting iterations.

+
+
instance$result[, .(nrounds, eta, max_depth, colsample_bytree, colsample_bylevel, lambda, alpha, subsample)]
+
+
   nrounds       eta max_depth colsample_bytree colsample_bylevel    lambda     alpha subsample
+     <num>     <num>     <int>            <num>             <num>     <num>     <num>     <num>
+1:     128 -1.985313         8        0.4828647         0.3001509 -3.816118 -4.998944 0.4464856
+
+
+

The archive of a Hyperband run has the additional columns "bracket" and "stage".

+
+
as.data.table(instance$archive)[, .(bracket, stage, classif.ce, eta, max_depth, colsample_bytree)]
+
+
    bracket stage classif.ce        eta max_depth colsample_bytree
+      <int> <num>      <num>      <num>     <int>            <num>
+ 1:       3     0 0.09061278 -3.6110452        20        0.2671318
+ 2:       3     0 0.06388527 -1.9853130         8        0.4828647
+ 3:       3     0 0.11147327 -2.8428844         3        0.3152709
+ 4:       3     0 0.07301173 -3.9228523        19        0.5369803
+ 5:       3     0 0.07953064 -3.6486183        17        0.2039727
+---                                                               
+31:       0     0 0.06258149 -1.8578637         9        0.7343156
+32:       3     3 0.03976532 -1.9853130         8        0.4828647
+33:       2     2 0.03976532 -0.9898459         4        0.2534038
+34:       1     1 0.05345502 -2.5345314        13        0.5260946
+35:       1     1 0.06714472 -8.5597326        16        0.9890136
+
+
+
+
+

Conclusion

+

The handling of Hyperband in mlr3tuning is very similar to that of other tuners. We only have to select an additional fidelity parameter and tag it with "budget". We have tried to keep the runtime of the example low. For your optimization, you should use cross-validation and increase the maximum number of boosting rounds. The Bischl et al. (2021) search space suggests 5000 boosting rounds. Check out our next post on Hyperband which uses the size of the training data set as the fidelity parameter.

+ + + +
+ +

References

+
+Bischl, Bernd, Martin Binder, Michel Lang, Tobias Pielok, Jakob Richter, Stefan Coors, Janek Thomas, et al. 2021. “Hyperparameter Optimization: Foundations, Algorithms, Best Practices and Open Challenges.” arXiv:2107.05847 [Cs, Stat], July. http://arxiv.org/abs/2107.05847. +
+
+Jamieson, Kevin, and Ameet Talwalkar. 2016. “Non-Stochastic Best Arm Identification and Hyperparameter Optimization.” In Proceedings of the 19th International Conference on Artificial Intelligence and Statistics, edited by Arthur Gretton and Christian C. Robert, 51:240–48. Proceedings of Machine Learning Research. Cadiz, Spain: PMLR. http://proceedings.mlr.press/v51/jamieson16.html. +
+
+Li, Lisha, Kevin Jamieson, Giulia DeSalvo, Afshin Rostamizadeh, and Ameet Talwalkar. 2018. “Hyperband: A Novel Bandit-Based Approach to Hyperparameter Optimization.” Journal of Machine Learning Research 18 (185): 1–52. https://jmlr.org/papers/v18/16-558.html. +
+
]]>
+ tuning + classification + https://mlr-org.com/gallery/optimization/2023-01-15-hyperband-xgboost/ + Sun, 15 Jan 2023 00:00:00 GMT + +
+ + Visualization in mlr3 + Marc Becker + https://mlr-org.com/gallery/technical/2022-12-22-mlr3viz/ + +

Scope

+

We showcase the visualization functions of the mlr3 ecosystem. The mlr3viz package creates a plot for almost all mlr3 objects. This post displays all available plots with their reproducible code. We start with plots of the base mlr3 objects. This includes boxplots of tasks, dendrograms of cluster learners and ROC curves of predictions. After that, we tune a classification tree and visualize the results. Finally, we show visualizations for filters.

+
+
+
+ +
+
+Note +
+
+
+

This article will be updated whenever a new plot is available in mlr3viz.

+
+
+ +
+

Package

+

The mlr3viz package defines autoplot() functions to draw plots with ggplot2. Often there is more than one type of plot for an object. You can change the plot with the type argument. The help pages list all possible choices. The easiest way to access the help pages is via the pkgdown website. The plots use the viridis color pallet and the appearance is controlled with the theme argument. By default, the minimal theme is applied.

+
+
+

Tasks

+
+

Classification

+

We begin with plots of the classification task Palmer Penguins. We plot the class frequency of the target variable.

+
+
library(mlr3verse)
+library(mlr3viz)
+
+task = tsk("penguins")
+task$select(c("body_mass", "bill_length"))
+
+autoplot(task, type = "target")
+
+
+
+

+
+
+
+
+

The "duo" plot shows the distribution of multiple features.

+
+
autoplot(task, type = "duo")
+
+
+
+

+
+
+
+
+

The "pairs" plot shows the pairwise comparison of multiple features. The classes of the target variable are shown in different colors.

+
+
autoplot(task, type = "pairs")
+
+
+
+

+
+
+
+
+
+
+

Regression

+

Next, we plot the regression task mtcars. We create a boxplot of the target variable.

+
+
task = tsk("mtcars")
+task$select(c("am", "carb"))
+
+autoplot(task, type = "target")
+
+
+
+

+
+
+
+
+

The "pairs" plot shows the pairwise comparison of mutiple features and the target variable.

+
+
autoplot(task, type = "pairs")
+
+
+
+

+
+
+
+
+
+
+

Cluster

+

Finally, we plot the cluster task US Arrests. The "pairs" plot shows the pairwise comparison of mutiple features.

+
+
library(mlr3cluster)
+
+task = mlr_tasks$get("usarrests")
+
+autoplot(task, type = "pairs")
+
+
+
+

+
+
+
+
+
+
+
+

Learner

+
+

Classification

+

The "prediction" plot shows the decision boundary of a classification learner and the true class labels as points.

+
+
task = tsk("pima")$select(c("age", "pedigree"))
+learner = lrn("classif.rpart")
+learner$train(task)
+
+autoplot(learner, type = "prediction", task)
+
+
+
+

+
+
+
+
+

Using probabilities.

+
+
task = tsk("pima")$select(c("age", "pedigree"))
+learner = lrn("classif.rpart", predict_type = "prob")
+learner$train(task)
+
+autoplot(learner, type = "prediction", task)
+
+
+
+

+
+
+
+
+
+
+

Regression

+

The "prediction" plot of a regression learner illustrates the decision boundary and the true response as points.

+
+
task = tsk("boston_housing")$select("age")
+learner = lrn("regr.rpart")
+learner$train(task)
+
+autoplot(learner, type = "prediction", task)
+
+
+
+

+
+
+
+
+

When using two features, the response surface is plotted in the background.

+
+
task = tsk("boston_housing")$select(c("age", "rm"))
+learner = lrn("regr.rpart")
+learner$train(task)
+
+autoplot(learner, type = "prediction", task)
+
+
+
+

+
+
+
+
+
+
+

GLMNet

+

The classification and regression GLMNet learner is equipped with a plot function.

+
+
library(mlr3data)
+
+task = tsk("ilpd")
+task$select(setdiff(task$feature_names, "gender"))
+learner = lrn("classif.glmnet")
+learner$train(task)
+
+autoplot(learner, type = "ggfortify")
+
+
+
+

+
+
+
+
+
+
task = tsk("mtcars")
+learner = lrn("regr.glmnet")
+learner$train(task)
+
+autoplot(learner, type = "ggfortify")
+
+
+
+

+
+
+
+
+
+
+

Rpart

+

We plot a classification tree of the rpart package. We have to fit the learner with keep_model = TRUE to keep the model object.

+
+
task = tsk("penguins")
+learner = lrn("classif.rpart", keep_model = TRUE)
+learner$train(task)
+
+autoplot(learner, type = "ggparty")
+
+
+
+

+
+
+
+
+

We can also plot regression trees.

+
+
task = tsk("mtcars")
+learner = lrn("regr.rpart", keep_model = TRUE)
+learner$train(task)
+
+autoplot(learner, type = "ggparty")
+
+
+
+

+
+
+
+
+
+
+

ClustHierachical

+

The "dend" plot shows the result of the hierarchical clustering of the data.

+
+
library(mlr3cluster)
+
+task = tsk("usarrests")
+learner = lrn("clust.hclust")
+learner$train(task)
+
+autoplot(learner, type = "dend", task = task)
+
+
+
+

+
+
+
+
+

The "scree" type plots the number of clusters and the height.

+
+
autoplot(learner, type = "scree")
+
+
+
+

+
+
+
+
+
+
+
+

Prediction

+
+

Classification

+

We plot the predictions of a classification learner. The "stacked" plot shows the predicted and true class labels.

+
+
task = tsk("spam")
+learner = lrn("classif.rpart", predict_type = "prob")
+pred = learner$train(task)$predict(task)
+
+autoplot(pred, type = "stacked")
+
+
+
+

+
+
+
+
+

The ROC curve plots the true positive rate against the false positive rate at different thresholds.

+
+
autoplot(pred, type = "roc")
+
+
+
+

+
+
+
+
+

The precision-recall curve plots the precision against the recall at different thresholds.

+
+
autoplot(pred, type = "prc")
+
+
+
+

+
+
+
+
+

The "threshold" plot varies the threshold of a binary classification and plots against the resulting performance.

+
+
autoplot(pred, type = "threshold")
+
+
+
+

+
+
+
+
+
+
+

Regression

+

The predictions of a regression learner are often presented as a scatterplot of truth and predicted response.

+
+
task = tsk("boston_housing")
+learner = lrn("regr.rpart")
+pred = learner$train(task)$predict(task)
+
+autoplot(pred, type = "xy")
+
+
+
+

+
+
+
+
+

Additionally, we plot the response with the residuals.

+
+
autoplot(pred, type = "residual")
+
+
+
+

+
+
+
+
+

We can also plot the distribution of the residuals.

+
+
autoplot(pred, type = "histogram")
+
+
+
+

+
+
+
+
+
+
+

Cluster

+

The predictions of a cluster learner are often presented as a scatterplot of the data points colored by the cluster.

+
+
library(mlr3cluster)
+
+task = tsk("usarrests")
+learner = lrn("clust.kmeans", centers = 3)
+pred = learner$train(task)$predict(task)
+
+autoplot(pred, task, type = "scatter")
+
+
+
+

+
+
+
+
+

The "sil" plot shows the silhouette width of the clusters. The dashed line is the mean silhouette width.

+
+
autoplot(pred, task, type = "sil")
+
+
+
+

+
+
+
+
+

The "pca" plot shows the first two principal components of the data colored by the cluster.

+
+
autoplot(pred, task, type = "pca")
+
+
+
+

+
+
+
+
+
+
+
+

Resample Result

+
+

Classification

+

The "boxplot" shows the distribution of the performance measures.

+
+
task = tsk("sonar")
+learner = lrn("classif.rpart", predict_type = "prob")
+resampling = rsmp("cv")
+rr = resample(task, learner, resampling)
+
+autoplot(rr, type = "boxplot")
+
+
+
+

+
+
+
+
+

We can also plot the distribution of the performance measures as a “histogram”.

+
+
autoplot(rr, type = "histogram")
+
+
+
+

+
+
+
+
+

The ROC curve plots the true positive rate against the false positive rate at different thresholds.

+
+
autoplot(rr, type = "roc")
+
+
+
+

+
+
+
+
+

The precision-recall curve plots the precision against the recall at different thresholds.

+
+
autoplot(rr, type = "prc")
+
+
+
+

+
+
+
+
+

The "prediction" plot shows two features and the predicted class in the background. Points mark the observations of the test set and the color presents the truth.

+
+
task = tsk("pima")
+task$filter(seq(100))
+task$select(c("age", "glucose"))
+learner = lrn("classif.rpart")
+resampling = rsmp("cv", folds = 3)
+rr = resample(task, learner, resampling, store_models = TRUE)
+
+autoplot(rr, type = "prediction")
+
+
+
+

+
+
+
+
+

Alternatively, we can plot class probabilities.

+
+
task = tsk("pima")
+task$filter(seq(100))
+task$select(c("age", "glucose"))
+learner = lrn("classif.rpart", predict_type = "prob")
+resampling = rsmp("cv", folds = 3)
+rr = resample(task, learner, resampling, store_models = TRUE)
+
+autoplot(rr, type = "prediction")
+
+
+
+

+
+
+
+
+

In addition to the test set, we can also plot the train set.

+
+
task = tsk("pima")
+task$filter(seq(100))
+task$select(c("age", "glucose"))
+learner = lrn("classif.rpart", predict_type = "prob", predict_sets = c("train", "test"))
+resampling = rsmp("cv", folds = 3)
+rr = resample(task, learner, resampling, store_models = TRUE)
+
+autoplot(rr, type = "prediction", predict_sets = c("train", "test"))
+
+
+
+

+
+
+
+
+

The "prediction" plot can also show categorical features.

+
+
task = tsk("german_credit")
+task$filter(seq(100))
+task$select(c("housing", "employment_duration"))
+learner = lrn("classif.rpart")
+resampling = rsmp("cv", folds = 3)
+rr = resample(task, learner, resampling, store_models = TRUE)
+
+autoplot(rr, type = "prediction")
+
+
+
+

+
+
+
+
+
+
+

Regression

+

The “prediction” plot shows one feature and the response. Points mark the observations of the test set.

+
+
task = tsk("boston_housing")
+task$select("age")
+task$filter(seq(100))
+learner = lrn("regr.rpart")
+resampling = rsmp("cv", folds  = 3)
+rr = resample(task, learner, resampling, store_models = TRUE)
+
+autoplot(rr, type = "prediction")
+
+
+
+

+
+
+
+
+

Additionally, we can add confidence bounds.

+
+
task = tsk("boston_housing")
+task$select("age")
+task$filter(seq(100))
+learner = lrn("regr.lm", predict_type = "se")
+resampling = rsmp("cv", folds  = 3)
+rr = resample(task, learner, resampling, store_models = TRUE)
+
+autoplot(rr, type = "prediction")
+
+
+
+

+
+
+
+
+

And add the train set.

+
+
task = tsk("boston_housing")
+task$select("age")
+task$filter(seq(100))
+learner = lrn("regr.lm", predict_type = "se", predict_sets = c("train", "test"))
+resampling = rsmp("cv", folds = 3)
+rr = resample(task, learner, resampling, store_models = TRUE)
+
+autoplot(rr, type = "prediction", predict_sets = c("train", "test"))
+
+
+
+

+
+
+
+
+

We can also add the prediction surface to the background.

+
+
task = tsk("boston_housing")
+task$select(c("age", "rm"))
+task$filter(seq(100))
+learner = lrn("regr.rpart")
+resampling = rsmp("cv", folds = 3)
+rr = resample(task, learner, resampling, store_models = TRUE)
+
+autoplot(rr, type = "prediction")
+
+
+
+

+
+
+
+
+
+
+
+

Benchmark Result

+

We show the performance distribution of a benchmark with multiple tasks.

+
+
tasks = tsks(c("pima", "sonar"))
+learner = lrns(c("classif.featureless", "classif.rpart", "classif.xgboost"), predict_type = "prob")
+resampling = rsmps("cv")
+bmr = benchmark(benchmark_grid(tasks, learner, resampling))
+
+autoplot(bmr, type = "boxplot")
+
+
+
+

+
+
+
+
+

We plot a benchmark result with one task and multiple learners.

+
+
tasks = tsk("pima")
+learner = lrns(c("classif.featureless", "classif.rpart", "classif.xgboost"), predict_type = "prob")
+resampling = rsmps("cv")
+bmr = benchmark(benchmark_grid(tasks, learner, resampling))
+
+

We plot an roc curve for each learner.

+
+
autoplot(bmr, type = "roc")
+
+
+
+

+
+
+
+
+

Alternatively, we can plot precision-recall curves.

+
+
autoplot(bmr, type = "prc")
+
+
+
+

+
+
+
+
+
+
+

Tuning Instance

+

We tune the hyperparameters of a decision tree on the sonar task. The "performance" plot shows the performance over batches.

+
+
library(mlr3tuning)
+library(mlr3tuningspaces)
+library(mlr3learners)
+
+instance = tune(
+  tuner = tnr("gensa"),
+  task = tsk("sonar"),
+  learner = lts(lrn("classif.rpart")),
+  resampling = rsmp("holdout"),
+  measures = msr("classif.ce"),
+  term_evals = 100
+)
+
+autoplot(instance, type = "performance")
+
+
+
+

+
+
+
+
+

The "incumbent" plot shows the performance of the best hyperparameter setting over the number of evaluations.

+
+
autoplot(instance, type = "incumbent")
+
+
+
+

+
+
+
+
+

The "parameter" plot shows the performance for each hyperparameter setting.

+
+
autoplot(instance, type = "parameter", cols_x = c("cp", "minsplit"))
+
+
+
+

+
+
+
+
+

The "marginal" plot shows the performance of different hyperparameter values. The color indicates the batch.

+
+
autoplot(instance, type = "marginal", cols_x = "cp")
+
+
+
+

+
+
+
+
+

The "parallel" plot visualizes the relationship of hyperparameters.

+
+
autoplot(instance, type = "parallel")
+
+
+
+

+
+
+
+
+

We plot cp against minsplit and color the points by the performance.

+
+
autoplot(instance, type = "points", cols_x = c("cp", "minsplit"))
+
+
+
+

+
+
+
+
+

Next, we plot all hyperparameters against each other.

+
+
autoplot(instance, type = "pairs")
+
+
+
+

+
+
+
+
+

We plot the performance surface of two hyperparameters. The surface is interpolated with a learner.

+
+
autoplot(instance, type = "surface", cols_x = c("cp", "minsplit"), learner = mlr3::lrn("regr.ranger"))
+
+
+
+

+
+
+
+
+
+
+

Filter

+

We plot filter scores for the mtcars task.

+
+
library(mlr3filters)
+
+task = tsk("mtcars")
+f = flt("correlation")
+f$calculate(task)
+
+autoplot(f, n = 5)
+
+
+
+

+
+
+
+
+
+
+

Conclusion

+

The mlr3viz package brings together the visualization functions of the mlr3 ecosystem. All plots are drawn with the autoplot() function and the appearance can be customized with the theme argument. If you need to highly customize a plot e.g. for a publication, we encourage you to check our code on GitHub. The code should be easily adaptable to your needs. We are also looking forward to new visualizations. You can suggest new plots in an issue on GitHub.

+ + +
+ + ]]>
+ visualization + https://mlr-org.com/gallery/technical/2022-12-22-mlr3viz/ + Thu, 22 Dec 2022 00:00:00 GMT +
+ + Hyperparameter Optimization on the Palmer Penguins Data Set + Marc Becker + https://mlr-org.com/gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/ + +

Scope

+

In this post, we optimize the hyperparameters of a simple classification tree on the Palmer Penguins data set with only a few lines of code.

+

First, we introduce tuning spaces and show the importance of transformation functions. Next, we execute the tuning and present the basic building blocks of tuning in mlr3. Finally, we fit a classification tree with optimized hyperparameters on the full data set.

+ +
+

Prerequistes

+

We load the mlr3verse package which pulls the most important packages for this example. Among other packages, it loads the hyperparameter optimization package of the mlr3 ecosystem mlr3tuning.

+
+
library(mlr3verse)
+
+

In this example, we use the Palmer Penguins data set which classifies 344 penguins in three species. The data set was collected from 3 islands in the Palmer Archipelago in Antarctica. It includes the name of the island, the size (flipper length, body mass, and bill dimension), and the sex of the penguin.

+
+
tsk("penguins")
+
+
<TaskClassif:penguins> (344 x 8): Palmer Penguins
+* Target: species
+* Properties: multiclass
+* Features (7):
+  - int (3): body_mass, flipper_length, year
+  - dbl (2): bill_depth, bill_length
+  - fct (2): island, sex
+
+
+
+
+Code +
library(palmerpenguins)
+library(ggplot2)
+ggplot(data = penguins, aes(x = flipper_length_mm, y = bill_length_mm)) +
+  geom_point(aes(color = species, shape = species), size = 3, alpha = 0.8) +
+  geom_smooth(method = "lm", se = FALSE, aes(color = species)) +
+  theme_minimal() +
+  scale_color_manual(values = c("darkorange","purple","cyan4")) +
+  labs(x = "Flipper length (mm)", y = "Bill length (mm)",  color = "Penguin species", shape = "Penguin species") +
+  theme(
+    legend.position = c(0.85, 0.15),
+    legend.background = element_rect(fill = "white", color = NA),
+    text = element_text(size = 10))
+
+
+
+
+

+
Flipper and bill length dimensions for Adelie, Chinstrap, and Gentoo Penguins at Palmer Station (Horst 2022).
+
+
+
+
+
+
+

Learner

+

We use the rpart classification tree. A learner stores all information about its hyperparameters in the slot $param_set. Not all parameters are tunable. We have to choose a subset of the hyperparameters we want to tune.

+
+
learner = lrn("classif.rpart")
+as.data.table(learner$param_set)[, list(id, class, lower, upper, nlevels)]
+
+
                id    class lower upper nlevels
+            <char>   <char> <num> <num>   <num>
+ 1:             cp ParamDbl     0     1     Inf
+ 2:     keep_model ParamLgl    NA    NA       2
+ 3:     maxcompete ParamInt     0   Inf     Inf
+ 4:       maxdepth ParamInt     1    30      30
+ 5:   maxsurrogate ParamInt     0   Inf     Inf
+ 6:      minbucket ParamInt     1   Inf     Inf
+ 7:       minsplit ParamInt     1   Inf     Inf
+ 8: surrogatestyle ParamInt     0     1       2
+ 9:   usesurrogate ParamInt     0     2       3
+10:           xval ParamInt     0   Inf     Inf
+
+
+
+
+

Tuning Space

+

The package mlr3tuningspaces is a collection of search spaces for hyperparameter tuning from peer-reviewed articles. We use the search space from the Bischl et al. (2021) article.

+
+
lts("classif.rpart.default")
+
+
<TuningSpace:classif.rpart.default>: Classification Rpart with Default
+          id lower upper levels logscale
+      <char> <num> <num> <list>   <lgcl>
+1:  minsplit 2e+00 128.0            TRUE
+2: minbucket 1e+00  64.0            TRUE
+3:        cp 1e-04   0.1            TRUE
+
+
+

The classification tree is mainly influenced by three hyperparameters:

+
    +
  • The complexity hyperparameter cp that controls when the learner considers introducing another branch.
  • +
  • The minsplit hyperparameter that controls how many observations must be present in a leaf for another split to be attempted.
  • +
  • The minbucket hyperparameter that the minimum number of observations in any terminal node.
  • +
+

We argument the learner with the search space in one go.

+
+
lts(lrn("classif.rpart"))
+
+
<LearnerClassifRpart:classif.rpart>: Classification Tree
+* Model: -
+* Parameters: xval=0, minsplit=<RangeTuneToken>, minbucket=<RangeTuneToken>, cp=<RangeTuneToken>
+* Packages: mlr3, rpart
+* Predict Types:  [response], prob
+* Feature Types: logical, integer, numeric, factor, ordered
+* Properties: importance, missings, multiclass, selected_features, twoclass, weights
+
+
+
+

Transformations

+

The column logscale indicates that the hyperparameters are tuned on the logarithmic scale. The tuning algorithm proposes hyperparameter values that are transformed with the exponential function before they are passed to the learner. For example, the cp parameter is bounded between 0 and 1. The tuning algorithm searches between log(1e-04) and log(1e-01) but the learner gets the transformed values between 1e-04 and 1e-01. Using the log transformation emphasizes smaller cp values but also creates large values.

+
+
lts("classif.rpart.default")
+
+
<TuningSpace:classif.rpart.default>: Classification Rpart with Default
+          id lower upper levels logscale
+      <char> <num> <num> <list>   <lgcl>
+1:  minsplit 2e+00 128.0            TRUE
+2: minbucket 1e+00  64.0            TRUE
+3:        cp 1e-04   0.1            TRUE
+
+
+
+
+
+

Tuning

+

The tune() function controls and executes the tuning. The method sets the optimization algorithm. The mlr3 ecosystem offers various optimization algorithms e.g. Random Search, GenSA, and Hyperband. In this example, we will use a simple grid search with a grid resolution of 5. Our three-dimensional grid consists of hyperparameter configurations. The resampling strategy and performance measure specify how the performance of a model is evaluated. We choose a 3-fold cross-validation and use the classification error.

+
+
instance = tune(
+  tuner = tnr("grid_search", resolution = 5),
+  task = tsk("penguins"),
+  learner = lts(lrn("classif.rpart")),
+  resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce")
+)
+
+

The tune() function returns a tuning instance that includes an archive with all evaluated hyperparameter configurations.

+
+
as.data.table(instance$archive)[, list(minsplit, minbucket, cp, classif.ce, resample_result)]
+
+
      minsplit minbucket        cp classif.ce      resample_result
+         <num>     <num>     <num>      <num>               <list>
+  1: 2.7764798  2.087194 -2.302585 0.06107297 <ResampleResult[21]>
+  2: 1.7348135  4.174387 -2.302585 0.18001526 <ResampleResult[21]>
+  3: 0.6931472  1.043597 -9.210340 0.02906178 <ResampleResult[21]>
+  4: 0.6931472  3.130790 -9.210340 0.06107297 <ResampleResult[21]>
+  5: 2.7764798  3.130790 -4.029524 0.06107297 <ResampleResult[21]>
+ ---                                                              
+121: 3.8181461  0.000000 -5.756463 0.04065599 <ResampleResult[21]>
+122: 0.6931472  0.000000 -7.483402 0.02616323 <ResampleResult[21]>
+123: 0.6931472  3.130790 -2.302585 0.06107297 <ResampleResult[21]>
+124: 1.7348135  2.087194 -4.029524 0.04937707 <ResampleResult[21]>
+125: 3.8181461  0.000000 -2.302585 0.06107297 <ResampleResult[21]>
+
+
+

The best configuration and the corresponding measured performance can be retrieved from the tuning instance.

+
+
instance$result
+
+
    minsplit minbucket       cp learner_param_vals  x_domain classif.ce
+       <num>     <num>    <num>             <list>    <list>      <num>
+1: 0.6931472         0 -9.21034          <list[4]> <list[3]> 0.02616323
+
+
+

The $result_learner_param_vals field contains the best hyperparameter setting on the learner scale.

+
+
instance$result_learner_param_vals
+
+
$xval
+[1] 0
+
+$minsplit
+[1] 2
+
+$minbucket
+[1] 1
+
+$cp
+[1] 1e-04
+
+
+
+
+

Final Model

+

The learner we use to make predictions on new data is called the final model. The final model is trained on the full data set. We add the optimized hyperparameters to the learner and train the learner on the full dataset.

+
+
learner = lrn("classif.rpart")
+learner$param_set$values = instance$result_learner_param_vals
+learner$train(tsk("penguins"))
+
+

The trained model can now be used to predict new, external data.

+ + + +
+ +

References

+
+Bischl, Bernd, Martin Binder, Michel Lang, Tobias Pielok, Jakob Richter, Stefan Coors, Janek Thomas, et al. 2021. “Hyperparameter Optimization: Foundations, Algorithms, Best Practices and Open Challenges.” arXiv:2107.05847 [Cs, Stat], July. http://arxiv.org/abs/2107.05847. +
+
+Horst, Allison. 2022. “Palmer Penguins Artwork and Figures.” https://github.com/allisonhorst. +
+
]]>
+ tuning + classification + optimization-gallery + https://mlr-org.com/gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/ + Thu, 10 Nov 2022 00:00:00 GMT + +
+ + Early Stopping with XGBoost + Marc Becker + https://mlr-org.com/gallery/optimization/2022-11-04-early-stopping-with-xgboost/ + +

Scope

+

In this post, we use early stopping to reduce overfitting when training an XGBoost model. We start with a short recap on early stopping and overfitting. After that, we use the early stopping mechanism of XGBoost and train a model on the Spam Classification data set. Finally we show how to simultaneously tune hyperparameters and use early stopping. The reader should be familiar with tuning in the mlr3 ecosystem.

+ +
+

Early Stopping

+

Early stopping is a technique used to reduce overfitting when fitting a model in an iterative process. Overfitting occurs when a model fits increasingly to the training data but the performance on unseen data decreases. This means the model’s training error decreases, while its test performance deteriorates. When using early stopping, the performance is monitored on a test set, and the training stops when performance decreases in a specific number of iterations.

+
+
+

XGBoost with Early Stopping

+

We initialize the random number generator with a fixed seed for reproducibility. The mlr3verse package provides all functions required for this example.

+
+
set.seed(7832)
+
+library(mlr3verse)
+
+

When training an XGBoost model, we can use early stopping to find the optimal number of boosting rounds. The partition() function splits the observations of the task into two disjoint sets. We use 80% of observations to train the model and the remaining 20% as the test set to monitor the performance.

+
+
task = tsk("spam")
+split = partition(task, ratio = 0.8)
+task$set_row_roles(split$test, "test")
+
+

The early_stopping_set parameter controls which set is used to monitor the performance. Additionally, we need to define the range in which the performance must increase with early_stopping_rounds and the maximum number of boosting rounds with nrounds. In this example, the training is stopped when the classification error is not decreasing for 100 rounds or 1000 rounds are reached.

+
+
learner = lrn("classif.xgboost",
+  nrounds = 1000,
+  early_stopping_rounds = 100,
+  early_stopping_set = "test",
+  eval_metric = "error"
+)
+
+

We train the learner with early stopping.

+
+
learner$train(task)
+
+

The $evaluation_log of the model stores the performance scores on the training and test set. Figure 1 shows that the classification error on the training set decreases, whereas the error on the test set increases after 20 rounds.

+
+
+Code +
library(ggplot2)
+library(data.table)
+
+data = melt(
+  learner$model$evaluation_log,
+  id.vars = "iter",
+  variable.name = "set",
+  value.name = "error"
+)
+
+ggplot(data, aes(x = iter, y = error, group = set)) +
+  geom_line(aes(color = set)) +
+  geom_vline(aes(xintercept = learner$model$best_iteration), color = "grey") +
+  scale_colour_manual(values=c("#f8766d", "#00b0f6"), labels = c("Train", "Test")) +
+  labs(x = "Rounds", y = "Classification Error", color = "Set") +
+  theme_minimal()
+
+
+
+
+

+
Comparison between train and test set classification error.
+
+
+
+
+

The slot $best_iteration contains the optimal number of boosting rounds.

+
+
learner$model$best_iteration
+
+
[1] 20
+
+
+

Note that, learner$predict() will use the model from the last iteration, not the best one. See the next section on how to fit a model with the optimal number of boosting rounds and hyperparameter configuration.

+
+
+

Tuning

+

In this section, we want to tune the hyperparameters of an XGBoost model and find the optimal number of boosting rounds in one go. For this, we need the early stopping callback which handles early stopping during the tuning process. The performance of a hyperparameter configuration is evaluated with a resampling strategy while tuning e.g. 3-fold cross-validation. In each resampling iteration, a new XGBoost model is trained and early stopping is used to find the optimal number of boosting rounds. This results in three different optimal numbers of boosting rounds for one hyperparameter configuration when applying 3-fold cross-validation. The callback picks the maximum of the three values and writes it to the archive. It uses the maximum value because the final model is fitted on the complete data set. Now let’s start with a practical example.

+

First, we load the XGBoost learner and set the early stopping parameters.

+
+
learner = lrn("classif.xgboost",
+  nrounds = 1000,
+  early_stopping_rounds = 100,
+  early_stopping_set = "test"
+)
+
+

Next, we load a predefined tuning space from the mlr3tuningspaces package. The tuning space includes the most commonly tuned parameters of XGBoost.

+
+
tuning_space = lts("classif.xgboost.default")
+as.data.table(tuning_space)
+
+
                  id lower upper logscale
+1:               eta 1e-04     1     TRUE
+2:           nrounds 1e+00  5000    FALSE
+3:         max_depth 1e+00    20    FALSE
+4:  colsample_bytree 1e-01     1    FALSE
+5: colsample_bylevel 1e-01     1    FALSE
+6:            lambda 1e-03  1000     TRUE
+7:             alpha 1e-03  1000     TRUE
+8:         subsample 1e-01     1    FALSE
+
+
+

We argument the learner with the tuning space.

+
+
learner = lts(learner)
+
+

The default tuning space contains the nrounds hyperparameter. We have to overwrite it with an upper bound for early stopping.

+
+
learner$param_set$set_values(nrounds = 1000)
+
+

We run a small batch of random hyperparameter configurations.

+
+
instance = tune(
+  tuner = tnr("random_search", batch_size = 2),
+  task = task,
+  learner = learner,
+  resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce"),
+  term_evals = 4,
+  callbacks = clbk("mlr3tuning.early_stopping")
+)
+
+

We can see that the optimal number of boosting rounds (max_nrounds) strongly depends on the other hyperparameters.

+
+
as.data.table(instance$archive)[, list(batch_nr, max_nrounds, eta, max_depth, colsample_bytree, colsample_bylevel, lambda, alpha, subsample)]
+
+
   batch_nr max_nrounds       eta max_depth colsample_bytree colsample_bylevel     lambda     alpha subsample
+1:        1        1000 -4.129996        13        0.5466492         0.3051989 -0.9448420  2.535477 0.5454539
+2:        1         998 -3.338899         8        0.6193478         0.7392354 -2.2338126  1.793921 0.2294161
+3:        2        1000 -6.059897         5        0.6118892         0.5445475 -6.5698270  5.414224 0.9635730
+4:        2        1000 -4.528129         1        0.1094186         0.2526143 -0.7535105 -3.041829 0.5934376
+
+
+

In the best hyperparameter configuration, the value of nrounds is replaced by max_nrounds and early stopping is deactivated.

+
+
instance$result_learner_param_vals
+
+
$nrounds
+[1] 998
+
+$nthread
+[1] 1
+
+$verbose
+[1] 0
+
+$early_stopping_set
+[1] "none"
+
+$eta
+[1] 0.03547598
+
+$max_depth
+[1] 8
+
+$colsample_bytree
+[1] 0.6193478
+
+$colsample_bylevel
+[1] 0.7392354
+
+$lambda
+[1] 0.1071192
+
+$alpha
+[1] 6.012984
+
+$subsample
+[1] 0.2294161
+
+
+

Finally, fit the final model on the complete data set.

+
+
learner = lrn("classif.xgboost")
+learner$param_set$values = instance$result_learner_param_vals
+learner$train(task)
+
+

The trained model can now be used to make predictions on new data.

+

We can also use the AutoTuner to get a tuned XGBoost model. Note that, early stopping is deactivated when the final model is fitted.

+ + +
+ + ]]>
+ tuning + classification + https://mlr-org.com/gallery/optimization/2022-11-04-early-stopping-with-xgboost/ + Wed, 09 Nov 2022 00:00:00 GMT + +
+ + Introduction to mlr3tuningspaces + Marc Becker + https://mlr-org.com/gallery/optimization/2021-07-06-introduction-to-mlr3tuningspaces/ + +

Scope

+

The package mlr3tuningspaces offers a selection of published search spaces for many popular machine learning algorithms. In this post, we show how to tune a mlr3 learners with these search spaces.

+ +
+

Prerequisites

+

The packages mlr3verse and mlr3tuningspaces are required for this demonstration:

+
+
library(mlr3verse)
+library(mlr3tuningspaces)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+

In the example, we use the pima indian diabetes data set which is used to predict whether or not a patient has diabetes. The patients are characterized by 8 numeric features, some of them have missing values.

+
+
# retrieve the task from mlr3
+task = tsk("pima")
+
+# generate a quick textual overview using the skimr package
+skimr::skim(task$data())
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Data summary
Nametask$data()
Number of rows768
Number of columns9
KeyNULL
_______________________
Column type frequency:
factor1
numeric8
________________________
Group variablesNone
+

Variable type: factor

+ ++++++++ + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_rateorderedn_uniquetop_counts
diabetes01FALSE2neg: 500, pos: 268
+

Variable type: numeric

+ +++++++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_ratemeansdp0p25p50p75p100hist
age01.0033.2411.7621.0024.0029.0041.0081.00▇▃▁▁▁
glucose50.99121.6930.5444.0099.00117.00141.00199.00▁▇▇▃▂
insulin3740.51155.55118.7814.0076.25125.00190.00846.00▇▂▁▁▁
mass110.9932.466.9218.2027.5032.3036.6067.10▅▇▃▁▁
pedigree01.000.470.330.080.240.370.632.42▇▃▁▁▁
pregnant01.003.853.370.001.003.006.0017.00▇▃▂▁▁
pressure350.9572.4112.3824.0064.0072.0080.00122.00▁▃▇▂▁
triceps2270.7029.1510.487.0022.0029.0036.0099.00▆▇▁▁▁
+
+
+
+
+

Tuning Search Space

+

For tuning, it is important to create a search space that defines the type and range of the hyperparameters. A learner stores all information about its hyperparameters in the slot $param_set. Usually, we have to chose a subset of hyperparameters we want to tune.

+
+
lrn("classif.rpart")$param_set
+
+
<ParamSet>
+                id    class lower upper nlevels        default value
+ 1:             cp ParamDbl     0     1     Inf           0.01      
+ 2:     keep_model ParamLgl    NA    NA       2          FALSE      
+ 3:     maxcompete ParamInt     0   Inf     Inf              4      
+ 4:       maxdepth ParamInt     1    30      30             30      
+ 5:   maxsurrogate ParamInt     0   Inf     Inf              5      
+ 6:      minbucket ParamInt     1   Inf     Inf <NoDefault[3]>      
+ 7:       minsplit ParamInt     1   Inf     Inf             20      
+ 8: surrogatestyle ParamInt     0     1       2              0      
+ 9:   usesurrogate ParamInt     0     2       3              2      
+10:           xval ParamInt     0   Inf     Inf             10     0
+
+
+
+
+

Package

+

At the heart of mlr3tuningspaces is the R6 class TuningSpace. It stores a list of TuneToken, helper functions and additional meta information. The list of TuneToken can be directly applied to the $values slot of a learner’s ParamSet. The search spaces are stored in the mlr_tuning_spaces dictionary.

+
+
as.data.table(mlr_tuning_spaces)
+
+
                        key                                 label         learner n_values
+ 1:  classif.glmnet.default       Classification GLM with Default  classif.glmnet        2
+ 2:     classif.glmnet.rbv1     Classification GLM with RandomBot  classif.glmnet        2
+ 3:     classif.glmnet.rbv2     Classification GLM with RandomBot  classif.glmnet        2
+ 4:    classif.kknn.default      Classification KKNN with Default    classif.kknn        3
+ 5:       classif.kknn.rbv1    Classification KKNN with RandomBot    classif.kknn        1
+ 6:       classif.kknn.rbv2    Classification KKNN with RandomBot    classif.kknn        1
+ 7:  classif.ranger.default    Classification Ranger with Default  classif.ranger        4
+ 8:     classif.ranger.rbv1  Classification Ranger with RandomBot  classif.ranger        6
+ 9:     classif.ranger.rbv2  Classification Ranger with RandomBot  classif.ranger        8
+10:   classif.rpart.default     Classification Rpart with Default   classif.rpart        3
+11:      classif.rpart.rbv1   Classification Rpart with RandomBot   classif.rpart        4
+12:      classif.rpart.rbv2   Classification Rpart with RandomBot   classif.rpart        4
+13:     classif.svm.default       Classification SVM with Default     classif.svm        4
+14:        classif.svm.rbv1     Classification SVM with RandomBot     classif.svm        4
+15:        classif.svm.rbv2     Classification SVM with RandomBot     classif.svm        5
+16: classif.xgboost.default   Classification XGBoost with Default classif.xgboost        8
+17:    classif.xgboost.rbv1 Classification XGBoost with RandomBot classif.xgboost       10
+18:    classif.xgboost.rbv2 Classification XGBoost with RandomBot classif.xgboost       13
+19:     regr.glmnet.default           Regression GLM with Default     regr.glmnet        2
+20:        regr.glmnet.rbv1         Regression GLM with RandomBot     regr.glmnet        2
+21:        regr.glmnet.rbv2         Regression GLM with RandomBot     regr.glmnet        2
+22:       regr.kknn.default          Regression KKNN with Default       regr.kknn        3
+23:          regr.kknn.rbv1        Regression KKNN with RandomBot       regr.kknn        1
+24:          regr.kknn.rbv2        Regression KKNN with RandomBot       regr.kknn        1
+25:     regr.ranger.default        Regression Ranger with Default     regr.ranger        4
+26:        regr.ranger.rbv1      Regression Ranger with RandomBot     regr.ranger        6
+27:        regr.ranger.rbv2      Regression Ranger with RandomBot     regr.ranger        7
+28:      regr.rpart.default         Regression Rpart with Default      regr.rpart        3
+29:         regr.rpart.rbv1       Regression Rpart with RandomBot      regr.rpart        4
+30:         regr.rpart.rbv2       Regression Rpart with RandomBot      regr.rpart        4
+31:        regr.svm.default           Regression SVM with Default        regr.svm        4
+32:           regr.svm.rbv1         Regression SVM with RandomBot        regr.svm        4
+33:           regr.svm.rbv2         Regression SVM with RandomBot        regr.svm        5
+34:    regr.xgboost.default       Regression XGBoost with Default    regr.xgboost        8
+35:       regr.xgboost.rbv1     Regression XGBoost with RandomBot    regr.xgboost       10
+36:       regr.xgboost.rbv2     Regression XGBoost with RandomBot    regr.xgboost       13
+                        key                                 label         learner n_values
+
+
+

We can use the sugar function lts() to retrieve a TuningSpace.

+
+
tuning_space_rpart = lts("classif.rpart.default")
+tuning_space_rpart
+
+
<TuningSpace:classif.rpart.default>: Classification Rpart with Default
+          id lower upper levels logscale
+1:  minsplit 2e+00 128.0            TRUE
+2: minbucket 1e+00  64.0            TRUE
+3:        cp 1e-04   0.1            TRUE
+
+
+

The $values slot contains the list of of TuneToken.

+
+
tuning_space_rpart$values
+
+
$minsplit
+Tuning over:
+range [2, 128] (log scale)
+
+
+$minbucket
+Tuning over:
+range [1, 64] (log scale)
+
+
+$cp
+Tuning over:
+range [1e-04, 0.1] (log scale)
+
+
+

We apply the search space and tune the learner.

+
+
learner = lrn("classif.rpart")
+
+learner$param_set$values = tuning_space_rpart$values
+
+instance = tune(
+  tuner = tnr("random_search"),
+  task = tsk("pima"),
+  learner = learner,
+  resampling = rsmp ("holdout"),
+  measure = msr("classif.ce"),
+  term_evals = 10)
+
+instance$result
+
+
   minsplit minbucket        cp learner_param_vals  x_domain classif.ce
+1:  3.40059  1.963618 -4.114895          <list[3]> <list[3]>  0.2539062
+
+
+

We can also get the learner with search space already applied from the TuningSpace.

+
+
learner = tuning_space_rpart$get_learner()
+print(learner$param_set)
+
+
<ParamSet>
+                id    class lower upper nlevels        default               value
+ 1:             cp ParamDbl     0     1     Inf           0.01 <RangeTuneToken[2]>
+ 2:     keep_model ParamLgl    NA    NA       2          FALSE                    
+ 3:     maxcompete ParamInt     0   Inf     Inf              4                    
+ 4:       maxdepth ParamInt     1    30      30             30                    
+ 5:   maxsurrogate ParamInt     0   Inf     Inf              5                    
+ 6:      minbucket ParamInt     1   Inf     Inf <NoDefault[3]> <RangeTuneToken[2]>
+ 7:       minsplit ParamInt     1   Inf     Inf             20 <RangeTuneToken[2]>
+ 8: surrogatestyle ParamInt     0     1       2              0                    
+ 9:   usesurrogate ParamInt     0     2       3              2                    
+10:           xval ParamInt     0   Inf     Inf             10                   0
+
+
+

This method also allows to set constant parameters.

+
+
learner = tuning_space_rpart$get_learner(maxdepth = 15)
+print(learner$param_set)
+
+
<ParamSet>
+                id    class lower upper nlevels        default               value
+ 1:             cp ParamDbl     0     1     Inf           0.01 <RangeTuneToken[2]>
+ 2:     keep_model ParamLgl    NA    NA       2          FALSE                    
+ 3:     maxcompete ParamInt     0   Inf     Inf              4                    
+ 4:       maxdepth ParamInt     1    30      30             30                  15
+ 5:   maxsurrogate ParamInt     0   Inf     Inf              5                    
+ 6:      minbucket ParamInt     1   Inf     Inf <NoDefault[3]> <RangeTuneToken[2]>
+ 7:       minsplit ParamInt     1   Inf     Inf             20 <RangeTuneToken[2]>
+ 8: surrogatestyle ParamInt     0     1       2              0                    
+ 9:   usesurrogate ParamInt     0     2       3              2                    
+10:           xval ParamInt     0   Inf     Inf             10                   0
+
+
+

The lts() function sets the default search space directly to a learner.

+
+
learner = lts(lrn("classif.rpart", maxdepth = 15))
+print(learner$param_set)
+
+
<ParamSet>
+                id    class lower upper nlevels        default               value
+ 1:             cp ParamDbl     0     1     Inf           0.01 <RangeTuneToken[2]>
+ 2:     keep_model ParamLgl    NA    NA       2          FALSE                    
+ 3:     maxcompete ParamInt     0   Inf     Inf              4                    
+ 4:       maxdepth ParamInt     1    30      30             30                  15
+ 5:   maxsurrogate ParamInt     0   Inf     Inf              5                    
+ 6:      minbucket ParamInt     1   Inf     Inf <NoDefault[3]> <RangeTuneToken[2]>
+ 7:       minsplit ParamInt     1   Inf     Inf             20 <RangeTuneToken[2]>
+ 8: surrogatestyle ParamInt     0     1       2              0                    
+ 9:   usesurrogate ParamInt     0     2       3              2                    
+10:           xval ParamInt     0   Inf     Inf             10                   0
+
+
+ + +
+ + ]]>
+ tuning + classification + https://mlr-org.com/gallery/optimization/2021-07-06-introduction-to-mlr3tuningspaces/ + Tue, 06 Jul 2021 00:00:00 GMT + +
+ + Practical Tuning Series - Tuning and Parallel Processing + Marc Becker + Theresa Ullmann + Michel Lang + Bernd Bischl + Jakob Richter + Martin Binder + https://mlr-org.com/gallery/optimization/2021-03-12-practical-tuning-series-tuning-and-parallel-processing/ + +

Scope

+

This is the fourth part of the practical tuning series. The other parts can be found here:

+ +

In this post, we teach how to run various jobs in mlr3 in parallel. The goal is to map computational jobs (e.g. evaluation of one configuration) to a pool of workers (usually physical CPU cores, sometimes remote computational nodes) to reduce the run time needed for tuning.

+ +
+

Prerequisites

+

We load the mlr3verse package which pulls in the most important packages for this example. Additionally, make sure you have installed the packages future and future.apply.

+
+
library(mlr3verse)
+
+

We decrease the verbosity of the logger to keep the output clearly represented. The lgr package is used for logging in all mlr3 packages. The mlr3 logger prints the logging messages from the base package, whereas the bbotk logger is responsible for logging messages from the optimization packages (e.g. mlr3tuning ).

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+
+
+

Parallel Backend

+

The workers are specified by the parallel backend which orchestrates starting up, shutting down, and communication with the workers. On a single machine, multisession and multicore are common backends. The multisession backend spawns new background R processes. It is available on all platforms.

+
+
future::plan("multisession")
+
+

The multicore backend uses forked R processes which allows the workers to access R objects in a shared memory. This reduces the overhead since R objects are only copied in memory if they are modified. Unfortunately, forking processes is not supported on Windows and when running R from within RStudio.

+
+
future::plan("multicore")
+
+

Both backends support the workers argument that specifies the number of used cores.

+

Use this code if your code should run with the multicore backend when possible.

+
+
if (future::supportsMulticore()) {
+  future::plan(future::multicore)
+} else {
+  future::plan(future::multisession)
+}
+
+
+
+

Resampling

+

The resample() and benchmark() functions in mlr3 can be executed in parallel. The parallelization is triggered by simply declaring a plan via future::plan().

+
+
future::plan("multisession")
+
+task = tsk("pima")
+learner = lrn("classif.rpart") # classification tree
+resampling = rsmp("cv", folds = 3)
+
+resample(task, learner, resampling)
+
+
<ResampleResult> with 3 resampling iterations
+ task_id    learner_id resampling_id iteration warnings errors
+    pima classif.rpart            cv         1        0      0
+    pima classif.rpart            cv         2        0      0
+    pima classif.rpart            cv         3        0      0
+
+
+

The 3-fold cross-validation gives us 3 jobs since each resampling iteration is executed in parallel.

+

The benchmark() function accepts a design of experiments as input where each experiment is defined as a combination of a task, a learner, and a resampling strategy. For each experiment, resampling is performed. The nested loop over experiments and resampling iterations is flattened so that all resampling iterations of all experiments can be executed in parallel.

+
+
future::plan("multisession")
+
+tasks = list(tsk("pima"), tsk("iris"))
+learner = lrn("classif.rpart")
+resampling = rsmp("cv", folds = 3)
+
+grid = benchmark_grid(tasks, learner, resampling)
+
+benchmark(grid)
+
+
<BenchmarkResult> of 6 rows with 2 resampling runs
+ nr task_id    learner_id resampling_id iters warnings errors
+  1    pima classif.rpart            cv     3        0      0
+  2    iris classif.rpart            cv     3        0      0
+
+
+

The 2 experiments and the 3-fold cross-validation result in 6 jobs which are executed in parallel.

+
+
+

Tuning

+

The mlr3tuning package internally calls benchmark() during tuning. If the tuner is capable of suggesting multiple configurations per iteration (such as random search, grid search, or hyperband), these configurations represent individual experiments, and the loop flattening of benchmark() is triggered. E.g., all resampling iterations of all hyperparameter configurations on a grid can be executed in parallel.

+
+
future::plan("multisession")
+
+learner = lrn("classif.rpart")
+learner$param_set$values$cp = to_tune(0.001, 0.1)
+learner$param_set$values$minsplit = to_tune(1, 10)
+
+instance = tune(
+  tuner = tnr("random_search", batch_size = 5), # random search suggests 5 configurations per batch
+  task = tsk("pima"),
+  learner = learner,
+  resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce"),
+  term_evals = 10
+)
+
+

The batch size of 5 and the 3-fold cross-validation gives us 15 jobs. This is done twice because of the limit of 10 evaluations in total.

+
+
+

Nested Resampling

+

Nested resampling results in two nested resampling loops. For this, an AutoTuner is passed to resample() or benchmark(). We can choose different parallelization backends for the inner and outer resampling loop, respectively. We just have to pass a list of backends.

+
+
# Runs the outer loop in parallel and the inner loop sequentially
+future::plan(list("multisession", "sequential"))
+
+# Runs the outer loop sequentially and the inner loop in parallel
+future::plan(list("sequential", "multisession"))
+
+learner = lrn("classif.rpart")
+learner$param_set$values$cp = to_tune(0.001, 0.1)
+learner$param_set$values$minsplit = to_tune(1, 10)
+
+rr = tune_nested(
+  tuner = tnr("random_search", batch_size = 5), # random search suggests 5 configurations per batch
+  task = tsk("pima"),
+  learner = learner,
+  inner_resampling = rsmp ("cv", folds = 3),
+  outer_resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce"),
+  term_evals = 10
+)
+
+

While nesting real parallelization backends is often unintended and causes unnecessary overhead, it is useful in some distributed computing setups. It can be achieved with future by forcing a fixed number of workers for each loop.

+
+
# Runs both loops in parallel
+future::plan(list(future::tweak("multisession", workers = 2),
+                  future::tweak("multisession", workers = 4)))
+
+

This example would run on 8 cores (= 2 * 4) on the local machine.

+
+
+

Resources

+

The mlr3book includes a chapters on parallelization. The mlr3cheatsheets contain frequently used commands and workflows of mlr3.

+ + +
+ + ]]>
+ tuning + resampling + parallelization + classification + practical tuning series + https://mlr-org.com/gallery/optimization/2021-03-12-practical-tuning-series-tuning-and-parallel-processing/ + Fri, 12 Mar 2021 00:00:00 GMT +
+ + Practical Tuning Series - Build an Automated Machine Learning System + Marc Becker + Theresa Ullmann + Michel Lang + Bernd Bischl + Jakob Richter + Martin Binder + https://mlr-org.com/gallery/optimization/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/ + +

Scope

+

This is the third part of the practical tuning series. The other parts can be found here:

+ +

In this post, we implement a simple automated machine learning (AutoML) system which includes preprocessing, a switch between multiple learners and hyperparameter tuning. For this, we build a pipeline with the mlr3pipelines extension package. Additionally, we use nested resampling to get an unbiased performance estimate of our AutoML system.

+ +
+

Prerequisites

+

We load the mlr3verse package which pulls in the most important packages for this example.

+
+
library(mlr3verse)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented. The lgr package is used for logging in all mlr3 packages. The mlr3 logger prints the logging messages from the base package, whereas the bbotk logger is responsible for logging messages from the optimization packages (e.g. mlr3tuning ).

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+

In this example, we use the Pima Indians Diabetes data set which is used to to predict whether or not a patient has diabetes. The patients are characterized by 8 numeric features and some have missing values.

+
+
task = tsk("pima")
+
+
+
+

Branching

+

We use three popular machine learning algorithms: k-nearest-neighbors, support vector machines and random forests.

+
+
learners = list(
+  lrn("classif.kknn", id = "kknn"),
+  lrn("classif.svm", id = "svm", type = "C-classification"),
+  lrn("classif.ranger", id = "ranger")
+)
+
+

The PipeOpBranch allows us to specify multiple alternatives paths. In this graph, the paths lead to the different learner models. The selection hyperparameter controls which path is executed i.e., which learner is used to fit a model. It is important to use the PipeOpBranch after the branching so that the outputs are merged into one result object. We visualize the graph with branching below.

+
+
graph =
+  po("branch", options = c("kknn", "svm", "ranger")) %>>%
+  gunion(lapply(learners, po)) %>>%
+  po("unbranch")
+graph$plot(html = FALSE)
+
+
+
+

+
+
+
+
+

Alternatively, we can use the ppl()-shortcut to load a predefined graph from the mlr_graphs dictionary. For this, the learner list must be named.

+
+
learners = list(
+  kknn = lrn("classif.kknn", id = "kknn"),
+  svm = lrn("classif.svm", id = "svm", type = "C-classification"),
+  ranger = lrn("classif.ranger", id = "ranger")
+)
+
+graph = ppl("branch", lapply(learners, po))
+
+
+
+

Preprocessing

+

The task has missing data in five columns.

+
+
round(task$missings() / task$nrow, 2)
+
+
diabetes      age  glucose  insulin     mass pedigree pregnant pressure  triceps 
+    0.00     0.00     0.01     0.49     0.01     0.00     0.00     0.05     0.30 
+
+
+

The pipeline "robustify" function creates a preprocessing pipeline based on our task. The resulting pipeline imputes missing values with PipeOpImputeHist and creates a dummy column (PipeOpMissInd) which indicates the imputed missing values. Internally, this creates two paths and the results are combined with PipeOpFeatureUnion. In contrast to PipeOpBranch, both paths are executed. Additionally, "robustify" adds PipeOpEncode to encode factor columns and PipeOpRemoveConstants to remove features with a constant value.

+
+
graph = ppl("robustify", task = task, factors_to_numeric = TRUE) %>>%
+  graph
+plot(graph, html = FALSE)
+
+
+
+

+
+
+
+
+

We could also create the preprocessing pipeline manually.

+
+
gunion(list(po("imputehist"),
+  po("missind", affect_columns = selector_type(c("numeric", "integer"))))) %>>%
+  po("featureunion") %>>%
+  po("encode") %>>%
+  po("removeconstants")
+
+
Graph with 5 PipeOps:
+              ID         State        sccssors          prdcssors
+      imputehist <<UNTRAINED>>    featureunion                   
+         missind <<UNTRAINED>>    featureunion                   
+    featureunion <<UNTRAINED>>          encode imputehist,missind
+          encode <<UNTRAINED>> removeconstants       featureunion
+ removeconstants <<UNTRAINED>>                             encode
+
+
+
+
+

Graph Learner

+

We use as_learner() to create a GraphLearner which encapsulates the pipeline and can be used like a learner.

+
+
graph_learner = as_learner(graph)
+
+

The parameter set of the graph learner includes all hyperparameters from all contained learners. The hyperparameter ids are prefixed with the corresponding learner ids. The hyperparameter branch.selection controls which learner is used.

+
+
as.data.table(graph_learner$param_set)[, .(id, class, lower, upper, nlevels)]
+
+
                                              id    class lower upper nlevels
+ 1:           removeconstants_prerobustify.ratio ParamDbl     0     1     Inf
+ 2:         removeconstants_prerobustify.rel_tol ParamDbl     0   Inf     Inf
+ 3:         removeconstants_prerobustify.abs_tol ParamDbl     0   Inf     Inf
+ 4:       removeconstants_prerobustify.na_ignore ParamLgl    NA    NA       2
+ 5:  removeconstants_prerobustify.affect_columns ParamUty    NA    NA     Inf
+ 6:                    imputehist.affect_columns ParamUty    NA    NA     Inf
+ 7:                                missind.which ParamFct    NA    NA       2
+ 8:                                 missind.type ParamFct    NA    NA       4
+ 9:                       missind.affect_columns ParamUty    NA    NA     Inf
+10:                  imputesample.affect_columns ParamUty    NA    NA     Inf
+11:                                encode.method ParamFct    NA    NA       5
+12:                        encode.affect_columns ParamUty    NA    NA     Inf
+13:          removeconstants_postrobustify.ratio ParamDbl     0     1     Inf
+14:        removeconstants_postrobustify.rel_tol ParamDbl     0   Inf     Inf
+15:        removeconstants_postrobustify.abs_tol ParamDbl     0   Inf     Inf
+16:      removeconstants_postrobustify.na_ignore ParamLgl    NA    NA       2
+17: removeconstants_postrobustify.affect_columns ParamUty    NA    NA     Inf
+18:                                       kknn.k ParamInt     1   Inf     Inf
+19:                                kknn.distance ParamDbl     0   Inf     Inf
+20:                                  kknn.kernel ParamFct    NA    NA      10
+21:                                   kknn.scale ParamLgl    NA    NA       2
+22:                                 kknn.ykernel ParamUty    NA    NA     Inf
+23:                             kknn.store_model ParamLgl    NA    NA       2
+24:                                svm.cachesize ParamDbl  -Inf   Inf     Inf
+25:                            svm.class.weights ParamUty    NA    NA     Inf
+26:                                    svm.coef0 ParamDbl  -Inf   Inf     Inf
+27:                                     svm.cost ParamDbl     0   Inf     Inf
+28:                                    svm.cross ParamInt     0   Inf     Inf
+29:                          svm.decision.values ParamLgl    NA    NA       2
+30:                                   svm.degree ParamInt     1   Inf     Inf
+31:                                  svm.epsilon ParamDbl     0   Inf     Inf
+32:                                   svm.fitted ParamLgl    NA    NA       2
+33:                                    svm.gamma ParamDbl     0   Inf     Inf
+34:                                   svm.kernel ParamFct    NA    NA       4
+35:                                       svm.nu ParamDbl  -Inf   Inf     Inf
+36:                                    svm.scale ParamUty    NA    NA     Inf
+37:                                svm.shrinking ParamLgl    NA    NA       2
+38:                                svm.tolerance ParamDbl     0   Inf     Inf
+39:                                     svm.type ParamFct    NA    NA       2
+40:                                 ranger.alpha ParamDbl  -Inf   Inf     Inf
+41:                ranger.always.split.variables ParamUty    NA    NA     Inf
+42:                         ranger.class.weights ParamUty    NA    NA     Inf
+43:                               ranger.holdout ParamLgl    NA    NA       2
+44:                            ranger.importance ParamFct    NA    NA       4
+45:                            ranger.keep.inbag ParamLgl    NA    NA       2
+46:                             ranger.max.depth ParamInt     0   Inf     Inf
+47:                         ranger.min.node.size ParamInt     1   Inf     Inf
+48:                              ranger.min.prop ParamDbl  -Inf   Inf     Inf
+49:                               ranger.minprop ParamDbl  -Inf   Inf     Inf
+50:                                  ranger.mtry ParamInt     1   Inf     Inf
+51:                            ranger.mtry.ratio ParamDbl     0     1     Inf
+52:                     ranger.num.random.splits ParamInt     1   Inf     Inf
+53:                           ranger.num.threads ParamInt     1   Inf     Inf
+54:                             ranger.num.trees ParamInt     1   Inf     Inf
+55:                             ranger.oob.error ParamLgl    NA    NA       2
+56:                 ranger.regularization.factor ParamUty    NA    NA     Inf
+57:               ranger.regularization.usedepth ParamLgl    NA    NA       2
+58:                               ranger.replace ParamLgl    NA    NA       2
+59:             ranger.respect.unordered.factors ParamFct    NA    NA       3
+60:                       ranger.sample.fraction ParamDbl     0     1     Inf
+61:                           ranger.save.memory ParamLgl    NA    NA       2
+62:          ranger.scale.permutation.importance ParamLgl    NA    NA       2
+63:                             ranger.se.method ParamFct    NA    NA       2
+64:                                  ranger.seed ParamInt  -Inf   Inf     Inf
+65:                  ranger.split.select.weights ParamUty    NA    NA     Inf
+66:                             ranger.splitrule ParamFct    NA    NA       3
+67:                               ranger.verbose ParamLgl    NA    NA       2
+68:                          ranger.write.forest ParamLgl    NA    NA       2
+69:                             branch.selection ParamFct    NA    NA       3
+                                              id    class lower upper nlevels
+
+
+
+
+

Tune the pipeline

+

We will only tune one hyperparameter for each learner in this example. Additionally, we tune the branching parameter which selects one of the three learners. We have to specify that a hyperparameter is only valid for a certain learner by using depends = branch.selection == <learner_id>.

+
+
# branch
+graph_learner$param_set$values$branch.selection =
+  to_tune(c("kknn", "svm", "ranger"))
+
+# kknn
+graph_learner$param_set$values$kknn.k =
+  to_tune(p_int(3, 50, logscale = TRUE, depends = branch.selection == "kknn"))
+
+# svm
+graph_learner$param_set$values$svm.cost =
+  to_tune(p_dbl(-1, 1, trafo = function(x) 10^x, depends = branch.selection == "svm"))
+
+# ranger
+graph_learner$param_set$values$ranger.mtry =
+  to_tune(p_int(1, 8, depends = branch.selection == "ranger"))
+
+# short learner id for printing
+graph_learner$id = "graph_learner"
+
+

We define a tuning instance and select a random search which is stopped after 20 evaluated configurations.

+
+
instance = tune(
+  tuner = tnr("random_search"),
+  task = task,
+  learner = graph_learner,
+  resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce"),
+  term_evals = 20
+)
+
+

The following shows a quick way to visualize the tuning results.

+
+
autoplot(instance, type = "marginal",
+  cols_x = c("x_domain_kknn.k", "x_domain_svm.cost", "ranger.mtry"))
+
+
+
+

+
+
+
+
+
+
+

Final Model

+

We add the optimized hyperparameters to the graph learner and train the learner on the full dataset.

+
+
learner = as_learner(graph)
+learner$param_set$values = instance$result_learner_param_vals
+learner$train(task)
+
+

The trained model can now be used to make predictions on new data. A common mistake is to report the performance estimated on the resampling sets on which the tuning was performed (instance$result_y) as the model’s performance. Instead we have to use nested resampling to get an unbiased performance estimate.

+
+
+

Nested Resampling

+

We use nested resampling to get an unbiased estimate of the predictive performance of our graph learner.

+
+
graph_learner = as_learner(graph)
+graph_learner$param_set$values$branch.selection =
+  to_tune(c("kknn", "svm", "ranger"))
+graph_learner$param_set$values$kknn.k =
+  to_tune(p_int(3, 50, logscale = TRUE, depends = branch.selection == "kknn"))
+graph_learner$param_set$values$svm.cost =
+  to_tune(p_dbl(-1, 1, trafo = function(x) 10^x, depends = branch.selection == "svm"))
+graph_learner$param_set$values$ranger.mtry =
+  to_tune(p_int(1, 8, depends = branch.selection == "ranger"))
+graph_learner$id = "graph_learner"
+
+inner_resampling = rsmp("cv", folds = 3)
+at = AutoTuner$new(
+  learner = graph_learner,
+  resampling = inner_resampling,
+  measure = msr("classif.ce"),
+  terminator = trm("evals", n_evals = 10),
+  tuner = tnr("random_search")
+)
+
+outer_resampling = rsmp("cv", folds = 3)
+rr = resample(task, at, outer_resampling, store_models = TRUE)
+
+

We check the inner tuning results for stable hyperparameters. This means that the selected hyperparameters should not vary too much. We might observe unstable models in this example because the small data set and the low number of resampling iterations might introduce too much randomness. Usually, we aim for the selection of stable hyperparameters for all outer training sets.

+
+
extract_inner_tuning_results(rr)
+
+
+
+
+ +
+
+

Next, we want to compare the predictive performances estimated on the outer resampling to the inner resampling. Significantly lower predictive performances on the outer resampling indicate that the models with the optimized hyperparameters overfit the data.

+
+
rr$score()[, .(iteration, task_id, learner_id, resampling_id, classif.ce)]
+
+
   iteration task_id          learner_id resampling_id classif.ce
+1:         1    pima graph_learner.tuned            cv  0.2265625
+2:         2    pima graph_learner.tuned            cv  0.2382812
+3:         3    pima graph_learner.tuned            cv  0.2656250
+
+
+

The aggregated performance of all outer resampling iterations is essentially the unbiased performance of the graph learner with optimal hyperparameter found by random search.

+
+
rr$aggregate()
+
+
classif.ce 
+ 0.2434896 
+
+
+

Applying nested resampling can be shortened by using the tune_nested()-shortcut.

+
+
graph_learner = as_learner(graph)
+graph_learner$param_set$values$branch.selection =
+  to_tune(c("kknn", "svm", "ranger"))
+graph_learner$param_set$values$kknn.k =
+  to_tune(p_int(3, 50, logscale = TRUE, depends = branch.selection == "kknn"))
+graph_learner$param_set$values$svm.cost =
+  to_tune(p_dbl(-1, 1, trafo = function(x) 10^x, depends = branch.selection == "svm"))
+graph_learner$param_set$values$ranger.mtry =
+  to_tune(p_int(1, 8, depends = branch.selection == "ranger"))
+graph_learner$id = "graph_learner"
+
+rr = tune_nested(
+  tuner = tnr("random_search"),
+  task = task,
+  learner = graph_learner,
+  inner_resampling = rsmp("cv", folds = 3),
+  outer_resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce"),
+  term_evals = 10,
+)
+
+
+
+

Resources

+

The mlr3book includes chapters on pipelines and hyperparameter tuning. The mlr3cheatsheets contain frequently used commands and workflows of mlr3.

+ + +
+ + ]]>
+ tuning + resampling + mlr3pipelines + automl + classification + practical tuning series + https://mlr-org.com/gallery/optimization/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/ + Thu, 11 Mar 2021 00:00:00 GMT +
+ + Practical Tuning Series - Tune a Preprocessing Pipeline + Marc Becker + Theresa Ullmann + Michel Lang + Bernd Bischl + Jakob Richter + Martin Binder + https://mlr-org.com/gallery/optimization/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/ + +

Scope

+

This is the second part of the practical tuning series. The other parts can be found here:

+ +

In this post, we build a simple preprocessing pipeline and tune it. For this, we are using the mlr3pipelines extension package. First, we start by imputing missing values in the Pima Indians Diabetes data set. After that, we encode a factor column to numerical dummy columns in the data set. Next, we combine both preprocessing steps to a Graph and create a GraphLearner. Finally, nested resampling is used to compare the performance of two imputation methods.

+ +
+

Prerequisites

+

We load the mlr3verse package which pulls in the most important packages for this example.

+
+
library(mlr3verse)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented. The lgr package is used for logging in all mlr3 packages. The mlr3 logger prints the logging messages from the base package, whereas the bbotk logger is responsible for logging messages from the optimization packages (e.g. mlr3tuning ).

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+

In this example, we use the Pima Indians Diabetes data set which is used to predict whether or not a patient has diabetes. The patients are characterized by 8 numeric features of which some have missing values. We alter the data set by categorizing the feature pressure (blood pressure) into the categories "low", "mid", and "high".

+
+
# retrieve the task from mlr3
+task = tsk("pima")
+
+# create data frame with categorized pressure feature
+data = task$data(cols = "pressure")
+breaks = quantile(data$pressure, probs = c(0, 0.33, 0.66, 1), na.rm = TRUE)
+data$pressure = cut(data$pressure, breaks, labels = c("low", "mid", "high"))
+
+# overwrite the feature in the task
+task$cbind(data)
+
+# generate a quick textual overview
+skimr::skim(task$data())
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Data summary
Nametask$data()
Number of rows768
Number of columns9
KeyNULL
_______________________
Column type frequency:
factor2
numeric7
________________________
Group variablesNone
+

Variable type: factor

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_rateorderedn_uniquetop_counts
diabetes01.00FALSE2neg: 500, pos: 268
pressure360.95FALSE3low: 282, mid: 245, hig: 205
+

Variable type: numeric

+ +++++++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_ratemeansdp0p25p50p75p100hist
age01.0033.2411.7621.0024.0029.0041.0081.00▇▃▁▁▁
glucose50.99121.6930.5444.0099.00117.00141.00199.00▁▇▇▃▂
insulin3740.51155.55118.7814.0076.25125.00190.00846.00▇▂▁▁▁
mass110.9932.466.9218.2027.5032.3036.6067.10▅▇▃▁▁
pedigree01.000.470.330.080.240.370.632.42▇▃▁▁▁
pregnant01.003.853.370.001.003.006.0017.00▇▃▂▁▁
triceps2270.7029.1510.487.0022.0029.0036.0099.00▆▇▁▁▁
+
+
+

We choose the xgboost algorithm from the xgboost package as learner.

+
+
learner = lrn("classif.xgboost", nrounds = 100, id = "xgboost", verbose = 0)
+
+
+
+

Missing Values

+

The task has missing data in five columns.

+
+
round(task$missings() / task$nrow, 2)
+
+
diabetes      age  glucose  insulin     mass pedigree pregnant pressure  triceps 
+    0.00     0.00     0.01     0.49     0.01     0.00     0.00     0.05     0.30 
+
+
+

The xgboost learner has an internal method for handling missing data but some learners cannot handle missing values. We will try to beat the internal method in terms of predictive performance. The mlr3pipelines package offers various methods to impute missing values.

+
+
mlr_pipeops$keys("^impute")
+
+
[1] "imputeconstant" "imputehist"     "imputelearner"  "imputemean"     "imputemedian"   "imputemode"    
+[7] "imputeoor"      "imputesample"  
+
+
+

We choose the PipeOpImputeOOR that adds the new factor level ".MISSING". to factorial features and imputes numerical features by constant values shifted below the minimum (default) or above the maximum.

+
+
imputer = po("imputeoor")
+print(imputer)
+
+
PipeOp: <imputeoor> (not trained)
+values: <min=TRUE, offset=1, multiplier=1>
+Input channels <name [train type, predict type]>:
+  input [Task,Task]
+Output channels <name [train type, predict type]>:
+  output [Task,Task]
+
+
+

As the output suggests, the in- and output of this pipe operator is a Task for both the training and the predict step. We can manually train the pipe operator to check its functionality:

+
+
task_imputed = imputer$train(list(task))[[1]]
+task_imputed$missings()
+
+
diabetes      age pedigree pregnant  glucose  insulin     mass pressure  triceps 
+       0        0        0        0        0        0        0        0        0 
+
+
+

Let’s compare an observation with missing values to the observation with imputed observation.

+
+
rbind(
+  task$data()[8,],
+  task_imputed$data()[8,]
+)
+
+
   diabetes age glucose insulin mass pedigree pregnant pressure triceps
+1:      neg  29     115      NA 35.3    0.134       10     <NA>      NA
+2:      neg  29     115    -819 35.3    0.134       10 .MISSING     -86
+
+
+

Note that OOR imputation is in particular useful for tree-based models, but should not be used for linear models or distance-based models.

+
+
+

Factor Encoding

+

The xgboost learner cannot handle categorical features. Therefore, we must to convert factor columns to numerical dummy columns. For this, we argument the xgboost learner with automatic factor encoding.

+

The PipeOpEncode encodes factor columns with one of six methods. In this example, we use one-hot encoding which creates a new binary column for each factor level.

+
+
factor_encoding = po("encode", method = "one-hot")
+
+

We manually trigger the encoding on the task.

+
+
factor_encoding$train(list(task))
+
+
$output
+<TaskClassif:pima> (768 x 11): Pima Indian Diabetes
+* Target: diabetes
+* Properties: twoclass
+* Features (10):
+  - dbl (10): age, glucose, insulin, mass, pedigree, pregnant, pressure.high, pressure.low, pressure.mid,
+    triceps
+
+
+

The factor column pressure has been converted to the three binary columns "pressure.low", "pressure.mid", and "pressure.high".

+
+
+

Constructing the Pipeline

+

We created two preprocessing steps which could be used to create a new task with encoded factor variables and imputed missing values. However, if we do this before resampling, information from the test can leak into our training step which typically leads to overoptimistic performance measures. To avoid this, we add the preprocessing steps to the Learner itself, creating a GraphLearner. For this, we create a Graph first.

+
+
graph = po("encode") %>>%
+  po("imputeoor") %>>%
+  learner
+plot(graph, html = FALSE)
+
+
+
+

+
+
+
+
+

We use as_learner() to wrap the Graph into a GraphLearner with which allows us to use the graph like a normal learner.

+
+
graph_learner = as_learner(graph)
+
+# short learner id for printing
+graph_learner$id = "graph_learner"
+
+

The GraphLearner can be trained and used for making predictions. Instead of calling $train() or $predict() manually, we will directly use it for resampling. We choose a 3-fold cross-validation as the resampling strategy.

+
+
resampling = rsmp("cv", folds = 3)
+
+rr = resample(task = task, learner = graph_learner, resampling = resampling)
+
+
+
rr$score()[, c("iteration", "task_id", "learner_id", "resampling_id", "classif.ce"), with = FALSE]
+
+
   iteration task_id    learner_id resampling_id classif.ce
+1:         1    pima graph_learner            cv  0.2851562
+2:         2    pima graph_learner            cv  0.2460938
+3:         3    pima graph_learner            cv  0.2968750
+
+
+

For each resampling iteration, the following steps are performed:

+
    +
  1. The task is subsetted to the training indices.
  2. +
  3. The factor encoder replaces factor features with dummy columns in the training task.
  4. +
  5. The OOR imputer determines values to impute from the training task and then replaces all missing values with learned imputation values.
  6. +
  7. The learner is applied on the modified training task and the model is stored inside the learner.
  8. +
+

Next is the predict step:

+
    +
  1. The task is subsetted to the test indices.
  2. +
  3. The factor encoder replaces all factor features with dummy columns in the test task.
  4. +
  5. The OOR imputer replaces all missing values of the test task with the imputation values learned on the training set.
  6. +
  7. The learner’s predict method is applied on the modified test task.
  8. +
+

By following this procedure, it is guaranteed that no information can leak from the training step to the predict step.

+
+
+

Tuning the Pipeline

+

Let’s have a look at the parameter set of the GraphLearner. It consists of the xgboost hyperparameters, and additionally, the parameter of the PipeOp encode and imputeoor. All hyperparameters are prefixed with the id of the respective PipeOp or learner.

+
+
as.data.table(graph_learner$param_set)[, c("id", "class", "lower", "upper", "nlevels"), with = FALSE]
+
+
                                     id    class lower upper nlevels
+ 1:                       encode.method ParamFct    NA    NA       5
+ 2:               encode.affect_columns ParamUty    NA    NA     Inf
+ 3:                       imputeoor.min ParamLgl    NA    NA       2
+ 4:                    imputeoor.offset ParamDbl     0   Inf     Inf
+ 5:                imputeoor.multiplier ParamDbl     0   Inf     Inf
+ 6:            imputeoor.affect_columns ParamUty    NA    NA     Inf
+ 7:                       xgboost.alpha ParamDbl     0   Inf     Inf
+ 8:               xgboost.approxcontrib ParamLgl    NA    NA       2
+ 9:                  xgboost.base_score ParamDbl  -Inf   Inf     Inf
+10:                     xgboost.booster ParamFct    NA    NA       3
+11:                   xgboost.callbacks ParamUty    NA    NA     Inf
+12:           xgboost.colsample_bylevel ParamDbl     0     1     Inf
+13:            xgboost.colsample_bynode ParamDbl     0     1     Inf
+14:            xgboost.colsample_bytree ParamDbl     0     1     Inf
+15: xgboost.disable_default_eval_metric ParamLgl    NA    NA       2
+16:       xgboost.early_stopping_rounds ParamInt     1   Inf     Inf
+17:          xgboost.early_stopping_set ParamFct    NA    NA       3
+18:                         xgboost.eta ParamDbl     0     1     Inf
+19:                 xgboost.eval_metric ParamUty    NA    NA     Inf
+20:            xgboost.feature_selector ParamFct    NA    NA       5
+21:                       xgboost.feval ParamUty    NA    NA     Inf
+22:                       xgboost.gamma ParamDbl     0   Inf     Inf
+23:                 xgboost.grow_policy ParamFct    NA    NA       2
+24:     xgboost.interaction_constraints ParamUty    NA    NA     Inf
+25:              xgboost.iterationrange ParamUty    NA    NA     Inf
+26:                      xgboost.lambda ParamDbl     0   Inf     Inf
+27:                 xgboost.lambda_bias ParamDbl     0   Inf     Inf
+28:                     xgboost.max_bin ParamInt     2   Inf     Inf
+29:              xgboost.max_delta_step ParamDbl     0   Inf     Inf
+30:                   xgboost.max_depth ParamInt     0   Inf     Inf
+31:                  xgboost.max_leaves ParamInt     0   Inf     Inf
+32:                    xgboost.maximize ParamLgl    NA    NA       2
+33:            xgboost.min_child_weight ParamDbl     0   Inf     Inf
+34:                     xgboost.missing ParamDbl  -Inf   Inf     Inf
+35:        xgboost.monotone_constraints ParamUty    NA    NA     Inf
+36:              xgboost.normalize_type ParamFct    NA    NA       2
+37:                     xgboost.nrounds ParamInt     1   Inf     Inf
+38:                     xgboost.nthread ParamInt     1   Inf     Inf
+39:                  xgboost.ntreelimit ParamInt     1   Inf     Inf
+40:           xgboost.num_parallel_tree ParamInt     1   Inf     Inf
+41:                   xgboost.objective ParamUty    NA    NA     Inf
+42:                    xgboost.one_drop ParamLgl    NA    NA       2
+43:                xgboost.outputmargin ParamLgl    NA    NA       2
+44:                 xgboost.predcontrib ParamLgl    NA    NA       2
+45:                   xgboost.predictor ParamFct    NA    NA       2
+46:             xgboost.predinteraction ParamLgl    NA    NA       2
+47:                    xgboost.predleaf ParamLgl    NA    NA       2
+48:               xgboost.print_every_n ParamInt     1   Inf     Inf
+49:                xgboost.process_type ParamFct    NA    NA       2
+50:                   xgboost.rate_drop ParamDbl     0     1     Inf
+51:                xgboost.refresh_leaf ParamLgl    NA    NA       2
+52:                     xgboost.reshape ParamLgl    NA    NA       2
+53:          xgboost.seed_per_iteration ParamLgl    NA    NA       2
+54:             xgboost.sampling_method ParamFct    NA    NA       2
+55:                 xgboost.sample_type ParamFct    NA    NA       2
+56:                   xgboost.save_name ParamUty    NA    NA     Inf
+57:                 xgboost.save_period ParamInt     0   Inf     Inf
+58:            xgboost.scale_pos_weight ParamDbl  -Inf   Inf     Inf
+59:                   xgboost.skip_drop ParamDbl     0     1     Inf
+60:                xgboost.strict_shape ParamLgl    NA    NA       2
+61:                   xgboost.subsample ParamDbl     0     1     Inf
+62:                       xgboost.top_k ParamInt     0   Inf     Inf
+63:                    xgboost.training ParamLgl    NA    NA       2
+64:                 xgboost.tree_method ParamFct    NA    NA       5
+65:      xgboost.tweedie_variance_power ParamDbl     1     2     Inf
+66:                     xgboost.updater ParamUty    NA    NA     Inf
+67:                     xgboost.verbose ParamInt     0     2       3
+68:                   xgboost.watchlist ParamUty    NA    NA     Inf
+69:                   xgboost.xgb_model ParamUty    NA    NA     Inf
+                                     id    class lower upper nlevels
+
+
+

We will tune the encode method.

+
+
graph_learner$param_set$values$encode.method = to_tune(c("one-hot", "treatment"))
+
+

We define a tuning instance and use grid search since we want to try all encode methods.

+
+
instance = tune(
+  tuner = tnr("grid_search"),
+  task = task,
+  learner = graph_learner,
+  resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce")
+)
+
+

The archive shows us the performance of the model with different encoding methods.

+
+
print(instance$archive)
+
+
<ArchiveTuning> with 2 evaluations
+   encode.method classif.ce batch_nr warnings errors
+1:     treatment       0.26        1        0      0
+2:       one-hot       0.26        2        0      0
+
+
+
+
+

Nested Resampling

+

We create one GraphLearner with imputeoor and test it against a GraphLearner that uses the internal imputation method of xgboost. Applying nested resampling ensures a fair comparison of the predictive performances.

+
+
graph_1 = po("encode") %>>%
+  learner
+graph_learner_1 = GraphLearner$new(graph_1)
+
+graph_learner_1$param_set$values$encode.method = to_tune(c("one-hot", "treatment"))
+
+at_1 = AutoTuner$new(
+  learner = graph_learner_1,
+  resampling = resampling,
+  measure = msr("classif.ce"),
+  terminator = trm("none"),
+  tuner = tnr("grid_search"),
+  store_models = TRUE
+)
+
+
+
graph_2 = po("encode") %>>%
+  po("imputeoor") %>>%
+  learner
+graph_learner_2 = GraphLearner$new(graph_2)
+
+graph_learner_2$param_set$values$encode.method = to_tune(c("one-hot", "treatment"))
+
+at_2 = AutoTuner$new(
+  learner = graph_learner_2,
+  resampling = resampling,
+  measure = msr("classif.ce"),
+  terminator = trm("none"),
+  tuner = tnr("grid_search"),
+  store_models = TRUE
+)
+
+

We run the benchmark.

+
+
resampling_outer = rsmp("cv", folds = 3)
+design = benchmark_grid(task, list(at_1, at_2), resampling_outer)
+
+bmr = benchmark(design, store_models = TRUE)
+
+

We compare the aggregated performances on the outer test sets which give us an unbiased performance estimate of the GraphLearners with the different encoding methods.

+
+
bmr$aggregate()
+
+
   nr task_id                     learner_id resampling_id iters classif.ce
+1:  1    pima           encode.xgboost.tuned            cv     3  0.2578125
+2:  2    pima encode.imputeoor.xgboost.tuned            cv     3  0.2630208
+Hidden columns: resample_result
+
+
autoplot(bmr)
+
+
+
+

+
+
+
+
+

Note that in practice, it is required to tune preprocessing hyperparameters jointly with the hyperparameters of the learner. Otherwise, comparing preprocessing steps is not feasible and can lead to wrong conclusions.

+

Applying nested resampling can be shortened by using the auto_tuner()-shortcut.

+
+
graph_1 = po("encode") %>>% learner
+graph_learner_1 = as_learner(graph_1)
+graph_learner_1$param_set$values$encode.method = to_tune(c("one-hot", "treatment"))
+
+at_1 = auto_tuner(
+  method = "grid_search",
+  learner = graph_learner_1,
+  resampling = resampling,
+  measure = msr("classif.ce"),
+  store_models = TRUE)
+
+graph_2 = po("encode") %>>% po("imputeoor") %>>% learner
+graph_learner_2 = as_learner(graph_2)
+graph_learner_2$param_set$values$encode.method = to_tune(c("one-hot", "treatment"))
+
+at_2 = auto_tuner(
+  method = "grid_search",
+  learner = graph_learner_2,
+  resampling = resampling,
+  measure = msr("classif.ce"),
+  store_models = TRUE)
+
+design = benchmark_grid(task, list(at_1, at_2), rsmp("cv", folds = 3))
+
+bmr = benchmark(design, store_models = TRUE)
+
+
+
+

Final Model

+

We train the chosen GraphLearner with the AutoTuner to get a final model with optimized hyperparameters.

+
+
at_2$train(task)
+
+

The trained model can now be used to make predictions on new data at_2$predict(). The pipeline ensures that the preprocessing is always a part of the train and predict step.

+
+
+

Resources

+

The mlr3book includes chapters on pipelines and hyperparameter tuning. The mlr3cheatsheets contain frequently used commands and workflows of mlr3.

+ + +
+ + ]]>
+ tuning + resampling + mlr3pipelines + classification + practical tuning series + https://mlr-org.com/gallery/optimization/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/ + Wed, 10 Mar 2021 00:00:00 GMT +
+ + Practical Tuning Series - Tune a Support Vector Machine + Marc Becker + Theresa Ullmann + Michel Lang + Bernd Bischl + Jakob Richter + Martin Binder + https://mlr-org.com/gallery/optimization/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/ + +
requireNamespace("DiceKriging")
+
+
Loading required namespace: DiceKriging
+
+ +
+

Scope

+

This is the first part of the practical tuning series. The other parts can be found here:

+ +

In this post, we demonstrate how to optimize the hyperparameters of a support vector machine (SVM). We are using the mlr3 machine learning framework with the mlr3tuning extension package.

+

First, we start by showing the basic building blocks of mlr3tuning and tune the cost and gamma hyperparameters of an SVM with a radial basis function on the Iris data set. After that, we use transformations to tune the both hyperparameters on the logarithmic scale. Next, we explain the importance of dependencies to tune hyperparameters like degree which are dependent on the choice of kernel. After that, we fit an SVM with optimized hyperparameters on the full dataset. Finally, nested resampling is used to compute an unbiased performance estimate of our tuned SVM.

+
+
+

Prerequisites

+

We load the mlr3verse package which pulls in the most important packages for this example.

+
+
library(mlr3verse)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented. The lgr package is used for logging in all mlr3 packages. The mlr3 logger prints the logging messages from the base package, whereas the bbotk logger is responsible for logging messages from the optimization packages (e.g. mlr3tuning ).

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+

In the example, we use the Iris data set which classifies 150 flowers in three species of Iris. The flowers are characterized by sepal length and width and petal length and width. The Iris data set allows us to quickly fit models to it. However, the influence of hyperparameter tuning on the predictive performance might be minor. Other data sets might give more meaningful tuning results.

+
+
# retrieve the task from mlr3
+task = tsk("iris")
+
+# generate a quick textual overview using the skimr package
+skimr::skim(task$data())
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Data summary
Nametask$data()
Number of rows150
Number of columns5
KeyNULL
_______________________
Column type frequency:
factor1
numeric4
________________________
Group variablesNone
+

Variable type: factor

+ ++++++++ + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_rateorderedn_uniquetop_counts
Species01FALSE3set: 50, ver: 50, vir: 50
+

Variable type: numeric

+ +++++++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_ratemeansdp0p25p50p75p100hist
Petal.Length013.761.771.01.64.355.16.9▇▁▆▇▂
Petal.Width011.200.760.10.31.301.82.5▇▁▇▅▃
Sepal.Length015.840.834.35.15.806.47.9▆▇▇▅▂
Sepal.Width013.060.442.02.83.003.34.4▁▆▇▂▁
+
+
+

We choose the support vector machine implementation from the e1071 package (which is based on LIBSVM) and use it as a classification machine by setting type to "C-classification".

+
+
learner = lrn("classif.svm", type = "C-classification", kernel = "radial")
+
+
+
+

Tuning Search Space

+

For tuning, it is important to create a search space that defines the type and range of the hyperparameters. A learner stores all information about its hyperparameters in the slot $param_set. Not all parameters are tunable. We have to choose a subset of the hyperparameters we want to tune.

+
+
as.data.table(learner$param_set)[, .(id, class, lower, upper, nlevels)]
+
+

We use the to_tune() function to define the range over which the hyperparameter should be tuned. We opt for the cost and gamma hyperparameters of the radial kernel and set the tuning ranges with lower and upper bounds.

+
+
learner$param_set$values$cost = to_tune(0.1, 10)
+learner$param_set$values$gamma = to_tune(0, 5)
+
+
+
+

Tuning

+

We specify how to evaluate the performance of the different hyperparameter configurations. For this, we choose 3-fold cross validation as the resampling strategy and the classification error as the performance measure.

+
+
resampling = rsmp("cv", folds = 3)
+measure = msr("classif.ce")
+
+

Usually, we have to select a budget for the tuning. This is done by choosing a Terminator, which stops the tuning e.g. after a performance level is reached or after a given time. However, some tuners like grid search terminate themselves. In this case, we choose a terminator that never stops and the tuning is not stopped before all grid points are evaluated.

+
+
terminator = trm("none")
+
+

At this point, we can construct a TuningInstanceSingleCrit that describes the tuning problem.

+
+
instance = TuningInstanceSingleCrit$new(
+  task = task,
+  learner = learner,
+  resampling = resampling,
+  measure = measure,
+  terminator = terminator
+)
+
+print(instance)
+
+
<TuningInstanceSingleCrit>
+* State:  Not optimized
+* Objective: <ObjectiveTuning:classif.svm_on_iris>
+* Search Space:
+      id    class lower upper nlevels
+1:  cost ParamDbl   0.1    10     Inf
+2: gamma ParamDbl   0.0     5     Inf
+* Terminator: <TerminatorNone>
+
+
+

Finally, we have to choose a Tuner. Grid Search discretizes numeric parameters into a given resolution and constructs a grid from the Cartesian product of these sets. Categorical parameters produce a grid over all levels specified in the search space. In this example, we only use a resolution of 5 to keep the runtime low. Usually, a higher resolution is used to create a denser grid.

+
+
tuner = tnr("grid_search", resolution = 5)
+
+print(tuner)
+
+
<TunerGridSearch>: Grid Search
+* Parameters: resolution=5, batch_size=1
+* Parameter classes: ParamLgl, ParamInt, ParamDbl, ParamFct
+* Properties: dependencies, single-crit, multi-crit
+* Packages: mlr3tuning
+
+
+

We can preview the proposed configurations by using generate_design_grid(). This function is internally executed by TunerGridSearch.

+
+
generate_design_grid(learner$param_set$search_space(), resolution = 5)
+
+
<Design> with 25 rows:
+      cost gamma
+ 1:  0.100  0.00
+ 2:  0.100  1.25
+ 3:  0.100  2.50
+ 4:  0.100  3.75
+ 5:  0.100  5.00
+ 6:  2.575  0.00
+ 7:  2.575  1.25
+ 8:  2.575  2.50
+ 9:  2.575  3.75
+10:  2.575  5.00
+11:  5.050  0.00
+12:  5.050  1.25
+13:  5.050  2.50
+14:  5.050  3.75
+15:  5.050  5.00
+16:  7.525  0.00
+17:  7.525  1.25
+18:  7.525  2.50
+19:  7.525  3.75
+20:  7.525  5.00
+21: 10.000  0.00
+22: 10.000  1.25
+23: 10.000  2.50
+24: 10.000  3.75
+25: 10.000  5.00
+      cost gamma
+
+
+

We trigger the tuning by passing the TuningInstanceSingleCrit to the $optimize() method of the Tuner. The instance is modified in-place.

+
+
tuner$optimize(instance)
+
+
   cost gamma learner_param_vals  x_domain classif.ce
+1: 5.05  1.25          <list[4]> <list[2]>       0.06
+
+
+

We plot the performances depending on the evaluated cost and gamma values.

+
+
autoplot(instance, type = "surface", cols_x = c("cost", "gamma"),
+  learner = lrn("regr.km"))
+
+
+
+
+
+

+
+
+
+
+

The points mark the evaluated cost and gamma values. We should not infer the performance of new values from the heatmap since it is only an interpolation. However, we can see the general interaction between the hyperparameters.

+

Tuning a learner can be shortened by using the tune()-shortcut.

+
+
learner = lrn("classif.svm", type = "C-classification", kernel = "radial")
+learner$param_set$values$cost = to_tune(0.1, 10)
+learner$param_set$values$gamma = to_tune(0, 5)
+
+instance = tune(
+  tuner = tnr("grid_search", resolution = 5),
+  task = tsk("iris"),
+  learner = learner,
+  resampling = rsmp ("holdout"),
+  measure = msr("classif.ce")
+)
+
+
+
+

Transformation

+

Next, we want to tune the cost and gamma hyperparameter more efficiently. It is recommended to tune cost and gamma on the logarithmic scale (Hsu, Chang, and Lin 2003). The log transformation emphasizes smaller cost and gamma values but also creates large values. Therefore, we use a log transformation to emphasize this region of the search space with a denser grid.

+

Generally speaking, transformations can be used to convert hyperparameters to a new scale. These transformations are applied before the proposed configuration is passed to the Learner. We can directly define the transformation in the to_tune() function. The lower and upper bound is set on the original scale.

+
+
learner = lrn("classif.svm", type = "C-classification", kernel = "radial")
+
+# tune from 2^-15 to 2^15 on a log scale
+learner$param_set$values$cost = to_tune(p_dbl(-15, 15, trafo = function(x) 2^x))
+
+# tune from 2^-15 to 2^5 on a log scale
+learner$param_set$values$gamma = to_tune(p_dbl(-15, 5, trafo = function(x) 2^x))
+
+

Transformations to the log scale are the ones most commonly used. We can use a shortcut for this transformation. The lower and upper bound is set on the transformed scale.

+
+
learner$param_set$values$cost = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))
+learner$param_set$values$gamma = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))
+
+

We use the tune()-shortcut to run the tuning.

+
+
instance = tune(
+  tuner = tnr("grid_search", resolution = 5),
+  task = task,
+  learner = learner,
+  resampling = resampling,
+  measure = measure
+)
+
+

The hyperparameter values after the transformation are stored in the x_domain column as lists. We can expand these lists into multiple columns by using as.data.table(). The hyperparameter names are prefixed by x_domain.

+
+
as.data.table(instance$archive)[, .(cost, gamma, x_domain_cost, x_domain_gamma)]
+
+
          cost      gamma x_domain_cost x_domain_gamma
+ 1:  -5.756463 -11.512925  3.162278e-03   1.000000e-05
+ 2:   0.000000  11.512925  1.000000e+00   1.000000e+05
+ 3: -11.512925  11.512925  1.000000e-05   1.000000e+05
+ 4:  11.512925   5.756463  1.000000e+05   3.162278e+02
+ 5: -11.512925   0.000000  1.000000e-05   1.000000e+00
+ 6:  11.512925  -5.756463  1.000000e+05   3.162278e-03
+ 7:  11.512925   0.000000  1.000000e+05   1.000000e+00
+ 8: -11.512925   5.756463  1.000000e-05   3.162278e+02
+ 9:   0.000000   0.000000  1.000000e+00   1.000000e+00
+10:   5.756463   0.000000  3.162278e+02   1.000000e+00
+11:   0.000000  -5.756463  1.000000e+00   3.162278e-03
+12:   0.000000 -11.512925  1.000000e+00   1.000000e-05
+13:  -5.756463  -5.756463  3.162278e-03   3.162278e-03
+14:  11.512925 -11.512925  1.000000e+05   1.000000e-05
+15:   5.756463  11.512925  3.162278e+02   1.000000e+05
+16:   0.000000   5.756463  1.000000e+00   3.162278e+02
+17:  -5.756463   0.000000  3.162278e-03   1.000000e+00
+18:   5.756463 -11.512925  3.162278e+02   1.000000e-05
+19:  -5.756463  11.512925  3.162278e-03   1.000000e+05
+20:  11.512925  11.512925  1.000000e+05   1.000000e+05
+21:   5.756463  -5.756463  3.162278e+02   3.162278e-03
+22: -11.512925 -11.512925  1.000000e-05   1.000000e-05
+23: -11.512925  -5.756463  1.000000e-05   3.162278e-03
+24:   5.756463   5.756463  3.162278e+02   3.162278e+02
+25:  -5.756463   5.756463  3.162278e-03   3.162278e+02
+          cost      gamma x_domain_cost x_domain_gamma
+
+
+

We plot the performances depending on the evaluated cost and gamma values.

+
+
library(ggplot2)
+library(scales)
+autoplot(instance, type = "points", cols_x = c("x_domain_cost", "x_domain_gamma")) +
+  scale_x_continuous(
+    trans = log2_trans(),
+    breaks = trans_breaks("log10", function(x) 10^x),
+    labels = trans_format("log10", math_format(10^.x))) +
+  scale_y_continuous(
+    trans = log2_trans(),
+    breaks = trans_breaks("log10", function(x) 10^x),
+    labels = trans_format("log10", math_format(10^.x)))
+
+
+
+

+
+
+
+
+
+
+

Dependencies

+

Dependencies ensure that certain parameters are only proposed depending on values of other hyperparameters. We want to tune the degree hyperparameter that is only needed for the polynomial kernel.

+
+
learner = lrn("classif.svm", type = "C-classification")
+
+learner$param_set$values$cost = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))
+learner$param_set$values$gamma = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))
+
+learner$param_set$values$kernel = to_tune(c("polynomial", "radial"))
+learner$param_set$values$degree = to_tune(1, 4)
+
+

The dependencies are already stored in the learner parameter set.

+
+
learner$param_set$deps
+
+
       id     on           cond
+1:   cost   type <CondEqual[9]>
+2:     nu   type <CondEqual[9]>
+3: degree kernel <CondEqual[9]>
+4:  coef0 kernel <CondAnyOf[9]>
+5:  gamma kernel <CondAnyOf[9]>
+
+
+

The gamma hyperparameter depends on the kernel being polynomial, radial or sigmoid

+
+
learner$param_set$deps$cond[[5]]
+
+
CondAnyOf: x ∈ {polynomial, radial, sigmoid}
+
+
+

whereas the degree hyperparameter is solely used by the polynomial kernel.

+
+
learner$param_set$deps$cond[[3]]
+
+
CondEqual: x = polynomial
+
+
+

We preview the grid to show the effect of the dependencies.

+
+
generate_design_grid(learner$param_set$search_space(), resolution = 2)
+
+
<Design> with 12 rows:
+         cost     gamma     kernel degree
+ 1: -11.51293 -11.51293 polynomial      1
+ 2: -11.51293 -11.51293 polynomial      4
+ 3: -11.51293 -11.51293     radial     NA
+ 4: -11.51293  11.51293 polynomial      1
+ 5: -11.51293  11.51293 polynomial      4
+ 6: -11.51293  11.51293     radial     NA
+ 7:  11.51293 -11.51293 polynomial      1
+ 8:  11.51293 -11.51293 polynomial      4
+ 9:  11.51293 -11.51293     radial     NA
+10:  11.51293  11.51293 polynomial      1
+11:  11.51293  11.51293 polynomial      4
+12:  11.51293  11.51293     radial     NA
+
+
+

The value for degree is NA if the dependency on the kernel is not satisfied.

+

We use the tune()-shortcut to run the tuning.

+
+
instance = tune(
+  tuner = tnr("grid_search", resolution = 3),
+  task = task,
+  learner = learner,
+  resampling = resampling,
+  measure = measure
+)
+
+
+
instance$result
+
+
   cost    gamma     kernel degree learner_param_vals  x_domain classif.ce
+1:    0 11.51293 polynomial      1          <list[5]> <list[4]> 0.02666667
+
+
+
+
+

Final Model

+

We add the optimized hyperparameters to the learner and train the learner on the full dataset.

+
+
learner = lrn("classif.svm")
+learner$param_set$values = instance$result_learner_param_vals
+learner$train(task)
+
+

The trained model can now be used to make predictions on new data. A common mistake is to report the performance estimated on the resampling sets on which the tuning was performed (instance$result_y) as the model’s performance. These scores might be biased and overestimate the ability of the fitted model to predict with new data. Instead, we have to use nested resampling to get an unbiased performance estimate.

+
+
+

Nested Resampling

+

Tuning should not be performed on the same resampling sets which are used for evaluating the model itself, since this would result in a biased performance estimate. Nested resampling uses an outer and inner resampling to separate the tuning from the performance estimation of the model. We can use the AutoTuner class for running nested resampling. The AutoTuner wraps a Learner and tunes the hyperparameter of the learner during $train(). This is our inner resampling loop.

+
+
learner = lrn("classif.svm", type = "C-classification")
+learner$param_set$values$cost = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))
+learner$param_set$values$gamma = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))
+learner$param_set$values$kernel = to_tune(c("polynomial", "radial"))
+learner$param_set$values$degree = to_tune(1, 4)
+
+resampling_inner = rsmp("cv", folds = 3)
+terminator = trm("none")
+tuner = tnr("grid_search", resolution = 3)
+
+at = AutoTuner$new(
+  learner = learner,
+  resampling = resampling_inner,
+  measure = measure,
+  terminator = terminator,
+  tuner = tuner,
+  store_models = TRUE)
+
+

We put the AutoTuner into a resample() call to get the outer resampling loop.

+
+
resampling_outer = rsmp("cv", folds = 3)
+rr = resample(task = task, learner = at, resampling = resampling_outer, store_models = TRUE)
+
+

We check the inner tuning results for stable hyperparameters. This means that the selected hyperparameters should not vary too much. We might observe unstable models in this example because the small data set and the low number of resampling iterations might introduce too much randomness. Usually, we aim for the selection of stable hyperparameters for all outer training sets.

+
+
extract_inner_tuning_results(rr)[, .SD, .SDcols = !c("learner_param_vals", "x_domain")]
+
+
   iteration     cost     gamma     kernel degree classif.ce task_id        learner_id resampling_id
+1:         1  0.00000   0.00000 polynomial      1 0.03000594    iris classif.svm.tuned            cv
+2:         2  0.00000   0.00000 polynomial      1 0.03000594    iris classif.svm.tuned            cv
+3:         3 11.51293 -11.51293     radial     NA 0.02020202    iris classif.svm.tuned            cv
+
+
+

Next, we want to compare the predictive performances estimated on the outer resampling to the inner resampling (extract_inner_tuning_results(rr)). Significantly lower predictive performances on the outer resampling indicate that the models with the optimized hyperparameters overfit the data.

+
+
rr$score()[, .(iteration, task_id, learner_id, resampling_id, classif.ce)]
+
+
   iteration task_id        learner_id resampling_id classif.ce
+1:         1    iris classif.svm.tuned            cv       0.04
+2:         2    iris classif.svm.tuned            cv       0.06
+3:         3    iris classif.svm.tuned            cv       0.00
+
+
+

The archives of the AutoTuners allows us to inspect all evaluated hyperparameters configurations with the associated predictive performances.

+
+
extract_inner_tuning_archives(rr, unnest = NULL, exclude_columns = c("resample_result", "uhash", "x_domain", "timestamp"))
+
+
     iteration      cost     gamma     kernel degree classif.ce runtime_learners batch_nr warnings errors task_id
+  1:         1   0.00000 -11.51293 polynomial      2 0.68033274            0.017        1        0      0    iris
+  2:         1   0.00000 -11.51293     radial     NA 0.64111705            0.017        2        0      0    iris
+  3:         1   0.00000   0.00000 polynomial      1 0.03000594            0.017        3        0      0    iris
+  4:         1  11.51293   0.00000 polynomial      1 0.05050505            0.012        4        0      0    iris
+  5:         1  11.51293  11.51293     radial     NA 0.66013072            0.014        5        0      0    iris
+ ---                                                                                                             
+104:         3  11.51293 -11.51293 polynomial      2 0.68924540            0.013       32        0      0    iris
+105:         3 -11.51293 -11.51293     radial     NA 0.68924540            0.012       33        0      0    iris
+106:         3 -11.51293  11.51293 polynomial      4 0.11883541            0.015       34        0      0    iris
+107:         3   0.00000 -11.51293 polynomial      4 0.68924540            0.015       35        0      0    iris
+108:         3  11.51293  11.51293 polynomial      1 0.06951872            0.725       36        0      0    iris
+            learner_id resampling_id
+  1: classif.svm.tuned            cv
+  2: classif.svm.tuned            cv
+  3: classif.svm.tuned            cv
+  4: classif.svm.tuned            cv
+  5: classif.svm.tuned            cv
+ ---                                
+104: classif.svm.tuned            cv
+105: classif.svm.tuned            cv
+106: classif.svm.tuned            cv
+107: classif.svm.tuned            cv
+108: classif.svm.tuned            cv
+
+
+

The aggregated performance of all outer resampling iterations is essentially the unbiased performance of an SVM with optimal hyperparameter found by grid search.

+
+
rr$aggregate()
+
+
classif.ce 
+0.03333333 
+
+
+

Applying nested resampling can be shortened by using the tune_nested()-shortcut.

+
+
learner = lrn("classif.svm", type = "C-classification")
+learner$param_set$values$cost = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))
+learner$param_set$values$gamma = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))
+learner$param_set$values$kernel = to_tune(c("polynomial", "radial"))
+learner$param_set$values$degree = to_tune(1, 4)
+
+rr = tune_nested(
+  tuner = tnr("grid_search", resolution = 3),
+  task = tsk("iris"),
+  learner = learner,
+  inner_resampling = rsmp ("cv", folds = 3),
+  outer_resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce"),
+)
+
+
+
+

Resources

+

The mlr3book includes chapters on tuning spaces and hyperparameter tuning. The mlr3cheatsheets contain frequently used commands and workflows of mlr3.

+ + + +
+ +

References

+
+Hsu, Chih-wei, Chih-chung Chang, and Chih-Jen Lin. 2003. “A Practical Guide to Support Vector Classification.” +
+
]]>
+ tuning + resampling + classification + practical tuning series + https://mlr-org.com/gallery/optimization/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/ + Tue, 09 Mar 2021 00:00:00 GMT +
+ + Tuning a Complex Graph + Lennart Schneider + https://mlr-org.com/gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html + +
# include: false
+requireNamespace("bst")
+
+
Loading required namespace: bst
+
+
requireNamespace("fastICA")
+
+
Loading required namespace: fastICA
+
+ +

In this use case we show how to tune a rather complex graph consisting of different preprocessing steps and different learners where each preprocessing step and learner itself has parameters that can be tuned. You will learn the following:

+
    +
  • Build a Graph that consists of two common preprocessing steps, then switches between two dimensionality reduction techniques followed by a Learner vs. no dimensionality reduction followed by another Learner
  • +
  • Define the search space for tuning that handles inter-dependencies between pipeline steps and hyperparameters
  • +
  • Run a grid search to find an optimal choice of preprocessing steps and hyperparameters.
  • +
+

Ideally you already had a look at how to tune over multiple learners.

+

First, we load the packages we will need:

+
+
library(mlr3verse)
+library(mlr3learners)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented. The lgr package is used for logging in all mlr3 packages. The mlr3 logger prints the logging messages from the base package, whereas the bbotk logger is responsible for logging messages from the optimization packages (e.g. mlr3tuning ).

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+
+

Data and Task

+

We are going to work with some gene expression data included as a supplement in the bst package. The data consists of 2308 gene profiles in 63 training and 20 test samples. The following data preprocessing steps are done analogously as in vignette("khan", package = "bst"):

+
+
datafile = system.file("extdata", "supplemental_data", package = "bst")
+dat0 = read.delim(datafile, header = TRUE, skip = 1)[, -(1:2)]
+dat0 = t(dat0)
+dat = data.frame(dat0[!(rownames(dat0) %in%
+  c("TEST.9", "TEST.13", "TEST.5", "TEST.3", "TEST.11")), ])
+dat$class = as.factor(
+  c(substr(rownames(dat)[1:63], start = 1, stop = 2),
+    c("NB", "RM", "NB", "EW", "RM", "BL", "EW", "RM", "EW", "EW", "EW", "RM",
+      "BL", "RM", "NB", "NB", "NB", "NB", "BL", "EW")
+  )
+)
+
+

We then construct our training and test Task :

+
+
task = as_task_classif(dat, target = "class", id = "SRBCT")
+task_train = task$clone(deep = TRUE)
+task_train$filter(1:63)
+task_test = task$clone(deep = TRUE)
+task_test$filter(64:83)
+
+
+
+

Workflow

+

Our graph will start with log transforming the features, followed by scaling them. Then, either a PCA or ICA is applied to extract principal / independent components followed by fitting a LDA or a ranger random forest is fitted without any preprocessing (the log transformation and scaling should most likely affect the LDA more than the ranger random forest). Regarding the PCA and ICA, both the number of principal / independent components are tuning parameters. Regarding the LDA, we can further choose different methods for estimating the mean and variance and regarding the ranger, we want to tune the mtry and num.tree parameters. Note that the PCA-LDA combination has already been successfully applied in different cancer diagnostic contexts when the feature space is of high dimensionality (Morais and Lima 2018).

+

To allow for switching between the PCA / ICA-LDA and ranger we can either use branching or proxy pipelines, i.e., PipeOpBranch and PipeOpUnbranch or PipeOpProxy. We will first cover branching in detail and later show how the same can be done using PipeOpProxy.

+
+
+

Baseline

+

First, we have a look at the baseline classification accuracy of the LDA and ranger on the training task:

+
+
base = benchmark(benchmark_grid(
+  task_train,
+  learners = list(lrn("classif.lda"), lrn("classif.ranger")),
+  resamplings = rsmp("cv", folds = 3)))
+
+
Warning in lda.default(x, grouping, ...): variables are collinear
+
+Warning in lda.default(x, grouping, ...): variables are collinear
+
+Warning in lda.default(x, grouping, ...): variables are collinear
+
+
base$aggregate(measures = msr("classif.acc"))
+
+
   nr task_id     learner_id resampling_id iters classif.acc
+1:  1   SRBCT    classif.lda            cv     3   0.6666667
+2:  2   SRBCT classif.ranger            cv     3   0.9206349
+Hidden columns: resample_result
+
+
+

The out-of-the-box ranger appears to already have good performance on the training task. Regarding the LDA, we do get a warning message that some features are colinear. This strongly suggests to reduce the dimensionality of the feature space. Let’s see if we can get some better performance, at least for the LDA.

+
+
+

Branching

+

Our graph starts with log transforming the features (we explicitly use base 10 only for better interpretability when inspecting the model later), using PipeOpColApply, followed by scaling the features using PipeOpScale. Then, the first branch allows for switching between the PCA / ICA-LDA and ranger, and within PCA / ICA-LDA, the second branch allows for switching between PCA and ICA:

+
+
graph1 =
+  po("colapply", applicator = function(x) log(x, base = 10)) %>>%
+  po("scale") %>>%
+  # pca / ica followed by lda vs. ranger
+  po("branch", id = "branch_learner", options = c("pca_ica_lda", "ranger")) %>>%
+  gunion(list(
+    po("branch", id = "branch_preproc_lda", options = c("pca", "ica")) %>>%
+      gunion(list(
+        po("pca"), po("ica")
+      )) %>>%
+      po("unbranch", id = "unbranch_preproc_lda") %>>%
+      lrn("classif.lda"),
+    lrn("classif.ranger")
+  )) %>>%
+  po("unbranch", id = "unbranch_learner")
+
+

Note that the names of the options within each branch are arbitrary, but ideally they describe what is happening. Therefore we go with "pca_ica_lda" / "ranger” and "pca" / "ica". Finally, we also could have used the branch ppl to make branching easier (we will come back to this in the Proxy section). The graph looks like the following:

+
+
graph1$plot(html = FALSE)
+
+
+
+

+
+
+
+
+

We can inspect the parameters of the ParamSet of the graph to see which parameters can be set:

+
+
graph1$param_set$ids()
+
+
 [1] "colapply.applicator"                         "colapply.affect_columns"                    
+ [3] "scale.center"                                "scale.scale"                                
+ [5] "scale.robust"                                "scale.affect_columns"                       
+ [7] "branch_learner.selection"                    "branch_preproc_lda.selection"               
+ [9] "pca.center"                                  "pca.scale."                                 
+[11] "pca.rank."                                   "pca.affect_columns"                         
+[13] "ica.n.comp"                                  "ica.alg.typ"                                
+[15] "ica.fun"                                     "ica.alpha"                                  
+[17] "ica.method"                                  "ica.row.norm"                               
+[19] "ica.maxit"                                   "ica.tol"                                    
+[21] "ica.verbose"                                 "ica.w.init"                                 
+[23] "ica.affect_columns"                          "classif.lda.dimen"                          
+[25] "classif.lda.method"                          "classif.lda.nu"                             
+[27] "classif.lda.predict.method"                  "classif.lda.predict.prior"                  
+[29] "classif.lda.prior"                           "classif.lda.tol"                            
+[31] "classif.ranger.alpha"                        "classif.ranger.always.split.variables"      
+[33] "classif.ranger.class.weights"                "classif.ranger.holdout"                     
+[35] "classif.ranger.importance"                   "classif.ranger.keep.inbag"                  
+[37] "classif.ranger.max.depth"                    "classif.ranger.min.node.size"               
+[39] "classif.ranger.min.prop"                     "classif.ranger.minprop"                     
+[41] "classif.ranger.mtry"                         "classif.ranger.mtry.ratio"                  
+[43] "classif.ranger.num.random.splits"            "classif.ranger.num.threads"                 
+[45] "classif.ranger.num.trees"                    "classif.ranger.oob.error"                   
+[47] "classif.ranger.regularization.factor"        "classif.ranger.regularization.usedepth"     
+[49] "classif.ranger.replace"                      "classif.ranger.respect.unordered.factors"   
+[51] "classif.ranger.sample.fraction"              "classif.ranger.save.memory"                 
+[53] "classif.ranger.scale.permutation.importance" "classif.ranger.se.method"                   
+[55] "classif.ranger.seed"                         "classif.ranger.split.select.weights"        
+[57] "classif.ranger.splitrule"                    "classif.ranger.verbose"                     
+[59] "classif.ranger.write.forest"                
+
+
+

The id’s are prefixed by the respective PipeOp they belong to, e.g., pca.rank. refers to the rank. parameter of PipeOpPCA.

+
+
+

Search Space

+

Our graph either fits a LDA after applying PCA or ICA, or alternatively a ranger with no preprocessing. These two options each define selection parameters that we can tune. Moreover, within the respective PipeOp’s we want to tune the following parameters: pca.rank., ica.n.comp, classif.lda.method, classif.ranger.mtry, and classif.ranger.num.trees. The first two parameters are integers that in-principal could range from 1 to the number of features. However, for ICA, the upper bound must not exceed the number of observations and as we will later use 3-fold cross-validation as the resampling method for the tuning, we just set the upper bound to 30 (and do the same for PCA). Regarding the classif.lda.method we will only be interested in "moment" estimation vs. minimum volume ellipsoid covariance estimation ("mve"). Moreover, we set the lower bound of classif.ranger.mtry to 200 (which is around the number of features divided by 10) and the upper bound to 1000.

+
+
tune_ps1 = ps(
+  branch_learner.selection =
+    p_fct(c("pca_ica_lda", "ranger")),
+  branch_preproc_lda.selection =
+    p_fct(c("pca", "ica"), depends = branch_learner.selection == "pca_ica_lda"),
+  pca.rank. =
+    p_int(1, 30, depends = branch_preproc_lda.selection == "pca"),
+  ica.n.comp =
+    p_int(1, 30, depends = branch_preproc_lda.selection == "ica"),
+  classif.lda.method =
+    p_fct(c("moment", "mve"), depends = branch_preproc_lda.selection == "ica"),
+  classif.ranger.mtry =
+    p_int(200, 1000, depends = branch_learner.selection == "ranger"),
+  classif.ranger.num.trees =
+    p_int(500, 2000, depends = branch_learner.selection == "ranger"))
+
+

The parameter branch_learner.selection defines whether we go down the left (PCA / ICA followed by LDA) or the right branch (ranger). The parameter branch_preproc_lda.selection defines whether a PCA or ICA will be applied prior to the LDA. The other parameters directly belong to the ParamSet of the PCA / ICA / LDA / ranger. Note that it only makes sense to switch between PCA / ICA if the "pca_ica_lda" branch was selected beforehand. We have to specify this via the depends parameter.

+

Finally, we also could have proceeded to tune the numeric parameters on a log scale. I.e., looking at pca.rank. the performance difference between rank 1 and 2 is probably much larger than between rank 29 and rank 30. The mlr3tuning Tutorial covers such transformations.

+
+
+

Tuning

+

We can now tune the parameters of our graph as defined in the search space with respect to a measure. We will use the classification accuracy. As a resampling method we use 3-fold cross-validation. We will use the TerminatorNone (i.e., no early termination) for terminating the tuning because we will apply a grid search (we use a grid search because it gives nicely plottable and understandable results but if there were much more parameters, random search or more intelligent optimization methods would be preferred to a grid search:

+
+
tune1 = TuningInstanceSingleCrit$new(
+  task_train,
+  learner = graph1,
+  resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.acc"),
+  search_space = tune_ps1,
+  terminator = trm("none")
+)
+
+

We then perform a grid search using a resolution of 4 for the numeric parameters. The grid being used will look like the following (note that the dependencies we specified above are handled automatically):

+
+
generate_design_grid(tune_ps1, resolution = 4)
+
+
+
+
+ +
+
+

We trigger the tuning.

+
+
tuner_gs = tnr("grid_search", resolution = 4, batch_size = 10)
+tuner_gs$optimize(tune1)
+
+
   branch_learner.selection branch_preproc_lda.selection pca.rank. ica.n.comp classif.lda.method classif.ranger.mtry
+1:              pca_ica_lda                          ica        NA         10                mve                  NA
+   classif.ranger.num.trees learner_param_vals  x_domain classif.acc
+1:                       NA          <list[8]> <list[4]>    0.984127
+
+
+

Now, we can inspect the results ordered by the classification accuracy:

+
+
as.data.table(tune1$archive)[order(classif.acc), ]
+
+
+
+
+ +
+
+

We achieve very good accuracy using ranger, more or less regardless how mtry and num.trees are set. However, the LDA also shows very good accuracy when combined with PCA or ICA retaining 30 components.

+

For now, we decide to use ranger with mtry set to 200 and num.trees set to 1000.

+

Setting these parameters manually in our graph, then training on the training task and predicting on the test task yields an accuracy of:

+
+
graph1$param_set$values$branch_learner.selection = "ranger"
+graph1$param_set$values$classif.ranger.mtry = 200
+graph1$param_set$values$classif.ranger.num.trees = 1000
+graph1$train(task_train)
+
+
$unbranch_learner.output
+NULL
+
+
graph1$predict(task_test)[[1L]]$score(msr("classif.acc"))
+
+
classif.acc 
+          1 
+
+
+

Note that we also could have wrapped our graph in a GraphLearner and proceeded to use this as a learner in an AutoTuner.

+
+
+

Proxy

+

Instead of using branches to split our graph with respect to the learner and preprocessing options, we can also use PipeOpProxy. PipeOpProxy accepts a single content parameter that can contain any other PipeOp or Graph. This is extremely flexible in the sense that we do not have to specify our options during construction. However, the parameters of the contained PipeOp or Graph are no longer directly contained in the ParamSet of the resulting graph. Therefore, when tuning the graph, we do have to make use of a trafo function.

+
+
graph2 =
+  po("colapply", applicator = function(x) log(x, base = 10)) %>>%
+  po("scale") %>>%
+  po("proxy")
+
+

This graph now looks like the following:

+
+
graph2$plot(html = FALSE)
+
+
+
+

+
+
+
+
+

At first, this may look like a linear graph. However, as the content parameter of PipeOpProxy can be tuned and set to contain any other PipeOp or Graph, this will allow for a similar non-linear graph as when doing branching.

+
+
graph2$param_set$ids()
+
+
[1] "colapply.applicator"     "colapply.affect_columns" "scale.center"            "scale.scale"            
+[5] "scale.robust"            "scale.affect_columns"    "proxy.content"          
+
+
+

We can tune the graph by using the same search space as before. However, here the trafo function is of central importance to actually set our options and parameters:

+
+
tune_ps2 = tune_ps1$clone(deep = TRUE)
+
+

The trafo function does all the work, i.e., selecting either the PCA / ICA-LDA or ranger as the proxy.content as well as setting the parameters of the respective preprocessing PipeOps and Learners.

+
+
proxy_options = list(
+  pca_ica_lda =
+    ppl("branch", graphs = list(pca = po("pca"), ica = po("ica"))) %>>%
+      lrn("classif.lda"),
+  ranger = lrn("classif.ranger")
+)
+
+

Above, we made use of the branch ppl allowing us to easily construct a branching graph. Of course we also could have use another nested PipeOpProxy to specify the preprocessing options ("pca" vs. "ica") within proxy_options if for some reason we do not want to do branching at all. The trafo function below selects one of the proxy_options from above and sets the respective parameters for the PCA, ICA, LDA and ranger. Here, the argument x is a list which will contain sampled / selected parameters from our ParamSet (in our case, tune_ps2). The return value is a list only including the appropriate proxy.content parameter. In each tuning iteration, the proxy.content parameter of our graph will be set to this value.

+
+
tune_ps2$trafo = function(x, param_set) {
+  proxy.content = proxy_options[[x$branch_learner.selection]]
+  if (x$branch_learner.selection == "pca_ica_lda") {
+    # pca_ica_lda
+    proxy.content$param_set$values$branch.selection = x$branch_preproc_lda.selection
+    if (x$branch_preproc_lda.selection == "pca") {
+      proxy.content$param_set$values$pca.rank. = x$pca.rank.
+    } else {
+      proxy.content$param_set$values$ica.n.comp = x$ica.n.comp
+    }
+    proxy.content$param_set$values$classif.lda.method = x$classif.lda.method
+  } else {
+    # ranger
+    proxy.content$param_set$values$mtry = x$classif.ranger.mtry
+    proxy.content$param_set$values$num.trees = x$classif.ranger.num.trees
+  }
+  list(proxy.content = proxy.content)
+}
+
+

I.e., suppose that the following parameters will be selected from our ParamSet:

+
+
x = list(
+  branch_learner.selection = "ranger",
+  classif.ranger.mtry = 200,
+  classif.ranger.num.trees = 500)
+
+

The trafo function will then return:

+
+
tune_ps2$trafo(x)
+
+
$proxy.content
+<LearnerClassifRanger:classif.ranger>
+* Model: -
+* Parameters: num.threads=1, mtry=200, num.trees=500
+* Packages: mlr3, mlr3learners, ranger
+* Predict Types:  [response], prob
+* Feature Types: logical, integer, numeric, character, factor, ordered
+* Properties: hotstart_backward, importance, multiclass, oob_error, twoclass, weights
+
+
+

Tuning can be carried out analogously as done above:

+
+
tune2 = TuningInstanceSingleCrit$new(
+  task_train,
+  learner = graph2,
+  resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.acc"),
+  search_space = tune_ps2,
+  terminator = trm("none")
+)
+tuner_gs$optimize(tune2)
+
+
+
as.data.table(tune2$archive)[order(classif.acc), ]
+
+ + + +
+ +

References

+
+Morais, Camilo LM, and Kássio MG Lima. 2018. “Principal Component Analysis with Linear and Quadratic Discriminant Analysis for Identification of Cancer Samples Based on Mass Spectrometry.” Journal of the Brazilian Chemical Society 29 (3): 472–81. https://doi.org/10.21577/0103-5053.20170159. +
+
]]>
+ tuning + mlr3pipelines + classification + https://mlr-org.com/gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html + Wed, 03 Feb 2021 00:00:00 GMT + +
+ + Integer Hyperparameters in Tuners for Real-valued Search Spaces + Marc Becker + https://mlr-org.com/gallery/optimization/2021-01-19-integer-hyperparameters-in-tuners-for-real-valued-search-spaces/ + +

Introduction

+

Tuner for real-valued search spaces are not able to tune on integer hyperparameters. However, it is possible to round the real values proposed by a Tuner to integers before passing them to the learner in the evaluation. We show how to apply a parameter transformation to a ParamSet and use this set in the tuning process.

+

We load the mlr3verse package which pulls in the most important packages for this example.

+
+
library(mlr3verse)
+
+
Loading required package: mlr3
+
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+ +
+

Task and Learner

+

In this example, we use the k-Nearest-Neighbor classification learner. We want to tune the integer-valued hyperparameter k which defines the numbers of neighbors.

+
+
learner = lrn("classif.kknn")
+print(learner$param_set$params$k)
+
+
   id    class lower upper levels default
+1:  k ParamInt     1   Inf              7
+
+
+
+
+

Tuning

+

We choose generalized simulated annealing as tuning strategy. The param_classes field of TunerGenSA states that the tuner only supports real-valued (ParamDbl) hyperparameter tuning.

+
+
print(tnr("gensa"))
+
+
<TunerGenSA>: Generalized Simulated Annealing
+* Parameters: trace.mat=FALSE, smooth=FALSE
+* Parameter classes: ParamDbl
+* Properties: single-crit
+* Packages: mlr3tuning, bbotk, GenSA
+
+
+

To get integer-valued hyperparameter values for k, we construct a search space with a transformation function. The as.integer() function converts any real valued number to an integer by removing the decimal places.

+
+
search_space = ps(
+  k = p_dbl(lower = 3, upper = 7.99, trafo = as.integer)
+)
+
+

We start the tuning and compare the results of the search space to the results in the space of the learners hyperparameter set.

+
+
instance = tune(
+  tuner = tnr("gensa"),
+  task = tsk("iris"),
+  learner = learner,
+  resampling = rsmp("holdout"),
+  measure = msr("classif.ce"),
+  term_evals = 20,
+  search_space = search_space)
+
+
Warning in optim(theta.old, fun, gradient, control = control, method = method, : one-dimensional optimization by Nelder-Mead is unreliable:
+use "Brent" or optimize() directly
+
+
+

The optimal k is still a real number in the search space.

+
+
instance$result_x_search_space
+
+
         k
+1: 3.82686
+
+
+

However, in the learners hyperparameters space, k is an integer value.

+
+
instance$result_x_domain
+
+
$k
+[1] 3
+
+
+

The archive shows us that for all real-valued k proposed by GenSA, an integer-valued k in the learner hyperparameter space (x_domain_k) was created.

+
+
as.data.table(instance$archive)[, .(k, classif.ce, x_domain_k)]
+
+
           k classif.ce x_domain_k
+ 1: 3.826860       0.06          3
+ 2: 5.996323       0.06          5
+ 3: 5.941332       0.06          5
+ 4: 3.826860       0.06          3
+ 5: 3.826860       0.06          3
+ 6: 3.826860       0.06          3
+ 7: 4.209546       0.06          4
+ 8: 3.444174       0.06          3
+ 9: 4.018203       0.06          4
+10: 3.635517       0.06          3
+11: 3.922532       0.06          3
+12: 3.731189       0.06          3
+13: 3.874696       0.06          3
+14: 3.779024       0.06          3
+15: 3.850778       0.06          3
+16: 3.802942       0.06          3
+17: 3.838819       0.06          3
+18: 3.814901       0.06          3
+19: 3.832840       0.06          3
+20: 3.820881       0.06          3
+
+
+

Internally, TunerGenSA was given the parameter types of the search space and therefore suggested real numbers for k. Before the performance of the different k values was evaluated, the transformation function of the search_space parameter set was called and k was transformed to an integer value.

+

Note that the tuner is not aware of the transformation. This has two problematic consequences: First, the tuner might propose different real valued configurations that after rounding end up to be already evaluated configurations and we end up with re-evaluating the same hyperparameter configuration. This is only problematic, if we only optimze integer parameters. Second, the rounding introduces discontinuities which can be problematic for some tuners.

+

We successfully tuned a integer-valued hyperparameter with TunerGenSA which is only suitable for an real-valued search space. This technique is not limited to tuning problems. Optimizer in bbotk can be also used in the same way to produce points with integer parameters.

+ + +
+ + ]]>
+ tuning + classification + https://mlr-org.com/gallery/optimization/2021-01-19-integer-hyperparameters-in-tuners-for-real-valued-search-spaces/ + Tue, 19 Jan 2021 00:00:00 GMT +
+
+
diff --git a/gallery.html b/gallery.html new file mode 100644 index 00000000..63e0f13a --- /dev/null +++ b/gallery.html @@ -0,0 +1,1119 @@ + + + + + + + + + +gallery – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + +
+ + + + + + +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/2020-01-30-house-prices-in-king-county/index.html b/gallery/2020-01-30-house-prices-in-king-county/index.html new file mode 100644 index 00000000..9e35126d --- /dev/null +++ b/gallery/2020-01-30-house-prices-in-king-county/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-01-30-impute-missing-levels/index.html b/gallery/2020-01-30-impute-missing-levels/index.html new file mode 100644 index 00000000..84ccb2d4 --- /dev/null +++ b/gallery/2020-01-30-impute-missing-levels/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-01-31-encode-factors-for-xgboost/index.html b/gallery/2020-01-31-encode-factors-for-xgboost/index.html new file mode 100644 index 00000000..c20b67d4 --- /dev/null +++ b/gallery/2020-01-31-encode-factors-for-xgboost/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-02-01-tuning-multiplexer/index.html b/gallery/2020-02-01-tuning-multiplexer/index.html new file mode 100644 index 00000000..6471b62c --- /dev/null +++ b/gallery/2020-02-01-tuning-multiplexer/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-02-25-remove-correlated-features/index.html b/gallery/2020-02-25-remove-correlated-features/index.html new file mode 100644 index 00000000..5eb733bb --- /dev/null +++ b/gallery/2020-02-25-remove-correlated-features/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-03-11-basics-german-credit/index.html b/gallery/2020-03-11-basics-german-credit/index.html new file mode 100644 index 00000000..c9aa144e --- /dev/null +++ b/gallery/2020-03-11-basics-german-credit/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html b/gallery/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html new file mode 100644 index 00000000..8fe4887b --- /dev/null +++ b/gallery/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-03-11-mlr3tuning-tutorial-german-credit/index.html b/gallery/2020-03-11-mlr3tuning-tutorial-german-credit/index.html new file mode 100644 index 00000000..49ff7d0a --- /dev/null +++ b/gallery/2020-03-11-mlr3tuning-tutorial-german-credit/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-03-12-intro-pipelines-titanic/index.html b/gallery/2020-03-12-intro-pipelines-titanic/index.html new file mode 100644 index 00000000..6b90f9cc --- /dev/null +++ b/gallery/2020-03-12-intro-pipelines-titanic/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-03-18-iris-mlr3-basics/index.html b/gallery/2020-03-18-iris-mlr3-basics/index.html new file mode 100644 index 00000000..fff3239f --- /dev/null +++ b/gallery/2020-03-18-iris-mlr3-basics/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-03-30-imbalanced-data/index.html b/gallery/2020-03-30-imbalanced-data/index.html new file mode 100644 index 00000000..3ec420f0 --- /dev/null +++ b/gallery/2020-03-30-imbalanced-data/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-03-30-stratification-blocking/index.html b/gallery/2020-03-30-stratification-blocking/index.html new file mode 100644 index 00000000..9cb7343e --- /dev/null +++ b/gallery/2020-03-30-stratification-blocking/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-04-18-regression-chains/index.html b/gallery/2020-04-18-regression-chains/index.html new file mode 100644 index 00000000..f15366bf --- /dev/null +++ b/gallery/2020-04-18-regression-chains/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-04-23-pipelines-selectors-branches/index.html b/gallery/2020-04-23-pipelines-selectors-branches/index.html new file mode 100644 index 00000000..6fee5718 --- /dev/null +++ b/gallery/2020-04-23-pipelines-selectors-branches/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-04-27-mlr3pipelines-Imputation-titanic/index.html b/gallery/2020-04-27-mlr3pipelines-Imputation-titanic/index.html new file mode 100644 index 00000000..93a14da7 --- /dev/null +++ b/gallery/2020-04-27-mlr3pipelines-Imputation-titanic/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-04-27-tuning-stacking/index.html b/gallery/2020-04-27-tuning-stacking/index.html new file mode 100644 index 00000000..50af1832 --- /dev/null +++ b/gallery/2020-04-27-tuning-stacking/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-05-02-feature-engineering-of-date-time-variables/index.html b/gallery/2020-05-02-feature-engineering-of-date-time-variables/index.html new file mode 100644 index 00000000..b4ba76d9 --- /dev/null +++ b/gallery/2020-05-02-feature-engineering-of-date-time-variables/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-05-04-moneyball/index.html b/gallery/2020-05-04-moneyball/index.html new file mode 100644 index 00000000..ecaafe60 --- /dev/null +++ b/gallery/2020-05-04-moneyball/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-06-15-target-transformations-via-pipelines/index.html b/gallery/2020-06-15-target-transformations-via-pipelines/index.html new file mode 100644 index 00000000..cc69230c --- /dev/null +++ b/gallery/2020-06-15-target-transformations-via-pipelines/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-08-13-a-production-example-using-plumber-and-docker/index.html b/gallery/2020-08-13-a-production-example-using-plumber-and-docker/index.html new file mode 100644 index 00000000..b9899f46 --- /dev/null +++ b/gallery/2020-08-13-a-production-example-using-plumber-and-docker/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-08-14-comparison-of-decision-boundaries/index.html b/gallery/2020-08-14-comparison-of-decision-boundaries/index.html new file mode 100644 index 00000000..2a165d17 --- /dev/null +++ b/gallery/2020-08-14-comparison-of-decision-boundaries/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-09-11-liver-patient-classification/index.html b/gallery/2020-09-11-liver-patient-classification/index.html new file mode 100644 index 00000000..b5fe4bf0 --- /dev/null +++ b/gallery/2020-09-11-liver-patient-classification/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-09-14-mlr3fselect-basic/index.html b/gallery/2020-09-14-mlr3fselect-basic/index.html new file mode 100644 index 00000000..531f92ac --- /dev/null +++ b/gallery/2020-09-14-mlr3fselect-basic/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2020-10-14-threshold-tuning/index.html b/gallery/2020-10-14-threshold-tuning/index.html new file mode 100644 index 00000000..4f5126cf --- /dev/null +++ b/gallery/2020-10-14-threshold-tuning/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2021-01-19-integer-hyperparameters-in-tuners-for-real-valued-search-spaces/index.html b/gallery/2021-01-19-integer-hyperparameters-in-tuners-for-real-valued-search-spaces/index.html new file mode 100644 index 00000000..54b2dc52 --- /dev/null +++ b/gallery/2021-01-19-integer-hyperparameters-in-tuners-for-real-valued-search-spaces/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2021-01-20-keras/index.html b/gallery/2021-01-20-keras/index.html new file mode 100644 index 00000000..593b46a3 --- /dev/null +++ b/gallery/2021-01-20-keras/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2021-02-03-tuning-a-complex-graph/index.html b/gallery/2021-02-03-tuning-a-complex-graph/index.html new file mode 100644 index 00000000..3bf6bffa --- /dev/null +++ b/gallery/2021-02-03-tuning-a-complex-graph/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/index.html b/gallery/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/index.html new file mode 100644 index 00000000..24b40680 --- /dev/null +++ b/gallery/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/index.html b/gallery/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/index.html new file mode 100644 index 00000000..e934b833 --- /dev/null +++ b/gallery/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index.html b/gallery/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index.html new file mode 100644 index 00000000..18a75b2d --- /dev/null +++ b/gallery/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2021-03-12-practical-tuning-series-tuning-and-parallel-processing/index.html b/gallery/2021-03-12-practical-tuning-series-tuning-and-parallel-processing/index.html new file mode 100644 index 00000000..eb4db892 --- /dev/null +++ b/gallery/2021-03-12-practical-tuning-series-tuning-and-parallel-processing/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2021-07-06-introduction-to-mlr3tuningspaces/index.html b/gallery/2021-07-06-introduction-to-mlr3tuningspaces/index.html new file mode 100644 index 00000000..5ea97edb --- /dev/null +++ b/gallery/2021-07-06-introduction-to-mlr3tuningspaces/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2022-11-04-early-stopping-with-xgboost/index.html b/gallery/2022-11-04-early-stopping-with-xgboost/index.html new file mode 100644 index 00000000..2ea4294f --- /dev/null +++ b/gallery/2022-11-04-early-stopping-with-xgboost/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/index.html b/gallery/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/index.html new file mode 100644 index 00000000..cb4d505b --- /dev/null +++ b/gallery/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/basic/2020-01-30-house-prices-in-king-county/index.html b/gallery/basic/2020-01-30-house-prices-in-king-county/index.html new file mode 100644 index 00000000..2dcf0e8e --- /dev/null +++ b/gallery/basic/2020-01-30-house-prices-in-king-county/index.html @@ -0,0 +1,1298 @@ + + + + + + + + + + + + +House Prices in King County – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

House Prices in King County

+
+
+

Apply multiple preprocessing steps, fit a model and visualize the results.

+
+
+
+
+ + +
+ +
+
Author
+
+

Florian Pfisterer

+
+
+ +
+
Published
+
+

January 30, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +

The use-case illustrated below touches on the following concepts:

+ +

The relevant sections in the mlr3book are linked to for the reader’s convenience.

+

This use case shows how to model housing price data in King County. Following features are illustrated:

+ +

We load the mlr3verse package which pulls in the most important packages for this example.

+
+
library(mlr3verse)
+
+
Loading required package: mlr3
+
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+
+

House Price Prediction in King County

+

We use the kc_housing dataset contained in the package mlr3data in order to provide a use-case for the application of mlr3 on real-world data.

+
+
data("kc_housing", package = "mlr3data")
+
+
+

Exploratory Data Analysis

+

In order to get a quick impression of our data, we perform some initial Exploratory Data Analysis. This helps us to get a first impression of our data and might help us arrive at additional features that can help with the prediction of the house prices.

+

We can get a quick overview using R’s summary function:

+
+
summary(kc_housing)
+
+
      date                           price            bedrooms        bathrooms      sqft_living       sqft_lot      
+ Min.   :2014-05-02 00:00:00.0   Min.   :  75000   Min.   : 0.000   Min.   :0.000   Min.   :  290   Min.   :    520  
+ 1st Qu.:2014-07-22 00:00:00.0   1st Qu.: 321950   1st Qu.: 3.000   1st Qu.:1.750   1st Qu.: 1427   1st Qu.:   5040  
+ Median :2014-10-16 00:00:00.0   Median : 450000   Median : 3.000   Median :2.250   Median : 1910   Median :   7618  
+ Mean   :2014-10-29 03:58:09.9   Mean   : 540088   Mean   : 3.371   Mean   :2.115   Mean   : 2080   Mean   :  15107  
+ 3rd Qu.:2015-02-17 00:00:00.0   3rd Qu.: 645000   3rd Qu.: 4.000   3rd Qu.:2.500   3rd Qu.: 2550   3rd Qu.:  10688  
+ Max.   :2015-05-27 00:00:00.0   Max.   :7700000   Max.   :33.000   Max.   :8.000   Max.   :13540   Max.   :1651359  
+                                                                                                                     
+     floors      waterfront           view          condition         grade          sqft_above   sqft_basement   
+ Min.   :1.000   Mode :logical   Min.   :0.0000   Min.   :1.000   Min.   : 1.000   Min.   : 290   Min.   :  10.0  
+ 1st Qu.:1.000   FALSE:21450     1st Qu.:0.0000   1st Qu.:3.000   1st Qu.: 7.000   1st Qu.:1190   1st Qu.: 450.0  
+ Median :1.500   TRUE :163       Median :0.0000   Median :3.000   Median : 7.000   Median :1560   Median : 700.0  
+ Mean   :1.494                   Mean   :0.2343   Mean   :3.409   Mean   : 7.657   Mean   :1788   Mean   : 742.4  
+ 3rd Qu.:2.000                   3rd Qu.:0.0000   3rd Qu.:4.000   3rd Qu.: 8.000   3rd Qu.:2210   3rd Qu.: 980.0  
+ Max.   :3.500                   Max.   :4.0000   Max.   :5.000   Max.   :13.000   Max.   :9410   Max.   :4820.0  
+                                                                                                  NA's   :13126   
+    yr_built     yr_renovated      zipcode           lat             long        sqft_living15    sqft_lot15    
+ Min.   :1900   Min.   :1934    Min.   :98001   Min.   :47.16   Min.   :-122.5   Min.   : 399   Min.   :   651  
+ 1st Qu.:1951   1st Qu.:1987    1st Qu.:98033   1st Qu.:47.47   1st Qu.:-122.3   1st Qu.:1490   1st Qu.:  5100  
+ Median :1975   Median :2000    Median :98065   Median :47.57   Median :-122.2   Median :1840   Median :  7620  
+ Mean   :1971   Mean   :1996    Mean   :98078   Mean   :47.56   Mean   :-122.2   Mean   :1987   Mean   : 12768  
+ 3rd Qu.:1997   3rd Qu.:2007    3rd Qu.:98118   3rd Qu.:47.68   3rd Qu.:-122.1   3rd Qu.:2360   3rd Qu.: 10083  
+ Max.   :2015   Max.   :2015    Max.   :98199   Max.   :47.78   Max.   :-121.3   Max.   :6210   Max.   :871200  
+                NA's   :20699                                                                                   
+
+
dim(kc_housing)
+
+
[1] 21613    20
+
+
+

Our dataset has 21613 observations and 20 columns. The variable we want to predict is price. In addition to the price column, we have several other columns:

+
    +
  • id: A unique identifier for every house.

  • +
  • date: A date column, indicating when the house was sold. This column is currently not encoded as a date and requires some preprocessing.

  • +
  • zipcode: A column indicating the ZIP code. This is a categorical variable with many factor levels.

  • +
  • long, lat The longitude and latitude of the house

  • +
  • ... several other numeric columns providing information about the house, such as number of rooms, square feet etc.

  • +
+

Before we continue with the analysis, we preprocess some features so that they are stored in the correct format.

+

First we convert the date column to numeric. To do so, we convert the date to the POSIXct date/time class with the anytime package. Next, use difftime() to convert to days since the first day recorded in the data set:

+
+
library(anytime)
+dates = anytime(kc_housing$date)
+kc_housing$date = as.numeric(difftime(dates, min(dates), units = "days"))
+
+

Afterwards, we convert the zip code to a factor:

+
+
kc_housing$zipcode = as.factor(kc_housing$zipcode)
+
+

And add a new column renovated indicating whether a house was renovated at some point.

+
+
kc_housing$renovated = as.numeric(!is.na(kc_housing$yr_renovated))
+kc_housing$has_basement = as.numeric(!is.na(kc_housing$sqft_basement))
+
+

We drop the id column which provides no information about the house prices:

+
+
kc_housing$id = NULL
+
+

Additionally, we convert the price from Dollar to units of 1000 Dollar to improve readability.

+
+
kc_housing$price = kc_housing$price / 1000
+
+

Additionally, for now we simply drop the columns that have missing values, as some of our learners can not deal with them. A better option to deal with missing values would be imputation, i.e. replacing missing values with valid ones. We will deal with this in a separate article.

+
+
kc_housing$yr_renovated = NULL
+kc_housing$sqft_basement = NULL
+
+

We can now plot the density of the price to get a first impression on its distribution.

+
+
library(ggplot2)
+ggplot(kc_housing, aes(x = price)) + geom_density()
+
+
+
+

+
+
+
+
+

We can see that the prices for most houses lie between 75.000 and 1.5 million dollars. There are few extreme values of up to 7.7 million dollars.

+

Feature engineering often allows us to incorporate additional knowledge about the data and underlying processes. This can often greatly enhance predictive performance. A simple example: A house which has yr_renovated == 0 means that is has not been renovated yet. Additionally, we want to drop features which should not have any influence (id column).

+

After those initial manipulations, we load all required packages and create a TaskRegr containing our data.

+
+
tsk = as_task_regr(kc_housing, target = "price")
+
+

We can inspect associations between variables using mlr3viz’s autoplot function in order to get some good first impressions for our data. Note, that this does in no way prevent us from using other powerful plot functions of our choice on the original data.

+
+

Distribution of the price:

+

The outcome we want to predict is the price variable. The autoplot function provides a good first glimpse on our data. As the resulting object is a ggplot2 object, we can use faceting and other functions from ggplot2 in order to enhance plots.

+
+
autoplot(tsk) + facet_wrap(~renovated)
+
+
+
+

+
+
+
+
+

We can observe that renovated flats seem to achieve higher sales values, and this might thus be a relevant feature.

+

Additionally, we can for example look at the condition of the house. Again, we clearly can see that the price rises with increasing condition.

+
+
autoplot(tsk) + facet_wrap(~condition)
+
+
+
+

+
+
+
+
+
+
+

Association between variables

+

In addition to the association with the target variable, the association between the features can also lead to interesting insights. We investigate using variables associated with the quality and size of the house. Note that we use $clone() and $select() to clone the task and select only a subset of the features for the autoplot function, as autoplot per default uses all features. The task is cloned before we select features in order to keep the original task intact.

+
+
# Variables associated with quality
+autoplot(tsk$clone()$select(tsk$feature_names[c(3, 17)]), type = "pairs")
+
+
Registered S3 method overwritten by 'GGally':
+  method from   
+  +.gg   ggplot2
+
+
+
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
+`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
+
+
+
+
+

+
+
+
+
+
+
autoplot(tsk$clone()$select(tsk$feature_names[c(9:12)]), type = "pairs")
+
+
+
+

+
+
+
+
+
+
+
+

Splitting into train and test data

+

In mlr3, we do not create train and test data sets, but instead keep only a vector of train and test indices.

+
+
train.idx = sample(seq_len(tsk$nrow), 0.7 * tsk$nrow)
+test.idx = setdiff(seq_len(tsk$nrow), train.idx)
+
+

We can do the same for our task:

+
+
task_train = tsk$clone()$filter(train.idx)
+task_test = tsk$clone()$filter(test.idx)
+
+
+
+

A first model: Decision Tree

+

Decision trees cannot only be used as a powerful tool for predictive models but also for exploratory data analysis. In order to fit a decision tree, we first get the regr.rpart learner from the mlr_learners dictionary by using the sugar function lrn.

+

For now, we leave out the zipcode variable, as we also have the latitude and longitude of each house. Again, we use $clone(), so we do not change the original task.

+
+
tsk_nozip = task_train$clone()$select(setdiff(tsk$feature_names, "zipcode"))
+
+# Get the learner
+lrn = lrn("regr.rpart")
+
+# And train on the task
+lrn$train(tsk_nozip, row_ids = train.idx)
+
+
+
plot(lrn$model)
+text(lrn$model)
+
+
+
+

+
+
+
+
+

The learned tree relies on several variables in order to distinguish between cheaper and pricier houses. The features we split along are grade, sqft_living, but also some features related to the area (longitude and latitude). We can visualize the price across different regions in order to get more info:

+
+
# Load the ggmap package in order to visualize on a map
+library(ggmap)
+
+# And create a quick plot for the price
+qmplot(long, lat, maptype = "watercolor", color = log(price),
+  data = kc_housing[train.idx[1:3000], ]) +
+  scale_colour_viridis_c()
+
+
+
+

+
+
+
+
# And the zipcode
+qmplot(long, lat, maptype = "watercolor", color = zipcode,
+  data = kc_housing[train.idx[1:3000], ]) + guides(color = FALSE)
+
+
Warning: The `<scale>` argument of `guides()` cannot be `FALSE`. Use "none" instead as of ggplot2 3.3.4.
+
+
+
+
+

+
+
+
+
+

We can see that the price is clearly associated with the zipcode when comparing then two plots. As a result, we might want to indeed use the zipcode column in our future endeavors.

+
+
+

A first baseline: Decision Tree

+

After getting an initial idea for our data, we might want to construct a first baseline, in order to see what a simple model already can achieve.

+

We use resample() with 3-fold cross-validation on our training data in order to get a reliable estimate of the algorithm’s performance on future data. Before we start with defining and training learners, we create a Resampling in order to make sure that we always compare on exactly the same data.

+
+
cv3 = rsmp("cv", folds = 3)
+
+

For the cross-validation we only use the training data by cloning the task and selecting only observations from the training set.

+
+
lrn_rpart = lrn("regr.rpart")
+res = resample(task = task_train, lrn_rpart, cv3)
+res$score(msr("regr.rmse"))
+
+
      task_id learner_id resampling_id iteration regr.rmse
+1: kc_housing regr.rpart            cv         1  205.7541
+2: kc_housing regr.rpart            cv         2  205.6597
+3: kc_housing regr.rpart            cv         3  213.3846
+Hidden columns: task, learner, resampling, prediction
+
+
sprintf("RMSE of the simple rpart: %s", round(sqrt(res$aggregate()), 2))
+
+
[1] "RMSE of the simple rpart: 208.3"
+
+
+
+
+

Many Trees: Random Forest

+

We might be able to improve upon the RMSE using more powerful learners. We first load the mlr3learners package, which contains the ranger learner (a package which implements the “Random Forest” algorithm).

+
+
library(mlr3learners)
+lrn_ranger = lrn("regr.ranger", num.trees = 15L)
+res = resample(task = task_train, lrn_ranger, cv3)
+res$score(msr("regr.rmse"))
+
+
      task_id  learner_id resampling_id iteration regr.rmse
+1: kc_housing regr.ranger            cv         1  142.2424
+2: kc_housing regr.ranger            cv         2  161.6867
+3: kc_housing regr.ranger            cv         3  138.2549
+Hidden columns: task, learner, resampling, prediction
+
+
sprintf("RMSE of the simple ranger: %s", round(sqrt(res$aggregate()), 2))
+
+
[1] "RMSE of the simple ranger: 147.75"
+
+
+

Often tuning RandomForest methods does not increase predictive performances substantially. If time permits, it can nonetheless lead to improvements and should thus be performed. In this case, we resort to tune a different kind of model: Gradient Boosted Decision Trees from the package xgboost.

+
+
+

A better baseline: AutoTuner

+

Tuning can often further improve the performance. In this case, we tune the xgboost learner in order to see whether this can improve performance. For the AutoTuner we have to specify a Termination Criterion (how long the tuning should run) a Tuner (which tuning method to use) and a ParamSet (which space we might want to search through). For now, we do not use the zipcode column, as xgboost cannot naturally deal with categorical features. The AutoTuner automatically performs nested cross-validation.

+
+
lrn_xgb = lrn("regr.xgboost")
+
+# Define the search space
+search_space = ps(
+  eta = p_dbl(lower = 0.2, upper = .4),
+  min_child_weight = p_dbl(lower = 1, upper = 20),
+  subsample = p_dbl(lower = .7, upper = .8),
+  colsample_bytree = p_dbl(lower = .9, upper = 1),
+  colsample_bylevel = p_dbl(lower = .5, upper = .7),
+  nrounds = p_int(lower = 1L, upper = 25))
+
+at = auto_tuner(
+  tuner = tnr("random_search", batch_size = 40),
+  learner = lrn_xgb,
+  resampling = rsmp("holdout"),
+  measure = msr("regr.rmse"),
+  search_space = search_space,
+  term_evals = 10)
+
+
+
# And resample the AutoTuner
+res = resample(tsk_nozip, at, cv3, store_models = TRUE)
+
+
+
res$score(msr("regr.rmse"))
+
+
      task_id         learner_id resampling_id iteration regr.rmse
+1: kc_housing regr.xgboost.tuned            cv         1  147.0554
+2: kc_housing regr.xgboost.tuned            cv         2  136.4282
+3: kc_housing regr.xgboost.tuned            cv         3  132.4484
+Hidden columns: task, learner, resampling, prediction
+
+
sprintf("RMSE of the tuned xgboost: %s", round(sqrt(res$aggregate()), 2))
+
+
[1] "RMSE of the tuned xgboost: 138.78"
+
+
+

We can obtain the resulting parameters in the respective splits by accessing the ResampleResult.

+
+
sapply(res$learners, function(x) x$learner$param_set$values)[-2, ]
+
+
                   [,1]      [,2]      [,3]     
+nrounds            25        23        24       
+verbose            0         0         0        
+early_stopping_set "none"    "none"    "none"   
+eta                0.220869  0.3809271 0.2115116
+min_child_weight   1.885109  7.472919  1.910491 
+subsample          0.7542127 0.7884631 0.7000357
+colsample_bytree   0.9032271 0.9675298 0.9120812
+colsample_bylevel  0.5259713 0.6817893 0.630818 
+
+
+

NOTE: To keep runtime low, we only tune parts of the hyperparameter space of xgboost in this example. Additionally, we only allow for \(10\) random search iterations, which is usually too little for real-world applications. Nonetheless, we are able to obtain an improved performance when comparing to the ranger model.

+

In order to further improve our results we have several options:

+
    +
  • Find or engineer better features
  • +
  • Remove Features to avoid overfitting
  • +
  • Obtain additional data (often prohibitive)
  • +
  • Try more models
  • +
  • Improve the tuning +
      +
    • Increase the tuning budget
    • +
    • Enlarge the tuning search space
    • +
    • Use a more efficient tuning algorithm
    • +
  • +
  • Stacking and Ensembles
  • +
+

Below we will investigate some of those possibilities and investigate whether this improves performance.

+
+
+

Advanced: Engineering Features: Mutating ZIP-Codes

+

In order to better cluster the zip codes, we compute a new feature: med_price: It computes the median price in each zip-code. This might help our model to improve the prediction. This is equivalent to impact encoding more information:

+

We can equip a learner with impact encoding using mlr3pipelines. More information on mlr3pipelines can be obtained from other posts.

+
+
lrn_impact = po("encodeimpact", affect_columns = selector_name("zipcode")) %>>% lrn("regr.ranger")
+
+

Again, we run resample() and compute the RMSE.

+
+
res = resample(task = task_train, lrn_impact, cv3)
+
+
+
res$score(msr("regr.rmse"))
+
+
      task_id               learner_id resampling_id iteration regr.rmse
+1: kc_housing encodeimpact.regr.ranger            cv         1  119.4597
+2: kc_housing encodeimpact.regr.ranger            cv         2  146.3315
+3: kc_housing encodeimpact.regr.ranger            cv         3  125.4193
+Hidden columns: task, learner, resampling, prediction
+
+
sprintf("RMSE of ranger with med_price: %s", round(sqrt(res$aggregate()), 2))
+
+
[1] "RMSE of ranger with med_price: 130.91"
+
+
+
+
+

Advanced: Obtaining a sparser model

+

In many cases, we might want to have a sparse model. For this purpose we can use a mlr3filters::Filter implemented in mlr3filters. This can prevent our learner from overfitting make it easier for humans to interpret models as fewer variables influence the resulting prediction.

+

In this example, we use PipeOpFilter (via po("filter", ...)) to add a feature-filter before training the model. For a more in-depth insight, refer to the sections on mlr3pipelines and mlr3filters in the mlr3 book: Feature Selection and Pipelines.

+
+
filter = flt("mrmr")
+
+

The resulting RMSE is slightly higher, and at the same time we only use \(12\) features.

+
+
graph = po("filter", filter, param_vals = list(filter.nfeat = 12)) %>>% po("learner", lrn("regr.ranger"))
+lrn_filter = as_learner(graph)
+res = resample(task = task_train, lrn_filter, cv3)
+
+
+
res$score(msr("regr.rmse"))
+
+
      task_id       learner_id resampling_id iteration regr.rmse
+1: kc_housing mrmr.regr.ranger            cv         1  152.6009
+2: kc_housing mrmr.regr.ranger            cv         2  156.7883
+3: kc_housing mrmr.regr.ranger            cv         3  149.0143
+Hidden columns: task, learner, resampling, prediction
+
+
sprintf("RMSE of ranger with filtering: %s", round(sqrt(res$aggregate()), 2))
+
+
[1] "RMSE of ranger with filtering: 152.83"
+
+
+
+
+
+

Summary:

+

We have seen different ways to improve models with respect to our criteria by:

+
    +
  • Choosing a suitable algorithm
  • +
  • Choosing good hyperparameters (tuning)
  • +
  • Filtering features
  • +
  • Engineering new features
  • +
+

A combination of all the above would most likely yield an even better model. This is left as an exercise to the reader.

+

The best model we found in this example is the ranger model with the added med_price feature. In a final step, we now want to assess the model’s quality on the held-out data we stored in our task_test. In order to do so, and to prevent data leakage, we can only add the median price from the training data.

+
+
library(data.table)
+
+data = task_train$data(cols = c("price", "zipcode"))
+data[, med_price := median(price), by = "zipcode"]
+test_data = task_test$data(cols = "zipcode")
+test = merge(test_data, unique(data[, .(zipcode, med_price)]), all.x = TRUE)
+task_test$cbind(test)
+
+

Now we can use the augmented task_test to predict on new data.

+
+
lrn_ranger$train(task_train)
+pred = lrn_ranger$predict(task_test)
+pred$score(msr("regr.rmse"))
+
+
regr.rmse 
+   145.01 
+
+
+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-012-1.png b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-012-1.png new file mode 100644 index 00000000..ea78f492 Binary files /dev/null and b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-012-1.png differ diff --git a/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-013-1.png b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-013-1.png new file mode 100644 index 00000000..ea78f492 Binary files /dev/null and b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-013-1.png differ diff --git a/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-014-1.png b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-014-1.png new file mode 100644 index 00000000..667574a1 Binary files /dev/null and b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-014-1.png differ diff --git a/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-015-1.png b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-015-1.png new file mode 100644 index 00000000..689ed19a Binary files /dev/null and b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-015-1.png differ diff --git a/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-016-1.png b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-016-1.png new file mode 100644 index 00000000..0214754a Binary files /dev/null and b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-016-1.png differ diff --git a/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-017-1.png b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-017-1.png new file mode 100644 index 00000000..3c99a773 Binary files /dev/null and b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-017-1.png differ diff --git a/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-018-1.png b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-018-1.png new file mode 100644 index 00000000..8208cc40 Binary files /dev/null and b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-018-1.png differ diff --git a/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-021-1.png b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-021-1.png new file mode 100644 index 00000000..c52fe776 Binary files /dev/null and b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-021-1.png differ diff --git a/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-022-1.png b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-022-1.png new file mode 100644 index 00000000..38fbce5e Binary files /dev/null and b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-022-1.png differ diff --git a/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-022-2.png b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-022-2.png new file mode 100644 index 00000000..1708d94a Binary files /dev/null and b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-022-2.png differ diff --git a/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-023-1.png b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-023-1.png new file mode 100644 index 00000000..75887d5b Binary files /dev/null and b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-023-1.png differ diff --git a/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-023-2.png b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-023-2.png new file mode 100644 index 00000000..95a99a86 Binary files /dev/null and b/gallery/basic/2020-01-30-house-prices-in-king-county/index_files/figure-html/2020-01-30-house-prices-in-king-county-023-2.png differ diff --git a/gallery/basic/2020-01-30-impute-missing-levels/index.html b/gallery/basic/2020-01-30-impute-missing-levels/index.html new file mode 100644 index 00000000..502eda9b --- /dev/null +++ b/gallery/basic/2020-01-30-impute-missing-levels/index.html @@ -0,0 +1,1061 @@ + + + + + + + + + + + + +Impute Missing Variables – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Impute Missing Variables

+
+
+

Augment a Random Forest with automatic imputation.

+
+
+
+
+ + +
+ +
+
Author
+
+

Florian Pfisterer

+
+
+ +
+
Published
+
+

January 31, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Prerequisites

+

This tutorial assumes familiarity with the basics of mlr3pipelines. Consult the mlr3book if some aspects are not fully understandable. It deals with the problem of missing data.

+

The random forest implementation in the package ranger unfortunately does not support missing values. Therefore, it is required to impute missing features before passing the data to the learner.

+

We show how to use mlr3pipelines to augment the ranger learner with automatic imputation.

+

We load the mlr3verse package which pulls in the most important packages for this example.

+
+
library(mlr3verse)
+
+
Loading required package: mlr3
+
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+
+
+
+

Construct the Base Objects

+

First, we take an example task with missing values (pima) and create the ranger learner:

+
+
library(mlr3learners)
+
+task = tsk("pima")
+print(task)
+
+
<TaskClassif:pima> (768 x 9): Pima Indian Diabetes
+* Target: diabetes
+* Properties: twoclass
+* Features (8):
+  - dbl (8): age, glucose, insulin, mass, pedigree, pregnant, pressure, triceps
+
+
learner = lrn("classif.ranger")
+print(learner)
+
+
<LearnerClassifRanger:classif.ranger>
+* Model: -
+* Parameters: num.threads=1
+* Packages: mlr3, mlr3learners, ranger
+* Predict Types:  [response], prob
+* Feature Types: logical, integer, numeric, character, factor, ordered
+* Properties: hotstart_backward, importance, multiclass, oob_error, twoclass, weights
+
+
+

We can now inspect the task for missing values. task$missings() returns the count of missing values for each variable.

+
+
task$missings()
+
+
diabetes      age  glucose  insulin     mass pedigree pregnant pressure  triceps 
+       0        0        5      374       11        0        0       35      227 
+
+
+

Additionally, we can see that the ranger learner can not handle missing values:

+
+
learner$properties
+
+
[1] "hotstart_backward" "importance"        "multiclass"        "oob_error"         "twoclass"         
+[6] "weights"          
+
+
+

For comparison, other learners, e.g. the rpart learner can handle missing values internally.

+
+
lrn("classif.rpart")$properties
+
+
[1] "importance"        "missings"          "multiclass"        "selected_features" "twoclass"         
+[6] "weights"          
+
+
+

Before we dive deeper, we quickly try to visualize the columns with many missing values:

+
+
autoplot(task$clone()$select(c("insulin", "triceps")), type = "pairs")
+
+
+
+

+
+
+
+
+
+
+

Operators overview

+

An overview over implemented PipeOps for imputation can be obtained like so:

+
+
as.data.table(mlr_pipeops)[tags %in% "missings", list(key)]
+
+
              key
+1: imputeconstant
+2:     imputehist
+3:  imputelearner
+4:     imputemean
+5:   imputemedian
+6:     imputemode
+7:      imputeoor
+8:   imputesample
+
+
+
+
+

Construct Operators

+

mlr3pipelines contains several imputation methods. We focus on rather simple ones, and show how to impute missing values for factor features and numeric features respectively.

+

Since our task only has numeric features, we do not need to deal with imputing factor levels, and can instead concentrate on imputing numeric values:

+

We do this in a two-step process: * We create new indicator columns, that tells us whether the value of a feature is “missing” or “present”. We achieve this using the missind PipeOp.

+
    +
  • Afterwards, we impute every missing value by sampling from the histogram of the respective column. We achieve this using the imputehist PipeOp.
  • +
+

We also have to make sure to apply the pipe operators in the correct order!

+
+
imp_missind = po("missind")
+imp_num = po("imputehist", affect_columns = selector_type("numeric"))
+
+

In order to better understand we can look at the results of every PipeOp separately.

+

We can manually trigger the PipeOp to test the operator on our task:

+
+
task_ext = imp_missind$train(list(task))[[1]]
+task_ext$data()
+
+
     diabetes missing_glucose missing_insulin missing_mass missing_pressure missing_triceps
+  1:      pos         present         missing      present          present         present
+  2:      neg         present         missing      present          present         present
+  3:      pos         present         missing      present          present         missing
+  4:      neg         present         present      present          present         present
+  5:      pos         present         present      present          present         present
+ ---                                                                                       
+764:      neg         present         present      present          present         present
+765:      neg         present         missing      present          present         present
+766:      neg         present         present      present          present         present
+767:      pos         present         missing      present          present         missing
+768:      neg         present         missing      present          present         present
+
+
+

For imputehist, we can do the same:

+
+
task_ext = imp_num$train(list(task))[[1]]
+task_ext$data()
+
+
     diabetes age pedigree pregnant glucose   insulin mass pressure   triceps
+  1:      pos  50    0.627        6     148 163.11747 33.6       72 35.000000
+  2:      neg  31    0.351        1      85 160.63628 26.6       66 29.000000
+  3:      pos  32    0.672        8     183 297.18282 23.3       64  8.204983
+  4:      neg  21    0.167        1      89  94.00000 28.1       66 23.000000
+  5:      pos  33    2.288        0     137 168.00000 43.1       40 35.000000
+ ---                                                                         
+764:      neg  63    0.171       10     101 180.00000 32.9       76 48.000000
+765:      neg  27    0.340        2     122  83.69836 36.8       70 27.000000
+766:      neg  30    0.245        5     121 112.00000 26.2       72 23.000000
+767:      pos  47    0.349        1     126  68.49318 30.1       60 24.460702
+768:      neg  23    0.315        1      93  17.80534 30.4       70 31.000000
+
+
+

This time we obtain the imputed data set without missing values.

+
+
task_ext$missings()
+
+
diabetes      age pedigree pregnant  glucose  insulin     mass pressure  triceps 
+       0        0        0        0        0        0        0        0        0 
+
+
+
+
+

Putting everything together

+

Now we have to put all PipeOps together in order to form a graph that handles imputation automatically.

+

We do this by creating a Graph that copies the data twice, processes each copy using the respective imputation method and afterwards unions the features. For this we need the following two PipeOps : * copy: Creates copies of the data. * featureunion Merges the two tasks together.

+
+
graph = po("copy", 2) %>>%
+  gunion(list(imp_missind, imp_num)) %>>%
+  po("featureunion")
+
+

as a last step we append the learner we planned on using:

+
+
graph = graph %>>% po(learner)
+
+

We can now visualize the resulting graph:

+
+
graph$plot()
+
+
+
+

+
+
+
+
+
+
+

Resampling

+

Correct imputation is especially important when applying imputation to held-out data during the predict step. If applied incorrectly, imputation could leak info from the test set, which potentially skews our performance estimates. mlr3pipelines takes this complexity away from the user and handles correct imputation internally.

+

By wrapping this graph into a GraphLearner, we can now train resample the full graph, here with a 3-fold cross validation:

+
+
graph_learner = as_learner(graph)
+rr = resample(task, graph_learner, rsmp("cv", folds = 3))
+rr$aggregate()
+
+
classif.ce 
+ 0.2330729 
+
+
+
+
+

Missing values during prediction

+

In some cases, we have missing values only in the data we want to predict on. In order to showcase this, we create a copy of the task with several more missing columns.

+
+
dt = task$data()
+dt[1:10, "age"] = NA
+dt[30:70, "pedigree"] = NA
+task_2 = as_task_classif(dt, id = "pima2", target = "diabetes")
+
+

And now we learn on task, while trying to predict on task_2.

+
+
graph_learner$train(task)
+graph_learner$predict(task_2)
+
+
<PredictionClassif> for 768 observations:
+    row_ids truth response
+          1   pos      pos
+          2   neg      neg
+          3   pos      pos
+---                       
+        766   neg      neg
+        767   pos      pos
+        768   neg      neg
+
+
+
+
+

Missing factor features

+

For factor features, the process works analogously. Instead of using imputehist, we can for example use imputeoor. This will simply replace every NA in each factor variable with a new value missing.

+

A full graph might the look like this:

+
+
imp_missind = po("missind", affect_columns = NULL, which = "all")
+imp_fct = po("imputeoor", affect_columns = selector_type("factor"))
+graph = po("copy", 2) %>>%
+  gunion(list(imp_missind, imp_num %>>% imp_fct)) %>>%
+  po("featureunion")
+
+

Note that we specify the parameter affect_columns = NULL when initializing missind, because we also want indicator columns for our factor features. By default, affect_columns would be set to selector_invert(selector_type(c("factor", "ordered", "character"))). We also set the parameter which to "all" to add indicator columns for all features, regardless whether values were missing during training or not.

+

In order to test out our new graph, we again create a situation where our task has missing factor levels. As the (pima) task does not have any factor levels, we use the famous (boston_housing) task.

+
+
# task_bh_1 is the training data without missings
+task_bh_1 = tsk("boston_housing")
+
+# task_bh_2 is the prediction data with missings
+dt = task_bh_1$data()
+dt[1:10, chas := NA][20:30, rm := NA]
+task_bh_2 = as_task_regr(dt, id = "bh", target = "medv")
+
+

Now we train on task_bh_1 and predict on task_bh_2:

+
+
graph_learner = as_learner(graph %>>% po(lrn("regr.ranger")))
+graph_learner$train(task_bh_1)
+graph_learner$predict(task_bh_2)
+
+
<PredictionRegr> for 506 observations:
+    row_ids truth response
+          1  24.0 25.16204
+          2  21.6 22.21102
+          3  34.7 33.84124
+---                       
+        504  23.9 23.68916
+        505  22.0 22.20551
+        506  11.9 16.14491
+
+
+

Success! We learned how to deal with missing values in less than 10 minutes.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/basic/2020-01-30-impute-missing-levels/index_files/figure-html/2020-01-30-impute-missing-levels-007-1.png b/gallery/basic/2020-01-30-impute-missing-levels/index_files/figure-html/2020-01-30-impute-missing-levels-007-1.png new file mode 100644 index 00000000..e1e5466b Binary files /dev/null and b/gallery/basic/2020-01-30-impute-missing-levels/index_files/figure-html/2020-01-30-impute-missing-levels-007-1.png differ diff --git a/gallery/basic/2020-01-30-impute-missing-levels/index_files/figure-html/2020-01-30-impute-missing-levels-008-1.png b/gallery/basic/2020-01-30-impute-missing-levels/index_files/figure-html/2020-01-30-impute-missing-levels-008-1.png new file mode 100644 index 00000000..8f2d0c0b Binary files /dev/null and b/gallery/basic/2020-01-30-impute-missing-levels/index_files/figure-html/2020-01-30-impute-missing-levels-008-1.png differ diff --git a/gallery/basic/2020-01-30-impute-missing-levels/index_files/figure-html/2020-01-30-impute-missing-levels-015-1.png b/gallery/basic/2020-01-30-impute-missing-levels/index_files/figure-html/2020-01-30-impute-missing-levels-015-1.png new file mode 100644 index 00000000..aa859a36 Binary files /dev/null and b/gallery/basic/2020-01-30-impute-missing-levels/index_files/figure-html/2020-01-30-impute-missing-levels-015-1.png differ diff --git a/gallery/basic/2020-01-30-impute-missing-levels/index_files/figure-html/2020-01-30-impute-missing-levels-016-1.png b/gallery/basic/2020-01-30-impute-missing-levels/index_files/figure-html/2020-01-30-impute-missing-levels-016-1.png new file mode 100644 index 00000000..d42b058a Binary files /dev/null and b/gallery/basic/2020-01-30-impute-missing-levels/index_files/figure-html/2020-01-30-impute-missing-levels-016-1.png differ diff --git a/gallery/basic/2020-01-31-encode-factors-for-xgboost/index.html b/gallery/basic/2020-01-31-encode-factors-for-xgboost/index.html new file mode 100644 index 00000000..47b21192 --- /dev/null +++ b/gallery/basic/2020-01-31-encode-factors-for-xgboost/index.html @@ -0,0 +1,943 @@ + + + + + + + + + + + + +Encode Factor Levels for xgboost – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Encode Factor Levels for xgboost

+
+
+

Encode factor variables in a task.

+
+
+
+
+ + +
+ +
+
Author
+
+

Michel Lang

+
+
+ +
+
Published
+
+

January 31, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +

The package xgboost unfortunately does not support handling of categorical features. Therefore, it is required to manually convert factor columns to numerical dummy features. We show how to use mlr3pipelines to augment the xgboost learner with an automatic factor encoding.

+

We load the mlr3verse package which pulls in the most important packages for this example.

+
+
library(mlr3verse)
+
+
Loading required package: mlr3
+
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+
+
+

Construct the Base Objects

+

First, we take an example task with factors (german_credit) and create the xgboost learner:

+
+
library(mlr3learners)
+
+task = tsk("german_credit")
+print(task)
+
+
<TaskClassif:german_credit> (1000 x 21): German Credit
+* Target: credit_risk
+* Properties: twoclass
+* Features (20):
+  - fct (14): credit_history, employment_duration, foreign_worker, housing, job, other_debtors,
+    other_installment_plans, people_liable, personal_status_sex, property, purpose, savings, status,
+    telephone
+  - int (3): age, amount, duration
+  - ord (3): installment_rate, number_credits, present_residence
+
+
learner = lrn("classif.xgboost", nrounds = 100)
+print(learner)
+
+
<LearnerClassifXgboost:classif.xgboost>
+* Model: -
+* Parameters: nrounds=100, nthread=1, verbose=0, early_stopping_set=none
+* Packages: mlr3, mlr3learners, xgboost
+* Predict Types:  [response], prob
+* Feature Types: logical, integer, numeric
+* Properties: hotstart_forward, importance, missings, multiclass, twoclass, weights
+
+
+

We now compare the feature types of the task and the supported feature types:

+
+
unique(task$feature_types$type)
+
+
[1] "integer" "factor"  "ordered"
+
+
learner$feature_types
+
+
[1] "logical" "integer" "numeric"
+
+
setdiff(task$feature_types$type, learner$feature_types)
+
+
[1] "factor"  "ordered"
+
+
+

In this example, we have to convert factors and ordered factors to numeric columns to apply the xgboost learner. Because xgboost is based on decision trees (at least in its default settings), it is perfectly fine to convert the ordered factors to integer. Unordered factors must still be encoded though.

+
+
+

Construct Operators

+

The factor encoder’s man page can be found under mlr_pipeops_encode. Here, we decide to use “treatment” encoding (first factor level serves as baseline, and there will be a new binary column for each additional level). We restrict the operator to factor columns using the respective Selector selector_type():

+
+
fencoder = po("encode", method = "treatment", affect_columns = selector_type("factor"))
+
+

We can manually trigger the PipeOp to test the operator on our task:

+
+
fencoder$train(list(task))
+
+
$output
+<TaskClassif:german_credit> (1000 x 50): German Credit
+* Target: credit_risk
+* Properties: twoclass
+* Features (49):
+  - dbl (43): credit_history.all.credits.at.this.bank.paid.back.duly,
+    credit_history.critical.account.other.credits.elsewhere,
+    credit_history.existing.credits.paid.back.duly.till.now,
+    credit_history.no.credits.taken.all.credits.paid.back.duly, employment_duration....7.yrs,
+    employment_duration...1.yr, employment_duration.1..........4.yrs, employment_duration.4..........7.yrs,
+    foreign_worker.yes, housing.own, housing.rent, job.manager.self.empl.highly.qualif..employee,
+    job.skilled.employee.official, job.unskilled...resident, other_debtors.co.applicant,
+    other_debtors.guarantor, other_installment_plans.none, other_installment_plans.stores,
+    people_liable.3.or.more, personal_status_sex.female...non.single.or.male...single,
+    personal_status_sex.female...single, personal_status_sex.male...married.widowed,
+    property.building.soc..savings.agr....life.insurance, property.car.or.other, property.real.estate,
+    purpose.business, purpose.car..new., purpose.car..used., purpose.domestic.appliances,
+    purpose.education, purpose.furniture.equipment, purpose.radio.television, purpose.repairs,
+    purpose.retraining, purpose.vacation, savings........1000.DM, savings.......100.DM,
+    savings.100..........500.DM, savings.500..........1000.DM,
+    status........200.DM...salary.for.at.least.1.year, status.......0.DM, status.0.........200.DM,
+    telephone.yes..under.customer.name.
+  - int (3): age, amount, duration
+  - ord (3): installment_rate, number_credits, present_residence
+
+
+

The ordered factor remained untouched, all other factors have been converted to numeric columns. To also convert the ordered variables installment_rate, number_credits, and present_residence, we construct the colapply operator with the converter as.integer():

+
+
ord_to_int = po("colapply", applicator = as.integer, affect_columns = selector_type("ordered"))
+
+

Applied on the original task, it changes factor columns to integer:

+
+
ord_to_int$train(list(task))
+
+
$output
+<TaskClassif:german_credit> (1000 x 21): German Credit
+* Target: credit_risk
+* Properties: twoclass
+* Features (20):
+  - fct (14): credit_history, employment_duration, foreign_worker, housing, job, other_debtors,
+    other_installment_plans, people_liable, personal_status_sex, property, purpose, savings, status,
+    telephone
+  - int (6): age, amount, duration, installment_rate, number_credits, present_residence
+
+
+
+

Construct Pipeline

+

Finally, we construct a linear pipeline consisting of

+
    +
  1. the factor encoder fencoder,
  2. +
  3. the ordered factor converter ord_to_int, and
  4. +
  5. the xgboost base learner.
  6. +
+
+
graph = fencoder %>>% ord_to_int %>>% learner
+print(graph)
+
+
Graph with 3 PipeOps:
+              ID         State        sccssors prdcssors
+          encode        <list>        colapply          
+        colapply        <list> classif.xgboost    encode
+ classif.xgboost <<UNTRAINED>>                  colapply
+
+
+

The pipeline is wrapped in a GraphLearner so that it behaves like a regular learner:

+
+
graph_learner = as_learner(graph)
+
+

We can now apply the new learner on the task, here with a 3-fold cross validation:

+
+
rr = resample(task, graph_learner, rsmp("cv", folds = 3))
+rr$aggregate()
+
+
classif.ce 
+ 0.2620435 
+
+
+

Success! We augmented xgboost with handling of factors and ordered factors. If we combine this learner with a tuner from mlr3tuning, we get a universal and competitive learner.

+ + +
+
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/basic/2020-02-25-remove-correlated-features/index.html b/gallery/basic/2020-02-25-remove-correlated-features/index.html new file mode 100644 index 00000000..00e9dcc1 --- /dev/null +++ b/gallery/basic/2020-02-25-remove-correlated-features/index.html @@ -0,0 +1,874 @@ + + + + + + + + + + + + + +Select Uncorrelated Features – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Select Uncorrelated Features

+
+
+

Remove correlated features with a pipeline.

+
+
+ +
+ + +
+ +
+
Authors
+
+

Martin Binder

+

Florian Pfisterer

+
+
+ +
+
Published
+
+

February 25, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +

The following example describes a situation where we aim to remove correlated features. This in essence means, that we drop features until no features have a correlation higher than a given cutoff. This is often useful when we for example want to use linear models.

+
+

Prerequisites

+

This tutorial assumes familiarity with the basics of mlr3pipelines. Consult the mlr3book if some aspects are not fully understandable. Additionally, we compare different cutoff values via tuning using the mlr3tuning package. Again, the mlr3book has an intro to mlr3tuning and paradox.

+

The example describes a very involved use-case, where the behavior of PipeOpSelect is manipulated via a trafo on it’s ParamSet

+
+
+

Getting started

+

We load the mlr3verse package which pulls in the most important packages for this example.

+
+
library(mlr3verse)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+

The basic pipeline looks as follows: We use PipeOpSelect to select a set of variables followed by a rpart learner.

+
+
graph_learner = po("select") %>>% lrn("classif.rpart")
+
+

Now we get to the magic:

+

We want to use the function caret::findCorrelation() from the caret package in order to select uncorrelated variables. This function has a cutoff parameter, that specifies the maximum correlation allowed between variables. In order to expose this variable as a numeric parameter we can tune over we specify the following ParamSet:

+
+
search_space = ps(cutoff = p_dbl(0, 1))
+
+

We define a function select_cutoff that takes as input a Task and returns a list of features we aim to keep.

+

Now we use a trafo to transform the cutoff into a set of variables, which is what PipeOpSelect can work with. Note that we use x$cutoff = NULL in order to remove the temporary parameter we introduced, as PipeOpSelect does not know what to do with it.

+
+
search_space$trafo = function(x, param_set) {
+  cutoff = x$cutoff
+  x$select.selector = function(task) {
+    fn = task$feature_names
+    data = task$data(cols = fn)
+    drop = caret::findCorrelation(cor(data), cutoff = cutoff, exact = TRUE, names = TRUE)
+    setdiff(fn, drop)
+  }
+  x$cutoff = NULL
+  x
+}
+
+

If you are not sure, you understand the trafo concept, consult the mlr3book. It has a section on the trafo concept.

+

Now we tune over different values for cutoff.

+
+
instance = tune(
+  tuner = tnr("grid_search"),
+  task = tsk("iris"),
+  learner = graph_learner,
+  resampling = rsmp("cv", folds = 3L),
+  measure = msr("classif.ce"),
+  search_space = search_space,
+  # don't need the following line for optimization, this is for
+  # demonstration that different features were selected
+  store_models = TRUE)
+
+

In order to demonstrate that different cutoff values result in different features being selected, we can run the following to inspect the trained models. Note this inspects only the trained models of the first CV fold of each evaluated model. The features being excluded depends on the training data seen by the pipeline and may be different in different folds, even at the same cutoff value.

+
+
as.data.table(instance$archive)[
+  order(cutoff),
+  list(cutoff, classif.ce,
+    featurenames = lapply(resample_result, function(x) {
+      x$learners[[1]]$model$classif.rpart$train_task$feature_names
+    }
+  ))]
+
+
       cutoff classif.ce                                      featurenames
+ 1: 0.0000000 0.28666667                                      Sepal.Length
+ 2: 0.1111111 0.28666667                                      Sepal.Length
+ 3: 0.2222222 0.28666667                                      Sepal.Length
+ 4: 0.3333333 0.27333333                          Sepal.Length,Sepal.Width
+ 5: 0.4444444 0.27333333                          Sepal.Length,Sepal.Width
+ 6: 0.5555556 0.27333333                          Sepal.Length,Sepal.Width
+ 7: 0.6666667 0.27333333                          Sepal.Length,Sepal.Width
+ 8: 0.7777778 0.27333333                          Sepal.Length,Sepal.Width
+ 9: 0.8888889 0.04000000              Petal.Width,Sepal.Length,Sepal.Width
+10: 1.0000000 0.06666667 Petal.Length,Petal.Width,Sepal.Length,Sepal.Width
+
+
+

Voila, we created our own PipeOp, that uses very advanced knowledge of mlr3pipelines and paradox in only few lines of code.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/basic/2020-03-11-basics-german-credit/index.html b/gallery/basic/2020-03-11-basics-german-credit/index.html new file mode 100644 index 00000000..a796648f --- /dev/null +++ b/gallery/basic/2020-03-11-basics-german-credit/index.html @@ -0,0 +1,1922 @@ + + + + + + + + + + + + + + +German Credit Series - Basics – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

German Credit Series - Basics

+
+
+

Train different models.

+
+
+
+
+ + +
+ +
+
Authors
+
+

Martin Binder

+

Florian Pfisterer

+

Michel Lang

+
+
+ +
+
Published
+
+

March 11, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Intro

+

This is the first part in a serial of tutorials. The other parts of this series can be found here:

+ +

We will walk through this tutorial interactively. The text is kept short to be followed in real time.

+
+
+

Prerequisites

+

Ensure all packages used in this tutorial are installed. This includes the mlr3verse package, as well as other packages for data handling, cleaning and visualization which we are going to use (data.table, ggplot2, rchallenge, and skimr).

+

Then, load the main packages we are going to use:

+
+
library("mlr3verse")
+library("mlr3learners")
+library("mlr3tuning")
+library("data.table")
+library("ggplot2")
+
+lgr::get_logger("mlr3")$set_threshold("warn")
+
+
+
+

Machine Learning Use Case: German Credit Data

+

The German credit data was originally donated in 1994 by Prof. Dr. Hans Hoffman of the University of Hamburg. A description can be found at the UCI repository. The goal is to classify people by their credit risk (good or bad) using 20 personal, demographic and financial features:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Feature NameDescription
ageage in years
amountamount asked by applicant
credit_historypast credit history of applicant at this bank
durationduration of the credit in months
employment_durationpresent employment since
foreign_workeris applicant foreign worker?
housingtype of apartment rented, owned, for free / no payment
installment_rateinstallment rate in percentage of disposable income
jobcurrent job information
number_creditsnumber of existing credits at this bank
other_debtorsother debtors/guarantors present?
other_installment_plansother installment plans the applicant is paying
people_liablenumber of people being liable to provide maintenance
personal_status_sexcombination of sex and personal status of applicant
present_residencepresent residence since
propertyproperties that applicant has
purposereason customer is applying for a loan
savingssavings accounts/bonds at this bank
statusstatus/balance of checking account at this bank
telephoneis there any telephone registered for this customer?
+
+

Importing the Data

+

The dataset we are going to use is a transformed version of this German credit dataset, as provided by the rchallenge package (this transformed dataset was proposed by Ulrike Grömping, with factors instead of dummy variables and corrected features):

+
+
data("german", package = "rchallenge")
+
+

First, we’ll do a thorough investigation of the dataset.

+
+
+

Exploring the Data

+

We can get a quick overview of our dataset using R’s summary function:

+
+
dim(german)
+
+
[1] 1000   21
+
+
str(german)
+
+
'data.frame':   1000 obs. of  21 variables:
+ $ status                 : Factor w/ 4 levels "no checking account",..: 1 1 2 1 1 1 1 1 4 2 ...
+ $ duration               : int  18 9 12 12 12 10 8 6 18 24 ...
+ $ credit_history         : Factor w/ 5 levels "delay in paying off in the past",..: 5 5 3 5 5 5 5 5 5 3 ...
+ $ purpose                : Factor w/ 11 levels "others","car (new)",..: 3 1 10 1 1 1 1 1 4 4 ...
+ $ amount                 : int  1049 2799 841 2122 2171 2241 3398 1361 1098 3758 ...
+ $ savings                : Factor w/ 5 levels "unknown/no savings account",..: 1 1 2 1 1 1 1 1 1 3 ...
+ $ employment_duration    : Factor w/ 5 levels "unemployed","< 1 yr",..: 2 3 4 3 3 2 4 2 1 1 ...
+ $ installment_rate       : Ord.factor w/ 4 levels ">= 35"<"25 <= ... < 35"<..: 4 2 2 3 4 1 1 2 4 1 ...
+ $ personal_status_sex    : Factor w/ 4 levels "male : divorced/separated",..: 2 3 2 3 3 3 3 3 2 2 ...
+ $ other_debtors          : Factor w/ 3 levels "none","co-applicant",..: 1 1 1 1 1 1 1 1 1 1 ...
+ $ present_residence      : Ord.factor w/ 4 levels "< 1 yr"<"1 <= ... < 4 yrs"<..: 4 2 4 2 4 3 4 4 4 4 ...
+ $ property               : Factor w/ 4 levels "unknown / no property",..: 2 1 1 1 2 1 1 1 3 4 ...
+ $ age                    : int  21 36 23 39 38 48 39 40 65 23 ...
+ $ other_installment_plans: Factor w/ 3 levels "bank","stores",..: 3 3 3 3 1 3 3 3 3 3 ...
+ $ housing                : Factor w/ 3 levels "for free","rent",..: 1 1 1 1 2 1 2 2 2 1 ...
+ $ number_credits         : Ord.factor w/ 4 levels "1"<"2-3"<"4-5"<..: 1 2 1 2 2 2 2 1 2 1 ...
+ $ job                    : Factor w/ 4 levels "unemployed/unskilled - non-resident",..: 3 3 2 2 2 2 2 2 1 1 ...
+ $ people_liable          : Factor w/ 2 levels "3 or more","0 to 2": 2 1 2 1 2 1 2 1 2 2 ...
+ $ telephone              : Factor w/ 2 levels "no","yes (under customer name)": 1 1 1 1 1 1 1 1 1 1 ...
+ $ foreign_worker         : Factor w/ 2 levels "yes","no": 2 2 2 1 1 1 1 1 2 2 ...
+ $ credit_risk            : Factor w/ 2 levels "bad","good": 2 2 2 2 2 2 2 2 2 2 ...
+
+
+

Our dataset has 1000 observations and 21 columns. The variable we want to predict is credit_risk (either good or bad), i.e., we aim to classify people by their credit risk.

+

We also recommend the skimr package as it creates very well readable and understandable overviews:

+
+
skimr::skim(german)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Data summary
Namegerman
Number of rows1000
Number of columns21
_______________________
Column type frequency:
factor18
numeric3
________________________
Group variablesNone
+

Variable type: factor

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_rateorderedn_uniquetop_counts
status01FALSE4…: 394, no : 274, …: 269, 0<=: 63
credit_history01FALSE5no : 530, all: 293, exi: 88, cri: 49
purpose01FALSE10fur: 280, oth: 234, car: 181, car: 103
savings01FALSE5unk: 603, …: 183, …: 103, 100: 63
employment_duration01FALSE51 <: 339, >= : 253, 4 <: 174, < 1: 172
installment_rate01TRUE4< 2: 476, 25 : 231, 20 : 157, >= : 136
personal_status_sex01FALSE4mal: 548, fem: 310, fem: 92, mal: 50
other_debtors01FALSE3non: 907, gua: 52, co-: 41
present_residence01TRUE4>= : 413, 1 <: 308, 4 <: 149, < 1: 130
property01FALSE4bui: 332, unk: 282, car: 232, rea: 154
other_installment_plans01FALSE3non: 814, ban: 139, sto: 47
housing01FALSE3ren: 714, for: 179, own: 107
number_credits01TRUE41: 633, 2-3: 333, 4-5: 28, >= : 6
job01FALSE4ski: 630, uns: 200, man: 148, une: 22
people_liable01FALSE20 t: 845, 3 o: 155
telephone01FALSE2no: 596, yes: 404
foreign_worker01FALSE2no: 963, yes: 37
credit_risk01FALSE2goo: 700, bad: 300
+

Variable type: numeric

+ +++++++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_ratemeansdp0p25p50p75p100hist
duration0120.9012.06412.018.024.0072▇▇▂▁▁
amount013271.252822.752501365.52319.53972.2518424▇▂▁▁▁
age0135.5411.351927.033.042.0075▇▆▃▁▁
+
+
+

During an exploratory analysis meaningful discoveries could be:

+
    +
  • Skewed distributions
  • +
  • Missing values
  • +
  • Empty / rare factor variables
  • +
+

An explanatory analysis is crucial to get a feeling for your data. On the other hand the data can be validated this way. Non-plausible data can be investigated or outliers can be removed.

+

After feeling confident with the data, we want to do modeling now.

+
+
+
+

Modeling

+

Considering how we are going to tackle the problem of classifying the credit risk relates closely to what mlr3 entities we will use.

+

The typical questions that arise when building a machine learning workflow are:

+
    +
  • What is the problem we are trying to solve?
  • +
  • What are appropriate learning algorithms?
  • +
  • How do we evaluate “good” performance?
  • +
+

More systematically in mlr3 they can be expressed via five components:

+
    +
  1. The Task definition.
  2. +
  3. The Learner definition.
  4. +
  5. The training.
  6. +
  7. The prediction.
  8. +
  9. The evaluation via one or multiple Measures.
  10. +
+
+

Task Definition

+

First, we are interested in the target which we want to model. Most supervised machine learning problems are regression or classification problems. However, note that other problems include unsupervised learning or time-to-event data (covered in mlr3proba).

+

Within mlr3, to distinguish between these problems, we define Tasks. If we want to solve a classification problem, we define a classification task – TaskClassif. For a regression problem, we define a regression task – TaskRegr.

+

In our case it is clearly our objective to model or predict the binary factor variable credit_risk. Thus, we define a TaskClassif:

+
+
task = as_task_classif(german, id = "GermanCredit", target = "credit_risk")
+
+

Note that the German credit data is also given as an example task which ships with the mlr3 package. Thus, you actually don’t need to construct it yourself, just call tsk("german_credit") to retrieve the object from the dictionary mlr_tasks.

+
+
+

Learner Definition

+

After having decided what should be modeled, we need to decide on how. This means we need to decide which learning algorithms, or Learners are appropriate. Using prior knowledge (e.g. knowing that it is a classification task or assuming that the classes are linearly separable) one ends up with one or more suitable Learners.

+

Many learners can be obtained via the mlr3learners package. Additionally, many learners are provided via the mlr3extralearners package, from GitHub. These two resources combined account for a large fraction of standard learning algorithms. As mlr3 usually only wraps learners from packages, it is even easy to create a formal Learner by yourself. You may find the section about extending mlr3 in the mlr3book very helpful. If you happen to write your own Learner in mlr3, we would be happy if you share it with the mlr3 community.

+

All available Learners (i.e. all which you have installed from mlr3, mlr3learners, mlr3extralearners, or self-written ones) are registered in the dictionary mlr_learners:

+
+
mlr_learners
+
+
<DictionaryLearner> with 134 stored values
+Keys: classif.AdaBoostM1, classif.bart, classif.C50, classif.catboost, classif.cforest, classif.ctree,
+  classif.cv_glmnet, classif.debug, classif.earth, classif.featureless, classif.fnn, classif.gam,
+  classif.gamboost, classif.gausspr, classif.gbm, classif.glmboost, classif.glmer, classif.glmnet,
+  classif.IBk, classif.J48, classif.JRip, classif.kknn, classif.ksvm, classif.lda, classif.liblinear,
+  classif.lightgbm, classif.LMT, classif.log_reg, classif.lssvm, classif.mob, classif.multinom,
+  classif.naive_bayes, classif.nnet, classif.OneR, classif.PART, classif.qda, classif.randomForest,
+  classif.ranger, classif.rfsrc, classif.rpart, classif.svm, classif.xgboost, clust.agnes, clust.ap,
+  clust.cmeans, clust.cobweb, clust.dbscan, clust.diana, clust.em, clust.fanny, clust.featureless,
+  clust.ff, clust.hclust, clust.kkmeans, clust.kmeans, clust.MBatchKMeans, clust.mclust, clust.meanshift,
+  clust.pam, clust.SimpleKMeans, clust.xmeans, dens.kde_ks, dens.locfit, dens.logspline, dens.mixed,
+  dens.nonpar, dens.pen, dens.plug, dens.spline, regr.bart, regr.catboost, regr.cforest, regr.ctree,
+  regr.cubist, regr.cv_glmnet, regr.debug, regr.earth, regr.featureless, regr.fnn, regr.gam, regr.gamboost,
+  regr.gausspr, regr.gbm, regr.glm, regr.glmboost, regr.glmnet, regr.IBk, regr.kknn, regr.km, regr.ksvm,
+  regr.liblinear, regr.lightgbm, regr.lm, regr.lmer, regr.M5Rules, regr.mars, regr.mob, regr.nnet,
+  regr.randomForest, regr.ranger, regr.rfsrc, regr.rpart, regr.rsm, regr.rvm, regr.svm, regr.xgboost,
+  surv.akritas, surv.aorsf, surv.blackboost, surv.cforest, surv.coxboost, surv.coxtime, surv.ctree,
+  surv.cv_coxboost, surv.cv_glmnet, surv.deephit, surv.deepsurv, surv.dnnsurv, surv.flexible,
+  surv.gamboost, surv.gbm, surv.glmboost, surv.glmnet, surv.loghaz, surv.mboost, surv.nelson,
+  surv.obliqueRSF, surv.parametric, surv.pchazard, surv.penalized, surv.ranger, surv.rfsrc, surv.svm,
+  surv.xgboost
+
+
+

For our problem, a suitable learner could be one of the following: Logistic regression, CART, random forest (or many more).

+

A learner can be initialized with the lrn() function and the name of the learner, e.g., lrn("classif.xxx"). Use ?mlr_learners_xxx to open the help page of a learner named xxx.

+

For example, a logistic regression can be initialized in the following manner (logistic regression uses R’s glm() function and is provided by the mlr3learners package):

+
+
library("mlr3learners")
+learner_logreg = lrn("classif.log_reg")
+print(learner_logreg)
+
+
<LearnerClassifLogReg:classif.log_reg>
+* Model: -
+* Parameters: list()
+* Packages: mlr3, mlr3learners, stats
+* Predict Types:  [response], prob
+* Feature Types: logical, integer, numeric, character, factor, ordered
+* Properties: loglik, twoclass
+
+
+
+
+

Training

+

Training is the procedure, where a model is fitted on the (training) data.

+
+

Logistic Regression

+

We start with the example of the logistic regression. However, you will immediately see that the procedure generalizes to any learner very easily.

+

An initialized learner can be trained on data using $train():

+
+
learner_logreg$train(task)
+
+

Typically, in machine learning, one does not use the full data which is available but a subset, the so-called training data.

+

To efficiently perform a split of the data one could do the following:

+
+
train_set = sample(task$row_ids, 0.8 * task$nrow)
+test_set = setdiff(task$row_ids, train_set)
+
+

80 percent of the data is used for training. The remaining 20 percent are used for evaluation at a subsequent later point in time. train_set is an integer vector referring to the selected rows of the original dataset:

+
+
head(train_set)
+
+
[1] 836 679 129 930 509 471
+
+
+

In mlr3 the training with a subset of the data can be declared by the additional argument row_ids = train_set:

+
+
learner_logreg$train(task, row_ids = train_set)
+
+

The fitted model can be accessed via:

+
+
learner_logreg$model
+
+

+Call:  stats::glm(formula = task$formula(), family = "binomial", data = data, 
+    model = FALSE)
+
+Coefficients:
+                                              (Intercept)                                                        age  
+                                                0.0688846                                                 -0.0159818  
+                                                   amount     credit_historycritical account/other credits elsewhere  
+                                                0.0001329                                                  0.4580373  
+credit_historyno credits taken/all credits paid back duly     credit_historyexisting credits paid back duly till now  
+                                               -0.5087518                                                 -1.0249187  
+    credit_historyall credits at this bank paid back duly                                                   duration  
+                                               -1.5582920                                                  0.0360543  
+                                employment_duration< 1 yr                        employment_duration1 <= ... < 4 yrs  
+                                                0.0720620                                                 -0.1262893  
+                      employment_duration4 <= ... < 7 yrs                                employment_duration>= 7 yrs  
+                                               -0.5589136                                                 -0.1545512  
+                                         foreign_workerno                                                housingrent  
+                                                1.3647905                                                 -0.6199554  
+                                               housingown                                         installment_rate.L  
+                                               -0.6851413                                                  0.8838467  
+                                       installment_rate.Q                                         installment_rate.C  
+                                               -0.0385000                                                 -0.1072466  
+                                  jobunskilled - resident                               jobskilled employee/official  
+                                                0.9797910                                                  0.7657897  
+            jobmanager/self-empl./highly qualif. employee                                           number_credits.L  
+                                                0.5793418                                                  0.4081443  
+                                         number_credits.Q                                           number_credits.C  
+                                               -0.3386148                                                 -0.0262034  
+                                other_debtorsco-applicant                                     other_debtorsguarantor  
+                                                0.4995457                                                 -0.4840799  
+                            other_installment_plansstores                                other_installment_plansnone  
+                                                0.1844457                                                 -0.2035917  
+                                      people_liable0 to 2    personal_status_sexfemale : non-single or male : single  
+                                               -0.2306212                                                 -0.2797497  
+                personal_status_sexmale : married/widowed                         personal_status_sexfemale : single  
+                                               -0.7947385                                                 -0.4173530  
+                                      present_residence.L                                        present_residence.Q  
+                                                0.0948244                                                 -0.4654771  
+                                      present_residence.C                                       propertycar or other  
+                                                0.2317025                                                  0.2583020  
+        propertybuilding soc. savings agr./life insurance                                        propertyreal estate  
+                                                0.2595201                                                  0.6821534  
+                                         purposecar (new)                                          purposecar (used)  
+                                               -1.5120761                                                 -0.6224479  
+                               purposefurniture/equipment                                    purposeradio/television  
+                                               -0.7776132                                                 -0.1649750  
+                               purposedomestic appliances                                             purposerepairs  
+                                                0.1966830                                                  0.3824875  
+                                          purposevacation                                          purposeretraining  
+                                               -1.9184037                                                 -0.9364954  
+                                          purposebusiness                                       savings... <  100 DM  
+                                               -1.2647440                                                 -0.2148135  
+                              savings100 <= ... <  500 DM                                savings500 <= ... < 1000 DM  
+                                               -0.5445696                                                 -1.4241969  
+                                    savings... >= 1000 DM                                           status... < 0 DM  
+                                               -1.0478097                                                 -0.4584854  
+                                   status0<= ... < 200 DM           status... >= 200 DM / salary for at least 1 year  
+                                               -0.8798435                                                 -1.7552018  
+                       telephoneyes (under customer name)  
+                                               -0.1798432  
+
+Degrees of Freedom: 799 Total (i.e. Null);  745 Residual
+Null Deviance:      980.7 
+Residual Deviance: 702.6    AIC: 812.6
+
+
+

The stored object is a normal glm object and all its S3 methods work as expected:

+
+
class(learner_logreg$model)
+
+
[1] "glm" "lm" 
+
+
summary(learner_logreg$model)
+
+

+Call:
+stats::glm(formula = task$formula(), family = "binomial", data = data, 
+    model = FALSE)
+
+Deviance Residuals: 
+    Min       1Q   Median       3Q      Max  
+-2.3992  -0.6812  -0.3642   0.6939   2.7540  
+
+Coefficients:
+                                                            Estimate Std. Error z value Pr(>|z|)    
+(Intercept)                                                0.0688846  1.3333299   0.052 0.958797    
+age                                                       -0.0159818  0.0105444  -1.516 0.129605    
+amount                                                     0.0001329  0.0000502   2.647 0.008110 ** 
+credit_historycritical account/other credits elsewhere     0.4580373  0.6523911   0.702 0.482623    
+credit_historyno credits taken/all credits paid back duly -0.5087518  0.4802925  -1.059 0.289484    
+credit_historyexisting credits paid back duly till now    -1.0249188  0.5343038  -1.918 0.055082 .  
+credit_historyall credits at this bank paid back duly     -1.5582920  0.4858084  -3.208 0.001338 ** 
+duration                                                   0.0360543  0.0106583   3.383 0.000718 ***
+employment_duration< 1 yr                                  0.0720620  0.4845297   0.149 0.881770    
+employment_duration1 <= ... < 4 yrs                       -0.1262893  0.4577516  -0.276 0.782632    
+employment_duration4 <= ... < 7 yrs                       -0.5589136  0.5016876  -1.114 0.265250    
+employment_duration>= 7 yrs                               -0.1545512  0.4625121  -0.334 0.738262    
+foreign_workerno                                           1.3647905  0.6425196   2.124 0.033660 *  
+housingrent                                               -0.6199554  0.2705326  -2.292 0.021928 *  
+housingown                                                -0.6851413  0.5581021  -1.228 0.219587    
+installment_rate.L                                         0.8838467  0.2472850   3.574 0.000351 ***
+installment_rate.Q                                        -0.0385001  0.2217440  -0.174 0.862161    
+installment_rate.C                                        -0.1072466  0.2281857  -0.470 0.638357    
+jobunskilled - resident                                    0.9797910  0.7877153   1.244 0.213559    
+jobskilled employee/official                               0.7657897  0.7627061   1.004 0.315358    
+jobmanager/self-empl./highly qualif. employee              0.5793418  0.7790492   0.744 0.457087    
+number_credits.L                                           0.4081443  0.7356488   0.555 0.579026    
+number_credits.Q                                          -0.3386148  0.6189845  -0.547 0.584345    
+number_credits.C                                          -0.0262034  0.4717322  -0.056 0.955703    
+other_debtorsco-applicant                                  0.4995457  0.4504675   1.109 0.267452    
+other_debtorsguarantor                                    -0.4840799  0.4744964  -1.020 0.307635    
+other_installment_plansstores                              0.1844457  0.4733765   0.390 0.696804    
+other_installment_plansnone                               -0.2035917  0.2881916  -0.706 0.479911    
+people_liable0 to 2                                       -0.2306212  0.2905750  -0.794 0.427386    
+personal_status_sexfemale : non-single or male : single   -0.2797497  0.4602069  -0.608 0.543268    
+personal_status_sexmale : married/widowed                 -0.7947384  0.4513890  -1.761 0.078297 .  
+personal_status_sexfemale : single                        -0.4173530  0.5348044  -0.780 0.435165    
+present_residence.L                                        0.0948244  0.2496873   0.380 0.704114    
+present_residence.Q                                       -0.4654771  0.2293239  -2.030 0.042379 *  
+present_residence.C                                        0.2317025  0.2240902   1.034 0.301150    
+propertycar or other                                       0.2583020  0.2934956   0.880 0.378812    
+propertybuilding soc. savings agr./life insurance          0.2595201  0.2712751   0.957 0.338735    
+propertyreal estate                                        0.6821535  0.4931574   1.383 0.166592    
+purposecar (new)                                          -1.5120761  0.4173677  -3.623 0.000291 ***
+purposecar (used)                                         -0.6224479  0.2979802  -2.089 0.036718 *  
+purposefurniture/equipment                                -0.7776132  0.2803938  -2.773 0.005549 ** 
+purposeradio/television                                   -0.1649750  0.8289212  -0.199 0.842244    
+purposedomestic appliances                                 0.1966830  0.6322897   0.311 0.755751    
+purposerepairs                                             0.3824875  0.4657037   0.821 0.411469    
+purposevacation                                           -1.9184037  1.1948196  -1.606 0.108362    
+purposeretraining                                         -0.9364954  0.4014654  -2.333 0.019664 *  
+purposebusiness                                           -1.2647440  0.8064326  -1.568 0.116807    
+savings... <  100 DM                                      -0.2148135  0.3235401  -0.664 0.506724    
+savings100 <= ... <  500 DM                               -0.5445696  0.5037257  -1.081 0.279660    
+savings500 <= ... < 1000 DM                               -1.4241969  0.6223390  -2.288 0.022111 *  
+savings... >= 1000 DM                                     -1.0478097  0.3067055  -3.416 0.000635 ***
+status... < 0 DM                                          -0.4584854  0.2481344  -1.848 0.064641 .  
+status0<= ... < 200 DM                                    -0.8798435  0.4219102  -2.085 0.037035 *  
+status... >= 200 DM / salary for at least 1 year          -1.7552018  0.2629099  -6.676 2.45e-11 ***
+telephoneyes (under customer name)                        -0.1798432  0.2322797  -0.774 0.438781    
+---
+Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
+
+(Dispersion parameter for binomial family taken to be 1)
+
+    Null deviance: 980.75  on 799  degrees of freedom
+Residual deviance: 702.58  on 745  degrees of freedom
+AIC: 812.58
+
+Number of Fisher Scoring iterations: 5
+
+
+
+
+

Random Forest

+

Just like the logistic regression, we could train a random forest instead. We use the fast implementation from the ranger package. For this, we first need to define the learner and then actually train it.

+

We now additionally supply the importance argument (importance = "permutation"). Doing so, we override the default and let the learner do feature importance determination based on permutation feature importance:

+
+
learner_rf = lrn("classif.ranger", importance = "permutation")
+learner_rf$train(task, row_ids = train_set)
+
+

We can access the importance values using $importance():

+
+
learner_rf$importance()
+
+
                 status                duration                  amount          credit_history                 savings 
+           0.0352305897            0.0220794319            0.0126390139            0.0118909925            0.0097629159 
+                    age                property     employment_duration        installment_rate           other_debtors 
+           0.0089588614            0.0065744135            0.0054059438            0.0039772325            0.0029554567 
+                purpose                     job                 housing     personal_status_sex       present_residence 
+           0.0029153698            0.0019001816            0.0017784386            0.0016809300            0.0012840096 
+              telephone          number_credits other_installment_plans           people_liable          foreign_worker 
+           0.0010803276            0.0009842075            0.0004556746            0.0003807613            0.0003657158 
+
+
+

In order to obtain a plot for the importance values, we convert the importance to a data.table and then process it with ggplot2:

+
+
importance = as.data.table(learner_rf$importance(), keep.rownames = TRUE)
+colnames(importance) = c("Feature", "Importance")
+ggplot(importance, aes(x = reorder(Feature, Importance), y = Importance)) +
+  geom_col() + coord_flip() + xlab("")
+
+
+
+

+
+
+
+
+
+
+
+

Prediction

+

Let’s see what the models predict.

+

After training a model, the model can be used for prediction. Usually, prediction is the main purpose of machine learning models.

+

In our case, the model can be used to classify new credit applicants w.r.t. their associated credit risk (good vs. bad) on the basis of the features. Typically, machine learning models predict numeric values. In the regression case this is very natural. For classification, most models predict scores or probabilities. Based on these values, one can derive class predictions.

+
+

Predict Classes

+

First, we directly predict classes:

+
+
prediction_logreg = learner_logreg$predict(task, row_ids = test_set)
+prediction_rf = learner_rf$predict(task, row_ids = test_set)
+
+
+
prediction_logreg
+
+
<PredictionClassif> for 200 observations:
+    row_ids truth response
+         18  good     good
+         23   bad      bad
+         26  good     good
+---                       
+        996   bad     good
+        997   bad      bad
+       1000   bad     good
+
+
+
+
prediction_rf
+
+
<PredictionClassif> for 200 observations:
+    row_ids truth response
+         18  good     good
+         23   bad      bad
+         26  good     good
+---                       
+        996   bad      bad
+        997   bad     good
+       1000   bad     good
+
+
+

The $predict() method returns a Prediction object. It can be converted to a data.table if one wants to use it downstream.

+

We can also display the prediction results aggregated in a confusion matrix:

+
+
prediction_logreg$confusion
+
+
        truth
+response bad good
+    bad   28   17
+    good  30  125
+
+
prediction_rf$confusion
+
+
        truth
+response bad good
+    bad   24   13
+    good  34  129
+
+
+
+
+

Predict Probabilities

+

Most learners may not only predict a class variable (“response”), but also their degree of “belief” / “uncertainty” in a given response. Typically, we achieve this by setting the $predict_type slot of a Learner to "prob". Sometimes this needs to be done before the learner is trained. Alternatively, we can directly create the learner with this option: lrn("classif.log_reg", predict_type = "prob").

+
+
learner_logreg$predict_type = "prob"
+
+
+
learner_logreg$predict(task, row_ids = test_set)
+
+
<PredictionClassif> for 200 observations:
+    row_ids truth response   prob.bad prob.good
+         18  good     good 0.24602549 0.7539745
+         23   bad      bad 0.88286383 0.1171362
+         26  good     good 0.05730414 0.9426959
+---                                            
+        996   bad     good 0.49783778 0.5021622
+        997   bad      bad 0.59947093 0.4005291
+       1000   bad     good 0.42568263 0.5743174
+
+
+

Note that sometimes one needs to be cautious when dealing with the probability interpretation of the predictions.

+
+
+
+

Performance Evaluation

+

To measure the performance of a learner on new unseen data, we usually mimic the scenario of unseen data by splitting up the data into training and test set. The training set is used for training the learner, and the test set is only used for predicting and evaluating the performance of the trained learner. Numerous resampling methods (cross-validation, bootstrap) repeat the splitting process in different ways.

+

Within mlr3, we need to specify the resampling strategy using the rsmp() function:

+
+
resampling = rsmp("holdout", ratio = 2/3)
+print(resampling)
+
+
<ResamplingHoldout>: Holdout
+* Iterations: 1
+* Instantiated: FALSE
+* Parameters: ratio=0.6667
+
+
+

Here, we use “holdout”, a simple train-test split (with just one iteration). We use the resample() function to undertake the resampling calculation:

+
+
res = resample(task, learner = learner_logreg, resampling = resampling)
+res
+
+
<ResampleResult> of 1 iterations
+* Task: GermanCredit
+* Learner: classif.log_reg
+* Warnings: 0 in 0 iterations
+* Errors: 0 in 0 iterations
+
+
+

The default score of the measure is included in the $aggregate() slot:

+
+
res$aggregate()
+
+
classif.ce 
+ 0.2432432 
+
+
+

The default measure in this scenario is the classification error. Lower is better.

+

We can easily run different resampling strategies, e.g. repeated holdout ("subsampling"), or cross validation. Most methods perform repeated train/predict cycles on different data subsets and aggregate the result (usually as the mean). Doing this manually would require us to write loops. mlr3 does the job for us:

+
+
resampling = rsmp("subsampling", repeats = 10)
+rr = resample(task, learner = learner_logreg, resampling = resampling)
+rr$aggregate()
+
+
classif.ce 
+ 0.2474474 
+
+
+

Instead, we could also run cross-validation:

+
+
resampling = resampling = rsmp("cv", folds = 10)
+rr = resample(task, learner = learner_logreg, resampling = resampling)
+rr$aggregate()
+
+
classif.ce 
+     0.257 
+
+
+

mlr3 features scores for many more measures. Here, we apply mlr_measures_classif.fpr for the false positive rate, and mlr_measures_classif.fnr for the false negative rate. Multiple measures can be provided as a list of measures (which can directly be constructed via msrs():

+
+
# false positive rate
+rr$aggregate(msr("classif.fpr"))
+
+
classif.fpr 
+  0.1472895 
+
+
# false positive rate and false negative
+measures = msrs(c("classif.fpr", "classif.fnr"))
+rr$aggregate(measures)
+
+
classif.fpr classif.fnr 
+  0.1472895   0.5197922 
+
+
+

There are a few more resampling methods, and quite a few more measures (implemented in mlr3measures). They are automatically registered in the respective dictionaries:

+
+
mlr_resamplings
+
+
<DictionaryResampling> with 9 stored values
+Keys: bootstrap, custom, custom_cv, cv, holdout, insample, loo, repeated_cv, subsampling
+
+
mlr_measures
+
+
<DictionaryMeasure> with 67 stored values
+Keys: aic, bic, classif.acc, classif.auc, classif.bacc, classif.bbrier, classif.ce, classif.costs,
+  classif.dor, classif.fbeta, classif.fdr, classif.fn, classif.fnr, classif.fomr, classif.fp, classif.fpr,
+  classif.logloss, classif.mauc_au1p, classif.mauc_au1u, classif.mauc_aunp, classif.mauc_aunu,
+  classif.mbrier, classif.mcc, classif.npv, classif.ppv, classif.prauc, classif.precision, classif.recall,
+  classif.sensitivity, classif.specificity, classif.tn, classif.tnr, classif.tp, classif.tpr, clust.ch,
+  clust.db, clust.dunn, clust.silhouette, clust.wss, debug_classif, oob_error, regr.bias, regr.ktau,
+  regr.mae, regr.mape, regr.maxae, regr.medae, regr.medse, regr.mse, regr.msle, regr.pbias, regr.rae,
+  regr.rmse, regr.rmsle, regr.rrse, regr.rse, regr.rsq, regr.sae, regr.smape, regr.srho, regr.sse,
+  selected_features, sim.jaccard, sim.phi, time_both, time_predict, time_train
+
+
+

To get help on a resampling method, use ?mlr_resamplings_xxx, for a measure do ?mlr_measures_xxx. You can also browse the mlr3 reference online.

+

Note that some measures, for example AUC, require the prediction of probabilities.

+
+
+

Performance Comparison and Benchmarks

+

We could compare Learners by evaluating resample() for each of them manually. However, benchmark() automatically performs resampling evaluations for multiple learners and tasks. benchmark_grid() creates fully crossed designs: Multiple Learners for multiple Tasks are compared w.r.t. multiple Resamplings.

+
+
learners = lrns(c("classif.log_reg", "classif.ranger"), predict_type = "prob")
+grid = benchmark_grid(
+  tasks = task,
+  learners = learners,
+  resamplings = rsmp("cv", folds = 10)
+)
+bmr = benchmark(grid)
+
+

Careful, large benchmarks may take a long time! This one should take less than a minute, however. In general, we want to use parallelization to speed things up on multi-core machines. For parallelization, mlr3 relies on the future package:

+
+
# future::plan("multicore") # uncomment for parallelization
+
+

In the benchmark we can compare different measures. Here, we look at the misclassification rate and the AUC:

+
+
measures = msrs(c("classif.ce", "classif.auc"))
+performances = bmr$aggregate(measures)
+performances[, c("learner_id", "classif.ce", "classif.auc")]
+
+
        learner_id classif.ce classif.auc
+1: classif.log_reg      0.250   0.7646559
+2:  classif.ranger      0.239   0.7977865
+
+
+

We see that the two models perform very similarly.

+
+
+
+

Deviating from hyperparameters defaults

+

The previously shown techniques build the backbone of a mlr3-featured machine learning workflow. However, in most cases one would never proceed in the way we did. While many R packages have carefully selected default settings, they will not perform optimally in any scenario. Typically, we can select the values of such hyperparameters. The (hyper)parameters of a Learner can be accessed and set via its ParamSet $param_set:

+
+
learner_rf$param_set
+
+
<ParamSet>
+                              id    class lower upper nlevels        default    parents       value
+ 1:                        alpha ParamDbl  -Inf   Inf     Inf            0.5                       
+ 2:       always.split.variables ParamUty    NA    NA     Inf <NoDefault[3]>                       
+ 3:                class.weights ParamUty    NA    NA     Inf                                      
+ 4:                      holdout ParamLgl    NA    NA       2          FALSE                       
+ 5:                   importance ParamFct    NA    NA       4 <NoDefault[3]>            permutation
+ 6:                   keep.inbag ParamLgl    NA    NA       2          FALSE                       
+ 7:                    max.depth ParamInt     0   Inf     Inf                                      
+ 8:                min.node.size ParamInt     1   Inf     Inf                                      
+ 9:                     min.prop ParamDbl  -Inf   Inf     Inf            0.1                       
+10:                      minprop ParamDbl  -Inf   Inf     Inf            0.1                       
+11:                         mtry ParamInt     1   Inf     Inf <NoDefault[3]>                       
+12:                   mtry.ratio ParamDbl     0     1     Inf <NoDefault[3]>                       
+13:            num.random.splits ParamInt     1   Inf     Inf              1  splitrule            
+14:                  num.threads ParamInt     1   Inf     Inf              1                      1
+15:                    num.trees ParamInt     1   Inf     Inf            500                       
+16:                    oob.error ParamLgl    NA    NA       2           TRUE                       
+17:        regularization.factor ParamUty    NA    NA     Inf              1                       
+18:      regularization.usedepth ParamLgl    NA    NA       2          FALSE                       
+19:                      replace ParamLgl    NA    NA       2           TRUE                       
+20:    respect.unordered.factors ParamFct    NA    NA       3         ignore                       
+21:              sample.fraction ParamDbl     0     1     Inf <NoDefault[3]>                       
+22:                  save.memory ParamLgl    NA    NA       2          FALSE                       
+23: scale.permutation.importance ParamLgl    NA    NA       2          FALSE importance            
+24:                    se.method ParamFct    NA    NA       2        infjack                       
+25:                         seed ParamInt  -Inf   Inf     Inf                                      
+26:         split.select.weights ParamUty    NA    NA     Inf                                      
+27:                    splitrule ParamFct    NA    NA       3           gini                       
+28:                      verbose ParamLgl    NA    NA       2           TRUE                       
+29:                 write.forest ParamLgl    NA    NA       2           TRUE                       
+                              id    class lower upper nlevels        default    parents       value
+
+
learner_rf$param_set$values = list(verbose = FALSE)
+
+

We can choose parameters for our learners in two distinct manners. If we have prior knowledge on how the learner should be (hyper-)parameterized, the way to go would be manually entering the parameters in the parameter set. In most cases, however, we would want to tune the learner so that it can search “good” model configurations itself. For now, we only want to compare a few models.

+

To get an idea on which parameters can be manipulated, we can investigate the parameters of the original package version or look into the parameter set of the learner:

+
+
## ?ranger::ranger
+as.data.table(learner_rf$param_set)[, .(id, class, lower, upper)]
+
+
                              id    class lower upper
+ 1:                        alpha ParamDbl  -Inf   Inf
+ 2:       always.split.variables ParamUty    NA    NA
+ 3:                class.weights ParamUty    NA    NA
+ 4:                      holdout ParamLgl    NA    NA
+ 5:                   importance ParamFct    NA    NA
+ 6:                   keep.inbag ParamLgl    NA    NA
+ 7:                    max.depth ParamInt     0   Inf
+ 8:                min.node.size ParamInt     1   Inf
+ 9:                     min.prop ParamDbl  -Inf   Inf
+10:                      minprop ParamDbl  -Inf   Inf
+11:                         mtry ParamInt     1   Inf
+12:                   mtry.ratio ParamDbl     0     1
+13:            num.random.splits ParamInt     1   Inf
+14:                  num.threads ParamInt     1   Inf
+15:                    num.trees ParamInt     1   Inf
+16:                    oob.error ParamLgl    NA    NA
+17:        regularization.factor ParamUty    NA    NA
+18:      regularization.usedepth ParamLgl    NA    NA
+19:                      replace ParamLgl    NA    NA
+20:    respect.unordered.factors ParamFct    NA    NA
+21:              sample.fraction ParamDbl     0     1
+22:                  save.memory ParamLgl    NA    NA
+23: scale.permutation.importance ParamLgl    NA    NA
+24:                    se.method ParamFct    NA    NA
+25:                         seed ParamInt  -Inf   Inf
+26:         split.select.weights ParamUty    NA    NA
+27:                    splitrule ParamFct    NA    NA
+28:                      verbose ParamLgl    NA    NA
+29:                 write.forest ParamLgl    NA    NA
+                              id    class lower upper
+
+
+

For the random forest two meaningful parameters which steer model complexity are num.trees and mtry. num.trees defaults to 500 and mtry to floor(sqrt(ncol(data) - 1)), in our case 4.

+

In the following we aim to train three different learners:

+
    +
  1. The default random forest.
  2. +
  3. A random forest with low num.trees and low mtry.
  4. +
  5. A random forest with high num.trees and high mtry.
  6. +
+

We will benchmark their performance on the German credit dataset. For this we construct the three learners and set the parameters accordingly:

+
+
rf_med = lrn("classif.ranger", id = "med", predict_type = "prob")
+
+rf_low = lrn("classif.ranger", id = "low", predict_type = "prob",
+  num.trees = 5, mtry = 2)
+
+rf_high = lrn("classif.ranger", id = "high", predict_type = "prob",
+  num.trees = 1000, mtry = 11)
+
+

Once the learners are defined, we can benchmark them:

+
+
learners = list(rf_low, rf_med, rf_high)
+grid = benchmark_grid(
+  tasks = task,
+  learners = learners,
+  resamplings = rsmp("cv", folds = 10)
+)
+
+
+
bmr = benchmark(grid)
+print(bmr)
+
+
<BenchmarkResult> of 30 rows with 3 resampling runs
+ nr      task_id learner_id resampling_id iters warnings errors
+  1 GermanCredit        low            cv    10        0      0
+  2 GermanCredit        med            cv    10        0      0
+  3 GermanCredit       high            cv    10        0      0
+
+
+

We compare misclassification rate and AUC again:

+
+
measures = msrs(c("classif.ce", "classif.auc"))
+performances = bmr$aggregate(measures)
+performances[, .(learner_id, classif.ce, classif.auc)]
+
+
   learner_id classif.ce classif.auc
+1:        low      0.278   0.7287261
+2:        med      0.240   0.7973700
+3:       high      0.233   0.7891017
+
+
autoplot(bmr)
+
+
+
+

+
+
+
+
+

The “low” settings seem to underfit a bit, the “high” setting is comparable to the default setting “med”.

+
+
+

Outlook

+

This tutorial was a detailed introduction to machine learning workflows within mlr3. Having followed this tutorial you should be able to run your first models yourself. Next to that we spiked into performance evaluation and benchmarking. Furthermore, we showed how to customize learners.

+

The next parts of the tutorial will go more into depth into additional mlr3 topics:

+ + + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/basic/2020-03-11-basics-german-credit/index_files/figure-html/2020-03-11-basics-german-credit-016-1.png b/gallery/basic/2020-03-11-basics-german-credit/index_files/figure-html/2020-03-11-basics-german-credit-016-1.png new file mode 100644 index 00000000..4cb9d04a Binary files /dev/null and b/gallery/basic/2020-03-11-basics-german-credit/index_files/figure-html/2020-03-11-basics-german-credit-016-1.png differ diff --git a/gallery/basic/2020-03-11-basics-german-credit/index_files/figure-html/2020-03-11-basics-german-credit-038-1.png b/gallery/basic/2020-03-11-basics-german-credit/index_files/figure-html/2020-03-11-basics-german-credit-038-1.png new file mode 100644 index 00000000..8b8949c7 Binary files /dev/null and b/gallery/basic/2020-03-11-basics-german-credit/index_files/figure-html/2020-03-11-basics-german-credit-038-1.png differ diff --git a/gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html b/gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html new file mode 100644 index 00000000..f6296a26 --- /dev/null +++ b/gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html @@ -0,0 +1,1155 @@ + + + + + + + + + + + + + +German Credit Series - Pipelines – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

German Credit Series - Pipelines

+
+
+

Impute missing values, filter features and stack Learners.

+
+
+
+
+ + +
+ +
+
Authors
+
+

Martin Binder

+

Florian Pfisterer

+
+
+ +
+
Published
+
+

March 11, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Outline

+

This is the third part of a serial of use cases with the German credit dataset. The other parts of this series can be found here:

+ +

In this tutorial, we continue working with the German credit dataset. We already used different Learners on it and tried to optimize their hyperparameters. Now we will do four additional things:

+
    +
  1. We preprocess the data as an integrated step of the model fitting process
  2. +
  3. We tune the associated preprocessing parameters
  4. +
  5. We stack multiple Learners in an ensemble model
  6. +
  7. We discuss some techniques that make Learners able to tackle challenging datasets that they could not handle otherwise (we are going to outline what challenging means in particular later on)
  8. +
+
+
+

Prerequisites

+

First, load the packages we are going to use:

+
+
library("mlr3verse")
+library("data.table")
+library("ggplot2")
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+

We again use the German credit dataset, but will restrict ourselves to the factorial features. To make things interesting or to make it a bit harder for our Learners, we introduce missing values in the dataset:

+
+
task = tsk("german_credit")
+credit_full = task$data()
+credit = credit_full[, sapply(credit_full, FUN = is.factor), with = FALSE]
+
+# sample values to NA
+credit = credit[, lapply(.SD, function(x) {
+  x[sample(c(TRUE, NA), length(x), replace = TRUE, prob = c(.9, .1))]
+})]
+credit$credit_risk = credit_full$credit_risk
+task = TaskClassif$new("GermanCredit", credit, "credit_risk")
+
+

We instantiate a Resampling instance for this Task to be able to compare resampling performance:

+
+
cv10 = rsmp("cv")$instantiate(task)
+
+

We also might want to use multiple cores to reduce long run times of tuning runs.

+
+
future::plan("multiprocess")
+
+
+
+

Intro

+

In this use case, we will take a look at composite machine learning algorithms that may incorporate data preprocessing or the combination of multiple Learners (“ensemble methods”).

+

We use the mlr3pipelines package that enables us to chain PipeOps into data flow Graphs.

+

Available PipeOps are listed in the mlr_pipeops dictionary:

+
+
mlr_pipeops
+
+
<DictionaryPipeOp> with 64 stored values
+Keys: boxcox, branch, chunk, classbalancing, classifavg, classweights, colapply, collapsefactors, colroles,
+  copy, datefeatures, encode, encodeimpact, encodelmer, featureunion, filter, fixfactors, histbin, ica,
+  imputeconstant, imputehist, imputelearner, imputemean, imputemedian, imputemode, imputeoor, imputesample,
+  kernelpca, learner, learner_cv, missind, modelmatrix, multiplicityexply, multiplicityimply, mutate, nmf,
+  nop, ovrsplit, ovrunite, pca, proxy, quantilebin, randomprojection, randomresponse, regravg,
+  removeconstants, renamecolumns, replicate, scale, scalemaxabs, scalerange, select, smote, spatialsign,
+  subsample, targetinvert, targetmutate, targettrafoscalerange, textvectorizer, threshold, tunethreshold,
+  unbranch, vtreat, yeojohnson
+
+
+
+
+

Missing Value Imputation

+

We have just introduced missing values into our data. While some Learners can deal with missing value, many cannot. Trying to train a random forest fails because of this:

+
+
ranger = lrn("classif.ranger")
+ranger$train(task)
+
+
Error: Task 'GermanCredit' has missing values in column(s) 'credit_history', 'employment_duration', 'foreign_worker', 'housing', 'installment_rate', 'job', 'number_credits', 'other_debtors', 'other_installment_plans', 'people_liable', 'personal_status_sex', 'present_residence', 'property', 'purpose', 'savings', 'status', 'telephone', but learner 'classif.ranger' does not support this
+
+
+

We can perform imputation of missing values using a PipeOp. To find out which imputation PipeOps are available, we do the following:

+
+
mlr_pipeops$keys("^impute")
+
+
[1] "imputeconstant" "imputehist"     "imputelearner"  "imputemean"     "imputemedian"   "imputemode"    
+[7] "imputeoor"      "imputesample"  
+
+
+

We choose to impute factorial features using a new level (via PipeOpImputeOOR). Let’s use the PipeOp itself to create an imputed Task. This shows us how the PipeOp actually works:

+
+
imputer = po("imputeoor")
+task_imputed = imputer$train(list(task))[[1]]
+task_imputed$missings()
+head(task_imputed$data())
+
+
+
+
+ +
+
+

We do not only need complete data during training but also during prediction. Using the same imputation heuristic for both is the most consistent strategy. This way the imputation strategy can, in fact, be seen as a part of the complete learner (which could be tuned).

+

If we used the imputed Task for Resampling, we would leak information from the test set into the training set. Therefore, it is mandatory to attach the imputation operator to the Learner itself, creating a GraphLearner:

+
+
graph_learner_ranger = as_learner(po("imputeoor") %>>% ranger)
+
+graph_learner_ranger$train(task)
+
+

This GraphLearner can be used for resampling – like an ordinary Learner:

+
+
rr = resample(task, learner = graph_learner_ranger, resampling = cv10)
+rr$aggregate()
+
+
classif.ce 
+     0.287 
+
+
+
+
+

Feature Filtering

+

Typically, sparse models, i.e. having models with few(er) features, are desirable. This is due to a variety of reasons, e.g., enhanced interpretability or decreased costs of acquiring data. Furthermore, sparse models may actually be associated with increased performance (especially if overfitting is anticipated). We can use feature filter to only keep features with the highest information. Filters are implemented in the mlr3filters package and listed in the following dictionary:

+
+
mlr_filters
+
+
<DictionaryFilter> with 21 stored values
+Keys: anova, auc, carscore, carsurvscore, cmim, correlation, disr, find_correlation, importance,
+  information_gain, jmi, jmim, kruskal_test, mim, mrmr, njmim, performance, permutation, relief,
+  selected_features, variance
+
+
+

We apply the FilterMIM (mutual information maximization) Filter as implemented in the praznik package. This Filter allows for the selection of the top-k features of best mutual information.

+
+
filter = flt("mim")
+filter$calculate(task_imputed)$scores
+
+
                 status          credit_history                 savings                 purpose                property 
+                 1.0000                  0.9375                  0.8750                  0.8125                  0.7500 
+                housing     employment_duration other_installment_plans     personal_status_sex           other_debtors 
+                 0.6875                  0.6250                  0.5625                  0.5000                  0.4375 
+       installment_rate          foreign_worker                     job          number_credits               telephone 
+                 0.3750                  0.3125                  0.2500                  0.1875                  0.1250 
+      present_residence           people_liable 
+                 0.0625                  0.0000 
+
+
+

Making use of this Filter, you may wonder at which costs the reduction of the feature space comes. We can investigate the trade-off between features and performance by tuning. We incorporate our filtering strategy into the pipeline using PipeOpFilter. Like before, we need to perform imputation as the Filter also relies on complete data:

+
+
fpipe = po("imputeoor") %>>% po("filter", flt("mim"), filter.nfeat = 3)
+fpipe$train(task)[[1]]$head()
+
+
   credit_risk                              credit_history                    savings
+1:        good     all credits at this bank paid back duly             ... >= 1000 DM
+2:         bad no credits taken/all credits paid back duly unknown/no savings account
+3:        good     all credits at this bank paid back duly unknown/no savings account
+4:        good no credits taken/all credits paid back duly unknown/no savings account
+5:         bad    existing credits paid back duly till now unknown/no savings account
+6:        good                                    .MISSING             ... >= 1000 DM
+                                       status
+1:                        no checking account
+2:                                 ... < 0 DM
+3: ... >= 200 DM / salary for at least 1 year
+4:                        no checking account
+5:                        no checking account
+6: ... >= 200 DM / salary for at least 1 year
+
+
+

We can now tune over the mim.filter.nfeat parameter. It steers how many features are kept by the Filter and eventually used by the learner:

+
+
search_space = ps(
+  mim.filter.nfeat = p_int(lower = 1, upper = length(task$feature_names))
+)
+
+

The problem is one-dimensional (i.e. only one parameter is tuned). Thus, we make use of a grid search. For higher dimensions, strategies like random search are more appropriate. The tuning procedure may take some time:

+
+
instance = tune(
+  tuner = tnr("grid_search"),
+  task,
+  learner = fpipe %>>% lrn("classif.ranger"),
+  resampling = cv10,
+  measure = msr("classif.ce"),
+  search_space = search_space)
+
+

We can plot the performance against the number of features. If we do so, we see the possible trade-off between sparsity and predictive performance:

+
+
autoplot(instance, type =  "marginal")
+
+
+
+

+
+
+
+
+
+
+

Stacking

+

We want to build a model that is based on the predictions of other Learners. This means that we are in the state that we need predictions already during training. This is a very specific case that is luckily handled by PipeOpLearnerCV. PipeOpLearnerCV performs cross-validation during the training phase and returns the cross-validated predictions. We use "prob" predictions because they carry more information than response prediction:

+
+
graph_stack = po("imputeoor") %>>%
+  gunion(list(
+    po("learner_cv", lrn("classif.ranger", predict_type = "prob")),
+    po("learner_cv", lrn("classif.kknn", predict_type = "prob")))) %>>%
+  po("featureunion") %>>% lrn("classif.log_reg")
+
+

We built a pretty complex Graph already. Therefore, we plot it:

+
+
graph_stack$plot(html = FALSE)
+
+
+
+

+
+
+
+
+

We now compare the performance of the stacked learner to the performance of the individual Learners:

+
+
grid = benchmark_grid(
+  task = task,
+  learner = list(
+    graph_stack,
+    as_learner(po("imputeoor") %>>% lrn("classif.ranger")),
+    as_learner(po("imputeoor") %>>% lrn("classif.kknn")),
+    as_learner(po("imputeoor") %>>% lrn("classif.log_reg"))),
+  resampling = cv10)
+
+bmr = benchmark(grid)
+
+
+
+
                                                           learner_id classif.ce
+1: imputeoor.classif.ranger.classif.kknn.featureunion.classif.log_reg      0.282
+2:                                           imputeoor.classif.ranger      0.292
+3:                                             imputeoor.classif.kknn      0.299
+4:                                          imputeoor.classif.log_reg      0.283
+
+
+

If we train the stacked learner and look into the final Learner (the logistic regression), we can see how “important” each Learner of the stacked learner is:

+
+
graph_stack$train(task)
+
+
$classif.log_reg.output
+NULL
+
+
summary(graph_stack$pipeops$classif.log_reg$state$model)
+
+

+Call:
+stats::glm(formula = task$formula(), family = "binomial", data = data, 
+    model = FALSE)
+
+Coefficients: (2 not defined because of singularities)
+                         Estimate Std. Error z value Pr(>|z|)    
+(Intercept)               -3.3179     0.3527  -9.406  < 2e-16 ***
+classif.ranger.prob.good   5.4010     0.5648   9.563  < 2e-16 ***
+classif.ranger.prob.bad        NA         NA      NA       NA    
+classif.kknn.prob.good     0.8502     0.3169   2.683  0.00729 ** 
+classif.kknn.prob.bad          NA         NA      NA       NA    
+---
+Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
+
+(Dispersion parameter for binomial family taken to be 1)
+
+    Null deviance: 1221.7  on 999  degrees of freedom
+Residual deviance: 1054.1  on 997  degrees of freedom
+AIC: 1060.1
+
+Number of Fisher Scoring iterations: 4
+
+
+

The random forest has a higher contribution.

+
+
+

Robustify: Preventing new Prediction Factor Levels and other Problems

+

We now shift the context, using the complete German credit dataset:

+
+
task = tsk("german_credit")
+
+

There is a potential practical problem for both, small data sets and data sets with covariates having many factor levels: It may occur that not all possible factor levels have been used by the Learner during training. This happens because these rare instances are simply not sampled. The prediction then may fail because the Learner does not know how to handle unseen factor levels:

+
+
task_unseen = task$clone()$filter(1:30)
+learner_logreg = lrn("classif.log_reg")
+learner_logreg$train(task_unseen)
+learner_logreg$predict(task)
+
+
Error in model.frame.default(Terms, newdata, na.action = na.action, xlev = object$xlevels): factor job has new levels unemployed/unskilled - non-resident
+
+
+

Not only logistic regression but also many other Learners cannot handle new levels during prediction. Thus, we use PipeOpFixFactors to prevent that. PipeOpFixFactors introduces NA values for unseen levels. This means that we may need to impute afterwards. To solve this issue we can use PipeOpImputeSample, but with affect_columns set to only factorial features.

+

Another observation is that all-constant features may also be a problem:

+
+
task_constant = task$clone()$filter(1:2)
+learner_logreg = lrn("classif.log_reg")
+learner_logreg$train(task_constant)
+
+
Error in `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]): contrasts can be applied only to factors with 2 or more levels
+
+
+

This can be fixed using PipeOpRemoveConstants.

+

Both, handling unseen levels and all-constant features can be handled simultaneously using the following Graph:

+
+
robustify = po("fixfactors") %>>%
+  po("removeconstants") %>>%
+  po("imputesample", affect_columns = selector_type(c("ordered", "factor")))
+
+robustify$plot(html = FALSE)
+
+
+
+

+
+
+
+
+

This robust learner works even in very pathological conditions:

+
+
graph_learner_robustify = as_learner(robustify %>>% learner_logreg)
+
+graph_learner_robustify$train(task_constant)
+graph_learner_robustify$predict(task)
+
+
<PredictionClassif> for 1000 observations:
+    row_ids truth response
+          1  good     good
+          2   bad      bad
+          3  good     good
+---                       
+        998  good      bad
+        999   bad      bad
+       1000  good      bad
+
+
+
+
+

Your Ideas

+

There are various possibilities for preprocessing with PipeOps. You can try different methods for preprocessing and training. Feel free to discover this variety by yourself! Here are only a few hints that help when working with PipeOps:

+
    +
  • It is not allowed to have two PipeOps with the same ID in a Graph +
      +
    • Initialize a PipeOp with po("...", id = "xyz") to change its ID on construction
    • +
  • +
  • If you build large Graphs involving complicated optimizations, like many "learner_cv", they may need a long time to train
  • +
  • Use the affect_columns parameter if you want a PipeOp to only operate on part of the data
  • +
  • Use po("select") if you want to remove certain columns (possibly only along a single branch of multiple parallel branches). Both take selector_xxx() arguments, e.g. selector_type("integer")
  • +
  • You may get the best performance if you actually inspect the features and see what kind of transformations work best for them (know your data!)
  • +
  • See what PipeOps are available by inspecting mlr_pipeops$keys(), and get help about them using ?mlr_pipeops_xxx
  • +
+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3pipelines-tutorial-german-credit-018-1.png b/gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3pipelines-tutorial-german-credit-018-1.png new file mode 100644 index 00000000..de7ed8c4 Binary files /dev/null and b/gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3pipelines-tutorial-german-credit-018-1.png differ diff --git a/gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3pipelines-tutorial-german-credit-020-1.png b/gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3pipelines-tutorial-german-credit-020-1.png new file mode 100644 index 00000000..1edb2b47 Binary files /dev/null and b/gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3pipelines-tutorial-german-credit-020-1.png differ diff --git a/gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3pipelines-tutorial-german-credit-027-1.png b/gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3pipelines-tutorial-german-credit-027-1.png new file mode 100644 index 00000000..60e495ab Binary files /dev/null and b/gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3pipelines-tutorial-german-credit-027-1.png differ diff --git a/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index.html b/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index.html new file mode 100644 index 00000000..81a3482a --- /dev/null +++ b/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index.html @@ -0,0 +1,1264 @@ + + + + + + + + + + + + + +German Credit Series - Tuning – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

German Credit Series - Tuning

+
+
+

Optimize Hyperparameters and apply nested resampling.

+
+
+
+
+ + +
+ +
+
Authors
+
+

Martin Binder

+

Florian Pfisterer

+
+
+ +
+
Published
+
+

March 11, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Intro

+

This is the second part of a serial of tutorials. The other parts of this series can be found here:

+ +

We will continue working with the German credit dataset. In Part I, we peeked into the dataset by using and comparing some learners with their default parameters. We will now see how to:

+
    +
  • Tune hyperparameters for a given problem
  • +
  • Perform nested resampling
  • +
+
+
+

Prerequisites

+

First, load the packages we are going to use:

+
+
library("mlr3verse")
+library("data.table")
+library("mlr3tuning")
+library("ggplot2")
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+

We use the same Task as in Part I:

+
+
task = tsk("german_credit")
+
+

We also might want to use multiple cores to reduce long run times of tuning runs.

+
+
future::plan("multiprocess")
+
+
+

Evaluation

+

We will evaluate all hyperparameter configurations using 10-fold cross-validation. We use a fixed train-test split, i.e. the same splits for each evaluation. Otherwise, some evaluation could get unusually “hard” splits, which would make comparisons unfair.

+
+
cv10 = rsmp("cv", folds = 10)
+
+# fix the train-test splits using the $instantiate() method
+cv10$instantiate(task)
+
+# have a look at the test set instances per fold
+cv10$instance
+
+
      row_id fold
+   1:     18    1
+   2:     19    1
+   3:     35    1
+   4:     38    1
+   5:     55    1
+  ---            
+ 996:    973   10
+ 997:    975   10
+ 998:    981   10
+ 999:    993   10
+1000:    998   10
+
+
+
+
+
+

Simple Parameter Tuning

+

Parameter tuning in mlr3 needs two packages:

+
    +
  1. The paradox package is used for the search space definition of the hyperparameters.
  2. +
  3. The mlr3tuning package is used for tuning the hyperparameters.
  4. +
+

The packages are loaded by the mlr3verse package.

+
+

Search Space and Problem Definition

+

First, we need to decide what Learner we want to optimize. We will use LearnerClassifKKNN, the “kernelized” k-nearest neighbor classifier. We will use kknn as a normal kNN without weighting first (i.e., using the rectangular kernel):

+
+
knn = lrn("classif.kknn", predict_type = "prob", kernel = "rectangular")
+
+

As a next step, we decide what parameters we optimize over. Before that, though, we are interested in the parameter set on which we could tune:

+
+
knn$param_set
+
+
+
+
            id    class lower upper nlevels
+1:           k ParamInt     1   Inf     Inf
+2:    distance ParamDbl     0   Inf     Inf
+3:      kernel ParamFct    NA    NA      10
+4:       scale ParamLgl    NA    NA       2
+5:     ykernel ParamUty    NA    NA     Inf
+6: store_model ParamLgl    NA    NA       2
+
+
+

We first tune the k parameter (i.e. the number of nearest neighbors), between 3 to 20. Second, we tune the distance function, allowing L1 and L2 distances. To do so, we use the paradox package to define a search space (see the online vignette for a more complete introduction.

+
+
search_space = ps(
+  k = p_int(3, 20),
+  distance = p_int(1, 2)
+)
+
+

As a next step, we define a TuningInstanceSingleCrit that represents the problem we are trying to optimize.

+
+
instance_grid = TuningInstanceSingleCrit$new(
+  task = task,
+  learner = knn,
+  resampling = cv10,
+  measure = msr("classif.ce"),
+  terminator = trm("none"),
+  search_space = search_space
+)
+
+
+ +
+

Random Search and Transformation

+

Let’s have a look at a larger search space. For example, we could tune all available parameters and limit k to large values (50). We also now tune the distance param continuously from 1 to 3 as a double and tune distance kernel and whether we scale the features.

+

We may find two problems when doing so:

+

First, the resulting difference in performance between k = 3 and k = 4 is probably larger than the difference between k = 49 and k = 50. While 4 is 33% larger than 3, 50 is only 2 percent larger than 49. To account for this we will use a transformation function for k and optimize in log-space. We define the range for k from log(3) to log(50) and exponentiate in the transformation. Now, as k has become a double instead of an int (in the search space, before transformation), we round it in the extra_trafo.

+
+
search_space_large = ps(
+  k = p_dbl(log(3), log(50)),
+  distance = p_dbl(1, 3),
+  kernel = p_fct(c("rectangular", "gaussian", "rank", "optimal")),
+  scale = p_lgl(),
+  .extra_trafo = function(x, param_set) {
+    x$k = round(exp(x$k))
+    x
+  }
+)
+
+

The second problem is that grid search may (and often will) take a long time. For instance, trying out three different values for k, distance, kernel, and the two values for scale will take 54 evaluations. Because of this, we use a different search algorithm, namely the Random Search. We need to specify in the tuning instance a termination criterion. The criterion tells the search algorithm when to stop. Here, we will terminate after 36 evaluations:

+
+
tuner_random = tnr("random_search", batch_size = 36)
+
+instance_random = TuningInstanceSingleCrit$new(
+  task = task,
+  learner = knn,
+  resampling = cv10,
+  measure = msr("classif.ce"),
+  terminator = trm("evals", n_evals = 36),
+  search_space = search_space_large
+)
+
+
+
tuner_random$optimize(instance_random)
+
+
          k distance   kernel scale learner_param_vals  x_domain classif.ce
+1: 1.683743 1.985146 gaussian  TRUE          <list[4]> <list[4]>      0.254
+
+
+

Like before, we can review the Archive. It includes the points before and after the transformation. The archive includes a column for each parameter the Tuner sampled on the search space (values before the transformation) and additional columns with prefix x_domain_* that refer to the parameters used by the learner (values after the transformation):

+
+
as.data.table(instance_random$archive)
+
+
+
+
+ +
+
+

Let’s now investigate the performance by parameters. This is especially easy using visualization:

+
+
ggplot(as.data.table(instance_random$archive),
+  aes(x = x_domain_k, y = classif.ce, color = x_domain_scale)) +
+  geom_point(size = 3) + geom_line()
+
+
+
+

+
+
+
+
+

The previous plot suggests that scale has a strong influence on performance. For the kernel, there does not seem to be a strong influence:

+
+
ggplot(as.data.table(instance_random$archive),
+  aes(x = x_domain_k, y = classif.ce, color = x_domain_kernel)) +
+  geom_point(size = 3) + geom_line()
+
+
+
+

+
+
+
+
+
+
+
+

Nested Resampling

+

Having determined tuned configurations that seem to work well, we want to find out which performance we can expect from them. However, this may require more than this naive approach:

+
+
instance_random$result_y
+
+
classif.ce 
+     0.254 
+
+
instance_grid$result_y
+
+
classif.ce 
+      0.25 
+
+
+

The problem associated with evaluating tuned models is overtuning. The more we search, the more optimistically biased the associated performance metrics from tuning become.

+

There is a solution to this problem, namely Nested Resampling.

+

The mlr3tuning package provides an AutoTuner that acts like our tuning method but is actually a Learner. The $train() method facilitates tuning of hyperparameters on the training data, using a resampling strategy (below we use 5-fold cross-validation). Then, we actually train a model with optimal hyperparameters on the whole training data.

+

The AutoTuner finds the best parameters and uses them for training:

+
+
at_grid = AutoTuner$new(
+  learner = knn,
+  resampling = rsmp("cv", folds = 5), # we can NOT use fixed resampling here
+  measure = msr("classif.ce"),
+  terminator = trm("none"),
+  tuner = tnr("grid_search", resolution = 18),
+  search_space = search_space
+)
+
+

The AutoTuner behaves just like a regular Learner. It can be used to combine the steps of hyperparameter tuning and model fitting but is especially useful for resampling and fair comparison of performance through benchmarking:

+
+
rr = resample(task, at_grid, cv10, store_models = TRUE)
+
+

We check the inner tuning results for stable hyperparameters. This means that the selected hyperparameters should not vary too much. We might observe unstable models in this example because the small data set and the low number of resampling iterations might introduce too much randomness. Usually, we aim for the selection of stable hyperparameters for all outer training sets.

+
+
extract_inner_tuning_results(rr)
+
+
+
+
    iteration  k distance classif.ce       task_id         learner_id resampling_id
+ 1:         1  7        1  0.2588889 german_credit classif.kknn.tuned            cv
+ 2:         2  5        2  0.2377778 german_credit classif.kknn.tuned            cv
+ 3:         3 10        2  0.2500000 german_credit classif.kknn.tuned            cv
+ 4:         4  9        2  0.2488889 german_credit classif.kknn.tuned            cv
+ 5:         5  7        2  0.2477778 german_credit classif.kknn.tuned            cv
+ 6:         6  8        2  0.2411111 german_credit classif.kknn.tuned            cv
+ 7:         7  8        2  0.2688889 german_credit classif.kknn.tuned            cv
+ 8:         8  7        2  0.2477778 german_credit classif.kknn.tuned            cv
+ 9:         9  7        2  0.2655556 german_credit classif.kknn.tuned            cv
+10:        10  7        2  0.2455556 german_credit classif.kknn.tuned            cv
+
+
+

Next, we want to compare the predictive performances estimated on the outer resampling to the inner resampling (extract_inner_tuning_results(rr)). Significantly lower predictive performances on the outer resampling indicate that the models with the optimized hyperparameters overfit the data.

+
+
rr$score()
+
+
+
+
+ +
+
+

The archives of the AutoTuners allows us to inspect all evaluated hyperparameters configurations with the associated predictive performances.

+
+
extract_inner_tuning_archives(rr)
+
+
+
+
+ +
+
+

We aggregate the performances of all resampling iterations:

+
+
rr$aggregate()
+
+
classif.ce 
+     0.255 
+
+
+

Essentially, this is the performance of a “knn with optimal hyperparameters found by grid search”. Note that at_grid is not changed since resample() creates a clone for each resampling iteration.

+

The trained AutoTuner objects can be accessed by using

+
+
rr$learners[[1]]
+
+
<AutoTuner:classif.kknn.tuned>
+* Model: list
+* Search Space:
+<ParamSet>
+         id    class lower upper nlevels        default value
+1:        k ParamInt     3    20      18 <NoDefault[3]>      
+2: distance ParamInt     1     2       2 <NoDefault[3]>      
+* Packages: mlr3, mlr3tuning, mlr3learners, kknn
+* Predict Type: prob
+* Feature Types: logical, integer, numeric, factor, ordered
+* Properties: multiclass, twoclass
+
+
rr$learners[[1]]$tuning_result
+
+
   k distance learner_param_vals  x_domain classif.ce
+1: 7        1          <list[3]> <list[2]>  0.2588889
+
+
+
+
+

Appendix

+
+

Example: Tuning With A Larger Budget

+

It is always interesting to look at what could have been. The following dataset contains an optimization run result with 3600 evaluations – more than above by a factor of 100:

+
+
+
+ +
+
+

The scale effect is just as visible as before with fewer data:

+
+
ggplot(perfdata, aes(x = x_domain_k, y = classif.ce, color = scale)) +
+  geom_point(size = 2, alpha = 0.3)
+
+
+
+

+
+
+
+
+

Now, there seems to be a visible pattern by kernel as well:

+
+
ggplot(perfdata, aes(x = x_domain_k, y = classif.ce, color = kernel)) +
+  geom_point(size = 2, alpha = 0.3)
+
+
+
+

+
+
+
+
+

In fact, if we zoom in to (5, 40) \(\times\) (0.23, 0.28) and do decrease smoothing we see that different kernels have their optimum at different values of k:

+
+
ggplot(perfdata, aes(x = x_domain_k, y = classif.ce, color = kernel,
+  group = interaction(kernel, scale))) +
+  geom_point(size = 2, alpha = 0.3) + geom_smooth() +
+  xlim(5, 40) + ylim(0.23, 0.28)
+
+
`geom_smooth()` using method = 'loess' and formula = 'y ~ x'
+
+
+
+
+

+
+
+
+
+

What about the distance parameter? If we select all results with k between 10 and 20 and plot distance and kernel we see an approximate relationship:

+
+
ggplot(perfdata[x_domain_k > 10 & x_domain_k < 20 & scale == TRUE],
+  aes(x = distance, y = classif.ce, color = kernel)) +
+  geom_point(size = 2) + geom_smooth()
+
+
`geom_smooth()` using method = 'loess' and formula = 'y ~ x'
+
+
+
+
+

+
+
+
+
+

In sum our observations are: The scale parameter is very influential, and scaling is beneficial. The distance type seems to be the least influential. There seems to be an interaction between ‘k’ and ‘kernel’.

+ + +
+
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-018-1.png b/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-018-1.png new file mode 100644 index 00000000..517d261c Binary files /dev/null and b/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-018-1.png differ diff --git a/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-024-1.png b/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-024-1.png new file mode 100644 index 00000000..af583d42 Binary files /dev/null and b/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-024-1.png differ diff --git a/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-025-1.png b/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-025-1.png new file mode 100644 index 00000000..7eed7651 Binary files /dev/null and b/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-025-1.png differ diff --git a/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-039-1.png b/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-039-1.png new file mode 100644 index 00000000..fb7abac5 Binary files /dev/null and b/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-039-1.png differ diff --git a/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-040-1.png b/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-040-1.png new file mode 100644 index 00000000..f72823fd Binary files /dev/null and b/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-040-1.png differ diff --git a/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-041-1.png b/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-041-1.png new file mode 100644 index 00000000..8eb61025 Binary files /dev/null and b/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-041-1.png differ diff --git a/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-042-1.png b/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-042-1.png new file mode 100644 index 00000000..57995057 Binary files /dev/null and b/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index_files/figure-html/2020-03-11-mlr3tuning-tutorial-german-credit-042-1.png differ diff --git a/gallery/basic/2020-03-18-iris-mlr3-basics/index.html b/gallery/basic/2020-03-18-iris-mlr3-basics/index.html new file mode 100644 index 00000000..297fbef5 --- /dev/null +++ b/gallery/basic/2020-03-18-iris-mlr3-basics/index.html @@ -0,0 +1,1083 @@ + + + + + + + + + + + + +mlr3 Basics on “Iris” - Hello World! – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

mlr3 Basics on “Iris” - Hello World!

+
+
+

Learn the basic operations train, predict, score, resample, and benchmark.

+
+
+
+
+ + +
+ +
+
Author
+
+

Bernd Bischl

+
+
+ +
+
Published
+
+

March 18, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Goals and Prerequisites

+

This use case shows how to use the basic mlr3 package on the iris Task, so it’s our “Hello World” example. It assumes no prior knowledge in ML or mlr3. You can find most of the content here also in the mlr3book in a more detailed way. Hence we will not make a lot of general comments, but keep it hands-on and short.

+

The following operations are shown:

+ +
+
+

Loading basic packages

+

We load the mlr3verse package which pulls in the most important packages for this example. The mlr3learners package loads additional learners.

+
+
library(mlr3verse)
+library(mlr3learners)
+
+lgr::get_logger("mlr3")$set_threshold("warn")
+
+
+
+

Creating tasks and learners

+

Let’s work on the canonical, simple iris data set, and try out some ML algorithms. We will start by using a decision tree with default settings.

+
+
# creates mlr3 task from scratch, from a data.frame
+# 'target' names the column in the dataset we want to learn to predict
+task = as_task_classif(iris, target = "Species")
+# in this case we could also take the iris example from mlr3's dictionary of shipped example tasks
+# 2 equivalent calls to create a task. The second is just sugar for the user.
+task = mlr_tasks$get("iris")
+task = tsk("iris")
+print(task)
+
+
<TaskClassif:iris> (150 x 5): Iris Flowers
+* Target: Species
+* Properties: multiclass
+* Features (4):
+  - dbl (4): Petal.Length, Petal.Width, Sepal.Length, Sepal.Width
+
+
# create learner from dictionary of mlr3learners
+# 2 equivalent calls:
+learner_1 = mlr_learners$get("classif.rpart")
+learner_1 = lrn("classif.rpart")
+print(learner_1)
+
+
<LearnerClassifRpart:classif.rpart>: Classification Tree
+* Model: -
+* Parameters: xval=0
+* Packages: mlr3, rpart
+* Predict Types:  [response], prob
+* Feature Types: logical, integer, numeric, factor, ordered
+* Properties: importance, missings, multiclass, selected_features, twoclass, weights
+
+
+
+
+

Train and predict

+

Now the usual ML operations: Train on some observations, predict on others.

+
+
# train learner on subset of task
+learner_1$train(task, row_ids = 1:120)
+# this is what the decision tree looks like
+print(learner_1$model)
+
+
n= 120 
+
+node), split, n, loss, yval, (yprob)
+      * denotes terminal node
+
+1) root 120 70 setosa (0.41666667 0.41666667 0.16666667)  
+  2) Petal.Length< 2.45 50  0 setosa (1.00000000 0.00000000 0.00000000) *
+  3) Petal.Length>=2.45 70 20 versicolor (0.00000000 0.71428571 0.28571429)  
+    6) Petal.Length< 4.95 49  1 versicolor (0.00000000 0.97959184 0.02040816) *
+    7) Petal.Length>=4.95 21  2 virginica (0.00000000 0.09523810 0.90476190) *
+
+
# predict using observations from task
+prediction = learner_1$predict(task, row_ids = 121:150)
+# predict using "new" observations from an external data.frame
+prediction = learner_1$predict_newdata(newdata = iris[121:150, ])
+print(prediction)
+
+
<PredictionClassif> for 30 observations:
+    row_ids     truth   response
+          1 virginica  virginica
+          2 virginica versicolor
+          3 virginica  virginica
+---                             
+         28 virginica  virginica
+         29 virginica  virginica
+         30 virginica  virginica
+
+
+
+
+

Evaluation

+

Let’s score our Prediction object with some metrics. And take a deeper look by inspecting the confusion matrix.

+
+
head(as.data.table(mlr_measures))
+
+
              key                          label task_type          packages predict_type task_properties
+1:            aic   Akaike Information Criterion      <NA>              mlr3         <NA>                
+2:            bic Bayesian Information Criterion      <NA>              mlr3         <NA>                
+3:    classif.acc        Classification Accuracy   classif mlr3,mlr3measures     response                
+4:    classif.auc       Area Under the ROC Curve   classif mlr3,mlr3measures         prob        twoclass
+5:   classif.bacc              Balanced Accuracy   classif mlr3,mlr3measures     response                
+6: classif.bbrier             Binary Brier Score   classif mlr3,mlr3measures         prob        twoclass
+
+
scores = prediction$score(msr("classif.acc"))
+print(scores)
+
+
classif.acc 
+  0.8333333 
+
+
scores = prediction$score(msrs(c("classif.acc", "classif.ce")))
+print(scores)
+
+
classif.acc  classif.ce 
+  0.8333333   0.1666667 
+
+
cm = prediction$confusion
+print(cm)
+
+
            truth
+response     setosa versicolor virginica
+  setosa          0          0         0
+  versicolor      0          0         5
+  virginica       0          0        25
+
+
+
+
+

Changing hyperpars

+

The Learner contains information about all parameters that can be configured, including data type, constraints, defaults, etc. We can change the hyperparameters either during construction of later through an active binding.

+
+
as.data.table(learner_1$param_set)[, .(id, class, lower, upper, nlevels)]
+
+
                id    class lower upper nlevels
+ 1:             cp ParamDbl     0     1     Inf
+ 2:     keep_model ParamLgl    NA    NA       2
+ 3:     maxcompete ParamInt     0   Inf     Inf
+ 4:       maxdepth ParamInt     1    30      30
+ 5:   maxsurrogate ParamInt     0   Inf     Inf
+ 6:      minbucket ParamInt     1   Inf     Inf
+ 7:       minsplit ParamInt     1   Inf     Inf
+ 8: surrogatestyle ParamInt     0     1       2
+ 9:   usesurrogate ParamInt     0     2       3
+10:           xval ParamInt     0   Inf     Inf
+
+
+
+
learner_2 = lrn("classif.rpart", predict_type = "prob", minsplit = 50)
+learner_2$param_set$values$minsplit = 50
+
+
+
+

Resampling

+

Resampling simply repeats the train-predict-score loop and collects all results in a nice data.table::data.table().

+
+
cv10 = rsmp("cv", folds = 10)
+rr = resample(task, learner_1, cv10)
+print(rr)
+
+
<ResampleResult> with 10 resampling iterations
+ task_id    learner_id resampling_id iteration warnings errors
+    iris classif.rpart            cv         1        0      0
+    iris classif.rpart            cv         2        0      0
+    iris classif.rpart            cv         3        0      0
+    iris classif.rpart            cv         4        0      0
+    iris classif.rpart            cv         5        0      0
+    iris classif.rpart            cv         6        0      0
+    iris classif.rpart            cv         7        0      0
+    iris classif.rpart            cv         8        0      0
+    iris classif.rpart            cv         9        0      0
+    iris classif.rpart            cv        10        0      0
+
+
+
+
rr$score(msrs(c("classif.acc", "classif.ce")))[, .(iteration, task_id, learner_id, resampling_id, classif.ce)]
+
+
    iteration task_id    learner_id resampling_id classif.ce
+ 1:         1    iris classif.rpart            cv 0.06666667
+ 2:         2    iris classif.rpart            cv 0.00000000
+ 3:         3    iris classif.rpart            cv 0.06666667
+ 4:         4    iris classif.rpart            cv 0.06666667
+ 5:         5    iris classif.rpart            cv 0.20000000
+ 6:         6    iris classif.rpart            cv 0.06666667
+ 7:         7    iris classif.rpart            cv 0.06666667
+ 8:         8    iris classif.rpart            cv 0.00000000
+ 9:         9    iris classif.rpart            cv 0.00000000
+10:        10    iris classif.rpart            cv 0.20000000
+
+
+
+
# get all predictions nicely concatenated in a table
+prediction = rr$prediction()
+as.data.table(prediction)
+
+
     row_ids      truth   response
+  1:       5     setosa     setosa
+  2:       7     setosa     setosa
+  3:      26     setosa     setosa
+  4:      34     setosa     setosa
+  5:      55 versicolor versicolor
+ ---                              
+146:     100 versicolor versicolor
+147:     113  virginica  virginica
+148:     124  virginica  virginica
+149:     136  virginica  virginica
+150:     139  virginica versicolor
+
+
+
+
cm = prediction$confusion
+print(cm)
+
+
            truth
+response     setosa versicolor virginica
+  setosa         50          0         0
+  versicolor      0         45         6
+  virginica       0          5        44
+
+
+
+
+

Populating the learner dictionary

+

mlr3learners ships out with a dozen different popular Learners. We can list them from the dictionary. If we want more, we can install an extension package, mlr3extralearners, from GitHub. Note how after loading mlr3extralearners the dictionary increases in size.

+
+
head(as.data.table(mlr_learners)[, c("key", "packages")])
+
+
                   key                 packages
+1:   classif.cv_glmnet mlr3,mlr3learners,glmnet
+2:       classif.debug                     mlr3
+3: classif.featureless                     mlr3
+4:      classif.glmnet mlr3,mlr3learners,glmnet
+5:        classif.kknn   mlr3,mlr3learners,kknn
+6:         classif.lda   mlr3,mlr3learners,MASS
+
+
library(mlr3extralearners)
+print(as.data.table(mlr_learners)[, c("key", "packages")])
+
+
                     key                                                packages
+  1:  classif.AdaBoostM1                            mlr3,mlr3extralearners,RWeka
+  2:         classif.C50                              mlr3,mlr3extralearners,C50
+  3:         classif.IBk                            mlr3,mlr3extralearners,RWeka
+  4:         classif.J48                            mlr3,mlr3extralearners,RWeka
+  5:        classif.JRip                            mlr3,mlr3extralearners,RWeka
+ ---                                                                            
+137: surv.priority_lasso                            mlr3,mlr3proba,prioritylasso
+138:         surv.ranger                 mlr3,mlr3proba,mlr3extralearners,ranger
+139:          surv.rfsrc mlr3,mlr3proba,mlr3extralearners,randomForestSRC,pracma
+140:            surv.svm            mlr3,mlr3proba,mlr3extralearners,survivalsvm
+141:        surv.xgboost                mlr3,mlr3proba,mlr3extralearners,xgboost
+
+
+
+
+

Benchmarking multiple learners

+

The benchmark function can conveniently compare `r ref(“Learner”, “Learners”) on the same dataset(s).

+
+
learners = list(learner_1, learner_2, lrn("classif.randomForest"))
+grid = benchmark_grid(task, learners, cv10)
+bmr = benchmark(grid)
+print(bmr)
+
+
<BenchmarkResult> of 30 rows with 3 resampling runs
+ nr task_id           learner_id resampling_id iters warnings errors
+  1    iris        classif.rpart            cv    10        0      0
+  2    iris        classif.rpart            cv    10        0      0
+  3    iris classif.randomForest            cv    10        0      0
+
+
print(bmr$aggregate(measures = msrs(c("classif.acc", "classif.ce"))))
+
+
   nr task_id           learner_id resampling_id iters classif.acc classif.ce
+1:  1    iris        classif.rpart            cv    10   0.9266667 0.07333333
+2:  2    iris        classif.rpart            cv    10   0.9266667 0.07333333
+3:  3    iris classif.randomForest            cv    10   0.9533333 0.04666667
+Hidden columns: resample_result
+
+
+
+
+

Conclusion

+

We left out a lot of details and other features. If you want to know more, read the mlr3book and the documentation of the mentioned packages.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/basic/2020-03-30-imbalanced-data/index.html b/gallery/basic/2020-03-30-imbalanced-data/index.html new file mode 100644 index 00000000..fe572945 --- /dev/null +++ b/gallery/basic/2020-03-30-imbalanced-data/index.html @@ -0,0 +1,2028 @@ + + + + + + + + + + + + +Imbalanced Data Handling with mlr3 – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Imbalanced Data Handling with mlr3

+
+
+

Handle imbalanced data with oversampling, undersampling, and SMOTE imbalance correction.

+
+
+
+
+ + +
+ +
+
Author
+
+

Giuseppe Casalicchio

+
+
+ +
+
Published
+
+

March 30, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Intro

+

This use case compares different approaches to handle class imbalance for the Optical Recognition of Handwritten Digits (optdigits) binary classification data set using the mlr3 package. We mainly focus on undersampling the majority class, oversampling the minority class, and the SMOTE imbalance correction (Chawla et al. 2002) that enriches the minority class with synthetic data. The use case requires prior knowledge in basic ML concepts (issues imbalanced data, hyperparameter tuning, nested cross-validation). The R packages mlr3, mlr3pipelines and mlr3tuning will be used. You can find most of the content here also in the mlr3book explained in a more detailed way.

+

These steps are performed:

+
    +
  • Retrieve data sets from OpenML
  • +
  • Define imbalance correction pipeline Graphs (undersampling, oversampling and SMOTE) with mlr3pipelines
  • +
  • Autotune the Graph together with a learner using mlr3tuning
  • +
  • Benchmark the autotuned Graph and visualize the results using mlr3viz
  • +
+
+
+

Prerequisites

+

We load the most important packages for this post.

+
+
library(mlr3verse)
+
+
Loading required package: mlr3
+
+
library(mlr3learners)
+library(OpenML)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+
+
+
+

Retrieve data sets from OpenML

+

OpenML.org is an open machine learning platform, which allows users to share data, code and machine learning experiments. The OpenML R package can query available data sets using a filter-like approach by providing desired dataset characteristics like number.of.classes or number.of.features.

+
+
# get list of curated binary classification data sets (see https://arxiv.org/abs/1708.03731v2)
+ds = listOMLDataSets(
+  number.of.classes = 2,
+  number.of.features = c(1, 100),
+  number.of.instances = c(5000, 10000)
+)
+# select imbalanced data sets (without categorical features as SMOTE cannot handle them)
+ds = subset(ds, minority.class.size / number.of.instances < 0.2 &
+  number.of.symbolic.features == 1)
+ds
+
+# pick one data set from list above
+d = getOMLDataSet(980)
+d
+
+

After downloading the chosen data set, we create an mlr3 classification task:

+
+
# make sure target is a factor and create mlr3 tasks
+data = as.data.frame(d)
+data[[d$target.features]] = as.factor(data[[d$target.features]])
+task = as_task_classif(data, id = d$desc$name, target = d$target.features)
+task
+
+

Please note that the optdigits dataset is also included in the mlr3data package where you can get the preprocessed (integers properly encoded as such, etc.) data via:

+
+
data("optdigits", package = "mlr3data")
+task = as_task_classif(optdigits, target = "binaryclass", positive = "P")
+
+

Quick overview of the data:

+
+
skimr::skim(task$data())
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Data summary
Nametask$data()
Number of rows5620
Number of columns65
KeyNULL
_______________________
Column type frequency:
factor1
numeric64
________________________
Group variablesNone
+

Variable type: factor

+ ++++++++ + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_rateorderedn_uniquetop_counts
binaryclass01FALSE2N: 5048, P: 572
+

Variable type: numeric

+ +++++++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_ratemeansdp0p25p50p75p100hist
input1010.000.0000000▁▁▇▁▁
input10011.973.10000316▇▁▁▁▁
input110110.515.4306121516▃▂▂▂▇
input120111.804.0009131516▁▂▂▃▇
input130110.514.7907111516▂▂▃▃▇
input14018.265.970291416▇▂▃▃▇
input15012.093.92000216▇▁▁▁▁
input16010.140.94000015▇▁▁▁▁
input17010.000.1000005▇▁▁▁▁
input18012.603.49001416▇▂▁▁▁
input19019.685.8304121516▅▂▂▃▇
input2010.300.8800008▇▁▁▁▁
input20016.825.880161216▇▃▂▂▅
input21017.166.150161316▇▂▂▂▆
input22017.976.260091416▇▂▂▃▇
input23011.963.48000316▇▁▁▁▁
input24010.050.4400008▇▁▁▁▁
input25010.000.0300001▇▁▁▁▁
input26012.383.11001416▇▂▁▁▁
input27019.196.1503111516▅▂▂▂▇
input28019.035.9004101516▅▂▂▃▇
input29019.756.2403121616▅▁▂▂▇
input3015.394.67015916▇▃▃▂▂
input30017.775.960181416▇▃▃▃▇
input31012.333.64000416▇▁▁▁▁
input32010.000.0600002▇▁▁▁▁
input33010.000.0300001▇▁▁▁▁
input34012.143.30000415▇▁▁▁▁
input35017.666.280081416▇▂▂▂▇
input36019.186.2203111616▅▂▂▂▇
input370110.335.9206131616▃▁▂▂▇
input38019.055.8804101516▅▂▂▃▇
input39012.913.50001614▇▂▂▁▁
input40111.824.26010131516▁▁▂▃▇
input40010.000.0000000▁▁▇▁▁
input41010.020.2700007▇▁▁▁▁
input42011.462.95000216▇▁▁▁▁
input43016.596.520041416▇▁▁▂▅
input44017.206.460071416▇▂▂▂▆
input45017.846.300181416▇▂▂▂▇
input46018.535.770391416▆▂▃▃▇
input47013.494.36001716▇▂▂▁▁
input48010.020.2500006▇▁▁▁▁
input49010.010.25000010▇▁▁▁▁
input50111.584.4609131516▁▁▂▃▇
input50010.781.93000016▇▁▁▁▁
input51017.755.660281316▇▃▃▅▇
input52019.775.1706101516▃▃▃▃▇
input53019.655.3105101516▃▃▃▃▇
input54019.125.9703111516▅▂▂▃▇
input55013.744.91001716▇▂▁▁▁
input56010.170.84000013▇▁▁▁▁
input57010.000.0200001▇▁▁▁▁
input58010.280.93000010▇▁▁▁▁
input59015.765.020151016▇▃▃▂▂
input6015.595.630041016▇▂▂▂▃
input600111.994.35010131516▁▁▁▃▇
input610111.574.9809131616▂▁▁▃▇
input62016.725.820061216▇▂▂▃▅
input63012.094.05000216▇▁▁▁▁
input64010.251.42000016▇▁▁▁▁
input7011.383.36000016▇▁▁▁▁
input8010.141.05000016▇▁▁▁▁
input9010.000.0900005▇▁▁▁▁
+
+
+
+
+

Imbalance correction

+

In mlr3pipelines , there is a class balancing and a smote pipe operator that can be combined with any learner. Below, we define the undersampling, oversampling and SMOTE PipeOps/Graph. All three imbalance correction methods have hyperparameters to control the degree of class imbalance. We apply the PipeOps/Graph to the current task with specific hyperparameter values to see how the class balance changes:

+
+
# check original class balance
+table(task$truth())
+
+

+   P    N 
+ 572 5048 
+
+
# undersample majority class (relative to majority class)
+po_under = po("classbalancing",
+  id = "undersample", adjust = "major",
+  reference = "major", shuffle = FALSE, ratio = 1 / 6)
+# reduce majority class by factor '1/ratio'
+table(po_under$train(list(task))$output$truth())
+
+

+  P   N 
+572 841 
+
+
# oversample majority class (relative to majority class)
+po_over = po("classbalancing",
+  id = "oversample", adjust = "minor",
+  reference = "minor", shuffle = FALSE, ratio = 6)
+# enrich minority class by factor 'ratio'
+table(po_over$train(list(task))$output$truth())
+
+

+   P    N 
+3432 5048 
+
+
+

Note that the original SMOTE algorithm only accepts numeric features (see smotefamily::SMOTE). To keep it simple, we therefore preprocess the data and coerce integers to numerics prior to running SMOTE and reverse this afterwards:

+
+
# SMOTE enriches the minority class with synthetic data
+gr_smote =
+  po("colapply", id = "int_to_num",
+    applicator = as.numeric, affect_columns = selector_type("integer")) %>>%
+  po("smote", dup_size = 6) %>>%
+  po("colapply", id = "num_to_int",
+    applicator = function(x) as.integer(round(x, 0L)), affect_columns = selector_type("numeric"))
+# enrich minority class by factor (dup_size + 1)
+table(gr_smote$train(task)[[1L]]$truth())
+
+

+   P    N 
+4004 5048 
+
+
+
+
+

Construct AutoTuner

+

We combine the PipeOps/Graph with a learner (here ranger) to make each pipeline graph behave like a learner:

+
+
# create random forest learner
+learner = lrn("classif.ranger", num.trees = 50)
+
+# combine learner with pipeline graph
+learner_under = as_learner(po_under %>>% learner)
+learner_under$id = "undersample.ranger"
+learner_over = as_learner(po_over %>>% learner)
+learner_over$id = "oversample.ranger"
+learner_smote = as_learner(gr_smote %>>% learner)
+learner_smote$id = "smote.ranger"
+
+

We define the search space in order to tune the hyperparameters of the class imbalance methods.

+
+
# define parameter search space for each method
+search_space_under = ps(undersample.ratio = p_dbl(1 / 6, 1))
+search_space_over = ps(oversample.ratio = p_dbl(1, 6))
+search_space_smote = ps(
+  smote.dup_size = p_int(1, 6),
+  smote.K = p_int(1, 6),
+  # makes sure we use numbers to the power of two to better explore the parameter space
+  .extra_trafo = function(x, param_set) {
+    x$smote.K = round(2^(x$smote.K))
+    x
+  }
+)
+
+

We create an AutoTuner class from the learner to tune the graph (random forest learner + imbalance correction method) based on a 3-fold cross-validation using the F-beta Score as performance measure. To keep runtime low, we define the search space only for the imbalance correction method. However, one can also jointly tune the hyperparameter of the learner along with the imbalance correction method by extending the search space with the learner’s hyperparameters. Note that SMOTE has two hyperparameters K and dup_size. While K changes the behavior of the SMOTE algorithm, dup_size will affect oversampling rate. To focus on the effect of the oversampling rate on the performance, we will consider SMOTE with K = 2 as a different imbalance correction method as SMOTE with K = 4 (and so on). Hence, we use grid search with 5 different hyperparameter configurations for the undersampling method, the oversampling method and each SMOTE variant for tuning:

+
+
inner_cv3 = rsmp("cv", folds = 3)
+measure = msr("classif.fbeta")
+
+learns = list(
+  auto_tuner(
+    tuner = tnr("grid_search", resolution = 6),
+    learner = learner_under,
+    resampling = inner_cv3,
+    measure = measure,
+    search_space = search_space_under
+  ),
+  auto_tuner(
+    tuner = tnr("grid_search", resolution = 6),
+    learner = learner_over,
+    resampling = inner_cv3,
+    measure = measure,
+    search_space = search_space_over
+  ),
+  auto_tuner(
+    tuner = tnr("grid_search", resolution = 6),
+    learner = learner_smote,
+    resampling = inner_cv3,
+    measure = measure,
+    search_space = search_space_smote
+  )
+)
+
+
+
+

Benchmark AutoTuner

+

The AutoTuner is a fully tuned graph that behaves like a usual learner. For the tuning a 3-fold CV is used. Now, we use the benchmark() function to compare the tuned class imbalance pipeline graphs based on a holdout for the outer evaluation:

+
+
outer_holdout = rsmp("holdout")
+design = benchmark_grid(
+  tasks = task,
+  learners = learns,
+  resamplings = outer_holdout
+)
+print(design)
+
+
        task                  learner resampling
+1: optdigits undersample.ranger.tuned    holdout
+2: optdigits  oversample.ranger.tuned    holdout
+3: optdigits       smote.ranger.tuned    holdout
+
+
+
+
lgr::get_logger("bbotk")$set_threshold("warn")
+# NOTE: This code runs about 5 minutes
+bmr = benchmark(design, store_models = TRUE)
+
+
+

Visualize benchmark results

+
+
bmr$aggregate(measure)
+
+
   nr   task_id               learner_id resampling_id iters classif.fbeta
+1:  1 optdigits undersample.ranger.tuned       holdout     1     0.9453552
+2:  2 optdigits  oversample.ranger.tuned       holdout     1     0.9508197
+3:  3 optdigits       smote.ranger.tuned       holdout     1     0.9539295
+Hidden columns: resample_result
+
+
# one value per boxplot since we used holdout as outer resampling
+autoplot(bmr, measure = measure)
+
+
+
+

+
+
+
+
+
+
+

Visualize the tuning path

+

With store_models = TRUE we allow the benchmark() function to store each single model that was computed during tuning. Therefore, we can plot the tuning path of the best learner from the subsampling iterations:

+
+
library(ggplot2)
+bmr_data_learners = as.data.table(bmr)$learner
+utune_path = bmr_data_learners[[1]]$model$tuning_instance$archive$data
+utune_gg = ggplot(utune_path, aes(x = undersample.ratio, y = classif.fbeta)) +
+  geom_point(size = 3) +
+  geom_line() + ylim(0.9, 1)
+
+otune_path = bmr_data_learners[[2]]$model$tuning_instance$archive$data
+otune_gg = ggplot(otune_path, aes(x = oversample.ratio, y = classif.fbeta)) +
+  geom_point(size = 3) +
+  geom_line() + ylim(0.9, 1)
+
+stune_path = bmr_data_learners[[3]]$model$tuning_instance$archive$data
+stune_gg = ggplot(stune_path, aes(
+  x = smote.dup_size,
+  y = classif.fbeta, col = factor(smote.K))) +
+  geom_point(size = 3) +
+  geom_line() + ylim(0.9, 1)
+
+library(ggpubr)
+ggarrange(utune_gg, otune_gg, stune_gg, common.legend = TRUE, nrow = 1)
+
+
+
+

+
+
+
+
+

The results show that oversampling the minority class (for simple oversampling as well as for SMOTE) and undersampling the majority class yield a better performance for this specific data set.

+
+
+
+

Conclusion

+

In this post, we tuned and compared 5 different settings of sampling ratios for the undersampling method, the oversampling method and different SMOTE variants (using different values of K nearest neighbors during the sampling process). If you want to know more, read the mlr3book and the documentation of the mentioned packages.

+ + + +
+ +

References

+
+Chawla, N. V., K. W. Bowyer, L. O. Hall, and W. P. Kegelmeyer. 2002. “SMOTE: Synthetic Minority over-Sampling Technique.” Journal of Artificial Intelligence Research 16 (June): 321–57. https://doi.org/10.1613/jair.953. +
+
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/basic/2020-03-30-imbalanced-data/index_files/figure-html/2020-03-30-imbalanced-data-015-1.png b/gallery/basic/2020-03-30-imbalanced-data/index_files/figure-html/2020-03-30-imbalanced-data-015-1.png new file mode 100644 index 00000000..697128ed Binary files /dev/null and b/gallery/basic/2020-03-30-imbalanced-data/index_files/figure-html/2020-03-30-imbalanced-data-015-1.png differ diff --git a/gallery/basic/2020-03-30-imbalanced-data/index_files/figure-html/2020-03-30-imbalanced-data-016-1.png b/gallery/basic/2020-03-30-imbalanced-data/index_files/figure-html/2020-03-30-imbalanced-data-016-1.png new file mode 100644 index 00000000..78b15749 Binary files /dev/null and b/gallery/basic/2020-03-30-imbalanced-data/index_files/figure-html/2020-03-30-imbalanced-data-016-1.png differ diff --git a/gallery/basic/2020-03-30-imbalanced-data/index_files/figure-html/2020-03-30-imbalanced-data-018-1.png b/gallery/basic/2020-03-30-imbalanced-data/index_files/figure-html/2020-03-30-imbalanced-data-018-1.png new file mode 100644 index 00000000..175b62e7 Binary files /dev/null and b/gallery/basic/2020-03-30-imbalanced-data/index_files/figure-html/2020-03-30-imbalanced-data-018-1.png differ diff --git a/gallery/basic/2020-03-30-imbalanced-data/index_files/figure-html/2020-03-30-imbalanced-data-019-1.png b/gallery/basic/2020-03-30-imbalanced-data/index_files/figure-html/2020-03-30-imbalanced-data-019-1.png new file mode 100644 index 00000000..563d9944 Binary files /dev/null and b/gallery/basic/2020-03-30-imbalanced-data/index_files/figure-html/2020-03-30-imbalanced-data-019-1.png differ diff --git a/gallery/basic/2020-03-30-stratification-blocking/index.html b/gallery/basic/2020-03-30-stratification-blocking/index.html new file mode 100644 index 00000000..f18b8930 --- /dev/null +++ b/gallery/basic/2020-03-30-stratification-blocking/index.html @@ -0,0 +1,1127 @@ + + + + + + + + + + + + + +Resampling - Stratified, Blocked and Predefined – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Resampling - Stratified, Blocked and Predefined

+
+
+

Apply stratified, block and custom resampling.

+
+
+
+
+ + +
+ +
+
Authors
+
+

Milan Dragicevic

+

Giuseppe Casalicchio

+
+
+ +
+
Published
+
+

March 30, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Intro

+

When evaluating machine learning algorithms through resampling, it is preferable that each train/test partition will be a representative subset of the whole data set. This post covers three ways to achieve such reliable resampling procedures:

+
    +
  1. Stratified resampling for classification problems where each train/test split maintains the target class distribution of the original data set.
  2. +
  3. Block resampling where a grouping factor determines which observations should be together in train/test splits.
  4. +
  5. Custom resampling using predefined and manually created folds for the train/test splits.
  6. +
+
+
+

Prerequisites

+

We load the most important packages for this post.

+
+
library(mlr3verse)
+library(mlbench)
+library(data.table)
+
+

We initialize the random number generator with a fixed seed for reproducibility.

+
+
set.seed(7832)
+
+
+
+

Stratified resampling

+

In classification tasks, the ratio of the target class distribution should be similar in each train/test split, which is achieved by stratification. This is particularly useful in the case of imbalanced classes and small data sets.

+

Stratification can also be performed with respect to explanatory categorical variables to ensure that all subgroups are represented in all training and test sets.

+

In mlr3, each Task has a slot $col_roles. This slot shows general roles certain features will have throughout different stages of the machine learning process. At least, the $col_roles slot shows which variables will be used as features and as the target. However, the $col_roles slot can be more diverse and some variables might even serve multiple roles. We can specify the variable used for stratification in task$col_roles$stratum. This will be illustrated in the following example using the german_credit data:

+
+
task_gc = tsk("german_credit")
+task_gc$col_roles
+
+
$feature
+ [1] "age"                     "amount"                  "credit_history"          "duration"               
+ [5] "employment_duration"     "foreign_worker"          "housing"                 "installment_rate"       
+ [9] "job"                     "number_credits"          "other_debtors"           "other_installment_plans"
+[13] "people_liable"           "personal_status_sex"     "present_residence"       "property"               
+[17] "purpose"                 "savings"                 "status"                  "telephone"              
+
+$target
+[1] "credit_risk"
+
+$name
+character(0)
+
+$order
+character(0)
+
+$stratum
+character(0)
+
+$group
+character(0)
+
+$weight
+character(0)
+
+
+

We use the target feature called credit_risk to specify stratification with respect to the target variable:

+
+
task_gc$col_roles$stratum = "credit_risk"
+# alternatively task_gc$col_roles$stratum = task_gc$col_roles$target
+
+

After the specification of task$col_roles$stratum, the active binding task$strata will show the number of observations in each group and the corresponding row id’s:

+
+
task_gc$strata
+
+
     N                row_id
+1: 700       1,3,4,6,7,8,...
+2: 300  2, 5,10,11,12,14,...
+
+
+

Specify 3-fold cross validation and instantiate the resampling on the task:

+
+
cv3 = rsmp("cv", folds = 3)
+cv3$instantiate(task_gc)
+cv3$instance
+
+
      row_id fold
+   1:      7    1
+   2:      8    1
+   3:      9    1
+   4:     17    1
+   5:     22    1
+  ---            
+ 996:    959    3
+ 997:    967    3
+ 998:    980    3
+ 999:    984    3
+1000:    999    3
+
+
+

Check if the target class distribution is similar in each fold:

+
+
dt = merge(cv3$instance, task_gc$data()[, row_id := .I], by = "row_id")
+dt[, .(class_ratio = sum(credit_risk == "bad") /
+  sum(credit_risk == "good")), by = fold]
+
+
   fold class_ratio
+1:    2   0.4291845
+2:    3   0.4291845
+3:    1   0.4273504
+
+
+

And compare it with the target class distribution from the whole data set:

+
+
dt[, .(class_ratio = sum(credit_risk == "bad") / sum(credit_risk == "good"))]
+
+
   class_ratio
+1:   0.4285714
+
+
+

Note that the variable used for stratification does not necessarily have to be the target class. In fact, multiple categorical features can be used for stratification to maintain their frequency distribution in each fold:

+
+
task_gc$col_roles$stratum = c("housing", "telephone")
+task_gc$strata
+
+
     N                      row_id
+1: 280        1,13,20,21,26,30,...
+2: 433        2, 3, 7, 9,10,14,...
+3:  47   4,  5, 45, 76,134,192,...
+4:  61        6,19,37,55,63,69,...
+5:  63   8, 48, 60, 72, 96,100,...
+6: 116       11,12,15,22,23,28,...
+
+
+

To illustrate if stratification based on multiple categorical features works, we need to instantiate the CV folds again as we changed the features used for stratification:

+
+
cv3$instantiate(task_gc)
+cv3$instance
+
+
      row_id fold
+   1:     13    1
+   2:     21    1
+   3:     31    1
+   4:     33    1
+   5:     43    1
+  ---            
+ 996:    945    3
+ 997:    973    3
+ 998:    974    3
+ 999:    986    3
+1000:    993    3
+
+
+

Again, we check the relative frequency of observations in each group (combination of housing and telephone) across all folds:

+
+
dt = merge(cv3$instance, task_gc$data()[, row_id := .I], by = "row_id")
+dt = dt[, .(freq = .N), by = list(fold, housing, telephone)]
+dt = dcast(dt, housing + telephone ~ fold)
+
+
Using 'freq' as value column. Use 'value.var' to override
+
+
dt[, c(3:5) := lapply(.SD, function(x) x / sum(x)), .SDcols = 3:5]
+dt
+
+
    housing                 telephone          1          2          3
+1: for free                        no 0.11607143 0.11711712 0.11480363
+2: for free yes (under customer name) 0.06250000 0.06306306 0.06344411
+3:     rent                        no 0.43154762 0.43243243 0.43504532
+4:     rent yes (under customer name) 0.27976190 0.27927928 0.28096677
+5:      own                        no 0.04761905 0.04804805 0.04531722
+6:      own yes (under customer name) 0.06250000 0.06006006 0.06042296
+
+
+

And compare it with the relative frequency from the whole data set:

+
+
task_gc$data()[, .(freq = .N / max(.I)),
+  by = list(housing, telephone)
+][order(housing, telephone), ]
+
+
    housing                 telephone       freq
+1: for free                        no 0.11681772
+2: for free yes (under customer name) 0.06415479
+3:     rent                        no 0.43300000
+4:     rent yes (under customer name) 0.28084253
+5:      own                        no 0.04895833
+6:      own yes (under customer name) 0.06106106
+
+
+

It is evident that in each fold, the combination of housing and telephone have similar frequencies that also coincide with the frequencies from the whole data set.

+
+
+

Block resampling

+

An additional concern when specifying resampling is respecting the natural grouping of the data. Blocking refers to the situation where subsets of observations belong together and must not be separated during resampling. Hence, for one train/test set pair the entire block is either in the training set or in the test set.

+

The following example is based on the BreastCancer data set from the mlbench package:

+
+
data(BreastCancer, package = "mlbench")
+task_bc = as_task_classif(BreastCancer, target = "Class", positive = "malignant")
+
+

In the BreastCancer data set, for example, several observations have the same “Id” (Sample code number) which implies these are samples taken from the same patient at different times.

+
+
# Let's count how many observation actually have the same Id more than once
+sum(table(BreastCancer$Id) > 1)
+
+
[1] 46
+
+
+

There are 46 Id’s with more than one observation (row).

+

The model trained on this data set will be used to predict cancer status of new patients. Hence, we have to make sure that each Id occurs exactly in one fold, so that all observations with the same Id should be either used for training or for evaluating the model. This way, we get less biased performance estimates via k-fold cross validation. The following example will illustrate block cross validation which can be achieved by specifying a blocking factor in the task$col_roles$group slot:

+
+
# Use Id column as block factor
+task_bc$col_roles$group = "Id"
+# Remove Id from feature
+# task_bc$col_roles$feature = setdiff(task_bc$col_roles$feature, "Id")
+cv5 = rsmp("cv", folds = 5)
+set.seed(123)
+cv5$instantiate(task_bc)
+cv5$instance
+
+
      row_id fold
+  1: 1016277    1
+  2: 1044572    1
+  3: 1049815    1
+  4: 1050718    1
+  5: 1054590    1
+ ---             
+641: 1369821    5
+642: 1371026    5
+643: 1371920    5
+644:  714039    5
+645:  841769    5
+
+
+

In this case, the row_id column of the cv5$instance slot refers to values of the grouping variable “Id”. Additionally, the number of rows of the cv5$instance is the same as the number of unique groups:

+
+
all(cv5$instance$row_id %in% BreastCancer$Id)
+
+
[1] TRUE
+
+
nrow(cv5$instance) == length(unique(BreastCancer$Id))
+
+
[1] TRUE
+
+
+

If the specified blocking groups are respected, each Id appears only in exactly one fold. To inspect if blocking was successful when generating the folds we count how often each Id appears in a specific fold and print the Ids that appear in more than one fold:

+
+
dt = merge(task_bc$data(), cv5$instance, by.x = "Id", by.y = "row_id")
+dt = dt[, .(unique_folds = length(unique(fold))), by = Id]
+dt[unique_folds > 1, ]
+
+
Empty data.table (0 rows and 2 cols): Id,unique_folds
+
+
+

As expected, the table is empty as there are no Id’s present in more than one fold.

+
+
+

Resampling with predefined folds

+

In some use cases, it might be necessary to use predefined folds. When using k-fold cross validation without repetition this can be achieved by manually creating a feature used to denote folds and assigning it to the task$col_roles$group slot. First, we create a vector that contains 5 predefined folds:

+
+
folds = sample(rep(1:5, length.out = nrow(BreastCancer)),
+  size = nrow(BreastCancer),
+  replace = F
+)
+head(folds, 20)
+
+
 [1] 2 2 4 1 5 2 5 3 1 5 4 3 3 4 5 3 3 5 2 4
+
+
table(folds)
+
+
folds
+  1   2   3   4   5 
+140 140 140 140 139 
+
+
+

This vector is now added to the data set and will be used as grouping factor just as when defining block resampling:

+
+
task_bc = TaskClassif$new(
+  id = "BreastCancer",
+  backend = data.frame(BreastCancer, foldIds = as.factor(folds)),
+  target = "Class",
+  positive = "malignant"
+)
+task_bc$col_roles$group = "foldIds"
+# Remove "foldIds" from features
+# task_bc$col_roles$feature = setdiff(task_bc$col_roles$feature, "foldIds")
+
+

We now instantiate a 5-fold CV that will respect the predefined folds:

+
+
cv5 = rsmp("cv", folds = 5)
+cv5$instantiate(task_bc)
+cv5$instance
+
+
   row_id fold
+1:      1    1
+2:      2    2
+3:      3    3
+4:      4    4
+5:      5    5
+
+
+

Since we have only five predefined folds, the cv5$instance data table has five rows and shows which of our foldIds values (contained in the row_id column) will belong to which instantiated fold. To check if the predefined groups are respected, we count how often each foldIds appears in a specific fold:

+
+
dt = merge(task_bc$data(), cv5$instance, by.x = "foldIds", by.y = "row_id")
+dt[, .(unique_folds = length(unique(fold))), by = foldIds]
+
+
   foldIds unique_folds
+1:       1            1
+2:       2            1
+3:       3            1
+4:       4            1
+5:       5            1
+
+
+

There are five groups and each foldIds appears only in exactly one fold. This means that each instantiated fold corresponds to one of the predefined folds.

+

The previous example does not cover how to perform repeated k-fold CV or time series CV with predefined indices. This is possible via the mlr_resamplings_custom to which a list of predefined train and test indices can be assigned. In the following example, a custom resampling is created using indices created by caret::createMultiFolds():

+
+
task_gc = tsk("german_credit")
+train_ind = caret::createMultiFolds(task_gc$truth(), k = 5, times = 10)
+test_ind = lapply(train_ind, function(x) setdiff(1:task_gc$nrow, x))
+rc = rsmp("custom")
+rc$instantiate(task_gc, train_ind, test_ind)
+
+

We now check if the instantiated custom resampling contains the intended folds:

+
+
# check it for the first fold
+all.equal(train_ind[[1]], rc$train_set(1))
+
+
[1] TRUE
+
+
# check it for all folds
+unlist(lapply(1:rc$iters, function(i) all.equal(train_ind[[i]], rc$train_set(i))))
+
+
 [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
+[24] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
+[47] TRUE TRUE TRUE TRUE
+
+
+
+
+

Conclusions

+

This post shows how to control the resampling process when using mlr3 in order to account for data specificities.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index.html b/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index.html new file mode 100644 index 00000000..47653b4a --- /dev/null +++ b/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index.html @@ -0,0 +1,1339 @@ + + + + + + + + + + + + +Feature Engineering of Date-Time Variables – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Feature Engineering of Date-Time Variables

+
+
+

Engineer features using date-time variables.

+
+
+
+
+ + +
+ +
+
Author
+
+

Lennart Schneider

+
+
+ +
+
Published
+
+

May 2, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +

In this tutorial, we demonstrate how mlr3pipelines can be used to easily engineer features based on date-time variables. Relying on the Bike Sharing Dataset and the ranger learner we compare the root mean square error (RMSE) of a random forest using the original features (baseline), to the RMSE of a random forest using newly engineered features on top of the original ones.

+
+

Motivation

+

A single date-time variable (i.e., a POSIXct column) contains plenty of information ranging from year, month, day, hour, minute and second to other features such as week of the year, or day of the week. Moreover, most of these features are of cyclical nature, i.e., the eleventh and twelfth hour of a day are one hour apart, but so are the 23rd hour and midnight of the other day (see also this blog post and fastai for more information).

+

Not respecting this cyclical nature results in treating hours on a linear continuum. One way to handle a cyclical feature \(\mathbf{x}\) is to compute the sine and cosine transformation of \(\frac{2 \pi \mathbf{x}}{\mathbf{x}_{\text{max}}}\), with \(\mathbf{x}_{\text{max}} = 24\) for hours and \(60\) for minutes and seconds.

+

This results in a two-dimensional representation of the feature:

+
+
+
+
+

+
+
+
+
+

mlr3pipelines provides the PipeOpDateFeatures pipeline which can be used to automatically engineer features based on POSIXct columns, including handling of cyclical features.

+

This is useful as most learners naturally cannot handle dates and POSIXct variables and therefore require conversion prior to training.

+
+
+

Prerequisites

+

We load the mlr3verse package which pulls in the most important packages for this example. The mlr3learners package loads additional learners.

+
+
library(mlr3verse)
+library(mlr3learners)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+
+
+
+

Bike Sharing

+

The Bike Sharing Dataset contains the hourly count of rental bikes between years 2011 and 2012 in Capital bikeshare system with the corresponding weather and seasonal information. The dataset can be downloaded from the UCI Machine Learning Repository. After reading in the data, we fix some factor levels, and convert some data types:

+

The Bike Sharing Dataset contains the hourly count of rental bikes between years 2011 and 2012 in Capital bikeshare system with the corresponding weather and seasonal information. We load the data set from the mlr3data package.

+
+
data("bike_sharing", package = "mlr3data")
+
+

Our goal will be to predict the total number of rented bikes on a given day: cnt.

+
+
skimr::skim(bike_sharing)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Data summary
Namebike_sharing
Number of rows17379
Number of columns14
KeyNULL
_______________________
Column type frequency:
character1
factor2
logical2
numeric9
________________________
Group variablesNone
+

Variable type: character

+ ++++++++++ + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_rateminmaxemptyn_uniquewhitespace
date01101007310
+

Variable type: factor

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_rateorderedn_uniquetop_counts
season01FALSE4sum: 4496, spr: 4409, win: 4242, fal: 4232
weather01FALSE41: 11413, 2: 4544, 3: 1419, 4: 3
+

Variable type: logical

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_ratemeancount
holiday010.03FAL: 16879, TRU: 500
working_day010.68TRU: 11865, FAL: 5514
+

Variable type: numeric

+ +++++++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_ratemeansdp0p25p50p75p100hist
year010.500.500.000.001.001.001.00▇▁▁▁▇
month016.543.441.004.007.0010.0012.00▇▆▆▅▇
hour0111.556.910.006.0012.0018.0023.00▇▇▆▇▇
weekday013.002.010.001.003.005.006.00▇▃▃▃▇
temperature010.500.190.020.340.500.661.00▂▇▇▇▁
apparent_temperature010.480.170.000.330.480.621.00▁▆▇▆▁
humidity010.630.190.000.480.630.781.00▁▃▇▇▆
windspeed010.190.120.000.100.190.250.85▇▆▂▁▁
count01189.46181.391.0040.00142.00281.00977.00▇▃▁▁▁
+
+
+

The original dataset does not contain a POSIXct column, but we can easily generate one based on the other variables available (note that as no information regarding minutes and seconds is available, we set them to :00:00):

+
+
bike_sharing$date = as.POSIXct(paste0(bike_sharing$date, " ", bike_sharing$hour, ":00:00"),
+  tz = "GMT", format = "%Y-%m-%d %H:%M:%S")
+
+
+
+
+
+

+
+
+
+
+
+
+

Baseline Random Forest

+

We construct a new regression task and keep a holdout set.

+
+
task = as_task_regr(bike_sharing, target = "count")
+
+validation_set = sample(seq_len(task$nrow), size = 0.3 * task$nrow)
+
+task$set_row_roles(validation_set, roles = "holdout")
+
+

To estimate the performance on unseen data, we will use a 3-fold cross-validation. Note that this involves validating on past data, which is usually bad practice but should suffice for this example:

+
+
cv3 = rsmp("cv", folds = 3)
+
+

To obtain reliable estimates on how well our model generalizes to the future, we would have to split our training and test sets according to the date variable.

+

As our baseline model, we use a random forest, ranger learner. For the baseline, we dropdate, our new POSIXct variable which we will only use later.

+
+
learner_ranger = lrn("regr.ranger")
+task_ranger = task$clone()
+task_ranger$select(setdiff(task$feature_names, c("date")))
+
+

We can then use resample() with 3-fold cross-validation:

+
+
rr_ranger = resample(task_ranger, learner = learner_ranger, resampling = cv3)
+
+rr_ranger$score(msr("regr.mse"))[, .(iteration, task_id, learner_id, resampling_id, regr.mse)]
+
+
   iteration      task_id  learner_id resampling_id regr.mse
+1:         1 bike_sharing regr.ranger            cv 4543.904
+2:         2 bike_sharing regr.ranger            cv 4276.996
+3:         3 bike_sharing regr.ranger            cv 4767.763
+
+
+

We calculate the average RMSE.

+
+
rr_ranger$aggregate()
+
+
regr.mse 
+4529.554 
+
+
+

We now want to improve our baseline model by using newly engineered features based on the date POSIXct column.

+
+
+

PipeOpDateFeatures

+

To engineer new features we use PipeOpDateFeatures. This pipeline automatically dispatches on POSIXct columns of the data and by default adds plenty of new date-time related features. Here, we want to add all except for minute and second, because this information is not available. As we additionally want to use cyclical versions of the features we set cyclic = TRUE:

+
+
pipeop_date = po("datefeatures", cyclic = TRUE, minute = FALSE, second = FALSE)
+
+

Training this pipeline will result in simply adding the new features (and removing the original POSIXct feature(s) used for the feature engineering, see also the keep_date_var parameter). In our task, we can now drop the features, yr, mnth, hr, and weekday, because our pipeline will generate these anyways:

+
+
task_ex = task$clone()
+task_ex$select(setdiff(task$feature_names,
+  c("instant", "dteday", "yr", "mnth", "hr", "weekday", "casual", "registered")))
+
+pipeop_date$train(list(task_ex))
+
+
$output
+<TaskRegr:bike_sharing> (12166 x 32)
+* Target: count
+* Properties: -
+* Features (31):
+  - dbl (23): apparent_temperature, date.day_of_month, date.day_of_month_cos, date.day_of_month_sin,
+    date.day_of_week, date.day_of_week_cos, date.day_of_week_sin, date.day_of_year, date.day_of_year_cos,
+    date.day_of_year_sin, date.hour, date.hour_cos, date.hour_sin, date.month, date.month_cos,
+    date.month_sin, date.week_of_year, date.week_of_year_cos, date.week_of_year_sin, date.year, humidity,
+    temperature, windspeed
+  - lgl (3): date.is_day, holiday, working_day
+  - int (3): hour, month, year
+  - fct (2): season, weather
+
+
+

Note that it may be useful to familiarize yourself with PipeOpRemoveConstants which can be used after the feature engineering to remove features that are constant. PipeOpDateFeatures does not do this step automatically.

+

To combine this feature engineering step with a random forest, ranger learner, we now construct a GraphLearner.

+
+
+

Using the New Features in a GraphLearner

+

We create a GraphLearner consisting of the PipeOpDateFeatures pipeline and a ranger learner. This GraphLearner then behaves like any other Learner:

+
+
graph = po("datefeatures", cyclic = TRUE, minute = FALSE, second = FALSE) %>>%
+  lrn("regr.ranger")
+
+graph_learner = as_learner(graph)
+
+plot(graph, html = FALSE)
+
+
+
+

+
+
+
+
+

Using resample() with 3-fold cross-validation on the task yields:

+
+
task_graph_learner = task$clone()
+task_graph_learner$select(setdiff(task$feature_names,
+  c("instant", "dteday", "yr", "mnth", "hr", "weekday", "casual", "registered")))
+
+rr_graph_learner = resample(task_graph_learner, learner = graph_learner, resampling = cv3)
+
+rr_graph_learner$score(msr("regr.mse"))
+
+
        task_id               learner_id resampling_id iteration regr.mse
+1: bike_sharing datefeatures.regr.ranger            cv         1 2521.642
+2: bike_sharing datefeatures.regr.ranger            cv         2 2229.746
+3: bike_sharing datefeatures.regr.ranger            cv         3 2254.390
+Hidden columns: task, learner, resampling, prediction
+
+
+
+
+
+ +
+
+

We calculate the average RMSE.

+
+
rr_graph_learner$aggregate()
+
+
regr.mse 
+2335.259 
+
+
+

and therefore improved by almost 94%!

+

Finally, we fit our GraphLearner on the complete training set and predict on the validation set:

+
+
task$select(setdiff(task$feature_names, c("year", "month", "hour", "weekday")))
+
+graph_learner$train(task)
+
+prediction = graph_learner$predict(task, row_ids = task$row_roles$validation)
+
+

Where we can obtain the RMSE on the held-out validation data.

+
+
prediction$score(msr("regr.mse"))
+
+
regr.mse 
+460.0281 
+
+
+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index_files/figure-html/2020-05-02-feature-engineering-of-date-time-variables-001-1.png b/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index_files/figure-html/2020-05-02-feature-engineering-of-date-time-variables-001-1.png new file mode 100644 index 00000000..f99d7be7 Binary files /dev/null and b/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index_files/figure-html/2020-05-02-feature-engineering-of-date-time-variables-001-1.png differ diff --git a/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index_files/figure-html/2020-05-02-feature-engineering-of-date-time-variables-007-1.png b/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index_files/figure-html/2020-05-02-feature-engineering-of-date-time-variables-007-1.png new file mode 100644 index 00000000..417c8695 Binary files /dev/null and b/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index_files/figure-html/2020-05-02-feature-engineering-of-date-time-variables-007-1.png differ diff --git a/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index_files/figure-html/2020-05-02-feature-engineering-of-date-time-variables-015-1.png b/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index_files/figure-html/2020-05-02-feature-engineering-of-date-time-variables-015-1.png new file mode 100644 index 00000000..0f302698 Binary files /dev/null and b/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index_files/figure-html/2020-05-02-feature-engineering-of-date-time-variables-015-1.png differ diff --git a/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index_files/figure-html/feature-engineering-of-date-time-variables-002-1.png b/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index_files/figure-html/feature-engineering-of-date-time-variables-002-1.png new file mode 100644 index 00000000..f99d7be7 Binary files /dev/null and b/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index_files/figure-html/feature-engineering-of-date-time-variables-002-1.png differ diff --git a/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index_files/figure-html/feature-engineering-of-date-time-variables-008-1.png b/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index_files/figure-html/feature-engineering-of-date-time-variables-008-1.png new file mode 100644 index 00000000..417c8695 Binary files /dev/null and b/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index_files/figure-html/feature-engineering-of-date-time-variables-008-1.png differ diff --git a/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index_files/figure-html/feature-engineering-of-date-time-variables-019-1.png b/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index_files/figure-html/feature-engineering-of-date-time-variables-019-1.png new file mode 100644 index 00000000..582b8156 Binary files /dev/null and b/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index_files/figure-html/feature-engineering-of-date-time-variables-019-1.png differ diff --git a/gallery/basic/2020-05-04-moneyball/index.html b/gallery/basic/2020-05-04-moneyball/index.html new file mode 100644 index 00000000..da514246 --- /dev/null +++ b/gallery/basic/2020-05-04-moneyball/index.html @@ -0,0 +1,1396 @@ + + + + + + + + + + + + +mlr3 and OpenML - Moneyball Use Case – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

mlr3 and OpenML - Moneyball Use Case

+
+
+

Download data from OpenML data and impute missing values.

+
+
+ +
+ + +
+ +
+
Author
+
+

Philipp Kopper

+
+
+ +
+
Published
+
+

May 4, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +

This use case shows how to easily work with datasets available via OpenML into an mlr3 workflow.

+

The following operations are illustrated:

+ +
+

Prerequisites

+
+
# various functions of the mlr3 ecosystem
+library("mlr3verse")
+# about a dozen reasonable learners
+library("mlr3learners")
+# retrieving the data
+library("OpenML")
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+
+
+
+

Retrieving the data from OpenML

+

We can use the OpenML package to retrieve data (and more) straight away. OpenML is is an inclusive movement to build an open, organized, online ecosystem for machine learning. Typically, you can retrieve the data with an data.id. The id can be found on OpenML. We choose the data set 41021. The related web page can be accessed here. This data set was uploaded by Joaquin Vanschoren.

+
+
oml_data = getOMLDataSet(data.id = 41021)
+
+
Downloading from 'http://www.openml.org/api/v1/data/41021' to '/tmp/RtmpIRWjZy/cache/datasets/41021/description.xml'.
+
+
+
Downloading from 'https://api.openml.org/data/v1/download/18626236/Moneyball.arff' to '/tmp/RtmpIRWjZy/cache/datasets/41021/dataset.arff'
+
+
+
Loading required package: readr
+
+
+

The description indicates that the data set is associated with baseball or more precisely the story of Moneyball.

+
+
head(as.data.table(oml_data))
+
+
+
+
+ +
+
+

However, the description within the OpenML object is not very detailed. The previously referenced page however states the following:

+

In the early 2000s, Billy Beane and Paul DePodesta worked for the Oakland Athletics. During their work there, they disrupted the game of baseball. They didn’t do it using a bat or glove, and they certainly didn’t do it by throwing money at the issue; in fact, money was the issue. They didn’t have enough of it, but they were still expected to keep up with teams that had more substantial endorsements. This is where Statistics came riding down the hillside on a white horse to save the day. This data set contains some of the information that was available to Beane and DePodesta in the early 2000s, and it can be used to better understand their methods.

+

This data set contains a set of variables that Beane and DePodesta emphasized in their work. They determined that statistics like on-base percentage (obp) and slugging percentage (slg) were very important when it came to scoring runs, however, they were largely undervalued by most scouts at the time. This translated to a gold mine for Beane and DePodesta. Since these players weren’t being looked at by other teams, they could recruit these players on a small budget. The variables are as follows:

+
    +
  • team
  • +
  • league
  • +
  • year
  • +
  • runs scored (rs)
  • +
  • runs allowed (ra)
  • +
  • wins (w)
  • +
  • on-base percentage (obp)
  • +
  • slugging percentage (slg)
  • +
  • batting average (ba)
  • +
  • playoffs (binary)
  • +
  • rankseason
  • +
  • rankplayoffs
  • +
  • games played (g)
  • +
  • opponent on-base percentage (oobp)
  • +
  • opponent slugging percentage (oslg)
  • +
+

While Beane and DePodesta defined most of these statistics and measures for individual players, this data set is on the team level.

+

These statistics seem very informative if you are into baseball. If baseball of rather obscure to you, simply take these features as given or give this article a quick read.

+

Finally, note that the moneyball dataset is also included in the mlr3data package where you can get the preprocessed (integers properly encoded as such, etc.) data via:

+
+
data("moneyball", package = "mlr3data")
+skimr::skim(moneyball)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Data summary
Namemoneyball
Number of rows1232
Number of columns15
_______________________
Column type frequency:
factor6
numeric9
________________________
Group variablesNone
+

Variable type: factor

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_rateorderedn_uniquetop_counts
team01.0FALSE39BAL: 47, BOS: 47, CHC: 47, CHW: 47
league01.0FALSE2AL: 616, NL: 616
playoffs01.0FALSE20: 988, 1: 244
rankseason9880.2FALSE82: 53, 1: 52, 3: 44, 4: 44
rankplayoffs9880.2FALSE53: 80, 4: 68, 1: 47, 2: 47
g01.0FALSE8162: 954, 161: 139, 163: 93, 160: 23
+

Variable type: numeric

+ +++++++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_ratemeansdp0p25p50p75p100hist
year01.001988.9614.821962.001976.751989.002002.002012.00▆▆▇▆▇
rs01.00715.0891.53463.00652.00711.00775.001009.00▁▆▇▃▁
ra01.00715.0893.08472.00649.75709.00774.251103.00▂▇▆▂▁
w01.0080.9011.4640.0073.0081.0089.00116.00▁▃▇▆▁
obp01.000.330.020.280.320.330.340.37▁▃▇▅▁
slg01.000.400.030.300.380.400.420.49▁▅▇▅▁
ba01.000.260.010.210.250.260.270.29▁▂▇▆▂
oobp8120.340.330.020.290.320.330.340.38▂▇▇▃▁
oslg8120.340.420.030.350.400.420.440.50▁▆▇▅▁
+
+
+

The summary shows how this data we are dealing with looks like: Some data is missing, however, this has structural reasons. There are 39 teams with each maximally 47 years (1962 - 2012). For 988 cases the information on rankseason and rankplayoffs is missing. This is since these simply did not reach the playoffs and hence have no reported rank.

+
+
summary(moneyball[moneyball$playoffs == 0, c("rankseason", "rankplayoffs")])
+
+
   rankseason  rankplayoffs
+ 1      :  0   1   :  0    
+ 2      :  0   2   :  0    
+ 3      :  0   3   :  0    
+ 4      :  0   4   :  0    
+ 5      :  0   5   :  0    
+ (Other):  0   NA's:988    
+ NA's   :988               
+
+
+

On the other hand, oobp and oslg have \(812\) missing values. It seems as if these measures were not available before \(1998\).

+
+
library(ggplot2)
+library(naniar)
+
+ggplot(moneyball, aes(x = year, y = oobp)) +
+  geom_miss_point()
+
+
+
+

+
+
+
+
+

We seem to have a missing data problem. Typically, in this case, we have three options: They are:

+
    +
  • Complete case analysis: Exclude all observation with missing values.

  • +
  • Complete feature analysis: Exclude all features with missing values.

  • +
  • Missing value imputation: Use a model to “guess” the missing values (based on the underlying distribution of the data.

  • +
+

Usually, missing value imputation is preferred over the first two. However, in machine learning, one can try out all options and see which performs best for the underlying problem. For now, we limit ourselves to a rather simple imputation technique, imputation by randomly sampling from the univariate distribution. Note that this does not take the multivariate distribution into account properly and that there are more elaborate approaches. We only aim to impute oobp and oslg. For the other missing (categorical) features, we simply add a new level which indicates that information is missing (i.e. all missing values belong to).

+

It is important to note that in this case here the vast majority of information on the features is missing. In this case, imputation is performed to not throw away the existing information of the features.

+

mlr3 has some solutions for that within the mlr3pipelines package. We start with an easy PipeOp which only performs numeric imputation.

+
+
imp_num = po("imputehist", affect_columns = selector_type(c("integer", "numeric")))
+
+

Next, we append the second imputation job for factors.

+
+
imp_fct = po("imputeoor", affect_columns = selector_type("factor"))
+graph = imp_num %>>% imp_fct
+graph$plot(html = FALSE)
+
+
+
+

+
+
+
+
+
+
+

Creating tasks and learners

+

The fact that there is missing data does not affect the task definition. The task determines what is the problem to be solved by machine learning. We want to explain the runs scored (rs). rs is an important measure as a run is equivalent to a ‘point’ scored in other sports. Naturally, the aim of a coach should be to maximise runs scored and minimise runs allowed. As runs scored and runs allowed are both legitimate targets we ignore the runs allowed here. The task is defined by:

+
+
# creates a `mlr3` task from scratch, from a data.frame
+# 'target' names the column in the dataset we want to learn to predict
+task = as_task_regr(moneyball, target = "rs")
+task$missings()
+
+
+
+
+ +
+
+

The $missings() method indicates what we already knew: our missing values. Missing values are not always a problem. Some learners can deal with them pretty well. However, we want to use a random forest for our task.

+
+
# creates a learner
+test_learner = lrn("regr.ranger")
+
+# displays the properties
+test_learner$properties
+
+
[1] "hotstart_backward" "importance"        "oob_error"         "weights"          
+
+
+

Typically, in mlr3 the $properties field would tell us whether missing values are a problem to this learner or not. As it is not listed here, the random forest cannot deal with missing values.

+

As we aim to use imputation beforehand, we incorporate it into the learner. Our selected learner is going to be a random forest from the ranger package.

+

One can allow the embedding of the preprocessing (imputation) into a learner by creating a PipeOpLearner. This special Learner can be put into a graph together with the imputer.

+
+
# convert learner to pipeop learner and set hyperparameter
+pipeop_learner = po(lrn("regr.ranger"), num.trees = 1000, importance = "permutation")
+
+# add pipeop learner to graph and create graph learner
+graph_learner = as_learner(graph %>>% pipeop_learner)
+
+

The final graph looks like the following:

+
+
graph_learner$graph$plot(html = FALSE)
+
+
+
+

+
+
+
+
+
+
+

Train and predict

+

To get a feeling of how our model performs we simply train the Learner on a subset of the data and predict the hold-out data.

+
+
# defines the training and testing data; 95% is used for training
+train_set = sample(task$nrow, 0.95 * task$nrow)
+test_set = setdiff(seq_len(task$nrow), train_set)
+
+# train learner on subset of task
+graph_learner$train(task, row_ids = train_set)
+
+# predict using held out observations
+prediction = graph_learner$predict(task, row_ids = test_set)
+
+head(as.data.table(prediction))
+
+
+
+
+ +
+
+

Viewing the predicted values it seems like the model predicts reasonable values that are fairly close to the truth.

+
+
+

Evaluation & Resampling

+

While the prediction indicated that the model is doing what it is supposed to, we want to have a more systematic understanding of the model performance. That means we want to know by how much our model is away from the truth on average. Cross-validation investigates this question. In mlr3 10-fold cross-validation is constructed as follows:

+
+
cv10 = rsmp("cv", folds = 10)
+rr = resample(task, graph_learner, cv10)
+
+

We choose some of the performance measures provided by:

+
+
as.data.table(mlr_measures)
+
+
+
+
+ +
+
+

We choose the mean absolute error and the mean squared error.

+
+
rr$score(msrs(c("regr.mae", "regr.mse")))
+
+
+
+
+ +
+
+

We can also compute now by how much our model was on average wrong when predicting the runs scored.

+
+
rr$aggregate(msr("regr.mae"))
+
+
regr.mae 
+19.39997 
+
+
+

That seems not too bad. Considering that on average approximately 715 runs per team per season have been scored.

+
+
mean(moneyball$rs)
+
+
[1] 715.082
+
+
+
+
+

Performance boost of imputation

+

To assess if imputation was beneficial, we can compare our current learner with a learner which ignores the missing features. Normally, one would set up a benchmark for this. However, we want to keep things short in this use case. Thus, we only set up the alternative learner (with identical hyperparameters) and compare the 10-fold cross-validated mean absolute error.

+

As we are mostly interested in the numeric imputation we leave the remaining graph as it is.

+
+
impute_oor = po("imputeoor", affect_columns = selector_type("factor"))
+
+

Subsequently, we create a pipeline with PipeOpSelect.

+
+
feature_names = colnames(moneyball)[!sapply(moneyball, anyNA)]
+feature_names = c(feature_names[feature_names %in% task$feature_names],
+  "rankseason", "rankplayoffs")
+select_na = po("select", selector = selector_name(feature_names))
+
+graph_2 = impute_oor %>>% select_na
+graph_2$plot(html = FALSE)
+
+
+
+

+
+
+
+
+

Now we complete the learner and apply resampling as before.

+
+
graph_learner_2 = as_learner(graph_2 %>>% pipeop_learner)
+rr_2 = resample(task, graph_learner_2, cv10)
+rr_2$aggregate(msr("regr.mae"))
+
+
regr.mae 
+19.03752 
+
+
+

Surprisingly, the performance seems to be approximately the same. That means that the imputed features seem not very helpful. We can use the variable.importance of the random forest.

+
+
sort(graph_learner$model$regr.ranger$model$variable.importance, decreasing = TRUE)
+
+
+
+
+ +
+
+

We see that according to this the left out oobp and oslg seem to have solely rudimentary explanatory power. This may be because there were simply too many instances or because the features are themselves not very powerful.

+
+
+

Conclusion

+

So, to sum up, what we have learned: We can access very cool data straight away with the OpenML package. (We are working on a better direct implementation into mlr3 at the moment.) We can work with missing data very well in mlr3. Nevertheless, we discovered that sometimes imputation does not lead to the intended goals. We also learned how to use some PipeOps from the mlr3pipelines package.

+

But most importantly, we found a way to predict the runs scored of MLB teams.

+

If you want to know more, read the mlr3book and the documentation of the mentioned packages.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-008-1.png b/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-008-1.png new file mode 100644 index 00000000..37edaa0d Binary files /dev/null and b/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-008-1.png differ diff --git a/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-009-1.png b/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-009-1.png new file mode 100644 index 00000000..37edaa0d Binary files /dev/null and b/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-009-1.png differ diff --git a/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-010-1.png b/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-010-1.png new file mode 100644 index 00000000..5e42e519 Binary files /dev/null and b/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-010-1.png differ diff --git a/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-011-1.png b/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-011-1.png new file mode 100644 index 00000000..cc22da09 Binary files /dev/null and b/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-011-1.png differ diff --git a/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-015-1.png b/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-015-1.png new file mode 100644 index 00000000..bf2a09cf Binary files /dev/null and b/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-015-1.png differ diff --git a/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-016-1.png b/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-016-1.png new file mode 100644 index 00000000..3a82c318 Binary files /dev/null and b/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-016-1.png differ diff --git a/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-026-1.png b/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-026-1.png new file mode 100644 index 00000000..9e6d6cc0 Binary files /dev/null and b/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-026-1.png differ diff --git a/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-027-1.png b/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-027-1.png new file mode 100644 index 00000000..b8b6efc2 Binary files /dev/null and b/gallery/basic/2020-05-04-moneyball/index_files/figure-html/2020-05-04-moneyball-027-1.png differ diff --git a/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index.html b/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index.html new file mode 100644 index 00000000..433f858d --- /dev/null +++ b/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index.html @@ -0,0 +1,1023 @@ + + + + + + + + + + + + +Comparison of Decision Boundaries of Classification Learners – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Comparison of Decision Boundaries of Classification Learners

+
+
+

Visualize the decision boundaries of multiple classification learners on some artificial data sets.

+
+
+ +
+ + +
+ +
+
Author
+
+

Michel Lang

+
+
+ +
+
Published
+
+

August 14, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +

The visualization of decision boundaries helps to understand what the pros and cons of individual classification learners are. This posts demonstrates how to create such plots.

+

We load the mlr3 package.

+
+
library("mlr3")
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+
+
+

Artificial Data Sets

+

The three artificial data sets are generated by task generators (implemented in mlr3):

+
+
N <- 200
+tasks <- list(
+  tgen("xor")$generate(N),
+  tgen("moons")$generate(N),
+  tgen("circle")$generate(N)
+)
+
+
+

XOR

+

Points are distributed on a 2-dimensional cube with corners \((\pm 1, \pm 1)\). Class is "red" if \(x\) and \(y\) have the same sign, and "black" otherwise.

+
+
plot(tgen("xor"))
+
+
+
+

+
+
+
+
+
+
+

Circle

+

Two circles with same center but different radii. Points in the smaller circle are "black", points only in the larger circle are "red".

+
+
plot(tgen("circle"))
+
+
+
+

+
+
+
+
+
+
+

Moons

+

Two interleaving half circles (“moons”).

+
+
plot(tgen("moons"))
+
+
+
+

+
+
+
+
+
+
+
+

Learners

+

We consider the following learners:

+
+
library("mlr3learners")
+
+learners <- list(
+  # k-nearest neighbours classifier
+  lrn("classif.kknn", id = "kkn", predict_type = "prob", k = 3),
+
+  # linear svm
+  lrn("classif.svm", id = "lin. svm", predict_type = "prob", kernel = "linear"),
+
+  # radial-basis function svm
+  lrn("classif.svm",
+    id = "rbf svm", predict_type = "prob", kernel = "radial",
+    gamma = 2, cost = 1, type = "C-classification"
+  ),
+
+  # naive bayes
+  lrn("classif.naive_bayes", id = "naive bayes", predict_type = "prob"),
+
+  # single decision tree
+  lrn("classif.rpart", id = "tree", predict_type = "prob", cp = 0, maxdepth = 5),
+
+  # random forest
+  lrn("classif.ranger", id = "random forest", predict_type = "prob")
+)
+
+

The hyperparameters are chosen in a way that the decision boundaries look “typical” for the respective classifier. Of course, with different hyperparameters, results may look very different.

+
+
+

Fitting the Models

+

To apply each learner on each task, we first build an exhaustive grid design of experiments with benchmark_grid() and then pass it to benchmark() to do the actual work. A simple holdout resampling is used here:

+
+
design <- benchmark_grid(
+  tasks = tasks,
+  learners = learners,
+  resamplings = rsmp("holdout")
+)
+
+bmr <- benchmark(design, store_models = TRUE)
+
+

A quick look into the performance values:

+
+
perf <- bmr$aggregate(msr("classif.acc"))[, c("task_id", "learner_id", "classif.acc")]
+perf
+
+
       task_id    learner_id classif.acc
+ 1:    xor_200           kkn   0.9402985
+ 2:    xor_200      lin. svm   0.5223881
+ 3:    xor_200       rbf svm   0.9701493
+ 4:    xor_200   naive bayes   0.4328358
+ 5:    xor_200          tree   0.9402985
+ 6:    xor_200 random forest   1.0000000
+ 7:  moons_200           kkn   1.0000000
+ 8:  moons_200      lin. svm   0.8805970
+ 9:  moons_200       rbf svm   1.0000000
+10:  moons_200   naive bayes   0.8955224
+11:  moons_200          tree   0.8955224
+12:  moons_200 random forest   0.9552239
+13: circle_200           kkn   0.8805970
+14: circle_200      lin. svm   0.4925373
+15: circle_200       rbf svm   0.8955224
+16: circle_200   naive bayes   0.7014925
+17: circle_200          tree   0.7462687
+18: circle_200 random forest   0.7761194
+
+
+
+
+

Plotting

+

To generate the plots, we iterate over the individual ResampleResult objects stored in the BenchmarkResult, and in each iteration we store the plot of the learner prediction generated by the mlr3viz package.

+
+
library("mlr3viz")
+
+n <- bmr$n_resample_results
+plots <- vector("list", n)
+for (i in seq_len(n)) {
+  rr <- bmr$resample_result(i)
+  plots[[i]] <- autoplot(rr, type = "prediction")
+}
+
+

We now have a list of plots. Each one can be printed individually:

+
+
print(plots[[1]])
+
+
+
+

+
+
+
+
+

Note that only observations from the test data is plotted as points.

+

To get a nice annotated overview, we arranged all plots together in a single pdf file. The number in the upper right is the respective accuracy on the test set.

+
+
pdf(file = "plot_learner_prediction.pdf", width = 20, height = 6)
+ntasks <- length(tasks)
+nlearners <- length(learners)
+m <- msr("classif.acc")
+
+# for each plot
+for (i in seq_along(plots)) {
+  plots[[i]] <- plots[[i]] +
+    # remove legend
+    ggplot2::theme(legend.position = "none") +
+    # remove labs
+    ggplot2::xlab("") + ggplot2::ylab("") +
+    # add accuracy score as annotation
+    ggplot2::annotate("text",
+      label = sprintf("%.2f", bmr$resample_result(i)$aggregate(m)),
+      x = Inf, y = Inf, vjust = 2, hjust = 1.5
+    )
+}
+
+# for each plot of the first column
+for (i in seq_len(ntasks)) {
+  ii <- (i - 1) * nlearners + 1L
+  plots[[ii]] <- plots[[ii]] + ggplot2::ylab(sub("_[0-9]+$", "", tasks[[i]]$id))
+}
+
+# for each plot of the first row
+for (i in seq_len(nlearners)) {
+  plots[[i]] <- plots[[i]] + ggplot2::ggtitle(learners[[i]]$id)
+}
+
+gridExtra::grid.arrange(grobs = plots, nrow = length(tasks))
+dev.off()
+
+

As you can see, the decision boundaries look very different. Some are linear, others are parallel to the axis, and yet others are highly non-linear. The boundaries are partly very smooth with a slow transition of probabilities, others are very abrupt. All these properties are important during model selection, and should be considered for your problem at hand.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/2020-08-14-comparison-of-decision-boundaries-004-1.png b/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/2020-08-14-comparison-of-decision-boundaries-004-1.png new file mode 100644 index 00000000..6f923c8d Binary files /dev/null and b/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/2020-08-14-comparison-of-decision-boundaries-004-1.png differ diff --git a/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/2020-08-14-comparison-of-decision-boundaries-005-1.png b/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/2020-08-14-comparison-of-decision-boundaries-005-1.png new file mode 100644 index 00000000..3cf6d139 Binary files /dev/null and b/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/2020-08-14-comparison-of-decision-boundaries-005-1.png differ diff --git a/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/2020-08-14-comparison-of-decision-boundaries-006-1.png b/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/2020-08-14-comparison-of-decision-boundaries-006-1.png new file mode 100644 index 00000000..4df3f452 Binary files /dev/null and b/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/2020-08-14-comparison-of-decision-boundaries-006-1.png differ diff --git a/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/2020-08-14-comparison-of-decision-boundaries-011-1.png b/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/2020-08-14-comparison-of-decision-boundaries-011-1.png new file mode 100644 index 00000000..5c0dacda Binary files /dev/null and b/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/2020-08-14-comparison-of-decision-boundaries-011-1.png differ diff --git a/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/comparison-of-decision-boundaries-005-1.png b/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/comparison-of-decision-boundaries-005-1.png new file mode 100644 index 00000000..6f923c8d Binary files /dev/null and b/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/comparison-of-decision-boundaries-005-1.png differ diff --git a/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/comparison-of-decision-boundaries-006-1.png b/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/comparison-of-decision-boundaries-006-1.png new file mode 100644 index 00000000..3cf6d139 Binary files /dev/null and b/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/comparison-of-decision-boundaries-006-1.png differ diff --git a/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/comparison-of-decision-boundaries-007-1.png b/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/comparison-of-decision-boundaries-007-1.png new file mode 100644 index 00000000..4df3f452 Binary files /dev/null and b/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/comparison-of-decision-boundaries-007-1.png differ diff --git a/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/comparison-of-decision-boundaries-013-1.png b/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/comparison-of-decision-boundaries-013-1.png new file mode 100644 index 00000000..19543087 Binary files /dev/null and b/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index_files/figure-html/comparison-of-decision-boundaries-013-1.png differ diff --git a/gallery/basic/2021-01-20-keras/index.html b/gallery/basic/2021-01-20-keras/index.html new file mode 100644 index 00000000..a7f126bf --- /dev/null +++ b/gallery/basic/2021-01-20-keras/index.html @@ -0,0 +1,754 @@ + + + + + + + + + + + + +Introduction to mlr3keras - Boston Housing – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Introduction to mlr3keras - Boston Housing

+
+
+

This use case provides an introduction to mlr3keras via the boston housing dataset.

+
+
+ +
+ + +
+ +
+
Author
+
+

Florian Pfisterer

+
+
+ +
+
Published
+
+

September 11, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +

The following article describes how to fit a Neural Network learner to the boston_housing dataset. This article is part of the mlr3keras vignette. For additional information or help on mlr3keras, please consult the mlr3keras website.

+ + + + + +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/basic/2021-01-20-keras/keras_logo.png b/gallery/basic/2021-01-20-keras/keras_logo.png new file mode 100644 index 00000000..b31c97b6 Binary files /dev/null and b/gallery/basic/2021-01-20-keras/keras_logo.png differ diff --git a/gallery/optimization/2020-09-14-mlr3fselect-basic/index.html b/gallery/optimization/2020-09-14-mlr3fselect-basic/index.html new file mode 100644 index 00000000..732e25b6 --- /dev/null +++ b/gallery/optimization/2020-09-14-mlr3fselect-basic/index.html @@ -0,0 +1,1153 @@ + + + + + + + + + + + + +Feature Selection on the Titanic Data Set – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Feature Selection on the Titanic Data Set

+
+
+

Run a feature selection with different algorithms and use nested resampling.

+
+
+
+
+ + +
+ +
+
Author
+
+

Marc Becker

+
+
+ +
+
Published
+
+

January 8, 2021

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Introduction

+

In this tutorial, we introduce the mlr3fselect package by comparing feature selection methods on the Titanic disaster data set. The objective of feature selection is to enhance the interpretability of models, speed up the learning process and increase the predictive performance.

+

We load the mlr3verse package which pulls in the most important packages for this example.

+
+
library(mlr3verse)
+library(mlr3fselect)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+
+
+

Titanic Data Set

+

The Titanic data set contains data for 887 Titanic passengers, including whether they survived when the Titanic sank. Our goal will be to predict the survival of the Titanic passengers.

+

After loading the data set from the mlr3data package, we impute the missing age values with the median age of the passengers, set missing embarked values to "s" and remove character features. We could use feature engineering to create new features from the character features, however we want to focus on feature selection in this tutorial.

+

In addition to the survived column, the reduced data set contains the following attributes for each passenger:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FeatureDescription
ageAge
sexSex
sib_spNumber of siblings / spouses aboard
parchNumber of parents / children aboard
fareAmount paid for the ticket
pc_classPassenger class
embarkedPort of embarkation
+
+
library(mlr3data)
+
+data("titanic", package = "mlr3data")
+titanic$age[is.na(titanic$age)] = median(titanic$age, na.rm = TRUE)
+titanic$embarked[is.na(titanic$embarked)] = "S"
+titanic$ticket = NULL
+titanic$name = NULL
+titanic$cabin = NULL
+titanic = titanic[!is.na(titanic$survived),]
+
+

We construct a binary classification task.

+
+
task = as_task_classif(titanic, target = "survived", positive = "yes")
+
+
+
+

Model

+

We use the logistic regression learner provided by the mlr3learners package.

+
+
library(mlr3learners)
+
+learner = lrn("classif.log_reg")
+
+

To evaluate the predictive performance, we choose a 3-fold cross-validation and the classification error as the measure.

+
+
resampling = rsmp("cv", folds = 3)
+measure = msr("classif.ce")
+
+resampling$instantiate(task)
+
+
+
+

Classes

+

The FSelectInstanceSingleCrit class specifies a general feature selection scenario. It includes the ObjectiveFSelect object that encodes the black box objective function which is optimized by a feature selection algorithm. The evaluated feature sets are stored in an ArchiveFSelect object. The archive provides a method for querying the best performing feature set.

+

The Terminator classes determine when to stop the feature selection. In this example we choose a terminator that stops the feature selection after 10 seconds. The sugar functions trm() and trms() can be used to retrieve terminators from the mlr_terminators dictionary.

+
+
terminator = trm("run_time", secs = 10)
+FSelectInstanceSingleCrit$new(
+  task = task,
+  learner = learner,
+  resampling = resampling,
+  measure = measure,
+  terminator = terminator)
+
+
<FSelectInstanceSingleCrit>
+* State:  Not optimized
+* Objective: <ObjectiveFSelect:classif.log_reg_on_titanic>
+* Terminator: <TerminatorRunTime>
+
+
+

The FSelector subclasses describe the feature selection strategy. The sugar function fs() can be used to retrieve feature selection algorithms from the mlr_fselectors dictionary.

+
+
mlr_fselectors
+
+
<DictionaryFSelector> with 8 stored values
+Keys: design_points, exhaustive_search, genetic_search, random_search, rfe, rfecv, sequential,
+  shadow_variable_search
+
+
+
+ +
+

Sequential forward selection

+

We try sequential forward selection. We chose TerminatorStagnation that stops the feature selection if the predictive performance does not increase anymore.

+
+
terminator = trm("stagnation", iters = 5)
+instance = FSelectInstanceSingleCrit$new(
+  task = task,
+  learner = learner,
+  resampling = resampling,
+  measure = measure,
+  terminator = terminator)
+
+fselector = fs("sequential")
+fselector$optimize(instance)
+
+
     age embarked  fare parch pclass  sex sib_sp                features classif.ce
+1: FALSE    FALSE FALSE  TRUE   TRUE TRUE   TRUE parch,pclass,sex,sib_sp  0.1964085
+
+
+

The FSelectorSequential object has a special method for displaying the optimization path of the sequential feature selection.

+
+
fselector$optimization_path(instance)
+
+
    age embarked  fare parch pclass   sex sib_sp classif.ce batch_nr
+1: TRUE    FALSE FALSE FALSE  FALSE FALSE  FALSE  0.3838384        1
+2: TRUE    FALSE FALSE FALSE  FALSE  TRUE  FALSE  0.2132435        2
+3: TRUE    FALSE FALSE FALSE  FALSE  TRUE   TRUE  0.2087542        3
+4: TRUE    FALSE FALSE FALSE   TRUE  TRUE   TRUE  0.2143659        4
+5: TRUE    FALSE FALSE  TRUE   TRUE  TRUE   TRUE  0.2065095        5
+6: TRUE    FALSE  TRUE  TRUE   TRUE  TRUE   TRUE  0.2020202        6
+
+
+
+
+

Recursive feature elimination

+

Recursive feature elimination utilizes the $importance() method of learners. In each iteration the feature(s) with the lowest importance score is dropped. We choose the non-recursive algorithm (recursive = FALSE) which calculates the feature importance once on the complete feature set. The recursive version (recursive = TRUE) recomputes the feature importance on the reduced feature set in every iteration.

+
+
learner = lrn("classif.ranger", importance = "impurity")
+terminator = trm("none")
+instance = FSelectInstanceSingleCrit$new(
+  task = task,
+  learner = learner,
+  resampling = resampling,
+  measure = measure,
+  terminator = terminator,
+  store_models = TRUE)
+
+fselector = fs("rfe", recursive = FALSE)
+fselector$optimize(instance)
+
+
    age embarked fare parch pclass  sex sib_sp                               features classif.ce
+1: TRUE     TRUE TRUE  TRUE   TRUE TRUE   TRUE age,embarked,fare,parch,pclass,sex,...  0.1694725
+
+
+

We access the results.

+
+
as.data.table(instance$archive, exclude_columns = c("runtime_learners", "timestamp", "batch_nr", "resample_result", "uhash"))
+
+
    age embarked fare parch pclass  sex sib_sp classif.ce warnings errors      importance
+1: TRUE     TRUE TRUE  TRUE   TRUE TRUE   TRUE  0.1694725        0      0 7,6,5,4,3,2,...
+2: TRUE    FALSE TRUE FALSE  FALSE TRUE  FALSE  0.2132435        0      0           7,6,5
+                                 features
+1: age,embarked,fare,parch,pclass,sex,...
+2:                           age,fare,sex
+
+
+
+
+

Nested resampling

+

It is a common mistake to report the predictive performance estimated on resampling sets during the feature selection as the performance that can be expected from the combined feature selection and model training. The repeated evaluation of the model might leak information about the test sets into the model and thus leads to over-fitting and over-optimistic performance results. Nested resampling uses an outer and inner resampling to separate the feature selection from the performance estimation of the model. We can use the AutoFSelector class for running nested resampling. The AutoFSelector essentially combines a given Learner and feature selection method into a Learner with internal automatic feature selection. The inner resampling loop that is used to determine the best feature set is conducted internally each time the AutoFSelector Learner object is trained.

+
+
resampling_inner = rsmp("cv", folds = 5)
+measure = msr("classif.ce")
+
+at = AutoFSelector$new(
+  learner = learner,
+  resampling = resampling_inner,
+  measure = measure,
+  terminator = terminator,
+  fselect = fs("sequential"),
+  store_models = TRUE)
+
+

We put the AutoFSelector into a resample() call to get the outer resampling loop.

+
+
resampling_outer = rsmp("cv", folds = 3)
+
+rr = resample(task, at, resampling_outer, store_models = TRUE)
+
+

The aggregated performance of all outer resampling iterations is the unbiased predictive performance we can expected from the logistic regression model with an optimized feature set found by sequential selection.

+
+
rr$aggregate()
+
+
classif.ce 
+ 0.1829405 
+
+
+

We check whether the feature sets that were selected in the inner resampling are stable. The selected feature sets should not differ too much. We might observe unstable models in this example because the small data set and the low number of resampling iterations might introduces too much randomness. Usually, we aim for the selection of similar feature sets for all outer training sets.

+
+
extract_inner_fselect_results(rr)
+
+
+
+
+ +
+
+

Next, we want to compare the predictive performances estimated on the outer resampling to the inner resampling. Significantly lower predictive performances on the outer resampling indicate that the models with the optimized feature sets overfit the data.

+
+
rr$score()[, .(iteration, task_id, learner_id, resampling_id, classif.ce)]
+
+
   iteration task_id               learner_id resampling_id classif.ce
+1:         1 titanic classif.ranger.fselector            cv  0.1515152
+2:         2 titanic classif.ranger.fselector            cv  0.1952862
+3:         3 titanic classif.ranger.fselector            cv  0.2020202
+
+
+

The archives of the AutoFSelectors gives us all evaluated feature sets with the associated predictive performances.

+
+
extract_inner_fselect_archives(rr)
+
+
+
+
+ +
+
+
+
+

Shortcuts

+

Selecting a feature subset can be shortened by using the fselect()-shortcut.

+
+
instance = fselect(
+  tuner = tnr( "random_search",
+  task = tsk("iris"),
+  learner = lrn("classif.log_reg"),
+  resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce"),
+  term_evals = 10
+)
+
+

Applying nested resampling can be shortened by using the fselect_nested()-shortcut.

+
+
rr = fselect_nested(
+  tuner = tnr("random_search"),
+  task = tsk("iris"),
+  learner = lrn("classif.log_reg"),
+  inner_resampling = rsmp ("cv", folds = 3),
+  outer_resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce"),
+  term_evals = 10
+)
+
+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/optimization/2020-10-14-threshold-tuning/index.html b/gallery/optimization/2020-10-14-threshold-tuning/index.html new file mode 100644 index 00000000..7be7e8ce --- /dev/null +++ b/gallery/optimization/2020-10-14-threshold-tuning/index.html @@ -0,0 +1,1013 @@ + + + + + + + + + + + + +Threshold Tuning for Classification Tasks – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Threshold Tuning for Classification Tasks

+
+
+

Adjust the probability thresholds of classes.

+
+
+
+
+ + +
+ +
+
Author
+
+

Florian Pfisterer

+
+
+ +
+
Published
+
+

October 14, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Intro

+

Predicting probabilities in classification tasks allows us to adjust the probability thresholds required for assigning an observation to a certain class. This can lead to improved classification performance, especially for cases where we e.g. aim to balance off metrics such as false positive and false negative rates.

+

This is for example often done in ROC Analysis. The mlr3book also has a chapter on ROC Analysis) for the interested reader. This post does not focus on ROC analysis, but instead focusses on the general problem of adjusting classification thresholds for arbitrary metrics.

+

This post assumes some familiarity with the mlr3, and also the mlr3pipelines and mlr3tuning packages, as both are used during the post. The mlr3book contains more details on those two packages. This post is a more in-depth version of the article on threshold tuning in the mlr3book.

+
+
+

Prerequisites

+

We load the mlr3verse package which pulls in the most important packages for this example.

+
+
library(mlr3verse)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+
+
+

Thresholds: A short intro

+

In order to understand thresholds, we will quickly showcase the effect of setting different thresholds:

+

First we create a learner that predicts probabilities and use it to predict on holdout data, storing the prediction.

+
+
learner = lrn("classif.rpart", predict_type = "prob")
+rr = resample(tsk("pima"), learner, rsmp("holdout"))
+prd = rr$prediction()
+prd
+
+
<PredictionClassif> for 256 observations:
+    row_ids truth response  prob.pos  prob.neg
+          4   neg      neg 0.1057692 0.8942308
+          6   neg      neg 0.0200000 0.9800000
+         10   pos      neg 0.1428571 0.8571429
+---                                           
+        764   neg      neg 0.2777778 0.7222222
+        766   neg      neg 0.0200000 0.9800000
+        767   pos      pos 0.8000000 0.2000000
+
+
+

If we now look at the confusion matrix, the off-diagonal elements are errors made by our model (false positives and false negatives) while on-diagol ements are where our model predicted correctly.

+
+
# Print confusion matrix
+prd$confusion
+
+
        truth
+response pos neg
+     pos  53  27
+     neg  37 139
+
+
# Print False Positives and False Negatives
+prd$score(list(msr("classif.fp"), msr("classif.fn")))
+
+
classif.fp classif.fn 
+        27         37 
+
+
+

By adjusting the classification threshold, in this case the probability required to predict the positive class, we can now trade off predicting more positive cases (first row) against predicting fewer negative cases (second row) or vice versa.

+
+
# Lower threshold: More positives
+prd$set_threshold(0.25)$confusion
+
+
        truth
+response pos neg
+     pos  78  71
+     neg  12  95
+
+
+
+
# Higher threshold: Fewer positives
+prd$set_threshold(0.75)$confusion
+
+
        truth
+response pos neg
+     pos  52  20
+     neg  38 146
+
+
+

This threshold value can now be adjusted optimally for a given measure, such as accuracy. How this can be done is discussed in the following section.

+
+
+

Adjusting thresholds: Two strategies

+

Currently mlr3pipelines offers two main strategies towards adjusting classification thresholds. We can either expose the thresholds as a hyperparameter of the Learner by using PipeOpThreshold. This allows us to tune the thresholds via an outside optimizer from mlr3tuning.

+

Alternatively, we can also use PipeOpTuneThreshold which automatically tunes the threshold after each learner fit.

+

In this blog-post, we’ll go through both strategies.

+
+
+

PipeOpThreshold

+

PipeOpThreshold can be put directly after a Learner.

+

A simple example would be:

+
+
gr = lrn("classif.rpart", predict_type = "prob") %>>% po("threshold")
+l = GraphLearner$new(gr)
+
+

Note, that predict_type = “prob” is required for po("threshold") to have any effect.

+

The thresholds are now exposed as a hyperparameter of the GraphLearner we created:

+
+
as.data.table(l$param_set)[, .(id, class, lower, upper, nlevels)]
+
+
                              id    class lower upper nlevels
+ 1:             classif.rpart.cp ParamDbl     0     1     Inf
+ 2:     classif.rpart.keep_model ParamLgl    NA    NA       2
+ 3:     classif.rpart.maxcompete ParamInt     0   Inf     Inf
+ 4:       classif.rpart.maxdepth ParamInt     1    30      30
+ 5:   classif.rpart.maxsurrogate ParamInt     0   Inf     Inf
+ 6:      classif.rpart.minbucket ParamInt     1   Inf     Inf
+ 7:       classif.rpart.minsplit ParamInt     1   Inf     Inf
+ 8: classif.rpart.surrogatestyle ParamInt     0     1       2
+ 9:   classif.rpart.usesurrogate ParamInt     0     2       3
+10:           classif.rpart.xval ParamInt     0   Inf     Inf
+11:         threshold.thresholds ParamUty    NA    NA     Inf
+
+
+

We can now tune those thresholds from the outside as follows:

+

Before tuning, we have to define which hyperparameters we want to tune over. In this example, we only tune over the thresholds parameter of the threshold PipeOp. you can easily imagine, that we can also jointly tune over additional hyperparameters, i.e. rpart’s cp parameter.

+

As the Task we aim to optimize for is a binary task, we can simply specify the threshold parameter:

+
+
search_space = ps(
+  threshold.thresholds = p_dbl(lower = 0, upper = 1)
+)
+
+

We now create a AutoTuner, which automatically tunes the supplied learner over the ParamSet we supplied above.

+
+
at = auto_tuner(
+  tuner = tnr("random_search"),
+  learner = l,
+  resampling = rsmp("cv", folds = 3L),
+  measure = msr("classif.ce"),
+  search_space = search_space,
+  term_evals = 5L,
+)
+
+at$train(tsk("german_credit"))
+
+

For multi-class Tasks, this is a little more complicated. We have to use a trafo to transform a set of ParamDbl into the desired format for threshold.thresholds: A named numeric vector containing the thresholds. This can be easily achieved via a trafo function:

+
+
search_space = ps(
+  versicolor = p_dbl(lower = 0, upper = 1),
+  setosa = p_dbl(lower = 0, upper = 1),
+  virginica = p_dbl(lower = 0, upper = 1),
+  .extra_trafo = function(x, param_set) {
+    list(threshold.thresholds = mlr3misc::map_dbl(x, identity))
+  }
+)
+
+

Inside the .exta_trafo, we simply collect all set params into a named vector via map_dbl and store it in the threshold.thresholds slot expected by the learner.

+

Again, we create a AutoTuner, which automatically tunes the supplied learner over the ParamSet we supplied above.

+
+
at_2 = auto_tuner(
+  tuner = tnr("random_search"),
+  learner = l,
+  resampling = rsmp("cv", folds = 3L),
+  measure = msr("classif.ce"),
+  search_space = search_space,
+  term_evals = 5L,
+)
+
+at_2$train(tsk("iris"))
+
+

One drawback of this strategy is, that this requires us to fit a new model for each new threshold setting. While setting a threshold and computing performance is relatively cheap, fitting the learner is often more computationally demanding. A better strategy is therefore often to optimize the thresholds separately after each model fit.

+
+
+

PipeOpTuneThreshold

+

PipeOpTuneThreshold on the other hand works together with PipeOpLearnerCV. It directly optimizes the cross-validated predictions made by this PipeOp.

+

A simple example would be:

+
+
gr = po("learner_cv", lrn("classif.rpart", predict_type = "prob")) %>>%
+  po("tunethreshold")
+l2 = GraphLearner$new(gr)
+
+

Note, that predict_type = “prob” is required for po("tunethreshold") to have any effect. Additionally, note that this time no threshold parameter is exposed, it is automatically tuned internally.

+
+
as.data.table(l2$param_set)[, .(id, class, lower, upper, nlevels)]
+
+
                                        id    class lower upper nlevels
+ 1:        classif.rpart.resampling.method ParamFct    NA    NA       2
+ 2:         classif.rpart.resampling.folds ParamInt     2   Inf     Inf
+ 3: classif.rpart.resampling.keep_response ParamLgl    NA    NA       2
+ 4:                       classif.rpart.cp ParamDbl     0     1     Inf
+ 5:               classif.rpart.keep_model ParamLgl    NA    NA       2
+ 6:               classif.rpart.maxcompete ParamInt     0   Inf     Inf
+ 7:                 classif.rpart.maxdepth ParamInt     1    30      30
+ 8:             classif.rpart.maxsurrogate ParamInt     0   Inf     Inf
+ 9:                classif.rpart.minbucket ParamInt     1   Inf     Inf
+10:                 classif.rpart.minsplit ParamInt     1   Inf     Inf
+11:           classif.rpart.surrogatestyle ParamInt     0     1       2
+12:             classif.rpart.usesurrogate ParamInt     0     2       3
+13:                     classif.rpart.xval ParamInt     0   Inf     Inf
+14:           classif.rpart.affect_columns ParamUty    NA    NA     Inf
+15:                  tunethreshold.measure ParamUty    NA    NA     Inf
+16:                tunethreshold.optimizer ParamUty    NA    NA     Inf
+17:                tunethreshold.log_level ParamUty    NA    NA     Inf
+
+
+

If we now use the GraphLearner, it automatically adjusts the thresholds during prediction.

+

Note that we can set ResamplingInsample as a resampling strategy for PipeOpLearnerCV in order to evaluate predictions on the “training” data. This is generally not advised, as it might lead to over-fitting on the thresholds but can significantly reduce runtime.

+

Finally, we can compare no threshold tuning to the tunethreshold approach:

+
+

Comparison of the approaches

+
+
bmr = benchmark(benchmark_grid(
+  learners = list(no_tuning = lrn("classif.rpart"), internal = l2),
+  tasks = tsk("german_credit"),
+  rsmp("cv", folds = 3L)
+))
+
+
+
bmr$aggregate(list(msr("classif.ce"), msr("classif.fnr")))
+
+
   nr       task_id                  learner_id resampling_id iters classif.ce classif.fnr
+1:  1 german_credit               classif.rpart            cv     3  0.2760095  0.12723983
+2:  2 german_credit classif.rpart.tunethreshold            cv     3  0.2879916  0.04485325
+Hidden columns: resample_result
+
+
+ + +
+
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/optimization/2021-01-19-integer-hyperparameters-in-tuners-for-real-valued-search-spaces/index.html b/gallery/optimization/2021-01-19-integer-hyperparameters-in-tuners-for-real-valued-search-spaces/index.html new file mode 100644 index 00000000..937d47cc --- /dev/null +++ b/gallery/optimization/2021-01-19-integer-hyperparameters-in-tuners-for-real-valued-search-spaces/index.html @@ -0,0 +1,900 @@ + + + + + + + + + + + + +Integer Hyperparameters in Tuners for Real-valued Search Spaces – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Integer Hyperparameters in Tuners for Real-valued Search Spaces

+
+
+

Optimize integer hyperparameters with tuners that can only propose real numbers.

+
+
+
+
+ + +
+ +
+
Author
+
+

Marc Becker

+
+
+ +
+
Published
+
+

January 19, 2021

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Introduction

+

Tuner for real-valued search spaces are not able to tune on integer hyperparameters. However, it is possible to round the real values proposed by a Tuner to integers before passing them to the learner in the evaluation. We show how to apply a parameter transformation to a ParamSet and use this set in the tuning process.

+

We load the mlr3verse package which pulls in the most important packages for this example.

+
+
library(mlr3verse)
+
+
Loading required package: mlr3
+
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+
+
+

Task and Learner

+

In this example, we use the k-Nearest-Neighbor classification learner. We want to tune the integer-valued hyperparameter k which defines the numbers of neighbors.

+
+
learner = lrn("classif.kknn")
+print(learner$param_set$params$k)
+
+
   id    class lower upper levels default
+1:  k ParamInt     1   Inf              7
+
+
+
+
+

Tuning

+

We choose generalized simulated annealing as tuning strategy. The param_classes field of TunerGenSA states that the tuner only supports real-valued (ParamDbl) hyperparameter tuning.

+
+
print(tnr("gensa"))
+
+
<TunerGenSA>: Generalized Simulated Annealing
+* Parameters: trace.mat=FALSE, smooth=FALSE
+* Parameter classes: ParamDbl
+* Properties: single-crit
+* Packages: mlr3tuning, bbotk, GenSA
+
+
+

To get integer-valued hyperparameter values for k, we construct a search space with a transformation function. The as.integer() function converts any real valued number to an integer by removing the decimal places.

+
+
search_space = ps(
+  k = p_dbl(lower = 3, upper = 7.99, trafo = as.integer)
+)
+
+

We start the tuning and compare the results of the search space to the results in the space of the learners hyperparameter set.

+
+
instance = tune(
+  tuner = tnr("gensa"),
+  task = tsk("iris"),
+  learner = learner,
+  resampling = rsmp("holdout"),
+  measure = msr("classif.ce"),
+  term_evals = 20,
+  search_space = search_space)
+
+
Warning in optim(theta.old, fun, gradient, control = control, method = method, : one-dimensional optimization by Nelder-Mead is unreliable:
+use "Brent" or optimize() directly
+
+
+

The optimal k is still a real number in the search space.

+
+
instance$result_x_search_space
+
+
         k
+1: 3.82686
+
+
+

However, in the learners hyperparameters space, k is an integer value.

+
+
instance$result_x_domain
+
+
$k
+[1] 3
+
+
+

The archive shows us that for all real-valued k proposed by GenSA, an integer-valued k in the learner hyperparameter space (x_domain_k) was created.

+
+
as.data.table(instance$archive)[, .(k, classif.ce, x_domain_k)]
+
+
           k classif.ce x_domain_k
+ 1: 3.826860       0.06          3
+ 2: 5.996323       0.06          5
+ 3: 5.941332       0.06          5
+ 4: 3.826860       0.06          3
+ 5: 3.826860       0.06          3
+ 6: 3.826860       0.06          3
+ 7: 4.209546       0.06          4
+ 8: 3.444174       0.06          3
+ 9: 4.018203       0.06          4
+10: 3.635517       0.06          3
+11: 3.922532       0.06          3
+12: 3.731189       0.06          3
+13: 3.874696       0.06          3
+14: 3.779024       0.06          3
+15: 3.850778       0.06          3
+16: 3.802942       0.06          3
+17: 3.838819       0.06          3
+18: 3.814901       0.06          3
+19: 3.832840       0.06          3
+20: 3.820881       0.06          3
+
+
+

Internally, TunerGenSA was given the parameter types of the search space and therefore suggested real numbers for k. Before the performance of the different k values was evaluated, the transformation function of the search_space parameter set was called and k was transformed to an integer value.

+

Note that the tuner is not aware of the transformation. This has two problematic consequences: First, the tuner might propose different real valued configurations that after rounding end up to be already evaluated configurations and we end up with re-evaluating the same hyperparameter configuration. This is only problematic, if we only optimze integer parameters. Second, the rounding introduces discontinuities which can be problematic for some tuners.

+

We successfully tuned a integer-valued hyperparameter with TunerGenSA which is only suitable for an real-valued search space. This technique is not limited to tuning problems. Optimizer in bbotk can be also used in the same way to produce points with integer parameters.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/optimization/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/index.html b/gallery/optimization/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/index.html new file mode 100644 index 00000000..71f5afb2 --- /dev/null +++ b/gallery/optimization/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/index.html @@ -0,0 +1,1443 @@ + + + + + + + + + + + + + + + + + +Practical Tuning Series - Tune a Support Vector Machine – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Practical Tuning Series - Tune a Support Vector Machine

+
+
+

Optimize the hyperparameters of a support vector machine.

+
+
+
+
+ + +
+ +
+
Authors
+
+

Marc Becker

+

Theresa Ullmann

+

Michel Lang

+

Bernd Bischl

+

Jakob Richter

+

Martin Binder

+
+
+ +
+
Published
+
+

March 9, 2021

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+
requireNamespace("DiceKriging")
+
+
Loading required namespace: DiceKriging
+
+
+
+

Scope

+

This is the first part of the practical tuning series. The other parts can be found here:

+ +

In this post, we demonstrate how to optimize the hyperparameters of a support vector machine (SVM). We are using the mlr3 machine learning framework with the mlr3tuning extension package.

+

First, we start by showing the basic building blocks of mlr3tuning and tune the cost and gamma hyperparameters of an SVM with a radial basis function on the Iris data set. After that, we use transformations to tune the both hyperparameters on the logarithmic scale. Next, we explain the importance of dependencies to tune hyperparameters like degree which are dependent on the choice of kernel. After that, we fit an SVM with optimized hyperparameters on the full dataset. Finally, nested resampling is used to compute an unbiased performance estimate of our tuned SVM.

+
+
+

Prerequisites

+

We load the mlr3verse package which pulls in the most important packages for this example.

+
+
library(mlr3verse)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented. The lgr package is used for logging in all mlr3 packages. The mlr3 logger prints the logging messages from the base package, whereas the bbotk logger is responsible for logging messages from the optimization packages (e.g. mlr3tuning ).

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+

In the example, we use the Iris data set which classifies 150 flowers in three species of Iris. The flowers are characterized by sepal length and width and petal length and width. The Iris data set allows us to quickly fit models to it. However, the influence of hyperparameter tuning on the predictive performance might be minor. Other data sets might give more meaningful tuning results.

+
+
# retrieve the task from mlr3
+task = tsk("iris")
+
+# generate a quick textual overview using the skimr package
+skimr::skim(task$data())
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Data summary
Nametask$data()
Number of rows150
Number of columns5
KeyNULL
_______________________
Column type frequency:
factor1
numeric4
________________________
Group variablesNone
+

Variable type: factor

+ ++++++++ + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_rateorderedn_uniquetop_counts
Species01FALSE3set: 50, ver: 50, vir: 50
+

Variable type: numeric

+ +++++++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_ratemeansdp0p25p50p75p100hist
Petal.Length013.761.771.01.64.355.16.9▇▁▆▇▂
Petal.Width011.200.760.10.31.301.82.5▇▁▇▅▃
Sepal.Length015.840.834.35.15.806.47.9▆▇▇▅▂
Sepal.Width013.060.442.02.83.003.34.4▁▆▇▂▁
+
+
+

We choose the support vector machine implementation from the e1071 package (which is based on LIBSVM) and use it as a classification machine by setting type to "C-classification".

+
+
learner = lrn("classif.svm", type = "C-classification", kernel = "radial")
+
+
+
+

Tuning Search Space

+

For tuning, it is important to create a search space that defines the type and range of the hyperparameters. A learner stores all information about its hyperparameters in the slot $param_set. Not all parameters are tunable. We have to choose a subset of the hyperparameters we want to tune.

+
+
as.data.table(learner$param_set)[, .(id, class, lower, upper, nlevels)]
+
+

We use the to_tune() function to define the range over which the hyperparameter should be tuned. We opt for the cost and gamma hyperparameters of the radial kernel and set the tuning ranges with lower and upper bounds.

+
+
learner$param_set$values$cost = to_tune(0.1, 10)
+learner$param_set$values$gamma = to_tune(0, 5)
+
+
+
+

Tuning

+

We specify how to evaluate the performance of the different hyperparameter configurations. For this, we choose 3-fold cross validation as the resampling strategy and the classification error as the performance measure.

+
+
resampling = rsmp("cv", folds = 3)
+measure = msr("classif.ce")
+
+

Usually, we have to select a budget for the tuning. This is done by choosing a Terminator, which stops the tuning e.g. after a performance level is reached or after a given time. However, some tuners like grid search terminate themselves. In this case, we choose a terminator that never stops and the tuning is not stopped before all grid points are evaluated.

+
+
terminator = trm("none")
+
+

At this point, we can construct a TuningInstanceSingleCrit that describes the tuning problem.

+
+
instance = TuningInstanceSingleCrit$new(
+  task = task,
+  learner = learner,
+  resampling = resampling,
+  measure = measure,
+  terminator = terminator
+)
+
+print(instance)
+
+
<TuningInstanceSingleCrit>
+* State:  Not optimized
+* Objective: <ObjectiveTuning:classif.svm_on_iris>
+* Search Space:
+      id    class lower upper nlevels
+1:  cost ParamDbl   0.1    10     Inf
+2: gamma ParamDbl   0.0     5     Inf
+* Terminator: <TerminatorNone>
+
+
+

Finally, we have to choose a Tuner. Grid Search discretizes numeric parameters into a given resolution and constructs a grid from the Cartesian product of these sets. Categorical parameters produce a grid over all levels specified in the search space. In this example, we only use a resolution of 5 to keep the runtime low. Usually, a higher resolution is used to create a denser grid.

+
+
tuner = tnr("grid_search", resolution = 5)
+
+print(tuner)
+
+
<TunerGridSearch>: Grid Search
+* Parameters: resolution=5, batch_size=1
+* Parameter classes: ParamLgl, ParamInt, ParamDbl, ParamFct
+* Properties: dependencies, single-crit, multi-crit
+* Packages: mlr3tuning
+
+
+

We can preview the proposed configurations by using generate_design_grid(). This function is internally executed by TunerGridSearch.

+
+
generate_design_grid(learner$param_set$search_space(), resolution = 5)
+
+
<Design> with 25 rows:
+      cost gamma
+ 1:  0.100  0.00
+ 2:  0.100  1.25
+ 3:  0.100  2.50
+ 4:  0.100  3.75
+ 5:  0.100  5.00
+ 6:  2.575  0.00
+ 7:  2.575  1.25
+ 8:  2.575  2.50
+ 9:  2.575  3.75
+10:  2.575  5.00
+11:  5.050  0.00
+12:  5.050  1.25
+13:  5.050  2.50
+14:  5.050  3.75
+15:  5.050  5.00
+16:  7.525  0.00
+17:  7.525  1.25
+18:  7.525  2.50
+19:  7.525  3.75
+20:  7.525  5.00
+21: 10.000  0.00
+22: 10.000  1.25
+23: 10.000  2.50
+24: 10.000  3.75
+25: 10.000  5.00
+      cost gamma
+
+
+

We trigger the tuning by passing the TuningInstanceSingleCrit to the $optimize() method of the Tuner. The instance is modified in-place.

+
+
tuner$optimize(instance)
+
+
   cost gamma learner_param_vals  x_domain classif.ce
+1: 5.05  1.25          <list[4]> <list[2]>       0.06
+
+
+

We plot the performances depending on the evaluated cost and gamma values.

+
+
autoplot(instance, type = "surface", cols_x = c("cost", "gamma"),
+  learner = lrn("regr.km"))
+
+
+
+
+
+

+
+
+
+
+

The points mark the evaluated cost and gamma values. We should not infer the performance of new values from the heatmap since it is only an interpolation. However, we can see the general interaction between the hyperparameters.

+

Tuning a learner can be shortened by using the tune()-shortcut.

+
+
learner = lrn("classif.svm", type = "C-classification", kernel = "radial")
+learner$param_set$values$cost = to_tune(0.1, 10)
+learner$param_set$values$gamma = to_tune(0, 5)
+
+instance = tune(
+  tuner = tnr("grid_search", resolution = 5),
+  task = tsk("iris"),
+  learner = learner,
+  resampling = rsmp ("holdout"),
+  measure = msr("classif.ce")
+)
+
+
+
+

Transformation

+

Next, we want to tune the cost and gamma hyperparameter more efficiently. It is recommended to tune cost and gamma on the logarithmic scale (Hsu, Chang, and Lin 2003). The log transformation emphasizes smaller cost and gamma values but also creates large values. Therefore, we use a log transformation to emphasize this region of the search space with a denser grid.

+

Generally speaking, transformations can be used to convert hyperparameters to a new scale. These transformations are applied before the proposed configuration is passed to the Learner. We can directly define the transformation in the to_tune() function. The lower and upper bound is set on the original scale.

+
+
learner = lrn("classif.svm", type = "C-classification", kernel = "radial")
+
+# tune from 2^-15 to 2^15 on a log scale
+learner$param_set$values$cost = to_tune(p_dbl(-15, 15, trafo = function(x) 2^x))
+
+# tune from 2^-15 to 2^5 on a log scale
+learner$param_set$values$gamma = to_tune(p_dbl(-15, 5, trafo = function(x) 2^x))
+
+

Transformations to the log scale are the ones most commonly used. We can use a shortcut for this transformation. The lower and upper bound is set on the transformed scale.

+
+
learner$param_set$values$cost = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))
+learner$param_set$values$gamma = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))
+
+

We use the tune()-shortcut to run the tuning.

+
+
instance = tune(
+  tuner = tnr("grid_search", resolution = 5),
+  task = task,
+  learner = learner,
+  resampling = resampling,
+  measure = measure
+)
+
+

The hyperparameter values after the transformation are stored in the x_domain column as lists. We can expand these lists into multiple columns by using as.data.table(). The hyperparameter names are prefixed by x_domain.

+
+
as.data.table(instance$archive)[, .(cost, gamma, x_domain_cost, x_domain_gamma)]
+
+
          cost      gamma x_domain_cost x_domain_gamma
+ 1:  -5.756463 -11.512925  3.162278e-03   1.000000e-05
+ 2:   0.000000  11.512925  1.000000e+00   1.000000e+05
+ 3: -11.512925  11.512925  1.000000e-05   1.000000e+05
+ 4:  11.512925   5.756463  1.000000e+05   3.162278e+02
+ 5: -11.512925   0.000000  1.000000e-05   1.000000e+00
+ 6:  11.512925  -5.756463  1.000000e+05   3.162278e-03
+ 7:  11.512925   0.000000  1.000000e+05   1.000000e+00
+ 8: -11.512925   5.756463  1.000000e-05   3.162278e+02
+ 9:   0.000000   0.000000  1.000000e+00   1.000000e+00
+10:   5.756463   0.000000  3.162278e+02   1.000000e+00
+11:   0.000000  -5.756463  1.000000e+00   3.162278e-03
+12:   0.000000 -11.512925  1.000000e+00   1.000000e-05
+13:  -5.756463  -5.756463  3.162278e-03   3.162278e-03
+14:  11.512925 -11.512925  1.000000e+05   1.000000e-05
+15:   5.756463  11.512925  3.162278e+02   1.000000e+05
+16:   0.000000   5.756463  1.000000e+00   3.162278e+02
+17:  -5.756463   0.000000  3.162278e-03   1.000000e+00
+18:   5.756463 -11.512925  3.162278e+02   1.000000e-05
+19:  -5.756463  11.512925  3.162278e-03   1.000000e+05
+20:  11.512925  11.512925  1.000000e+05   1.000000e+05
+21:   5.756463  -5.756463  3.162278e+02   3.162278e-03
+22: -11.512925 -11.512925  1.000000e-05   1.000000e-05
+23: -11.512925  -5.756463  1.000000e-05   3.162278e-03
+24:   5.756463   5.756463  3.162278e+02   3.162278e+02
+25:  -5.756463   5.756463  3.162278e-03   3.162278e+02
+          cost      gamma x_domain_cost x_domain_gamma
+
+
+

We plot the performances depending on the evaluated cost and gamma values.

+
+
library(ggplot2)
+library(scales)
+autoplot(instance, type = "points", cols_x = c("x_domain_cost", "x_domain_gamma")) +
+  scale_x_continuous(
+    trans = log2_trans(),
+    breaks = trans_breaks("log10", function(x) 10^x),
+    labels = trans_format("log10", math_format(10^.x))) +
+  scale_y_continuous(
+    trans = log2_trans(),
+    breaks = trans_breaks("log10", function(x) 10^x),
+    labels = trans_format("log10", math_format(10^.x)))
+
+
+
+

+
+
+
+
+
+
+

Dependencies

+

Dependencies ensure that certain parameters are only proposed depending on values of other hyperparameters. We want to tune the degree hyperparameter that is only needed for the polynomial kernel.

+
+
learner = lrn("classif.svm", type = "C-classification")
+
+learner$param_set$values$cost = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))
+learner$param_set$values$gamma = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))
+
+learner$param_set$values$kernel = to_tune(c("polynomial", "radial"))
+learner$param_set$values$degree = to_tune(1, 4)
+
+

The dependencies are already stored in the learner parameter set.

+
+
learner$param_set$deps
+
+
       id     on           cond
+1:   cost   type <CondEqual[9]>
+2:     nu   type <CondEqual[9]>
+3: degree kernel <CondEqual[9]>
+4:  coef0 kernel <CondAnyOf[9]>
+5:  gamma kernel <CondAnyOf[9]>
+
+
+

The gamma hyperparameter depends on the kernel being polynomial, radial or sigmoid

+
+
learner$param_set$deps$cond[[5]]
+
+
CondAnyOf: x ∈ {polynomial, radial, sigmoid}
+
+
+

whereas the degree hyperparameter is solely used by the polynomial kernel.

+
+
learner$param_set$deps$cond[[3]]
+
+
CondEqual: x = polynomial
+
+
+

We preview the grid to show the effect of the dependencies.

+
+
generate_design_grid(learner$param_set$search_space(), resolution = 2)
+
+
<Design> with 12 rows:
+         cost     gamma     kernel degree
+ 1: -11.51293 -11.51293 polynomial      1
+ 2: -11.51293 -11.51293 polynomial      4
+ 3: -11.51293 -11.51293     radial     NA
+ 4: -11.51293  11.51293 polynomial      1
+ 5: -11.51293  11.51293 polynomial      4
+ 6: -11.51293  11.51293     radial     NA
+ 7:  11.51293 -11.51293 polynomial      1
+ 8:  11.51293 -11.51293 polynomial      4
+ 9:  11.51293 -11.51293     radial     NA
+10:  11.51293  11.51293 polynomial      1
+11:  11.51293  11.51293 polynomial      4
+12:  11.51293  11.51293     radial     NA
+
+
+

The value for degree is NA if the dependency on the kernel is not satisfied.

+

We use the tune()-shortcut to run the tuning.

+
+
instance = tune(
+  tuner = tnr("grid_search", resolution = 3),
+  task = task,
+  learner = learner,
+  resampling = resampling,
+  measure = measure
+)
+
+
+
instance$result
+
+
   cost    gamma     kernel degree learner_param_vals  x_domain classif.ce
+1:    0 11.51293 polynomial      1          <list[5]> <list[4]> 0.02666667
+
+
+
+
+

Final Model

+

We add the optimized hyperparameters to the learner and train the learner on the full dataset.

+
+
learner = lrn("classif.svm")
+learner$param_set$values = instance$result_learner_param_vals
+learner$train(task)
+
+

The trained model can now be used to make predictions on new data. A common mistake is to report the performance estimated on the resampling sets on which the tuning was performed (instance$result_y) as the model’s performance. These scores might be biased and overestimate the ability of the fitted model to predict with new data. Instead, we have to use nested resampling to get an unbiased performance estimate.

+
+
+

Nested Resampling

+

Tuning should not be performed on the same resampling sets which are used for evaluating the model itself, since this would result in a biased performance estimate. Nested resampling uses an outer and inner resampling to separate the tuning from the performance estimation of the model. We can use the AutoTuner class for running nested resampling. The AutoTuner wraps a Learner and tunes the hyperparameter of the learner during $train(). This is our inner resampling loop.

+
+
learner = lrn("classif.svm", type = "C-classification")
+learner$param_set$values$cost = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))
+learner$param_set$values$gamma = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))
+learner$param_set$values$kernel = to_tune(c("polynomial", "radial"))
+learner$param_set$values$degree = to_tune(1, 4)
+
+resampling_inner = rsmp("cv", folds = 3)
+terminator = trm("none")
+tuner = tnr("grid_search", resolution = 3)
+
+at = AutoTuner$new(
+  learner = learner,
+  resampling = resampling_inner,
+  measure = measure,
+  terminator = terminator,
+  tuner = tuner,
+  store_models = TRUE)
+
+

We put the AutoTuner into a resample() call to get the outer resampling loop.

+
+
resampling_outer = rsmp("cv", folds = 3)
+rr = resample(task = task, learner = at, resampling = resampling_outer, store_models = TRUE)
+
+

We check the inner tuning results for stable hyperparameters. This means that the selected hyperparameters should not vary too much. We might observe unstable models in this example because the small data set and the low number of resampling iterations might introduce too much randomness. Usually, we aim for the selection of stable hyperparameters for all outer training sets.

+
+
extract_inner_tuning_results(rr)[, .SD, .SDcols = !c("learner_param_vals", "x_domain")]
+
+
   iteration     cost     gamma     kernel degree classif.ce task_id        learner_id resampling_id
+1:         1  0.00000   0.00000 polynomial      1 0.03000594    iris classif.svm.tuned            cv
+2:         2  0.00000   0.00000 polynomial      1 0.03000594    iris classif.svm.tuned            cv
+3:         3 11.51293 -11.51293     radial     NA 0.02020202    iris classif.svm.tuned            cv
+
+
+

Next, we want to compare the predictive performances estimated on the outer resampling to the inner resampling (extract_inner_tuning_results(rr)). Significantly lower predictive performances on the outer resampling indicate that the models with the optimized hyperparameters overfit the data.

+
+
rr$score()[, .(iteration, task_id, learner_id, resampling_id, classif.ce)]
+
+
   iteration task_id        learner_id resampling_id classif.ce
+1:         1    iris classif.svm.tuned            cv       0.04
+2:         2    iris classif.svm.tuned            cv       0.06
+3:         3    iris classif.svm.tuned            cv       0.00
+
+
+

The archives of the AutoTuners allows us to inspect all evaluated hyperparameters configurations with the associated predictive performances.

+
+
extract_inner_tuning_archives(rr, unnest = NULL, exclude_columns = c("resample_result", "uhash", "x_domain", "timestamp"))
+
+
     iteration      cost     gamma     kernel degree classif.ce runtime_learners batch_nr warnings errors task_id
+  1:         1   0.00000 -11.51293 polynomial      2 0.68033274            0.017        1        0      0    iris
+  2:         1   0.00000 -11.51293     radial     NA 0.64111705            0.017        2        0      0    iris
+  3:         1   0.00000   0.00000 polynomial      1 0.03000594            0.017        3        0      0    iris
+  4:         1  11.51293   0.00000 polynomial      1 0.05050505            0.012        4        0      0    iris
+  5:         1  11.51293  11.51293     radial     NA 0.66013072            0.014        5        0      0    iris
+ ---                                                                                                             
+104:         3  11.51293 -11.51293 polynomial      2 0.68924540            0.013       32        0      0    iris
+105:         3 -11.51293 -11.51293     radial     NA 0.68924540            0.012       33        0      0    iris
+106:         3 -11.51293  11.51293 polynomial      4 0.11883541            0.015       34        0      0    iris
+107:         3   0.00000 -11.51293 polynomial      4 0.68924540            0.015       35        0      0    iris
+108:         3  11.51293  11.51293 polynomial      1 0.06951872            0.725       36        0      0    iris
+            learner_id resampling_id
+  1: classif.svm.tuned            cv
+  2: classif.svm.tuned            cv
+  3: classif.svm.tuned            cv
+  4: classif.svm.tuned            cv
+  5: classif.svm.tuned            cv
+ ---                                
+104: classif.svm.tuned            cv
+105: classif.svm.tuned            cv
+106: classif.svm.tuned            cv
+107: classif.svm.tuned            cv
+108: classif.svm.tuned            cv
+
+
+

The aggregated performance of all outer resampling iterations is essentially the unbiased performance of an SVM with optimal hyperparameter found by grid search.

+
+
rr$aggregate()
+
+
classif.ce 
+0.03333333 
+
+
+

Applying nested resampling can be shortened by using the tune_nested()-shortcut.

+
+
learner = lrn("classif.svm", type = "C-classification")
+learner$param_set$values$cost = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))
+learner$param_set$values$gamma = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))
+learner$param_set$values$kernel = to_tune(c("polynomial", "radial"))
+learner$param_set$values$degree = to_tune(1, 4)
+
+rr = tune_nested(
+  tuner = tnr("grid_search", resolution = 3),
+  task = tsk("iris"),
+  learner = learner,
+  inner_resampling = rsmp ("cv", folds = 3),
+  outer_resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce"),
+)
+
+
+
+

Resources

+

The mlr3book includes chapters on tuning spaces and hyperparameter tuning. The mlr3cheatsheets contain frequently used commands and workflows of mlr3.

+ + + +
+ +

References

+
+Hsu, Chih-wei, Chih-chung Chang, and Chih-Jen Lin. 2003. “A Practical Guide to Support Vector Classification.” +
+
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/optimization/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/index_files/figure-html/2021-03-09-practical-tuning-series-tune-a-support-vector-machine-014-1.png b/gallery/optimization/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/index_files/figure-html/2021-03-09-practical-tuning-series-tune-a-support-vector-machine-014-1.png new file mode 100644 index 00000000..5dd4997f Binary files /dev/null and b/gallery/optimization/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/index_files/figure-html/2021-03-09-practical-tuning-series-tune-a-support-vector-machine-014-1.png differ diff --git a/gallery/optimization/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/index_files/figure-html/2021-03-09-practical-tuning-series-tune-a-support-vector-machine-020-1.png b/gallery/optimization/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/index_files/figure-html/2021-03-09-practical-tuning-series-tune-a-support-vector-machine-020-1.png new file mode 100644 index 00000000..6c90ce76 Binary files /dev/null and b/gallery/optimization/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/index_files/figure-html/2021-03-09-practical-tuning-series-tune-a-support-vector-machine-020-1.png differ diff --git a/gallery/optimization/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/index.html b/gallery/optimization/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/index.html new file mode 100644 index 00000000..fd13e55f --- /dev/null +++ b/gallery/optimization/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/index.html @@ -0,0 +1,1396 @@ + + + + + + + + + + + + + + + + + +Practical Tuning Series - Tune a Preprocessing Pipeline – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Practical Tuning Series - Tune a Preprocessing Pipeline

+
+
+

Build a simple preprocessing pipeline and tune it.

+
+
+
+
+ + +
+ +
+
Authors
+
+

Marc Becker

+

Theresa Ullmann

+

Michel Lang

+

Bernd Bischl

+

Jakob Richter

+

Martin Binder

+
+
+ +
+
Published
+
+

March 10, 2021

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Scope

+

This is the second part of the practical tuning series. The other parts can be found here:

+ +

In this post, we build a simple preprocessing pipeline and tune it. For this, we are using the mlr3pipelines extension package. First, we start by imputing missing values in the Pima Indians Diabetes data set. After that, we encode a factor column to numerical dummy columns in the data set. Next, we combine both preprocessing steps to a Graph and create a GraphLearner. Finally, nested resampling is used to compare the performance of two imputation methods.

+
+
+

Prerequisites

+

We load the mlr3verse package which pulls in the most important packages for this example.

+
+
library(mlr3verse)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented. The lgr package is used for logging in all mlr3 packages. The mlr3 logger prints the logging messages from the base package, whereas the bbotk logger is responsible for logging messages from the optimization packages (e.g. mlr3tuning ).

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+

In this example, we use the Pima Indians Diabetes data set which is used to predict whether or not a patient has diabetes. The patients are characterized by 8 numeric features of which some have missing values. We alter the data set by categorizing the feature pressure (blood pressure) into the categories "low", "mid", and "high".

+
+
# retrieve the task from mlr3
+task = tsk("pima")
+
+# create data frame with categorized pressure feature
+data = task$data(cols = "pressure")
+breaks = quantile(data$pressure, probs = c(0, 0.33, 0.66, 1), na.rm = TRUE)
+data$pressure = cut(data$pressure, breaks, labels = c("low", "mid", "high"))
+
+# overwrite the feature in the task
+task$cbind(data)
+
+# generate a quick textual overview
+skimr::skim(task$data())
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Data summary
Nametask$data()
Number of rows768
Number of columns9
KeyNULL
_______________________
Column type frequency:
factor2
numeric7
________________________
Group variablesNone
+

Variable type: factor

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_rateorderedn_uniquetop_counts
diabetes01.00FALSE2neg: 500, pos: 268
pressure360.95FALSE3low: 282, mid: 245, hig: 205
+

Variable type: numeric

+ +++++++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_ratemeansdp0p25p50p75p100hist
age01.0033.2411.7621.0024.0029.0041.0081.00▇▃▁▁▁
glucose50.99121.6930.5444.0099.00117.00141.00199.00▁▇▇▃▂
insulin3740.51155.55118.7814.0076.25125.00190.00846.00▇▂▁▁▁
mass110.9932.466.9218.2027.5032.3036.6067.10▅▇▃▁▁
pedigree01.000.470.330.080.240.370.632.42▇▃▁▁▁
pregnant01.003.853.370.001.003.006.0017.00▇▃▂▁▁
triceps2270.7029.1510.487.0022.0029.0036.0099.00▆▇▁▁▁
+
+
+

We choose the xgboost algorithm from the xgboost package as learner.

+
+
learner = lrn("classif.xgboost", nrounds = 100, id = "xgboost", verbose = 0)
+
+
+
+

Missing Values

+

The task has missing data in five columns.

+
+
round(task$missings() / task$nrow, 2)
+
+
diabetes      age  glucose  insulin     mass pedigree pregnant pressure  triceps 
+    0.00     0.00     0.01     0.49     0.01     0.00     0.00     0.05     0.30 
+
+
+

The xgboost learner has an internal method for handling missing data but some learners cannot handle missing values. We will try to beat the internal method in terms of predictive performance. The mlr3pipelines package offers various methods to impute missing values.

+
+
mlr_pipeops$keys("^impute")
+
+
[1] "imputeconstant" "imputehist"     "imputelearner"  "imputemean"     "imputemedian"   "imputemode"    
+[7] "imputeoor"      "imputesample"  
+
+
+

We choose the PipeOpImputeOOR that adds the new factor level ".MISSING". to factorial features and imputes numerical features by constant values shifted below the minimum (default) or above the maximum.

+
+
imputer = po("imputeoor")
+print(imputer)
+
+
PipeOp: <imputeoor> (not trained)
+values: <min=TRUE, offset=1, multiplier=1>
+Input channels <name [train type, predict type]>:
+  input [Task,Task]
+Output channels <name [train type, predict type]>:
+  output [Task,Task]
+
+
+

As the output suggests, the in- and output of this pipe operator is a Task for both the training and the predict step. We can manually train the pipe operator to check its functionality:

+
+
task_imputed = imputer$train(list(task))[[1]]
+task_imputed$missings()
+
+
diabetes      age pedigree pregnant  glucose  insulin     mass pressure  triceps 
+       0        0        0        0        0        0        0        0        0 
+
+
+

Let’s compare an observation with missing values to the observation with imputed observation.

+
+
rbind(
+  task$data()[8,],
+  task_imputed$data()[8,]
+)
+
+
   diabetes age glucose insulin mass pedigree pregnant pressure triceps
+1:      neg  29     115      NA 35.3    0.134       10     <NA>      NA
+2:      neg  29     115    -819 35.3    0.134       10 .MISSING     -86
+
+
+

Note that OOR imputation is in particular useful for tree-based models, but should not be used for linear models or distance-based models.

+
+
+

Factor Encoding

+

The xgboost learner cannot handle categorical features. Therefore, we must to convert factor columns to numerical dummy columns. For this, we argument the xgboost learner with automatic factor encoding.

+

The PipeOpEncode encodes factor columns with one of six methods. In this example, we use one-hot encoding which creates a new binary column for each factor level.

+
+
factor_encoding = po("encode", method = "one-hot")
+
+

We manually trigger the encoding on the task.

+
+
factor_encoding$train(list(task))
+
+
$output
+<TaskClassif:pima> (768 x 11): Pima Indian Diabetes
+* Target: diabetes
+* Properties: twoclass
+* Features (10):
+  - dbl (10): age, glucose, insulin, mass, pedigree, pregnant, pressure.high, pressure.low, pressure.mid,
+    triceps
+
+
+

The factor column pressure has been converted to the three binary columns "pressure.low", "pressure.mid", and "pressure.high".

+
+
+

Constructing the Pipeline

+

We created two preprocessing steps which could be used to create a new task with encoded factor variables and imputed missing values. However, if we do this before resampling, information from the test can leak into our training step which typically leads to overoptimistic performance measures. To avoid this, we add the preprocessing steps to the Learner itself, creating a GraphLearner. For this, we create a Graph first.

+
+
graph = po("encode") %>>%
+  po("imputeoor") %>>%
+  learner
+plot(graph, html = FALSE)
+
+
+
+

+
+
+
+
+

We use as_learner() to wrap the Graph into a GraphLearner with which allows us to use the graph like a normal learner.

+
+
graph_learner = as_learner(graph)
+
+# short learner id for printing
+graph_learner$id = "graph_learner"
+
+

The GraphLearner can be trained and used for making predictions. Instead of calling $train() or $predict() manually, we will directly use it for resampling. We choose a 3-fold cross-validation as the resampling strategy.

+
+
resampling = rsmp("cv", folds = 3)
+
+rr = resample(task = task, learner = graph_learner, resampling = resampling)
+
+
+
rr$score()[, c("iteration", "task_id", "learner_id", "resampling_id", "classif.ce"), with = FALSE]
+
+
   iteration task_id    learner_id resampling_id classif.ce
+1:         1    pima graph_learner            cv  0.2851562
+2:         2    pima graph_learner            cv  0.2460938
+3:         3    pima graph_learner            cv  0.2968750
+
+
+

For each resampling iteration, the following steps are performed:

+
    +
  1. The task is subsetted to the training indices.
  2. +
  3. The factor encoder replaces factor features with dummy columns in the training task.
  4. +
  5. The OOR imputer determines values to impute from the training task and then replaces all missing values with learned imputation values.
  6. +
  7. The learner is applied on the modified training task and the model is stored inside the learner.
  8. +
+

Next is the predict step:

+
    +
  1. The task is subsetted to the test indices.
  2. +
  3. The factor encoder replaces all factor features with dummy columns in the test task.
  4. +
  5. The OOR imputer replaces all missing values of the test task with the imputation values learned on the training set.
  6. +
  7. The learner’s predict method is applied on the modified test task.
  8. +
+

By following this procedure, it is guaranteed that no information can leak from the training step to the predict step.

+
+
+

Tuning the Pipeline

+

Let’s have a look at the parameter set of the GraphLearner. It consists of the xgboost hyperparameters, and additionally, the parameter of the PipeOp encode and imputeoor. All hyperparameters are prefixed with the id of the respective PipeOp or learner.

+
+
as.data.table(graph_learner$param_set)[, c("id", "class", "lower", "upper", "nlevels"), with = FALSE]
+
+
                                     id    class lower upper nlevels
+ 1:                       encode.method ParamFct    NA    NA       5
+ 2:               encode.affect_columns ParamUty    NA    NA     Inf
+ 3:                       imputeoor.min ParamLgl    NA    NA       2
+ 4:                    imputeoor.offset ParamDbl     0   Inf     Inf
+ 5:                imputeoor.multiplier ParamDbl     0   Inf     Inf
+ 6:            imputeoor.affect_columns ParamUty    NA    NA     Inf
+ 7:                       xgboost.alpha ParamDbl     0   Inf     Inf
+ 8:               xgboost.approxcontrib ParamLgl    NA    NA       2
+ 9:                  xgboost.base_score ParamDbl  -Inf   Inf     Inf
+10:                     xgboost.booster ParamFct    NA    NA       3
+11:                   xgboost.callbacks ParamUty    NA    NA     Inf
+12:           xgboost.colsample_bylevel ParamDbl     0     1     Inf
+13:            xgboost.colsample_bynode ParamDbl     0     1     Inf
+14:            xgboost.colsample_bytree ParamDbl     0     1     Inf
+15: xgboost.disable_default_eval_metric ParamLgl    NA    NA       2
+16:       xgboost.early_stopping_rounds ParamInt     1   Inf     Inf
+17:          xgboost.early_stopping_set ParamFct    NA    NA       3
+18:                         xgboost.eta ParamDbl     0     1     Inf
+19:                 xgboost.eval_metric ParamUty    NA    NA     Inf
+20:            xgboost.feature_selector ParamFct    NA    NA       5
+21:                       xgboost.feval ParamUty    NA    NA     Inf
+22:                       xgboost.gamma ParamDbl     0   Inf     Inf
+23:                 xgboost.grow_policy ParamFct    NA    NA       2
+24:     xgboost.interaction_constraints ParamUty    NA    NA     Inf
+25:              xgboost.iterationrange ParamUty    NA    NA     Inf
+26:                      xgboost.lambda ParamDbl     0   Inf     Inf
+27:                 xgboost.lambda_bias ParamDbl     0   Inf     Inf
+28:                     xgboost.max_bin ParamInt     2   Inf     Inf
+29:              xgboost.max_delta_step ParamDbl     0   Inf     Inf
+30:                   xgboost.max_depth ParamInt     0   Inf     Inf
+31:                  xgboost.max_leaves ParamInt     0   Inf     Inf
+32:                    xgboost.maximize ParamLgl    NA    NA       2
+33:            xgboost.min_child_weight ParamDbl     0   Inf     Inf
+34:                     xgboost.missing ParamDbl  -Inf   Inf     Inf
+35:        xgboost.monotone_constraints ParamUty    NA    NA     Inf
+36:              xgboost.normalize_type ParamFct    NA    NA       2
+37:                     xgboost.nrounds ParamInt     1   Inf     Inf
+38:                     xgboost.nthread ParamInt     1   Inf     Inf
+39:                  xgboost.ntreelimit ParamInt     1   Inf     Inf
+40:           xgboost.num_parallel_tree ParamInt     1   Inf     Inf
+41:                   xgboost.objective ParamUty    NA    NA     Inf
+42:                    xgboost.one_drop ParamLgl    NA    NA       2
+43:                xgboost.outputmargin ParamLgl    NA    NA       2
+44:                 xgboost.predcontrib ParamLgl    NA    NA       2
+45:                   xgboost.predictor ParamFct    NA    NA       2
+46:             xgboost.predinteraction ParamLgl    NA    NA       2
+47:                    xgboost.predleaf ParamLgl    NA    NA       2
+48:               xgboost.print_every_n ParamInt     1   Inf     Inf
+49:                xgboost.process_type ParamFct    NA    NA       2
+50:                   xgboost.rate_drop ParamDbl     0     1     Inf
+51:                xgboost.refresh_leaf ParamLgl    NA    NA       2
+52:                     xgboost.reshape ParamLgl    NA    NA       2
+53:          xgboost.seed_per_iteration ParamLgl    NA    NA       2
+54:             xgboost.sampling_method ParamFct    NA    NA       2
+55:                 xgboost.sample_type ParamFct    NA    NA       2
+56:                   xgboost.save_name ParamUty    NA    NA     Inf
+57:                 xgboost.save_period ParamInt     0   Inf     Inf
+58:            xgboost.scale_pos_weight ParamDbl  -Inf   Inf     Inf
+59:                   xgboost.skip_drop ParamDbl     0     1     Inf
+60:                xgboost.strict_shape ParamLgl    NA    NA       2
+61:                   xgboost.subsample ParamDbl     0     1     Inf
+62:                       xgboost.top_k ParamInt     0   Inf     Inf
+63:                    xgboost.training ParamLgl    NA    NA       2
+64:                 xgboost.tree_method ParamFct    NA    NA       5
+65:      xgboost.tweedie_variance_power ParamDbl     1     2     Inf
+66:                     xgboost.updater ParamUty    NA    NA     Inf
+67:                     xgboost.verbose ParamInt     0     2       3
+68:                   xgboost.watchlist ParamUty    NA    NA     Inf
+69:                   xgboost.xgb_model ParamUty    NA    NA     Inf
+                                     id    class lower upper nlevels
+
+
+

We will tune the encode method.

+
+
graph_learner$param_set$values$encode.method = to_tune(c("one-hot", "treatment"))
+
+

We define a tuning instance and use grid search since we want to try all encode methods.

+
+
instance = tune(
+  tuner = tnr("grid_search"),
+  task = task,
+  learner = graph_learner,
+  resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce")
+)
+
+

The archive shows us the performance of the model with different encoding methods.

+
+
print(instance$archive)
+
+
<ArchiveTuning> with 2 evaluations
+   encode.method classif.ce batch_nr warnings errors
+1:     treatment       0.26        1        0      0
+2:       one-hot       0.26        2        0      0
+
+
+
+
+

Nested Resampling

+

We create one GraphLearner with imputeoor and test it against a GraphLearner that uses the internal imputation method of xgboost. Applying nested resampling ensures a fair comparison of the predictive performances.

+
+
graph_1 = po("encode") %>>%
+  learner
+graph_learner_1 = GraphLearner$new(graph_1)
+
+graph_learner_1$param_set$values$encode.method = to_tune(c("one-hot", "treatment"))
+
+at_1 = AutoTuner$new(
+  learner = graph_learner_1,
+  resampling = resampling,
+  measure = msr("classif.ce"),
+  terminator = trm("none"),
+  tuner = tnr("grid_search"),
+  store_models = TRUE
+)
+
+
+
graph_2 = po("encode") %>>%
+  po("imputeoor") %>>%
+  learner
+graph_learner_2 = GraphLearner$new(graph_2)
+
+graph_learner_2$param_set$values$encode.method = to_tune(c("one-hot", "treatment"))
+
+at_2 = AutoTuner$new(
+  learner = graph_learner_2,
+  resampling = resampling,
+  measure = msr("classif.ce"),
+  terminator = trm("none"),
+  tuner = tnr("grid_search"),
+  store_models = TRUE
+)
+
+

We run the benchmark.

+
+
resampling_outer = rsmp("cv", folds = 3)
+design = benchmark_grid(task, list(at_1, at_2), resampling_outer)
+
+bmr = benchmark(design, store_models = TRUE)
+
+

We compare the aggregated performances on the outer test sets which give us an unbiased performance estimate of the GraphLearners with the different encoding methods.

+
+
bmr$aggregate()
+
+
   nr task_id                     learner_id resampling_id iters classif.ce
+1:  1    pima           encode.xgboost.tuned            cv     3  0.2578125
+2:  2    pima encode.imputeoor.xgboost.tuned            cv     3  0.2630208
+Hidden columns: resample_result
+
+
autoplot(bmr)
+
+
+
+

+
+
+
+
+

Note that in practice, it is required to tune preprocessing hyperparameters jointly with the hyperparameters of the learner. Otherwise, comparing preprocessing steps is not feasible and can lead to wrong conclusions.

+

Applying nested resampling can be shortened by using the auto_tuner()-shortcut.

+
+
graph_1 = po("encode") %>>% learner
+graph_learner_1 = as_learner(graph_1)
+graph_learner_1$param_set$values$encode.method = to_tune(c("one-hot", "treatment"))
+
+at_1 = auto_tuner(
+  method = "grid_search",
+  learner = graph_learner_1,
+  resampling = resampling,
+  measure = msr("classif.ce"),
+  store_models = TRUE)
+
+graph_2 = po("encode") %>>% po("imputeoor") %>>% learner
+graph_learner_2 = as_learner(graph_2)
+graph_learner_2$param_set$values$encode.method = to_tune(c("one-hot", "treatment"))
+
+at_2 = auto_tuner(
+  method = "grid_search",
+  learner = graph_learner_2,
+  resampling = resampling,
+  measure = msr("classif.ce"),
+  store_models = TRUE)
+
+design = benchmark_grid(task, list(at_1, at_2), rsmp("cv", folds = 3))
+
+bmr = benchmark(design, store_models = TRUE)
+
+
+
+

Final Model

+

We train the chosen GraphLearner with the AutoTuner to get a final model with optimized hyperparameters.

+
+
at_2$train(task)
+
+

The trained model can now be used to make predictions on new data at_2$predict(). The pipeline ensures that the preprocessing is always a part of the train and predict step.

+
+
+

Resources

+

The mlr3book includes chapters on pipelines and hyperparameter tuning. The mlr3cheatsheets contain frequently used commands and workflows of mlr3.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/optimization/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/index_files/figure-html/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline-013-1.png b/gallery/optimization/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/index_files/figure-html/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline-013-1.png new file mode 100644 index 00000000..20ed6df0 Binary files /dev/null and b/gallery/optimization/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/index_files/figure-html/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline-013-1.png differ diff --git a/gallery/optimization/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/index_files/figure-html/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline-024-1.png b/gallery/optimization/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/index_files/figure-html/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline-024-1.png new file mode 100644 index 00000000..0e714614 Binary files /dev/null and b/gallery/optimization/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/index_files/figure-html/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline-024-1.png differ diff --git a/gallery/optimization/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index.html b/gallery/optimization/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index.html new file mode 100644 index 00000000..ba80f073 --- /dev/null +++ b/gallery/optimization/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index.html @@ -0,0 +1,1143 @@ + + + + + + + + + + + + + + + + + +Practical Tuning Series - Build an Automated Machine Learning System – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Practical Tuning Series - Build an Automated Machine Learning System

+
+
+

Implement a simple automated machine learning system.

+
+
+
+
+ + +
+ +
+
Authors
+
+

Marc Becker

+

Theresa Ullmann

+

Michel Lang

+

Bernd Bischl

+

Jakob Richter

+

Martin Binder

+
+
+ +
+
Published
+
+

March 11, 2021

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Scope

+

This is the third part of the practical tuning series. The other parts can be found here:

+ +

In this post, we implement a simple automated machine learning (AutoML) system which includes preprocessing, a switch between multiple learners and hyperparameter tuning. For this, we build a pipeline with the mlr3pipelines extension package. Additionally, we use nested resampling to get an unbiased performance estimate of our AutoML system.

+
+
+

Prerequisites

+

We load the mlr3verse package which pulls in the most important packages for this example.

+
+
library(mlr3verse)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented. The lgr package is used for logging in all mlr3 packages. The mlr3 logger prints the logging messages from the base package, whereas the bbotk logger is responsible for logging messages from the optimization packages (e.g. mlr3tuning ).

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+

In this example, we use the Pima Indians Diabetes data set which is used to to predict whether or not a patient has diabetes. The patients are characterized by 8 numeric features and some have missing values.

+
+
task = tsk("pima")
+
+
+
+

Branching

+

We use three popular machine learning algorithms: k-nearest-neighbors, support vector machines and random forests.

+
+
learners = list(
+  lrn("classif.kknn", id = "kknn"),
+  lrn("classif.svm", id = "svm", type = "C-classification"),
+  lrn("classif.ranger", id = "ranger")
+)
+
+

The PipeOpBranch allows us to specify multiple alternatives paths. In this graph, the paths lead to the different learner models. The selection hyperparameter controls which path is executed i.e., which learner is used to fit a model. It is important to use the PipeOpBranch after the branching so that the outputs are merged into one result object. We visualize the graph with branching below.

+
+
graph =
+  po("branch", options = c("kknn", "svm", "ranger")) %>>%
+  gunion(lapply(learners, po)) %>>%
+  po("unbranch")
+graph$plot(html = FALSE)
+
+
+
+

+
+
+
+
+

Alternatively, we can use the ppl()-shortcut to load a predefined graph from the mlr_graphs dictionary. For this, the learner list must be named.

+
+
learners = list(
+  kknn = lrn("classif.kknn", id = "kknn"),
+  svm = lrn("classif.svm", id = "svm", type = "C-classification"),
+  ranger = lrn("classif.ranger", id = "ranger")
+)
+
+graph = ppl("branch", lapply(learners, po))
+
+
+
+

Preprocessing

+

The task has missing data in five columns.

+
+
round(task$missings() / task$nrow, 2)
+
+
diabetes      age  glucose  insulin     mass pedigree pregnant pressure  triceps 
+    0.00     0.00     0.01     0.49     0.01     0.00     0.00     0.05     0.30 
+
+
+

The pipeline "robustify" function creates a preprocessing pipeline based on our task. The resulting pipeline imputes missing values with PipeOpImputeHist and creates a dummy column (PipeOpMissInd) which indicates the imputed missing values. Internally, this creates two paths and the results are combined with PipeOpFeatureUnion. In contrast to PipeOpBranch, both paths are executed. Additionally, "robustify" adds PipeOpEncode to encode factor columns and PipeOpRemoveConstants to remove features with a constant value.

+
+
graph = ppl("robustify", task = task, factors_to_numeric = TRUE) %>>%
+  graph
+plot(graph, html = FALSE)
+
+
+
+

+
+
+
+
+

We could also create the preprocessing pipeline manually.

+
+
gunion(list(po("imputehist"),
+  po("missind", affect_columns = selector_type(c("numeric", "integer"))))) %>>%
+  po("featureunion") %>>%
+  po("encode") %>>%
+  po("removeconstants")
+
+
Graph with 5 PipeOps:
+              ID         State        sccssors          prdcssors
+      imputehist <<UNTRAINED>>    featureunion                   
+         missind <<UNTRAINED>>    featureunion                   
+    featureunion <<UNTRAINED>>          encode imputehist,missind
+          encode <<UNTRAINED>> removeconstants       featureunion
+ removeconstants <<UNTRAINED>>                             encode
+
+
+
+
+

Graph Learner

+

We use as_learner() to create a GraphLearner which encapsulates the pipeline and can be used like a learner.

+
+
graph_learner = as_learner(graph)
+
+

The parameter set of the graph learner includes all hyperparameters from all contained learners. The hyperparameter ids are prefixed with the corresponding learner ids. The hyperparameter branch.selection controls which learner is used.

+
+
as.data.table(graph_learner$param_set)[, .(id, class, lower, upper, nlevels)]
+
+
                                              id    class lower upper nlevels
+ 1:           removeconstants_prerobustify.ratio ParamDbl     0     1     Inf
+ 2:         removeconstants_prerobustify.rel_tol ParamDbl     0   Inf     Inf
+ 3:         removeconstants_prerobustify.abs_tol ParamDbl     0   Inf     Inf
+ 4:       removeconstants_prerobustify.na_ignore ParamLgl    NA    NA       2
+ 5:  removeconstants_prerobustify.affect_columns ParamUty    NA    NA     Inf
+ 6:                    imputehist.affect_columns ParamUty    NA    NA     Inf
+ 7:                                missind.which ParamFct    NA    NA       2
+ 8:                                 missind.type ParamFct    NA    NA       4
+ 9:                       missind.affect_columns ParamUty    NA    NA     Inf
+10:                  imputesample.affect_columns ParamUty    NA    NA     Inf
+11:                                encode.method ParamFct    NA    NA       5
+12:                        encode.affect_columns ParamUty    NA    NA     Inf
+13:          removeconstants_postrobustify.ratio ParamDbl     0     1     Inf
+14:        removeconstants_postrobustify.rel_tol ParamDbl     0   Inf     Inf
+15:        removeconstants_postrobustify.abs_tol ParamDbl     0   Inf     Inf
+16:      removeconstants_postrobustify.na_ignore ParamLgl    NA    NA       2
+17: removeconstants_postrobustify.affect_columns ParamUty    NA    NA     Inf
+18:                                       kknn.k ParamInt     1   Inf     Inf
+19:                                kknn.distance ParamDbl     0   Inf     Inf
+20:                                  kknn.kernel ParamFct    NA    NA      10
+21:                                   kknn.scale ParamLgl    NA    NA       2
+22:                                 kknn.ykernel ParamUty    NA    NA     Inf
+23:                             kknn.store_model ParamLgl    NA    NA       2
+24:                                svm.cachesize ParamDbl  -Inf   Inf     Inf
+25:                            svm.class.weights ParamUty    NA    NA     Inf
+26:                                    svm.coef0 ParamDbl  -Inf   Inf     Inf
+27:                                     svm.cost ParamDbl     0   Inf     Inf
+28:                                    svm.cross ParamInt     0   Inf     Inf
+29:                          svm.decision.values ParamLgl    NA    NA       2
+30:                                   svm.degree ParamInt     1   Inf     Inf
+31:                                  svm.epsilon ParamDbl     0   Inf     Inf
+32:                                   svm.fitted ParamLgl    NA    NA       2
+33:                                    svm.gamma ParamDbl     0   Inf     Inf
+34:                                   svm.kernel ParamFct    NA    NA       4
+35:                                       svm.nu ParamDbl  -Inf   Inf     Inf
+36:                                    svm.scale ParamUty    NA    NA     Inf
+37:                                svm.shrinking ParamLgl    NA    NA       2
+38:                                svm.tolerance ParamDbl     0   Inf     Inf
+39:                                     svm.type ParamFct    NA    NA       2
+40:                                 ranger.alpha ParamDbl  -Inf   Inf     Inf
+41:                ranger.always.split.variables ParamUty    NA    NA     Inf
+42:                         ranger.class.weights ParamUty    NA    NA     Inf
+43:                               ranger.holdout ParamLgl    NA    NA       2
+44:                            ranger.importance ParamFct    NA    NA       4
+45:                            ranger.keep.inbag ParamLgl    NA    NA       2
+46:                             ranger.max.depth ParamInt     0   Inf     Inf
+47:                         ranger.min.node.size ParamInt     1   Inf     Inf
+48:                              ranger.min.prop ParamDbl  -Inf   Inf     Inf
+49:                               ranger.minprop ParamDbl  -Inf   Inf     Inf
+50:                                  ranger.mtry ParamInt     1   Inf     Inf
+51:                            ranger.mtry.ratio ParamDbl     0     1     Inf
+52:                     ranger.num.random.splits ParamInt     1   Inf     Inf
+53:                           ranger.num.threads ParamInt     1   Inf     Inf
+54:                             ranger.num.trees ParamInt     1   Inf     Inf
+55:                             ranger.oob.error ParamLgl    NA    NA       2
+56:                 ranger.regularization.factor ParamUty    NA    NA     Inf
+57:               ranger.regularization.usedepth ParamLgl    NA    NA       2
+58:                               ranger.replace ParamLgl    NA    NA       2
+59:             ranger.respect.unordered.factors ParamFct    NA    NA       3
+60:                       ranger.sample.fraction ParamDbl     0     1     Inf
+61:                           ranger.save.memory ParamLgl    NA    NA       2
+62:          ranger.scale.permutation.importance ParamLgl    NA    NA       2
+63:                             ranger.se.method ParamFct    NA    NA       2
+64:                                  ranger.seed ParamInt  -Inf   Inf     Inf
+65:                  ranger.split.select.weights ParamUty    NA    NA     Inf
+66:                             ranger.splitrule ParamFct    NA    NA       3
+67:                               ranger.verbose ParamLgl    NA    NA       2
+68:                          ranger.write.forest ParamLgl    NA    NA       2
+69:                             branch.selection ParamFct    NA    NA       3
+                                              id    class lower upper nlevels
+
+
+
+
+

Tune the pipeline

+

We will only tune one hyperparameter for each learner in this example. Additionally, we tune the branching parameter which selects one of the three learners. We have to specify that a hyperparameter is only valid for a certain learner by using depends = branch.selection == <learner_id>.

+
+
# branch
+graph_learner$param_set$values$branch.selection =
+  to_tune(c("kknn", "svm", "ranger"))
+
+# kknn
+graph_learner$param_set$values$kknn.k =
+  to_tune(p_int(3, 50, logscale = TRUE, depends = branch.selection == "kknn"))
+
+# svm
+graph_learner$param_set$values$svm.cost =
+  to_tune(p_dbl(-1, 1, trafo = function(x) 10^x, depends = branch.selection == "svm"))
+
+# ranger
+graph_learner$param_set$values$ranger.mtry =
+  to_tune(p_int(1, 8, depends = branch.selection == "ranger"))
+
+# short learner id for printing
+graph_learner$id = "graph_learner"
+
+

We define a tuning instance and select a random search which is stopped after 20 evaluated configurations.

+
+
instance = tune(
+  tuner = tnr("random_search"),
+  task = task,
+  learner = graph_learner,
+  resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce"),
+  term_evals = 20
+)
+
+

The following shows a quick way to visualize the tuning results.

+
+
autoplot(instance, type = "marginal",
+  cols_x = c("x_domain_kknn.k", "x_domain_svm.cost", "ranger.mtry"))
+
+
+
+

+
+
+
+
+
+
+

Final Model

+

We add the optimized hyperparameters to the graph learner and train the learner on the full dataset.

+
+
learner = as_learner(graph)
+learner$param_set$values = instance$result_learner_param_vals
+learner$train(task)
+
+

The trained model can now be used to make predictions on new data. A common mistake is to report the performance estimated on the resampling sets on which the tuning was performed (instance$result_y) as the model’s performance. Instead we have to use nested resampling to get an unbiased performance estimate.

+
+
+

Nested Resampling

+

We use nested resampling to get an unbiased estimate of the predictive performance of our graph learner.

+
+
graph_learner = as_learner(graph)
+graph_learner$param_set$values$branch.selection =
+  to_tune(c("kknn", "svm", "ranger"))
+graph_learner$param_set$values$kknn.k =
+  to_tune(p_int(3, 50, logscale = TRUE, depends = branch.selection == "kknn"))
+graph_learner$param_set$values$svm.cost =
+  to_tune(p_dbl(-1, 1, trafo = function(x) 10^x, depends = branch.selection == "svm"))
+graph_learner$param_set$values$ranger.mtry =
+  to_tune(p_int(1, 8, depends = branch.selection == "ranger"))
+graph_learner$id = "graph_learner"
+
+inner_resampling = rsmp("cv", folds = 3)
+at = AutoTuner$new(
+  learner = graph_learner,
+  resampling = inner_resampling,
+  measure = msr("classif.ce"),
+  terminator = trm("evals", n_evals = 10),
+  tuner = tnr("random_search")
+)
+
+outer_resampling = rsmp("cv", folds = 3)
+rr = resample(task, at, outer_resampling, store_models = TRUE)
+
+

We check the inner tuning results for stable hyperparameters. This means that the selected hyperparameters should not vary too much. We might observe unstable models in this example because the small data set and the low number of resampling iterations might introduce too much randomness. Usually, we aim for the selection of stable hyperparameters for all outer training sets.

+
+
extract_inner_tuning_results(rr)
+
+
+
+
+ +
+
+

Next, we want to compare the predictive performances estimated on the outer resampling to the inner resampling. Significantly lower predictive performances on the outer resampling indicate that the models with the optimized hyperparameters overfit the data.

+
+
rr$score()[, .(iteration, task_id, learner_id, resampling_id, classif.ce)]
+
+
   iteration task_id          learner_id resampling_id classif.ce
+1:         1    pima graph_learner.tuned            cv  0.2265625
+2:         2    pima graph_learner.tuned            cv  0.2382812
+3:         3    pima graph_learner.tuned            cv  0.2656250
+
+
+

The aggregated performance of all outer resampling iterations is essentially the unbiased performance of the graph learner with optimal hyperparameter found by random search.

+
+
rr$aggregate()
+
+
classif.ce 
+ 0.2434896 
+
+
+

Applying nested resampling can be shortened by using the tune_nested()-shortcut.

+
+
graph_learner = as_learner(graph)
+graph_learner$param_set$values$branch.selection =
+  to_tune(c("kknn", "svm", "ranger"))
+graph_learner$param_set$values$kknn.k =
+  to_tune(p_int(3, 50, logscale = TRUE, depends = branch.selection == "kknn"))
+graph_learner$param_set$values$svm.cost =
+  to_tune(p_dbl(-1, 1, trafo = function(x) 10^x, depends = branch.selection == "svm"))
+graph_learner$param_set$values$ranger.mtry =
+  to_tune(p_int(1, 8, depends = branch.selection == "ranger"))
+graph_learner$id = "graph_learner"
+
+rr = tune_nested(
+  tuner = tnr("random_search"),
+  task = task,
+  learner = graph_learner,
+  inner_resampling = rsmp("cv", folds = 3),
+  outer_resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce"),
+  term_evals = 10,
+)
+
+
+
+

Resources

+

The mlr3book includes chapters on pipelines and hyperparameter tuning. The mlr3cheatsheets contain frequently used commands and workflows of mlr3.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/optimization/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index_files/figure-html/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system-005-1.png b/gallery/optimization/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index_files/figure-html/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system-005-1.png new file mode 100644 index 00000000..49b83efc Binary files /dev/null and b/gallery/optimization/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index_files/figure-html/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system-005-1.png differ diff --git a/gallery/optimization/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index_files/figure-html/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system-008-1.png b/gallery/optimization/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index_files/figure-html/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system-008-1.png new file mode 100644 index 00000000..1cee5139 Binary files /dev/null and b/gallery/optimization/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index_files/figure-html/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system-008-1.png differ diff --git a/gallery/optimization/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index_files/figure-html/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system-014-1.png b/gallery/optimization/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index_files/figure-html/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system-014-1.png new file mode 100644 index 00000000..7abb4a4b Binary files /dev/null and b/gallery/optimization/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index_files/figure-html/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system-014-1.png differ diff --git a/gallery/optimization/2021-03-12-practical-tuning-series-tuning-and-parallel-processing/index.html b/gallery/optimization/2021-03-12-practical-tuning-series-tuning-and-parallel-processing/index.html new file mode 100644 index 00000000..57fa9585 --- /dev/null +++ b/gallery/optimization/2021-03-12-practical-tuning-series-tuning-and-parallel-processing/index.html @@ -0,0 +1,944 @@ + + + + + + + + + + + + + + + + + +Practical Tuning Series - Tuning and Parallel Processing – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Practical Tuning Series - Tuning and Parallel Processing

+
+
+

Run various jobs in mlr3 in parallel.

+
+
+
+
+ + +
+ +
+
Authors
+
+

Marc Becker

+

Theresa Ullmann

+

Michel Lang

+

Bernd Bischl

+

Jakob Richter

+

Martin Binder

+
+
+ +
+
Published
+
+

March 12, 2021

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Scope

+

This is the fourth part of the practical tuning series. The other parts can be found here:

+ +

In this post, we teach how to run various jobs in mlr3 in parallel. The goal is to map computational jobs (e.g. evaluation of one configuration) to a pool of workers (usually physical CPU cores, sometimes remote computational nodes) to reduce the run time needed for tuning.

+
+
+

Prerequisites

+

We load the mlr3verse package which pulls in the most important packages for this example. Additionally, make sure you have installed the packages future and future.apply.

+
+
library(mlr3verse)
+
+

We decrease the verbosity of the logger to keep the output clearly represented. The lgr package is used for logging in all mlr3 packages. The mlr3 logger prints the logging messages from the base package, whereas the bbotk logger is responsible for logging messages from the optimization packages (e.g. mlr3tuning ).

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+
+
+

Parallel Backend

+

The workers are specified by the parallel backend which orchestrates starting up, shutting down, and communication with the workers. On a single machine, multisession and multicore are common backends. The multisession backend spawns new background R processes. It is available on all platforms.

+
+
future::plan("multisession")
+
+

The multicore backend uses forked R processes which allows the workers to access R objects in a shared memory. This reduces the overhead since R objects are only copied in memory if they are modified. Unfortunately, forking processes is not supported on Windows and when running R from within RStudio.

+
+
future::plan("multicore")
+
+

Both backends support the workers argument that specifies the number of used cores.

+

Use this code if your code should run with the multicore backend when possible.

+
+
if (future::supportsMulticore()) {
+  future::plan(future::multicore)
+} else {
+  future::plan(future::multisession)
+}
+
+
+
+

Resampling

+

The resample() and benchmark() functions in mlr3 can be executed in parallel. The parallelization is triggered by simply declaring a plan via future::plan().

+
+
future::plan("multisession")
+
+task = tsk("pima")
+learner = lrn("classif.rpart") # classification tree
+resampling = rsmp("cv", folds = 3)
+
+resample(task, learner, resampling)
+
+
<ResampleResult> with 3 resampling iterations
+ task_id    learner_id resampling_id iteration warnings errors
+    pima classif.rpart            cv         1        0      0
+    pima classif.rpart            cv         2        0      0
+    pima classif.rpart            cv         3        0      0
+
+
+

The 3-fold cross-validation gives us 3 jobs since each resampling iteration is executed in parallel.

+

The benchmark() function accepts a design of experiments as input where each experiment is defined as a combination of a task, a learner, and a resampling strategy. For each experiment, resampling is performed. The nested loop over experiments and resampling iterations is flattened so that all resampling iterations of all experiments can be executed in parallel.

+
+
future::plan("multisession")
+
+tasks = list(tsk("pima"), tsk("iris"))
+learner = lrn("classif.rpart")
+resampling = rsmp("cv", folds = 3)
+
+grid = benchmark_grid(tasks, learner, resampling)
+
+benchmark(grid)
+
+
<BenchmarkResult> of 6 rows with 2 resampling runs
+ nr task_id    learner_id resampling_id iters warnings errors
+  1    pima classif.rpart            cv     3        0      0
+  2    iris classif.rpart            cv     3        0      0
+
+
+

The 2 experiments and the 3-fold cross-validation result in 6 jobs which are executed in parallel.

+
+
+

Tuning

+

The mlr3tuning package internally calls benchmark() during tuning. If the tuner is capable of suggesting multiple configurations per iteration (such as random search, grid search, or hyperband), these configurations represent individual experiments, and the loop flattening of benchmark() is triggered. E.g., all resampling iterations of all hyperparameter configurations on a grid can be executed in parallel.

+
+
future::plan("multisession")
+
+learner = lrn("classif.rpart")
+learner$param_set$values$cp = to_tune(0.001, 0.1)
+learner$param_set$values$minsplit = to_tune(1, 10)
+
+instance = tune(
+  tuner = tnr("random_search", batch_size = 5), # random search suggests 5 configurations per batch
+  task = tsk("pima"),
+  learner = learner,
+  resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce"),
+  term_evals = 10
+)
+
+

The batch size of 5 and the 3-fold cross-validation gives us 15 jobs. This is done twice because of the limit of 10 evaluations in total.

+
+
+

Nested Resampling

+

Nested resampling results in two nested resampling loops. For this, an AutoTuner is passed to resample() or benchmark(). We can choose different parallelization backends for the inner and outer resampling loop, respectively. We just have to pass a list of backends.

+
+
# Runs the outer loop in parallel and the inner loop sequentially
+future::plan(list("multisession", "sequential"))
+
+# Runs the outer loop sequentially and the inner loop in parallel
+future::plan(list("sequential", "multisession"))
+
+learner = lrn("classif.rpart")
+learner$param_set$values$cp = to_tune(0.001, 0.1)
+learner$param_set$values$minsplit = to_tune(1, 10)
+
+rr = tune_nested(
+  tuner = tnr("random_search", batch_size = 5), # random search suggests 5 configurations per batch
+  task = tsk("pima"),
+  learner = learner,
+  inner_resampling = rsmp ("cv", folds = 3),
+  outer_resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce"),
+  term_evals = 10
+)
+
+

While nesting real parallelization backends is often unintended and causes unnecessary overhead, it is useful in some distributed computing setups. It can be achieved with future by forcing a fixed number of workers for each loop.

+
+
# Runs both loops in parallel
+future::plan(list(future::tweak("multisession", workers = 2),
+                  future::tweak("multisession", workers = 4)))
+
+

This example would run on 8 cores (= 2 * 4) on the local machine.

+
+
+

Resources

+

The mlr3book includes a chapters on parallelization. The mlr3cheatsheets contain frequently used commands and workflows of mlr3.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/optimization/2021-07-06-introduction-to-mlr3tuningspaces/cover.png b/gallery/optimization/2021-07-06-introduction-to-mlr3tuningspaces/cover.png new file mode 100644 index 00000000..faf4e3ec Binary files /dev/null and b/gallery/optimization/2021-07-06-introduction-to-mlr3tuningspaces/cover.png differ diff --git a/gallery/optimization/2021-07-06-introduction-to-mlr3tuningspaces/index.html b/gallery/optimization/2021-07-06-introduction-to-mlr3tuningspaces/index.html new file mode 100644 index 00000000..277d976a --- /dev/null +++ b/gallery/optimization/2021-07-06-introduction-to-mlr3tuningspaces/index.html @@ -0,0 +1,1210 @@ + + + + + + + + + + + + +Introduction to mlr3tuningspaces – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Introduction to mlr3tuningspaces

+
+
+

Apply predefined search spaces from scientific articles.

+
+
+ +
+ + +
+ +
+
Author
+
+

Marc Becker

+
+
+ +
+
Published
+
+

July 6, 2021

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Scope

+

The package mlr3tuningspaces offers a selection of published search spaces for many popular machine learning algorithms. In this post, we show how to tune a mlr3 learners with these search spaces.

+
+
+

Prerequisites

+

The packages mlr3verse and mlr3tuningspaces are required for this demonstration:

+
+
library(mlr3verse)
+library(mlr3tuningspaces)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+

In the example, we use the pima indian diabetes data set which is used to predict whether or not a patient has diabetes. The patients are characterized by 8 numeric features, some of them have missing values.

+
+
# retrieve the task from mlr3
+task = tsk("pima")
+
+# generate a quick textual overview using the skimr package
+skimr::skim(task$data())
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Data summary
Nametask$data()
Number of rows768
Number of columns9
KeyNULL
_______________________
Column type frequency:
factor1
numeric8
________________________
Group variablesNone
+

Variable type: factor

+ ++++++++ + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_rateorderedn_uniquetop_counts
diabetes01FALSE2neg: 500, pos: 268
+

Variable type: numeric

+ +++++++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_ratemeansdp0p25p50p75p100hist
age01.0033.2411.7621.0024.0029.0041.0081.00▇▃▁▁▁
glucose50.99121.6930.5444.0099.00117.00141.00199.00▁▇▇▃▂
insulin3740.51155.55118.7814.0076.25125.00190.00846.00▇▂▁▁▁
mass110.9932.466.9218.2027.5032.3036.6067.10▅▇▃▁▁
pedigree01.000.470.330.080.240.370.632.42▇▃▁▁▁
pregnant01.003.853.370.001.003.006.0017.00▇▃▂▁▁
pressure350.9572.4112.3824.0064.0072.0080.00122.00▁▃▇▂▁
triceps2270.7029.1510.487.0022.0029.0036.0099.00▆▇▁▁▁
+
+
+
+
+

Tuning Search Space

+

For tuning, it is important to create a search space that defines the type and range of the hyperparameters. A learner stores all information about its hyperparameters in the slot $param_set. Usually, we have to chose a subset of hyperparameters we want to tune.

+
+
lrn("classif.rpart")$param_set
+
+
<ParamSet>
+                id    class lower upper nlevels        default value
+ 1:             cp ParamDbl     0     1     Inf           0.01      
+ 2:     keep_model ParamLgl    NA    NA       2          FALSE      
+ 3:     maxcompete ParamInt     0   Inf     Inf              4      
+ 4:       maxdepth ParamInt     1    30      30             30      
+ 5:   maxsurrogate ParamInt     0   Inf     Inf              5      
+ 6:      minbucket ParamInt     1   Inf     Inf <NoDefault[3]>      
+ 7:       minsplit ParamInt     1   Inf     Inf             20      
+ 8: surrogatestyle ParamInt     0     1       2              0      
+ 9:   usesurrogate ParamInt     0     2       3              2      
+10:           xval ParamInt     0   Inf     Inf             10     0
+
+
+
+
+

Package

+

At the heart of mlr3tuningspaces is the R6 class TuningSpace. It stores a list of TuneToken, helper functions and additional meta information. The list of TuneToken can be directly applied to the $values slot of a learner’s ParamSet. The search spaces are stored in the mlr_tuning_spaces dictionary.

+
+
as.data.table(mlr_tuning_spaces)
+
+
                        key                                 label         learner n_values
+ 1:  classif.glmnet.default       Classification GLM with Default  classif.glmnet        2
+ 2:     classif.glmnet.rbv1     Classification GLM with RandomBot  classif.glmnet        2
+ 3:     classif.glmnet.rbv2     Classification GLM with RandomBot  classif.glmnet        2
+ 4:    classif.kknn.default      Classification KKNN with Default    classif.kknn        3
+ 5:       classif.kknn.rbv1    Classification KKNN with RandomBot    classif.kknn        1
+ 6:       classif.kknn.rbv2    Classification KKNN with RandomBot    classif.kknn        1
+ 7:  classif.ranger.default    Classification Ranger with Default  classif.ranger        4
+ 8:     classif.ranger.rbv1  Classification Ranger with RandomBot  classif.ranger        6
+ 9:     classif.ranger.rbv2  Classification Ranger with RandomBot  classif.ranger        8
+10:   classif.rpart.default     Classification Rpart with Default   classif.rpart        3
+11:      classif.rpart.rbv1   Classification Rpart with RandomBot   classif.rpart        4
+12:      classif.rpart.rbv2   Classification Rpart with RandomBot   classif.rpart        4
+13:     classif.svm.default       Classification SVM with Default     classif.svm        4
+14:        classif.svm.rbv1     Classification SVM with RandomBot     classif.svm        4
+15:        classif.svm.rbv2     Classification SVM with RandomBot     classif.svm        5
+16: classif.xgboost.default   Classification XGBoost with Default classif.xgboost        8
+17:    classif.xgboost.rbv1 Classification XGBoost with RandomBot classif.xgboost       10
+18:    classif.xgboost.rbv2 Classification XGBoost with RandomBot classif.xgboost       13
+19:     regr.glmnet.default           Regression GLM with Default     regr.glmnet        2
+20:        regr.glmnet.rbv1         Regression GLM with RandomBot     regr.glmnet        2
+21:        regr.glmnet.rbv2         Regression GLM with RandomBot     regr.glmnet        2
+22:       regr.kknn.default          Regression KKNN with Default       regr.kknn        3
+23:          regr.kknn.rbv1        Regression KKNN with RandomBot       regr.kknn        1
+24:          regr.kknn.rbv2        Regression KKNN with RandomBot       regr.kknn        1
+25:     regr.ranger.default        Regression Ranger with Default     regr.ranger        4
+26:        regr.ranger.rbv1      Regression Ranger with RandomBot     regr.ranger        6
+27:        regr.ranger.rbv2      Regression Ranger with RandomBot     regr.ranger        7
+28:      regr.rpart.default         Regression Rpart with Default      regr.rpart        3
+29:         regr.rpart.rbv1       Regression Rpart with RandomBot      regr.rpart        4
+30:         regr.rpart.rbv2       Regression Rpart with RandomBot      regr.rpart        4
+31:        regr.svm.default           Regression SVM with Default        regr.svm        4
+32:           regr.svm.rbv1         Regression SVM with RandomBot        regr.svm        4
+33:           regr.svm.rbv2         Regression SVM with RandomBot        regr.svm        5
+34:    regr.xgboost.default       Regression XGBoost with Default    regr.xgboost        8
+35:       regr.xgboost.rbv1     Regression XGBoost with RandomBot    regr.xgboost       10
+36:       regr.xgboost.rbv2     Regression XGBoost with RandomBot    regr.xgboost       13
+                        key                                 label         learner n_values
+
+
+

We can use the sugar function lts() to retrieve a TuningSpace.

+
+
tuning_space_rpart = lts("classif.rpart.default")
+tuning_space_rpart
+
+
<TuningSpace:classif.rpart.default>: Classification Rpart with Default
+          id lower upper levels logscale
+1:  minsplit 2e+00 128.0            TRUE
+2: minbucket 1e+00  64.0            TRUE
+3:        cp 1e-04   0.1            TRUE
+
+
+

The $values slot contains the list of of TuneToken.

+
+
tuning_space_rpart$values
+
+
$minsplit
+Tuning over:
+range [2, 128] (log scale)
+
+
+$minbucket
+Tuning over:
+range [1, 64] (log scale)
+
+
+$cp
+Tuning over:
+range [1e-04, 0.1] (log scale)
+
+
+

We apply the search space and tune the learner.

+
+
learner = lrn("classif.rpart")
+
+learner$param_set$values = tuning_space_rpart$values
+
+instance = tune(
+  tuner = tnr("random_search"),
+  task = tsk("pima"),
+  learner = learner,
+  resampling = rsmp ("holdout"),
+  measure = msr("classif.ce"),
+  term_evals = 10)
+
+instance$result
+
+
   minsplit minbucket        cp learner_param_vals  x_domain classif.ce
+1:  3.40059  1.963618 -4.114895          <list[3]> <list[3]>  0.2539062
+
+
+

We can also get the learner with search space already applied from the TuningSpace.

+
+
learner = tuning_space_rpart$get_learner()
+print(learner$param_set)
+
+
<ParamSet>
+                id    class lower upper nlevels        default               value
+ 1:             cp ParamDbl     0     1     Inf           0.01 <RangeTuneToken[2]>
+ 2:     keep_model ParamLgl    NA    NA       2          FALSE                    
+ 3:     maxcompete ParamInt     0   Inf     Inf              4                    
+ 4:       maxdepth ParamInt     1    30      30             30                    
+ 5:   maxsurrogate ParamInt     0   Inf     Inf              5                    
+ 6:      minbucket ParamInt     1   Inf     Inf <NoDefault[3]> <RangeTuneToken[2]>
+ 7:       minsplit ParamInt     1   Inf     Inf             20 <RangeTuneToken[2]>
+ 8: surrogatestyle ParamInt     0     1       2              0                    
+ 9:   usesurrogate ParamInt     0     2       3              2                    
+10:           xval ParamInt     0   Inf     Inf             10                   0
+
+
+

This method also allows to set constant parameters.

+
+
learner = tuning_space_rpart$get_learner(maxdepth = 15)
+print(learner$param_set)
+
+
<ParamSet>
+                id    class lower upper nlevels        default               value
+ 1:             cp ParamDbl     0     1     Inf           0.01 <RangeTuneToken[2]>
+ 2:     keep_model ParamLgl    NA    NA       2          FALSE                    
+ 3:     maxcompete ParamInt     0   Inf     Inf              4                    
+ 4:       maxdepth ParamInt     1    30      30             30                  15
+ 5:   maxsurrogate ParamInt     0   Inf     Inf              5                    
+ 6:      minbucket ParamInt     1   Inf     Inf <NoDefault[3]> <RangeTuneToken[2]>
+ 7:       minsplit ParamInt     1   Inf     Inf             20 <RangeTuneToken[2]>
+ 8: surrogatestyle ParamInt     0     1       2              0                    
+ 9:   usesurrogate ParamInt     0     2       3              2                    
+10:           xval ParamInt     0   Inf     Inf             10                   0
+
+
+

The lts() function sets the default search space directly to a learner.

+
+
learner = lts(lrn("classif.rpart", maxdepth = 15))
+print(learner$param_set)
+
+
<ParamSet>
+                id    class lower upper nlevels        default               value
+ 1:             cp ParamDbl     0     1     Inf           0.01 <RangeTuneToken[2]>
+ 2:     keep_model ParamLgl    NA    NA       2          FALSE                    
+ 3:     maxcompete ParamInt     0   Inf     Inf              4                    
+ 4:       maxdepth ParamInt     1    30      30             30                  15
+ 5:   maxsurrogate ParamInt     0   Inf     Inf              5                    
+ 6:      minbucket ParamInt     1   Inf     Inf <NoDefault[3]> <RangeTuneToken[2]>
+ 7:       minsplit ParamInt     1   Inf     Inf             20 <RangeTuneToken[2]>
+ 8: surrogatestyle ParamInt     0     1       2              0                    
+ 9:   usesurrogate ParamInt     0     2       3              2                    
+10:           xval ParamInt     0   Inf     Inf             10                   0
+
+
+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/optimization/2022-11-04-early-stopping-with-xgboost/cover.jpg b/gallery/optimization/2022-11-04-early-stopping-with-xgboost/cover.jpg new file mode 100644 index 00000000..c5103ff6 Binary files /dev/null and b/gallery/optimization/2022-11-04-early-stopping-with-xgboost/cover.jpg differ diff --git a/gallery/optimization/2022-11-04-early-stopping-with-xgboost/index.html b/gallery/optimization/2022-11-04-early-stopping-with-xgboost/index.html new file mode 100644 index 00000000..b6b8243c --- /dev/null +++ b/gallery/optimization/2022-11-04-early-stopping-with-xgboost/index.html @@ -0,0 +1,972 @@ + + + + + + + + + + + + +Early Stopping with XGBoost – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Early Stopping with XGBoost

+
+
+

Simultaneously optimize hyperparameters and use early stopping.

+
+
+ +
+ + +
+ +
+
Author
+
+

Marc Becker

+
+
+ +
+
Published
+
+

November 9, 2022

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Scope

+

In this post, we use early stopping to reduce overfitting when training an XGBoost model. We start with a short recap on early stopping and overfitting. After that, we use the early stopping mechanism of XGBoost and train a model on the Spam Classification data set. Finally we show how to simultaneously tune hyperparameters and use early stopping. The reader should be familiar with tuning in the mlr3 ecosystem.

+
+
+

Early Stopping

+

Early stopping is a technique used to reduce overfitting when fitting a model in an iterative process. Overfitting occurs when a model fits increasingly to the training data but the performance on unseen data decreases. This means the model’s training error decreases, while its test performance deteriorates. When using early stopping, the performance is monitored on a test set, and the training stops when performance decreases in a specific number of iterations.

+
+
+

XGBoost with Early Stopping

+

We initialize the random number generator with a fixed seed for reproducibility. The mlr3verse package provides all functions required for this example.

+
+
set.seed(7832)
+
+library(mlr3verse)
+
+

When training an XGBoost model, we can use early stopping to find the optimal number of boosting rounds. The partition() function splits the observations of the task into two disjoint sets. We use 80% of observations to train the model and the remaining 20% as the test set to monitor the performance.

+
+
task = tsk("spam")
+split = partition(task, ratio = 0.8)
+task$set_row_roles(split$test, "test")
+
+

The early_stopping_set parameter controls which set is used to monitor the performance. Additionally, we need to define the range in which the performance must increase with early_stopping_rounds and the maximum number of boosting rounds with nrounds. In this example, the training is stopped when the classification error is not decreasing for 100 rounds or 1000 rounds are reached.

+
+
learner = lrn("classif.xgboost",
+  nrounds = 1000,
+  early_stopping_rounds = 100,
+  early_stopping_set = "test",
+  eval_metric = "error"
+)
+
+

We train the learner with early stopping.

+
+
learner$train(task)
+
+

The $evaluation_log of the model stores the performance scores on the training and test set. Figure 1 shows that the classification error on the training set decreases, whereas the error on the test set increases after 20 rounds.

+
+
+Code +
library(ggplot2)
+library(data.table)
+
+data = melt(
+  learner$model$evaluation_log,
+  id.vars = "iter",
+  variable.name = "set",
+  value.name = "error"
+)
+
+ggplot(data, aes(x = iter, y = error, group = set)) +
+  geom_line(aes(color = set)) +
+  geom_vline(aes(xintercept = learner$model$best_iteration), color = "grey") +
+  scale_colour_manual(values=c("#f8766d", "#00b0f6"), labels = c("Train", "Test")) +
+  labs(x = "Rounds", y = "Classification Error", color = "Set") +
+  theme_minimal()
+
+
+
+
+

+
Comparison between train and test set classification error.
+
+
+
+
+

The slot $best_iteration contains the optimal number of boosting rounds.

+
+
learner$model$best_iteration
+
+
[1] 20
+
+
+

Note that, learner$predict() will use the model from the last iteration, not the best one. See the next section on how to fit a model with the optimal number of boosting rounds and hyperparameter configuration.

+
+
+

Tuning

+

In this section, we want to tune the hyperparameters of an XGBoost model and find the optimal number of boosting rounds in one go. For this, we need the early stopping callback which handles early stopping during the tuning process. The performance of a hyperparameter configuration is evaluated with a resampling strategy while tuning e.g. 3-fold cross-validation. In each resampling iteration, a new XGBoost model is trained and early stopping is used to find the optimal number of boosting rounds. This results in three different optimal numbers of boosting rounds for one hyperparameter configuration when applying 3-fold cross-validation. The callback picks the maximum of the three values and writes it to the archive. It uses the maximum value because the final model is fitted on the complete data set. Now let’s start with a practical example.

+

First, we load the XGBoost learner and set the early stopping parameters.

+
+
learner = lrn("classif.xgboost",
+  nrounds = 1000,
+  early_stopping_rounds = 100,
+  early_stopping_set = "test"
+)
+
+

Next, we load a predefined tuning space from the mlr3tuningspaces package. The tuning space includes the most commonly tuned parameters of XGBoost.

+
+
tuning_space = lts("classif.xgboost.default")
+as.data.table(tuning_space)
+
+
                  id lower upper logscale
+1:               eta 1e-04     1     TRUE
+2:           nrounds 1e+00  5000    FALSE
+3:         max_depth 1e+00    20    FALSE
+4:  colsample_bytree 1e-01     1    FALSE
+5: colsample_bylevel 1e-01     1    FALSE
+6:            lambda 1e-03  1000     TRUE
+7:             alpha 1e-03  1000     TRUE
+8:         subsample 1e-01     1    FALSE
+
+
+

We argument the learner with the tuning space.

+
+
learner = lts(learner)
+
+

The default tuning space contains the nrounds hyperparameter. We have to overwrite it with an upper bound for early stopping.

+
+
learner$param_set$set_values(nrounds = 1000)
+
+

We run a small batch of random hyperparameter configurations.

+
+
instance = tune(
+  tuner = tnr("random_search", batch_size = 2),
+  task = task,
+  learner = learner,
+  resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce"),
+  term_evals = 4,
+  callbacks = clbk("mlr3tuning.early_stopping")
+)
+
+

We can see that the optimal number of boosting rounds (max_nrounds) strongly depends on the other hyperparameters.

+
+
as.data.table(instance$archive)[, list(batch_nr, max_nrounds, eta, max_depth, colsample_bytree, colsample_bylevel, lambda, alpha, subsample)]
+
+
   batch_nr max_nrounds       eta max_depth colsample_bytree colsample_bylevel     lambda     alpha subsample
+1:        1        1000 -4.129996        13        0.5466492         0.3051989 -0.9448420  2.535477 0.5454539
+2:        1         998 -3.338899         8        0.6193478         0.7392354 -2.2338126  1.793921 0.2294161
+3:        2        1000 -6.059897         5        0.6118892         0.5445475 -6.5698270  5.414224 0.9635730
+4:        2        1000 -4.528129         1        0.1094186         0.2526143 -0.7535105 -3.041829 0.5934376
+
+
+

In the best hyperparameter configuration, the value of nrounds is replaced by max_nrounds and early stopping is deactivated.

+
+
instance$result_learner_param_vals
+
+
$nrounds
+[1] 998
+
+$nthread
+[1] 1
+
+$verbose
+[1] 0
+
+$early_stopping_set
+[1] "none"
+
+$eta
+[1] 0.03547598
+
+$max_depth
+[1] 8
+
+$colsample_bytree
+[1] 0.6193478
+
+$colsample_bylevel
+[1] 0.7392354
+
+$lambda
+[1] 0.1071192
+
+$alpha
+[1] 6.012984
+
+$subsample
+[1] 0.2294161
+
+
+

Finally, fit the final model on the complete data set.

+
+
learner = lrn("classif.xgboost")
+learner$param_set$values = instance$result_learner_param_vals
+learner$train(task)
+
+

The trained model can now be used to make predictions on new data.

+

We can also use the AutoTuner to get a tuned XGBoost model. Note that, early stopping is deactivated when the final model is fitted.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/optimization/2022-11-04-early-stopping-with-xgboost/index_files/figure-html/2022-11-04-early-stopping-with-xgboost-006-1.png b/gallery/optimization/2022-11-04-early-stopping-with-xgboost/index_files/figure-html/2022-11-04-early-stopping-with-xgboost-006-1.png new file mode 100644 index 00000000..097f549d Binary files /dev/null and b/gallery/optimization/2022-11-04-early-stopping-with-xgboost/index_files/figure-html/2022-11-04-early-stopping-with-xgboost-006-1.png differ diff --git a/gallery/optimization/2022-11-04-early-stopping-with-xgboost/index_files/figure-html/early-stopping-with-xgboost-007-1.png b/gallery/optimization/2022-11-04-early-stopping-with-xgboost/index_files/figure-html/early-stopping-with-xgboost-007-1.png new file mode 100644 index 00000000..097f549d Binary files /dev/null and b/gallery/optimization/2022-11-04-early-stopping-with-xgboost/index_files/figure-html/early-stopping-with-xgboost-007-1.png differ diff --git a/gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/cover.png b/gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/cover.png new file mode 100644 index 00000000..736ae89b Binary files /dev/null and b/gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/cover.png differ diff --git a/gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/index.html b/gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/index.html new file mode 100644 index 00000000..5d85d1e0 --- /dev/null +++ b/gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/index.html @@ -0,0 +1,1047 @@ + + + + + + + + + + + + +Hyperparameter Optimization on the Palmer Penguins Data Set – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Hyperparameter Optimization on the Palmer Penguins Data Set

+
+
+

Optimize the hyperparameters of a classification tree with a few lines of code.

+
+
+ +
+ + +
+ +
+
Author
+ +
+ +
+
Published
+
+

November 10, 2022

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Scope

+

In this post, we optimize the hyperparameters of a simple classification tree on the Palmer Penguins data set with only a few lines of code.

+

First, we introduce tuning spaces and show the importance of transformation functions. Next, we execute the tuning and present the basic building blocks of tuning in mlr3. Finally, we fit a classification tree with optimized hyperparameters on the full data set.

+
+
+

Prerequistes

+

We load the mlr3verse package which pulls the most important packages for this example. Among other packages, it loads the hyperparameter optimization package of the mlr3 ecosystem mlr3tuning.

+
+
library(mlr3verse)
+
+

In this example, we use the Palmer Penguins data set which classifies 344 penguins in three species. The data set was collected from 3 islands in the Palmer Archipelago in Antarctica. It includes the name of the island, the size (flipper length, body mass, and bill dimension), and the sex of the penguin.

+
+
tsk("penguins")
+
+
<TaskClassif:penguins> (344 x 8): Palmer Penguins
+* Target: species
+* Properties: multiclass
+* Features (7):
+  - int (3): body_mass, flipper_length, year
+  - dbl (2): bill_depth, bill_length
+  - fct (2): island, sex
+
+
+
+
+Code +
library(palmerpenguins)
+library(ggplot2)
+ggplot(data = penguins, aes(x = flipper_length_mm, y = bill_length_mm)) +
+  geom_point(aes(color = species, shape = species), size = 3, alpha = 0.8) +
+  geom_smooth(method = "lm", se = FALSE, aes(color = species)) +
+  theme_minimal() +
+  scale_color_manual(values = c("darkorange","purple","cyan4")) +
+  labs(x = "Flipper length (mm)", y = "Bill length (mm)",  color = "Penguin species", shape = "Penguin species") +
+  theme(
+    legend.position = c(0.85, 0.15),
+    legend.background = element_rect(fill = "white", color = NA),
+    text = element_text(size = 10))
+
+
+
+
+

+
Flipper and bill length dimensions for Adelie, Chinstrap, and Gentoo Penguins at Palmer Station (Horst 2022).
+
+
+
+
+
+
+

Learner

+

We use the rpart classification tree. A learner stores all information about its hyperparameters in the slot $param_set. Not all parameters are tunable. We have to choose a subset of the hyperparameters we want to tune.

+
+
learner = lrn("classif.rpart")
+as.data.table(learner$param_set)[, list(id, class, lower, upper, nlevels)]
+
+
                id    class lower upper nlevels
+            <char>   <char> <num> <num>   <num>
+ 1:             cp ParamDbl     0     1     Inf
+ 2:     keep_model ParamLgl    NA    NA       2
+ 3:     maxcompete ParamInt     0   Inf     Inf
+ 4:       maxdepth ParamInt     1    30      30
+ 5:   maxsurrogate ParamInt     0   Inf     Inf
+ 6:      minbucket ParamInt     1   Inf     Inf
+ 7:       minsplit ParamInt     1   Inf     Inf
+ 8: surrogatestyle ParamInt     0     1       2
+ 9:   usesurrogate ParamInt     0     2       3
+10:           xval ParamInt     0   Inf     Inf
+
+
+
+
+

Tuning Space

+

The package mlr3tuningspaces is a collection of search spaces for hyperparameter tuning from peer-reviewed articles. We use the search space from the Bischl et al. (2021) article.

+
+
lts("classif.rpart.default")
+
+
<TuningSpace:classif.rpart.default>: Classification Rpart with Default
+          id lower upper levels logscale
+      <char> <num> <num> <list>   <lgcl>
+1:  minsplit 2e+00 128.0            TRUE
+2: minbucket 1e+00  64.0            TRUE
+3:        cp 1e-04   0.1            TRUE
+
+
+

The classification tree is mainly influenced by three hyperparameters:

+
    +
  • The complexity hyperparameter cp that controls when the learner considers introducing another branch.
  • +
  • The minsplit hyperparameter that controls how many observations must be present in a leaf for another split to be attempted.
  • +
  • The minbucket hyperparameter that the minimum number of observations in any terminal node.
  • +
+

We argument the learner with the search space in one go.

+
+
lts(lrn("classif.rpart"))
+
+
<LearnerClassifRpart:classif.rpart>: Classification Tree
+* Model: -
+* Parameters: xval=0, minsplit=<RangeTuneToken>, minbucket=<RangeTuneToken>, cp=<RangeTuneToken>
+* Packages: mlr3, rpart
+* Predict Types:  [response], prob
+* Feature Types: logical, integer, numeric, factor, ordered
+* Properties: importance, missings, multiclass, selected_features, twoclass, weights
+
+
+
+

Transformations

+

The column logscale indicates that the hyperparameters are tuned on the logarithmic scale. The tuning algorithm proposes hyperparameter values that are transformed with the exponential function before they are passed to the learner. For example, the cp parameter is bounded between 0 and 1. The tuning algorithm searches between log(1e-04) and log(1e-01) but the learner gets the transformed values between 1e-04 and 1e-01. Using the log transformation emphasizes smaller cp values but also creates large values.

+
+
lts("classif.rpart.default")
+
+
<TuningSpace:classif.rpart.default>: Classification Rpart with Default
+          id lower upper levels logscale
+      <char> <num> <num> <list>   <lgcl>
+1:  minsplit 2e+00 128.0            TRUE
+2: minbucket 1e+00  64.0            TRUE
+3:        cp 1e-04   0.1            TRUE
+
+
+
+
+
+

Tuning

+

The tune() function controls and executes the tuning. The method sets the optimization algorithm. The mlr3 ecosystem offers various optimization algorithms e.g. Random Search, GenSA, and Hyperband. In this example, we will use a simple grid search with a grid resolution of 5. Our three-dimensional grid consists of \(5^3 = 125\) hyperparameter configurations. The resampling strategy and performance measure specify how the performance of a model is evaluated. We choose a 3-fold cross-validation and use the classification error.

+
+
instance = tune(
+  tuner = tnr("grid_search", resolution = 5),
+  task = tsk("penguins"),
+  learner = lts(lrn("classif.rpart")),
+  resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce")
+)
+
+

The tune() function returns a tuning instance that includes an archive with all evaluated hyperparameter configurations.

+
+
as.data.table(instance$archive)[, list(minsplit, minbucket, cp, classif.ce, resample_result)]
+
+
      minsplit minbucket        cp classif.ce      resample_result
+         <num>     <num>     <num>      <num>               <list>
+  1: 2.7764798  2.087194 -2.302585 0.06107297 <ResampleResult[21]>
+  2: 1.7348135  4.174387 -2.302585 0.18001526 <ResampleResult[21]>
+  3: 0.6931472  1.043597 -9.210340 0.02906178 <ResampleResult[21]>
+  4: 0.6931472  3.130790 -9.210340 0.06107297 <ResampleResult[21]>
+  5: 2.7764798  3.130790 -4.029524 0.06107297 <ResampleResult[21]>
+ ---                                                              
+121: 3.8181461  0.000000 -5.756463 0.04065599 <ResampleResult[21]>
+122: 0.6931472  0.000000 -7.483402 0.02616323 <ResampleResult[21]>
+123: 0.6931472  3.130790 -2.302585 0.06107297 <ResampleResult[21]>
+124: 1.7348135  2.087194 -4.029524 0.04937707 <ResampleResult[21]>
+125: 3.8181461  0.000000 -2.302585 0.06107297 <ResampleResult[21]>
+
+
+

The best configuration and the corresponding measured performance can be retrieved from the tuning instance.

+
+
instance$result
+
+
    minsplit minbucket       cp learner_param_vals  x_domain classif.ce
+       <num>     <num>    <num>             <list>    <list>      <num>
+1: 0.6931472         0 -9.21034          <list[4]> <list[3]> 0.02616323
+
+
+

The $result_learner_param_vals field contains the best hyperparameter setting on the learner scale.

+
+
instance$result_learner_param_vals
+
+
$xval
+[1] 0
+
+$minsplit
+[1] 2
+
+$minbucket
+[1] 1
+
+$cp
+[1] 1e-04
+
+
+
+
+

Final Model

+

The learner we use to make predictions on new data is called the final model. The final model is trained on the full data set. We add the optimized hyperparameters to the learner and train the learner on the full dataset.

+
+
learner = lrn("classif.rpart")
+learner$param_set$values = instance$result_learner_param_vals
+learner$train(tsk("penguins"))
+
+

The trained model can now be used to predict new, external data.

+ + + +
+ +

References

+
+Bischl, Bernd, Martin Binder, Michel Lang, Tobias Pielok, Jakob Richter, Stefan Coors, Janek Thomas, et al. 2021. “Hyperparameter Optimization: Foundations, Algorithms, Best Practices and Open Challenges.” arXiv:2107.05847 [Cs, Stat], July. http://arxiv.org/abs/2107.05847. +
+
+Horst, Allison. 2022. “Palmer Penguins Artwork and Figures.” https://github.com/allisonhorst. +
+
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/index_files/figure-html/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins-005-1.png b/gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/index_files/figure-html/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins-005-1.png new file mode 100644 index 00000000..dc95fe1e Binary files /dev/null and b/gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/index_files/figure-html/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins-005-1.png differ diff --git a/gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/index_files/figure-html/hyperparameter-tuning-on-the-palmer-penguins-data-set-005-1.png b/gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/index_files/figure-html/hyperparameter-tuning-on-the-palmer-penguins-data-set-005-1.png new file mode 100644 index 00000000..5cece8d7 Binary files /dev/null and b/gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/index_files/figure-html/hyperparameter-tuning-on-the-palmer-penguins-data-set-005-1.png differ diff --git a/gallery/optimization/2023-01-15-hyperband-xgboost/cover.png b/gallery/optimization/2023-01-15-hyperband-xgboost/cover.png new file mode 100644 index 00000000..c32437ba Binary files /dev/null and b/gallery/optimization/2023-01-15-hyperband-xgboost/cover.png differ diff --git a/gallery/optimization/2023-01-15-hyperband-xgboost/index.html b/gallery/optimization/2023-01-15-hyperband-xgboost/index.html new file mode 100644 index 00000000..31aedc41 --- /dev/null +++ b/gallery/optimization/2023-01-15-hyperband-xgboost/index.html @@ -0,0 +1,984 @@ + + + + + + + + + + + + + +Hyperband Series - Iterative Training – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Hyperband Series - Iterative Training

+
+
+

Optimize the hyperparameters of an XGBoost model with Hyperband.

+
+
+ +
+ + +
+ +
+
Authors
+ +
+ +
+
Published
+
+

January 15, 2023

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Scope

+

Increasingly large data sets and search spaces make hyperparameter optimization a time-consuming task. Hyperband (Li et al. 2018) solves this by approximating the performance of a configuration on a simplified version of the problem such as a small subset of the training data, with just a few training epochs in a neural network, or with only a small number of iterations in a gradient-boosting model. After starting randomly sampled configurations, Hyperband iteratively allocates more resources to promising configurations and terminates low-performing ones. This type of optimization is called multi-fidelity optimization. The fidelity parameter is part of the search space and controls the tradeoff between the runtime and accuracy of the performance approximation. In this post, we will optimize XGBoost and use the number of boosting iterations as the fidelity parameter. This means Hyperband will allocate more boosting iterations to well-performing configurations. The number of boosting iterations increases the time to train a model and improves the performance until the model is overfitting to the training data. It is therefore a suitable fidelity parameter. We assume that you are already familiar with tuning in the mlr3 ecosystem. If not, you should start with the book chapter on optimization or the Hyperparameter Optimization on the Palmer Penguins Data Set post. This is the first part of the Hyperband series. The second part can be found here Hyperband Series - Data Set Subsampling.

+
+
+

Hyperband

+

Hyperband is an advancement of the Successive Halving algorithm by Jamieson and Talwalkar (2016). Successive Halving is initialized with the number of starting configurations \(n\), the proportion of configurations discarded in each stage \(\eta\), and the minimum \(r{_{min}}\) and maximum \(r{_{max}}\) budget of a single evaluation. The algorithm starts by sampling \(n\) random configurations and allocating the minimum budget \(r{_{min}}\) to them. The configurations are evaluated and \(\frac{1}{\eta}\) of the worst-performing configurations are discarded. The remaining configurations are promoted to the next stage and evaluated on a larger budget. This continues until one or more configurations are evaluated on the maximum budget \(r{_{max}}\) and the best performing configuration is selected. The number of stages is calculated so that each stage consumes approximately the same budget. This sometimes results in the minimum budget having to be slightly adjusted by the algorithm. Successive Halving has the disadvantage that is not clear whether we should choose a large \(n\) and try many configurations on a small budget or choose a small \(n\) and train more configurations on the full budget.

+

Hyperband solves this problem by running Successive Halving with different numbers of stating configurations. The algorithm is initialized with the same parameters as Successive Halving but without \(n\). Each run of Successive Halving is called a bracket and starts with a different budget \(r{_{0}}\). A smaller starting budget means that more configurations can be tried out. The most explorative bracket allocated the minimum budget \(r{_{min}}\). The next bracket increases the starting budget by a factor of \(\eta\). In each bracket, the starting budget increases further until the last bracket \(s = 0\) essentially performs a random search with the full budget \(r{_{max}}\). The number of brackets \(s{_{max}} + 1\) is calculated with \(s{_{max}} = {\log_\eta \frac{r{_{max}} }{r{_{min}}}}\). Under the condition that \(r{_{0}}\) increases by \(\eta\) with each bracket, \(r{_{min}}\) sometimes has to be adjusted slightly in order not to use more than \(r{_{max}}\) resources in the last bracket. The number of configurations in the base stages is calculated so that each bracket uses approximately the same amount of budget. The following table shows a full run of the Hyperband algorithm. The bracket \(s = 3\) is the most explorative bracket and \(s = 0\) performance a random search on the full budget.

+
+
+
+
+
+ +
+
+Figure 1: Hyperband schedule with \(\eta = 2\) , \(r{_{min}} = 1\) and \(r{_{max}} = 8\) +
+
+
+
+

The Hyperband implementation in mlr3hyperband evaluates configurations with the same budget in parallel. This results in all brackets finishing at approximately the same time. The colors in Figure 1 indicate batches that are evaluated in parallel.

+
+
+

Hyperparameter Optimization

+

In this practical example, we will optimize the hyperparameters of XGBoost on the Spam data set. We begin by loading the XGBoost learner..

+
+
library("mlr3verse")
+
+learner = lrn("classif.xgboost")
+
+

The next thing we do is define the search space. The nrounds parameter controls the number of boosting iterations. We set a range from 16 to 128 boosting iterations. This is used as \(r{_{min}}\) and \(r{_{max}}\) by the Hyperband algorithm. We need to tag the parameter with "budget" to identify it as a fidelity parameter. For the other hyperparameters, we take the search space for XGBoost from the Bischl et al. (2021) article. This search space works for a wide range of data sets.

+
+
learner$param_set$set_values(
+  nrounds           = to_tune(p_int(16, 128, tags = "budget")),
+  eta               = to_tune(1e-4, 1, logscale = TRUE),
+  max_depth         = to_tune(1, 20),
+  colsample_bytree  = to_tune(1e-1, 1),
+  colsample_bylevel = to_tune(1e-1, 1),
+  lambda            = to_tune(1e-3, 1e3, logscale = TRUE),
+  alpha             = to_tune(1e-3, 1e3, logscale = TRUE),
+  subsample         = to_tune(1e-1, 1)
+)
+
+

We construct the tuning instance. We use the "none" terminator because Hyperband terminates itself when all brackets are evaluated.

+
+
instance = ti(
+  task = tsk("spam"),
+  learner = learner,
+  resampling = rsmp("holdout"),
+  measures = msr("classif.ce"),
+  terminator = trm("none")
+)
+instance
+
+
<TuningInstanceSingleCrit>
+* State:  Not optimized
+* Objective: <ObjectiveTuning:classif.xgboost_on_spam>
+* Search Space:
+                  id    class     lower      upper nlevels
+              <char>   <char>     <num>      <num>   <num>
+1:           nrounds ParamInt 16.000000 128.000000     113
+2:               eta ParamDbl -9.210340   0.000000     Inf
+3:         max_depth ParamInt  1.000000  20.000000      20
+4:  colsample_bytree ParamDbl  0.100000   1.000000     Inf
+5: colsample_bylevel ParamDbl  0.100000   1.000000     Inf
+6:            lambda ParamDbl -6.907755   6.907755     Inf
+7:             alpha ParamDbl -6.907755   6.907755     Inf
+8:         subsample ParamDbl  0.100000   1.000000     Inf
+* Terminator: <TerminatorNone>
+
+
+

We load the Hyperband tuner and set eta = 2. Hyperband can start from the beginning when the last bracket is evaluated. We control the number of Hyperband runs with the repetition argument. The setting repetition = Inf is useful when a terminator should stop the optimization.

+
+
library("mlr3hyperband")
+
+tuner = tnr("hyperband", eta = 2, repetitions = 1)
+
+

The Hyperband implementation in mlr3hyperband evaluates configurations with the same budget in parallel. This results in all brackets finishing at approximately the same time. You can think of it as going diagonally through Figure 1. Using eta = 2 and a range from 16 to 128 boosting iterations results in the following schedule.

+
+
+
+ +
+
+

Now we are ready to start the tuning.

+
+
tuner$optimize(instance)
+
+

The result of a run is the configuration with the best performance. This does not necessarily have to be a configuration evaluated with the highest budget since we can overfit the data with too many boosting iterations.

+
+
instance$result[, .(nrounds, eta, max_depth, colsample_bytree, colsample_bylevel, lambda, alpha, subsample)]
+
+
   nrounds       eta max_depth colsample_bytree colsample_bylevel    lambda     alpha subsample
+     <num>     <num>     <int>            <num>             <num>     <num>     <num>     <num>
+1:     128 -1.985313         8        0.4828647         0.3001509 -3.816118 -4.998944 0.4464856
+
+
+

The archive of a Hyperband run has the additional columns "bracket" and "stage".

+
+
as.data.table(instance$archive)[, .(bracket, stage, classif.ce, eta, max_depth, colsample_bytree)]
+
+
    bracket stage classif.ce        eta max_depth colsample_bytree
+      <int> <num>      <num>      <num>     <int>            <num>
+ 1:       3     0 0.09061278 -3.6110452        20        0.2671318
+ 2:       3     0 0.06388527 -1.9853130         8        0.4828647
+ 3:       3     0 0.11147327 -2.8428844         3        0.3152709
+ 4:       3     0 0.07301173 -3.9228523        19        0.5369803
+ 5:       3     0 0.07953064 -3.6486183        17        0.2039727
+---                                                               
+31:       0     0 0.06258149 -1.8578637         9        0.7343156
+32:       3     3 0.03976532 -1.9853130         8        0.4828647
+33:       2     2 0.03976532 -0.9898459         4        0.2534038
+34:       1     1 0.05345502 -2.5345314        13        0.5260946
+35:       1     1 0.06714472 -8.5597326        16        0.9890136
+
+
+
+
+

Conclusion

+

The handling of Hyperband in mlr3tuning is very similar to that of other tuners. We only have to select an additional fidelity parameter and tag it with "budget". We have tried to keep the runtime of the example low. For your optimization, you should use cross-validation and increase the maximum number of boosting rounds. The Bischl et al. (2021) search space suggests 5000 boosting rounds. Check out our next post on Hyperband which uses the size of the training data set as the fidelity parameter.

+ + + +
+ +

References

+
+Bischl, Bernd, Martin Binder, Michel Lang, Tobias Pielok, Jakob Richter, Stefan Coors, Janek Thomas, et al. 2021. “Hyperparameter Optimization: Foundations, Algorithms, Best Practices and Open Challenges.” arXiv:2107.05847 [Cs, Stat], July. http://arxiv.org/abs/2107.05847. +
+
+Jamieson, Kevin, and Ameet Talwalkar. 2016. “Non-Stochastic Best Arm Identification and Hyperparameter Optimization.” In Proceedings of the 19th International Conference on Artificial Intelligence and Statistics, edited by Arthur Gretton and Christian C. Robert, 51:240–48. Proceedings of Machine Learning Research. Cadiz, Spain: PMLR. http://proceedings.mlr.press/v51/jamieson16.html. +
+
+Li, Lisha, Kevin Jamieson, Giulia DeSalvo, Afshin Rostamizadeh, and Ameet Talwalkar. 2018. “Hyperband: A Novel Bandit-Based Approach to Hyperparameter Optimization.” Journal of Machine Learning Research 18 (185): 1–52. https://jmlr.org/papers/v18/16-558.html. +
+
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/optimization/2023-01-16-hotstart/cover.jpg b/gallery/optimization/2023-01-16-hotstart/cover.jpg new file mode 100644 index 00000000..7e533229 Binary files /dev/null and b/gallery/optimization/2023-01-16-hotstart/cover.jpg differ diff --git a/gallery/optimization/2023-01-16-hotstart/index.html b/gallery/optimization/2023-01-16-hotstart/index.html new file mode 100644 index 00000000..7ca41957 --- /dev/null +++ b/gallery/optimization/2023-01-16-hotstart/index.html @@ -0,0 +1,914 @@ + + + + + + + + + + + + + +Hotstarting – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Hotstarting

+
+
+

Resume the training of learners.

+
+
+ +
+ + +
+ +
+
Authors
+ +
+ +
+
Published
+
+

January 16, 2023

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Scope

+

Hotstarting a learner resumes the training from an already fitted model. An example would be to train an already fit XGBoost model for an additional 500 boosting iterations. In mlr3, we call this process Hotstarting, where a learner has access to a cache of already trained models which is called a mlr3::HoststartStack We distinguish between forward and backward hotstarting. We start this post with backward hotstarting and then talk about the less efficient forward hotstarting.

+
+
+

Backward Hotstarting

+

In this example, we optimize the hyperparameters of a random forest and use hotstarting to reduce the runtime. Hotstarting a random forest backwards is very simple. The model remains unchanged and only a subset of the trees is used for prediction i.e. a new model is not fitted. For example, a random forest is trained with 1000 trees and a specific hyperparameter configuration. If another random forest with 500 trees but with the same hyperparameter configuration has to be trained, the model with 1000 trees is copied and only 500 trees are used for prediction.

+

We load the ranger learner and set the search space from the Bischl et al. (2021) article.

+
+
library(mlr3verse)
+
+learner = lrn("classif.ranger",
+  mtry.ratio      = to_tune(0, 1),
+  replace         = to_tune(),
+  sample.fraction = to_tune(1e-1, 1),
+  num.trees       = to_tune(1, 2000)
+)
+
+

We activate hotstarting with the allow_hotstart option. When running a grid search with hotstarting, the grid is sorted by the hot start parameter. This means the models with 2000 trees are trained first. The models with less than 2000 trees hot start on the 2000 trees models which allows the training to be completed immediately.

+
+
instance = tune(
+  tuner = tnr("grid_search", resolution = 5, batch_size = 5),
+  task = tsk("spam"),
+  learner = learner,
+  resampling = rsmp("holdout"),
+  measure = msr("classif.ce"),
+  allow_hotstart = TRUE
+)
+
+

For comparison, we perform the same tuning without hotstarting.

+
+
instance_2 = tune(
+  tuner = tnr("grid_search", resolution = 5, batch_size = 5),
+  task = tsk("spam"),
+  learner = learner,
+  resampling = rsmp("holdout"),
+  measure = msr("classif.ce"),
+  allow_hotstart = FALSE
+)
+
+

We plot the time of completion of each batch (see Figure 1). Each batch includes 5 configurations. We can see that tuning with hotstarting is slower at first. As soon as all models are fitted with 2000 trees, the tuning runs much faster and overtakes the tuning without hotstarting.

+
+
+
+
+
+ +
+
+Figure 1: Time of completion of each batch with and without hotstarting. +
+
+
+
+
+
+
+

Forward Hotstarting

+

Forward hotstarting is currently only supported by XGBoost. However, we have observed that hotstarting only provides a speed advantage for very large datasets and models with more than 5000 boosting rounds. The reason is that copying the models from the main process to the workers is a major bottleneck. The parallelization package future copies the models sequentially to the workers. Consequently, it takes a long time until the last worker can even start. Moreover, copying itself consumes a lot of time, and copying the model back from the worker blocks the main process again. During the development process, we overestimated the speed benefits of hotstarting and underestimated the overhead of parallelization. We can therefore only advise against using forward hotstarting during tuning. It is much more efficient to use the internal early-stopping mechanism of XGBoost. This eliminates the need to copy models to the worker. See the gallery post on early stopping for an example. We might improve the efficiency of the hotstarting mechanism in the future, if there are convincing use cases.

+
+
+

Manual Hotstarting

+

Nevertheless, forward hotstarting can be useful without parallelization. If you have an already trained model and want to add more boosting iteration to it. In this example, the learner_5000 is the already trained model. We create a new learner with the same hyperparameters but double the number of boosting iteration. To activate hotstarting, we create a HotstartStack and copy it to the $hotstart_stack slot of the new learner.

+
+
task = tsk("spam")
+
+learner_5000 = lrn("classif.xgboost", nrounds = 5000, eta = 0.1)
+learner_5000$train(task)
+
+learner_10000 = lrn("classif.xgboost", nrounds = 10000, eta = 0.1)
+learner_10000$hotstart_stack = HotstartStack$new(learner_5000)
+learner_10000$train(task)
+
+

Training the initial model took 59.885 seconds.

+
+
learner_5000$state$train_time
+
+
[1] 59.885
+
+
+

Adding 5000 boosting rounds took 46.837 seconds.

+
+
learner_10000$state$train_time - learner_5000$state$train_time
+
+
[1] 46.837
+
+
+

Training the model from the beginning would have taken about two minutes. This means, without parallelization, we get the expected speed advantage.

+
+
+

Conclusion

+

We have seen how mlr3 enables to reduce the training time, by building on a hotstart stack of already trained learners. One has to be careful, however, when using forward hotstarting during tuning because of the high parallelization overhead that arises from copying the models between the processes. If a model has an internal early stopping implementation, it should usually be relied upon instead of using the mlr3 hotstarting mechanism. However, manual forward hotstarting can be helpful in some situations when we do not want to train a large model from the beginning.

+ + + +
+ +

References

+
+Bischl, Bernd, Martin Binder, Michel Lang, Tobias Pielok, Jakob Richter, Stefan Coors, Janek Thomas, et al. 2021. “Hyperparameter Optimization: Foundations, Algorithms, Best Practices and Open Challenges.” arXiv:2107.05847 [Cs, Stat], July. http://arxiv.org/abs/2107.05847. +
+
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/optimization/2023-01-16-hotstart/index_files/figure-html/fig-time-batch-1.png b/gallery/optimization/2023-01-16-hotstart/index_files/figure-html/fig-time-batch-1.png new file mode 100644 index 00000000..e672f04b Binary files /dev/null and b/gallery/optimization/2023-01-16-hotstart/index_files/figure-html/fig-time-batch-1.png differ diff --git a/gallery/optimization/2023-01-16-hyperband-subsampling/cover.png b/gallery/optimization/2023-01-16-hyperband-subsampling/cover.png new file mode 100644 index 00000000..53194b7b Binary files /dev/null and b/gallery/optimization/2023-01-16-hyperband-subsampling/cover.png differ diff --git a/gallery/optimization/2023-01-16-hyperband-subsampling/index.html b/gallery/optimization/2023-01-16-hyperband-subsampling/index.html new file mode 100644 index 00000000..541a5c93 --- /dev/null +++ b/gallery/optimization/2023-01-16-hyperband-subsampling/index.html @@ -0,0 +1,969 @@ + + + + + + + + + + + + + +Hyperband Series - Data Set Subsampling – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Hyperband Series - Data Set Subsampling

+
+
+

Optimize the hyperparameters of a Support Vector Machine with Hyperband.

+
+
+ +
+ + +
+ +
+
Authors
+ +
+ +
+
Published
+
+

January 16, 2023

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Scope

+

We continue working with the Hyperband optimization algorithm (Li et al. 2018). The previous post used the number of boosting iterations of an XGBoost model as the resource. However, Hyperband is not limited to machine learning algorithms that are trained iteratively. The resource can also be the number of features, the training time of a model, or the size of the training data set. In this post, we will tune a support vector machine and use the size of the training data set as the fidelity parameter. The time to train a support vector machine and the performance increases with the size of the data set. This makes the data set size a suitable fidelity parameter for Hyperband. This is the second part of the Hyperband series. The first part can be found here Hyperband Series - Iterative Training. If you don’t know much about Hyperband, check out the first post which explains the algorithm in detail. We assume that you are already familiar with tuning in the mlr3 ecosystem. If not, you should start with the book chapter on optimization or the Hyperparameter Optimization on the Palmer Penguins Data Set post. A little knowledge about mlr3pipelines is beneficial but not necessary to understand the example.

+
+
+

Hyperparameter Optimization

+

In this post, we will optimize the hyperparameters of the support vector machine on the Sonar data set. We begin by constructing a classification machine by setting type to "C-classification".

+
+
library("mlr3verse")
+
+learner = lrn("classif.svm", id = "svm", type = "C-classification")
+
+

The mlr3pipelines package features a PipeOp for subsampling.

+
+
po("subsample")
+
+
PipeOp: <subsample> (not trained)
+values: <frac=0.6321, stratify=FALSE, replace=FALSE>
+Input channels <name [train type, predict type]>:
+  input [Task,Task]
+Output channels <name [train type, predict type]>:
+  output [Task,Task]
+
+
+

The PipeOp controls the size of the training data set with the frac parameter. We connect the PipeOp with the learner and get a GraphLearner.

+
+
graph_learner = as_learner(
+  po("subsample") %>>%
+  learner
+)
+
+

The graph learner subsamples and then fits a support vector machine on the data subset. The parameter set of the graph learner is a combination of the parameter sets of the PipeOp and learner.

+
+
as.data.table(graph_learner$param_set)[, .(id, lower, upper, levels)]
+
+
                    id lower upper                             levels
+ 1:     subsample.frac     0   Inf                                   
+ 2: subsample.stratify    NA    NA                         TRUE,FALSE
+ 3:  subsample.replace    NA    NA                         TRUE,FALSE
+ 4:      svm.cachesize  -Inf   Inf                                   
+ 5:  svm.class.weights    NA    NA                                   
+---                                                                  
+15:             svm.nu  -Inf   Inf                                   
+16:          svm.scale    NA    NA                                   
+17:      svm.shrinking    NA    NA                         TRUE,FALSE
+18:      svm.tolerance     0   Inf                                   
+19:           svm.type    NA    NA C-classification,nu-classification
+
+
+

Next, we create the search space. We use TuneToken to mark which hyperparameters should be tuned. We have to prefix the hyperparameters with the id of the PipeOps. The subsample.frac is the fidelity parameter that must be tagged with "budget" in the search space. The data set size is increased from 3.7% to 100%. For the other hyperparameters, we took the search space for support vector machines from the Kuehn et al. (2018) article. This search space works for a wide range of data sets.

+
+
graph_learner$param_set$set_values(
+  subsample.frac  = to_tune(p_dbl(3^-3, 1, tags = "budget")),
+  svm.kernel      = to_tune(c("linear", "polynomial", "radial")),
+  svm.cost        = to_tune(1e-4, 1e3, logscale = TRUE),
+  svm.gamma       = to_tune(1e-4, 1e3, logscale = TRUE),
+  svm.tolerance   = to_tune(1e-4, 2, logscale = TRUE),
+  svm.degree      = to_tune(2, 5)
+)
+
+

Support vector machines often crash or never finish the training with certain hyperparameter configurations. We set a timeout of 30 seconds and a fallback learner to handle these cases.

+
+
graph_learner$encapsulate = c(train = "evaluate", predict = "evaluate")
+graph_learner$timeout = c(train = 30, predict = 30)
+graph_learner$fallback = lrn("classif.featureless")
+
+

Let’s create the tuning instance. We use the "none" terminator because Hyperband controls the termination itself.

+
+
instance = ti(
+  task = tsk("sonar"),
+  learner = graph_learner,
+  resampling = rsmp("cv", folds = 3),
+  measures = msr("classif.ce"),
+  terminator = trm("none")
+)
+instance
+
+
<TuningInstanceSingleCrit>
+* State:  Not optimized
+* Objective: <ObjectiveTuning:subsample.svm_on_sonar>
+* Search Space:
+               id    class       lower     upper nlevels
+1: subsample.frac ParamDbl  0.03703704 1.0000000     Inf
+2:       svm.cost ParamDbl -9.21034037 6.9077553     Inf
+3:     svm.degree ParamInt  2.00000000 5.0000000       4
+4:      svm.gamma ParamDbl -9.21034037 6.9077553     Inf
+5:     svm.kernel ParamFct          NA        NA       3
+6:  svm.tolerance ParamDbl -9.21034037 0.6931472     Inf
+* Terminator: <TerminatorNone>
+
+
+

We load the Hyperband tuner and set eta = 3.

+
+
library("mlr3hyperband")
+
+tuner = tnr("hyperband", eta = 3)
+
+

Using eta = 3 and a lower bound of 3.7% for the data set size, results in the following schedule. Configurations with the same data set size are evaluated in parallel.

+
+
+
+ +
+
+

Now we are ready to start the tuning.

+
+
tuner$optimize(instance)
+
+

The best model is a support vector machine with a polynomial kernel.

+
+
instance$result[, .(subsample.frac, svm.cost, svm.degree, svm.gamma, svm.kernel, svm.tolerance, classif.ce)]
+
+
   subsample.frac svm.cost svm.degree svm.gamma svm.kernel svm.tolerance classif.ce
+1:              1 1.871535          3  -2.60663 polynomial     -4.573951  0.1491373
+
+
+

The archive contains all evaluated configurations. We look at the 8 configurations that were evaluated on the complete data set. The configuration with the best classification error on the full data set was sampled in bracket 2. The classification error was estimated to be 26% on 33% of the data set and increased to 19% on the full data set (see green line in Figure 1).

+
+
+
+
+
+ +
+
+Figure 1: Optimization path of the 8 configurations evaluated on the complete data set. +
+
+
+
+
+
+
+

Conclusion

+

Using the data set size as the budget parameter in Hyperband allows the tuning of machine learning models that are not trained iteratively. We have tried to keep the runtime of the example low. For your optimization, you should use cross-validation and run multiple iterations of Hyperband.

+
+
+ + + + +
+ +

References

+
+Kuehn, Daniel, Philipp Probst, Janek Thomas, and Bernd Bischl. 2018. “Automatic Exploration of Machine Learning Experiments on OpenML.” https://arxiv.org/abs/1806.10961. +
+
+Li, Lisha, Kevin Jamieson, Giulia DeSalvo, Afshin Rostamizadeh, and Ameet Talwalkar. 2018. “Hyperband: A Novel Bandit-Based Approach to Hyperparameter Optimization.” Journal of Machine Learning Research 18 (185): 1–52. https://jmlr.org/papers/v18/16-558.html. +
+
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/optimization/2023-01-16-hyperband-subsampling/index_files/figure-html/fig-hyperband-1.png b/gallery/optimization/2023-01-16-hyperband-subsampling/index_files/figure-html/fig-hyperband-1.png new file mode 100644 index 00000000..86d956eb Binary files /dev/null and b/gallery/optimization/2023-01-16-hyperband-subsampling/index_files/figure-html/fig-hyperband-1.png differ diff --git a/gallery/optimization/2023-01-31-default-configuration/cover.jpg b/gallery/optimization/2023-01-31-default-configuration/cover.jpg new file mode 100644 index 00000000..f9820a2a Binary files /dev/null and b/gallery/optimization/2023-01-31-default-configuration/cover.jpg differ diff --git a/gallery/optimization/2023-01-31-default-configuration/index.html b/gallery/optimization/2023-01-31-default-configuration/index.html new file mode 100644 index 00000000..796e5fab --- /dev/null +++ b/gallery/optimization/2023-01-31-default-configuration/index.html @@ -0,0 +1,886 @@ + + + + + + + + + + + + +Default Hyperparameter Configuration – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Default Hyperparameter Configuration

+
+
+

Run the default hyperparameter configuration of learners as a baseline.

+
+
+ +
+ + +
+ +
+
Author
+ +
+ +
+
Published
+
+

January 31, 2023

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Scope

+

The predictive performance of modern machine learning algorithms is highly dependent on the choice of their hyperparameter configuration. Options for setting hyperparameters are tuning, manual selection by the user, and using the default configuration of the algorithm. The default configurations are chosen to work with a wide range of data sets but they usually do not achieve the best predictive performance. When tuning a learner in mlr3, we can run the default configuration as a baseline. Seeing how well it performs will tell us whether tuning pays off. If the optimized configurations perform worse, we could expand the search space or try a different optimization algorithm. Of course, it could also be that tuning on the given data set is simply not worth it.

+

Probst, Boulesteix, and Bischl (2019) studied the tunability of machine learning algorithms. They found that the tunability of algorithms varies widely. Algorithms like glmnet and XGBoost are highly tunable, while algorithms like random forests work well with their default configuration. The highly tunable algorithms should thus beat their baselines more easily with optimized hyperparameters. In this article, we will tune the hyperparameters of a random forest and compare the performance of the default configuration with the optimized configurations.

+
+
+

Example

+

We tune the hyperparameters of the ranger learner on the spam data set. The search space is taken from Bischl et al. (2021).

+
+
library(mlr3verse)
+
+learner = lrn("classif.ranger",
+  mtry.ratio      = to_tune(0, 1),
+  replace         = to_tune(),
+  sample.fraction = to_tune(1e-1, 1),
+  num.trees       = to_tune(1, 2000)
+)
+
+

When creating the tuning instance, we set evaluate_default = TRUE to test the default hyperparameter configuration. The default configuration is evaluated in the first batch of the tuning run. The other batches use the specified tuning method. In this example, they are randomly drawn configurations.

+
+
instance = tune(
+  tuner = tnr("random_search", batch_size = 5),
+  task = tsk("spam"),
+  learner = learner,
+  resampling = rsmp ("holdout"),
+  measures = msr("classif.ce"),
+  term_evals = 51,
+  evaluate_default = TRUE
+)
+
+

The default configuration is recorded in the first row of the archive. The other rows contain the results of the random search.

+
+
as.data.table(instance$archive)[, .(batch_nr, mtry.ratio, replace, sample.fraction, num.trees, classif.ce)]
+
+
    batch_nr  mtry.ratio replace sample.fraction num.trees classif.ce
+ 1:        1 0.122807018    TRUE       1.0000000       500 0.04954368
+ 2:        2 0.285388074    TRUE       0.1794772       204 0.06584094
+ 3:        2 0.097424099   FALSE       0.9475526      1441 0.04237288
+ 4:        2 0.008888587   FALSE       0.3216562      1868 0.08409387
+ 5:        2 0.335543330    TRUE       0.8122653       106 0.05345502
+---                                                                  
+47:       11 0.788995735   FALSE       0.3692454       344 0.06258149
+48:       11 0.459305038    TRUE       0.3153485      1354 0.06258149
+49:       11 0.220334408    TRUE       0.9357554       817 0.05345502
+50:       11 0.868385877    TRUE       0.6743246      1040 0.06127771
+51:       11 0.015417312   FALSE       0.5627943      1836 0.08213820
+
+
+

We plot the performances of the evaluated hyperparameter configurations. The blue line connects the best configuration of each batch. We see that the default configuration already performs well and the optimized configurations can not beat it.

+
+
library(mlr3viz)
+
+autoplot(instance, type = "performance")
+
+
+
+

+
+
+
+
+
+
+

Conlcusion

+

The time required to test the default configuration is negligible compared to the time required to run the hyperparameter optimization. It gives us a valuable indication of whether our tuning is properly configured. Running the default configuration as a baseline is a good practice that should be used in every tuning run.

+ + + +
+ +

References

+
+Bischl, Bernd, Martin Binder, Michel Lang, Tobias Pielok, Jakob Richter, Stefan Coors, Janek Thomas, et al. 2021. “Hyperparameter Optimization: Foundations, Algorithms, Best Practices and Open Challenges.” arXiv:2107.05847 [Cs, Stat], July. http://arxiv.org/abs/2107.05847. +
+
+Probst, Philipp, Anne-Laure Boulesteix, and Bernd Bischl. 2019. “Tunability: Importance of Hyperparameters of Machine Learning Algorithms.” Journal of Machine Learning Research 20 (53): 1–32. http://jmlr.org/papers/v20/18-444.html. +
+
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/optimization/2023-01-31-default-configuration/index_files/figure-html/2023-01-31-default-configuration-005-1.png b/gallery/optimization/2023-01-31-default-configuration/index_files/figure-html/2023-01-31-default-configuration-005-1.png new file mode 100644 index 00000000..0d5e8276 Binary files /dev/null and b/gallery/optimization/2023-01-31-default-configuration/index_files/figure-html/2023-01-31-default-configuration-005-1.png differ diff --git a/gallery/optimization/2023-02-01-shadow-variable-search/cover.png b/gallery/optimization/2023-02-01-shadow-variable-search/cover.png new file mode 100644 index 00000000..6d9ca9b4 Binary files /dev/null and b/gallery/optimization/2023-02-01-shadow-variable-search/cover.png differ diff --git a/gallery/optimization/2023-02-01-shadow-variable-search/index.html b/gallery/optimization/2023-02-01-shadow-variable-search/index.html new file mode 100644 index 00000000..a7a0973b --- /dev/null +++ b/gallery/optimization/2023-02-01-shadow-variable-search/index.html @@ -0,0 +1,985 @@ + + + + + + + + + + + + + +Shadow Variable Search on the Pima Indian Diabetes Data Set – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Shadow Variable Search on the Pima Indian Diabetes Data Set

+
+
+

Run a feature selection with permutated features.

+
+
+ +
+ + +
+ +
+
Authors
+ +
+ +
+
Published
+
+

February 1, 2023

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Scope

+

Feature selection is the process of finding an optimal set of features to improve the performance, interpretability and robustness of machine learning algorithms. In this article, we introduce the Shadow Variable Search algorithm which is a wrapper method for feature selection. Wrapper methods iteratively add features to the model that optimize a performance measure. As an example, we will search for the optimal set of features for a support vector machine on the Pima Indian Diabetes data set. We assume that you are already familiar with the basic building blocks of the mlr3 ecosystem. If you are new to feature selection, we recommend reading the feature selection chapter of the mlr3book first. Some knowledge about mlr3pipelines is beneficial but not necessary to understand the example.

+
+ +
+

Task and Learner

+

The objective of the Pima Indian Diabetes data set is to predict whether a person has diabetes or not. The data set includes 768 patients with 8 measurements (see Figure 1).

+
+
task = tsk("pima")
+
+
+
+Code +
library(ggplot2)
+library(data.table)
+
+data = melt(as.data.table(task), id.vars = task$target_names, measure.vars = task$feature_names)
+
+ggplot(data, aes(x = value, fill = diabetes)) +
+  geom_density(alpha = 0.5) +
+  facet_wrap(~ variable, ncol = 8, scales = "free") +
+  scale_fill_viridis_d(end = 0.8) +
+  theme_minimal() +
+  theme(axis.title.x = element_blank())
+
+
+
+
+
+ +
+
+Figure 1: Distribution of the features in the Pima Indian Diabetes data set. +
+
+
+
+
+

The data set contains missing values.

+
+
task$missings()
+
+
diabetes      age  glucose  insulin     mass pedigree pregnant pressure  triceps 
+       0        0        5      374       11        0        0       35      227 
+
+
+

Support vector machines cannot handle missing values. We impute the missing values with the histogram imputation method.

+
+
learner = po("imputehist") %>>% lrn("classif.svm", predict_type = "prob")
+
+
+
+

Feature Selection

+

Now we define the feature selection problem by using the fsi() function that constructs an FSelectInstanceSingleCrit. In addition to the task and learner, we have to select a resampling strategy and performance measure to determine how the performance of a feature subset is evaluated. We pass the "none" terminator because the shadow variable search algorithm terminates by itself.

+
+
instance = fsi(
+  task = task,
+  learner = learner,
+  resampling = rsmp("cv", folds = 3),
+  measures = msr("classif.auc"),
+  terminator = trm("none")
+)
+
+

We are now ready to start the shadow variable search. To do this, we simply pass the instance to the $optimize() method of the optimizer.

+
+
optimizer$optimize(instance)
+
+
    age glucose insulin mass pedigree pregnant pressure triceps                  features classif.auc
+1: TRUE    TRUE   FALSE TRUE     TRUE    FALSE    FALSE   FALSE age,glucose,mass,pedigree    0.835165
+
+
+

The optimizer returns the best feature set and the corresponding estimated performance.

+

Figure 2 shows the optimization path of the feature selection. The feature glucose was selected first and in the following iterations age, mass and pedigree. Then a shadow variable was selected and the feature selection was terminated.

+
+
+Code +
library(data.table)
+library(ggplot2)
+library(mlr3misc)
+library(viridisLite)
+
+data = as.data.table(instance$archive)[order(-classif.auc), head(.SD, 1), by = batch_nr][order(batch_nr)]
+data[, features := map_chr(features, str_collapse)]
+data[, batch_nr := as.character(batch_nr)]
+
+ggplot(data, aes(x = batch_nr, y = classif.auc)) +
+  geom_bar(
+    stat = "identity",
+    width = 0.5,
+    fill = viridis(1, begin = 0.5),
+    alpha = 0.8) +
+  geom_text(
+    data = data,
+    mapping = aes(x = batch_nr, y = 0, label = features),
+    hjust = 0,
+    nudge_y = 0.05,
+    color = "white",
+    size = 5
+    ) +
+  coord_flip() +
+  xlab("Iteration") +
+  theme_minimal()
+
+
+
+
+
+ +
+
+Figure 2: Optimization path of the shadow variable search. +
+
+
+
+
+

The archive contains all evaluated feature sets. We can see that each feature has a corresponding shadow variable. We only show the variables age, glucose and insulin and their shadow variables here.

+
+
as.data.table(instance$archive)[, .(age, glucose, insulin, permuted__age, permuted__glucose, permuted__insulin, classif.auc)]
+
+
      age glucose insulin permuted__age permuted__glucose permuted__insulin classif.auc
+ 1:  TRUE   FALSE   FALSE         FALSE             FALSE             FALSE   0.6437052
+ 2: FALSE    TRUE   FALSE         FALSE             FALSE             FALSE   0.7598155
+ 3: FALSE   FALSE    TRUE         FALSE             FALSE             FALSE   0.4900280
+ 4: FALSE   FALSE   FALSE         FALSE             FALSE             FALSE   0.6424026
+ 5: FALSE   FALSE   FALSE         FALSE             FALSE             FALSE   0.5690107
+---                                                                                    
+54:  TRUE    TRUE   FALSE         FALSE             FALSE             FALSE   0.8266713
+55:  TRUE    TRUE   FALSE         FALSE             FALSE             FALSE   0.8063568
+56:  TRUE    TRUE   FALSE         FALSE             FALSE             FALSE   0.8244232
+57:  TRUE    TRUE   FALSE         FALSE             FALSE             FALSE   0.8234605
+58:  TRUE    TRUE   FALSE         FALSE             FALSE             FALSE   0.8164784
+
+
+
+
+

Final Model

+

The learner we use to make predictions on new data is called the final model. The final model is trained with the optimal feature set on the full data set. We subset the task to the optimal feature set and train the learner.

+
+
task$select(instance$result_feature_set)
+learner$train(task)
+
+

The trained model can now be used to predict new, external data.

+
+
+

Conclusion

+

The shadow variable search is a fast feature selection method that is easy to use. More information on the theoretical background can be found in Wu, Boos, and Stefanski (2007) and Thomas et al. (2017). If you want to know more about feature selection in general, we recommend having a look at our book.

+ + + +
+ +

References

+
+Thomas, Janek, Tobias Hepp, Andreas Mayr, and Bernd Bischl. 2017. “Probing for Sparse and Fast Variable Selection with Model-Based Boosting.” Computational and Mathematical Methods in Medicine 2017 (July): e1421409. https://doi.org/10.1155/2017/1421409. +
+
+Wu, Yujun, Dennis D Boos, and Leonard A Stefanski. 2007. “Controlling Variable Selection by the Addition of Pseudovariables.” Journal of the American Statistical Association 102 (477): 235–43. https://doi.org/10.1198/016214506000000843. +
+
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/optimization/2023-02-01-shadow-variable-search/index_files/figure-html/2023-02-01-shadow-variable-search-004-1.png b/gallery/optimization/2023-02-01-shadow-variable-search/index_files/figure-html/2023-02-01-shadow-variable-search-004-1.png new file mode 100644 index 00000000..66eef1a8 Binary files /dev/null and b/gallery/optimization/2023-02-01-shadow-variable-search/index_files/figure-html/2023-02-01-shadow-variable-search-004-1.png differ diff --git a/gallery/optimization/2023-02-01-shadow-variable-search/index_files/figure-html/fig-features-1.png b/gallery/optimization/2023-02-01-shadow-variable-search/index_files/figure-html/fig-features-1.png new file mode 100644 index 00000000..43814576 Binary files /dev/null and b/gallery/optimization/2023-02-01-shadow-variable-search/index_files/figure-html/fig-features-1.png differ diff --git a/gallery/optimization/2023-02-01-shadow-variable-search/index_files/figure-html/fig-optimization-path-1.png b/gallery/optimization/2023-02-01-shadow-variable-search/index_files/figure-html/fig-optimization-path-1.png new file mode 100644 index 00000000..73c24635 Binary files /dev/null and b/gallery/optimization/2023-02-01-shadow-variable-search/index_files/figure-html/fig-optimization-path-1.png differ diff --git a/gallery/optimization/2023-02-01-shadow-variable-search/index_files/figure-html/unnamed-chunk-1-1.png b/gallery/optimization/2023-02-01-shadow-variable-search/index_files/figure-html/unnamed-chunk-1-1.png new file mode 100644 index 00000000..879c30a6 Binary files /dev/null and b/gallery/optimization/2023-02-01-shadow-variable-search/index_files/figure-html/unnamed-chunk-1-1.png differ diff --git a/gallery/optimization/2023-02-07-recursive-feature-elimination/cover.jpg b/gallery/optimization/2023-02-07-recursive-feature-elimination/cover.jpg new file mode 100644 index 00000000..8729a3b3 Binary files /dev/null and b/gallery/optimization/2023-02-07-recursive-feature-elimination/cover.jpg differ diff --git a/gallery/optimization/2023-02-07-recursive-feature-elimination/index.html b/gallery/optimization/2023-02-07-recursive-feature-elimination/index.html new file mode 100644 index 00000000..298897cc --- /dev/null +++ b/gallery/optimization/2023-02-07-recursive-feature-elimination/index.html @@ -0,0 +1,1265 @@ + + + + + + + + + + + + +Recursive Feature Elimination on the Sonar Data Set – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Recursive Feature Elimination on the Sonar Data Set

+
+
+

Utilize the built-in feature importance of models.

+
+
+ +
+ + +
+ +
+
Author
+ +
+ +
+
Published
+
+

February 7, 2023

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Scope

+

Feature selection is the process of finding an optimal subset of features in order to improve the performance, interpretability and robustness of machine learning algorithms. In this article, we introduce the wrapper feature selection method Recursive Feature Elimination. Wrapper methods iteratively select features that optimize a performance measure. As an example, we will search for the optimal set of features for a gradient boosting machine and support vector machine on the Sonar data set. We assume that you are already familiar with the basic building blocks of the mlr3 ecosystem. If you are new to feature selection, we recommend reading the feature selection chapter of the mlr3book first.

+
+
+

Recursive Feature Elimination

+

Recursive Feature Elimination (RFE) is a widely used feature selection method for high-dimensional data sets. The idea is to iteratively remove the least predictive feature from a model until the desired number of features is reached. This feature is determined by the built-in feature importance method of the model. Currently, RFE works with support vector machines (SVM), decision tree algorithms and gradient boosting machines (GBM). Supported learners are tagged with the "importance" property. For a full list of supported learners, see the learner page on the mlr-org website and search for "importance".

+

Guyon et al. (2002) developed the RFE algorithm for SVMs (SVM-RFE) to select informative genes in cancer classification. The importance of the features is given by the weight vector of a linear support vector machine. This method was later extended to other machine learning algorithms. The only requirement is that the models can internally measure the feature importance. The random forest algorithm offers multiple options for measuring feature importance. The commonly used methods are the mean decrease in accuracy (MDA) and the mean decrease in impurity (MDI). The MDA measures the decrease in accuracy for a feature if it was randomly permuted in the out-of-bag sample. The MDI is the total reduction in node impurity when the feature is used for splitting. Gradient boosting algorithms like XGBoost, LightGBM and GBM use similar methods to measure the importance of the features.

+

Resampling strategies can be combined with the algorithm in different ways. The frameworks scikit-learn (Pedregosa et al. 2011) and caret (Kuhn 2008) implement a variant called recursive feature elimination with cross-validation (RFE-CV) that estimates the optimal number of features with cross-validation first. Then one more RFE is carried out on the complete dataset with the optimal number of features as the final feature set size. The RFE implementation in mlr3 can rank and aggregate importance scores across resampling iterations. We will explore both variants in more detail below.

+

mlr3fselect is the feature selection package of the mlr3 ecosystem. It implements the RFE and RFE-CV algorithm. We load all packages of the ecosystem with the mlr3verse package.

+
+
library(mlr3verse)
+
+

We retrieve the RFE optimizer with the fs() function.

+
+
optimizer = fs("rfe",
+  n_features = 1,
+  feature_number = 1,
+  aggregation = "rank")
+
+

The algorithm has multiple control parameters. The optimizer stops when the number of features equals n_features. The parameters feature_number, feature_fraction and subset_size determine the number of features that are removed in each iteration. The feature_number option removes a fixed number of features in each iteration, whereas feature_fraction removes a fraction of the features. The subset_size argument is a vector that specifies exactly how many features are removed in each iteration. The parameters are mutually exclusive and the default is feature_fraction = 0.5. Usually, RFE fits a new model in each resampling iteration and calculates the feature importance again. We can deactivate this behavior by setting recursive = FALSE. The selection of feature subsets in all iterations is then based solely on the importance scores of the first model trained with all features. When running an RFE with a resampling strategy like cross-validation, multiple models and importance scores are generated. The aggregation parameter determines how the importance scores are aggregated. The option "rank" ranks the importance scores in each iteration and then averages the ranks of the features. The feature with the lowest average rank is removed. The option "mean" averages the importance scores of the features across the iterations. The "mean" should only be used if the learner’s importance scores can be reasonably averaged.

+
+
+

Task

+

The objective of the Sonar data set is to predict whether a sonar signal bounced off a metal cylinder or a rock. The data set includes 60 numerical features (see Figure 1).

+
+
task = tsk("sonar")
+
+
+
+Code +
library(ggplot2)
+library(data.table)
+
+data = melt(as.data.table(task), id.vars = task$target_names, measure.vars = task$feature_names)
+data = data[c("V1", "V10", "V11", "V12", "V13", "V14"), , on = "variable"]
+
+ggplot(data, aes(x = value, fill = Class)) +
+  geom_density(alpha = 0.5) +
+  facet_wrap(~ variable, ncol = 6, scales = "free") +
+  scale_fill_viridis_d(end = 0.8) +
+  theme_minimal() +
+  theme(axis.title.x = element_blank())
+
+
+
+
+
+ +
+
+Figure 1: Distribution of the first 5 features in the Sonar dataset. +
+
+
+
+
+
+
+

Gradient Boosting Machine

+

We start with the GBM learner and set the predict type to "prob" to obtain class probabilities.

+
+
learner = lrn("classif.gbm",
+  distribution = "bernoulli",
+  predict_type = "prob")
+
+

Now we define the feature selection problem by using the fsi() function that constructs an FSelectInstanceSingleCrit. In addition to the task and learner, we have to select a resampling strategy and performance measure to determine how the performance of a feature subset is evaluated. We pass the "none" terminator because the n_features parameter of the optimizer determines when the feature selection stops.

+
+
instance = fsi(
+  task = task,
+  learner = learner,
+  resampling = rsmp("cv", folds = 6),
+  measures = msr("classif.auc"),
+  terminator = trm("none"))
+
+

We are now ready to start the RFE. To do this, we simply pass the instance to the $optimize() method of the optimizer.

+
+
optimizer$optimize(instance)
+
+

The optimizer saves the best feature set and the corresponding estimated performance in instance$result.

+

Figure 2 shows the optimization path of the feature selection. We observe that the performance increases first as the number of features decreases. As soon as informative features are removed, the performance drops.

+
+
+Code +
library(viridisLite)
+library(mlr3misc)
+
+data = as.data.table(instance$archive)
+data[, n:= map_int(importance, length)]
+
+ggplot(data, aes(x = n, y = classif.auc)) +
+  geom_line(
+    color = viridis(1, begin = 0.5),
+    linewidth = 1) +
+  geom_point(
+    fill = viridis(1, begin = 0.5),
+    shape = 21,
+    size = 3,
+    stroke = 0.5,
+    alpha = 0.8) +
+  xlab("Number of Features") +
+  scale_x_reverse() +
+  theme_minimal()
+
+
+
+
+
+ +
+
+Figure 2: Performance of the gradient-boosting models depending on the number of features. +
+
+
+
+
+

The importance scores of the feature sets are recorded in the archive.

+
+
as.data.table(instance$archive)[, list(features, classif.auc, importance)]
+
+
                      features classif.auc                                                importance
+ 1: V1,V10,V11,V12,V13,V14,...   0.8929304 58.83333,58.83333,54.50000,54.00000,53.33333,52.50000,...
+ 2: V1,V10,V11,V12,V13,V15,...   0.9177811 57.33333,56.00000,54.00000,53.66667,50.50000,50.00000,...
+ 3: V1,V10,V11,V12,V13,V15,...   0.9045253 54.83333,54.66667,54.66667,53.00000,51.83333,51.33333,...
+ 4: V1,V10,V11,V12,V13,V15,...   0.8927833 56.00000,55.83333,53.00000,52.00000,50.16667,50.00000,...
+ 5: V1,V10,V11,V12,V13,V15,...   0.9016274 55.50000,53.50000,51.33333,50.00000,49.00000,48.50000,...
+---                                                                                                 
+56:         V11,V12,V16,V48,V9   0.8311625              4.166667,3.333333,2.833333,2.500000,2.166667
+57:             V11,V12,V16,V9   0.8216772                       3.833333,2.666667,2.000000,1.500000
+58:                V11,V12,V16   0.8065807                                2.833333,1.833333,1.333333
+59:                    V11,V12   0.8023780                                         1.833333,1.166667
+60:                        V11   0.7515904                                                         1
+
+
+
+
+

Support Vector Machine

+

Now we will select the optimal feature set for an SVM with a linear kernel. The importance scores are the weights of the model.

+
+
learner = lrn("classif.svm",
+  type = "C-classification",
+  kernel = "linear",
+  predict_type = "prob")
+
+

The SVM learner does not support the calculation of importance scores at first. The reason is that importance scores cannot be determined with all kernels. This can be seen by the missing "importance" property.

+
+
learner$properties
+
+
[1] "multiclass" "twoclass"  
+
+
+

Using the "mlr3fselect.svm_rfe" callback however makes it possible to use a linear SVM with the RFE optimizer. The callback adds the $importance() method internally to the learner. We load the callback with the clbk() function and pass it as the "callback" argument to fsi().

+
+
instance = fsi(
+  task = task,
+  learner = learner,
+  resampling = rsmp("cv", folds = 6),
+  measures = msr("classif.auc"),
+  terminator = trm("none"),
+  callback = clbk("mlr3fselect.svm_rfe"))
+
+

We start the feature selection.

+
+
optimizer$optimize(instance)
+
+

Figure 3 shows the average performance of the SVMs depending on the number of features. We can see that the performance increases significantly with a reduced feature set.

+
+
+Code +
library(viridisLite)
+library(mlr3misc)
+
+data = as.data.table(instance$archive)
+data[, n:= map_int(importance, length)]
+
+ggplot(data, aes(x = n, y = classif.auc)) +
+  geom_line(
+    color = viridis(1, begin = 0.5),
+    linewidth = 1) +
+  geom_point(
+    fill = viridis(1, begin = 0.5),
+    shape = 21,
+    size = 3,
+    stroke = 0.5,
+    alpha = 0.8) +
+  xlab("Number of Features") +
+  scale_x_reverse() +
+  theme_minimal()
+
+
+
+
+
+ +
+
+Figure 3: Performance of the support vector machines depending on the number of features. +
+
+
+
+
+

For datasets with a lot of features, it is more efficient to remove several features per iteration. We show an example where 25% of the features are removed in each iteration.

+
+
optimizer = fs("rfe", n_features = 1, feature_fraction = 0.75)
+
+instance = fsi(
+  task = task,
+  learner = learner,
+  resampling = rsmp("cv", folds = 6),
+  measures = msr("classif.auc"),
+  terminator = trm("none"),
+  callback = clbk("mlr3fselect.svm_rfe"))
+
+optimizer$optimize(instance)
+
+

Figure 4 shows a similar optimization curve as Figure 3 but with fewer evaluated feature sets.

+
+
+Code +
library(viridisLite)
+library(mlr3misc)
+
+data = as.data.table(instance$archive)
+data[, n:= map_int(importance, length)]
+
+ggplot(data, aes(x = n, y = classif.auc)) +
+  geom_line(
+    color = viridis(1, begin = 0.5),
+    linewidth = 1) +
+  geom_point(
+    fill = viridis(1, begin = 0.5),
+    shape = 21,
+    size = 3,
+    stroke = 0.5,
+    alpha = 0.8) +
+  xlab("Number of Features") +
+  scale_x_reverse() +
+  theme_minimal()
+
+
+
+
+
+ +
+
+Figure 4: Optimization path of the feature selection. +
+
+
+
+
+
+
+

Recursive Feature Elimination with Cross Validation

+

RFE-CV estimates the optimal number of features before selecting a feature set. For this, an RFE is run in each resampling iteration and the number of features with the best mean performance is selected (see Figure 5). Then one more RFE is carried out on the complete dataset with the optimal number of features as the final feature set size.

+
+
+
+
+
+
+
%%{ init: { 'flowchart': { 'curve': 'bump' } } }%%
+flowchart TB
+    cross-validation[3-Fold Cross-Validation]
+    cross-validation-->rfe-1
+    cross-validation-->rfe-2
+    cross-validation-->rfe-3
+    subgraph rfe-1[RFE 1]
+    direction TB
+    f14[4 Features]
+    f13[3 Features]
+    f12[2 Features]
+    f11[1 Features]
+    f14-->f13-->f12-->f11
+    style f13 fill:#ccea84
+    end
+    subgraph rfe-2[RFE 2]
+    direction TB
+    f24[4 Features]
+    f23[3 Features]
+    f22[2 Features]
+    f21[1 Features]
+    f24-->f23-->f22-->f21
+    style f23 fill:#ccea84
+    end
+    subgraph rfe-3[RFE 3]
+    direction TB
+    f34[4 Features]
+    f33[3 Features]
+    f32[2 Features]
+    f31[1 Features]
+    f34-->f33-->f32-->f31
+    style f33 fill:#ccea84
+    end
+    all_obs[All Observations]
+    rfe-1-->all_obs
+    rfe-2-->all_obs
+    rfe-3-->all_obs
+    all_obs --> rfe
+    subgraph rfe[RFE]
+    direction TB
+    f54[4 Features]
+    f53[3 Features]
+    f54-->f53
+    style f53 fill:#8e6698
+    end
+
+
+
+
+Figure 5: Example of an RFE-CV. The optimal number of features is estimated with a 3-fold cross-validation. One RFE is executed with each train-test split (RFE 1 to RFE 3). The number of features with the best mean performance (green rectangles) is used as the size of the final feature set. A final RFE is performed on all observations. The algorithm stops when the optimal feature set size is reached (purple rectangle) and the optimized feature set is returned. +
+
+
+
+
+

We retrieve the RFE-CV optimizer. RFE-CV has almost the same control parameters as the RFE optimizer. The only difference is that no aggregation is needed.

+
+
optimizer = fs("rfecv",
+  n_features = 1,
+  feature_number = 1)
+
+

The chosen resampling strategy is used to estimate the optimal number of features. The 6-fold cross-validation results in 6 RFE runs. You can choose any other resampling strategy with multiple iterations. Let’s start the feature selection.

+
+
learner = lrn("classif.svm",
+  type = "C-classification",
+  kernel = "linear",
+  predict_type = "prob")
+
+instance = fsi(
+  task = task,
+  learner = learner,
+  resampling = rsmp("cv", folds = 6),
+  measures = msr("classif.auc"),
+  terminator = trm("none"),
+  callback = clbk("mlr3fselect.svm_rfe"))
+
+optimizer$optimize(instance)
+
+
+
+
+ +
+
+Warning +
+
+
+

The performance of the optimal feature set is calculated on the complete data set and should not be reported as the performance of the final model. Estimate the performance of the final model with nested resampling.

+
+
+

We visualize the selection of the optimal number of features. Each point is the mean performance of the number of features. We achieved the best performance with 19 features.

+
+
+Code +
library(ggplot2)
+library(viridisLite)
+library(mlr3misc)
+
+data = as.data.table(instance$archive)[!is.na(iteration), ]
+aggr = data[, list("y" = mean(unlist(.SD))), by = "batch_nr", .SDcols = "classif.auc"]
+aggr[, batch_nr := 61 - batch_nr]
+
+data[, n:= map_int(importance, length)]
+
+ggplot(aggr, aes(x = batch_nr, y = y)) +
+  geom_line(
+    color = viridis(1, begin = 0.5),
+    linewidth = 1) +
+  geom_point(
+    fill = viridis(1, begin = 0.5),
+    shape = 21,
+    size = 3,
+    stroke = 0.5,
+    alpha = 0.8) +
+  geom_vline(
+    xintercept = aggr[y == max(y)]$batch_nr,
+    colour = viridis(1, begin = 0.33),
+    linetype = 3
+  ) +
+  xlab("Number of Features") +
+  ylab("Mean AUC") +
+  scale_x_reverse() +
+  theme_minimal()
+
+
+
+
+
+ +
+
+Figure 6: Estimation of the optimal number of features. The best mean performance is achieved with 19 features (blue line). +
+
+
+
+
+

The archive contains the extra column "iteration" that indicates in which resampling iteration the feature set was evaluated. The feature subsets of the final RFE run have no value in the "iteration" column because they were evaluated on the complete data set.

+
+
as.data.table(instance$archive)[, list(features, classif.auc, iteration, importance)]
+
+
                       features classif.auc iteration                                                      importance
+  1: V1,V10,V11,V12,V13,V14,...   0.8782895         1       2.864018,1.532774,1.408485,1.399930,1.326165,1.167745,...
+  2: V1,V10,V11,V12,V13,V14,...   0.7026144         2       2.056442,1.706077,1.258703,1.191762,1.190752,1.178514,...
+  3: V1,V10,V11,V12,V13,V14,...   0.8790850         3       1.950412,1.887710,1.820891,1.616219,1.231928,1.138675,...
+  4: V1,V10,V11,V12,V13,V14,...   0.8125000         4 2.6958580,1.5623759,1.4990138,1.3902109,0.9385757,0.9232132,...
+  5: V1,V10,V11,V12,V13,V14,...   0.8807018         5       2.487483,1.470778,1.356517,1.033764,0.635383,0.575074,...
+ ---                                                                                                                 
+398:  V1,V11,V12,V16,V23,V3,...   0.9605275        NA 2.0089739,1.1047492,1.0011253,0.6602411,0.6015470,0.5431803,...
+399:  V1,V12,V16,V23,V3,V30,...   0.9595988        NA 1.8337471,1.1937962,0.9853467,0.7751384,0.7296726,0.6222569,...
+400:  V1,V12,V16,V23,V3,V30,...   0.9589486        NA 1.8824952,1.2468164,1.0106654,0.8090618,0.6983925,0.6568389,...
+401:  V1,V12,V16,V23,V3,V30,...   0.9559766        NA 2.3872902,0.9094028,0.8809098,0.8277941,0.7841591,0.7792772,...
+402:  V1,V12,V16,V23,V3,V30,...   0.9521687        NA 1.9485133,1.1482257,1.1098823,0.9591012,0.8234140,0.8118616,...
+
+
+
+
+

Final Model

+

The learner we use to make predictions on new data is called the final model. The final model is trained with the optimal feature set on the full data set. The optimal set consists of 19 features and is stored in instance$result_feature_set. We subset the task to the optimal feature set and train the learner.

+
+
task$select(instance$result_feature_set)
+learner$train(task)
+
+

The trained model can now be used to predict new, external data.

+
+
+

Conclusion

+

The RFE algorithm is a valuable feature selection method, especially for high-dimensional datasets with only a few observations. The numerous settings of the algorithm in mlr3 make it possible to apply it to many datasets and learners. If you want to know more about feature selection in general, we recommend having a look at our book.

+ + + +
+ +

References

+
+Guyon, Isabelle, Jason Weston, Stephen Barnhill, and Vladimir Vapnik. 2002. “Gene Selection for Cancer Classification Using Support Vector Machines.” Machine Learning 46 (1): 389–422. https://doi.org/10.1023/A:1012487302797. +
+
+Kuhn, Max. 2008. “Building Predictive Models in r Using the Caret Package.” Journal of Statistical Software 28 (November): 1–26. https://doi.org/10.18637/jss.v028.i05. +
+
+Pedregosa, Fabian, Gaël Varoquaux, Alexandre Gramfort, Vincent Michel, Bertrand Thirion, Olivier Grisel, Mathieu Blondel, et al. 2011. “Scikit-Learn: Machine Learning in Python.” Journal of Machine Learning Research 12 (85): 2825–30. http://jmlr.org/papers/v12/pedregosa11a.html. +
+
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/optimization/2023-02-07-recursive-feature-elimination/index_files/figure-html/2023-02-07- recursive-feature-elimination-013-1.png b/gallery/optimization/2023-02-07-recursive-feature-elimination/index_files/figure-html/2023-02-07- recursive-feature-elimination-013-1.png new file mode 100644 index 00000000..83e43cbe Binary files /dev/null and b/gallery/optimization/2023-02-07-recursive-feature-elimination/index_files/figure-html/2023-02-07- recursive-feature-elimination-013-1.png differ diff --git a/gallery/optimization/2023-02-07-recursive-feature-elimination/index_files/figure-html/fig-features-1.png b/gallery/optimization/2023-02-07-recursive-feature-elimination/index_files/figure-html/fig-features-1.png new file mode 100644 index 00000000..e81e52de Binary files /dev/null and b/gallery/optimization/2023-02-07-recursive-feature-elimination/index_files/figure-html/fig-features-1.png differ diff --git a/gallery/optimization/2023-02-07-recursive-feature-elimination/index_files/figure-html/fig-gbm-1.png b/gallery/optimization/2023-02-07-recursive-feature-elimination/index_files/figure-html/fig-gbm-1.png new file mode 100644 index 00000000..c4271f14 Binary files /dev/null and b/gallery/optimization/2023-02-07-recursive-feature-elimination/index_files/figure-html/fig-gbm-1.png differ diff --git a/gallery/optimization/2023-02-07-recursive-feature-elimination/index_files/figure-html/fig-rfecv-1.png b/gallery/optimization/2023-02-07-recursive-feature-elimination/index_files/figure-html/fig-rfecv-1.png new file mode 100644 index 00000000..78ed9448 Binary files /dev/null and b/gallery/optimization/2023-02-07-recursive-feature-elimination/index_files/figure-html/fig-rfecv-1.png differ diff --git a/gallery/optimization/2023-02-07-recursive-feature-elimination/index_files/figure-html/fig-svm-1.png b/gallery/optimization/2023-02-07-recursive-feature-elimination/index_files/figure-html/fig-svm-1.png new file mode 100644 index 00000000..daf01738 Binary files /dev/null and b/gallery/optimization/2023-02-07-recursive-feature-elimination/index_files/figure-html/fig-svm-1.png differ diff --git a/gallery/optimization/2023-02-07-recursive-feature-elimination/index_files/figure-html/fig-svm-2-1.png b/gallery/optimization/2023-02-07-recursive-feature-elimination/index_files/figure-html/fig-svm-2-1.png new file mode 100644 index 00000000..c8b5ef1c Binary files /dev/null and b/gallery/optimization/2023-02-07-recursive-feature-elimination/index_files/figure-html/fig-svm-2-1.png differ diff --git a/gallery/pipelines/2020-02-01-tuning-multiplexer/index.html b/gallery/pipelines/2020-02-01-tuning-multiplexer/index.html new file mode 100644 index 00000000..5e5be560 --- /dev/null +++ b/gallery/pipelines/2020-02-01-tuning-multiplexer/index.html @@ -0,0 +1,1173 @@ + + + + + + + + + + + + + +Tuning Over Multiple Learners – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Tuning Over Multiple Learners

+
+
+

Tune over multiple learners for a single task.

+
+
+
+
+ + +
+ +
+
Authors
+
+

Jakob Richter

+

Bernd Bischl

+
+
+ +
+
Published
+
+

February 1, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +

This use case shows how to tune over multiple learners for a single task. You will learn the following:

+ +

This is an advanced use case. What should you know before:

+ +
+

The Setup

+

Assume, you are given some ML task and what to compare a couple of learners, probably because you want to select the best of them at the end of the analysis. That’s a super standard scenario, it actually sounds so common that you might wonder: Why an (advanced) blog post about this? With pipelines? We will consider 2 cases: (a) Running the learners in their default, so without tuning, and (b) with tuning.

+

We load the mlr3verse package which pulls in the most important packages for this example. The mlr3learners package loads additional learners.

+
+
library(mlr3verse)
+library(mlr3tuning)
+library(mlr3learners)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+

Let’s define our learners.

+
+
learners = list(
+  lrn("classif.xgboost", id = "xgb", eval_metric = "logloss"),
+  lrn("classif.ranger", id = "rf")
+)
+learners_ids = sapply(learners, function(x) x$id)
+
+task = tsk("sonar") # some random data for this demo
+inner_cv2 = rsmp("cv", folds = 2) # inner loop for nested CV
+outer_cv5 = rsmp("cv", folds = 5) # outer loop for nested CV
+
+
+
+

Default Parameters

+
+
+

The Benchmark-Table Approach

+

Assume we don’t want to perform tuning and or with running all learner in their respective defaults. Simply run benchmark on the learners and the tasks. That tabulates our results nicely and shows us what works best.

+
+
grid = benchmark_grid(task, learners, outer_cv5)
+bmr = benchmark(grid)
+bmr$aggregate(measures = msr("classif.ce"))
+
+
   nr task_id learner_id resampling_id iters classif.ce
+1:  1   sonar        xgb            cv     5  0.2736353
+2:  2   sonar         rf            cv     5  0.1973287
+Hidden columns: resample_result
+
+
+
+
+

The Pipelines Approach

+

Ok, why would we ever want to change the simple approach above - and use pipelines / tuning for this? Three reasons:

+
    +
  1. What we are doing with benchmark() is actually statistically flawed, insofar if we report the error of the numerically best method from the benchmark table as its estimated future performance. If we do that we have “optimized on the CV” (we basically ran a grid search over our learners!) and we know that this is will produce optimistically biased results. NB: This is a somewhat ridiculous criticism if we are going over only a handful of options, and the bias will be very small. But it will be noticeable if we do this over hundreds of learners, so it is important to understand the underlying problem. This is a somewhat subtle point, and this gallery post is more about technical hints for mlr3, so we will stop this discussion here.
  2. +
  3. For some tuning algorithms, you might have a chance to more efficiently select from the set of algorithms than running the full benchmark. Because of the categorical nature of the problem, you will not be able to learn stuff like “If learner A works bad, I don’t have to try learner B”, but you can potentially save some resampling iterations. Assume you have so select from 100 candidates, experiments are expensive, and you use a 20-fold CV. If learner A has super-bad results in the first 5 folds of the CV, you might already want to stop here. “Racing” would be such a tuning algorithm.
  4. +
  5. It helps us to foreshadow what comes later in this post where we tune the learners.
  6. +
+

The pipeline just has a single purpose in this example: It should allow us to switch between different learners, depending on a hyperparameter. The pipe consists of three elements:

+
    +
  • branch pipes incoming data to one of the following elements, on different data channels. We can name these channel on construction with options.
  • +
  • our learners (combined with gunion())
  • +
  • unbranch combines the forked paths at the end.
  • +
+
+
graph =
+  po("branch", options = learners_ids) %>>%
+  gunion(lapply(learners, po)) %>>%
+  po("unbranch")
+plot(graph, html = FALSE)
+
+
+
+

+
+
+
+
+

The pipeline has now quite a lot of available hyperparameters. It includes all hyperparameters from all contained learners. But as we don’t tune them here (yet), we don’t care (yet). But the first hyperparameter is special. branch.selection controls over which (named) branching channel our data flows.

+
+
graph$param_set$ids()
+
+
 [1] "branch.selection"                "xgb.alpha"                       "xgb.approxcontrib"              
+ [4] "xgb.base_score"                  "xgb.booster"                     "xgb.callbacks"                  
+ [7] "xgb.colsample_bylevel"           "xgb.colsample_bynode"            "xgb.colsample_bytree"           
+[10] "xgb.disable_default_eval_metric" "xgb.early_stopping_rounds"       "xgb.early_stopping_set"         
+[13] "xgb.eta"                         "xgb.eval_metric"                 "xgb.feature_selector"           
+[16] "xgb.feval"                       "xgb.gamma"                       "xgb.grow_policy"                
+[19] "xgb.interaction_constraints"     "xgb.iterationrange"              "xgb.lambda"                     
+[22] "xgb.lambda_bias"                 "xgb.max_bin"                     "xgb.max_delta_step"             
+[25] "xgb.max_depth"                   "xgb.max_leaves"                  "xgb.maximize"                   
+[28] "xgb.min_child_weight"            "xgb.missing"                     "xgb.monotone_constraints"       
+[31] "xgb.normalize_type"              "xgb.nrounds"                     "xgb.nthread"                    
+[34] "xgb.ntreelimit"                  "xgb.num_parallel_tree"           "xgb.objective"                  
+[37] "xgb.one_drop"                    "xgb.outputmargin"                "xgb.predcontrib"                
+[40] "xgb.predictor"                   "xgb.predinteraction"             "xgb.predleaf"                   
+[43] "xgb.print_every_n"               "xgb.process_type"                "xgb.rate_drop"                  
+[46] "xgb.refresh_leaf"                "xgb.reshape"                     "xgb.seed_per_iteration"         
+[49] "xgb.sampling_method"             "xgb.sample_type"                 "xgb.save_name"                  
+[52] "xgb.save_period"                 "xgb.scale_pos_weight"            "xgb.skip_drop"                  
+[55] "xgb.strict_shape"                "xgb.subsample"                   "xgb.top_k"                      
+[58] "xgb.training"                    "xgb.tree_method"                 "xgb.tweedie_variance_power"     
+[61] "xgb.updater"                     "xgb.verbose"                     "xgb.watchlist"                  
+[64] "xgb.xgb_model"                   "rf.alpha"                        "rf.always.split.variables"      
+[67] "rf.class.weights"                "rf.holdout"                      "rf.importance"                  
+[70] "rf.keep.inbag"                   "rf.max.depth"                    "rf.min.node.size"               
+[73] "rf.min.prop"                     "rf.minprop"                      "rf.mtry"                        
+[76] "rf.mtry.ratio"                   "rf.num.random.splits"            "rf.num.threads"                 
+[79] "rf.num.trees"                    "rf.oob.error"                    "rf.regularization.factor"       
+[82] "rf.regularization.usedepth"      "rf.replace"                      "rf.respect.unordered.factors"   
+[85] "rf.sample.fraction"              "rf.save.memory"                  "rf.scale.permutation.importance"
+[88] "rf.se.method"                    "rf.seed"                         "rf.split.select.weights"        
+[91] "rf.splitrule"                    "rf.verbose"                      "rf.write.forest"                
+
+
graph$param_set$params$branch.selection
+
+
                 id    class lower upper levels        default
+1: branch.selection ParamFct    NA    NA xgb,rf <NoDefault[3]>
+
+
+

We can now tune over this pipeline, and probably running grid search seems a good idea to “touch” every available learner. NB: We have now written down in (much more complicated code) what we did before with benchmark.

+
+
graph_learner = as_learner(graph)
+graph_learner$id = "g"
+
+search_space = ps(
+  branch.selection = p_fct(c("rf", "xgb"))
+)
+
+instance = tune(
+  tuner = tnr("grid_search"),
+  task = task,
+  learner = graph_learner,
+  resampling = inner_cv2,
+  measure = msr("classif.ce"),
+  search_space = search_space
+)
+
+as.data.table(instance$archive)[, list(branch.selection, classif.ce)]
+
+
   branch.selection classif.ce
+1:               rf  0.1778846
+2:              xgb  0.3269231
+
+
+

But: Via this approach we can now get unbiased performance results via nested resampling and using the AutoTuner (which would make much more sense if we would select from 100 models and not 2).

+
+
at = auto_tuner(
+  tuner = tnr("grid_search"),
+  learner = graph_learner,
+  resampling = inner_cv2,
+  measure = msr("classif.ce"),
+  search_space = search_space
+)
+
+rr = resample(task, at, outer_cv5, store_models = TRUE)
+
+

Access inner tuning result.

+
+
extract_inner_tuning_results(rr)[, list(iteration, branch.selection, classif.ce)]
+
+
   iteration branch.selection classif.ce
+1:         1               rf  0.2349398
+2:         2               rf  0.1626506
+3:         3               rf  0.3012048
+4:         4               rf  0.2813396
+5:         5               rf  0.2932444
+
+
+

Access inner tuning archives.

+
+
extract_inner_tuning_archives(rr)[, list(iteration, branch.selection, classif.ce, resample_result)]
+
+
    iteration branch.selection classif.ce      resample_result
+ 1:         1               rf  0.2349398 <ResampleResult[21]>
+ 2:         1              xgb  0.2469880 <ResampleResult[21]>
+ 3:         2               rf  0.1626506 <ResampleResult[21]>
+ 4:         2              xgb  0.2530120 <ResampleResult[21]>
+ 5:         3              xgb  0.3795181 <ResampleResult[21]>
+ 6:         3               rf  0.3012048 <ResampleResult[21]>
+ 7:         4              xgb  0.3714859 <ResampleResult[21]>
+ 8:         4               rf  0.2813396 <ResampleResult[21]>
+ 9:         5              xgb  0.3353414 <ResampleResult[21]>
+10:         5               rf  0.2932444 <ResampleResult[21]>
+
+
+
+
+

Model-Selection and Tuning with Pipelines

+

Now let’s select from our given set of models and tune their hyperparameters. One way to do this is to define a search space for each individual learner, wrap them all with the AutoTuner, then call benchmark() on them. As this is pretty standard, we will skip this here, and show an even neater option, where you can tune over models and hyperparameters in one go. If you have quite a large space of potential learners and combine this with an efficient tuning algorithm, this can save quite some time in tuning as you can learn during optimization which options work best and focus on them. NB: Many AutoML systems work in a very similar way.

+
+
+

Define the Search Space

+

Remember, that the pipeline contains a joint set of all contained hyperparameters. Prefixed with the respective PipeOp ID, to make names unique.

+
+
as.data.table(graph$param_set)[, list(id, class, lower, upper, nlevels)]
+
+
                                 id    class lower upper nlevels
+ 1:                branch.selection ParamFct    NA    NA       2
+ 2:                       xgb.alpha ParamDbl     0   Inf     Inf
+ 3:               xgb.approxcontrib ParamLgl    NA    NA       2
+ 4:                  xgb.base_score ParamDbl  -Inf   Inf     Inf
+ 5:                     xgb.booster ParamFct    NA    NA       3
+ 6:                   xgb.callbacks ParamUty    NA    NA     Inf
+ 7:           xgb.colsample_bylevel ParamDbl     0     1     Inf
+ 8:            xgb.colsample_bynode ParamDbl     0     1     Inf
+ 9:            xgb.colsample_bytree ParamDbl     0     1     Inf
+10: xgb.disable_default_eval_metric ParamLgl    NA    NA       2
+11:       xgb.early_stopping_rounds ParamInt     1   Inf     Inf
+12:          xgb.early_stopping_set ParamFct    NA    NA       3
+13:                         xgb.eta ParamDbl     0     1     Inf
+14:                 xgb.eval_metric ParamUty    NA    NA     Inf
+15:            xgb.feature_selector ParamFct    NA    NA       5
+16:                       xgb.feval ParamUty    NA    NA     Inf
+17:                       xgb.gamma ParamDbl     0   Inf     Inf
+18:                 xgb.grow_policy ParamFct    NA    NA       2
+19:     xgb.interaction_constraints ParamUty    NA    NA     Inf
+20:              xgb.iterationrange ParamUty    NA    NA     Inf
+21:                      xgb.lambda ParamDbl     0   Inf     Inf
+22:                 xgb.lambda_bias ParamDbl     0   Inf     Inf
+23:                     xgb.max_bin ParamInt     2   Inf     Inf
+24:              xgb.max_delta_step ParamDbl     0   Inf     Inf
+25:                   xgb.max_depth ParamInt     0   Inf     Inf
+26:                  xgb.max_leaves ParamInt     0   Inf     Inf
+27:                    xgb.maximize ParamLgl    NA    NA       2
+28:            xgb.min_child_weight ParamDbl     0   Inf     Inf
+29:                     xgb.missing ParamDbl  -Inf   Inf     Inf
+30:        xgb.monotone_constraints ParamUty    NA    NA     Inf
+31:              xgb.normalize_type ParamFct    NA    NA       2
+32:                     xgb.nrounds ParamInt     1   Inf     Inf
+33:                     xgb.nthread ParamInt     1   Inf     Inf
+34:                  xgb.ntreelimit ParamInt     1   Inf     Inf
+35:           xgb.num_parallel_tree ParamInt     1   Inf     Inf
+36:                   xgb.objective ParamUty    NA    NA     Inf
+37:                    xgb.one_drop ParamLgl    NA    NA       2
+38:                xgb.outputmargin ParamLgl    NA    NA       2
+39:                 xgb.predcontrib ParamLgl    NA    NA       2
+40:                   xgb.predictor ParamFct    NA    NA       2
+41:             xgb.predinteraction ParamLgl    NA    NA       2
+42:                    xgb.predleaf ParamLgl    NA    NA       2
+43:               xgb.print_every_n ParamInt     1   Inf     Inf
+44:                xgb.process_type ParamFct    NA    NA       2
+45:                   xgb.rate_drop ParamDbl     0     1     Inf
+46:                xgb.refresh_leaf ParamLgl    NA    NA       2
+47:                     xgb.reshape ParamLgl    NA    NA       2
+48:          xgb.seed_per_iteration ParamLgl    NA    NA       2
+49:             xgb.sampling_method ParamFct    NA    NA       2
+50:                 xgb.sample_type ParamFct    NA    NA       2
+51:                   xgb.save_name ParamUty    NA    NA     Inf
+52:                 xgb.save_period ParamInt     0   Inf     Inf
+53:            xgb.scale_pos_weight ParamDbl  -Inf   Inf     Inf
+54:                   xgb.skip_drop ParamDbl     0     1     Inf
+55:                xgb.strict_shape ParamLgl    NA    NA       2
+56:                   xgb.subsample ParamDbl     0     1     Inf
+57:                       xgb.top_k ParamInt     0   Inf     Inf
+58:                    xgb.training ParamLgl    NA    NA       2
+59:                 xgb.tree_method ParamFct    NA    NA       5
+60:      xgb.tweedie_variance_power ParamDbl     1     2     Inf
+61:                     xgb.updater ParamUty    NA    NA     Inf
+62:                     xgb.verbose ParamInt     0     2       3
+63:                   xgb.watchlist ParamUty    NA    NA     Inf
+64:                   xgb.xgb_model ParamUty    NA    NA     Inf
+65:                        rf.alpha ParamDbl  -Inf   Inf     Inf
+66:       rf.always.split.variables ParamUty    NA    NA     Inf
+67:                rf.class.weights ParamUty    NA    NA     Inf
+68:                      rf.holdout ParamLgl    NA    NA       2
+69:                   rf.importance ParamFct    NA    NA       4
+70:                   rf.keep.inbag ParamLgl    NA    NA       2
+71:                    rf.max.depth ParamInt     0   Inf     Inf
+72:                rf.min.node.size ParamInt     1   Inf     Inf
+73:                     rf.min.prop ParamDbl  -Inf   Inf     Inf
+74:                      rf.minprop ParamDbl  -Inf   Inf     Inf
+75:                         rf.mtry ParamInt     1   Inf     Inf
+76:                   rf.mtry.ratio ParamDbl     0     1     Inf
+77:            rf.num.random.splits ParamInt     1   Inf     Inf
+78:                  rf.num.threads ParamInt     1   Inf     Inf
+79:                    rf.num.trees ParamInt     1   Inf     Inf
+80:                    rf.oob.error ParamLgl    NA    NA       2
+81:        rf.regularization.factor ParamUty    NA    NA     Inf
+82:      rf.regularization.usedepth ParamLgl    NA    NA       2
+83:                      rf.replace ParamLgl    NA    NA       2
+84:    rf.respect.unordered.factors ParamFct    NA    NA       3
+85:              rf.sample.fraction ParamDbl     0     1     Inf
+86:                  rf.save.memory ParamLgl    NA    NA       2
+87: rf.scale.permutation.importance ParamLgl    NA    NA       2
+88:                    rf.se.method ParamFct    NA    NA       2
+89:                         rf.seed ParamInt  -Inf   Inf     Inf
+90:         rf.split.select.weights ParamUty    NA    NA     Inf
+91:                    rf.splitrule ParamFct    NA    NA       3
+92:                      rf.verbose ParamLgl    NA    NA       2
+93:                 rf.write.forest ParamLgl    NA    NA       2
+                                 id    class lower upper nlevels
+
+
+

We decide to tune the mtry parameter of the random forest and the nrounds parameter of xgboost. Additionally, we tune branching parameter that selects our learner.

+

We also have to reflect the hierarchical order of the parameter sets (admittedly, this is somewhat inconvenient). We can only set the mtry value if the pipe is configured to use the random forest (ranger). The same applies for the xgboost parameter.

+
+
search_space = ps(
+  branch.selection = p_fct(c("rf", "xgb")),
+  rf.mtry = p_int(1L, 20L, depends = branch.selection == "rf"),
+  xgb.nrounds = p_int(1, 500, depends = branch.selection == "xgb"))
+
+
+ + +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/pipelines/2020-02-01-tuning-multiplexer/index_files/figure-html/2020-02-01-tuning-multiplexer-006-1.png b/gallery/pipelines/2020-02-01-tuning-multiplexer/index_files/figure-html/2020-02-01-tuning-multiplexer-006-1.png new file mode 100644 index 00000000..dfc7ef45 Binary files /dev/null and b/gallery/pipelines/2020-02-01-tuning-multiplexer/index_files/figure-html/2020-02-01-tuning-multiplexer-006-1.png differ diff --git a/gallery/pipelines/2020-02-01-tuning-multiplexer/index_files/figure-html/2020-02-01-tuning-multiplexer-015-1.png b/gallery/pipelines/2020-02-01-tuning-multiplexer/index_files/figure-html/2020-02-01-tuning-multiplexer-015-1.png new file mode 100644 index 00000000..d8bb92e5 Binary files /dev/null and b/gallery/pipelines/2020-02-01-tuning-multiplexer/index_files/figure-html/2020-02-01-tuning-multiplexer-015-1.png differ diff --git a/gallery/pipelines/2020-03-12-intro-pipelines-titanic/index.html b/gallery/pipelines/2020-03-12-intro-pipelines-titanic/index.html new file mode 100644 index 00000000..7d0eccf9 --- /dev/null +++ b/gallery/pipelines/2020-03-12-intro-pipelines-titanic/index.html @@ -0,0 +1,1210 @@ + + + + + + + + + + + + +A Pipeline for the Titanic Data Set - Basics – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

A Pipeline for the Titanic Data Set - Basics

+
+
+

Build a graph.

+
+
+
+
+ + +
+ +
+
Author
+
+

Florian Pfisterer

+
+
+ +
+
Published
+
+

March 12, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Intro

+

We load the mlr3verse package which pulls in the most important packages for this example. The mlr3learners package loads additional learners. The data is part of the mlr3data package.

+
+
library(mlr3verse)
+library(mlr3learners)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+
+

The titanic data is very interesting to analyze, even though it is part of many tutorials and showcases. This is because it requires many steps often required in real-world applications of machine learning techniques, such as missing value imputation, handling factors and others.

+

The following features are illustrated in this use case section:

+
    +
  • Summarizing the data set
  • +
  • Visualizing data
  • +
  • Splitting data into train and test data sets
  • +
  • Defining a task and a learner
  • +
+
+
+

Exploratory Data Analysis

+

With the dataset, we get an explanation of the meanings of the different variables:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VariablesDescription
survivedSurvival
nameName
ageAge
sexSex
sib_spNumber of siblings / spouses aboard
parchNumber of parents / children aboard
fareAmount paid for the ticket
pc_classPassenger class
embarkedPort of embarkation
ticketTicket number
cabinCabin
+

We can use the skimr package in order to get a first overview of the data:

+
+
data("titanic", package = "mlr3data")
+
+skimr::skim(titanic)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Data summary
Nametitanic
Number of rows1309
Number of columns11
_______________________
Column type frequency:
character3
factor4
numeric4
________________________
Group variablesNone
+

Variable type: character

+ ++++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_rateminmaxemptyn_uniquewhitespace
name01.001282013070
ticket01.0031809290
cabin10140.2311501860
+

Variable type: factor

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_rateorderedn_uniquetop_counts
survived4180.68FALSE2no: 549, yes: 342
pclass01.00TRUE33: 709, 1: 323, 2: 277
sex01.00FALSE2mal: 843, fem: 466
embarked21.00FALSE3S: 914, C: 270, Q: 123
+

Variable type: numeric

+ +++++++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_ratemeansdp0p25p50p75p100hist
age2630.829.8814.410.1721.028.0039.0080.00▂▇▅▂▁
sib_sp01.00.501.040.000.00.001.008.00▇▁▁▁▁
parch01.00.390.870.000.00.000.009.00▇▁▁▁▁
fare11.033.3051.760.007.914.4531.27512.33▇▁▁▁▁
+
+
+

We can now create a Task from our data. As we want to classify whether the person survived or not, we will create a TaskClassif. We’ll ignore the ‘titanic_test’ data for now and come back to it later.

+
+
+

A first model

+

In order to obtain solutions comparable to official leaderboards, such as the ones available from kaggle, we split the data into train and validation set before doing any further analysis. Here we are using the predefined split used by Kaggle.

+
+
task = as_task_classif(titanic, target = "survived", positive = "yes")
+task$set_row_roles(892:1309, "holdout")
+task
+
+
<TaskClassif:titanic> (891 x 11)
+* Target: survived
+* Properties: twoclass
+* Features (10):
+  - chr (3): cabin, name, ticket
+  - dbl (2): age, fare
+  - fct (2): embarked, sex
+  - int (2): parch, sib_sp
+  - ord (1): pclass
+
+
+

Our Task currently has \(3\) features of type character, which we don’t really know how to handle: “Cabin”, “Name”, “Ticket” and “PassengerId”. Additionally, from our skimr::skim() of the data, we have seen, that they have many unique values (up to 891).

+

We’ll drop them for now and see how we can deal with them later on.

+
+
task$select(cols = setdiff(task$feature_names, c("cabin", "name", "ticket")))
+
+

Additionally, we create a resampling instance that allows to compare data.

+
+
cv3 = rsmp("cv", folds = 3L)$instantiate(task)
+
+

To get a first impression of what performance we can fit a simple decision tree:

+
+
learner = mlr_learners$get("classif.rpart")
+# or shorter:
+learner = lrn("classif.rpart")
+
+rr = resample(task, learner, cv3, store_models = TRUE)
+
+rr$aggregate(msr("classif.acc"))
+
+
classif.acc 
+  0.8013468 
+
+
+

So our model should have a minimal accuracy of 0.80 in order to improve over the simple decision tree. In order to improve more, we might need to do some feature engineering.

+
+
+

Optimizing the model

+

If we now try to fit a ‘ranger’ random forest model, we will get an error, as ‘ranger’ models can not naturally handle missing values.

+
+
learner = lrn("classif.ranger", num.trees = 250, min.node.size = 4)
+
+rr = resample(task, learner, cv3, store_models = TRUE)
+
+
Error: Task 'titanic' has missing values in column(s) 'age', 'embarked', but learner 'classif.ranger' does not support this
+
+
+

This means we have to find a way to impute the missing values. To learn how to use more advanced commands of the mlr3pipelines package see:

+ + + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/pipelines/2020-04-18-regression-chains/index.html b/gallery/pipelines/2020-04-18-regression-chains/index.html new file mode 100644 index 00000000..975a5267 --- /dev/null +++ b/gallery/pipelines/2020-04-18-regression-chains/index.html @@ -0,0 +1,1321 @@ + + + + + + + + + + + + +Regression Chains – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Regression Chains

+
+
+

Handle multi-target regression with regression chains.

+
+
+
+
+ + +
+ +
+
Author
+
+

Lennart Schneider

+
+
+ +
+
Published
+
+

April 18, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +

In this tutorial we demonstrate how to use mlr3pipelines to handle multi-target regression by arranging regression models as a chain, i.e., creating a linear sequence of regression models.

+
+

Regression Chains

+

In a simple regression chain, regression models are arranged in a linear sequence. Here, the first model will use the input to predict a single output and the second model will use the input and the prediction output of the first model to make its own prediction and so on. For more details, see e.g. Spyromitros-Xioufis et al. (2016).

+
+
+

Before you start

+

The following sections describe an approach towards working with tasks that have multiple targets. E.g., in the example below, we have three target variables \(y_{1}\) to \(y_{3}\). This type of Task can be created via the mlr3multioutput package (currently under development) in the future. mlr3multioutput will also offer simple chaining approaches as pre-built pipelines (so called ppls). The current goal of this post is to show how such modeling steps can be written as a relatively small amount of pipeline steps and how such steps can be put together. Writing pipelines with such steps allows for great flexibility in modeling more complicated scenarios such as the ones described below.

+
+
+

Prerequisites

+

We load the mlr3verse package which pulls in the most important packages for this example.

+
+
library(mlr3verse)
+
+
Loading required package: mlr3
+
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+
+
+
+

Data

+

In the following, we rely on some toy data. We simulate 100 responses to three target variables, \(y_{1}\), \(y_{2}\), and \(y_{3}\) following a multivariate normal distribution with a mean and covariance matrix of:

+
+
library(data.table)
+library(mvtnorm)
+set.seed(2409)
+n = 100
+(mean <- c(y1 = 1, y2 = 2, y3 = 3))
+
+
y1 y2 y3 
+ 1  2  3 
+
+
(sigma <- matrix(c(1, -0.5, 0.25, -0.5, 1, -0.25, 0.25, -0.25, 1),
+  nrow = 3, ncol = 3, byrow = TRUE
+))
+
+
      [,1]  [,2]  [,3]
+[1,]  1.00 -0.50  0.25
+[2,] -0.50  1.00 -0.25
+[3,]  0.25 -0.25  1.00
+
+
Y = rmvnorm(n, mean = mean, sigma = sigma)
+
+

The feature variables \(x_{1}\), and \(x_{2}\) are simulated as follows: \(x_{1}\) is simply given by \(y_{1}\) and an independent normally distributed error term and \(x_{2}\) is given by \(y_{2}\) and an independent normally distributed error term.

+
+
x1 = Y[, 1] + rnorm(n, sd = 0.1)
+x2 = Y[, 2] + rnorm(n, sd = 0.1)
+
+

The final data is given as:

+
+
data = as.data.table(cbind(Y, x1, x2))
+str(data)
+
+
Classes 'data.table' and 'data.frame':  100 obs. of  5 variables:
+ $ y1: num  0.681 1.836 0.355 1.783 0.974 ...
+ $ y2: num  2.33 1.735 3.126 0.691 1.573 ...
+ $ y3: num  3.19 3.14 2.74 4.31 2.77 ...
+ $ x1: num  0.788 1.754 0.174 1.844 1.05 ...
+ $ x2: num  2.336 1.665 2.967 0.651 1.634 ...
+ - attr(*, ".internal.selfref")=<externalptr> 
+
+
+

This simulates a situation where we have multiple target variables that are correlated with each other, such that predicting them along with each other can improve the resulting prediction model. As a real-world example for such a situation, consider e.g. hospital data, where time spent in the ICU (not known a priori) heavily influences the cost incurred by a patient’s treatment.

+
+
+

3D Visualization of the Data

+

If you feel confident to already have a good feeling of the data, feel free to skip this section. If not, you can use the rgl package to play around with the following four 3D plots with either the feature variables or \(y_{1}\) and \(y_{2}\) on the x- and y-axis and the target variables on the respective z-axes:

+
+
library(rgl)
+colfun = colorRampPalette(c("#161B1D", "#ADD8E6"))
+
+
+
setorder(data, y1)
+plot3d(data$x1, data$x2, data$y1,
+  xlab = "x1", ylab = "x2", zlab = "y1",
+  type = "s", radius = 0.1, col = colfun(n)
+)
+
+
+
setorder(data, y2)
+plot3d(data$x1, data$x2, data$y2,
+  xlab = "x1", ylab = "x2", zlab = "y2",
+  type = "s", radius = 0.1, col = colfun(n)
+)
+
+
+
setorder(data, y3)
+plot3d(data$x1, data$x2, data$y3,
+  xlab = "x1", ylab = "x2", zlab = "y3",
+  type = "s", radius = 0.1, col = colfun(n)
+)
+
+
+
setorder(data, y3)
+plot3d(data$y1, data$y2, data$y3,
+  xlab = "y1", ylab = "y2", zlab = "y3",
+  type = "s", radius = 0.1, col = colfun(n)
+)
+
+
+
+

Building the Pipeline

+

In our regression chain, the first model will predict \(y_{1}\). Therefore, we initialize our Task with respect to this target:

+
+
task = as_task_regr(data, id = "multiregression", target = "y1")
+
+

As Learners we will use simple linear regression models. Our pipeline building the regression chain then has to do the following:

+
    +
  • Use the input to predict \(y_{1}\) within the first learner (i.e., \(y_{1} \sim x_{1} + x_{2}\)).
  • +
  • Combine the input with the prediction of \(y_{1}\), \(\hat{y_{1}}\) and use this to predict \(y_{2}\) within the second learner (i.e., \(y_{2} \sim x_{1} + x_{2} + \hat{y_{1}}\)).
  • +
  • Combine the input with the prediction of \(y_{2}\) and use this to predict \(y_{3}\) within the final third learner (i.e., \(y_{3} \sim x_{1} + x_{2} + \hat{y_{1}} + \hat{y_{2}}\)).
  • +
+

To combine predictions of a Learner with the previous input, we rely on PipeOpLearnerCV and PipeOpNOP arranged in parallel via gunion() combined via PipeOpFeatureUnion. To drop the respective remaining target variables as features, we rely on PipeOpColRoles. The first step of predicting \(y_{1}\) looks like the following:

+
+
step1 = po("copy", outnum = 2, id = "copy1") %>>%
+  gunion(list(
+    po("colroles",
+      id = "drop_y2_y3",
+      new_role = list(y2 = character(), y3 = character())
+    ) %>>%
+      po("learner_cv", learner = lrn("regr.lm"), id = "y1_learner"),
+    po("nop", id = "nop1")
+  )) %>>%
+  po("featureunion", id = "union1")
+step1$plot(html = FALSE)
+
+
+
+

+
+
+
+
+

Training using the input Task, shows us how the output and the $state look like:

+
+
step1_out = step1$train(task)[[1]]
+step1_out
+
+
<TaskRegr:multiregression> (100 x 6)
+* Target: y1
+* Properties: -
+* Features (5):
+  - dbl (5): x1, x2, y1_learner.response, y2, y3
+
+
step1$state
+
+
$copy1
+list()
+
+$drop_y2_y3
+$drop_y2_y3$dt_columns
+[1] "x1" "x2" "y2" "y3"
+
+$drop_y2_y3$affected_cols
+[1] "x1" "x2" "y2" "y3"
+
+$drop_y2_y3$intasklayout
+   id    type
+1: x1 numeric
+2: x2 numeric
+3: y2 numeric
+4: y3 numeric
+
+$drop_y2_y3$outtasklayout
+   id    type
+1: x1 numeric
+2: x2 numeric
+
+$drop_y2_y3$outtaskshell
+Empty data.table (0 rows and 3 cols): y1,x1,x2
+
+
+$y1_learner
+$y1_learner$model
+
+Call:
+stats::lm(formula = task$formula(), data = task$data())
+
+Coefficients:
+(Intercept)           x1           x2  
+   -0.03762      0.99851      0.01364  
+
+
+$y1_learner$log
+Empty data.table (0 rows and 3 cols): stage,class,msg
+
+$y1_learner$train_time
+[1] 0.004
+
+$y1_learner$param_vals
+named list()
+
+$y1_learner$task_hash
+[1] "933a5b384a9aaebf"
+
+$y1_learner$data_prototype
+Empty data.table (0 rows and 3 cols): y1,x1,x2
+
+$y1_learner$task_prototype
+Empty data.table (0 rows and 3 cols): y1,x1,x2
+
+$y1_learner$mlr3_version
+[1] '0.16.1'
+
+$y1_learner$train_task
+<TaskRegr:multiregression> (100 x 3)
+* Target: y1
+* Properties: -
+* Features (2):
+  - dbl (2): x1, x2
+
+$y1_learner$affected_cols
+[1] "x1" "x2"
+
+$y1_learner$intasklayout
+   id    type
+1: x1 numeric
+2: x2 numeric
+
+$y1_learner$outtasklayout
+                    id    type
+1: y1_learner.response numeric
+
+$y1_learner$outtaskshell
+Empty data.table (0 rows and 2 cols): y1,y1_learner.response
+
+
+$nop1
+list()
+
+$union1
+list()
+
+
+

Within the second step we then have to define \(y_{2}\) as the new target. This can be done using PipeOpUpdateTarget (note that PipeOpUpdateTarget currently is not exported but will be in a future version). By default, PipeOpUpdateTarget drops the original target from the feature set, here \(y_{1}\).

+
+
mlr_pipeops$add("update_target", mlr3pipelines:::PipeOpUpdateTarget)
+
+
+
step2 = po("update_target",
+  id = "y2_target",
+  new_target_name = "y2"
+) %>>%
+  po("copy", outnum = 2, id = "copy2") %>>%
+  gunion(list(
+    po("colroles",
+      id = "drop_y3",
+      new_role = list(y3 = character())
+    ) %>>%
+      po("learner_cv", learner = lrn("regr.lm"), id = "y2_learner"),
+    po("nop", id = "nop2")
+  )) %>>%
+  po("featureunion", id = "union2")
+
+

Again, we can train to see how the output and $state look like, but now using the output of step1 as the input:

+
+
step2_out = step2$train(step1_out)[[1]]
+step2_out
+
+
<TaskRegr:multiregression> (100 x 6)
+* Target: y2
+* Properties: -
+* Features (5):
+  - dbl (5): x1, x2, y1_learner.response, y2_learner.response, y3
+
+
step2$state
+
+
$y2_target
+list()
+
+$copy2
+list()
+
+$drop_y3
+$drop_y3$dt_columns
+[1] "x1"                  "x2"                  "y1_learner.response" "y3"                 
+
+$drop_y3$affected_cols
+[1] "y1_learner.response" "x1"                  "x2"                  "y3"                 
+
+$drop_y3$intasklayout
+                    id    type
+1:                  x1 numeric
+2:                  x2 numeric
+3: y1_learner.response numeric
+4:                  y3 numeric
+
+$drop_y3$outtasklayout
+                    id    type
+1:                  x1 numeric
+2:                  x2 numeric
+3: y1_learner.response numeric
+
+$drop_y3$outtaskshell
+Empty data.table (0 rows and 4 cols): y2,y1_learner.response,x1,x2
+
+
+$y2_learner
+$y2_learner$model
+
+Call:
+stats::lm(formula = task$formula(), data = task$data())
+
+Coefficients:
+        (Intercept)  y1_learner.response                   x1                   x2  
+            0.07135              0.22773             -0.25186              0.97877  
+
+
+$y2_learner$log
+Empty data.table (0 rows and 3 cols): stage,class,msg
+
+$y2_learner$train_time
+[1] 0.01
+
+$y2_learner$param_vals
+named list()
+
+$y2_learner$task_hash
+[1] "1bc5196bab655ff5"
+
+$y2_learner$data_prototype
+Empty data.table (0 rows and 4 cols): y2,y1_learner.response,x1,x2
+
+$y2_learner$task_prototype
+Empty data.table (0 rows and 4 cols): y2,y1_learner.response,x1,x2
+
+$y2_learner$mlr3_version
+[1] '0.16.1'
+
+$y2_learner$train_task
+<TaskRegr:multiregression> (100 x 4)
+* Target: y2
+* Properties: -
+* Features (3):
+  - dbl (3): x1, x2, y1_learner.response
+
+$y2_learner$affected_cols
+[1] "y1_learner.response" "x1"                  "x2"                 
+
+$y2_learner$intasklayout
+                    id    type
+1:                  x1 numeric
+2:                  x2 numeric
+3: y1_learner.response numeric
+
+$y2_learner$outtasklayout
+                    id    type
+1: y2_learner.response numeric
+
+$y2_learner$outtaskshell
+Empty data.table (0 rows and 2 cols): y2,y2_learner.response
+
+
+$nop2
+list()
+
+$union2
+list()
+
+
+

In the final third step we define \(y_{3}\) as the new target (again, PipeOpUpdateTarget drops the previous original target from the feature set, here \(y_{2}\)):

+
+
step3 = po("update_target",
+  id = "y3_target",
+  new_target_name = "y3"
+) %>>%
+  po("learner", learner = lrn("regr.lm"), id = "y3_learner")
+
+

Using the output of step2 as input:

+
+
step3_out = step3$train(step2_out)[[1]]
+step3_out
+
+
NULL
+
+
step3$state
+
+
$y3_target
+list()
+
+$y3_learner
+$y3_learner$model
+
+Call:
+stats::lm(formula = task$formula(), data = task$data())
+
+Coefficients:
+        (Intercept)  y2_learner.response  y1_learner.response                   x1                   x2  
+             2.6445               0.8155               3.8776              -3.5217              -0.7304  
+
+
+$y3_learner$log
+Empty data.table (0 rows and 3 cols): stage,class,msg
+
+$y3_learner$train_time
+[1] 0.013
+
+$y3_learner$param_vals
+named list()
+
+$y3_learner$task_hash
+[1] "24dbd64658d33d6d"
+
+$y3_learner$data_prototype
+Empty data.table (0 rows and 5 cols): y3,y2_learner.response,y1_learner.response,x1,x2
+
+$y3_learner$task_prototype
+Empty data.table (0 rows and 5 cols): y3,y2_learner.response,y1_learner.response,x1,x2
+
+$y3_learner$mlr3_version
+[1] '0.16.1'
+
+$y3_learner$train_task
+<TaskRegr:multiregression> (100 x 5)
+* Target: y3
+* Properties: -
+* Features (4):
+  - dbl (4): x1, x2, y1_learner.response, y2_learner.response
+
+
+

The complete pipeline, more precisely Graph, looks like the following:

+
+
graph = step1 %>>% step2 %>>% step3
+graph$plot(html = FALSE)
+
+
+
+

+
+
+
+
+
+
+

Evaluating the Pipeline

+

By wrapping our Graph in a GraphLearner, we can perform 3-fold cross-validation and get an estimated average of the root-mean-square error (of course, in a real world setting splitting the data in a training and test set should have been done):

+
+
learner = as_learner(graph)
+rr = resample(task, learner, rsmp("cv", folds = 3))
+rr$aggregate(msr("regr.mse"))
+
+
 regr.mse 
+0.7265587 
+
+
+
+
+

Predicting with the Pipeline

+

For completeness, we also show how a prediction step without having any target variable data available would look like:

+
+
data_predict = as.data.table(cbind(x1, x2, y1 = NA, y2 = NA, y3 = NA))
+learner$train(task)
+learner$predict_newdata(data_predict)
+
+
<PredictionRegr> for 100 observations:
+    row_ids truth response
+          1    NA 3.116960
+          2    NA 3.327345
+          3    NA 3.010821
+---                       
+         98    NA 3.462541
+         99    NA 3.020585
+        100    NA 3.664326
+
+
+

Note that we have to initialize the Task with \(y_{1}\) as the target but the pipeline will automatically predict \(y_{3}\) in the final step as our final target, which was our ultimate goal here.

+ + + +
+ +

References

+
+Spyromitros-Xioufis, Eleftherios, Grigorios Tsoumakas, William Groves, and Ioannis Vlahavas. 2016. “Multi-Target Regression via Input Space Expansion: Treating Targets as Inputs.” Machine Learning 104 (1): 55–98. https://doi.org/10.1007/s10994-016-5546-z. +
+
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/pipelines/2020-04-18-regression-chains/index_files/figure-html/2020-04-18-regression-chains-012-1.png b/gallery/pipelines/2020-04-18-regression-chains/index_files/figure-html/2020-04-18-regression-chains-012-1.png new file mode 100644 index 00000000..94460be3 Binary files /dev/null and b/gallery/pipelines/2020-04-18-regression-chains/index_files/figure-html/2020-04-18-regression-chains-012-1.png differ diff --git a/gallery/pipelines/2020-04-18-regression-chains/index_files/figure-html/2020-04-18-regression-chains-019-1.png b/gallery/pipelines/2020-04-18-regression-chains/index_files/figure-html/2020-04-18-regression-chains-019-1.png new file mode 100644 index 00000000..aab93665 Binary files /dev/null and b/gallery/pipelines/2020-04-18-regression-chains/index_files/figure-html/2020-04-18-regression-chains-019-1.png differ diff --git a/gallery/pipelines/2020-04-18-regression-chains/index_files/figure-html/regression-chains-013-1.png b/gallery/pipelines/2020-04-18-regression-chains/index_files/figure-html/regression-chains-013-1.png new file mode 100644 index 00000000..93ce05ee Binary files /dev/null and b/gallery/pipelines/2020-04-18-regression-chains/index_files/figure-html/regression-chains-013-1.png differ diff --git a/gallery/pipelines/2020-04-18-regression-chains/index_files/figure-html/regression-chains-020-1.png b/gallery/pipelines/2020-04-18-regression-chains/index_files/figure-html/regression-chains-020-1.png new file mode 100644 index 00000000..75284a1d Binary files /dev/null and b/gallery/pipelines/2020-04-18-regression-chains/index_files/figure-html/regression-chains-020-1.png differ diff --git a/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index.html b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index.html new file mode 100644 index 00000000..6dcd2fec --- /dev/null +++ b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index.html @@ -0,0 +1,1430 @@ + + + + + + + + + + + + + +Pipelines, Selectors, Branches – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Pipelines, Selectors, Branches

+
+
+

Build a preprocessing pipeline with branching.

+
+
+
+
+ + +
+ +
+
Authors
+
+

Milan Dragicevic

+

Giuseppe Casalicchio

+
+
+ +
+
Published
+
+

April 23, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Intro

+

mlr3pipelines offers a very flexible way to create data preprocessing steps. This is achieved by a modular approach using PipeOps. For detailed overview check the mlr3book.

+

Recommended prior readings:

+ +

This post covers:

+
    +
  1. How to apply different preprocessing steps on different features
  2. +
  3. How to branch different preprocessing steps, which allows to select the best performing path
  4. +
  5. How to tune the whole pipeline
  6. +
+
+
+

Prerequisites

+

We load the mlr3verse package which pulls in the most important packages for this example.

+
+
library(mlr3verse)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+

The Pima Indian Diabetes classification task will be used.

+
+
task_pima = tsk("pima")
+skimr::skim(task_pima$data())
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Data summary
Nametask_pima$data()
Number of rows768
Number of columns9
KeyNULL
_______________________
Column type frequency:
factor1
numeric8
________________________
Group variablesNone
+

Variable type: factor

+ ++++++++ + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_rateorderedn_uniquetop_counts
diabetes01FALSE2neg: 500, pos: 268
+

Variable type: numeric

+ +++++++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
skim_variablen_missingcomplete_ratemeansdp0p25p50p75p100hist
age01.0033.2411.7621.0024.0029.0041.0081.00▇▃▁▁▁
glucose50.99121.6930.5444.0099.00117.00141.00199.00▁▇▇▃▂
insulin3740.51155.55118.7814.0076.25125.00190.00846.00▇▂▁▁▁
mass110.9932.466.9218.2027.5032.3036.6067.10▅▇▃▁▁
pedigree01.000.470.330.080.240.370.632.42▇▃▁▁▁
pregnant01.003.853.370.001.003.006.0017.00▇▃▂▁▁
pressure350.9572.4112.3824.0064.0072.0080.00122.00▁▃▇▂▁
triceps2270.7029.1510.487.0022.0029.0036.0099.00▆▇▁▁▁
+
+
+
+
+

Selection of features for preprocessing steps

+

Several features of the pima task have missing values:

+
+
task_pima$missings()
+
+
diabetes      age  glucose  insulin     mass pedigree pregnant pressure  triceps 
+       0        0        5      374       11        0        0       35      227 
+
+
+

A common approach in such situations is to impute the missing values and to add a missing indicator column as explained in the Impute missing variables post. Suppose we want to use

+
    +
  • PipeOpImputeHist on features “glucose”, “mass” and “pressure” which have only few missing values and
  • +
  • PipeOpImputeMedian on features “insulin” and “triceps” which have much more missing values.
  • +
+

In the following subsections, we show two approaches to implement this.

+
+

1. Consider all features and apply the preprocessing step only to certain features

+

Using the affect_columns argument of a PipeOp to define the variables on which a PipeOp will operate with an appropriate Selector function:

+
+
# imputes values based on histogram
+imputer_hist = po("imputehist",
+  affect_columns = selector_name(c("glucose", "mass", "pressure")))
+# imputes values using the median
+imputer_median = po("imputemedian",
+  affect_columns = selector_name(c("insulin", "triceps")))
+# adds an indicator column for each feature with missing values
+miss_ind = po("missind")
+
+

When PipeOps are constructed this way, they will perform the specified preprocessing step on the appropriate features and pass all the input features to the subsequent steps:

+
+
# no missings in "glucose", "mass" and "pressure"
+imputer_hist$train(list(task_pima))[[1]]$missings()
+
+
diabetes      age  insulin pedigree pregnant  triceps  glucose     mass pressure 
+       0        0      374        0        0      227        0        0        0 
+
+
# no missings in "insulin" and "triceps"
+imputer_median$train(list(task_pima))[[1]]$missings()
+
+
diabetes      age  glucose     mass pedigree pregnant pressure  insulin  triceps 
+       0        0        5       11        0        0       35        0        0 
+
+
+

We construct a pipeline that combines imputer_hist and imputer_median. Here, imputer_hist will impute the features “glucose”, “mass” and “pressure”, and imputer_median will impute “insulin” and “triceps”. In each preprocessing step, all the input features are passed to the next step. In the end, we obtain a data set without missing values:

+
+
# combine the two impuation methods
+impute_graph = imputer_hist %>>% imputer_median
+impute_graph$plot(html = FALSE)
+
+
+
+

+
+
+
+
impute_graph$train(task_pima)[[1]]$missings()
+
+
diabetes      age pedigree pregnant  glucose     mass pressure  insulin  triceps 
+       0        0        0        0        0        0        0        0        0 
+
+
+

The PipeOpMissInd operator replaces features with missing values with a missing value indicator:

+
+
miss_ind$train(list(task_pima))[[1]]$data()
+
+
     diabetes missing_glucose missing_insulin missing_mass missing_pressure missing_triceps
+  1:      pos         present         missing      present          present         present
+  2:      neg         present         missing      present          present         present
+  3:      pos         present         missing      present          present         missing
+  4:      neg         present         present      present          present         present
+  5:      pos         present         present      present          present         present
+ ---                                                                                       
+764:      neg         present         present      present          present         present
+765:      neg         present         missing      present          present         present
+766:      neg         present         present      present          present         present
+767:      pos         present         missing      present          present         missing
+768:      neg         present         missing      present          present         present
+
+
+

Obviously, this step can not be applied to the already imputed data as there are no missing values. If we want to combine the previous two imputation steps with a third step that adds missing value indicators, we would need to PipeOpCopy the data two times and supply the first copy to impute_graph and the second copy to miss_ind using gunion(). Finally, the two outputs can be combined with PipeOpFeatureUnion:

+
+
impute_missind = po("copy", 2) %>>%
+  gunion(list(impute_graph, miss_ind)) %>>%
+  po("featureunion")
+impute_missind$plot(html = FALSE)
+
+
+
+

+
+
+
+
+
+
impute_missind$train(task_pima)[[1]]$data()
+
+
     diabetes age pedigree pregnant glucose mass pressure insulin triceps missing_glucose missing_insulin missing_mass
+  1:      pos  50    0.627        6     148 33.6       72     125      35         present         missing      present
+  2:      neg  31    0.351        1      85 26.6       66     125      29         present         missing      present
+  3:      pos  32    0.672        8     183 23.3       64     125      29         present         missing      present
+  4:      neg  21    0.167        1      89 28.1       66      94      23         present         present      present
+  5:      pos  33    2.288        0     137 43.1       40     168      35         present         present      present
+ ---                                                                                                                  
+764:      neg  63    0.171       10     101 32.9       76     180      48         present         present      present
+765:      neg  27    0.340        2     122 36.8       70     125      27         present         missing      present
+766:      neg  30    0.245        5     121 26.2       72     112      23         present         present      present
+767:      pos  47    0.349        1     126 30.1       60     125      29         present         missing      present
+768:      neg  23    0.315        1      93 30.4       70     125      31         present         missing      present
+     missing_pressure missing_triceps
+  1:          present         present
+  2:          present         present
+  3:          present         missing
+  4:          present         present
+  5:          present         present
+ ---                                 
+764:          present         present
+765:          present         present
+766:          present         present
+767:          present         missing
+768:          present         present
+
+
+
+
+

2. Select the features for each preprocessing step and apply the preprocessing steps to this subset

+

We can use the PipeOpSelect to select the appropriate features and then apply the desired impute PipeOp on them:

+
+
imputer_hist_2 = po("select",
+  selector = selector_name(c("glucose", "mass", "pressure")),
+  id = "slct1") %>>% # unique id so we can combine it in a pipeline with other select PipeOps
+  po("imputehist")
+
+imputer_hist_2$plot(html = FALSE)
+
+
+
+

+
+
+
+
+
+
imputer_hist_2$train(task_pima)[[1]]$data()
+
+
     diabetes glucose mass pressure
+  1:      pos     148 33.6       72
+  2:      neg      85 26.6       66
+  3:      pos     183 23.3       64
+  4:      neg      89 28.1       66
+  5:      pos     137 43.1       40
+ ---                               
+764:      neg     101 32.9       76
+765:      neg     122 36.8       70
+766:      neg     121 26.2       72
+767:      pos     126 30.1       60
+768:      neg      93 30.4       70
+
+
+
+
imputer_median_2 =
+  po("select", selector = selector_name(c("insulin", "triceps")), id = "slct2") %>>%
+  po("imputemedian")
+
+imputer_median_2$train(task_pima)[[1]]$data()
+
+
     diabetes insulin triceps
+  1:      pos     125      35
+  2:      neg     125      29
+  3:      pos     125      29
+  4:      neg      94      23
+  5:      pos     168      35
+ ---                         
+764:      neg     180      48
+765:      neg     125      27
+766:      neg     112      23
+767:      pos     125      29
+768:      neg     125      31
+
+
+

To reproduce the result of the fist example (1.), we need to copy the data four times and apply imputer_hist_2, imputer_median_2 and miss_ind on each of the three copies. The fourth copy is required to select the features without missing values and to append it to the final result. We can do this as follows:

+
+
other_features = task_pima$feature_names[task_pima$missings()[-1] == 0]
+
+imputer_missind_2 = po("copy", 4) %>>%
+  gunion(list(imputer_hist_2,
+    imputer_median_2,
+    miss_ind,
+    po("select", selector = selector_name(other_features), id = "slct3"))) %>>%
+  po("featureunion")
+
+imputer_missind_2$plot(html = FALSE)
+
+
+
+

+
+
+
+
+
+
imputer_missind_2$train(task_pima)[[1]]$data()
+
+
     diabetes glucose mass pressure insulin triceps missing_glucose missing_insulin missing_mass missing_pressure
+  1:      pos     148 33.6       72     125      35         present         missing      present          present
+  2:      neg      85 26.6       66     125      29         present         missing      present          present
+  3:      pos     183 23.3       64     125      29         present         missing      present          present
+  4:      neg      89 28.1       66      94      23         present         present      present          present
+  5:      pos     137 43.1       40     168      35         present         present      present          present
+ ---                                                                                                             
+764:      neg     101 32.9       76     180      48         present         present      present          present
+765:      neg     122 36.8       70     125      27         present         missing      present          present
+766:      neg     121 26.2       72     112      23         present         present      present          present
+767:      pos     126 30.1       60     125      29         present         missing      present          present
+768:      neg      93 30.4       70     125      31         present         missing      present          present
+     missing_triceps age pedigree pregnant
+  1:         present  50    0.627        6
+  2:         present  31    0.351        1
+  3:         missing  32    0.672        8
+  4:         present  21    0.167        1
+  5:         present  33    2.288        0
+ ---                                      
+764:         present  63    0.171       10
+765:         present  27    0.340        2
+766:         present  30    0.245        5
+767:         missing  47    0.349        1
+768:         present  23    0.315        1
+
+
+

Note that when there is one input channel, it is automatically copied as many times as needed for the downstream PipeOps. In other words, the code above works also without po("copy", 4):

+
+
imputer_missind_3 = gunion(list(imputer_hist_2,
+  imputer_median_2,
+  miss_ind,
+  po("select", selector = selector_name(other_features), id = "slct3"))) %>>%
+  po("featureunion")
+
+imputer_missind_3$train(task_pima)[[1]]$data()
+
+
     diabetes glucose mass pressure insulin triceps missing_glucose missing_insulin missing_mass missing_pressure
+  1:      pos     148 33.6       72     125      35         present         missing      present          present
+  2:      neg      85 26.6       66     125      29         present         missing      present          present
+  3:      pos     183 23.3       64     125      29         present         missing      present          present
+  4:      neg      89 28.1       66      94      23         present         present      present          present
+  5:      pos     137 43.1       40     168      35         present         present      present          present
+ ---                                                                                                             
+764:      neg     101 32.9       76     180      48         present         present      present          present
+765:      neg     122 36.8       70     125      27         present         missing      present          present
+766:      neg     121 26.2       72     112      23         present         present      present          present
+767:      pos     126 30.1       60     125      29         present         missing      present          present
+768:      neg      93 30.4       70     125      31         present         missing      present          present
+     missing_triceps age pedigree pregnant
+  1:         present  50    0.627        6
+  2:         present  31    0.351        1
+  3:         missing  32    0.672        8
+  4:         present  21    0.167        1
+  5:         present  33    2.288        0
+ ---                                      
+764:         present  63    0.171       10
+765:         present  27    0.340        2
+766:         present  30    0.245        5
+767:         missing  47    0.349        1
+768:         present  23    0.315        1
+
+
+

Usually, po("copy") is required when there are more than one input channels and multiple output channels, and their numbers do not match.

+
+
+
+

Branching

+

We can not know if the combination of a learner with this preprocessing graph will benefit from the imputation steps and the added missing value indicators. Maybe it would have been better to just use imputemedian on all the variables. We could investigate this assumption by adding an alternative path to the graph with the mentioned imputemedian. This is possible using the “branch” PipeOp:

+
+
imputer_median_3 = po("imputemedian", id = "simple_median") # add the id so it does not clash with `imputer_median`
+
+branches = c("impute_missind", "simple_median") # names of the branches
+
+graph_branch = po("branch", branches) %>>%
+  gunion(list(impute_missind, imputer_median_3)) %>>%
+  po("unbranch")
+
+graph_branch$plot(html = FALSE)
+
+
+
+

+
+
+
+
+
+
+

Tuning the pipeline

+

To finalize the graph, we combine it with a rpart learner:

+
+
graph = graph_branch %>>%
+  lrn("classif.rpart")
+
+graph$plot(html = FALSE)
+
+
+
+

+
+
+
+
+

To define the parameters to be tuned, we first check the available ones in the graph:

+
+
as.data.table(graph$param_set)[, .(id, class, lower, upper, nlevels)]
+
+
                              id    class lower upper nlevels
+ 1:             branch.selection ParamFct    NA    NA       2
+ 2:    imputehist.affect_columns ParamUty    NA    NA     Inf
+ 3:  imputemedian.affect_columns ParamUty    NA    NA     Inf
+ 4:                missind.which ParamFct    NA    NA       2
+ 5:                 missind.type ParamFct    NA    NA       4
+ 6:       missind.affect_columns ParamUty    NA    NA     Inf
+ 7: simple_median.affect_columns ParamUty    NA    NA     Inf
+ 8:             classif.rpart.cp ParamDbl     0     1     Inf
+ 9:     classif.rpart.keep_model ParamLgl    NA    NA       2
+10:     classif.rpart.maxcompete ParamInt     0   Inf     Inf
+11:       classif.rpart.maxdepth ParamInt     1    30      30
+12:   classif.rpart.maxsurrogate ParamInt     0   Inf     Inf
+13:      classif.rpart.minbucket ParamInt     1   Inf     Inf
+14:       classif.rpart.minsplit ParamInt     1   Inf     Inf
+15: classif.rpart.surrogatestyle ParamInt     0     1       2
+16:   classif.rpart.usesurrogate ParamInt     0     2       3
+17:           classif.rpart.xval ParamInt     0   Inf     Inf
+
+
+

We decide to jointly tune the "branch.selection", "classif.rpart.cp" and "classif.rpart.minbucket" hyperparameters:

+
+
search_space = ps(
+  branch.selection = p_fct(c("impute_missind", "simple_median")),
+  classif.rpart.cp = p_dbl(0.001, 0.1),
+  classif.rpart.minbucket = p_int(1, 10))
+
+

In order to tune the graph, it needs to be converted to a learner:

+
+
graph_learner = as_learner(graph)
+
+cv3 = rsmp("cv", folds = 3)
+
+cv3$instantiate(task_pima) # to generate folds for cross validation
+
+instance = tune(
+  tuner = tnr("random_search"),
+  task = task_pima,
+  learner = graph_learner,
+  resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce"),
+  search_space = search_space,
+  term_evals = 5)
+
+as.data.table(instance$archive, unnest = NULL, exclude_columns = c("x_domain", "uhash", "resample_result"))
+
+
   branch.selection classif.rpart.cp classif.rpart.minbucket classif.ce runtime_learners           timestamp batch_nr
+1:    simple_median       0.02172886                       2  0.2799479            2.774 2023-11-02 16:33:12        1
+2:   impute_missind       0.07525939                       1  0.2760417            2.701 2023-11-02 16:33:25        2
+3:   impute_missind       0.09207969                       3  0.2773438            1.031 2023-11-02 16:33:36        3
+4:   impute_missind       0.03984117                       6  0.2721354            2.184 2023-11-02 16:33:47        4
+5:   impute_missind       0.09872643                       7  0.2773438            2.507 2023-11-02 16:33:57        5
+   warnings errors
+1:        0      0
+2:        0      0
+3:        0      0
+4:        0      0
+5:        0      0
+
+
+

The best performance in this short tuned experiment was achieved with:

+
+
instance$result
+
+
   branch.selection classif.rpart.cp classif.rpart.minbucket learner_param_vals  x_domain classif.ce
+1:   impute_missind       0.03984117                       6          <list[9]> <list[3]>  0.2721354
+
+
+
+
+

Conclusion

+

This post shows ways on how to specify features on which preprocessing steps are to be performed. In addition it shows how to create alternative paths in the learner graph. The preprocessing steps that can be used are not limited to imputation. Check the list of available PipeOp.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-007-1.png b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-007-1.png new file mode 100644 index 00000000..d3560666 Binary files /dev/null and b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-007-1.png differ diff --git a/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-008-1.png b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-008-1.png new file mode 100644 index 00000000..c7603b3e Binary files /dev/null and b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-008-1.png differ diff --git a/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-009-1.png b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-009-1.png new file mode 100644 index 00000000..79069eae Binary files /dev/null and b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-009-1.png differ diff --git a/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-011-1.png b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-011-1.png new file mode 100644 index 00000000..bad32c18 Binary files /dev/null and b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-011-1.png differ diff --git a/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-014-1.png b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-014-1.png new file mode 100644 index 00000000..8d2e9b02 Binary files /dev/null and b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-014-1.png differ diff --git a/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-017-1.png b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-017-1.png new file mode 100644 index 00000000..677d5e8d Binary files /dev/null and b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-017-1.png differ diff --git a/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-018-1.png b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-018-1.png new file mode 100644 index 00000000..1fc765b9 Binary files /dev/null and b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-018-1.png differ diff --git a/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-019-1.png b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-019-1.png new file mode 100644 index 00000000..0b0be1e8 Binary files /dev/null and b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-019-1.png differ diff --git a/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-024-1.png b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-024-1.png new file mode 100644 index 00000000..845493b4 Binary files /dev/null and b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-024-1.png differ diff --git a/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-025-1.png b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-025-1.png new file mode 100644 index 00000000..f186e2a2 Binary files /dev/null and b/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index_files/figure-html/2020-04-23-pipelines-selectors-branches-025-1.png differ diff --git a/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index.html b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index.html new file mode 100644 index 00000000..6344c237 --- /dev/null +++ b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index.html @@ -0,0 +1,1102 @@ + + + + + + + + + + + + +A Pipeline for the Titanic Data Set - Advanced – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

A Pipeline for the Titanic Data Set - Advanced

+
+
+

Create new features and impute missing values with a pipeline.

+
+
+
+
+ + +
+ +
+
Author
+
+

Florian Pfisterer

+
+
+ +
+
Published
+
+

April 27, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +

This is the second post of the titanic use case series. You can find the first use case here.

+

In this section we will focus on more advanced usage of mlr3pipelines . Specifically, this section illustrates the different options when it comes to data imputation and feature engineering. Furthermore, the section shows how to benchmark, feature engineer and compare our results.

+

We load the mlr3verse package which pulls in the most important packages for this example. The mlr3learners package loads additional learners. The data is part of the mlr3data package.

+
+
library(mlr3verse)
+library(mlr3learners)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+future::plan("multicore")
+
+

As in the basics chapter, we use the titanic data set. To recap we have undertaken the following steps:

+
+
data("titanic", package = "mlr3data")
+
+# setting up the task
+task = as_task_classif(titanic, target = "survived", positive = "yes")
+task$set_row_roles(892:1309, "holdout")
+task$select(cols = setdiff(task$feature_names, c("cabin", "name", "ticket")))
+
+# setting up the learner
+learner = lrn("classif.rpart")
+
+#setting up our resampling method
+resampling = rsmp("cv", folds = 3L)$instantiate(task)
+
+res = resample(task, learner, resampling, store_models = TRUE)
+
+
+

Imputation

+

A very simple way to do this to just impute a constant value for each feature. We could i.e. impute every character or factor column with missing and every numeric column with -999. And depending on the model, this might actually be fine. This approach has a few drawbacks though:

+
    +
  • -999 could be a real value in the data.
  • +
  • imputing -999 skews the distribution of the data, which might result in bad models.
  • +
+

As a result, instead of imputing a constant value, we will do two things: * Draw samples from each numeric features’ histogram using PipeOpImputeHist * Add an additional column for each variable that indicates whether a value was missing or not. If the information that a value was missing is important, this column contains this information.

+

This imputation scheme is called ‘imputation with constants’ and is already implemented in mlr3pipelines . It can be done using PipeOpImputeConstant.

+

Remember that we are trying to optimize our predictive power by using a random forest model (mlr_learners_classif.ranger). Now, random forest models do not naturally handle missing values which is the reason why we need imputation. Before imputation, our data looks as follows:

+
+
task$missings()
+
+
survived      age embarked     fare    parch   pclass      sex   sib_sp 
+       0      177        2        0        0        0        0        0 
+
+
+

Let’s first deal with the categorical variables:

+
+
po_newlvl = po("imputeoor")
+task_newlvl = po_newlvl$train(list(task))[[1]]
+
+

Note that we use the PipeOp in an unusual way, which is why the syntax does not look very clean. We’ll learn how to use a full graph below.

+

First, let’s look at the result:

+
+
task_newlvl$missings()
+
+
survived     fare    parch   pclass      sex   sib_sp      age embarked 
+       0        0        0        0        0        0        0        0 
+
+
+

Cool! embarked does not have missing values anymore. Note that PipeOpImputeOOR by default affects character, factor and ordered columns.

+

For the numeric features we want to do two things, impute values and add an indicator column. In order to do this, we need a more complicated structure, a Graph.

+

Our po_indicator creates the indicator column. We tell it to only do this for numeric and integer columns via its param_vals, and additionally tell it to create a numeric column (0 = “not missing”, 1 = “missing”).

+
+
po_indicator = po("missind",
+  affect_columns = selector_type(c("numeric", "integer")), type = "numeric")
+
+

Now we can simultaneously impute features from the histogram and create indicator columns. This can be achieved using the gunion function, which puts two operations in parallel:

+
+
graph = gunion(list(po_indicator, po("imputehist")))
+graph = graph %>>% po("featureunion")
+
+

Afterwards, we cbind the resulting data using po("featureunion"), connecting the different operations using our graph connector: %>>%. We can now also connect the newlvl imputation:

+
+
graph = graph %>>% po("imputeoor")
+
+

and see what happens when we now train the whole Graph:

+
+
task_imputed = graph$clone()$train(task)[[1]]
+task_imputed$missings()
+
+
   survived missing_age      pclass         sex        fare       parch      sib_sp         age    embarked 
+          0           0           0           0           0           0           0           0           0 
+
+
+

Awesome, now we do not have any missing values!

+
+
autoplot(task_imputed)
+
+
+
+

+
+
+
+
+

We could now use task_imputed for resampling and see whether a ranger model does better. But this is dangerous! If we preprocess all training data at once, data could leak through the different cross-validation folds. In order to do this properly, we have to process the training data in every fold separately. Luckily, this is automatically handled in our Graph, if we use it through a GraphLearner.

+

We can simply append a ranger learner to the Graph and create a GraphLearner from this.

+
+
graph_learner = as_learner(graph$clone() %>>%
+  po("imputesample") %>>%
+  po("fixfactors") %>>%
+  po(learner))
+
+

We needed to use the following commands for the Graph: * PipeOpFixFactors: Removes empty factor levels and removes factor levels that do not exist during training. * PipeOpImputeSample: In some cases, if missing factor levels do not occur during training but only while predicting, PipeOpImputeOOR does not create a new level. For those, we sample a random value.

+
+
rr = resample(task, graph_learner, resampling, store_models = TRUE)
+rr$aggregate(msr("classif.acc"))
+
+
classif.acc 
+  0.7934905 
+
+
+

So our model has not improved heavily, currently it has an accuracy of 0.79.

+
+
+

Feature Engineering

+

We will do this using PipeOpMutate in order to showcase the power of mlr3pipelines . Additionally, we will make use of the character columns. Hence, we will re-select them:

+
+
task$col_roles$feature = c(task$feature_names, c("cabin", "name", "ticket"))
+
+
+
library("stringi")
+po_ftextract = po("mutate", mutation = list(
+  fare_per_person = ~ fare / (parch + sib_sp + 1),
+  deck = ~ factor(stri_sub(cabin, 1, 1)),
+  title = ~ factor(stri_match(name, regex = ", (.*)\\.")[, 2]),
+  surname = ~ factor(stri_match(name, regex = "(.*),")[, 2]),
+  ticket_prefix = ~ factor(stri_replace_all_fixed(stri_trim(stri_match(ticket, regex = "(.*) ")[, 2]), ".", ""))
+))
+
+

Quickly checking what happens:

+
+
task_eng = po_ftextract$clone()$train(list(task))[[1]]
+task_eng$data()
+
+
     survived age embarked    fare parch pclass    sex sib_sp cabin                                                name
+  1:       no  22        S  7.2500     0      3   male      1  <NA>                             Braund, Mr. Owen Harris
+  2:      yes  38        C 71.2833     0      1 female      1   C85 Cumings, Mrs. John Bradley (Florence Briggs Thayer)
+  3:      yes  26        S  7.9250     0      3 female      0  <NA>                              Heikkinen, Miss. Laina
+  4:      yes  35        S 53.1000     0      1 female      1  C123        Futrelle, Mrs. Jacques Heath (Lily May Peel)
+  5:       no  35        S  8.0500     0      3   male      0  <NA>                            Allen, Mr. William Henry
+ ---                                                                                                                   
+887:       no  27        S 13.0000     0      2   male      0  <NA>                               Montvila, Rev. Juozas
+888:      yes  19        S 30.0000     0      1 female      0   B42                        Graham, Miss. Margaret Edith
+889:       no  NA        S 23.4500     2      3 female      1  <NA>            Johnston, Miss. Catherine Helen "Carrie"
+890:      yes  26        C 30.0000     0      1   male      0  C148                               Behr, Mr. Karl Howell
+891:       no  32        Q  7.7500     0      3   male      0  <NA>                                 Dooley, Mr. Patrick
+               ticket fare_per_person deck title   surname ticket_prefix
+  1:        A/5 21171         3.62500 <NA>    Mr    Braund           A/5
+  2:         PC 17599        35.64165    C   Mrs   Cumings            PC
+  3: STON/O2. 3101282         7.92500 <NA>  Miss Heikkinen       STON/O2
+  4:           113803        26.55000    C   Mrs  Futrelle          <NA>
+  5:           373450         8.05000 <NA>    Mr     Allen          <NA>
+ ---                                                                    
+887:           211536        13.00000 <NA>   Rev  Montvila          <NA>
+888:           112053        30.00000    B  Miss    Graham          <NA>
+889:       W./C. 6607         5.86250 <NA>  Miss  Johnston           W/C
+890:           111369        30.00000    C    Mr      Behr          <NA>
+891:           370376         7.75000 <NA>    Mr    Dooley          <NA>
+
+
+
+
autoplot(task_eng$clone()$select(c("sex", "age")), type = "pairs")
+
+
Registered S3 method overwritten by 'GGally':
+  method from   
+  +.gg   ggplot2
+
+
+
Warning: Removed 177 rows containing non-finite values (`stat_boxplot()`).
+
+
+
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
+
+
+
Warning: Removed 177 rows containing non-finite values (`stat_bin()`).
+
+
+
Warning: Removed 177 rows containing non-finite values (`stat_density()`).
+
+
+
Warning: Removed 177 rows containing non-finite values (`stat_boxplot()`).
+
+
+
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
+
+
+
Warning: Removed 177 rows containing non-finite values (`stat_bin()`).
+
+
+
+
+

+
+
+
+
+

Now we can put everything together again, we concatenate our new PipeOp with the Graph created above and use PipeOpSelect in order to de-select the character features we used for feature extraction. Additionally, we collapse the ‘surname’, so only surnames that make up more than 0.6 % of the data are kept.

+

In summary, we do the following:

+
    +
  • mutate: The po_ftextract we defined above extracts additional features from the data.
  • +
  • collapsefactors: Removes factor levels that make up less then 3 % of the data.
  • +
  • select: Drops character columns.
  • +
  • gunion: Puts two PipeOps in parallel. +
      +
    • missind: po_indicator adds a column for each numeric with the info whether the value is NA or not.
    • +
    • imputehist: Imputes numeric and integer columns by sampling from the histogram.
    • +
  • +
  • featureunion: Cbind’s parallel data streams.
  • +
  • imputeoor: Imputes factor and ordered columns.
  • +
  • fixfactors: Removes empty factor levels and removes factor levels that do not exist during training.
  • +
  • imputesample: In some cases, if missing factor levels do not occur during training but only while predicting, imputeoor does not create a new level. For those, we sample a random value.
  • +
  • Learner: Appends a learner to the Graph.
  • +
+

The full graph we created is the following:

+
+
learner = lrn("classif.ranger", num.trees = 500, min.node.size = 4)
+
+
+
graph_final = po_ftextract %>>%
+  po("collapsefactors", param_vals = list(no_collapse_above_prevalence = 0.03)) %>>%
+  po("select", param_vals = list(selector = selector_invert(selector_type("character")))) %>>%
+  gunion(list(po_indicator, po("imputehist"))) %>>%
+  po("featureunion") %>>%
+  po("imputeoor") %>>%
+  po("fixfactors") %>>%
+  po("imputesample") %>>%
+  po(learner)
+
+
+
+

Evaluation

+

Let us see if things have improved:

+
+
graph_learner = as_learner(graph_final)
+
+rr = resample(task, graph_learner, resampling, store_models = TRUE)
+
+rr$aggregate(msr("classif.acc"))
+
+
classif.acc 
+  0.8249158 
+
+
+

We have improved even more!

+
+
+

Benchmarking

+

To undertake benchmarking, we need to set up a benchmarking design. The first step is creating a list with the learners we used, namely the learners form the first and second part of this use case.

+
+
learners = list(
+  lrn("classif.rpart", predict_type = "prob"),
+  lrn("classif.ranger", predict_type = "prob")
+)
+
+

Now we can define our benchmark design. This is done to ensure exhaustive and consistent resampling for all learners. This step is needed to execute over the same train/test split for each task.

+
+
bm_design = benchmark_grid(task_imputed, learners, rsmp("cv", folds = 10))
+bmr = benchmark(bm_design, store_models = TRUE)
+print(bmr)
+
+
<BenchmarkResult> of 20 rows with 2 resampling runs
+ nr task_id     learner_id resampling_id iters warnings errors
+  1 titanic  classif.rpart            cv    10        0      0
+  2 titanic classif.ranger            cv    10        0      0
+
+
+

So, where do we go from here? We could for instance use a boxplot:

+
+
autoplot(bmr)
+
+
+
+

+
+
+
+
+

Further we are able to compare sensitivity and specificity. Here we need to ensure that the benchmark results only contain a single Task:

+
+
autoplot(bmr$clone()$filter(task_id = "titanic"), type = "roc")
+
+
+
+

+
+
+
+
+

Moreover, one can compare the precision-recall:

+
+
# Precision vs Recall
+ggplot2::autoplot(bmr, type = "prc")
+
+
+
+

+
+
+
+
+

As one can see, there are various options when it comes to benchmarking and visualizing. You could have a look at some other use cases in our gallery for inspiration.

+
+
+

Future

+

In this case we have examined a number of different features, but there are many more things to explore! We could extract even more information from the different features and see what happens. But now you are left to yourself! There are many kaggle kernels that treat the Titanic Dataset available. This can be a great starter to find even better models.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-Imputation-titanic-011-1.png b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-Imputation-titanic-011-1.png new file mode 100644 index 00000000..86eb977d Binary files /dev/null and b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-Imputation-titanic-011-1.png differ diff --git a/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-Imputation-titanic-017-1.png b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-Imputation-titanic-017-1.png new file mode 100644 index 00000000..e0f2ed63 Binary files /dev/null and b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-Imputation-titanic-017-1.png differ diff --git a/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-Imputation-titanic-023-1.png b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-Imputation-titanic-023-1.png new file mode 100644 index 00000000..c139be1b Binary files /dev/null and b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-Imputation-titanic-023-1.png differ diff --git a/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-Imputation-titanic-024-1.png b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-Imputation-titanic-024-1.png new file mode 100644 index 00000000..f3f599cf Binary files /dev/null and b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-Imputation-titanic-024-1.png differ diff --git a/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-Imputation-titanic-025-1.png b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-Imputation-titanic-025-1.png new file mode 100644 index 00000000..afe01fd9 Binary files /dev/null and b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-Imputation-titanic-025-1.png differ diff --git a/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-titanic-advanced-012-1.png b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-titanic-advanced-012-1.png new file mode 100644 index 00000000..dee26e51 Binary files /dev/null and b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-titanic-advanced-012-1.png differ diff --git a/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-titanic-advanced-018-1.png b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-titanic-advanced-018-1.png new file mode 100644 index 00000000..10cf23d5 Binary files /dev/null and b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-titanic-advanced-018-1.png differ diff --git a/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-titanic-advanced-024-1.png b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-titanic-advanced-024-1.png new file mode 100644 index 00000000..810b7550 Binary files /dev/null and b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-titanic-advanced-024-1.png differ diff --git a/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-titanic-advanced-025-1.png b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-titanic-advanced-025-1.png new file mode 100644 index 00000000..c264d5f1 Binary files /dev/null and b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-titanic-advanced-025-1.png differ diff --git a/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-titanic-advanced-026-1.png b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-titanic-advanced-026-1.png new file mode 100644 index 00000000..3a46e8b4 Binary files /dev/null and b/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index_files/figure-html/2020-04-27-mlr3pipelines-titanic-advanced-026-1.png differ diff --git a/gallery/pipelines/2020-04-27-tuning-stacking/index.html b/gallery/pipelines/2020-04-27-tuning-stacking/index.html new file mode 100644 index 00000000..7e961b43 --- /dev/null +++ b/gallery/pipelines/2020-04-27-tuning-stacking/index.html @@ -0,0 +1,1285 @@ + + + + + + + + + + + + + +Tuning a Stacked Learner – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Tuning a Stacked Learner

+
+
+

Tune a multilevel stacking model.

+
+
+ +
+ + +
+ +
+
Authors
+
+

Milan Dragicevic

+

Giuseppe Casalicchio

+
+
+ +
+
Published
+
+

April 27, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Intro

+

Multilevel stacking is an ensemble technique, where predictions of several learners are added as new features to extend the orginal data on different levels. On each level, the extended data is used to train a new level of learners. This can be repeated for several iterations until a final learner is trained. To avoid overfitting, it is advisable to use test set (out-of-bag) predictions in each level.

+

In this post, a multilevel stacking example will be created using mlr3pipelines and tuned using mlr3tuning . A similar example is available in the mlr3book. However, we additionally explain how to tune the hyperparameters of the whole ensemble and each underlying learner jointly.

+

In our stacking example, we proceed as follows:

+
    +
  1. Level 0: Based on the input data, we train three learners (rpart, glmnet and lda) on a sparser feature space obtained using different feature filter methods from mlr3filters to obtain slightly decorrelated predictions. The test set predictions of these learners are attached to the original data (used in level 0) and will serve as input for the learners in level 1.
  2. +
  3. Level 1: We transform this extended data using PCA, on which we then train additional three learners (rpart, glmnet and lda). The test set predictions of the level 1 learners are attached to input data used in level 1.
  4. +
  5. Finally, we train a final ranger learner to the data extended by level 1. Note that the number of features selected by the feature filter method in level 0 and the number of principal components retained in level 1 will be jointly tuned with some other hyperparameters of the learners in each level.
  6. +
+
+
+

Prerequisites

+

We load the mlr3verse package which pulls in the most important packages for this example. The mlr3learners package loads additional learners.

+
+
library(mlr3verse)
+library(mlr3learners)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+

For the stacking example, we use the sonar classification task:

+
+
task_sonar = tsk("sonar")
+task_sonar$col_roles$stratum = task_sonar$target_names # stratification
+
+
+
+

Pipeline creation

+
+

Level 0

+

As mentioned, the level 0 learners are rpart, glmnet and lda:

+
+
learner_rpart = lrn("classif.rpart", predict_type = "prob")
+learner_glmnet = lrn("classif.glmnet", predict_type = "prob")
+learner_lda = lrn("classif.lda", predict_type = "prob")
+
+

To create the learner out-of-bag predictions, we use PipeOpLearnerCV:

+
+
cv1_rpart = po("learner_cv", learner_rpart, id = "rprt_1")
+cv1_glmnet = po("learner_cv", learner_glmnet, id = "glmnet_1")
+cv1_lda = po("learner_cv", learner_lda, id = "lda_1")
+
+

A sparser representation of the input data in level 0 is obtained using the following filters:

+
+
anova = po("filter", flt("anova"), id = "filt1")
+mrmr = po("filter", flt("mrmr"), id = "filt2")
+find_cor = po("filter", flt("find_correlation"), id = "filt3")
+
+

To summarize these steps into level 0, we use the gunion() function. The out-of-bag predictions of all level 0 learners is attached using PipeOpFeatureUnion along with the original data passed via PipeOpNOP:

+
+
level0 = gunion(list(
+  anova %>>% cv1_rpart,
+  mrmr %>>% cv1_glmnet,
+  find_cor %>>% cv1_lda,
+  po("nop", id = "nop1"))) %>>%
+  po("featureunion", id = "union1")
+
+

We can have a look at the graph from level 0:

+
+
level0$plot(html = FALSE)
+
+
+
+

+
+
+
+
+
+
+

Level 1

+

Now, we create the level 1 learners:

+
+
cv2_rpart = po("learner_cv", learner_rpart, id = "rprt_2")
+cv2_glmnet = po("learner_cv", learner_glmnet, id = "glmnet_2")
+cv2_lda = po("learner_cv", learner_lda, id = "lda_2")
+
+

All level 1 learners will use PipeOpPCA transformed data as input:

+
+
level1 = level0 %>>%
+  po("copy", 4) %>>%
+  gunion(list(
+    po("pca", id = "pca2_1", param_vals = list(scale. = TRUE)) %>>% cv2_rpart,
+    po("pca", id = "pca2_2", param_vals = list(scale. = TRUE)) %>>% cv2_glmnet,
+    po("pca", id = "pca2_3", param_vals = list(scale. = TRUE)) %>>% cv2_lda,
+    po("nop", id = "nop2"))) %>>%
+  po("featureunion", id = "union2")
+
+

We can have a look at the graph from level 1:

+
+
level1$plot(html = FALSE)
+
+
+
+

+
+
+
+
+

The out-of-bag predictions of the level 1 learners are attached to the input data from level 1 and a final ranger learner will be trained:

+
+
ranger_lrn = lrn("classif.ranger", predict_type = "prob")
+
+ensemble = level1 %>>% ranger_lrn
+ensemble$plot(html = FALSE)
+
+
+
+

+
+
+
+
+
+
+

Defining the tuning space

+

In order to tune the ensemble’s hyperparameter jointly, we define the search space using ParamSet from the paradox package:

+
+
search_space_ensemble = ps(
+  filt1.filter.nfeat = p_int(5, 50),
+  filt2.filter.nfeat = p_int(5, 50),
+  filt3.filter.nfeat = p_int(5, 50),
+  pca2_1.rank. = p_int(3, 50),
+  pca2_2.rank. = p_int(3, 50),
+  pca2_3.rank. = p_int(3, 20),
+  rprt_1.cp = p_dbl(0.001, 0.1),
+  rprt_1.minbucket = p_int(1, 10),
+  glmnet_1.alpha = p_dbl(0, 1),
+  rprt_2.cp = p_dbl(0.001, 0.1),
+  rprt_2.minbucket = p_int(1, 10),
+  glmnet_2.alpha = p_dbl(0, 1),
+  classif.ranger.mtry = p_int(1, 10),
+  classif.ranger.sample.fraction = p_dbl(0.5, 1),
+  classif.ranger.num.trees = p_int(50, 200))
+
+
+
+

Performance comparison

+

Even with a simple ensemble, there is quite a few things to setup. We compare the performance of the ensemble with a simple tuned ranger learner.

+

To proceed, we convert the ensemble pipeline as a GraphLearner:

+
+
learner_ensemble = as_learner(ensemble)
+learner_ensemble$id = "ensemble"
+learner_ensemble$predict_type = "prob"
+
+

We define the search space for the simple ranger learner:

+
+
search_space_ranger = ps(
+  mtry = p_int(1, 10),
+  sample.fraction = p_dbl(0.5, 1),
+  num.trees = p_int(50, 200))
+
+

For performance comparison, we use the benchmark() function that requires a design incorporating a list of learners and a list of tasks. Here, we have two learners (the simple ranger learner and the ensemble) and one task. Since we want to tune the simple ranger learner as well as the whole ensemble learner, we need to create an AutoTuner for each learner to be compared. To do so, we need to define a resampling strategy for the tuning in the inner loop (we use 3-fold cross-validation) and for the final evaluation (outer loop) use use holdout validation:

+
+
inner_resampling = rsmp("cv", folds = 3)
+
+# AutoTuner for the ensemble learner
+at_1 = auto_tuner(
+  tuner = tnr("random_search"),
+  learner = learner_ensemble,
+  resampling = inner_resampling,
+  measure = msr("classif.auc"),
+  search_space = search_space_ensemble,
+  term_evals = 3) # to limit running time
+
+# AutoTuner for the simple ranger learner
+at_2 = auto_tuner(
+  tuner = tnr("random_search"),
+  learner = ranger_lrn,
+  resampling = inner_resampling,
+  measure = msr("classif.auc"),
+  search_space = search_space_ranger,
+  term_evals = 3) # to limit running time
+
+# Define the list of learners
+learners = list(at_1, at_2)
+
+# For benchmarking, we use a simple holdout
+outer_resampling = rsmp("holdout")
+outer_resampling$instantiate(task_sonar)
+
+design = benchmark_grid(
+  tasks = task_sonar,
+  learners = learners,
+  resamplings = outer_resampling
+)
+
+
+
bmr = benchmark(design, store_models = TRUE)
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $predict()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $predict()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $predict()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $predict()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $predict()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $predict()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $predict()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $predict()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $predict()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $predict()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $predict()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $predict()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $predict()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $predict()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $predict()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $predict()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $predict()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $predict()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $train()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $train()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_1's $predict()
+
+
+
Warning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').
+This happened PipeOp glmnet_2's $predict()
+
+
+
+
bmr$aggregate(msr("classif.auc"))[, .(nr, task_id, learner_id, resampling_id, iters, classif.auc)]
+
+

For a more reliable comparison, the number of evaluation of the random search should be increased.

+
+
+
+

Conclusion

+

This example shows the versatility of mlr3pipelines. By using more learners, varied representations of the data set as well as more levels, a powerful yet compute hungry pipeline can be created. It is important to note that care should be taken to avoid name clashes of pipeline objects.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/pipelines/2020-04-27-tuning-stacking/index_files/figure-html/2020-04-27-tuning-stacking-008-1.png b/gallery/pipelines/2020-04-27-tuning-stacking/index_files/figure-html/2020-04-27-tuning-stacking-008-1.png new file mode 100644 index 00000000..9f40681b Binary files /dev/null and b/gallery/pipelines/2020-04-27-tuning-stacking/index_files/figure-html/2020-04-27-tuning-stacking-008-1.png differ diff --git a/gallery/pipelines/2020-04-27-tuning-stacking/index_files/figure-html/2020-04-27-tuning-stacking-009-1.png b/gallery/pipelines/2020-04-27-tuning-stacking/index_files/figure-html/2020-04-27-tuning-stacking-009-1.png new file mode 100644 index 00000000..002e8b3f Binary files /dev/null and b/gallery/pipelines/2020-04-27-tuning-stacking/index_files/figure-html/2020-04-27-tuning-stacking-009-1.png differ diff --git a/gallery/pipelines/2020-04-27-tuning-stacking/index_files/figure-html/2020-04-27-tuning-stacking-011-1.png b/gallery/pipelines/2020-04-27-tuning-stacking/index_files/figure-html/2020-04-27-tuning-stacking-011-1.png new file mode 100644 index 00000000..af286416 Binary files /dev/null and b/gallery/pipelines/2020-04-27-tuning-stacking/index_files/figure-html/2020-04-27-tuning-stacking-011-1.png differ diff --git a/gallery/pipelines/2020-04-27-tuning-stacking/index_files/figure-html/2020-04-27-tuning-stacking-012-1.png b/gallery/pipelines/2020-04-27-tuning-stacking/index_files/figure-html/2020-04-27-tuning-stacking-012-1.png new file mode 100644 index 00000000..474b1373 Binary files /dev/null and b/gallery/pipelines/2020-04-27-tuning-stacking/index_files/figure-html/2020-04-27-tuning-stacking-012-1.png differ diff --git a/gallery/pipelines/2020-04-27-tuning-stacking/index_files/figure-html/2020-04-27-tuning-stacking-013-1.png b/gallery/pipelines/2020-04-27-tuning-stacking/index_files/figure-html/2020-04-27-tuning-stacking-013-1.png new file mode 100644 index 00000000..879dfe88 Binary files /dev/null and b/gallery/pipelines/2020-04-27-tuning-stacking/index_files/figure-html/2020-04-27-tuning-stacking-013-1.png differ diff --git a/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/index.html b/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/index.html new file mode 100644 index 00000000..20717bf0 --- /dev/null +++ b/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/index.html @@ -0,0 +1,1396 @@ + + + + + + + + + + + + +Target Transformations via Pipelines – mlr-org + + + + + + + + + + + + + + + + + + + + +\usepackage{amsmath} + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Target Transformations via Pipelines

+
+
+

Transform the target variable.

+
+
+ +
+ + +
+ +
+
Author
+
+

Lennart Schneider

+
+
+ +
+
Published
+
+

June 15, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +

Transforming the target variable often can lead to predictive improvement and is a widely used tool. Typical transformations are for example the \(\log\) transformation of the target aiming at minimizing (right) skewness, or the Box Cox and Yeo-Johnson transformations being more flexible but having a similar goal.

+

One option to perform, e.g., a \(\log\) transformation would be to manually transform the target prior to training a Learner (and also predicting from it) and then manually invert this transformation via \(\exp\) after predicting from the Learner. This is quite cumbersome, especially if a transformation and inverse transformation require information about both the training and prediction data.

+

In this post, we show how to do various kinds of target transformations using mlr3pipelines and explain the design of the target transformation and inversion PipeOps.

+

You will:

+ +

As a prerequisite, you should be quite familiar with mlr3pipelines, i.e, know about the $state field of PipeOps, input and output channels, as well as Graphs. We will start with a PipeOp for simple target transformations, PipeOpTargetMutate.

+

We load the most important packages for this example.

+
+
library(mlr3)
+library(mlr3learners)
+library(mlr3pipelines)
+library(paradox)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+
+

In all sections we will use the mtcars regression task with mpg being a numerical, positive target:

+
+
task = tsk("mtcars")
+summary(task$data(cols = task$target_names))
+
+
      mpg       
+ Min.   :10.40  
+ 1st Qu.:15.43  
+ Median :19.20  
+ Mean   :20.09  
+ 3rd Qu.:22.80  
+ Max.   :33.90  
+
+
+

Moreover, as a Learner we will use an ordinary linear regression learner:

+
+
learner_lm = lrn("regr.lm")
+
+
+

Simple Target Transformations

+

The term simple refers to transformations that are given by a function of the target, relying on no other arguments (constants are of course allowed). The most prominent example is given by the \(\log\) transformation which we can later invert by applying the \(\exp\) transformation.

+

If you are only interested in doing such a transformation and you do not have the time to read more of this post, simply use the following syntactic sugar:

+
+
g_ppl = ppl("targettrafo", graph = learner_lm)
+g_ppl$param_set$values$targetmutate.trafo = function(x) log(x)
+g_ppl$param_set$values$targetmutate.inverter = function(x) list(response = exp(x$response))
+
+

This constructs a Graph that will \(\log\) transform the target prior to training the linear regression learner (or predicting from it) and \(\exp\) transform the target after predicting from it. Note that you can supply any other Learner or even a whole Graph as the graph argument.

+

Now, we will go into more detail about how this actually works:

+

We can perform a \(\log\) transformation of our numerical, positive target, mpg, using PipeOpTargetMutate (by default, ppl("targettrafo") uses this target transformation PipeOp):

+
+
trafo = po("targetmutate", param_vals = list(trafo = function(x) log(x)))
+
+

We have to specify the trafo parameter as a function of x (which will internally be evaluated to be the target of the Task): trafo = function(x) log(x)). In principle, this is all that is needed to transform the target prior to training a Learner (or predicting from it), i.e., if we now train this PipeOp, we see that the target is transformed as specified:

+
+
trafo$train(list(task))$output$data(cols = task$target_names)
+
+
         mpg
+ 1: 3.044522
+ 2: 3.044522
+ 3: 3.126761
+ 4: 3.063391
+ 5: 2.928524
+ 6: 2.895912
+ 7: 2.660260
+ 8: 3.194583
+ 9: 3.126761
+10: 2.954910
+11: 2.879198
+12: 2.797281
+13: 2.850707
+14: 2.721295
+15: 2.341806
+16: 2.341806
+17: 2.687847
+18: 3.478158
+19: 3.414443
+20: 3.523415
+21: 3.068053
+22: 2.740840
+23: 2.721295
+24: 2.587764
+25: 2.954910
+26: 3.306887
+27: 3.258097
+28: 3.414443
+29: 2.760010
+30: 2.980619
+31: 2.708050
+32: 3.063391
+         mpg
+
+
+

After having predicted from the Learner we could then proceed to apply the inverse transformation function in a similar manner. However, in mlr3pipelines, we decided to go with a more unified design of handling target transformations. In all target transformation PipeOps also the inverse transformation function of the target has to be specified. Therefore, in PipeOpTargetMutate, the parameter inverter also has to be correctly specified:

+
+
trafo$param_set$values$inverter = function(x) list(response = exp(x$response))
+
+

Internally, this function will be applied to the data.table downstream of a Prediction object without the $row_id and $truth columns, and we specify that the $response column should be transformed. Note that applying the inverse transformation will typically only be done to the $response column, because transforming standard errors or probabilities is often not straightforward.

+

To actually carry out the inverse transformation function after predicting from the Learner, we then rely on PipeOpTargetInvert. PipeOpTargetInvert has an empty ParamSet and its sole purpose is to apply the inverse transformation function after having predicted from a Learner (note that this whole design of target transformations may seem somewhat over-engineered at first glance, however, we will learn of its advantages when we later move to the advanced section).

+

PipeOpTargetInvert has two input channels named "fun" and "prediction". During training, both take NULL as input (because this is what a Learner’s "output" output and PipeOpTargetMutate’s "fun" output will return during training). During prediction, the "prediction" input takes a Prediction, and the "fun" input takes the "fun" output from PipeOpTargetMutate (you may have noticed already, that PipeOpTargetMutate has actually two outputs, "fun" and "output", with "fun" returning NULL during training and a function during prediction, while "output" always returns the transformed input Task). We can see this, if we look at:

+
+
trafo$output
+
+
     name train  predict
+1:    fun  NULL function
+2: output  Task     Task
+
+
trafo$predict(list(task))
+
+
$fun
+function(inputs) {
+        assert_list(inputs, len = 1L, types = "Prediction")
+        list(private$.invert(inputs[[1L]], predict_phase_state))
+      }
+<bytecode: 0x555be761be00>
+<environment: 0x555be76215b0>
+
+$output
+<TaskRegr:mtcars> (32 x 11): Motor Trends
+* Target: mpg
+* Properties: -
+* Features (10):
+  - dbl (10): am, carb, cyl, disp, drat, gear, hp, qsec, vs, wt
+
+
+

We will talk more about such technical details in the advanced section. For now, to finally construct our target transformation pipeline, we build a Graph:

+
+
g = Graph$new()
+g$add_pipeop(trafo)
+g$add_pipeop(learner_lm)
+g$add_pipeop(po("targetinvert"))
+
+

Manually connecting the edges is quite cumbersome. First we connect the "output" output of "targetmutate" to the "input" input of "regr.lm":

+
+
g$add_edge(src_id = "targetmutate", dst_id = "regr.lm",
+  src_channel = 2, dst_channel = 1)
+
+

Then we connect the "output" output of "regr.lm" to the "prediction" input of "targetinvert":

+
+
g$add_edge(src_id = "regr.lm", dst_id = "targetinvert",
+  src_channel = 1, dst_channel = 2)
+
+

Finally, we connect the "fun" output of "targetmutate" to the "fun" input of "targetinvert":

+
+
g$add_edge(src_id = "targetmutate", dst_id = "targetinvert",
+  src_channel = 1, dst_channel = 1)
+
+

This graph (which is conceptually the same graph as constructed via the ppl("targettrafo") syntactic sugar above) looks like the following:

+
+
g$plot(html = FALSE)
+
+
+
+

+
+
+
+
+

We can then finally call $train() and $predict() (prior to this we wrap the Graph in a GraphLearner):

+
+
gl = GraphLearner$new(g)
+gl$train(task)
+gl$state
+
+
$model
+$model$targetmutate
+list()
+
+$model$regr.lm
+$model$regr.lm$model
+
+Call:
+stats::lm(formula = task$formula(), data = task$data())
+
+Coefficients:
+(Intercept)           am         carb          cyl         disp         drat         gear           hp         qsec  
+  2.776e+00    4.738e-02   -2.012e-02    7.657e-03    4.989e-05    2.220e-02    5.925e-02   -8.964e-04    3.077e-02  
+         vs           wt  
+ -2.874e-03   -1.723e-01  
+
+
+$model$regr.lm$log
+Empty data.table (0 rows and 3 cols): stage,class,msg
+
+$model$regr.lm$train_time
+[1] 0.012
+
+$model$regr.lm$param_vals
+named list()
+
+$model$regr.lm$task_hash
+[1] "6ca8c90cdf732078"
+
+$model$regr.lm$data_prototype
+Empty data.table (0 rows and 11 cols): mpg,am,carb,cyl,disp,drat...
+
+$model$regr.lm$task_prototype
+Empty data.table (0 rows and 11 cols): mpg,am,carb,cyl,disp,drat...
+
+$model$regr.lm$mlr3_version
+[1] '0.16.1'
+
+$model$regr.lm$train_task
+<TaskRegr:mtcars> (32 x 11): Motor Trends
+* Target: mpg
+* Properties: -
+* Features (10):
+  - dbl (10): am, carb, cyl, disp, drat, gear, hp, qsec, vs, wt
+
+
+$model$targetinvert
+list()
+
+
+$log
+Empty data.table (0 rows and 3 cols): stage,class,msg
+
+$train_time
+[1] 0.098
+
+$param_vals
+$param_vals$targetmutate.trafo
+function(x) log(x)
+<bytecode: 0x555be6fb60f0>
+
+$param_vals$targetmutate.inverter
+function(x) list(response = exp(x$response))
+
+
+$task_hash
+[1] "58a137d2055e8406"
+
+$data_prototype
+Empty data.table (0 rows and 11 cols): mpg,am,carb,cyl,disp,drat...
+
+$task_prototype
+Empty data.table (0 rows and 11 cols): mpg,am,carb,cyl,disp,drat...
+
+$mlr3_version
+[1] '0.16.1'
+
+$train_task
+<TaskRegr:mtcars> (32 x 11): Motor Trends
+* Target: mpg
+* Properties: -
+* Features (10):
+  - dbl (10): am, carb, cyl, disp, drat, gear, hp, qsec, vs, wt
+
+
gl$predict(task)
+
+
<PredictionRegr> for 32 observations:
+    row_ids truth response
+          1  21.0 21.67976
+          2  21.0 21.10831
+          3  22.8 25.73690
+---                       
+         30  19.7 19.58533
+         31  15.0 14.11015
+         32  21.4 23.11105
+
+
+

and contrast this with $train() and $predict() of the naive linear regression learner (also look at the estimated coefficients of the linear regression contained in $state$model):

+
+
learner_lm$train(task)
+learner_lm$state
+
+
$model
+
+Call:
+stats::lm(formula = task$formula(), data = task$data())
+
+Coefficients:
+(Intercept)           am         carb          cyl         disp         drat         gear           hp         qsec  
+   12.30337      2.52023     -0.19942     -0.11144      0.01334      0.78711      0.65541     -0.02148      0.82104  
+         vs           wt  
+    0.31776     -3.71530  
+
+
+$log
+Empty data.table (0 rows and 3 cols): stage,class,msg
+
+$train_time
+[1] 0.004
+
+$param_vals
+named list()
+
+$task_hash
+[1] "58a137d2055e8406"
+
+$data_prototype
+Empty data.table (0 rows and 11 cols): mpg,am,carb,cyl,disp,drat...
+
+$task_prototype
+Empty data.table (0 rows and 11 cols): mpg,am,carb,cyl,disp,drat...
+
+$mlr3_version
+[1] '0.16.1'
+
+$train_task
+<TaskRegr:mtcars> (32 x 11): Motor Trends
+* Target: mpg
+* Properties: -
+* Features (10):
+  - dbl (10): am, carb, cyl, disp, drat, gear, hp, qsec, vs, wt
+
+
learner_lm$predict(task)
+
+
<PredictionRegr> for 32 observations:
+    row_ids truth response
+          1  21.0 22.59951
+          2  21.0 22.11189
+          3  22.8 26.25064
+---                       
+         30  19.7 19.69383
+         31  15.0 13.94112
+         32  21.4 24.36827
+
+
+

You should continue reading, if you are interested in more advanced target transformations, i.e., where the transformation and inverse transformation require information about both the training and prediction data.

+

First we will introduce the abstract base class for doing target transformations, PipeOpTargetTrafo, from which PipeOpTargetMutate inherits.

+
+
+

Abstract Base Class: PipeOpTargetTrafo

+

No matter how “complicated” the actual target transformation and inverse transformation may be, applying the inverse transformation function after having predicted from a Learner will always be done via PipeOpTargetInvert (as already outlined above, PipeOpTargetInvert has an empty ParamSet and its sole purpose is to apply the inverse transformation function after having predicted from a Learner). All Graphs for doing target transformations will therefore look similar like the simple one above, i.e., a target transformation PipeOp followed by some Learner or a whole Graph, followed by PipeOpTargetInvert. Therefore, using ppl("targettrafo") to construct such Graphs is highly recommended.

+

To allow for more advanced target transformations, we now have a closer look at the abstract base class, PipeOpTargetTrafo:

+

PipeOpTargetTrafo has one input channel, named "input" taking a Task both during training and prediction. It’s two output channels are named "fun" and "output". During training "fun" returns NULL and during prediction "fun" returns a function that will be used by PipeOpTargetInvert to perform the inverse target transformation on PipeOpTargetInvert’s "prediction" input. "output" returns the modified input Task both during training and prediction.

+

Subclasses can overload up to four functions:

+
    +
  • .get_state() takes the input Task and returns a list() which will internally be used to set the $state. Typically it is sensible to make use of the $state during .transform() and .train_invert(). The base implementation returns list() and should be overloaded if setting the state is desired.

  • +
  • .transform() takes the input Task and returns a modified Task (i.e., the Task with the transformed target). This is the main function for doing the actual target transformation. Note that .get_state() is evaluated a single time during training right before .transform() and therefore, you can rely on the $state that has been set. To update the input Task with respect to the transformed target, subclasses should make use of the convert_task() function and drop the original target from the Task. .transform() also accepts a phase argument that will receive "train" during training and "predict" during prediction. This can be used to enable different behavior during training and prediction. .transform() should always be overloaded by subclasses.

  • +
  • .train_invert() takes the input Task and returns a predict_phase_state object. This can be anything. Note that .train_invert() should not modify the input Task. The base implementation returns a list with a single argument, the $truth column of the input Task and should be overloaded if a more training-phase-dependent state is desired.

  • +
  • .invert() takes a Prediction and a predict_phase_state object as inputs and returns a Prediction. This is the main function for specifying the actual inverse target transformation that will later be carried out by PipeOpTargetInvert. Internally a private helper function , .invert_help() will construct the function that will be returned by the "fun" output of PipeOpTargetTrafo so that PipeOpTargetInvert can later simply dispatch this inverse target transformation on its "prediction" input.

  • +
+

The supposed workflow of a class inherited from PipeOpTargetTrafo is given in the following figure:

+
+
+
+
+

+
+
+
+
+

To solidify our understanding we will design a new target transformation PipeOp in the next section: PipeOpTargetTrafoBoxCox

+
+
+

Hands on: PipeOpTargetTrafoBoxCox

+
+
library(R6)
+
+

The Box-Cox transformation of a target \(y_{i}\) is given as:

+

\[y_{i}(\lambda) = \begin{cases} +\frac{y_{i}^{\lambda} - 1}{\lambda} & \text{if}~\lambda \neq 0; \\ +\log(y_{i}) & \text{if}~\lambda = 0 +\end{cases}\]

+

mlr3pipelines already supports the Box-Cox transformation for numerical, positive features, see ?PipeOpBoxCox.

+

Here we will design a PipeOp to apply the Box-Cox transformation as a target transformation. The \(\lambda\) parameter of the transformation is estimated during training and used for both the training and prediction transformation. After predicting from a Learner we will as always apply the inverse transformation function. To do the actual transformation we will use bestNormalize::boxcox().

+

First, we inherit from PipeOpTargetTrafo and overload the initialize() function:

+
+
PipeOpTargetTrafoBoxCox = R6Class("PipeOpTargetTrafoBoxCox",
+  inherit = PipeOpTargetTrafo,
+  public = list(
+    initialize = function(id = "targettrafoboxcox", param_vals = list()) {
+      param_set = ps(
+        standardize = p_lgl(default = TRUE, tags = c("train", "boxcox")),
+        eps = p_dbl(default = 0.001, lower = 0, tags = c("train", "boxcox")),
+        lower = p_dbl(default = -1L, tags = c("train", "boxcox")),
+        upper = p_dbl(default = 2L, tags = c("train", "boxcox"))
+      )
+      super$initialize(id = id, param_set = param_set, param_vals = param_vals,
+        packages = "bestNormalize", task_type_in = "TaskRegr",
+        task_type_out = "TaskRegr")
+    }
+  ),
+  private = list(
+
+    .get_state = function(task) {
+      ...
+    },
+
+    .transform = function(task, phase) {
+      ...
+    },
+
+    .train_invert = function(task) {
+      ...
+    },
+
+    .invert = function(prediction, predict_phase_state) {
+      ...
+    }
+  )
+)
+
+

As parameters, we allow "standardize" (whether to center and scale the transformed values to attempt a standard normal distribution), "eps" (tolerance parameter to identify if the \(\lambda\) parameter is equal to zero), "lower" (lower value for the estimation of the \(\lambda\) parameter) and "upper" (upper value for the estimation of the \(\lambda\) parameter). Note that we set task_type_in = "TaskRegr" and task_type_out = "TaskRegr" to specify that this PipeOp only works for regression Tasks.

+

Second, we overload the four functions as mentioned above.

+

We start with .get_state(). We extract the target and apply the Box-Cox transformation to the target. This yields an object of class "boxcox" which we will wrap in a list() and set as the $state (bc$x.t = NULL and bc$x = NULL is done to save some memory because we do not need the transformed original data and original data later):

+
+
    .get_state = function(task) {
+      target = task$data(cols = task$target_names)[[1L]]
+      bc = mlr3misc::invoke(bestNormalize::boxcox, target,
+        .args = self$param_set$get_values(tags = "boxcox"))
+      bc$x.t = NULL
+      bc$x = NULL
+      list(bc = bc)
+    },
+
+

Next, we tackle .transform(). This is quite straightforward, because objects of class "boxcox" have their own predict method which we can use here to carry out the actual Box-Cox transformation based on the learned \(\lambda\) parameter as stored in the "boxcox" object in the $state (both during training and prediction). We then rename the target, add it to the task and finally update the task with respect to this new target:

+
+
    .transform = function(task, phase) {
+      target = task$data(cols = task$target_names)[[1L]]
+      new_target = as.data.table(predict(self$state$bc, newdata = target))
+      colnames(new_target) = paste0(task$target_names, ".bc")
+      task$cbind(new_target)
+      convert_task(task, target = colnames(new_target),
+        drop_original_target = TRUE)
+    },
+
+

Time to overload .train_invert(). This is even more straightforward, because the prediction method for objects of class "boxcox" directly allows for inverting the transformation via setting the argument inverse = TRUE. Therefore, we only need the "boxcox" object stored in the $state along the $truth column of the input Task (remember that this list will later be available as the predict_phase_state object):

+
+
    .train_invert = function(task) {
+      list(truth = task$truth(), bc = self$state$bc)
+    },
+
+

Finally, we overload .invert(). We extract the truth from the predict_phase_state and the response from the Prediction. We then apply the inverse Box-Cox transformation to the response based on the \(\lambda\) parameter and the mean and standard deviation learned during training, relying on the predict_phase_state object. Finally, we construct a new Prediction object:

+
+
    .invert = function(prediction, predict_phase_state) {
+      truth = predict_phase_state$truth
+      response = predict(predict_phase_state$bc, newdata = prediction$response,
+        inverse = TRUE)
+      PredictionRegr$new(row_ids = prediction$row_ids, truth = truth,
+        response = response)
+    }
+
+

Note that this PipeOp is ill-equipped to handle the case of predict_type = "se", i.e., we always only return a response prediction (as outlined above, this is the case for most target transformations, because transforming standard errors or probabilities of a prediction is often not straightforward). We could of course check whether the predict_type is set to "se" and if this is the case, return NA as the standard errors.

+

To construct our final target transformation Graph with our linear regression learner, we again simply make use of ppl("targettrafo"):

+
+
g_bc = ppl("targettrafo", graph = learner_lm,
+  trafo_pipeop = PipeOpTargetTrafoBoxCox$new())
+
+

The following plot should already look quite familiar:

+
+
g_bc$plot(html = FALSE)
+
+
+
+

+
+
+
+
+

Finally we $train() and $predict() on the task (again, we wrap the Graph in a GraphLearner):

+
+
gl_bc = GraphLearner$new(g_bc)
+gl_bc$train(task)
+gl_bc$state
+
+
$model
+$model$regr.lm
+$model$regr.lm$model
+
+Call:
+stats::lm(formula = task$formula(), data = task$data())
+
+Coefficients:
+(Intercept)           am         carb          cyl         disp         drat         gear           hp         qsec  
+ -0.6272999    0.1670950   -0.0663126    0.0237529    0.0002376    0.0759944    0.1963335   -0.0030367    0.1043210  
+         vs           wt  
+ -0.0080166   -0.5800635  
+
+
+$model$regr.lm$log
+Empty data.table (0 rows and 3 cols): stage,class,msg
+
+$model$regr.lm$train_time
+[1] 0.007
+
+$model$regr.lm$param_vals
+named list()
+
+$model$regr.lm$task_hash
+[1] "612ab4e0ad596159"
+
+$model$regr.lm$data_prototype
+Empty data.table (0 rows and 11 cols): mpg.bc,am,carb,cyl,disp,drat...
+
+$model$regr.lm$task_prototype
+Empty data.table (0 rows and 11 cols): mpg.bc,am,carb,cyl,disp,drat...
+
+$model$regr.lm$mlr3_version
+[1] '0.16.1'
+
+$model$regr.lm$train_task
+<TaskRegr:mtcars> (32 x 11): Motor Trends
+* Target: mpg.bc
+* Properties: -
+* Features (10):
+  - dbl (10): am, carb, cyl, disp, drat, gear, hp, qsec, vs, wt
+
+
+$model$targettrafoboxcox
+$model$targettrafoboxcox$bc
+Standardized Box Cox Transformation with 32 nonmissing obs.:
+ Estimated statistics:
+ - lambda = 0.02955701 
+ - mean (before standardization) = 3.092016 
+ - sd (before standardization) = 0.324959 
+
+
+$model$targetinvert
+list()
+
+
+$log
+Empty data.table (0 rows and 3 cols): stage,class,msg
+
+$train_time
+[1] 0.075
+
+$param_vals
+named list()
+
+$task_hash
+[1] "58a137d2055e8406"
+
+$data_prototype
+Empty data.table (0 rows and 11 cols): mpg,am,carb,cyl,disp,drat...
+
+$task_prototype
+Empty data.table (0 rows and 11 cols): mpg,am,carb,cyl,disp,drat...
+
+$mlr3_version
+[1] '0.16.1'
+
+$train_task
+<TaskRegr:mtcars> (32 x 11): Motor Trends
+* Target: mpg
+* Properties: -
+* Features (10):
+  - dbl (10): am, carb, cyl, disp, drat, gear, hp, qsec, vs, wt
+
+
gl_bc$predict(task)
+
+
<PredictionRegr> for 32 observations:
+    row_ids truth response
+          1  21.0 21.70854
+          2  21.0 21.13946
+          3  22.8 25.75242
+---                       
+         30  19.7 19.58934
+         31  15.0 14.10658
+         32  21.4 23.15263
+
+
+

We could now proceed to benchmark our different target transformations:

+
+
bg = benchmark_grid(list(task), learners = list(learner_lm, gl, gl_bc),
+  resamplings = list(rsmp("cv", folds = 10)))
+bmr = benchmark(bg)
+
+
+
bmr$aggregate(msr("regr.mse"))
+
+
   nr task_id                             learner_id resampling_id iters  regr.mse
+1:  1  mtcars                                regr.lm            cv    10 11.866071
+2:  2  mtcars      targetmutate.regr.lm.targetinvert            cv    10  7.793303
+3:  3  mtcars targettrafoboxcox.regr.lm.targetinvert            cv    10  8.230192
+Hidden columns: resample_result
+
+
+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/index_files/figure-html/2020-06-15-target-transformations-via-pipelines-014-1.png b/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/index_files/figure-html/2020-06-15-target-transformations-via-pipelines-014-1.png new file mode 100644 index 00000000..e908ca86 Binary files /dev/null and b/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/index_files/figure-html/2020-06-15-target-transformations-via-pipelines-014-1.png differ diff --git a/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/index_files/figure-html/2020-06-15-target-transformations-via-pipelines-026-1.png b/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/index_files/figure-html/2020-06-15-target-transformations-via-pipelines-026-1.png new file mode 100644 index 00000000..d2678fdf Binary files /dev/null and b/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/index_files/figure-html/2020-06-15-target-transformations-via-pipelines-026-1.png differ diff --git a/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/index_files/figure-html/target-transformations-via-pipelines-015-1.png b/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/index_files/figure-html/target-transformations-via-pipelines-015-1.png new file mode 100644 index 00000000..ba57cc42 Binary files /dev/null and b/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/index_files/figure-html/target-transformations-via-pipelines-015-1.png differ diff --git a/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/index_files/figure-html/target-transformations-via-pipelines-027-1.png b/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/index_files/figure-html/target-transformations-via-pipelines-027-1.png new file mode 100644 index 00000000..bd89b99c Binary files /dev/null and b/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/index_files/figure-html/target-transformations-via-pipelines-027-1.png differ diff --git a/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/workflow.svg b/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/workflow.svg new file mode 100644 index 00000000..14796692 --- /dev/null +++ b/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/workflow.svg @@ -0,0 +1 @@ + diff --git a/gallery/pipelines/2020-09-11-liver-patient-classification/index.html b/gallery/pipelines/2020-09-11-liver-patient-classification/index.html new file mode 100644 index 00000000..b65e49a6 --- /dev/null +++ b/gallery/pipelines/2020-09-11-liver-patient-classification/index.html @@ -0,0 +1,1348 @@ + + + + + + + + + + + + + + + + +Liver Patient Classification Based on Diagnostic Measures – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Liver Patient Classification Based on Diagnostic Measures

+
+
+

Tune and benchmark pipelines.

+
+
+ +
+ + +
+ +
+
Authors
+
+

Julian Lange

+

Jae-Eun Nam

+

Viet Tran

+

Simon Wiegrebe

+

Henri Funk (Editor)

+
+
+ +
+
Published
+
+

September 11, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Preamble

+

The following examples were created as part of the Introduction to Machine Learning Lecture at LMU Munich. The goal of the project was to create and compare one or several machine learning pipelines for the problem at hand together with exploratory analysis and an exposition of results. The posts were contributed to the mlr3gallery by the authors and edited for better legibility by the editor. We want to thank the authors for allowing us to publish their results. Note, that correctness of the results can not be guaranteed.

+
+

Prerequisites

+

This tutorial assumes familiarity with the basics of mlr3tuning and mlr3pipelines. Consult the mlr3book if some aspects are not fully understandable. We load the most important packages for this example.

+
+
library(mlr3verse)
+library(dplyr)
+library(tidyr)
+library(DataExplorer)
+library(ggplot2)
+library(gridExtra)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+

Note, that expensive calculations are pre-saved in rds files in this tutorial to save computational time.

+

Machine learning (ML), a branch of both computer science and statistics, in conjunction with new computing technologies has been transforming research and industries across the board over the past decade. A prime example for this is the healthcare industry, where applications of ML, as well as artificial intelligence in general, have become more and more popular in recent years. One very frequently researched and applied use of ML in the medical field is the area of disease identification and diagnosis. ML technologies have shown potential in detecting anomalies and diseases through pattern recognition, even though an entirely digital diagnosis by a computer is probably still something for the far future. However, suitable and reliable models estimating the risk of diseases could help real doctors make quicker and better decisions today already. In this use case we examined machine learning algorithms and learners for the specific application of liver disease detection. The task is therefore a binary classification task to predict whether a patient has liver disease or not based on some common diagnostic measurements. This report is organized as follows. Section 1 introduces the data and section 2 provides more in-depth data exploration. Section 3 presents learners and their hyperparameter tuning while section 4, dealing with model fitting and benchmarking, presents results and conclusions.

+
+
+
+

Indian Liver Patient Dataset

+

The data set we used for our project is the “Indian Liver Patient Dataset” which was obtained from the mlr3data package. It was donated by three professors from India in 2012 UCI Machine Learning Repository” (n.d.).

+
+
# Importing data
+data("ilpd", package = "mlr3data")
+
+

It contains data for 583 patients collected in the north east of Andhra Pradesh, one of the 28 states of India. The observations are divided into two classes based on the patient having liver disease or not. Besides the class variable, which is our target, ten, mostly numerical, features are provided. To describe the features in more detail, the table below lists the variables included in the dataset.

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VariableDescription
ageAge of the patient (all patients above 89 are labelled as 90
genderSex of the patient (1 = female, 0 = male)
total_bilirubinTotal serum bilirubin (in mg/dL)
direct_bilirubinDirect bilirubin level (in mg/dL)
alkaline_phosphataseSerum alkaline phosphatase level (in U/L)
alanine_transaminaseSerum alanine transaminase level (in U/L)
aspartate_transaminaseSerum aspartate transaminase level (in U/L)
total_proteinTotal serum protein (in g/dL)
albuminSerum albumin level (in g/dL)
albumin_globulin_ratioAlbumin-to-globulin ratio
diseasedTarget variable (1 = liver disease, 0 = no liver disease)
+

As one can see, besides age and gender, the dataset contains eight additional numerical features. While the names and corresponding measurements look rather cryptic to the uninformed eye, they are all part of standard blood tests conducted to gather information about the state of a patient’s liver, so-called liver function tests. All of these measurements are frequently used markers for liver disease. For the first five, measuring the chemical compound bilirubin and the three enzymes alkaline phosphatase, alanine transaminase and aspartate transaminase, elevated levels indicate liver disease Gowda et al. (2009) Oh and Hustead (2011). For the remaining three, which concern protein levels, lower-than-normal values suggest a liver problem Carvalho and Machado (2018) Total Protein, Albumin-Globulin (A/G) Ratio (n.d.). Lastly, one should note that some of the measurements are part of more than one variable. For example, the total serum bilirubin is simply the sum of both the direct and indirect bilirubin levels and the amount of albumin is used to calculate the values of the total serum protein as well as the albumin-to-globulin ratio. So, one might already suspect that some of the features are highly correlated to one another, but more on that kind of analysis in the following section.

+
+
+

Data exporation

+
+

Univariate distribution

+

Next, we looked into the univariate distribution of each of the variables. We began with the target and the only discrete feature, gender, which are both binary.

+
+
+
+
+

+
+
+
+
+

The distribution of the target variable is quite imbalanced, as the barplot shows: the number of patients with and without liver disease equals 416 and 167, respectively. The underrepresentation of a class, in our case those without liver disease, might worsen the performance of ML models. In order to examine this, we additionally fitted the models on a dataset where we randomly over-sampled the minority class, resulting in a perfectly balanced dataset. Furthermore, we applied stratified sampling to ensure the proportion of the classes is maintained during cross-validation.

+

The only discrete feature gender is quite imbalanced, too. As one can see in the next section, this proportion is also observed within each target class. Prior to that, we looked into the distributions of the metric features.

+
+
+
+
+

+
+
+
+
+

Strikingly, some of the metric features are extremely right-skewed and contain several extreme values. To reduce the impact of outliers and since some models assume normality of features, we log-transformed these variables.

+
+
+

Features by class

+

To picture the relationship between the target and the features, we analysed the distributions of the features by class. First, we examined the discrete feature gender.

+
+
+
+
+

+
+
+
+
+

The percentage of males in the “disease” class is slightly higher, but overall the difference is small. Besides that, the gender imbalance can be observed in both classes, as we mentioned before. To see the differences in metric features, we compare the following boxplots, where right-skewed features are not log-transformed yet.

+
+
+
+
+

+
+
+
+
+

Except for the total amount of protein, for each feature we obtain differences between the median values of the two classes. Notably, in the case of strongly right-skewed features the “disease” class contains far more extreme values than the “no disease” class, which is probably because of its larger size. This effect is weakened by log-transforming such features, as can be seen in the boxplots below. Moreover, the dispersion in the class “disease” is greater for these features, as the length of the boxes indicates. Overall, the features seem to be correlated to the target, so it makes sense to use them for this task and model their relationship with the target.

+
+
+
+
+

+
+
+
+
+

Note, that the same result can be achieved more easily by using PipeOpMutate from mlr3pipelines. This PipeOp provides a smooth implementation to scale numeric features for mlr3 tasks.

+
+
+

Correlation

+

As we mentioned in the description of the data, there are features that are indirectly measured by another one. This suggests that they are highly correlated. Some of the models we want to compare assume independent features or have problems with multicollinearity. Therefore, we checked for correlations between features.

+
+
+
Registered S3 method overwritten by 'GGally':
+  method from   
+  +.gg   ggplot2
+
+
+
Warning in cor(data, use = method[1], method = method[2]): the standard deviation is zero
+
+
+
+
+

+
+
+
+
+

For four of the pairs we obtained a very high correlation coefficient. Looking at these features, it is clear they affect each other. As the complexity of the model should be minimized and due to multicollinearity concerns, we decided to take only one of each pair. When deciding on which features to keep, we chose those that are more specific and relevant regarding liver disease. Therefore, we chose albumin over the ratio between albumin and globulin and also over the total amount of protein. The same argument applies to using the amount of direct bilirubin instead of the total amount of bilirubin. Regarding aspartate transaminase and alanine transaminase, it was not clear which one to use, especially since we have no given real world implementation for the task and no medical training. Since we did not notice any fundamental differences in the data for these two features, we arbitrarily chose aspartate transaminase.

+
+
+

Final Dataset

+
+
## Reducing, transforming and scaling dataset
+ilpd = ilpd %>%
+  select(-total_bilirubin, -alanine_transaminase, -total_protein,
+         -albumin_globulin_ratio) %>%
+  mutate(
+    # Recode gender
+    gender = as.numeric(ifelse(gender == "Female", 1, 0)),
+     # Remove labels for class
+    diseased = factor(ifelse(diseased == "yes", 1, 0)),
+     # Log for features with skewed distributions
+    alkaline_phosphatase = log(alkaline_phosphatase),
+    aspartate_transaminase = log(aspartate_transaminase),
+    direct_bilirubin = log(direct_bilirubin)
+  )
+
+po_scale = po("scale")
+po_scale$param_set$values$affect_columns =
+  selector_name(c("age", "direct_bilirubin", "alkaline_phosphatase",
+  "aspartate_transaminase", "albumin"))
+
+

Lastly, we standardized all metric features, as different ranges and units might weigh features. This is especially important for the k-NN model. The following table shows the final dataset and the transformations we applied. Note: Different from log or other transformation, scaling depends on the data themselves. Scaling data before data are split leads to data leakage, were information of train and test set are shared. As Data Leakage causes higher performance, scaling should always be applied in each data split induced by the ML workflow separately. Therefore we strongly recommend the usage of PipeOpScale in such cases.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VariableTransformation
agescaled
albuminscaled
alkaline_phosphatasescaled and log-transformed
aspartate_transaminasescaled and log-transformed
direct_bilirubinscaled and log-transformed
diseasednone
gendernone
+
+
+
+

Learners and tuning

+

First, we need to define a task which contains the final dataset and some meta information. Further we need to specify the positive class since the package takes the first one as the positive class by default. The specification of the positive class has an impact on the evaluation later on.

+
+
## Task definition
+task_liver = as_task_classif(ilpd, target = "diseased", positive = "1")
+
+

In the following we are going to evaluate logistic regression, linear discriminant analysis (LDA), quadratic discriminant analysis (QDA), naive Bayes, k-nearest neighbour (k-NN), classification trees (CART) and random forest on the binary target.

+
+
## Learner definition
+# Use predict type "prob" for the AUC score. Predict on train and test sets to
+# detect overfitting
+
+learners = list(
+  learner_logreg = lrn("classif.log_reg", predict_type = "prob",
+    predict_sets = c("train", "test")),
+  learner_lda = lrn("classif.lda", predict_type = "prob",
+    predict_sets = c("train", "test")),
+  learner_qda = lrn("classif.qda", predict_type = "prob",
+    predict_sets = c("train", "test")),
+  learner_nb = lrn("classif.naive_bayes", predict_type = "prob",
+    predict_sets = c("train", "test")),
+  learner_knn = lrn("classif.kknn", scale = FALSE,
+    predict_type = "prob"),
+  learner_rpart = lrn("classif.rpart",
+    predict_type = "prob"),
+  learner_rf = lrn("classif.ranger", num.trees = 1000,
+    predict_type = "prob")
+)
+
+

In order to find optimal hyperparameters through tuning, we used random search to better cover the hyperparameter space. We define the hyperparameters to tune. We only tuned hyperparameters for k-NN, CART and random forest since the other methods have strong assumptions and serve as baseline. The following table shows the assumptions of the methods we chose.

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LearnersAssumption
Logistic regressionNo (or little) multicollinearity among features
Linear discriminant analysisNormality of classes, equal covariance (target)
Quadratic discriminant analysisNormality of classes
Naive BayesConditional independence of features
CARTNone
k-NNNone
Random forestNone
+

The following table shows the hyperparameters we tuned.

+ + + + + + + + + + + + + + + + + + + + + +
LearnerHyperparameters
k-NNk, distance, kernel
CARTminsplit, cp
Random forestmin.node.size, mtry
+

For k-NN we chose 3 as the lower limit and 50 as the upper limit for k (number of neighbors). A too small k can lead to overfitting. We also tried different distance measures (e.g. 1 for Manhattan distance, 2 for Euclidean distance) and kernels. For CART we tuned the hyperparameters cp (complexity parameter) and minsplit (minimum number of observations in a node in order to attempt a split). cp controls the size of the tree: small values can result in overfitting while large values can cause underfitting. We also tuned parameters for the minimum size of terminal nodes and the number of variables randomly sampled as candidates at each split (from 1 to number of features) for random forest.

+
+
tune_ps_knn = ps(
+  k = p_int(lower = 3, upper = 50), # Number of neighbors considered
+  distance = p_dbl(lower = 1, upper = 3),
+  kernel = p_fct(levels = c("rectangular", "gaussian", "rank", "optimal"))
+)
+tune_ps_rpart = ps(
+  # Minimum number of observations that must exist in a node in order for a
+  # split to be attempted
+  minsplit = p_int(lower = 10, upper = 40),
+  cp = p_dbl(lower = 0.001, upper = 0.1) # Complexity parameter
+)
+tune_ps_rf = ps(
+  # Minimum size of terminal nodes
+  min.node.size = p_int(lower = 10, upper = 50),
+  # Number of variables randomly sampled as candidates at each split
+  mtry = p_int(lower = 1, upper = 6)
+)
+
+

The next step is to instantiate the AutoTuner from mlr3tuning. We employed 5-fold cross-validation for the inner loop of the nested resampling. The number of evaluations was set to 100 as the stopping criterion. As an evaluation metric we used AUC.

+
+
# AutoTuner for k-NN, CART and random forest
+learners$learner_knn = auto_tuner(
+  tuner = tnr("random_search"),
+  learner = learners$learner_knn,
+  resampling = rsmp("cv", folds = 5L),
+  measure = msr("classif.auc"),
+  search_space = tune_ps_knn,
+  term_evals = 100,
+)
+learners$learner_knn$predict_sets = c("train", "test")
+
+learners$learner_rpart = auto_tuner(
+  tuner = tnr("random_search"),
+  learner = learners$learner_rpart,
+  resampling = rsmp("cv", folds = 5L),
+  measure = msr("classif.auc"),
+  search_space = tune_ps_rpart,
+  term_evals = 100,
+)
+learners$learner_rpart$predict_sets = c("train", "test")
+
+learners$learner_rf = auto_tuner(
+  tuner = tnr("random_search"),
+  learner = learners$learner_rf,
+  resampling = rsmp("cv", folds = 5L),
+  measure = msr("classif.auc"),
+  search_space = tune_ps_rf,
+  term_evals = 100,
+)
+learners$learner_rf$predict_sets = c("train", "test")
+
+

During our research we found that oversampling can potentially increase the performance of the learners. As mentioned in section 2.2, we opted for perfectly balancing the classes. By using mlr3pipelines we can apply the benchmark function later on.

+
+
# Oversampling minority class to get perfectly balanced classes
+po_over = po("classbalancing", id = "oversample", adjust = "minor",
+  reference = "minor", shuffle = FALSE, ratio = 416/167)
+table(po_over$train(list(task_liver))$output$truth()) # Check class balance
+
+

+  1   0 
+416 416 
+
+
+
+
# Learners with balanced/oversampled data
+learners_bal = lapply(learners, function(x) {
+  GraphLearner$new(po_scale %>>% po_over %>>% x)
+})
+lapply(learners_bal, function(x) x$predict_sets = c("train", "test"))
+
+
+
+

Model fitting and benchmarking

+

With the learners defined, the inner method of the nested resampling chosen and the tuners set up, we proceeded to choose the outer resampling method. We opted for stratified 5-fold cross-validation to maintain the distribution of the target variable, independent of oversampling. However, it turned out that normal cross-validation without stratification yields very similar results.

+
+
# 5-fold cross-validation
+resampling_outer = rsmp(id = "cv", .key = "cv", folds = 5L)
+
+# Stratification
+task_liver$col_roles$stratum = task_liver$target_names
+
+

To rank the different learners and finally decide which one fits best for the task at hand, we used benchmarking. The following code chunk executes our benchmarking with all learners.

+
+
design = benchmark_grid(
+  tasks = task_liver,
+  learners = c(learners, learners_bal),
+  resamplings = resampling_outer
+)
+
+bmr = benchmark(design, store_models = FALSE)
+
+

As mentioned above, stratified 5-fold cross-validation was chosen. This means that performance is determined as the average across five model evaluations with a train-test-split of 80% to 20%. Furthermore, the choice of performance metrics is crucial in ranking different learners. While each one of them has its specific use case, we opted for AUC, a performance metric taking into account both sensitivity and specificity, which we also used for hyperparameter tuning.

+

We first present a comparison of all learners by AUC, with and without oversampling, and for both training and test data.

+
+
+
                               learner_id auc_train  auc_test
+ 1:                       classif.log_reg 0.7555646 0.7416606
+ 2:                           classif.lda 0.7555611 0.7390708
+ 3:                           classif.qda 0.7697367 0.7347738
+ 4:                   classif.naive_bayes 0.7539943 0.7457096
+ 5:                    classif.kknn.tuned 0.8876589 0.7323200
+ 6:                   classif.rpart.tuned 0.8045344 0.6627003
+ 7:                  classif.ranger.tuned 0.9535820 0.7421109
+ 8:      scale.oversample.classif.log_reg 0.7556586 0.7434089
+ 9:          scale.oversample.classif.lda 0.7547323 0.7434744
+10:          scale.oversample.classif.qda 0.7678794 0.7340827
+11:  scale.oversample.classif.naive_bayes 0.7537216 0.7441955
+12:   scale.oversample.classif.kknn.tuned 1.0000000 0.7026322
+13:  scale.oversample.classif.rpart.tuned 0.8611873 0.6250559
+14: scale.oversample.classif.ranger.tuned 1.0000000 0.7433473
+
+
+

As can be seen in the results above, regardless of whether oversampling was applied or not, logistic regression, LDA, QDA, and naive Bayes have very similar performance on training and test data. On the other hand, k-NN, CART and random forest predict much better on the training data, indicating overfitting.

+

Furthermore, oversampling leaves AUC performance almost untouched for all learners.

+

The boxplots below graphically summarize AUC performance of all learners, with the blue dots indicating mean AUC performance.

+
+
+
Warning: The `fun.y` argument of `stat_summary()` is deprecated as of ggplot2 3.3.0.
+ℹ Please use the `fun` argument instead.
+
+
+
+
+

+
+
+
+
+

Random forest is the learner with the best AUC performance, both with and without oversampling. Whereas mean AUC is roughly between 0.65 and 0.75 for all learners, the individual components of AUC might differ substantially.

+

As a first step towards “AUC decomposition”, we consider the ROC curve, which provides valuable graphical insights into performance - even more so since AUC is directly derived from it.

+

Subsequently, sensitivity, specificity, false negative rate (FNR), and false positive rate (FPR) for each learner are shown explicitly in the output below, next to AUC.

+
+
+
                               learner_id classif.auc classif.sensitivity classif.specificity classif.fnr classif.fpr
+ 1:                       classif.log_reg   0.7416606           0.8920252           0.2452763  0.10797476   0.7547237
+ 2:                           classif.lda   0.7390708           0.9135972           0.1673797  0.08640275   0.8326203
+ 3:                           classif.qda   0.7347738           0.6875215           0.6709447  0.31247849   0.3290553
+ 4:                   classif.naive_bayes   0.7457096           0.6393574           0.7606061  0.36064257   0.2393939
+ 5:                    classif.kknn.tuned   0.7323200           0.8339931           0.3896613  0.16600688   0.6103387
+ 6:                   classif.rpart.tuned   0.6627003           0.8436317           0.1982175  0.15636833   0.8017825
+ 7:                  classif.ranger.tuned   0.7421109           0.9422834           0.1315508  0.05771658   0.8684492
+ 8:      scale.oversample.classif.log_reg   0.7434089           0.6202524           0.7609626  0.37974756   0.2390374
+ 9:          scale.oversample.classif.lda   0.7434744           0.5865175           0.7848485  0.41348250   0.2151515
+10:          scale.oversample.classif.qda   0.7340827           0.5552209           0.8267380  0.44477912   0.1732620
+11:  scale.oversample.classif.naive_bayes   0.7441955           0.5407917           0.8386809  0.45920826   0.1613191
+12:   scale.oversample.classif.kknn.tuned   0.7026322           0.7281985           0.5254902  0.27180149   0.4745098
+13:  scale.oversample.classif.rpart.tuned   0.6250559           0.6032702           0.6060606  0.39672978   0.3939394
+14: scale.oversample.classif.ranger.tuned   0.7433473           0.7548480           0.5327986  0.24515204   0.4672014
+
+
+

As it turned out, without oversampling logistic regression, LDA, k-NN, CART, and random forest score very high on sensitivity and rather low on specificity; QDA and naive Bayes, on the other hand, score relatively high on specificity, but not as high on sensitivity. By definition, high sensitivity (specificity) results from a low false negative (positive) rate, which is also represented in the data.

+

With oversampling, specificity increases at the cost of sensitivity for all learners (even for those which already had high specificity), as can be seen in the two graphs below.

+

For a given learner, say random forest, the different performance metrics and their dependence upon target variable balance are shown in the following graph.

+

To get a look at performance from yet another angle, we next considered the confusion matrix for each learner, which simply contrasts the absolute numbers of predictions and true values by category, with and without oversampling. You can have a look at all the confusion matrices, if you run the script.

+

The confusion matrices confirm the above conclusions: without oversampling, all learners (except QDA and naive Bayes) display very high numbers of true positives, but also of false positives, implying high sensitivity and low specificity. Also note that a trivial model classifying all individuals as “1” would cause fewer misclassifications than all of our models except random forest, casting doubt on the predictive power of the features in our dataset. Regarding learner performance with oversampling, the confusion matrices add another valuable insight:

+
    +
  • the total number of misclassifications increases for all learners
  • +
  • the correct predictions become more balanced (by partly shifting from true positives to true negatives)
  • +
  • the misclassifications partly shift from false positives to false negatives
  • +
+

The final decision regarding which learner works best - and also whether oversampling should be used or not - strongly depends on the real world implications of sensitivity and specificity. One of the two might outweigh the other many times over in terms of practical importance. Think of the typical HIV rapid diagnostic test example, where high sensitivity at the cost of low specificity might cause an (unwarranted) shock but is otherwise not dangerous, whereas low sensitivity would be highly perilous. As is usually the case, no black and white “best model” exists here - recall that, even with oversampling, none of our models perform well on both sensitivity and specificity. In our case, we would need to ask ourselves: what would be the consequences of high specificity at the cost of low sensitivity, which implies telling many patients with a liver disease that they are healthy; versus what would be the consequences of high sensitivity at the cost of low specificity, which would mean telling many healthy patients they have a liver disease. In absence of further topic-specific information, we can only state the best-performing learners for the particular performance metric chosen. As mentioned above, random forest performs best based on AUC. Random forest is furthermore the learner with the highest sensitivity score (and the lowest FNR), while naive Bayes is the one with the best specificity (and the lowest FPR) These results - and the ranking of learners in general, independent of the performance metric - are not affected by oversampling.

+

The analysis we conducted is, however, by no means exhaustive. On the feature level, while we focused almost exclusively on the machine learning and statistical analysis aspect during our analysis, one could also dig deeper into the actual topic (liver disease) and try to understand the variables as well as potential correlations and interactions more thoroughly. This might also mean to consider already thrown out variables again. Furthermore, feature engineering as well as data preprocessing, for instance using principal component analysis, could be applied to the dataset. Regarding hyperparameter tuning, different hyperparameters with larger hyperparameter spaces and numbers of evaluations could be considered. Furthermore, tuning could also be applied to some of those learners that we labeled as baseline learners, though to a lesser extent. Finally, we limited ourselves to those classifiers discussed in detail in the course. More classifiers exist, however; in particular, gradient boosting and support vector machines could additionally be applied to this task and potentially yield better results.

+ + + +
+ +

References

+
+Carvalho, Joana R., and Mariana Verdelho Machado. 2018. New Insights About Albumin and Liver Disease.” Annals of Hepatology 17 (4): 547–60. https://doi.org/10.5604/01.3001.0012.0916. +
+
+Gowda, Shivaraj, Prakash B Desai, Vinayak V Hull, Avinash A K Math, Sonal N Vernekar, and Shruthi S Kulkarni. 2009. A review on laboratory liver function tests.” The Pan African Medical Journal 3: 17. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC2984286/. +
+
+Oh, Robert C, and Thomas R Hustead. 2011. Causes and evaluation of mildly elevated liver transaminase levels.” American Family Physician 84: 1003–8. https://www.aafp.org/afp/2011/1101/p1003.html. +
+
+Total Protein, Albumin-Globulin (A/G) Ratio.” n.d. https://labtestsonline.org/tests/total-protein-albumin-globulin-ag-ratio. +
+
+UCI Machine Learning Repository.” n.d. University of California, Irvine, School of Information; Computer Sciences. http://archive.ics.uci.edu/ml. +
+
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-004-1.png b/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-004-1.png new file mode 100644 index 00000000..7cc18463 Binary files /dev/null and b/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-004-1.png differ diff --git a/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-005-1.png b/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-005-1.png new file mode 100644 index 00000000..963e2eed Binary files /dev/null and b/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-005-1.png differ diff --git a/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-006-1.png b/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-006-1.png new file mode 100644 index 00000000..3e342414 Binary files /dev/null and b/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-006-1.png differ diff --git a/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-007-1.png b/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-007-1.png new file mode 100644 index 00000000..234e0731 Binary files /dev/null and b/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-007-1.png differ diff --git a/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-008-1.png b/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-008-1.png new file mode 100644 index 00000000..8b0fc8b1 Binary files /dev/null and b/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-008-1.png differ diff --git a/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-009-1.png b/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-009-1.png new file mode 100644 index 00000000..02a2f3cd Binary files /dev/null and b/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-009-1.png differ diff --git a/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-010-1.png b/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-010-1.png new file mode 100644 index 00000000..c347b8f6 Binary files /dev/null and b/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-010-1.png differ diff --git a/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-011-1.png b/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-011-1.png new file mode 100644 index 00000000..02a2f3cd Binary files /dev/null and b/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-011-1.png differ diff --git a/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-020-1.png b/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-020-1.png new file mode 100644 index 00000000..8a7afe1e Binary files /dev/null and b/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-020-1.png differ diff --git a/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-024-1.png b/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-024-1.png new file mode 100644 index 00000000..fda1b76e Binary files /dev/null and b/gallery/pipelines/2020-09-11-liver-patient-classification/index_files/figure-html/2020-09-11-liver-patient-classification-024-1.png differ diff --git a/gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html b/gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html new file mode 100644 index 00000000..f6bba463 --- /dev/null +++ b/gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html @@ -0,0 +1,1169 @@ + + + + + + + + + + + + +Tuning a Complex Graph – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Tuning a Complex Graph

+
+
+

Tune a preprocessing pipeline and multiple tuners at once.

+
+
+ +
+ + +
+ +
+
Author
+
+

Lennart Schneider

+
+
+ +
+
Published
+
+

February 3, 2021

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+
# include: false
+requireNamespace("bst")
+
+
Loading required namespace: bst
+
+
requireNamespace("fastICA")
+
+
Loading required namespace: fastICA
+
+
+

In this use case we show how to tune a rather complex graph consisting of different preprocessing steps and different learners where each preprocessing step and learner itself has parameters that can be tuned. You will learn the following:

+ +

Ideally you already had a look at how to tune over multiple learners.

+

First, we load the packages we will need:

+
+
library(mlr3verse)
+library(mlr3learners)
+
+

We initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented. The lgr package is used for logging in all mlr3 packages. The mlr3 logger prints the logging messages from the base package, whereas the bbotk logger is responsible for logging messages from the optimization packages (e.g. mlr3tuning ).

+
+
set.seed(7832)
+lgr::get_logger("mlr3")$set_threshold("warn")
+lgr::get_logger("bbotk")$set_threshold("warn")
+
+
+

Data and Task

+

We are going to work with some gene expression data included as a supplement in the bst package. The data consists of 2308 gene profiles in 63 training and 20 test samples. The following data preprocessing steps are done analogously as in vignette("khan", package = "bst"):

+
+
datafile = system.file("extdata", "supplemental_data", package = "bst")
+dat0 = read.delim(datafile, header = TRUE, skip = 1)[, -(1:2)]
+dat0 = t(dat0)
+dat = data.frame(dat0[!(rownames(dat0) %in%
+  c("TEST.9", "TEST.13", "TEST.5", "TEST.3", "TEST.11")), ])
+dat$class = as.factor(
+  c(substr(rownames(dat)[1:63], start = 1, stop = 2),
+    c("NB", "RM", "NB", "EW", "RM", "BL", "EW", "RM", "EW", "EW", "EW", "RM",
+      "BL", "RM", "NB", "NB", "NB", "NB", "BL", "EW")
+  )
+)
+
+

We then construct our training and test Task :

+
+
task = as_task_classif(dat, target = "class", id = "SRBCT")
+task_train = task$clone(deep = TRUE)
+task_train$filter(1:63)
+task_test = task$clone(deep = TRUE)
+task_test$filter(64:83)
+
+
+
+

Workflow

+

Our graph will start with log transforming the features, followed by scaling them. Then, either a PCA or ICA is applied to extract principal / independent components followed by fitting a LDA or a ranger random forest is fitted without any preprocessing (the log transformation and scaling should most likely affect the LDA more than the ranger random forest). Regarding the PCA and ICA, both the number of principal / independent components are tuning parameters. Regarding the LDA, we can further choose different methods for estimating the mean and variance and regarding the ranger, we want to tune the mtry and num.tree parameters. Note that the PCA-LDA combination has already been successfully applied in different cancer diagnostic contexts when the feature space is of high dimensionality (Morais and Lima 2018).

+

To allow for switching between the PCA / ICA-LDA and ranger we can either use branching or proxy pipelines, i.e., PipeOpBranch and PipeOpUnbranch or PipeOpProxy. We will first cover branching in detail and later show how the same can be done using PipeOpProxy.

+
+
+

Baseline

+

First, we have a look at the baseline classification accuracy of the LDA and ranger on the training task:

+
+
base = benchmark(benchmark_grid(
+  task_train,
+  learners = list(lrn("classif.lda"), lrn("classif.ranger")),
+  resamplings = rsmp("cv", folds = 3)))
+
+
Warning in lda.default(x, grouping, ...): variables are collinear
+
+Warning in lda.default(x, grouping, ...): variables are collinear
+
+Warning in lda.default(x, grouping, ...): variables are collinear
+
+
base$aggregate(measures = msr("classif.acc"))
+
+
   nr task_id     learner_id resampling_id iters classif.acc
+1:  1   SRBCT    classif.lda            cv     3   0.6666667
+2:  2   SRBCT classif.ranger            cv     3   0.9206349
+Hidden columns: resample_result
+
+
+

The out-of-the-box ranger appears to already have good performance on the training task. Regarding the LDA, we do get a warning message that some features are colinear. This strongly suggests to reduce the dimensionality of the feature space. Let’s see if we can get some better performance, at least for the LDA.

+
+
+

Branching

+

Our graph starts with log transforming the features (we explicitly use base 10 only for better interpretability when inspecting the model later), using PipeOpColApply, followed by scaling the features using PipeOpScale. Then, the first branch allows for switching between the PCA / ICA-LDA and ranger, and within PCA / ICA-LDA, the second branch allows for switching between PCA and ICA:

+
+
graph1 =
+  po("colapply", applicator = function(x) log(x, base = 10)) %>>%
+  po("scale") %>>%
+  # pca / ica followed by lda vs. ranger
+  po("branch", id = "branch_learner", options = c("pca_ica_lda", "ranger")) %>>%
+  gunion(list(
+    po("branch", id = "branch_preproc_lda", options = c("pca", "ica")) %>>%
+      gunion(list(
+        po("pca"), po("ica")
+      )) %>>%
+      po("unbranch", id = "unbranch_preproc_lda") %>>%
+      lrn("classif.lda"),
+    lrn("classif.ranger")
+  )) %>>%
+  po("unbranch", id = "unbranch_learner")
+
+

Note that the names of the options within each branch are arbitrary, but ideally they describe what is happening. Therefore we go with "pca_ica_lda" / "ranger” and "pca" / "ica". Finally, we also could have used the branch ppl to make branching easier (we will come back to this in the Proxy section). The graph looks like the following:

+
+
graph1$plot(html = FALSE)
+
+
+
+

+
+
+
+
+

We can inspect the parameters of the ParamSet of the graph to see which parameters can be set:

+
+
graph1$param_set$ids()
+
+
 [1] "colapply.applicator"                         "colapply.affect_columns"                    
+ [3] "scale.center"                                "scale.scale"                                
+ [5] "scale.robust"                                "scale.affect_columns"                       
+ [7] "branch_learner.selection"                    "branch_preproc_lda.selection"               
+ [9] "pca.center"                                  "pca.scale."                                 
+[11] "pca.rank."                                   "pca.affect_columns"                         
+[13] "ica.n.comp"                                  "ica.alg.typ"                                
+[15] "ica.fun"                                     "ica.alpha"                                  
+[17] "ica.method"                                  "ica.row.norm"                               
+[19] "ica.maxit"                                   "ica.tol"                                    
+[21] "ica.verbose"                                 "ica.w.init"                                 
+[23] "ica.affect_columns"                          "classif.lda.dimen"                          
+[25] "classif.lda.method"                          "classif.lda.nu"                             
+[27] "classif.lda.predict.method"                  "classif.lda.predict.prior"                  
+[29] "classif.lda.prior"                           "classif.lda.tol"                            
+[31] "classif.ranger.alpha"                        "classif.ranger.always.split.variables"      
+[33] "classif.ranger.class.weights"                "classif.ranger.holdout"                     
+[35] "classif.ranger.importance"                   "classif.ranger.keep.inbag"                  
+[37] "classif.ranger.max.depth"                    "classif.ranger.min.node.size"               
+[39] "classif.ranger.min.prop"                     "classif.ranger.minprop"                     
+[41] "classif.ranger.mtry"                         "classif.ranger.mtry.ratio"                  
+[43] "classif.ranger.num.random.splits"            "classif.ranger.num.threads"                 
+[45] "classif.ranger.num.trees"                    "classif.ranger.oob.error"                   
+[47] "classif.ranger.regularization.factor"        "classif.ranger.regularization.usedepth"     
+[49] "classif.ranger.replace"                      "classif.ranger.respect.unordered.factors"   
+[51] "classif.ranger.sample.fraction"              "classif.ranger.save.memory"                 
+[53] "classif.ranger.scale.permutation.importance" "classif.ranger.se.method"                   
+[55] "classif.ranger.seed"                         "classif.ranger.split.select.weights"        
+[57] "classif.ranger.splitrule"                    "classif.ranger.verbose"                     
+[59] "classif.ranger.write.forest"                
+
+
+

The id’s are prefixed by the respective PipeOp they belong to, e.g., pca.rank. refers to the rank. parameter of PipeOpPCA.

+
+
+

Search Space

+

Our graph either fits a LDA after applying PCA or ICA, or alternatively a ranger with no preprocessing. These two options each define selection parameters that we can tune. Moreover, within the respective PipeOp’s we want to tune the following parameters: pca.rank., ica.n.comp, classif.lda.method, classif.ranger.mtry, and classif.ranger.num.trees. The first two parameters are integers that in-principal could range from 1 to the number of features. However, for ICA, the upper bound must not exceed the number of observations and as we will later use 3-fold cross-validation as the resampling method for the tuning, we just set the upper bound to 30 (and do the same for PCA). Regarding the classif.lda.method we will only be interested in "moment" estimation vs. minimum volume ellipsoid covariance estimation ("mve"). Moreover, we set the lower bound of classif.ranger.mtry to 200 (which is around the number of features divided by 10) and the upper bound to 1000.

+
+
tune_ps1 = ps(
+  branch_learner.selection =
+    p_fct(c("pca_ica_lda", "ranger")),
+  branch_preproc_lda.selection =
+    p_fct(c("pca", "ica"), depends = branch_learner.selection == "pca_ica_lda"),
+  pca.rank. =
+    p_int(1, 30, depends = branch_preproc_lda.selection == "pca"),
+  ica.n.comp =
+    p_int(1, 30, depends = branch_preproc_lda.selection == "ica"),
+  classif.lda.method =
+    p_fct(c("moment", "mve"), depends = branch_preproc_lda.selection == "ica"),
+  classif.ranger.mtry =
+    p_int(200, 1000, depends = branch_learner.selection == "ranger"),
+  classif.ranger.num.trees =
+    p_int(500, 2000, depends = branch_learner.selection == "ranger"))
+
+

The parameter branch_learner.selection defines whether we go down the left (PCA / ICA followed by LDA) or the right branch (ranger). The parameter branch_preproc_lda.selection defines whether a PCA or ICA will be applied prior to the LDA. The other parameters directly belong to the ParamSet of the PCA / ICA / LDA / ranger. Note that it only makes sense to switch between PCA / ICA if the "pca_ica_lda" branch was selected beforehand. We have to specify this via the depends parameter.

+

Finally, we also could have proceeded to tune the numeric parameters on a log scale. I.e., looking at pca.rank. the performance difference between rank 1 and 2 is probably much larger than between rank 29 and rank 30. The mlr3tuning Tutorial covers such transformations.

+
+
+

Tuning

+

We can now tune the parameters of our graph as defined in the search space with respect to a measure. We will use the classification accuracy. As a resampling method we use 3-fold cross-validation. We will use the TerminatorNone (i.e., no early termination) for terminating the tuning because we will apply a grid search (we use a grid search because it gives nicely plottable and understandable results but if there were much more parameters, random search or more intelligent optimization methods would be preferred to a grid search:

+
+
tune1 = TuningInstanceSingleCrit$new(
+  task_train,
+  learner = graph1,
+  resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.acc"),
+  search_space = tune_ps1,
+  terminator = trm("none")
+)
+
+

We then perform a grid search using a resolution of 4 for the numeric parameters. The grid being used will look like the following (note that the dependencies we specified above are handled automatically):

+
+
generate_design_grid(tune_ps1, resolution = 4)
+
+
+
+
+ +
+
+

We trigger the tuning.

+
+
tuner_gs = tnr("grid_search", resolution = 4, batch_size = 10)
+tuner_gs$optimize(tune1)
+
+
   branch_learner.selection branch_preproc_lda.selection pca.rank. ica.n.comp classif.lda.method classif.ranger.mtry
+1:              pca_ica_lda                          ica        NA         10                mve                  NA
+   classif.ranger.num.trees learner_param_vals  x_domain classif.acc
+1:                       NA          <list[8]> <list[4]>    0.984127
+
+
+

Now, we can inspect the results ordered by the classification accuracy:

+
+
as.data.table(tune1$archive)[order(classif.acc), ]
+
+
+
+
+ +
+
+

We achieve very good accuracy using ranger, more or less regardless how mtry and num.trees are set. However, the LDA also shows very good accuracy when combined with PCA or ICA retaining 30 components.

+

For now, we decide to use ranger with mtry set to 200 and num.trees set to 1000.

+

Setting these parameters manually in our graph, then training on the training task and predicting on the test task yields an accuracy of:

+
+
graph1$param_set$values$branch_learner.selection = "ranger"
+graph1$param_set$values$classif.ranger.mtry = 200
+graph1$param_set$values$classif.ranger.num.trees = 1000
+graph1$train(task_train)
+
+
$unbranch_learner.output
+NULL
+
+
graph1$predict(task_test)[[1L]]$score(msr("classif.acc"))
+
+
classif.acc 
+          1 
+
+
+

Note that we also could have wrapped our graph in a GraphLearner and proceeded to use this as a learner in an AutoTuner.

+
+
+

Proxy

+

Instead of using branches to split our graph with respect to the learner and preprocessing options, we can also use PipeOpProxy. PipeOpProxy accepts a single content parameter that can contain any other PipeOp or Graph. This is extremely flexible in the sense that we do not have to specify our options during construction. However, the parameters of the contained PipeOp or Graph are no longer directly contained in the ParamSet of the resulting graph. Therefore, when tuning the graph, we do have to make use of a trafo function.

+
+
graph2 =
+  po("colapply", applicator = function(x) log(x, base = 10)) %>>%
+  po("scale") %>>%
+  po("proxy")
+
+

This graph now looks like the following:

+
+
graph2$plot(html = FALSE)
+
+
+
+

+
+
+
+
+

At first, this may look like a linear graph. However, as the content parameter of PipeOpProxy can be tuned and set to contain any other PipeOp or Graph, this will allow for a similar non-linear graph as when doing branching.

+
+
graph2$param_set$ids()
+
+
[1] "colapply.applicator"     "colapply.affect_columns" "scale.center"            "scale.scale"            
+[5] "scale.robust"            "scale.affect_columns"    "proxy.content"          
+
+
+

We can tune the graph by using the same search space as before. However, here the trafo function is of central importance to actually set our options and parameters:

+
+
tune_ps2 = tune_ps1$clone(deep = TRUE)
+
+

The trafo function does all the work, i.e., selecting either the PCA / ICA-LDA or ranger as the proxy.content as well as setting the parameters of the respective preprocessing PipeOps and Learners.

+
+
proxy_options = list(
+  pca_ica_lda =
+    ppl("branch", graphs = list(pca = po("pca"), ica = po("ica"))) %>>%
+      lrn("classif.lda"),
+  ranger = lrn("classif.ranger")
+)
+
+

Above, we made use of the branch ppl allowing us to easily construct a branching graph. Of course we also could have use another nested PipeOpProxy to specify the preprocessing options ("pca" vs. "ica") within proxy_options if for some reason we do not want to do branching at all. The trafo function below selects one of the proxy_options from above and sets the respective parameters for the PCA, ICA, LDA and ranger. Here, the argument x is a list which will contain sampled / selected parameters from our ParamSet (in our case, tune_ps2). The return value is a list only including the appropriate proxy.content parameter. In each tuning iteration, the proxy.content parameter of our graph will be set to this value.

+
+
tune_ps2$trafo = function(x, param_set) {
+  proxy.content = proxy_options[[x$branch_learner.selection]]
+  if (x$branch_learner.selection == "pca_ica_lda") {
+    # pca_ica_lda
+    proxy.content$param_set$values$branch.selection = x$branch_preproc_lda.selection
+    if (x$branch_preproc_lda.selection == "pca") {
+      proxy.content$param_set$values$pca.rank. = x$pca.rank.
+    } else {
+      proxy.content$param_set$values$ica.n.comp = x$ica.n.comp
+    }
+    proxy.content$param_set$values$classif.lda.method = x$classif.lda.method
+  } else {
+    # ranger
+    proxy.content$param_set$values$mtry = x$classif.ranger.mtry
+    proxy.content$param_set$values$num.trees = x$classif.ranger.num.trees
+  }
+  list(proxy.content = proxy.content)
+}
+
+

I.e., suppose that the following parameters will be selected from our ParamSet:

+
+
x = list(
+  branch_learner.selection = "ranger",
+  classif.ranger.mtry = 200,
+  classif.ranger.num.trees = 500)
+
+

The trafo function will then return:

+
+
tune_ps2$trafo(x)
+
+
$proxy.content
+<LearnerClassifRanger:classif.ranger>
+* Model: -
+* Parameters: num.threads=1, mtry=200, num.trees=500
+* Packages: mlr3, mlr3learners, ranger
+* Predict Types:  [response], prob
+* Feature Types: logical, integer, numeric, character, factor, ordered
+* Properties: hotstart_backward, importance, multiclass, oob_error, twoclass, weights
+
+
+

Tuning can be carried out analogously as done above:

+
+
tune2 = TuningInstanceSingleCrit$new(
+  task_train,
+  learner = graph2,
+  resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.acc"),
+  search_space = tune_ps2,
+  terminator = trm("none")
+)
+tuner_gs$optimize(tune2)
+
+
+
as.data.table(tune2$archive)[order(classif.acc), ]
+
+ + + +
+ +

References

+
+Morais, Camilo LM, and Kássio MG Lima. 2018. “Principal Component Analysis with Linear and Quadratic Discriminant Analysis for Identification of Cancer Samples Based on Mass Spectrometry.” Journal of the Brazilian Chemical Society 29 (3): 472–81. https://doi.org/10.21577/0103-5053.20170159. +
+
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph_files/figure-html/tuning-a-complex-graph-009-1.png b/gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph_files/figure-html/tuning-a-complex-graph-009-1.png new file mode 100644 index 00000000..fd484acc Binary files /dev/null and b/gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph_files/figure-html/tuning-a-complex-graph-009-1.png differ diff --git a/gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph_files/figure-html/tuning-a-complex-graph-022, graph2-1.png b/gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph_files/figure-html/tuning-a-complex-graph-022, graph2-1.png new file mode 100644 index 00000000..ac2f1034 Binary files /dev/null and b/gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph_files/figure-html/tuning-a-complex-graph-022, graph2-1.png differ diff --git a/gallery/series/2020-03-11-basics-german-credit/index.html b/gallery/series/2020-03-11-basics-german-credit/index.html new file mode 100644 index 00000000..faef4e9e --- /dev/null +++ b/gallery/series/2020-03-11-basics-german-credit/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/series/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html b/gallery/series/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html new file mode 100644 index 00000000..0c2ec110 --- /dev/null +++ b/gallery/series/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/series/2020-03-11-mlr3tuning-tutorial-german-credit/index.html b/gallery/series/2020-03-11-mlr3tuning-tutorial-german-credit/index.html new file mode 100644 index 00000000..140de32e --- /dev/null +++ b/gallery/series/2020-03-11-mlr3tuning-tutorial-german-credit/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/series/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/index.html b/gallery/series/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/index.html new file mode 100644 index 00000000..6e1fc392 --- /dev/null +++ b/gallery/series/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/series/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/index.html b/gallery/series/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/index.html new file mode 100644 index 00000000..644445d7 --- /dev/null +++ b/gallery/series/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/series/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index.html b/gallery/series/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index.html new file mode 100644 index 00000000..ad10138a --- /dev/null +++ b/gallery/series/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/series/2021-03-12-practical-tuning-series-tuning-and-parallel-processing/index.html b/gallery/series/2021-03-12-practical-tuning-series-tuning-and-parallel-processing/index.html new file mode 100644 index 00000000..53c5af00 --- /dev/null +++ b/gallery/series/2021-03-12-practical-tuning-series-tuning-and-parallel-processing/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/series/2022-12-01-hyperband-xgboost/index.html b/gallery/series/2022-12-01-hyperband-xgboost/index.html new file mode 100644 index 00000000..78b50d86 --- /dev/null +++ b/gallery/series/2022-12-01-hyperband-xgboost/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/series/2022-12-02-hyperband-subsampling/index.html b/gallery/series/2022-12-02-hyperband-subsampling/index.html new file mode 100644 index 00000000..731e856d --- /dev/null +++ b/gallery/series/2022-12-02-hyperband-subsampling/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/series/2023-01-15-hyperband-xgboost/index.html b/gallery/series/2023-01-15-hyperband-xgboost/index.html new file mode 100644 index 00000000..78b50d86 --- /dev/null +++ b/gallery/series/2023-01-15-hyperband-xgboost/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/series/2023-01-16-hyperband-subsampling/index.html b/gallery/series/2023-01-16-hyperband-subsampling/index.html new file mode 100644 index 00000000..731e856d --- /dev/null +++ b/gallery/series/2023-01-16-hyperband-subsampling/index.html @@ -0,0 +1,14 @@ + + + Redirect + + + + + diff --git a/gallery/technical/2020-08-13-a-production-example-using-plumber-and-docker/index.html b/gallery/technical/2020-08-13-a-production-example-using-plumber-and-docker/index.html new file mode 100644 index 00000000..488a1f8f --- /dev/null +++ b/gallery/technical/2020-08-13-a-production-example-using-plumber-and-docker/index.html @@ -0,0 +1,1046 @@ + + + + + + + + + + + + +A Production Example Using Plumber and Docker – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

A Production Example Using Plumber and Docker

+
+
+

Write a REST API using plumber and deploy it using Docker.

+
+
+
+
+ + +
+ +
+
Author
+
+

Lennart Schneider

+
+
+ +
+
Published
+
+

August 13, 2020

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +

Production with R has come a long way. In this tutorial, we give a brief example on how to write a REST API and deploy it (relying on the mlr3 ecosystem for the actual training and predicting). Most of this tutorial was inspired by other excellent posts and vignettes:

+ +

All files presented in this tutorial are available here.

+
+

Modeling Background

+
+
library(data.table)
+library(mlr3)
+library(mlr3pipelines)
+
+

We will use a subset of the boston_housing Task. Our goal is to predict the median value of owner-occupied homes in USD 1000’s (target medv), using the features crim, tax and town (just to have factor, integer, and numeric feature types):

+
+
data = tsk("boston_housing")$data()
+data = data[, c("medv", "crim", "tax", "town")]
+
+
+
task = TaskRegr$new("boston", backend = data, target = "medv")
+
+

Let’s create a toy pipeline:

+

Regarding modeling, we will keep it very simple and use the rpart learner. Missing numerical features (which could happen during prediction) will be imputed by their median via PipeOpImputeMedian, while missing factorial features will be imputed using a new level via PipeOpImputeOOR. As PipeOpImputeOOR will introduce a new level, ".MISSING" to impute missing values, we also use PipeOpFixFactors:

+
+
g = po("imputemedian") %>>%
+  po("imputeoor") %>>%
+  po("fixfactors") %>>%
+  lrn("regr.rpart")
+
+

We wrap this Graph in a GraphLearner and can train on the Task:

+
+
gl = GraphLearner$new(g)
+gl$train(task)
+
+

We can inspect the trained pipeline looking at:

+
+
gl$model
+
+

Furthermore, we can save the trained pipeline, i.e., as "gl.rds":

+
+
saveRDS(gl, "gl.rds")
+
+

We will also store some information regarding the features, i.e., the feature names, types and levels (you will later see, why we need to do this):

+
+
feature_info = list(
+  feature_names = task$feature_names,
+  feature_types = task$feature_types,
+  levels = task$levels()
+)
+saveRDS(feature_info, "feature_info.rds")
+
+

Putting everything in a file, train_gl.R looks like the following, which we can then source before moving on:

+
+
# train_gl.R
+
+library(mlr3)
+library(mlr3pipelines)
+
+data = tsk("boston_housing")$data()
+data = data[, c("medv", "crim", "tax", "town")]
+task = TaskRegr$new("boston", backend = data, target = "medv")
+
+g = po("imputemedian") %>>%
+  po("imputeoor") %>>%
+  po("fixfactors") %>>%
+  lrn("regr.rpart")
+
+gl = GraphLearner$new(g)
+
+gl$train(task)
+
+saveRDS(gl, "gl.rds")
+
+feature_info = list(
+  feature_names = task$feature_names,
+  feature_types = task$feature_types,
+  levels = task$levels()
+)
+
+saveRDS(feature_info, "feature_info.rds")
+
+

Our goal of our REST (representational state transfer) API (application programming interface) will be to predict the medv of a new observation, i.e., it should do something like the following:

+
+
newdata = data.table(crim = 3.14, tax = 691, town = "Newton")
+gl$predict_newdata(newdata)
+
+
<PredictionRegr> for 1 observations:
+ row_ids truth response
+       1    NA 32.23288
+
+
+

However, in our REST API, the newdata will be received at an endpoint that accepts a particular input. In the next section we will use plumber to set up our web service.

+
+
+

Using plumber to set up our REST API

+

The package plumber allows us to create a REST API by simply commenting existing R code. plumber makes use of these comments to define the web service. Running plumber::plumb on the commented R file then results in a runnable web service that other systems can interact with over a network.

+

As an endpoint for predicting the medv, we will use a POST request. This will allow us to enclose data in the body of the request message. More precisely, we assume that the data will be provided in the JSON format.

+

When a POST request containing the data (in JSON format) is received our code must then:

+
    +
  1. convert the input (in JSON format) to a data.table with all feature columns matching their feature type

  2. +
  3. predict the medv based on the input using our trained pipeline and provide an output that can be understood by the client

  4. +
+

To make sure that all features match their feature type, we will later use the following function stored in the R file fix_feature_types.R:

+
+
# fix_feature_types.R
+
+fix_feature_types = function(feature, feature_name, feature_info) {
+  id = match(feature_name, feature_info$feature_names)
+  feature_type = feature_info$feature_types$type[id]
+  switch(feature_type,
+    "logical"   = as.logical(feature),
+    "integer"   = as.integer(feature),
+    "numeric"   = as.numeric(feature),
+    "character" = as.character(feature),
+    "factor"    = factor(feature, levels = feature_info$levels[[feature_name]],
+      ordered = FALSE),
+    "ordered"   = factor(feature, levels = feature_info$levels[[feature_name]],
+      ordered = TRUE),
+    "POSIXct"   = as.POSIXct(feature)
+  )
+}
+
+

fix_feature_types() can later be applied to the newdata, and will make sure, that all incoming features are converted to their expected feature type as in the original Task we used for training our pipeline (and this is the reason, why we stored the information about the features earlier). Note that in our tutorial we only have factor, integer, and numeric features, but fix_feature_types() should also work for all other supported feature_types listed in mlr_reflections$task_feature_types. However, it may need some customization depending on your own production environment to make the conversions meaningful.

+

The following R file, predict_gl.R loads our trained pipepline and feature information and provides an endpoint for a POST request, "/predict_medv". The incoming data then is converted using jsonlite::fromJSON. We expect the incoming data to either be JSON objects in an array or nested JSON objects and therefore we bind the converted vectors row-wise to a data.table using data.table::rbindlist. We then convert all features to their expected feature_types (using the fix_feature_types() function as defined above) and can finally predict the medv using our trained pipeline. As no default serialization from R6 objects to JSON objects exists (yet), we wrap the Prediction in a data.table (of course we could also only return the numeric prediction values):

+
+
# predict_gl.R
+
+library(data.table)
+library(jsonlite)
+library(mlr3)
+library(mlr3pipelines)
+
+source("fix_feature_types.R")
+
+gl = readRDS("gl.rds")
+
+feature_info = readRDS("feature_info.rds")
+
+#* @post /predict_medv
+function(req) {
+  # get the JSON string from the post body
+  newdata = fromJSON(req$postBody, simplifyVector = FALSE)
+  # expect either JSON objects in an array or nested JSON objects
+  newdata = rbindlist(newdata, use.names = TRUE)
+  # convert all features in place to their expected feature_type
+  newdata[, colnames(newdata) := mlr3misc::pmap(
+    list(.SD, colnames(newdata)),
+    fix_feature_types,
+    feature_info = feature_info)]
+  # predict and return as a data.table
+  as.data.table(gl$predict_newdata(newdata))
+  # or only the numeric values
+  # gl$predict_newdata(newdata)$response
+}
+
+

Note that the only difference to a regular R file is the comment

+
+
#* @post /predict_medv`
+
+

telling plumber to construct the endpoint "/predict_medv" for a POST request.

+

We can then run plumber::plumb. The following code sets up the web service locally on your personal machine at port 1030 (we use such a high number because some systems require administrator rights to allow processes to listen to lower ports):

+
+
library(plumber)
+r = plumb("predict_gl.R")
+r$run(port = 1030, host = "0.0.0.0")
+
+

Congratulations, your first REST API is running on your local machine. We can test it by providing some data, using curl via the command line:

+
+
curl --data '[{"crim":3.14, "tax":691, "town":"Newton"}]' "http://127.0.0.1:1030/predict_medv"
+
+

This should return the predicted medv:

+
+
[{"row_id":1,"response":"32.2329"}]
+
+

Alternatively, we can also use the httr::POST function within R:

+
+
newdata = '[{"crim":3.14, "tax":691, "town":"Newton"}]'
+resp = httr::POST(url = "http://127.0.0.1:1030/predict_medv",
+  body = newdata, encode = "json")
+httr::content(resp)
+
+

We can further play around a bit more and provide more than a single new observation and also check whether our feature type conversion and missing value imputation works:

+
+
newdata = '[
+  {"crim":3.14, "tax":691, "town":"Newton"},
+  {"crim":"not_a_number", "tax":3.14, "town":"Munich"},
+  {"tax":"not_a_number", "town":31, "crim":99}
+]'
+resp = httr::POST(url = "http://127.0.0.1:1030/predict_medv",
+  body = newdata, encode = "json")
+httr::content(resp)
+
+

Note that you can also use jsonlite::toJSON to convert a data.frame to JSON data for your toy examples here.

+

In the following final section we want to use Docker to run a virtual machine as a container (an instance of a snapshot of a machine at a moment in time).

+
+
+

Using Docker to Deploy our REST API

+

A Docker container image is a lightweight, standalone, executable package of software that includes everything needed to run an application. Suppose we want to run our REST API on an Amazon Web Service or Microsoft’s Azure Cloud. Then we can use a Docker container to easily set up our web service without going through the hassle of configuring manually our hosting instance.

+

We are going to need two things: An image and a container. An image defines the OS and software while the container is the actual running instance of the image. To build a Docker image we have to specify a Dockerfile. Note that it is sensible to set up the whole project in its own directory, e.g., ~/mlr3_api.

+

Every Dockerfile starts with a FROM statement describing the image we are building our image from. In our case we want an R based image that ideally already has plumber and its dependencies installed. Luckily, the trestletech/plumber image exists:

+
+
FROM trestletech/plumber
+
+

We then install the R packages needed to set up our REST API (note that we can skip jsonlite, because plumber already depends on it):

+
+
RUN R -e 'install.packages(c("data.table", "mlr3", "mlr3pipelines"))'
+
+

Next, we copy our trained pipeline (gl.rds), our stored feature information (feature_info.rds), our R file to convert features, (fix_feature_types.R) and our R file to predict (predict_gl.R) to a new directory /data and set this as the working directory:

+
+
RUN mkdir /data
+COPY gl.rds /data
+COPY feature_info.rds /data
+COPY fix_feature_types.R /data
+COPY predict_gl.R /data
+WORKDIR /data
+
+

Finally, we listen on port 1030 and start the server (this is analogously done as manually calling plumber::plumb on the predict_gl.R file and running it):

+
+
EXPOSE 1030
+ENTRYPOINT ["R", "-e", \
+    "r = plumber::plumb('/data/predict_gl.R'); r$run(port = 1030, host = '0.0.0.0')"]
+
+

The complete Dockerfile looks like the following:

+
+
FROM trestletech/plumber
+
+RUN R -e 'install.packages(c("data.table", "mlr3", "mlr3misc", "mlr3pipelines"))'
+
+RUN mkdir /data
+COPY gl.rds /data
+COPY feature_info.rds /data
+COPY fix_feature_types.R /data
+COPY predict_gl.R /data
+WORKDIR /data
+
+EXPOSE 1030
+ENTRYPOINT ["R", "-e", \
+    "r = plumber::plumb('/data/predict_gl.R'); r$run(port = 1030, host = '0.0.0.0')"]
+
+

To build the image we open a terminal in the mlr3_api directory and run:

+
+
docker build -t mlr3-plumber-demo .
+
+

This may take quite some time.

+

To finally run the container, simply use:

+
+
docker run --rm -p 1030:1030 mlr3-plumber-demo
+
+

You can then proceed to provide some data via curl or httr::POST (to the same local address, because the Docker container is still running on your local machine).

+

To stop all running containers use:

+
+
docker stop $(docker ps -a -q)
+
+

Finally, you can proceed to deploy your container to an Amazon Web Service or an Azure Cloud. For the latter, the package AzureContainers is especially helpful. If you do plan to do this note that the plumber service above is exposed over HTTP, and there is no authentication layer making it insecure. You may think about adding a layer of authentification and restricting the service to HTTPS.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/technical/2022-12-22-mlr3viz/index.html b/gallery/technical/2022-12-22-mlr3viz/index.html new file mode 100644 index 00000000..7f312338 --- /dev/null +++ b/gallery/technical/2022-12-22-mlr3viz/index.html @@ -0,0 +1,1612 @@ + + + + + + + + + + + + +Visualization in mlr3 – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Visualization in mlr3

+
+
+

Quickly plot the mlr3 ecosystem.

+
+
+
+
+ + +
+ +
+
Author
+ +
+ +
+
Published
+
+

December 22, 2022

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Scope

+

We showcase the visualization functions of the mlr3 ecosystem. The mlr3viz package creates a plot for almost all mlr3 objects. This post displays all available plots with their reproducible code. We start with plots of the base mlr3 objects. This includes boxplots of tasks, dendrograms of cluster learners and ROC curves of predictions. After that, we tune a classification tree and visualize the results. Finally, we show visualizations for filters.

+
+
+
+ +
+
+Note +
+
+
+

This article will be updated whenever a new plot is available in mlr3viz.

+
+
+
+
+

Package

+

The mlr3viz package defines autoplot() functions to draw plots with ggplot2. Often there is more than one type of plot for an object. You can change the plot with the type argument. The help pages list all possible choices. The easiest way to access the help pages is via the pkgdown website. The plots use the viridis color pallet and the appearance is controlled with the theme argument. By default, the minimal theme is applied.

+
+
+

Tasks

+
+

Classification

+

We begin with plots of the classification task Palmer Penguins. We plot the class frequency of the target variable.

+
+
library(mlr3verse)
+library(mlr3viz)
+
+task = tsk("penguins")
+task$select(c("body_mass", "bill_length"))
+
+autoplot(task, type = "target")
+
+
+
+

+
+
+
+
+

The "duo" plot shows the distribution of multiple features.

+
+
autoplot(task, type = "duo")
+
+
+
+

+
+
+
+
+

The "pairs" plot shows the pairwise comparison of multiple features. The classes of the target variable are shown in different colors.

+
+
autoplot(task, type = "pairs")
+
+
+
+

+
+
+
+
+
+
+

Regression

+

Next, we plot the regression task mtcars. We create a boxplot of the target variable.

+
+
task = tsk("mtcars")
+task$select(c("am", "carb"))
+
+autoplot(task, type = "target")
+
+
+
+

+
+
+
+
+

The "pairs" plot shows the pairwise comparison of mutiple features and the target variable.

+
+
autoplot(task, type = "pairs")
+
+
+
+

+
+
+
+
+
+
+

Cluster

+

Finally, we plot the cluster task US Arrests. The "pairs" plot shows the pairwise comparison of mutiple features.

+
+
library(mlr3cluster)
+
+task = mlr_tasks$get("usarrests")
+
+autoplot(task, type = "pairs")
+
+
+
+

+
+
+
+
+
+
+
+

Learner

+
+

Classification

+

The "prediction" plot shows the decision boundary of a classification learner and the true class labels as points.

+
+
task = tsk("pima")$select(c("age", "pedigree"))
+learner = lrn("classif.rpart")
+learner$train(task)
+
+autoplot(learner, type = "prediction", task)
+
+
+
+

+
+
+
+
+

Using probabilities.

+
+
task = tsk("pima")$select(c("age", "pedigree"))
+learner = lrn("classif.rpart", predict_type = "prob")
+learner$train(task)
+
+autoplot(learner, type = "prediction", task)
+
+
+
+

+
+
+
+
+
+
+

Regression

+

The "prediction" plot of a regression learner illustrates the decision boundary and the true response as points.

+
+
task = tsk("boston_housing")$select("age")
+learner = lrn("regr.rpart")
+learner$train(task)
+
+autoplot(learner, type = "prediction", task)
+
+
+
+

+
+
+
+
+

When using two features, the response surface is plotted in the background.

+
+
task = tsk("boston_housing")$select(c("age", "rm"))
+learner = lrn("regr.rpart")
+learner$train(task)
+
+autoplot(learner, type = "prediction", task)
+
+
+
+

+
+
+
+
+
+
+

GLMNet

+

The classification and regression GLMNet learner is equipped with a plot function.

+
+
library(mlr3data)
+
+task = tsk("ilpd")
+task$select(setdiff(task$feature_names, "gender"))
+learner = lrn("classif.glmnet")
+learner$train(task)
+
+autoplot(learner, type = "ggfortify")
+
+
+
+

+
+
+
+
+
+
task = tsk("mtcars")
+learner = lrn("regr.glmnet")
+learner$train(task)
+
+autoplot(learner, type = "ggfortify")
+
+
+
+

+
+
+
+
+
+
+

Rpart

+

We plot a classification tree of the rpart package. We have to fit the learner with keep_model = TRUE to keep the model object.

+
+
task = tsk("penguins")
+learner = lrn("classif.rpart", keep_model = TRUE)
+learner$train(task)
+
+autoplot(learner, type = "ggparty")
+
+
+
+

+
+
+
+
+

We can also plot regression trees.

+
+
task = tsk("mtcars")
+learner = lrn("regr.rpart", keep_model = TRUE)
+learner$train(task)
+
+autoplot(learner, type = "ggparty")
+
+
+
+

+
+
+
+
+
+
+

ClustHierachical

+

The "dend" plot shows the result of the hierarchical clustering of the data.

+
+
library(mlr3cluster)
+
+task = tsk("usarrests")
+learner = lrn("clust.hclust")
+learner$train(task)
+
+autoplot(learner, type = "dend", task = task)
+
+
+
+

+
+
+
+
+

The "scree" type plots the number of clusters and the height.

+
+
autoplot(learner, type = "scree")
+
+
+
+

+
+
+
+
+
+
+
+

Prediction

+
+

Classification

+

We plot the predictions of a classification learner. The "stacked" plot shows the predicted and true class labels.

+
+
task = tsk("spam")
+learner = lrn("classif.rpart", predict_type = "prob")
+pred = learner$train(task)$predict(task)
+
+autoplot(pred, type = "stacked")
+
+
+
+

+
+
+
+
+

The ROC curve plots the true positive rate against the false positive rate at different thresholds.

+
+
autoplot(pred, type = "roc")
+
+
+
+

+
+
+
+
+

The precision-recall curve plots the precision against the recall at different thresholds.

+
+
autoplot(pred, type = "prc")
+
+
+
+

+
+
+
+
+

The "threshold" plot varies the threshold of a binary classification and plots against the resulting performance.

+
+
autoplot(pred, type = "threshold")
+
+
+
+

+
+
+
+
+
+
+

Regression

+

The predictions of a regression learner are often presented as a scatterplot of truth and predicted response.

+
+
task = tsk("boston_housing")
+learner = lrn("regr.rpart")
+pred = learner$train(task)$predict(task)
+
+autoplot(pred, type = "xy")
+
+
+
+

+
+
+
+
+

Additionally, we plot the response with the residuals.

+
+
autoplot(pred, type = "residual")
+
+
+
+

+
+
+
+
+

We can also plot the distribution of the residuals.

+
+
autoplot(pred, type = "histogram")
+
+
+
+

+
+
+
+
+
+
+

Cluster

+

The predictions of a cluster learner are often presented as a scatterplot of the data points colored by the cluster.

+
+
library(mlr3cluster)
+
+task = tsk("usarrests")
+learner = lrn("clust.kmeans", centers = 3)
+pred = learner$train(task)$predict(task)
+
+autoplot(pred, task, type = "scatter")
+
+
+
+

+
+
+
+
+

The "sil" plot shows the silhouette width of the clusters. The dashed line is the mean silhouette width.

+
+
autoplot(pred, task, type = "sil")
+
+
+
+

+
+
+
+
+

The "pca" plot shows the first two principal components of the data colored by the cluster.

+
+
autoplot(pred, task, type = "pca")
+
+
+
+

+
+
+
+
+
+
+
+

Resample Result

+
+

Classification

+

The "boxplot" shows the distribution of the performance measures.

+
+
task = tsk("sonar")
+learner = lrn("classif.rpart", predict_type = "prob")
+resampling = rsmp("cv")
+rr = resample(task, learner, resampling)
+
+autoplot(rr, type = "boxplot")
+
+
+
+

+
+
+
+
+

We can also plot the distribution of the performance measures as a “histogram”.

+
+
autoplot(rr, type = "histogram")
+
+
+
+

+
+
+
+
+

The ROC curve plots the true positive rate against the false positive rate at different thresholds.

+
+
autoplot(rr, type = "roc")
+
+
+
+

+
+
+
+
+

The precision-recall curve plots the precision against the recall at different thresholds.

+
+
autoplot(rr, type = "prc")
+
+
+
+

+
+
+
+
+

The "prediction" plot shows two features and the predicted class in the background. Points mark the observations of the test set and the color presents the truth.

+
+
task = tsk("pima")
+task$filter(seq(100))
+task$select(c("age", "glucose"))
+learner = lrn("classif.rpart")
+resampling = rsmp("cv", folds = 3)
+rr = resample(task, learner, resampling, store_models = TRUE)
+
+autoplot(rr, type = "prediction")
+
+
+
+

+
+
+
+
+

Alternatively, we can plot class probabilities.

+
+
task = tsk("pima")
+task$filter(seq(100))
+task$select(c("age", "glucose"))
+learner = lrn("classif.rpart", predict_type = "prob")
+resampling = rsmp("cv", folds = 3)
+rr = resample(task, learner, resampling, store_models = TRUE)
+
+autoplot(rr, type = "prediction")
+
+
+
+

+
+
+
+
+

In addition to the test set, we can also plot the train set.

+
+
task = tsk("pima")
+task$filter(seq(100))
+task$select(c("age", "glucose"))
+learner = lrn("classif.rpart", predict_type = "prob", predict_sets = c("train", "test"))
+resampling = rsmp("cv", folds = 3)
+rr = resample(task, learner, resampling, store_models = TRUE)
+
+autoplot(rr, type = "prediction", predict_sets = c("train", "test"))
+
+
+
+

+
+
+
+
+

The "prediction" plot can also show categorical features.

+
+
task = tsk("german_credit")
+task$filter(seq(100))
+task$select(c("housing", "employment_duration"))
+learner = lrn("classif.rpart")
+resampling = rsmp("cv", folds = 3)
+rr = resample(task, learner, resampling, store_models = TRUE)
+
+autoplot(rr, type = "prediction")
+
+
+
+

+
+
+
+
+
+
+

Regression

+

The “prediction” plot shows one feature and the response. Points mark the observations of the test set.

+
+
task = tsk("boston_housing")
+task$select("age")
+task$filter(seq(100))
+learner = lrn("regr.rpart")
+resampling = rsmp("cv", folds  = 3)
+rr = resample(task, learner, resampling, store_models = TRUE)
+
+autoplot(rr, type = "prediction")
+
+
+
+

+
+
+
+
+

Additionally, we can add confidence bounds.

+
+
task = tsk("boston_housing")
+task$select("age")
+task$filter(seq(100))
+learner = lrn("regr.lm", predict_type = "se")
+resampling = rsmp("cv", folds  = 3)
+rr = resample(task, learner, resampling, store_models = TRUE)
+
+autoplot(rr, type = "prediction")
+
+
+
+

+
+
+
+
+

And add the train set.

+
+
task = tsk("boston_housing")
+task$select("age")
+task$filter(seq(100))
+learner = lrn("regr.lm", predict_type = "se", predict_sets = c("train", "test"))
+resampling = rsmp("cv", folds = 3)
+rr = resample(task, learner, resampling, store_models = TRUE)
+
+autoplot(rr, type = "prediction", predict_sets = c("train", "test"))
+
+
+
+

+
+
+
+
+

We can also add the prediction surface to the background.

+
+
task = tsk("boston_housing")
+task$select(c("age", "rm"))
+task$filter(seq(100))
+learner = lrn("regr.rpart")
+resampling = rsmp("cv", folds = 3)
+rr = resample(task, learner, resampling, store_models = TRUE)
+
+autoplot(rr, type = "prediction")
+
+
+
+

+
+
+
+
+
+
+
+

Benchmark Result

+

We show the performance distribution of a benchmark with multiple tasks.

+
+
tasks = tsks(c("pima", "sonar"))
+learner = lrns(c("classif.featureless", "classif.rpart", "classif.xgboost"), predict_type = "prob")
+resampling = rsmps("cv")
+bmr = benchmark(benchmark_grid(tasks, learner, resampling))
+
+autoplot(bmr, type = "boxplot")
+
+
+
+

+
+
+
+
+

We plot a benchmark result with one task and multiple learners.

+
+
tasks = tsk("pima")
+learner = lrns(c("classif.featureless", "classif.rpart", "classif.xgboost"), predict_type = "prob")
+resampling = rsmps("cv")
+bmr = benchmark(benchmark_grid(tasks, learner, resampling))
+
+

We plot an roc curve for each learner.

+
+
autoplot(bmr, type = "roc")
+
+
+
+

+
+
+
+
+

Alternatively, we can plot precision-recall curves.

+
+
autoplot(bmr, type = "prc")
+
+
+
+

+
+
+
+
+
+
+

Tuning Instance

+

We tune the hyperparameters of a decision tree on the sonar task. The "performance" plot shows the performance over batches.

+
+
library(mlr3tuning)
+library(mlr3tuningspaces)
+library(mlr3learners)
+
+instance = tune(
+  tuner = tnr("gensa"),
+  task = tsk("sonar"),
+  learner = lts(lrn("classif.rpart")),
+  resampling = rsmp("holdout"),
+  measures = msr("classif.ce"),
+  term_evals = 100
+)
+
+autoplot(instance, type = "performance")
+
+
+
+

+
+
+
+
+

The "incumbent" plot shows the performance of the best hyperparameter setting over the number of evaluations.

+
+
autoplot(instance, type = "incumbent")
+
+
+
+

+
+
+
+
+

The "parameter" plot shows the performance for each hyperparameter setting.

+
+
autoplot(instance, type = "parameter", cols_x = c("cp", "minsplit"))
+
+
+
+

+
+
+
+
+

The "marginal" plot shows the performance of different hyperparameter values. The color indicates the batch.

+
+
autoplot(instance, type = "marginal", cols_x = "cp")
+
+
+
+

+
+
+
+
+

The "parallel" plot visualizes the relationship of hyperparameters.

+
+
autoplot(instance, type = "parallel")
+
+
+
+

+
+
+
+
+

We plot cp against minsplit and color the points by the performance.

+
+
autoplot(instance, type = "points", cols_x = c("cp", "minsplit"))
+
+
+
+

+
+
+
+
+

Next, we plot all hyperparameters against each other.

+
+
autoplot(instance, type = "pairs")
+
+
+
+

+
+
+
+
+

We plot the performance surface of two hyperparameters. The surface is interpolated with a learner.

+
+
autoplot(instance, type = "surface", cols_x = c("cp", "minsplit"), learner = mlr3::lrn("regr.ranger"))
+
+
+
+

+
+
+
+
+
+
+

Filter

+

We plot filter scores for the mtcars task.

+
+
library(mlr3filters)
+
+task = tsk("mtcars")
+f = flt("correlation")
+f$calculate(task)
+
+autoplot(f, n = 5)
+
+
+
+

+
+
+
+
+
+
+

Conclusion

+

The mlr3viz package brings together the visualization functions of the mlr3 ecosystem. All plots are drawn with the autoplot() function and the appearance can be customized with the theme argument. If you need to highly customize a plot e.g. for a publication, we encourage you to check our code on GitHub. The code should be easily adaptable to your needs. We are also looking forward to new visualizations. You can suggest new plots in an issue on GitHub.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-002-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-002-1.png new file mode 100644 index 00000000..3b75652d Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-002-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-003-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-003-1.png new file mode 100644 index 00000000..b56c1a8f Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-003-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-004-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-004-1.png new file mode 100644 index 00000000..f4506576 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-004-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-005-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-005-1.png new file mode 100644 index 00000000..8cc5b3ea Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-005-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-006-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-006-1.png new file mode 100644 index 00000000..636c0f9a Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-006-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-007-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-007-1.png new file mode 100644 index 00000000..a14a47bd Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-007-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-008-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-008-1.png new file mode 100644 index 00000000..eb7aeed7 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-008-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-009-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-009-1.png new file mode 100644 index 00000000..1bd93b59 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-009-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-010-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-010-1.png new file mode 100644 index 00000000..6cb8fa2e Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-010-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-011-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-011-1.png new file mode 100644 index 00000000..7e76ca7f Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-011-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-012-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-012-1.png new file mode 100644 index 00000000..b6294dfb Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-012-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-013-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-013-1.png new file mode 100644 index 00000000..24ee0174 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-013-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-014-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-014-1.png new file mode 100644 index 00000000..345b623c Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-014-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-015-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-015-1.png new file mode 100644 index 00000000..4f2389c2 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-015-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-016-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-016-1.png new file mode 100644 index 00000000..afad9e67 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-016-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-017-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-017-1.png new file mode 100644 index 00000000..bdbec8ef Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-017-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-018-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-018-1.png new file mode 100644 index 00000000..4d3d1a7d Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-018-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-019-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-019-1.png new file mode 100644 index 00000000..b08133f1 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-019-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-020-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-020-1.png new file mode 100644 index 00000000..c789d3bd Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-020-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-021-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-021-1.png new file mode 100644 index 00000000..399698fe Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-021-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-022-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-022-1.png new file mode 100644 index 00000000..061cefc0 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-022-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-023-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-023-1.png new file mode 100644 index 00000000..b082414c Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-023-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-024-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-024-1.png new file mode 100644 index 00000000..fef4d53b Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-024-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-025-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-025-1.png new file mode 100644 index 00000000..4c567f39 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-025-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-026-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-026-1.png new file mode 100644 index 00000000..eaa63007 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-026-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-027-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-027-1.png new file mode 100644 index 00000000..b98deb78 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-027-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-028-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-028-1.png new file mode 100644 index 00000000..4d2e3491 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-028-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-029-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-029-1.png new file mode 100644 index 00000000..6d0082f7 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-029-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-030-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-030-1.png new file mode 100644 index 00000000..39f3dd74 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-030-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-031-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-031-1.png new file mode 100644 index 00000000..0b435929 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-031-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-032-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-032-1.png new file mode 100644 index 00000000..674319aa Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-032-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-033-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-033-1.png new file mode 100644 index 00000000..a507479b Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-033-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-034-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-034-1.png new file mode 100644 index 00000000..5344151e Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-034-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-035-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-035-1.png new file mode 100644 index 00000000..a465c023 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-035-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-036-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-036-1.png new file mode 100644 index 00000000..129812b0 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-036-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-037-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-037-1.png new file mode 100644 index 00000000..48303426 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-037-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-038-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-038-1.png new file mode 100644 index 00000000..c4c69cec Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-038-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-039-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-039-1.png new file mode 100644 index 00000000..cfd0158d Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-039-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-040-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-040-1.png new file mode 100644 index 00000000..2b7c8bb6 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-040-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-041-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-041-1.png new file mode 100644 index 00000000..98402ca6 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-041-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-042-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-042-1.png new file mode 100644 index 00000000..d7b38e2a Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-042-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-043-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-043-1.png new file mode 100644 index 00000000..681850d3 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-043-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-044-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-044-1.png new file mode 100644 index 00000000..347da084 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-044-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-045-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-045-1.png new file mode 100644 index 00000000..98402ca6 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-045-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-046-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-046-1.png new file mode 100644 index 00000000..63d01a5f Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-046-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-047-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-047-1.png new file mode 100644 index 00000000..168b7123 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-047-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-048-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-048-1.png new file mode 100644 index 00000000..66a30923 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-048-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-049-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-049-1.png new file mode 100644 index 00000000..075671e5 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-049-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-050-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-050-1.png new file mode 100644 index 00000000..43c9e714 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-050-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-051-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-051-1.png new file mode 100644 index 00000000..6599dd59 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-051-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-052-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-052-1.png new file mode 100644 index 00000000..05232c90 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-052-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-053-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-053-1.png new file mode 100644 index 00000000..05232c90 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/2022-12-22-mlr3viz-053-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-1-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-1-1.png new file mode 100644 index 00000000..eb7aeed7 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-1-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-10-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-10-1.png new file mode 100644 index 00000000..d56192a9 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-10-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-11-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-11-1.png new file mode 100644 index 00000000..6b10c75d Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-11-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-12-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-12-1.png new file mode 100644 index 00000000..dfa2f01b Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-12-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-13-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-13-1.png new file mode 100644 index 00000000..0860b276 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-13-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-14-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-14-1.png new file mode 100644 index 00000000..fc11c1a0 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-14-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-15-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-15-1.png new file mode 100644 index 00000000..787a0aed Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-15-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-16-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-16-1.png new file mode 100644 index 00000000..153a6c1b Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-16-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-17-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-17-1.png new file mode 100644 index 00000000..3c54b35a Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-17-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-18-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-18-1.png new file mode 100644 index 00000000..89abea8d Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-18-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-19-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-19-1.png new file mode 100644 index 00000000..3a736285 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-19-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-2-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-2-1.png new file mode 100644 index 00000000..1bd93b59 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-2-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-20-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-20-1.png new file mode 100644 index 00000000..f625a403 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-20-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-21-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-21-1.png new file mode 100644 index 00000000..ace4b597 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-21-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-22-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-22-1.png new file mode 100644 index 00000000..3915ef79 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-22-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-23-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-23-1.png new file mode 100644 index 00000000..e333f35b Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-23-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-24-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-24-1.png new file mode 100644 index 00000000..3253b301 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-24-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-25-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-25-1.png new file mode 100644 index 00000000..cbe929a0 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-25-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-26-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-26-1.png new file mode 100644 index 00000000..7e4241f9 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-26-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-27-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-27-1.png new file mode 100644 index 00000000..a23c1b9b Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-27-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-28-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-28-1.png new file mode 100644 index 00000000..b10dc502 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-28-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-29-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-29-1.png new file mode 100644 index 00000000..126f35a3 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-29-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-3-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-3-1.png new file mode 100644 index 00000000..6cb8fa2e Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-3-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-30-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-30-1.png new file mode 100644 index 00000000..360f8c3c Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-30-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-31-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-31-1.png new file mode 100644 index 00000000..9c9460a2 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-31-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-32-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-32-1.png new file mode 100644 index 00000000..e3d30228 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-32-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-33-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-33-1.png new file mode 100644 index 00000000..6f4aff0a Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-33-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-34-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-34-1.png new file mode 100644 index 00000000..0edf60b6 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-34-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-35-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-35-1.png new file mode 100644 index 00000000..6c724b86 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-35-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-36-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-36-1.png new file mode 100644 index 00000000..e8af1762 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-36-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-38-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-38-1.png new file mode 100644 index 00000000..3eba6d39 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-38-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-39-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-39-1.png new file mode 100644 index 00000000..db597b03 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-39-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-4-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-4-1.png new file mode 100644 index 00000000..7e76ca7f Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-4-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-40-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-40-1.png new file mode 100644 index 00000000..25fa2320 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-40-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-42-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-42-1.png new file mode 100644 index 00000000..c5e24799 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-42-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-43-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-43-1.png new file mode 100644 index 00000000..3aa69e56 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-43-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-44-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-44-1.png new file mode 100644 index 00000000..f7c76bd5 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-44-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-45-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-45-1.png new file mode 100644 index 00000000..0bafd71c Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-45-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-46-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-46-1.png new file mode 100644 index 00000000..751fcfc3 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-46-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-47-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-47-1.png new file mode 100644 index 00000000..fa6361fc Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-47-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-48-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-48-1.png new file mode 100644 index 00000000..623e6a69 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-48-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-5-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-5-1.png new file mode 100644 index 00000000..e522755b Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-5-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-6-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-6-1.png new file mode 100644 index 00000000..68dc0a86 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-6-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-7-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-7-1.png new file mode 100644 index 00000000..c3f38b2a Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-7-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-8-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-8-1.png new file mode 100644 index 00000000..95e9e607 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-8-1.png differ diff --git a/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-9-1.png b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-9-1.png new file mode 100644 index 00000000..1afef375 Binary files /dev/null and b/gallery/technical/2022-12-22-mlr3viz/index_files/figure-html/unnamed-chunk-9-1.png differ diff --git a/gallery/technical/2023-02-27-land-cover-classification/cover.png b/gallery/technical/2023-02-27-land-cover-classification/cover.png new file mode 100644 index 00000000..98c13f1b Binary files /dev/null and b/gallery/technical/2023-02-27-land-cover-classification/cover.png differ diff --git a/gallery/technical/2023-02-27-land-cover-classification/index.html b/gallery/technical/2023-02-27-land-cover-classification/index.html new file mode 100644 index 00000000..416ddc2c --- /dev/null +++ b/gallery/technical/2023-02-27-land-cover-classification/index.html @@ -0,0 +1,969 @@ + + + + + + + + + + + + +Spatial Data in the mlr3 Ecosystem – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Spatial Data in the mlr3 Ecosystem

+
+
+

Run a land cover classification of the city of Leipzig.

+
+
+ +
+ + +
+ +
+
Author
+ +
+ +
+
Published
+
+

February 27, 2023

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Scope

+

Working with spatial data in R requires a lot of data wrangling e.g. reading from different file formats, converting between spatial formats, creating tables from point layers, and predicting spatial raster images. The goal of mlr3spatial is to simplify these workflows within the mlr3 ecosystem. As a practical example, we will perform a land cover classification for the city of Leipzig, Germany. Figure 1 illustrates the typical workflow for this type of task: Load the training data, create a spatial task, train a learner with it, and predict the final raster image.

+
+
+
+
+
+
+
%%{ init: { 'flowchart': { 'curve': 'bump' } } }%%
+
+flowchart LR
+    subgraph files[Files]
+    vector[Vector]
+    raster[Raster]
+    end
+    subgraph load[Load Data]
+    sf
+    terra
+    end
+    vector --> sf
+    raster --> terra
+    subgraph train_model[Train Model]
+    task[Task]
+    learner[Learner]
+    end
+    terra --> prediction_raster
+    task --> learner
+    sf --> task
+    subgraph predict[Spatial Prediction]
+    prediction_raster[Raster Image]
+    end
+    learner --> prediction_raster
+
+
+
+
+Figure 1: Spatial prediction workflow in mlr3spatial. +
+
+
+
+
+

We assume that you are familiar with the mlr3 ecosystem and know the basic concepts of remote sensing. If not, we recommend reading the mlr3book first. If you are interested in spatial resampling, check out the book chapter on spatial analysis.

+
+
+

Land Cover Classification

+

Land cover is the physical material or vegetation that covers the surface of the earth, including both natural and human-made features. Understanding land cover patterns and changes over time is critical for addressing global environmental challenges, such as climate change, land degradation, and loss of biodiversity. Land cover classification is the process of assigning land cover classes to pixels in a raster image. With mlr3spatial, we can easily perform a land cover classification within the mlr3 ecosystem.

+

Before we can start the land cover classification, we need to load the necessary packages. The mlr3spatial package relies on terra for processing raster data and sf for vector data. These widely used packages read all common raster and vector formats. Additionally, the stars and raster packages are supported.

+
+
library(mlr3verse)
+library(mlr3spatial)
+library(terra, exclude = "resample")
+library(sf)
+
+

We will work with a Sentinel-2 scene of the city of Leipzig which consists of 7 bands with a 10 or 20m spatial resolution and an NDVI band. The data is included in the mlr3spatial package. We use the terra::rast() to load the TIFF raster file.

+
+
leipzig_raster = rast(system.file("extdata", "leipzig_raster.tif", package = "mlr3spatial"))
+leipzig_raster
+
+
class       : SpatRaster 
+dimensions  : 206, 154, 8  (nrow, ncol, nlyr)
+resolution  : 10, 10  (x, y)
+extent      : 731810, 733350, 5692030, 5694090  (xmin, xmax, ymin, ymax)
+coord. ref. : WGS 84 / UTM zone 32N (EPSG:32632) 
+source      : leipzig_raster.tif 
+names       :  b02,  b03,  b04,  b06,  b07,  b08, ... 
+min values  :  846,  645,  366,  375,  401,  374, ... 
+max values  : 4705, 4880, 5451, 4330, 5162, 5749, ... 
+
+
+

The training data is a GeoPackage point layer with land cover labels and spectral features. We load the file and create a simple feature point layer.

+
+
leipzig_vector = read_sf(system.file("extdata", "leipzig_points.gpkg", package = "mlr3spatial"), stringsAsFactors = TRUE)
+leipzig_vector
+
+
Simple feature collection with 97 features and 9 fields
+Geometry type: POINT
+Dimension:     XY
+Bounding box:  xmin: 731930.5 ymin: 5692136 xmax: 733220.3 ymax: 5693968
+Projected CRS: WGS 84 / UTM zone 32N
+# A tibble: 97 × 10
+     b02   b03   b04   b06   b07   b08   b11    ndvi land_cover               geom
+   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>   <dbl> <fct>             <POINT [m]>
+ 1   903   772   426  2998  4240  4029  1816  0.809  forest     (732480.1 5693957)
+ 2  1270  1256  1081  1998  2493  2957  2073  0.465  urban      (732217.4 5692769)
+ 3  1033   996   777  2117  2748  2799  1595  0.565  urban      (732737.2 5692469)
+ 4   962   773   500   465   505   396   153 -0.116  water      (733169.3 5692777)
+ 5  1576  1527  1626  1715  1745  1768  1980  0.0418 urban      (732202.2 5692644)
+ 6  1125  1185   920  3058  3818  3758  2682  0.607  pasture      (732153 5693059)
+ 7   880   746   424  2502  3500  3397  1469  0.778  forest     (731937.9 5693722)
+ 8  1332  1251  1385  1663  1799  1640  1910  0.0843 urban      (732416.2 5692324)
+ 9   940   741   475   452   515   400   139 -0.0857 water      (732933.7 5693344)
+10   902   802   454  2764  3821  3666  1567  0.780  forest     (732411.3 5693352)
+# ℹ 87 more rows
+
+
+

We plot both layers to get an overview of the data. The training points are located in the districts of Lindenau and Zentrum West.

+
+
+Code +
library(ggplot2)
+library(tidyterra, exclude = "filter")
+
+ggplot() +
+  geom_spatraster_rgb(data = leipzig_raster, r = 3, g = 2, b = 1, max_col_value = 5451) +
+  geom_spatvector(data = leipzig_vector, aes(color = land_cover)) +
+  scale_color_viridis_d(name = "Land cover", labels = c("Forest", "Pastures", "Urban", "Water")) +
+  theme_minimal()
+
+
+
+
+

+
+
+
+
+

The as_task_classif_st() function directly creates a spatial task from the point layer. This makes it unnecessary to transform the point layer to a data.frame with coordinates. Spatial tasks additionally store the coordinates of the training points. The coordinates are useful when estimating the performance of the model with spatial resampling.

+
+
task = as_task_classif_st(leipzig_vector, target = "land_cover")
+task
+
+
<TaskClassifST:leipzig_vector> (97 x 9)
+* Target: land_cover
+* Properties: multiclass
+* Features (8):
+  - dbl (8): b02, b03, b04, b06, b07, b08, b11, ndvi
+* Coordinates:
+           X       Y
+ 1: 732480.1 5693957
+ 2: 732217.4 5692769
+ 3: 732737.2 5692469
+ 4: 733169.3 5692777
+ 5: 732202.2 5692644
+---                 
+93: 733018.7 5692342
+94: 732551.4 5692887
+95: 732520.4 5692589
+96: 732542.2 5692204
+97: 732437.8 5692300
+
+
+

Now we can train a model with the task. We use a simple decision tree learner from the rpart package. The "classif_st" task is a specialization of the "classif" task and therefore works with all "classif" learners.

+
+
learner = lrn("classif.rpart")
+learner$train(task)
+
+

To get a complete land cover classification of Leipzig, we have to predict on each pixel and return a raster image with these predictions. The $predict() method of the learner only works for tabular data. To predict a raster image, we use the predict_spatial() function.

+
+
# predict land cover map
+land_cover = predict_spatial(leipzig_raster, learner)
+
+
+
+Code +
ggplot() +
+  geom_spatraster(data = land_cover) +
+  scale_fill_viridis_d(name = "Land cover", labels = c("Forest", "Pastures", "Urban", "Water")) +
+  theme_minimal()
+
+
+
+
+

+
+
+
+
+
+
+

Conclusion

+

Working with spatial data in R is very easy with the mlr3spatial package. You can quickly train a model with a point layer and predict a raster image. The mlr3spatial package is still in development and we are looking forward to your feedback and contributions.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/technical/2023-02-27-land-cover-classification/index_files/figure-html/2023-01-23-mlr3spatial-005-1.png b/gallery/technical/2023-02-27-land-cover-classification/index_files/figure-html/2023-01-23-mlr3spatial-005-1.png new file mode 100644 index 00000000..49008f01 Binary files /dev/null and b/gallery/technical/2023-02-27-land-cover-classification/index_files/figure-html/2023-01-23-mlr3spatial-005-1.png differ diff --git a/gallery/technical/2023-02-27-land-cover-classification/index_files/figure-html/2023-01-23-mlr3spatial-009-1.png b/gallery/technical/2023-02-27-land-cover-classification/index_files/figure-html/2023-01-23-mlr3spatial-009-1.png new file mode 100644 index 00000000..e9c627f9 Binary files /dev/null and b/gallery/technical/2023-02-27-land-cover-classification/index_files/figure-html/2023-01-23-mlr3spatial-009-1.png differ diff --git a/gallery/technical/2023-10-25-bart-survival/index.html b/gallery/technical/2023-10-25-bart-survival/index.html new file mode 100644 index 00000000..2ba85bc3 --- /dev/null +++ b/gallery/technical/2023-10-25-bart-survival/index.html @@ -0,0 +1,1509 @@ + + + + + + + + + + + + +Survival modeling in mlr3 using Bayesian Additive Regression Trees (BART) – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Survival modeling in mlr3 using Bayesian Additive Regression Trees (BART)

+
+
+

Demonstrate use of survival BART on the lung dataset via mlr3proba and distr6.

+
+
+
+
+ + +
+ +
+
Author
+ +
+ +
+
Published
+
+

October 25, 2023

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Intro

+

Here are some interesting reads regarding BART:

+ +

We incorporated the survival BART model in mlr3extralearners and in this tutorial we will demonstrate how we can use packages like mlr3, mlr3proba and distr6 to more easily manipulate the output predictions to assess model convergence, validate our model (via several survival metrics), as well as perform model interpretation via PDPs (Partial Dependence Plots).

+
+
+

Libraries

+
+
library(mlr3extralearners)
+library(mlr3pipelines)
+library(mlr3proba)
+library(distr6)
+library(BART) # 2.9.4
+library(dplyr)
+library(tidyr)
+library(tibble)
+library(ggplot2)
+
+
+
+

Data

+

We will use the Lung Cancer Dataset. We convert the time variable from days to months to ease the computational burden:

+
+
task_lung = tsk('lung')
+
+d = task_lung$data()
+# in case we want to select specific columns to keep
+# d = d[ ,colnames(d) %in% c("time", "status", "age", "sex", "ph.karno"), with = FALSE]
+d$time = ceiling(d$time/30.44)
+task_lung = as_task_surv(d, time = 'time', event = 'status', id = 'lung')
+task_lung$label = "Lung Cancer"
+
+
+
+
+ +
+
+Note +
+
+
+
    +
  1. The original BART implementation supports categorical features (factors). This results in different importance scores per each dummy level which doesn’t work well with mlr3. So features of type factor or character are not allowed and we leave it to the user to encode them as they please.
  2. +
  3. The original BART implementation supports features with missing values. This is totally fine with mlr3 as well! In this example, we impute the features to show good ML practice.
  4. +
+
+
+

In our lung dataset, we encode the sex feature and perform model-based imputation with the rpart regression learner:

+
+
po_encode = po('encode', method = 'treatment')
+po_impute = po('imputelearner', lrn('regr.rpart'))
+pre = po_encode %>>% po_impute
+task = pre$train(task_lung)[[1]]
+task
+
+
<TaskSurv:lung> (228 x 10): Lung Cancer
+* Target: time, status
+* Properties: -
+* Features (8):
+  - int (7): age, inst, meal.cal, pat.karno, ph.ecog, ph.karno, wt.loss
+  - dbl (1): sex
+
+
+

No missing values in our data:

+
+
task$missings()
+
+
     time    status       age       sex      inst  meal.cal pat.karno   ph.ecog  ph.karno   wt.loss 
+        0         0         0         0         0         0         0         0         0         0 
+
+
+

We partition the data to train and test sets:

+
+
set.seed(42)
+part = partition(task, ratio = 0.9)
+
+
+
+

Train and Test

+

We train the BART model and predict on the test set:

+
+
# default `ndpost` value: 1000. We reduce it to 50 to speed up calculations in this tutorial
+learner = lrn("surv.bart", nskip = 250, ndpost = 50, keepevery = 10, mc.cores = 10)
+learner$train(task, row_ids = part$train)
+p = learner$predict(task, row_ids = part$test)
+p
+
+
<PredictionSurv> for 23 observations:
+    row_ids time status    crank     distr
+          9    8   TRUE 66.19326 <list[1]>
+         10    6   TRUE 98.43005 <list[1]>
+         21   10   TRUE 54.82313 <list[1]>
+---                                       
+        160   13  FALSE 37.82089 <list[1]>
+        163   10  FALSE 69.63534 <list[1]>
+        194    8  FALSE 81.13678 <list[1]>
+
+
+

See more details about BART’s parameters on the online documentation.

+
+

distr

+

What kind of object is the predicted distr?

+
+
p$distr
+
+
Arrdist(23x31x50) 
+
+
+
+
+
+ +
+
+Arrdist dimensions: +
+
+
+
    +
  1. Patients (observations)
  2. +
  3. Time points (months)
  4. +
  5. Number of posterior draws
  6. +
+
+
+

Actually the $distr is an active R6 field - this means that some computation is required to create it. What the prediction object actually stores internally is a 3d survival array (can be used directly with no performance overhead):

+
+
dim(p$data$distr)
+
+
[1] 23 31 50
+
+
+

This is a more easy-to-understand and manipulate form of the full posterior survival matrix prediction from the BART package ((R. Sparapani, Spanbauer, and McCulloch 2021), pages 34-35).

+
+
+
+ +
+
+Warning +
+
+
+

Though we have optimized with C++ code the way the Arrdist object is constructed, calling the $distr field can be computationally taxing if the product of the sizes of the 3 dimensions above exceeds ~1 million. In our case, \(23 \times 31 \times 50 = 35650\) so the conversion to an Arrdist via $distr will certainly not create performance issues.

+
+
+

An example using the internal prediction data: get all the posterior probabilities of the 3rd patient in the test set, at 12 months (1 year):

+
+
p$data$distr[3, 12, ]
+
+
 [1] 0.26546909 0.27505937 0.21151435 0.46700513 0.26178380 0.24040003 0.29946469 0.52357780 0.40833108 0.40367780
+[11] 0.27027392 0.31781286 0.54151844 0.34460027 0.41826554 0.41866367 0.33694401 0.34511270 0.47244492 0.49423660
+[21] 0.42069678 0.20095489 0.48696980 0.48409357 0.35649439 0.47969355 0.16355660 0.33728105 0.40245228 0.42418033
+[31] 0.36336145 0.48181667 0.51858238 0.49635078 0.37238179 0.26694030 0.52219952 0.48992897 0.08572207 0.30306005
+[41] 0.33881682 0.33463870 0.29102074 0.43176131 0.38554545 0.38053756 0.36808776 0.13772665 0.21898264 0.14552514
+
+
+

Working with the $distr interface and Arrdist objects is very efficient as we will see later for predicting survival estimates.

+
+
+
+ +
+
+Tip +
+
+
+

In survival analysis, \(S(t) = 1 - F(t)\), where \(S(t)\) the survival function and \(F(t)\) the cumulative distribution function (cdf). The latter can be interpreted as risk or probability of death up to time \(t\).

+

We can verify the above from the prediction object:

+
+
surv_array = 1 - distr6::gprm(p$distr, "cdf") # 3d array
+testthat::expect_equal(p$data$distr, surv_array)
+
+
+
+
+
+

crank

+

crank is the expected mortality (Sonabend, Bender, and Vollmer 2022) which is the sum of the predicted cumulative hazard function (as is done in random survival forest models). Higher values denote larger risk. To calculate crank, we need a survival matrix. So we have to choose which 3rd dimension we should use from the predicted survival array. This is what the which.curve parameter of the learner does:

+
+
learner$param_set$get_values()$which.curve
+
+
[1] 0.5
+
+
+

The default value (\(0.5\) quantile) is the median survival probability. It could be any other quantile (e.g. \(0.25\)). Other possible values for which.curve are mean or a number denoting the exact posterior draw to extract (e.g. the last one, which.curve = 50).

+
+
+
+

Feature importance

+

Default score is the observed count of each feature in the trees (so the higher the score, the more important the feature):

+
+
learner$param_set$values$importance
+
+
[1] "count"
+
+
learner$importance()
+
+
      sex  meal.cal      inst pat.karno  ph.karno   wt.loss       age   ph.ecog 
+     7.84      7.46      7.08      6.76      6.60      6.46      5.48      5.42 
+
+
+
+
+

MCMC Diagnostics

+

BART uses internally MCMC (Markov Chain Monte Carlo) to sample from the posterior survival distribution. We need to check that MCMC has converged, meaning that the chains have reached a stationary distribution that approximates the true posterior survival distribution (otherwise the predictions may be inaccurate, misleading and unreliable).

+

We use Geweke’s convergence diagnostic test as it is implemented in the BART R package. We choose 10 random patients from the train set to evaluate the MCMC convergence.

+
+
# predictions on the train set
+p_train = learner$predict(task, row_ids = part$train)
+
+# choose 10 patients from the train set randomly and make a list
+ids = as.list(sample(length(part$train), 10))
+
+z_list = lapply(ids, function(id) {
+  # matrix with columns => time points and rows => posterior draws
+  post_surv = 1 - t(distr6::gprm(p_train$distr[id], "cdf")[1,,])
+  BART::gewekediag(post_surv)$z # get the z-scores
+})
+
+# plot the z scores vs time for all patients
+dplyr::bind_rows(z_list) %>%
+  tidyr::pivot_longer(cols = everything()) %>%
+  mutate(name = as.numeric(name)) %>%
+  ggplot(aes(x = name, y = value)) +
+  geom_point() +
+  labs(x = "Time (months)", y = "Z-scores") +
+  # add critical values for a = 0.05
+  geom_hline(yintercept = 1.96, linetype = 'dashed', color = "red") +
+  geom_hline(yintercept = -1.96, linetype = 'dashed', color = "red") +
+  theme_bw(base_size = 14)
+
+
+
+

+
Geweke plot for MCMC diagnostics. Z-scores for the difference in the mean survival prediction between the first 10% and last 50% part of a Markov chain. The predictions are taken from 10 random patients in the train set. Red lines indicate the a = 0.05 critical line. Only a few z-scores exceed the 95% limits so we conclude that convergence has been attained.
+
+
+
+
+
+
+

Performance (test set)

+

We will use the following survival metrics:

+
    +
  1. Integrated Brier Score (requires a survival distribution prediction - distr)
  2. +
  3. Right-Censored Log loss (requires a survival distribution prediction - distr)
  4. +
  5. Uno’s C-index (requires a continuous ranking score prediction - crank)
  6. +
+

For the first two measures we will use the ERV (Explained Residual Variation) version, which standardizes the scores against a Kaplan-Meier (KM) baseline (Sonabend et al. 2022). This means that values close to \(0\) represent performance similar to a KM model, negative values denote worse performance than KM and \(1\) is the absolute best possible score.

+
+
measures = list(
+  msr("surv.graf", ERV = TRUE),
+  msr("surv.rcll", ERV = TRUE),
+  msr("surv.cindex", weight_meth = "G2", id = "surv.cindex.uno")
+)
+
+for (measure in measures) {
+  print(p$score(measure, task = task, train_set = part$train))
+}
+
+
  surv.graf 
+-0.09950096 
+  surv.rcll 
+-0.02622117 
+surv.cindex.uno 
+       0.551951 
+
+
+
+
+
+ +
+
+Note +
+
+
+

All metrics use by default the median survival distribution from the 3d array, no matter what is the which.curve argument during the learner’s construction.

+
+
+
+
+

Resampling

+

Performing resampling with the BART learner is very easy using mlr3.

+

We first stratify the data by status, so that in each resampling the proportion of censored vs un-censored patients remains the same:

+
+
task$col_roles$stratum = 'status'
+task$strata
+
+
       N                row_id
+   <int>                <list>
+1:   165       1,2,4,5,7,8,...
+2:    63  3, 6,38,68,71,83,...
+
+
+
+
rr = resample(task, learner, resampling = rsmp("cv", folds = 5), store_backends = TRUE)
+
+
INFO  [11:41:53.078] [mlr3] Applying learner 'surv.bart' on task 'lung' (iter 1/5)
+INFO  [11:41:55.545] [mlr3] Applying learner 'surv.bart' on task 'lung' (iter 2/5)
+INFO  [11:41:57.937] [mlr3] Applying learner 'surv.bart' on task 'lung' (iter 3/5)
+INFO  [11:42:00.417] [mlr3] Applying learner 'surv.bart' on task 'lung' (iter 4/5)
+INFO  [11:42:03.357] [mlr3] Applying learner 'surv.bart' on task 'lung' (iter 5/5)
+
+
+

No errors or warnings:

+
+
rr$errors
+
+
Empty data.table (0 rows and 2 cols): iteration,msg
+
+
rr$warnings
+
+
Empty data.table (0 rows and 2 cols): iteration,msg
+
+
+

Performance in each fold:

+
+
rr$score(measures)
+
+
   task_id learner_id resampling_id iteration    surv.graf    surv.rcll surv.cindex.uno
+    <char>     <char>        <char>     <int>        <num>        <num>           <num>
+1:    lung  surv.bart            cv         1 -0.312614598 -0.102013166       0.5869665
+2:    lung  surv.bart            cv         2 -0.103181391 -0.009579343       0.5502903
+3:    lung  surv.bart            cv         3  0.001448263  0.338851363       0.6178001
+4:    lung  surv.bart            cv         4 -0.044161171  0.003691073       0.6157215
+5:    lung  surv.bart            cv         5 -0.043129352  0.157902047       0.5688389
+Hidden columns: task, learner, resampling, prediction
+
+
+

Mean cross-validation performance:

+
+
rr$aggregate(measures)
+
+
      surv.graf       surv.rcll surv.cindex.uno 
+     -0.1003276       0.0777704       0.5879235 
+
+
+
+
+

Uncertainty Quantification in Survival Prediction

+

We will choose two patients from the test set and plot their survival prediction posterior estimates.

+

Let’s choose the patients with the worst and the best survival time:

+
+
death_times = p$truth[,1]
+sort(death_times)
+
+
 [1]  3  5  5  6  6  6  7  8  8  8  8 10 10 10 12 12 12 13 15 16 17 18 27
+
+
worst_indx = which(death_times == min(death_times))[1] # died first
+best_indx  = which(death_times == max(death_times))[1] # died last
+
+patient_ids = c(worst_indx, best_indx)
+patient_ids # which patient IDs
+
+
[1]  5 18
+
+
death_times = death_times[patient_ids]
+death_times # 1st is worst, 2nd is best
+
+
[1]  3 27
+
+
+

Subset Arrdist to only the above 2 patients:

+
+
arrd = p$distr[patient_ids]
+arrd
+
+
Arrdist(2x31x50) 
+
+
+

We choose time points (in months) for the survival estimates:

+
+
months = seq(1, 36) # 1 month - 3 years
+
+

We use the $distr interface and the $survival property to get survival probabilities from an Arrdist object as well as the quantile credible intervals (CIs). The median survival probabilities can be extracted as follows:

+
+
med = arrd$survival(months) # 'med' for median
+
+colnames(med) = paste0(patient_ids, "_med")
+med = as_tibble(med) %>% add_column(month = months)
+head(med)
+
+
# A tibble: 6 × 3
+  `5_med` `18_med` month
+    <dbl>    <dbl> <int>
+1   0.874    0.981     1
+2   0.767    0.962     2
+3   0.670    0.945     3
+4   0.569    0.927     4
+5   0.465    0.901     5
+6   0.366    0.869     6
+
+
+

We can briefly verify model’s predictions: 1st patient survival probabilities on any month are lower (worst) compared to the 2nd patient.

+

Note that subsetting an Arrdist (3d array) creates a Matdist (2d matrix), for example we can explicitly get the median survival probabilities:

+
+
matd_median = arrd[, 0.5] # median
+head(matd_median$survival(months)) # same as with `arrd`
+
+
       [,1]      [,2]
+1 0.8741127 0.9808363
+2 0.7670382 0.9621618
+3 0.6701276 0.9450867
+4 0.5688809 0.9272284
+5 0.4647686 0.9007042
+6 0.3660939 0.8687270
+
+
+

Using the mean posterior survival probabilities or the ones from the last posterior draw is also possible and can be done as follows:

+
+
matd_mean = arrd[, "mean"] # mean (if needed)
+head(matd_mean$survival(months))
+
+
       [,1]      [,2]
+1 0.8652006 0.9748463
+2 0.7533538 0.9521817
+3 0.6560050 0.9293229
+4 0.5623555 0.9051549
+5 0.4750038 0.8758896
+6 0.3815333 0.8360373
+
+
matd_50draw = arrd[, 50] # the 50th posterior draw
+head(matd_50draw$survival(months))
+
+
       [,1]      [,2]
+1 0.9178342 0.9920982
+2 0.8424195 0.9842589
+3 0.7732014 0.9764815
+4 0.7096707 0.9687656
+5 0.6029119 0.9495583
+6 0.5122132 0.9307318
+
+
+

To get the CIs we will subset the Arrdist using a quantile number (0-1), which extracts a Matdist based on the cdf. The survival function is 1 - cdf, so low and upper bounds are reversed:

+
+
low  = arrd[, 0.975]$survival(months) # 2.5% bound
+high = arrd[, 0.025]$survival(months) # 97.5% bound
+colnames(low)  = paste0(patient_ids, "_low")
+colnames(high) = paste0(patient_ids, "_high")
+low  = as_tibble(low)
+high = as_tibble(high)
+
+

The median posterior survival probabilities for the two patient of interest and the corresponding CI bounds in a tidy format are:

+
+
surv_tbl =
+  bind_cols(low, med, high) %>%
+  pivot_longer(cols = !month, values_to = "surv",
+    names_to = c("patient_id", ".value"), names_sep = "_") %>%
+  relocate(patient_id)
+surv_tbl
+
+
# A tibble: 72 × 5
+   patient_id month   low   med  high
+   <chr>      <int> <dbl> <dbl> <dbl>
+ 1 5              1 0.713 0.874 0.953
+ 2 18             1 0.929 0.981 0.996
+ 3 5              2 0.508 0.767 0.903
+ 4 18             2 0.863 0.962 0.991
+ 5 5              3 0.362 0.670 0.855
+ 6 18             3 0.801 0.945 0.985
+ 7 5              4 0.244 0.569 0.804
+ 8 18             4 0.734 0.927 0.977
+ 9 5              5 0.146 0.465 0.748
+10 18             5 0.654 0.901 0.969
+# ℹ 62 more rows
+
+
+

We draw survival curves with the uncertainty for the survival probability quantified:

+
+
my_colors = c("#E41A1C", "#4DAF4A")
+names(my_colors) = patient_ids
+
+surv_tbl %>%
+  ggplot(aes(x = month, y = med)) +
+  geom_step(aes(color = patient_id), linewidth = 1) +
+  xlab('Time (Months)') +
+  ylab('Survival Probability') +
+  geom_ribbon(aes(ymin = low, ymax = high, fill = patient_id),
+    alpha = 0.3, show.legend = F) +
+  geom_vline(xintercept = death_times[1], linetype = 'dashed', color = my_colors[1]) +
+  geom_vline(xintercept = death_times[2], linetype = 'dashed', color = my_colors[2]) +
+  theme_bw(base_size = 14) +
+  scale_color_manual(values = my_colors) +
+  scale_fill_manual(values = my_colors) +
+  guides(color = guide_legend(title = "Patient ID"))
+
+
+
+

+
Uncertainty quantification for the survival prediction of two patients in the test set using 95% credible intervals. The two vertical lines correspond to the reported time of death (in months) for the two patients.
+
+
+
+
+
+
+

Partial Dependence Plot

+

We will use a Partial Dependence Plot (PDP) (Friedman 2001) to visualize how much different are males vs females in terms of their average survival predictions across time.

+
+
+
+ +
+
+Note +
+
+
+

PDPs assume that features are independent. In our case we need to check that sex doesn’t correlate with any of the other features used for training the BART learner. Since sex is a categorical feature, we fit a linear model using as target variable every other feature in the data (\(lm(feature \sim sex)\)) and conduct an ANOVA (ANalysis Of VAriance) to get the variance explained or \(R^2\). The square root of that value is the correlation measure we want.

+
+
+
+
# code from https://christophm.github.io/interpretable-ml-book/ale.html
+mycor = function(cnames, data) {
+  x.num = data[, cnames[1], with = FALSE][[1]]
+  x.cat = data[, cnames[2], with = FALSE][[1]]
+  # R^2 = Cor(X, Y)^2 in simple linear regression
+  sqrt(summary(lm(x.num ~ x.cat))$r.squared)
+}
+
+cnames = c("sex")
+combs = expand.grid(y = setdiff(colnames(d), "sex"), x = cnames)
+combs$cor = apply(combs, 1, mycor, data = task$data()) # use the train set
+combs
+
+
          y   x        cor
+1      time sex 0.12941337
+2    status sex 0.24343282
+3       age sex 0.12216709
+4      inst sex 0.07826337
+5  meal.cal sex 0.18389545
+6 pat.karno sex 0.04132443
+7   ph.ecog sex 0.02564987
+8  ph.karno sex 0.01702471
+9   wt.loss sex 0.13431983
+
+
+

sex doesn’t correlate strongly with any other feature, so we can compute the PDP:

+
+
# create two datasets: one with males and one with females
+# all other features remain the same (use train data, 205 patients)
+d = task$data(rows = part$train) # `rows = part$test` to use the test set
+
+d$sex = 1
+task_males = as_task_surv(d, time = 'time', event = 'status', id = 'lung-males')
+d$sex = 0
+task_females = as_task_surv(d, time = 'time', event = 'status', id = 'lung-females')
+
+# make predictions
+p_males   = learner$predict(task_males)
+p_females = learner$predict(task_females)
+
+# take the median posterior survival probability
+surv_males   = p_males$distr$survival(months) # patients x times
+surv_females = p_females$distr$survival(months) # patients x times
+
+# tidy up data: average and quantiles across patients
+data_males =
+  apply(surv_males, 1, function(row) {
+    tibble(
+      low = quantile(row, probs = 0.025),
+      avg = mean(row),
+      high = quantile(row, probs = 0.975)
+    )
+  }) %>%
+  bind_rows() %>%
+  add_column(sex = 'male', month = months, .before = 1)
+
+data_females =
+  apply(surv_females, 1, function(row) {
+    tibble(
+      low = quantile(row, probs = 0.025),
+      avg = mean(row),
+      high = quantile(row, probs = 0.975)
+    )
+  }) %>%
+  bind_rows() %>%
+  add_column(sex = 'female', month = months, .before = 1)
+
+pdp_tbl = bind_rows(data_males, data_females)
+pdp_tbl
+
+
# A tibble: 72 × 5
+   sex   month    low   avg  high
+   <chr> <int>  <dbl> <dbl> <dbl>
+ 1 male      1 0.836  0.942 0.981
+ 2 male      2 0.704  0.889 0.963
+ 3 male      3 0.587  0.839 0.943
+ 4 male      4 0.488  0.788 0.924
+ 5 male      5 0.392  0.732 0.897
+ 6 male      6 0.304  0.663 0.860
+ 7 male      7 0.234  0.601 0.829
+ 8 male      8 0.172  0.550 0.799
+ 9 male      9 0.130  0.503 0.766
+10 male     10 0.0945 0.455 0.733
+# ℹ 62 more rows
+
+
+
+
my_colors = c("#E41A1C", "#4DAF4A")
+names(my_colors) = c('male', 'female')
+
+pdp_tbl %>%
+  ggplot(aes(x = month, y = avg)) +
+  geom_step(aes(color = sex), linewidth = 1) +
+  xlab('Time (Months)') +
+  ylab('Survival Probability') +
+  geom_ribbon(aes(ymin = low, ymax = high, fill = sex), alpha = 0.2, show.legend = F) +
+  theme_bw(base_size = 14) +
+  scale_color_manual(values = my_colors) +
+  scale_fill_manual(values = my_colors)
+
+
+
+

+
Friedman’s partial dependence function with 95% prediction intervals: males vs females. Females show on average larger survival estimates compared to men, across all time points. Overlapping shaded area represents men and women that have similar survival characteristics.
+
+
+
+
+
+
+ + + + +
+ +

References

+
+Bonato, Vinicius, Veerabhadran Baladandayuthapani, Bradley M. Broom, Erik P. Sulman, Kenneth D. Aldape, and Kim Anh Do. 2011. Bayesian ensemble methods for survival prediction in gene expression data.” Bioinformatics 27 (3): 359–67. https://doi.org/10.1093/BIOINFORMATICS/BTQ660. +
+
+Chipman, Hugh A, Edward I George, and Robert E McCulloch. 2010. BART: BAYESIAN ADDITIVE REGRESSION TREES.” The Annals of Applied Statistics 4 (1): 266–98. http://www.jstor.org/stable/27801587. +
+
+Friedman, Jerome H. 2001. Greedy function approximation: a gradient boosting machine.” Annals of Statistics, 1189–1232. https://doi.org/10.1214/aos/1013203451. +
+
+Sonabend, Raphael, Andreas Bender, and Sebastian Vollmer. 2022. Avoiding C-hacking when evaluating survival distribution predictions with discrimination measures.” Edited by Zhiyong Lu. Bioinformatics, July. https://doi.org/10.1093/BIOINFORMATICS/BTAC451. +
+
+Sonabend, Raphael, Florian Pfisterer, Alan Mishler, Moritz Schauer, Lukas Burk, Sumantrak Mukherjee, and Sebastian Vollmer. 2022. Flexible Group Fairness Metrics for Survival Analysis,” May. https://doi.org/10.48550/arxiv.2206.03256. +
+
+Sparapani, Rodney A., Brent R. Logan, Robert E. McCulloch, and Purushottam W. Laud. 2016. Nonparametric survival analysis using Bayesian Additive Regression Trees (BART).” Statistics in Medicine 35 (16): 2741–53. https://doi.org/10.1002/SIM.6893. +
+
+Sparapani, Rodney, Charles Spanbauer, and Robert McCulloch. 2021. Nonparametric Machine Learning and Efficient Computation with Bayesian Additive Regression Trees: The BART R Package.” Journal of Statistical Software 97 (1): 1–66. https://doi.org/10.18637/JSS.V097.I01. +
+
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/technical/2023-10-25-bart-survival/index_files/figure-html/diag-mcmc-1.png b/gallery/technical/2023-10-25-bart-survival/index_files/figure-html/diag-mcmc-1.png new file mode 100644 index 00000000..002b3896 Binary files /dev/null and b/gallery/technical/2023-10-25-bart-survival/index_files/figure-html/diag-mcmc-1.png differ diff --git a/gallery/technical/2023-10-25-bart-survival/index_files/figure-html/surv-pdp-1.png b/gallery/technical/2023-10-25-bart-survival/index_files/figure-html/surv-pdp-1.png new file mode 100644 index 00000000..cdb20c50 Binary files /dev/null and b/gallery/technical/2023-10-25-bart-survival/index_files/figure-html/surv-pdp-1.png differ diff --git a/gallery/technical/2023-10-25-bart-survival/index_files/figure-html/surv-with-uq-1.png b/gallery/technical/2023-10-25-bart-survival/index_files/figure-html/surv-with-uq-1.png new file mode 100644 index 00000000..a404e947 Binary files /dev/null and b/gallery/technical/2023-10-25-bart-survival/index_files/figure-html/surv-with-uq-1.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/cover.png b/gallery/technical/2023-10-30-tidymodels/cover.png new file mode 100644 index 00000000..800e9d9f Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/cover.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index.html b/gallery/technical/2023-10-30-tidymodels/index.html new file mode 100644 index 00000000..e820287f --- /dev/null +++ b/gallery/technical/2023-10-30-tidymodels/index.html @@ -0,0 +1,1804 @@ + + + + + + + + + + + + +Analyzing the Runtime Performance of tidymodels and mlr3 – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Analyzing the Runtime Performance of tidymodels and mlr3

+
+
+

Compare the runtime performance of tidymodels and mlr3.

+
+
+ +
+ + +
+ +
+
Author
+ +
+ +
+
Published
+
+

October 30, 2023

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Scope

+

In the realm of data science, machine learning frameworks play an important role in streamlining and accelerating the development of analytical workflows. Among these, tidymodels and mlr3 stand out as prominent tools within the R community. They provide a unified interface for data preprocessing, model training, resampling and tuning. The streamlined and accelerated development process, while efficient, typically results in a trade-off concerning runtime performance. This article undertakes a detailed comparison of the runtime efficiency of tidymodels and mlr3, focusing on their performance in training, resampling, and tuning machine learning models. Specifically, we assess the time efficiency of these frameworks in running the rpart::rpart() and ranger::ranger() models, using the Sonar dataset as a test case. Additionally, the study delves into analyzing the runtime overhead of these frameworks by comparing their performance against training the models without a framework. Through this comparative analysis, the article aims to provide valuable insights into the operational trade-offs of using these advanced machine learning frameworks in practical data science applications.

+
+
+

Setup

+

We employ the microbenchmark package to measure the time required for training, resampling, and tuning models. This benchmarking process is applied to the Sonar dataset using the rpart and ranger algorithms.

+
+
library("mlr3verse")
+library("tidymodels")
+library("microbenchmark")
+
+task = tsk("sonar")
+data = task$data()
+formula = Class ~ .
+
+

To ensure the robustness of our results, each function call within the benchmark is executed 100 times in a randomized sequence. The microbenchmark package then provides us with detailed insights, including the median, lower quartile, and upper quartile of the runtimes. To further enhance the reliability of our findings, we execute the benchmark on a cluster. Each run of microbenchmark is repeated 100 times, with different seeds applied for each iteration. Resulting in a total of 10,000 function calls of each command. The computing environment for each worker in the cluster consists of 3 cores and 12 GB of RAM. For transparency and reproducibility, the examples of the code used for this experiment are provided as snippets in the article. The complete code, along with all details of the experiment, is available in our public repository, mlr-org/mlr-benchmark.

+

It’s important to note that our cluster setup is not specifically optimized for single-core performance. Consequently, executing the same benchmark on a local machine with might yield faster results.

+
+
+

Benchmark

+
+

Train the Models

+

Our benchmark starts with the fundamental task of model training. To facilitate a direct comparison, we have structured our presentation into two distinct segments. On the left, we demonstrate the initialization of the rpart model, employing both mlr3 and tidymodels frameworks. The rpart model is a decision tree classifier, which is a simple and fast-fitting algorithm for classification tasks. Simultaneously, on the right, we turn our attention to the initialization of the ranger model, known for its efficient implementation of the random forest algorithm. Our aim is to mirror the configuration as closely as possible across both frameworks, maintaining consistency in parameters and settings.

+
# tidymodels
+tm_mod = decision_tree() %>%
+  set_engine("rpart",
+    xval = 0L) %>%
+  set_mode("classification")
+
+# mlr3
+learner = lrn("classif.rpart",
+  xval = 0L)
+# tidymodels
+tm_mod = rand_forest(trees = 1000L) %>%
+  set_engine("ranger",
+    num.threads = 1L,
+    seed = 1) %>%
+  set_mode("classification")
+
+# mlr3
+learner = lrn("classif.ranger",
+  num.trees = 1000L,
+  num.threads = 1L,
+  seed = 1,
+  verbose = FALSE,
+  predict_type = "prob")
+
+
+ +
+
+

We measure the runtime for the train functions within each framework. The result of the train function is a trained model in both frameworks. In addition, we invoke the rpart() and ranger() functions to establish a baseline for the minimum achievable runtime. This allows us to not only assess the efficiency of the train functions in each framework but also to understand how they perform relative to the base packages.

+
+
# tidymodels train
+fit(tm_mod, formula, data = data)
+
+# mlr3 train
+learner$train(task)
+
+

When training an rpart model, tidymodels demonstrates superior speed, outperforming mlr3 (Table 1). Notably, the mlr3 package requires approximately twice the time compared to the baseline.

+

A key observation from our results is the significant relative overhead when using a framework for rpart model training. Given that rpart inherently requires a shorter training time, the additional processing time introduced by the frameworks becomes more pronounced. This aspect highlights the trade-off between the convenience offered by these frameworks and their impact on runtime for quicker tasks.

+

Conversely, when we shift our focus to training a ranger model, the scenario changes (Table 2). Here, the runtime performance of ranger is strikingly similar across both tidymodels and mlr3. This equality in execution time can be attributed to the inherently longer training duration required by ranger models. As a result, the relative overhead introduced by either framework becomes minimal, effectively diminishing in the face of the more time-intensive training process. This pattern suggests that for more complex or time-consuming tasks, the choice of framework may have a less significant impact on overall runtime performance.

+
+ +
+
+
+
+
+
+
+Table 1: Average runtime in milliseconds of training rpart depending on the framework. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FrameworkLQMedianUQ
base111112
mlr3232324
tidymodels181819
+
+
+
+
+
+
+
+
+
+Table 2: Average runtime in milliseconds of training ranger depending on the framework. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FrameworkLQMedianUQ
base286322347
mlr3301335357
tidymodels310342362
+
+
+
+
+
+
+
+
+
+

Resample Sequential

+

We proceed to evaluate the runtime performance of the resampling functions within both frameworks, specifically under conditions without parallelization. This step involves the generation of resampling splits, including 3-fold, 6-fold, and 9-fold cross-validation. Additionally, we run a 100 times repeated 3-fold cross-validation.

+

We generate the same resampling splits for both frameworks. This consistency is key to ensuring that any observed differences in runtime are attributable to the frameworks themselves, rather than variations in the resampling process.

+

In our pursuit of a fair and balanced comparison, we address certain inherent differences between the two frameworks. Notably, tidymodels inherently includes scoring of the resampling results as part of its process. To align the comparison, we replicate this scoring step in mlr3, thus maintaining a level field for evaluation. Furthermore, mlr3 inherently saves predictions during the resampling process. To match this, we activate the saving of the predictions in tidymodels.

+
+
# tidymodels resample
+control = control_grid(save_pred = TRUE)
+metrics = metric_set(accuracy)
+
+tm_wf =
+  workflow() %>%
+  add_model(tm_mod) %>%
+  add_formula(formula)
+
+fit_resamples(tm_wf, folds, metrics = metrics, control = control)
+
+# mlr3 resample
+measure = msr("classif.acc")
+
+rr = resample(task, learner, resampling)
+rr$score(measure)
+
+

When resampling the fast-fitting rpart model, mlr3 demonstrates a notable edge in speed, as detailed in Table 3. In contrast, when it comes to resampling the more computationally intensive ranger models, the performance of tidymodels and mlr3 converges closely (Table 4). This parity in performance is particularly noteworthy, considering the differing internal mechanisms and optimizations of tidymodels and mlr3. A consistent trend observed across both frameworks is a linear increase in runtime proportional to the number of folds in cross-validation (Figure 1).

+
+ +
+
+
+
+
+
+
+Table 3: Average runtime in milliseconds of rpart depending on the framework and resampling strategy. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FrameworkResamplingLQMedianUQ
mlr3cv3188196210
tidymodelscv3233242257
mlr3cv6343357379
tidymodelscv6401415436
mlr3cv9500520548
tidymodelscv9568588616
mlr3rcv100155261602316777
tidymodelsrcv100164091687617527
+
+
+
+
+
+
+
+
+
+Table 4: Average runtime in milliseconds of ranger depending on the framework and resampling strategy. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FrameworkResamplingLQMedianUQ
mlr3cv392310041062
tidymodelscv39169811023
mlr3cv6199021592272
tidymodelscv6208921762239
mlr3cv9307432793441
tidymodelscv9326033733453
mlr3rcv100859098864291381
tidymodelsrcv100878288882289843
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+Figure 1: Average runtime, measured in milliseconds, for cross-validations using rpart (displayed on the left) and ranger (on the right). The comparison encompasses variations across different frameworks and the number of folds in the cross-validation. +
+
+
+
+
+
+
+

Resample Parallel

+

We conducted a second set of resampling function tests, this time incorporating parallelization to explore its impact on runtime efficiency. In this phase, we utilized doFuture and doParallel as the primary parallelization packages for tidymodels, recognizing their robust support and compatibility. Meanwhile, for mlr3, the future package was employed to facilitate parallel processing.

+

Our findings, as presented in the respective tables (Table 5 and Table 6), reveal interesting dynamics about parallelization within the frameworks. When the number of folds in the resampling process is doubled, we observe only a marginal increase in the average runtime. This pattern suggests a significant overhead associated with initializing the parallel workers, a factor that becomes particularly influential in the overall efficiency of the parallelization process.

+

In the case of the rpart model, the parallelization overhead appears to outweigh the potential speedup benefits, as illustrated in the left section of Figure 2. This result indicates that for less complex models like rpart, where individual training times are relatively short, the initialization cost of parallel workers may not be sufficiently offset by the reduced processing time per fold.

+

Conversely, for the ranger model, the utilization of parallelization demonstrates a clear advantage over the sequential version, as evidenced in the right section of Figure 2. This finding underscores that for more computationally intensive models like ranger, which have longer individual training times, the benefits of parallel processing significantly overcome the initial overhead of worker setup. This differentiation highlights the importance of considering the complexity and inherent processing time of models when deciding to implement parallelization strategies in these frameworks.

+
+ +
+
+
+
+
+
+
+Table 5: Average runtime in milliseconds of mlr3 with future and rpart depending on the resampling strategy. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ResamplingLQMedianUQ
cv3625655703
cv6738771817
cv9831875923
rcv100862090439532
+
+
+
+
+
+
+
+
+
+Table 6: Average runtime in milliseconds of mlr3 with future and ranger depending on the resampling strategy. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ResamplingLQMedianUQ
cv3836884943
cv6120012491314
cv9157716341706
rcv100320473248333022
+
+
+
+
+
+
+
+

When paired with doFuture, tidymodels exhibits significantly slower runtime compared to the mlr3 package utilizing future (Table 7 and Table 8). We observed that tidymodels exports more data to the parallel workers, which notably exceeds that of mlr3. This substantial difference in data export could plausibly account for the observed slower runtime when using tidymodels on small tasks.

+
+ +
+
+
+
+
+
+
+Table 7: Average runtime in milliseconds of tidymodels with doFuture and rpart depending on the resampling strategy. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ResamplingLQMedianUQ
cv3277828173019
cv6280828563033
cv9293529753170
rcv100915493029489
+
+
+
+
+
+
+
+
+
+Table 8: Average runtime in milliseconds of tidymodels with doFuture and ranger depending on the resampling strategy. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ResamplingLQMedianUQ
cv3298230463234
cv6328233663543
cv9356836953869
rcv100275462784328166
+
+
+
+
+
+
+
+

The utilization of the doParallel package demonstrates a notable improvement in handling smaller resampling tasks. In these scenarios, the resampling process consistently outperforms the mlr3 framework in terms of speed. However, it’s important to note that even with this enhanced performance, the doParallel package does not always surpass the efficiency of the sequential version, especially when working with the rpart model. This specific observation is illustrated in the left section of Figure 2.

+
+ +
+
+
+
+
+
+
+Table 9: Average runtime in milliseconds of tidymodels with doParallel and rpart depending on the resampling strategy. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ResamplingLQMedianUQ
cv3557649863
cv6602714910
cv9661772968
rcv100106091082011071
+
+
+
+
+
+
+
+
+
+Table 10: Average runtime in milliseconds of tidymodels with doParallel and ranger depending on the resampling strategy. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ResamplingLQMedianUQ
cv3684756948
cv6100710991272
cv9136014611625
rcv100312053148631793
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+Figure 2: Average runtime, measured in milliseconds, for cross-validations using rpart (displayed on the left) and ranger (on the right). The comparison encompasses variations across different frameworks, the number of folds in the cross-validation, and the implementation of parallelization. +
+
+
+
+
+

In the context of repeated cross-validation, our findings underscore the efficacy of parallelization (Figure 3). Across all frameworks tested, the adoption of parallel processing techniques yields a significant increase in speed. This enhancement is particularly noticeable in larger resampling tasks, where the demands on computational resources are more substantial.

+

Interestingly, within these more extensive resampling scenarios, the doFuture package emerges as a more efficient option compared to doParallel. This distinction is important, as it highlights the relative strengths of different parallelization packages under varying workload conditions. While doParallel shows proficiency in smaller tasks, doFuture demonstrates its capability to handle larger, more complex resampling processes with greater speed and efficiency.

+
+
+
+
+
+ +
+
+Figure 3: Average runtime, measured in seconds, of a 100 times repeated 3-fold cross-validation using rpart (displayed on the left) and ranger (on the right). The comparison encompasses variations across different frameworks and the implementation of parallelization. +
+
+
+
+
+
+
+

Tune Sequential

+

We then shift our focus to assessing the runtime performance of the tuning functions. In this phase, the tidymodels package is utilized to evaluate a predefined grid, comprising a specific set of hyperparameter configurations. To ensure a balanced and comparable analysis, we employ the "design_points" tuner from the mlr3tuning package. This approach allows us to evaluate the same grid within the mlr3 framework, maintaining consistency across both platforms. The grid used for this comparison contains 200 hyperparameter configurations each, for both the rpart and ranger models. This approach helps us to understand how each framework handles the optimization of model hyperparameters, a key aspect of building effective and efficient machine learning models.

+
# tidymodels
+tm_mod = decision_tree(
+  cost_complexity = tune()) %>%
+  set_engine("rpart",
+    xval = 0) %>%
+  set_mode("classification")
+
+tm_design = data.table(
+  cost_complexity = seq(0.1, 0.2, length.out = 200))
+
+# mlr3
+learner = lrn("classif.rpart",
+  xval = 0,
+  cp = to_tune())
+
+mlr3_design = data.table(
+  cp = seq(0.1, 0.2, length.out = 200))
+# tidymodels
+tm_mod = rand_forest(
+  trees = tune()) %>%
+  set_engine("ranger",
+    num.threads = 1L,
+    seed = 1) %>%
+  set_mode("classification")
+
+tm_design = data.table(
+  trees = seq(1000, 1199))
+
+# mlr3
+learner = lrn("classif.ranger",
+  num.trees = to_tune(1, 10000),
+  num.threads = 1L,
+  seed = 1,
+  verbose = FALSE,
+  predict_type = "prob")
+
+mlr3_design = data.table(
+  num.trees = seq(1000, 1199))
+
+
+ +
+
+

We measure the runtime of the tune functions within each framework. Both the tidymodels and mlr3 frameworks are tasked with identifying the optimal hyperparameter configuration.

+
+
# tidymodels tune
+tune::tune_grid(
+  tm_wf,
+  resamples = resamples,
+  grid = design,
+  metrics = metrics)
+
+# mlr3 tune
+tuner = tnr("design_points", design = design, batch_size = nrow(design))
+mlr3tuning::tune(
+  tuner = tuner,
+  task = task,
+  learner = learner,
+  resampling = resampling,
+  measures = measure,
+  store_benchmark_result = FALSE)
+
+

In our sequential tuning tests, mlr3 demonstrates a notable advantage in terms of speed. This finding is clearly evidenced in our results, as shown in Table Table 11 for the rpart model and Table Table 12 for the ranger model. The faster performance of mlr3 in these sequential runs highlights its efficiency in handling the tuning process without parallelization.

+
+ +
+
+
+
+
+
+
+Table 11: Average runtime in seconds of tuning 200 points of rpart depending on the framework. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
FrameworkLQMedianUQ
mlr3272728
tidymodels373739
+
+
+
+
+
+
+
+
+
+Table 12: Average runtime in seconds of tuning 200 points of ranger depending on the framework. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
FrameworkLQMedianUQ
mlr3167171175
tidymodels194195196
+
+
+
+
+
+
+
+
+
+

Tune Parallel

+

Concluding our analysis, we proceed to evaluate the runtime performance of the tune functions, this time implementing parallelization to enhance efficiency. For these runs, parallelization is executed on 3 cores.

+

In the case of mlr3, we opt for the largest possible chunk size. This strategic choice means that all points within the tuning grid are sent to the workers in a single batch, effectively minimizing the overhead typically associated with parallelization. This approach is crucial in reducing the time spent in distributing tasks across multiple cores, thereby streamlining the tuning process. On the other hand, the tidymodels package also operates with the same chunk size, but this setting is determined and managed internally within the framework.

+

By conducting these parallelization tests, we aim to provide a deeper understanding of how each framework handles the distribution and management of computational tasks during the tuning process, particularly in a parallel computing environment. This final set of measurements is important in painting a complete picture of the runtime performance of the tune functions across both tidymodels and mlr3 under different operational settings.

+
+
options("mlr3.exec_chunk_size" = 200)
+
+

Our analysis of the parallelized tuning functions reveals that the runtimes for mlr3 and tidymodels are remarkably similar. However, subtle differences emerge upon closer inspection. For instance, the mlr3 package exhibits a slightly faster performance when tuning the rpart model, as indicated in Table 13. In contrast, it falls marginally behind tidymodels in tuning the ranger model, as shown in Table 14.

+

Interestingly, when considering the specific context of a 3-fold cross-validation, the doParallel package outperforms doFuture in terms of speed, as demonstrated in Figure 4. This outcome suggests that the choice of parallelization package can have a significant impact on tuning efficiency, particularly in scenarios with a smaller number of folds.

+

A key takeaway from our study is the clear benefit of enabling parallelization, regardless of the chosen framework-backend combination. Activating parallelization consistently enhances performance, making it a highly recommended strategy for tuning machine learning models, especially in tasks involving extensive hyperparameter exploration or larger datasets. This conclusion underscores the value of parallel processing in modern machine learning workflows, offering a practical solution for accelerating model tuning across various computational settings.

+
+ +
+
+
+
+
+
+
+Table 13: Average runtime in seconds of tuning 200 points of rpart depending on the framework. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FrameworkBackendLQMedianUQ
mlr3future111212
tidymodelsdoFuture171717
tidymodelsdoParallel131313
+
+
+
+
+
+
+
+
+
+Table 14: Average runtime in seconds of tuning 200 points of ranger depending on the framework. +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FrameworkBackendLQMedianUQ
mlr3future545555
tidymodelsdoFuture585859
tidymodelsdoParallel545455
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+Figure 4: Average runtime, measured in seconds, of a tuning 200 hyperparameter configurations of rpart (displayed on the left) and ranger (on the right). The comparison encompasses variations across different frameworks and the implementation of parallelization. +
+
+
+
+
+
+
+
+

Conclusion

+

Our analysis reveals that both tidymodels and mlr3 exhibit comparable runtimes across key processes such as training, resampling, and tuning, each displaying its own set of strengths and efficiencies.

+

A notable observation is the relative overhead associated with using either framework, particularly when working with fast-fitting models like rpart. In these cases, the additional processing time introduced by the frameworks is more pronounced due to the inherently short training time of rpart models. This results in a higher relative overhead, reflecting the trade-offs between the convenience of a comprehensive framework and the directness of more basic approaches.

+

Conversely, when dealing with slower-fitting models such as ranger, the scenario shifts. For these more time-intensive models, the relative overhead introduced by the frameworks diminishes significantly. In such instances, the extended training times of the models absorb much of the frameworks’ inherent overhead, rendering it relatively negligible.

+

In summary, while there is no outright winner in terms of overall performance, the decision to use tidymodels or mlr3 should be informed by the specific requirements of the task at hand.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/fig-resample-parallel-1.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/fig-resample-parallel-1.png new file mode 100644 index 00000000..fa8da3c4 Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/fig-resample-parallel-1.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/fig-resample-parallel-2-1.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/fig-resample-parallel-2-1.png new file mode 100644 index 00000000..6de1a6b6 Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/fig-resample-parallel-2-1.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/fig-resample-sequential-1.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/fig-resample-sequential-1.png new file mode 100644 index 00000000..9802a328 Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/fig-resample-sequential-1.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/fig-tune-parallel-1.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/fig-tune-parallel-1.png new file mode 100644 index 00000000..7068854d Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/fig-tune-parallel-1.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/resample-parallel-2-1.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/resample-parallel-2-1.png new file mode 100644 index 00000000..e4d84563 Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/resample-parallel-2-1.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-10-1.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-10-1.png new file mode 100644 index 00000000..9d4145f7 Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-10-1.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-17-1.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-17-1.png new file mode 100644 index 00000000..bf1957ed Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-17-1.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-17-2.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-17-2.png new file mode 100644 index 00000000..ab1dad59 Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-17-2.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-17-3.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-17-3.png new file mode 100644 index 00000000..a5b22148 Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-17-3.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-17-4.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-17-4.png new file mode 100644 index 00000000..f86c213e Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-17-4.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-18-1.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-18-1.png new file mode 100644 index 00000000..e4d84563 Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-18-1.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-18-2.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-18-2.png new file mode 100644 index 00000000..e1e70308 Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-18-2.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-23-1.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-23-1.png new file mode 100644 index 00000000..f698f4c4 Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-23-1.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-23-2.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-23-2.png new file mode 100644 index 00000000..564775be Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-23-2.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-24-1.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-24-1.png new file mode 100644 index 00000000..9451b1e9 Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-24-1.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-24-2.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-24-2.png new file mode 100644 index 00000000..564775be Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-24-2.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-28-1.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-28-1.png new file mode 100644 index 00000000..fd6f787e Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-28-1.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-31-1.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-31-1.png new file mode 100644 index 00000000..7afc888e Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-31-1.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-31-2.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-31-2.png new file mode 100644 index 00000000..61cf919a Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-31-2.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-32-1.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-32-1.png new file mode 100644 index 00000000..fd6f787e Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-32-1.png differ diff --git a/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-32-2.png b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-32-2.png new file mode 100644 index 00000000..61cf919a Binary files /dev/null and b/gallery/technical/2023-10-30-tidymodels/index_files/figure-html/unnamed-chunk-32-2.png differ diff --git a/gallery/technical/2023-12-21-time-constraints/cover.jpg b/gallery/technical/2023-12-21-time-constraints/cover.jpg new file mode 100644 index 00000000..3c062add Binary files /dev/null and b/gallery/technical/2023-12-21-time-constraints/cover.jpg differ diff --git a/gallery/technical/2023-12-21-time-constraints/index.html b/gallery/technical/2023-12-21-time-constraints/index.html new file mode 100644 index 00000000..ba91505d --- /dev/null +++ b/gallery/technical/2023-12-21-time-constraints/index.html @@ -0,0 +1,873 @@ + + + + + + + + + + + + +Time constraints in the mlr3 ecosystem – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+

Time constraints in the mlr3 ecosystem

+
+
+

Set time limits for learners, tuning and nested resampling.

+
+
+ +
+ + +
+ +
+
Author
+ +
+ +
+
Published
+
+

December 21, 2023

+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + +
+

Scope

+

Setting time limits is an important consideration when tuning unreliable or unstable learning algorithms and when working on shared computing resources. The mlr3 ecosystem provides several mechanisms for setting time constraints for individual learners, tuning processes, and nested resampling.

+
+
+

Learner

+

This section demonstrates how to impose time constraints using a support vector machine (SVM) as an illustrative example.

+
+
library(mlr3verse)
+
+learner = lrn("classif.svm")
+
+

Applying timeouts to the $train() and $predict() functions is essential for managing learners that may operate indefinitely. These time constraints are set independently for both the training and prediction stages. Generally, training a learner consumes more time than prediction. Certain learners, like k-nearest neighbors, lack a distinct training phase and require a timeout only during prediction. For the SVM’s training, we set a 10-second limit.

+
+
learner$timeout = c(train = 10, predict = Inf)
+
+

To effectively terminate the process if necessary, it’s important to run the training and prediction within a separate R process. The callr package is recommended for this encapsulation, as it tends to be more reliable than the evaluate package, especially for terminating externally compiled code.

+
+
learner$encapsulate = c(train = "callr", predict = "callr")
+
+

Note that using callr increases the runtime due to the overhead of starting an R process. Additionally, it’s advisable to specify a fallback learner, such as "classif.featureless", to provide baseline predictions in case the primary learner is terminated.

+
+
learner$fallback = lrn("classif.featureless")
+
+

These time constraints are now integrated into the training, resampling, and benchmarking processes. For more information on encapsulation and fallback learners, see the mlr3book. The next section will focus on setting time limits for the entire tuning process.

+
+
+

Tuning

+

When working with high-performance computing clusters, jobs are often bound by strict time constraints. Exceeding these limits results in the job being terminated and the loss of any results generated. Therefore, it’s important to ensure that the tuning process is designed to adhere to these time constraints.

+

The trm("runtime") controls the duration of the tuning process. We must take into account that the terminator can only check if the time limit is reached between batches. We must therefore set the time lower than the runtime of the job. How much lower depends on the runtime or time limit of the individual learners. The last batch should be able to finish before the time limit of the cluster is reached.

+
+
terminator = trm("run_time", secs = 60)
+
+instance = ti(
+  task = tsk("sonar"),
+  learner = learner,
+  resampling = rsmp("cv", folds = 3),
+  measures = msr("classif.ce"),
+  terminator = terminator
+)
+
+

With these settings, our tuning operation is configured to run for 60 seconds, while individual learners are set to terminate after 10 seconds. This approach ensures the tuning process is efficient and adheres to the constraints imposed by the high-performance computing cluster.

+
+
+

Nested Resampling

+

When using nested resampling, time constraints become more complex as they are applied across various levels. As before, the time limit for an individual learner during the tuning is set with $timeout. The time limit for the tuning processes in the auto tuners is controlled with the trm("runtime"). It’s important to note that once the auto tuner enters the final phase of fitting the model and making predictions on the outer test set, the time limit governed by the terminator no longer applies. Additionally, the time limit previously set on the learner is temporarily deactivated, allowing the auto tuner to complete its task uninterrupted. However, a separate time limit can be assigned to each auto tuner using $timeout. This limit encompasses not only the tuning phase but also the time required for fitting the final model and predictions on the outer test set.

+

The best way to show this is with an example. We set the time limit for an individual learner to 10 seconds.

+
+
learner$timeout = c(train = 10, predict = Inf)
+learner$encapsulate = c(train = "callr", predict = "callr")
+learner$fallback = lrn("classif.featureless")
+
+

Next, we give each auto tuner 60 seconds to finish the tuning process.

+
+
terminator = trm("run_time", secs = 60)
+
+

Furthermore, we impose a 120-second limit for resampling each auto tuner. This effectively divides the time allocation, with around 60 seconds for tuning and another 60 seconds for final model fitting and predictions on the outer test set.

+
+
at = auto_tuner(
+  tuner = tnr("random_search"),
+  learner = learner,
+  resampling = rsmp("cv", folds = 3),
+  measure = msr("classif.ce"),
+  terminator = trm("run_time", secs = 60)
+)
+
+at$timeout = c(train = 100, predict = 20)
+at$encapsulate = c(train = "callr", predict = "callr")
+at$fallback = lrn("classif.featureless")
+
+

In total, the entire nested resampling process is designed to be completed within 10 minutes (120 seconds multiplied by 5 folds).

+
+
rr = resample(task, at, rsmp("cv", folds = 5))
+
+
+
+

Conclusion

+

We delved into the setting of time constraints across different levels in the mlr3 ecosystem. From individual learners to the complexities of nested resampling, we’ve seen how effectively managing time limits can significantly enhance the efficiency and reliability of machine learning workflows. By utilizing the trm("runtime") for tuning processes and setting $timeout for individual learners and auto tuners, we can ensure that our machine learning tasks are not only effective but also adhere to the practical time constraints of shared computational resources. For more information, see also the error handling section in the mlr3book.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/graphs.html b/graphs.html new file mode 100644 index 00000000..b33fbb1e --- /dev/null +++ b/graphs.html @@ -0,0 +1,707 @@ + + + + + + + + + +graphs – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + +
+ + + + +
+

Graphs

+

Graphs are predefined arrangements of PipeOp objects from the mlr3pipelines package. The goal is to simplify some popular operations which usually consist of multiple steps.

+
+
+
+ +
+
+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/images/book.jpeg b/images/book.jpeg new file mode 100644 index 00000000..6292796f Binary files /dev/null and b/images/book.jpeg differ diff --git a/images/favicon.ico b/images/favicon.ico new file mode 100644 index 00000000..04638ecb Binary files /dev/null and b/images/favicon.ico differ diff --git a/images/mlr3_ecosystem.svg b/images/mlr3_ecosystem.svg new file mode 100644 index 00000000..86eb4ad0 --- /dev/null +++ b/images/mlr3_ecosystem.svg @@ -0,0 +1,1516 @@ + + + + + + + + + Feature Selection + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³fselect + + + Wrapper-based FS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³filters + + + Filter-based FS + + + + + + Other + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³batchmark + + + mlr3 - batchtools connector + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³misc + + + Devel Helper Functions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³measures + + + Performance Measures + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³verse + + + Meta-package + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rush + + + Asynchronous Parallellization + + + + + + Data + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³db + + + Database Backends + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³oml + + + OpenML Connection + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³data + + + Example datasets + + + + + + Learners + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³extralearners + + + Additional learners + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³learners + + + Core learners for mlr3 + + + + + + + + + Analysis + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³summary + + + Model Summaries + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³viz + + + Visualization + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³benchmark + + + Tools for benchmarking + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³inferr + + + Inference on the Generalization Error + + + + + + Pipelines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³pipelines + + + Preprocessing, pipelines & ensembles + + + + + + Special Tasks & Targets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³fda + + + Functional Data Analysis + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³cluster + + + Cluster Analysis + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³forecast + + + Time Series Forecasting & Resampling + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³spatiotempcv + + + Spatiotemporal resampling + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³spatial + + + Spatial prediction support + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³proba + + + Probabilistic Learning & Survival Analysis + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³fairness + + + Fairness in Machine Learning + + + + + + + + + + Core + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³ + + + tasks, learners, train-test-eval, + resample, benchmark + + + + + + + + + + + + + + + + + + + + + + Tuning & Optimization + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + miesmuschel + + + Flexible Mixed Integer + Evolutionary Strategies + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³hyperband + + + Hyperband Parameter Tuning + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³tuning + + + Hyperparameter Tuning + + + + + + + + + + + + paradox + Parameter Sets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³mbo + + + Bayesian Optimization + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr3tuningspaces + + + Tuning spaces for mlr3 learners + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr3automl + + + Automatic Machine Learning + + + + + + + + + bbotk + Black-Box Optimization + + + + + + + + + + + + + + + + Maturing + Planned + Stable + + + + + + + + + + + + + + + + + + + + + + + + + + + + mlr³torch + + + Deep Learning Framework + + + + + + + + + + diff --git a/images/team/bernd.jpg b/images/team/bernd.jpg new file mode 100644 index 00000000..3bb06ef7 Binary files /dev/null and b/images/team/bernd.jpg differ diff --git a/images/team/florian.jpg b/images/team/florian.jpg new file mode 100644 index 00000000..80cd5de4 Binary files /dev/null and b/images/team/florian.jpg differ diff --git a/images/team/john.jpg b/images/team/john.jpg new file mode 100644 index 00000000..df623de0 Binary files /dev/null and b/images/team/john.jpg differ diff --git a/images/team/larsko.jpg b/images/team/larsko.jpg new file mode 100644 index 00000000..82d9e1d4 Binary files /dev/null and b/images/team/larsko.jpg differ diff --git a/images/team/lennart.jpg b/images/team/lennart.jpg new file mode 100644 index 00000000..15090897 Binary files /dev/null and b/images/team/lennart.jpg differ diff --git a/images/team/marc.jpg b/images/team/marc.jpg new file mode 100644 index 00000000..1f06fb64 Binary files /dev/null and b/images/team/marc.jpg differ diff --git a/images/team/michel.png b/images/team/michel.png new file mode 100644 index 00000000..72ee702e Binary files /dev/null and b/images/team/michel.png differ diff --git a/images/team/patrick.jpg b/images/team/patrick.jpg new file mode 100755 index 00000000..b7a56cd2 Binary files /dev/null and b/images/team/patrick.jpg differ diff --git a/images/team/raphael.png b/images/team/raphael.png new file mode 100644 index 00000000..70c5190a Binary files /dev/null and b/images/team/raphael.png differ diff --git a/images/team/sebastian.jpg b/images/team/sebastian.jpg new file mode 100755 index 00000000..f539e5b2 Binary files /dev/null and b/images/team/sebastian.jpg differ diff --git a/index.html b/index.html new file mode 100644 index 00000000..671b75a3 --- /dev/null +++ b/index.html @@ -0,0 +1,846 @@ + + + + + + + + + +mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + +
+ + + + +
+

mlr3: Machine Learning in R

+
+

The mlr3 ecosystem is the framework for machine learning in R.

+

An open-source collection of R packages providing a unified interface for machine learning in the R language. Successor of mlr.

+
+
+
+
+
+ + + +
+A scientifically designed and easy to learn interface. +
+
+
+ + + +
+More than 100 connected machine learning algorithms. +
+
+
+ + + +
+Light on dependencies. +
+
+
+ + + +
+Convenient parallelization with the future package. +
+
+
+ + + +
+State-of-the-art optimization algorithms. +
+
+
+ + + +
+Dataflow programming with pipelines. +
+
+
+
+
+

Get Started

+

There are many packages in the mlr3 ecosystem that you may want to use. You can install the full mlr3 universe at once with:

+
+
install.packages("mlr3verse")
+
+

You can also use our Docker images.

+
+
+

Resources

+

+

Our book “Applied Machine Learning Using mlr3 in R” is the central entry point to mlr3 ecosystem. This essential guide covers key aspects of machine learning, from building and evaluating predictive models to advanced techniques like hyperparameter tuning for peak performance. It delves into constructing comprehensive machine learning pipelines, encompassing data pre-processing, modeling, and prediction aggregation.

+

The book is primarily aimed at researchers, practitioners, and graduate students who use machine learning or who are interested in using it. It can be used as a textbook for an introductory or advanced machine learning class that uses R, as a reference for people who work with machine learning methods, and in industry for exploratory experiments in machine learning.

+

In addition to the book, there are many other resources to learn more about mlr3. The gallery contains a collection of case studies that demonstrate the functionality of mlr3. The cheatsheets provide a quick overview of the most important functions. The resources section contains links to talks, courses, and other material.

+
+
+

Examples

+
+
+
+
+

+ +Basic Machine Learning +

+

Get to know the basic building blocks of machine learning in mlr3. Train your first learner and estimate its performance with resampling. Compare the performance of learners with benchmarking.

+ + + +
+
+

+ +Optimization +

+

Optimize the hyperparameters of a classification tree on the Palmer Penguins data set. Become familiar with search spaces and transformations. Fit a final model with optimized hyperparameters for predicting new data.

+ + + +
+
+

+ +Pipelines +

+

Build a preprocessing pipeline for missing data in the German Credit data set. Optimize the parameters of the pipeline and stack multiple learners into an ensemble model. Learn about techniques to tackle challenging data sets.

+ + + +
+
+

+ +Feature Selection +

+

Start a feature selection on the Titanic data set. Learn about different optimization algorithms and fit a final model. Estimate the performance of the optimized feature set with nested resampling.

+ + + +
+
+
+
+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/learners.html b/learners.html new file mode 100644 index 00000000..786baa6b --- /dev/null +++ b/learners.html @@ -0,0 +1,809 @@ + + + + + + + + + +learners – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + +
+ + + + +
+

Learners

+

To keep the dependencies on other packages reasonable, the base package mlr3 only ships with with regression and classification trees from the rpart package and some learners for debugging. A subjective selection of implementations for essential ML algorithms can be found in mlr3learners package. Survival learners are provided by mlr3proba, cluster learners via mlr3cluster. Additional learners, including some learners which are not yet to be considered stable or which are not available on CRAN, are connected via the mlr3extralearners package. For neural networks, see the mlr3torch extension.

+
+
+
+ +
+
+
+

Example Usage

+

Fit a classification tree on the Wisconsin Breast Cancer Data Set and predict on left-out observations.

+
+
library("mlr3verse")
+
+# retrieve the task
+task = tsk("breast_cancer")
+
+# split into two partitions
+split = partition(task)
+
+# retrieve a learner
+learner = lrn("classif.rpart", keep_model = TRUE, predict_type = "prob")
+
+# fit decision tree
+learner$train(task, split$train)
+
+# access learned model
+learner$model
+
+
n= 457 
+
+node), split, n, loss, yval, (yprob)
+      * denotes terminal node
+
+ 1) root 457 160 benign (0.35010941 0.64989059)  
+   2) cell_size=3,4,5,6,7,8,9,10 179  26 malignant (0.85474860 0.14525140)  
+     4) bare_nuclei=3,4,5,6,7,8,9,10 148   8 malignant (0.94594595 0.05405405) *
+     5) bare_nuclei=1,2 31  13 benign (0.41935484 0.58064516)  
+      10) cell_size=4,5,6,7,8,9,10 14   2 malignant (0.85714286 0.14285714) *
+      11) cell_size=1,2,3 17   1 benign (0.05882353 0.94117647) *
+   3) cell_size=1,2 278   7 benign (0.02517986 0.97482014) *
+
+
# predict on data frame with new data
+predictions = learner$predict_newdata(task$data(split$test))
+
+# predict on subset of the task
+predictions = learner$predict(task, split$test)
+
+# inspect predictions
+predictions
+
+
<PredictionClassif> for 226 observations:
+    row_ids     truth  response prob.malignant prob.benign
+          2    benign malignant     0.94594595  0.05405405
+          3    benign    benign     0.02517986  0.97482014
+          4    benign malignant     0.94594595  0.05405405
+---                                                       
+        665 malignant malignant     0.94594595  0.05405405
+        676 malignant malignant     0.94594595  0.05405405
+        682 malignant malignant     0.94594595  0.05405405
+
+
predictions$score(msr("classif.auc"))
+
+
classif.auc 
+  0.9476879 
+
+
autoplot(predictions, type = "roc")
+
+
+
+

+
+
+
+
+ + +
+
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/learners_files/figure-html/unnamed-chunk-4-1.png b/learners_files/figure-html/unnamed-chunk-4-1.png new file mode 100644 index 00000000..cfbe0300 Binary files /dev/null and b/learners_files/figure-html/unnamed-chunk-4-1.png differ diff --git a/listings.json b/listings.json new file mode 100644 index 00000000..70ea12ed --- /dev/null +++ b/listings.json @@ -0,0 +1,167 @@ +[ + { + "listing": "/gallery.html", + "items": [ + "/gallery/technical/2023-12-21-time-constraints/index.html", + "/gallery/technical/2023-10-30-tidymodels/index.html", + "/gallery/technical/2023-10-25-bart-survival/index.html", + "/gallery/technical/2023-02-27-land-cover-classification/index.html", + "/gallery/optimization/2023-02-07-recursive-feature-elimination/index.html", + "/gallery/optimization/2023-02-01-shadow-variable-search/index.html", + "/gallery/optimization/2023-01-31-default-configuration/index.html", + "/gallery/optimization/2023-01-16-hyperband-subsampling/index.html", + "/gallery/optimization/2023-01-16-hotstart/index.html", + "/gallery/optimization/2023-01-15-hyperband-xgboost/index.html", + "/gallery/technical/2022-12-22-mlr3viz/index.html", + "/gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/index.html", + "/gallery/optimization/2022-11-04-early-stopping-with-xgboost/index.html", + "/gallery/optimization/2021-07-06-introduction-to-mlr3tuningspaces/index.html", + "/gallery/optimization/2021-03-12-practical-tuning-series-tuning-and-parallel-processing/index.html", + "/gallery/optimization/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index.html", + "/gallery/optimization/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/index.html", + "/gallery/optimization/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/index.html", + "/gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html", + "/gallery/optimization/2021-01-19-integer-hyperparameters-in-tuners-for-real-valued-search-spaces/index.html", + "/gallery/optimization/2020-09-14-mlr3fselect-basic/index.html", + "/gallery/optimization/2020-10-14-threshold-tuning/index.html", + "/gallery/basic/2021-01-20-keras/index.html", + "/gallery/pipelines/2020-09-11-liver-patient-classification/index.html", + "/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index.html", + "/gallery/technical/2020-08-13-a-production-example-using-plumber-and-docker/index.html", + "/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/index.html", + "/gallery/basic/2020-05-04-moneyball/index.html", + "/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index.html", + "/gallery/pipelines/2020-04-27-tuning-stacking/index.html", + "/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index.html", + "/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index.html", + "/gallery/pipelines/2020-04-18-regression-chains/index.html", + "/gallery/basic/2020-03-30-stratification-blocking/index.html", + "/gallery/basic/2020-03-30-imbalanced-data/index.html", + "/gallery/basic/2020-03-18-iris-mlr3-basics/index.html", + "/gallery/pipelines/2020-03-12-intro-pipelines-titanic/index.html", + "/gallery/basic/2020-03-11-basics-german-credit/index.html", + "/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index.html", + "/gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html", + "/gallery/basic/2020-02-25-remove-correlated-features/index.html", + "/gallery/pipelines/2020-02-01-tuning-multiplexer/index.html", + "/gallery/basic/2020-01-30-impute-missing-levels/index.html", + "/gallery/basic/2020-01-31-encode-factors-for-xgboost/index.html", + "/gallery/basic/2020-01-30-house-prices-in-king-county/index.html" + ] + }, + { + "listing": "/gallery-all.html", + "items": [ + "/gallery/technical/2023-12-21-time-constraints/index.html", + "/gallery/technical/2023-10-30-tidymodels/index.html", + "/gallery/technical/2023-10-25-bart-survival/index.html", + "/gallery/technical/2023-02-27-land-cover-classification/index.html", + "/gallery/optimization/2023-02-07-recursive-feature-elimination/index.html", + "/gallery/optimization/2023-02-01-shadow-variable-search/index.html", + "/gallery/optimization/2023-01-31-default-configuration/index.html", + "/gallery/optimization/2023-01-16-hyperband-subsampling/index.html", + "/gallery/optimization/2023-01-16-hotstart/index.html", + "/gallery/optimization/2023-01-15-hyperband-xgboost/index.html", + "/gallery/technical/2022-12-22-mlr3viz/index.html", + "/gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/index.html", + "/gallery/optimization/2022-11-04-early-stopping-with-xgboost/index.html", + "/gallery/optimization/2021-07-06-introduction-to-mlr3tuningspaces/index.html", + "/gallery/optimization/2021-03-12-practical-tuning-series-tuning-and-parallel-processing/index.html", + "/gallery/optimization/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index.html", + "/gallery/optimization/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/index.html", + "/gallery/optimization/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/index.html", + "/gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html", + "/gallery/optimization/2021-01-19-integer-hyperparameters-in-tuners-for-real-valued-search-spaces/index.html", + "/gallery/optimization/2020-09-14-mlr3fselect-basic/index.html", + "/gallery/optimization/2020-10-14-threshold-tuning/index.html", + "/gallery/basic/2021-01-20-keras/index.html", + "/gallery/pipelines/2020-09-11-liver-patient-classification/index.html", + "/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index.html", + "/gallery/technical/2020-08-13-a-production-example-using-plumber-and-docker/index.html", + "/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/index.html", + "/gallery/basic/2020-05-04-moneyball/index.html", + "/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index.html", + "/gallery/pipelines/2020-04-27-tuning-stacking/index.html", + "/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index.html", + "/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index.html", + "/gallery/pipelines/2020-04-18-regression-chains/index.html", + "/gallery/basic/2020-03-30-stratification-blocking/index.html", + "/gallery/basic/2020-03-30-imbalanced-data/index.html", + "/gallery/basic/2020-03-18-iris-mlr3-basics/index.html", + "/gallery/pipelines/2020-03-12-intro-pipelines-titanic/index.html", + "/gallery/basic/2020-03-11-basics-german-credit/index.html", + "/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index.html", + "/gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html", + "/gallery/basic/2020-02-25-remove-correlated-features/index.html", + "/gallery/pipelines/2020-02-01-tuning-multiplexer/index.html", + "/gallery/basic/2020-01-30-impute-missing-levels/index.html", + "/gallery/basic/2020-01-31-encode-factors-for-xgboost/index.html", + "/gallery/basic/2020-01-30-house-prices-in-king-county/index.html" + ] + }, + { + "listing": "/gallery-all-optimization.html", + "items": [ + "/gallery/optimization/2023-02-07-recursive-feature-elimination/index.html", + "/gallery/optimization/2023-02-01-shadow-variable-search/index.html", + "/gallery/optimization/2023-01-31-default-configuration/index.html", + "/gallery/optimization/2023-01-16-hyperband-subsampling/index.html", + "/gallery/optimization/2023-01-16-hotstart/index.html", + "/gallery/optimization/2023-01-15-hyperband-xgboost/index.html", + "/gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/index.html", + "/gallery/optimization/2022-11-04-early-stopping-with-xgboost/index.html", + "/gallery/optimization/2021-07-06-introduction-to-mlr3tuningspaces/index.html", + "/gallery/optimization/2021-03-12-practical-tuning-series-tuning-and-parallel-processing/index.html", + "/gallery/optimization/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index.html", + "/gallery/optimization/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/index.html", + "/gallery/optimization/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/index.html", + "/gallery/optimization/2021-01-19-integer-hyperparameters-in-tuners-for-real-valued-search-spaces/index.html", + "/gallery/optimization/2020-09-14-mlr3fselect-basic/index.html", + "/gallery/optimization/2020-10-14-threshold-tuning/index.html" + ] + }, + { + "listing": "/gallery-all-pipelines.html", + "items": [ + "/gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html", + "/gallery/pipelines/2020-09-11-liver-patient-classification/index.html", + "/gallery/pipelines/2020-06-15-target-transformations-via-pipelines/index.html", + "/gallery/pipelines/2020-04-27-tuning-stacking/index.html", + "/gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index.html", + "/gallery/pipelines/2020-04-23-pipelines-selectors-branches/index.html", + "/gallery/pipelines/2020-04-18-regression-chains/index.html", + "/gallery/pipelines/2020-03-12-intro-pipelines-titanic/index.html", + "/gallery/pipelines/2020-02-01-tuning-multiplexer/index.html" + ] + }, + { + "listing": "/gallery-all-technical.html", + "items": [ + "/gallery/technical/2023-12-21-time-constraints/index.html", + "/gallery/technical/2023-10-30-tidymodels/index.html", + "/gallery/technical/2023-10-25-bart-survival/index.html", + "/gallery/technical/2023-02-27-land-cover-classification/index.html", + "/gallery/technical/2022-12-22-mlr3viz/index.html", + "/gallery/technical/2020-08-13-a-production-example-using-plumber-and-docker/index.html" + ] + }, + { + "listing": "/gallery-all-basic.html", + "items": [ + "/gallery/basic/2021-01-20-keras/index.html", + "/gallery/basic/2020-08-14-comparison-of-decision-boundaries/index.html", + "/gallery/basic/2020-05-04-moneyball/index.html", + "/gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index.html", + "/gallery/basic/2020-03-30-stratification-blocking/index.html", + "/gallery/basic/2020-03-30-imbalanced-data/index.html", + "/gallery/basic/2020-03-18-iris-mlr3-basics/index.html", + "/gallery/basic/2020-03-11-basics-german-credit/index.html", + "/gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index.html", + "/gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html", + "/gallery/basic/2020-02-25-remove-correlated-features/index.html", + "/gallery/basic/2020-01-30-impute-missing-levels/index.html", + "/gallery/basic/2020-01-31-encode-factors-for-xgboost/index.html", + "/gallery/basic/2020-01-30-house-prices-in-king-county/index.html" + ] + } +] \ No newline at end of file diff --git a/measures.html b/measures.html new file mode 100644 index 00000000..2f6b88cf --- /dev/null +++ b/measures.html @@ -0,0 +1,707 @@ + + + + + + + + + +measures – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + +
+ + + + +
+

Measures

+

Measures operate on Prediction objects generated by learners. They quantify the prediction by comparing prediction with ground truth. The Measure objects provide an abstraction for a plethora of performance measures.

+
+
+
+ +
+
+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/pipeops.html b/pipeops.html new file mode 100644 index 00000000..396d63ca --- /dev/null +++ b/pipeops.html @@ -0,0 +1,707 @@ + + + + + + + + + +pipeops – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + +
+ + + + +
+

Pipeline Operators

+

Objects of class PipeOp are the building blocks to compose linear machine learning pipelines and non-linear Graphs. The base objects are implemented in mlr3pipelines.

+
+
+
+ +
+
+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/resamplings.html b/resamplings.html new file mode 100644 index 00000000..0864a90c --- /dev/null +++ b/resamplings.html @@ -0,0 +1,776 @@ + + + + + + + + + +resamplings – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + + +
+ + + + +
+

Resamplings

+

Resamplings split the observations multiple times into two sets: training and test. The former is used to fit the model, the latter is used to evaluate the predictions. The Resampling objects provide an abstraction for this procedure while respecting stratification as well as grouping/blocking if this is required by the Task.

+

If only a single split is required (i.e., a holdout split), the partition() function provides a single split into training and test set.

+
+
+
+ +
+
+
+

Example Usage

+

Fit a Random Forest on the Wisconsin Breast Cancer Data Set using a 3-fold cross validation.

+
+
library("mlr3verse")
+
+
Loading required package: mlr3
+
+
# retrieve the task
+task = tsk("breast_cancer")
+
+# retrieve a learner
+learner = lrn("classif.ranger")
+
+# retrieve resampling strategy
+resampling = rsmp("cv", folds = 3)
+
+# perform resampling
+rr = resample(task, learner, resampling)
+
+
INFO  [18:11:42.354] [mlr3] Applying learner 'classif.ranger' on task 'breast_cancer' (iter 1/3)
+INFO  [18:11:42.925] [mlr3] Applying learner 'classif.ranger' on task 'breast_cancer' (iter 2/3)
+INFO  [18:11:43.001] [mlr3] Applying learner 'classif.ranger' on task 'breast_cancer' (iter 3/3)
+
+
rr
+
+
<ResampleResult> with 3 resampling iterations
+       task_id     learner_id resampling_id iteration warnings errors
+ breast_cancer classif.ranger            cv         1        0      0
+ breast_cancer classif.ranger            cv         2        0      0
+ breast_cancer classif.ranger            cv         3        0      0
+
+
+ + +
+
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/resources.html b/resources.html new file mode 100644 index 00000000..9e74b66e --- /dev/null +++ b/resources.html @@ -0,0 +1,1018 @@ + + + + + + + + + +Resources – mlr-org + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + + + + + + \ No newline at end of file diff --git a/robots.txt b/robots.txt new file mode 100644 index 00000000..1aa8a8ff --- /dev/null +++ b/robots.txt @@ -0,0 +1 @@ +Sitemap: https://mlr-org.com/sitemap.xml diff --git a/search.json b/search.json new file mode 100644 index 00000000..ab4b16a1 --- /dev/null +++ b/search.json @@ -0,0 +1,1878 @@ +[ + { + "objectID": "fselectors.html", + "href": "fselectors.html", + "title": "Feature Selection Wrapper", + "section": "", + "text": "Feature selection wrappers can be found in the mlr3fselect packages. The goal is to find the best subset of features with respect to a performance measure in an iterative fashion.\n\n\n\n\n\n\n\n\nRun a sequential feature selection on the Pima Indian Diabetes data set.\n\nlibrary(mlr3verse)\n\n# retrieve task\ntask = tsk(\"pima\")\n\n# load learner\nlearner = lrn(\"classif.rpart\")\n\n# feature selection on the pima indians diabetes data set\ninstance = fselect(\n fselector = fs(\"sequential\"),\n task = task,\n learner = learner,\n resampling = rsmp(\"holdout\"),\n measure = msr(\"classif.ce\")\n)\n\n# best performing feature subset\ninstance$result\n\n age glucose insulin mass pedigree pregnant pressure triceps\n <lgcl> <lgcl> <lgcl> <lgcl> <lgcl> <lgcl> <lgcl> <lgcl>\n1: FALSE TRUE FALSE FALSE FALSE TRUE TRUE TRUE\n features n_features classif.ce\n <list> <int> <num>\n1: glucose,pregnant,pressure,triceps 4 0.2304688\n\n# subset the task and fit the final model\ntask$select(instance$result_feature_set)\nlearner$train(task)\n\nprint(learner)\n\n<LearnerClassifRpart:classif.rpart>: Classification Tree\n* Model: rpart\n* Parameters: xval=0\n* Packages: mlr3, rpart\n* Predict Types: [response], prob\n* Feature Types: logical, integer, numeric, factor, ordered\n* Properties: importance, missings, multiclass, selected_features,\n twoclass, weights" + }, + { + "objectID": "fselectors.html#example-usage", + "href": "fselectors.html#example-usage", + "title": "Feature Selection Wrapper", + "section": "", + "text": "Run a sequential feature selection on the Pima Indian Diabetes data set.\n\nlibrary(mlr3verse)\n\n# retrieve task\ntask = tsk(\"pima\")\n\n# load learner\nlearner = lrn(\"classif.rpart\")\n\n# feature selection on the pima indians diabetes data set\ninstance = fselect(\n fselector = fs(\"sequential\"),\n task = task,\n learner = learner,\n resampling = rsmp(\"holdout\"),\n measure = msr(\"classif.ce\")\n)\n\n# best performing feature subset\ninstance$result\n\n age glucose insulin mass pedigree pregnant pressure triceps\n <lgcl> <lgcl> <lgcl> <lgcl> <lgcl> <lgcl> <lgcl> <lgcl>\n1: FALSE TRUE FALSE FALSE FALSE TRUE TRUE TRUE\n features n_features classif.ce\n <list> <int> <num>\n1: glucose,pregnant,pressure,triceps 4 0.2304688\n\n# subset the task and fit the final model\ntask$select(instance$result_feature_set)\nlearner$train(task)\n\nprint(learner)\n\n<LearnerClassifRpart:classif.rpart>: Classification Tree\n* Model: rpart\n* Parameters: xval=0\n* Packages: mlr3, rpart\n* Predict Types: [response], prob\n* Feature Types: logical, integer, numeric, factor, ordered\n* Properties: importance, missings, multiclass, selected_features,\n twoclass, weights" + }, + { + "objectID": "pipeops.html", + "href": "pipeops.html", + "title": "Pipeline Operators", + "section": "", + "text": "Pipeline Operators\nObjects of class PipeOp are the building blocks to compose linear machine learning pipelines and non-linear Graphs. The base objects are implemented in mlr3pipelines." + }, + { + "objectID": "index.html", + "href": "index.html", + "title": "mlr3: Machine Learning in R", + "section": "", + "text": "The mlr3 ecosystem is the framework for machine learning in R.\nAn open-source collection of R packages providing a unified interface for machine learning in the R language. Successor of mlr.\nA scientifically designed and easy to learn interface.\n\n\n\n\n\n\n\nMore than 100 connected machine learning algorithms.\n\n\n\n\n\n\n\nLight on dependencies.\n\n\n\n\n\n\n\nConvenient parallelization with the future package.\n\n\n\n\n\n\n\nState-of-the-art optimization algorithms.\n\n\n\n\n\n\n\nDataflow programming with pipelines." + }, + { + "objectID": "index.html#get-started", + "href": "index.html#get-started", + "title": "mlr3: Machine Learning in R", + "section": "Get Started", + "text": "Get Started\nThere are many packages in the mlr3 ecosystem that you may want to use. You can install the full mlr3 universe at once with:\n\ninstall.packages(\"mlr3verse\")\n\nYou can also use our Docker images." + }, + { + "objectID": "index.html#resources", + "href": "index.html#resources", + "title": "mlr3: Machine Learning in R", + "section": "Resources", + "text": "Resources\n\nOur book “Applied Machine Learning Using mlr3 in R” is the central entry point to mlr3 ecosystem. This essential guide covers key aspects of machine learning, from building and evaluating predictive models to advanced techniques like hyperparameter tuning for peak performance. It delves into constructing comprehensive machine learning pipelines, encompassing data pre-processing, modeling, and prediction aggregation.\nThe book is primarily aimed at researchers, practitioners, and graduate students who use machine learning or who are interested in using it. It can be used as a textbook for an introductory or advanced machine learning class that uses R, as a reference for people who work with machine learning methods, and in industry for exploratory experiments in machine learning.\nIn addition to the book, there are many other resources to learn more about mlr3. The gallery contains a collection of case studies that demonstrate the functionality of mlr3. The cheatsheets provide a quick overview of the most important functions. The resources section contains links to talks, courses, and other material." + }, + { + "objectID": "index.html#examples", + "href": "index.html#examples", + "title": "mlr3: Machine Learning in R", + "section": "Examples", + "text": "Examples\n\n\n\n\n\n\nBasic Machine Learning\n\nGet to know the basic building blocks of machine learning in mlr3. Train your first learner and estimate its performance with resampling. Compare the performance of learners with benchmarking.\n\n\n\n\n\n\n\nOptimization\n\nOptimize the hyperparameters of a classification tree on the Palmer Penguins data set. Become familiar with search spaces and transformations. Fit a final model with optimized hyperparameters for predicting new data.\n\n\n\n\n\n\n\nPipelines\n\nBuild a preprocessing pipeline for missing data in the German Credit data set. Optimize the parameters of the pipeline and stack multiple learners into an ensemble model. Learn about techniques to tackle challenging data sets.\n\n\n\n\n\n\n\nFeature Selection\n\nStart a feature selection on the Titanic data set. Learn about different optimization algorithms and fit a final model. Estimate the performance of the optimized feature set with nested resampling." + }, + { + "objectID": "gallery/technical/2023-12-21-time-constraints/index.html", + "href": "gallery/technical/2023-12-21-time-constraints/index.html", + "title": "Time constraints in the mlr3 ecosystem", + "section": "", + "text": "Scope\nSetting time limits is an important consideration when tuning unreliable or unstable learning algorithms and when working on shared computing resources. The mlr3 ecosystem provides several mechanisms for setting time constraints for individual learners, tuning processes, and nested resampling.\n\n\nLearner\nThis section demonstrates how to impose time constraints using a support vector machine (SVM) as an illustrative example.\n\nlibrary(mlr3verse)\n\nlearner = lrn(\"classif.svm\")\n\nApplying timeouts to the $train() and $predict() functions is essential for managing learners that may operate indefinitely. These time constraints are set independently for both the training and prediction stages. Generally, training a learner consumes more time than prediction. Certain learners, like k-nearest neighbors, lack a distinct training phase and require a timeout only during prediction. For the SVM’s training, we set a 10-second limit.\n\nlearner$timeout = c(train = 10, predict = Inf)\n\nTo effectively terminate the process if necessary, it’s important to run the training and prediction within a separate R process. The callr package is recommended for this encapsulation, as it tends to be more reliable than the evaluate package, especially for terminating externally compiled code.\n\nlearner$encapsulate = c(train = \"callr\", predict = \"callr\")\n\nNote that using callr increases the runtime due to the overhead of starting an R process. Additionally, it’s advisable to specify a fallback learner, such as \"classif.featureless\", to provide baseline predictions in case the primary learner is terminated.\n\nlearner$fallback = lrn(\"classif.featureless\")\n\nThese time constraints are now integrated into the training, resampling, and benchmarking processes. For more information on encapsulation and fallback learners, see the mlr3book. The next section will focus on setting time limits for the entire tuning process.\n\n\nTuning\nWhen working with high-performance computing clusters, jobs are often bound by strict time constraints. Exceeding these limits results in the job being terminated and the loss of any results generated. Therefore, it’s important to ensure that the tuning process is designed to adhere to these time constraints.\nThe trm(\"runtime\") controls the duration of the tuning process. We must take into account that the terminator can only check if the time limit is reached between batches. We must therefore set the time lower than the runtime of the job. How much lower depends on the runtime or time limit of the individual learners. The last batch should be able to finish before the time limit of the cluster is reached.\n\nterminator = trm(\"run_time\", secs = 60)\n\ninstance = ti(\n task = tsk(\"sonar\"),\n learner = learner,\n resampling = rsmp(\"cv\", folds = 3),\n measures = msr(\"classif.ce\"),\n terminator = terminator\n)\n\nWith these settings, our tuning operation is configured to run for 60 seconds, while individual learners are set to terminate after 10 seconds. This approach ensures the tuning process is efficient and adheres to the constraints imposed by the high-performance computing cluster.\n\n\nNested Resampling\nWhen using nested resampling, time constraints become more complex as they are applied across various levels. As before, the time limit for an individual learner during the tuning is set with $timeout. The time limit for the tuning processes in the auto tuners is controlled with the trm(\"runtime\"). It’s important to note that once the auto tuner enters the final phase of fitting the model and making predictions on the outer test set, the time limit governed by the terminator no longer applies. Additionally, the time limit previously set on the learner is temporarily deactivated, allowing the auto tuner to complete its task uninterrupted. However, a separate time limit can be assigned to each auto tuner using $timeout. This limit encompasses not only the tuning phase but also the time required for fitting the final model and predictions on the outer test set.\nThe best way to show this is with an example. We set the time limit for an individual learner to 10 seconds.\n\nlearner$timeout = c(train = 10, predict = Inf)\nlearner$encapsulate = c(train = \"callr\", predict = \"callr\")\nlearner$fallback = lrn(\"classif.featureless\")\n\nNext, we give each auto tuner 60 seconds to finish the tuning process.\n\nterminator = trm(\"run_time\", secs = 60)\n\nFurthermore, we impose a 120-second limit for resampling each auto tuner. This effectively divides the time allocation, with around 60 seconds for tuning and another 60 seconds for final model fitting and predictions on the outer test set.\n\nat = auto_tuner(\n tuner = tnr(\"random_search\"),\n learner = learner,\n resampling = rsmp(\"cv\", folds = 3),\n measure = msr(\"classif.ce\"),\n terminator = trm(\"run_time\", secs = 60)\n)\n\nat$timeout = c(train = 100, predict = 20)\nat$encapsulate = c(train = \"callr\", predict = \"callr\")\nat$fallback = lrn(\"classif.featureless\")\n\nIn total, the entire nested resampling process is designed to be completed within 10 minutes (120 seconds multiplied by 5 folds).\n\nrr = resample(task, at, rsmp(\"cv\", folds = 5))\n\n\n\nConclusion\nWe delved into the setting of time constraints across different levels in the mlr3 ecosystem. From individual learners to the complexities of nested resampling, we’ve seen how effectively managing time limits can significantly enhance the efficiency and reliability of machine learning workflows. By utilizing the trm(\"runtime\") for tuning processes and setting $timeout for individual learners and auto tuners, we can ensure that our machine learning tasks are not only effective but also adhere to the practical time constraints of shared computational resources. For more information, see also the error handling section in the mlr3book." + }, + { + "objectID": "gallery/technical/2023-10-25-bart-survival/index.html", + "href": "gallery/technical/2023-10-25-bart-survival/index.html", + "title": "Survival modeling in mlr3 using Bayesian Additive Regression Trees (BART)", + "section": "", + "text": "Here are some interesting reads regarding BART:\n\nThe first BART paper (Chipman, George, and McCulloch 2010).\nThe first implementation of BART for survival data (Bonato et al. 2011). This includes fully parametric AFT and Weibull models and the semi-parametric CoxPH regression model.\nThe first non-parametric implementation of BART for survival data (R. A. Sparapani et al. 2016)\nBART R package tutorial (R. Sparapani, Spanbauer, and McCulloch 2021)\n\nWe incorporated the survival BART model in mlr3extralearners and in this tutorial we will demonstrate how we can use packages like mlr3, mlr3proba and distr6 to more easily manipulate the output predictions to assess model convergence, validate our model (via several survival metrics), as well as perform model interpretation via PDPs (Partial Dependence Plots)." + }, + { + "objectID": "gallery/technical/2023-10-25-bart-survival/index.html#intro", + "href": "gallery/technical/2023-10-25-bart-survival/index.html#intro", + "title": "Survival modeling in mlr3 using Bayesian Additive Regression Trees (BART)", + "section": "", + "text": "Here are some interesting reads regarding BART:\n\nThe first BART paper (Chipman, George, and McCulloch 2010).\nThe first implementation of BART for survival data (Bonato et al. 2011). This includes fully parametric AFT and Weibull models and the semi-parametric CoxPH regression model.\nThe first non-parametric implementation of BART for survival data (R. A. Sparapani et al. 2016)\nBART R package tutorial (R. Sparapani, Spanbauer, and McCulloch 2021)\n\nWe incorporated the survival BART model in mlr3extralearners and in this tutorial we will demonstrate how we can use packages like mlr3, mlr3proba and distr6 to more easily manipulate the output predictions to assess model convergence, validate our model (via several survival metrics), as well as perform model interpretation via PDPs (Partial Dependence Plots)." + }, + { + "objectID": "gallery/technical/2023-10-25-bart-survival/index.html#libraries", + "href": "gallery/technical/2023-10-25-bart-survival/index.html#libraries", + "title": "Survival modeling in mlr3 using Bayesian Additive Regression Trees (BART)", + "section": "Libraries", + "text": "Libraries\n\nlibrary(mlr3extralearners)\nlibrary(mlr3pipelines)\nlibrary(mlr3proba)\nlibrary(distr6)\nlibrary(BART) # 2.9.4\nlibrary(dplyr)\nlibrary(tidyr)\nlibrary(tibble)\nlibrary(ggplot2)" + }, + { + "objectID": "gallery/technical/2023-10-25-bart-survival/index.html#data", + "href": "gallery/technical/2023-10-25-bart-survival/index.html#data", + "title": "Survival modeling in mlr3 using Bayesian Additive Regression Trees (BART)", + "section": "Data", + "text": "Data\nWe will use the Lung Cancer Dataset. We convert the time variable from days to months to ease the computational burden:\n\ntask_lung = tsk('lung')\n\nd = task_lung$data()\n# in case we want to select specific columns to keep\n# d = d[ ,colnames(d) %in% c(\"time\", \"status\", \"age\", \"sex\", \"ph.karno\"), with = FALSE]\nd$time = ceiling(d$time/30.44)\ntask_lung = as_task_surv(d, time = 'time', event = 'status', id = 'lung')\ntask_lung$label = \"Lung Cancer\"\n\n\n\n\n\n\n\nNote\n\n\n\n\nThe original BART implementation supports categorical features (factors). This results in different importance scores per each dummy level which doesn’t work well with mlr3. So features of type factor or character are not allowed and we leave it to the user to encode them as they please.\nThe original BART implementation supports features with missing values. This is totally fine with mlr3 as well! In this example, we impute the features to show good ML practice.\n\n\n\nIn our lung dataset, we encode the sex feature and perform model-based imputation with the rpart regression learner:\n\npo_encode = po('encode', method = 'treatment')\npo_impute = po('imputelearner', lrn('regr.rpart'))\npre = po_encode %>>% po_impute\ntask = pre$train(task_lung)[[1]]\ntask\n\n<TaskSurv:lung> (228 x 10): Lung Cancer\n* Target: time, status\n* Properties: -\n* Features (8):\n - int (7): age, inst, meal.cal, pat.karno, ph.ecog, ph.karno, wt.loss\n - dbl (1): sex\n\n\nNo missing values in our data:\n\ntask$missings()\n\n time status age sex inst meal.cal pat.karno ph.ecog ph.karno wt.loss \n 0 0 0 0 0 0 0 0 0 0 \n\n\nWe partition the data to train and test sets:\n\nset.seed(42)\npart = partition(task, ratio = 0.9)" + }, + { + "objectID": "gallery/technical/2023-10-25-bart-survival/index.html#train-and-test", + "href": "gallery/technical/2023-10-25-bart-survival/index.html#train-and-test", + "title": "Survival modeling in mlr3 using Bayesian Additive Regression Trees (BART)", + "section": "Train and Test", + "text": "Train and Test\nWe train the BART model and predict on the test set:\n\n# default `ndpost` value: 1000. We reduce it to 50 to speed up calculations in this tutorial\nlearner = lrn(\"surv.bart\", nskip = 250, ndpost = 50, keepevery = 10, mc.cores = 10)\nlearner$train(task, row_ids = part$train)\np = learner$predict(task, row_ids = part$test)\np\n\n<PredictionSurv> for 23 observations:\n row_ids time status crank distr\n 9 8 TRUE 66.19326 <list[1]>\n 10 6 TRUE 98.43005 <list[1]>\n 21 10 TRUE 54.82313 <list[1]>\n--- \n 160 13 FALSE 37.82089 <list[1]>\n 163 10 FALSE 69.63534 <list[1]>\n 194 8 FALSE 81.13678 <list[1]>\n\n\nSee more details about BART’s parameters on the online documentation.\n\ndistr\nWhat kind of object is the predicted distr?\n\np$distr\n\nArrdist(23x31x50) \n\n\n\n\n\n\n\n\nArrdist dimensions:\n\n\n\n\nPatients (observations)\nTime points (months)\nNumber of posterior draws\n\n\n\nActually the $distr is an active R6 field - this means that some computation is required to create it. What the prediction object actually stores internally is a 3d survival array (can be used directly with no performance overhead):\n\ndim(p$data$distr)\n\n[1] 23 31 50\n\n\nThis is a more easy-to-understand and manipulate form of the full posterior survival matrix prediction from the BART package ((R. Sparapani, Spanbauer, and McCulloch 2021), pages 34-35).\n\n\n\n\n\n\nWarning\n\n\n\nThough we have optimized with C++ code the way the Arrdist object is constructed, calling the $distr field can be computationally taxing if the product of the sizes of the 3 dimensions above exceeds ~1 million. In our case, \\(23 \\times 31 \\times 50 = 35650\\) so the conversion to an Arrdist via $distr will certainly not create performance issues.\n\n\nAn example using the internal prediction data: get all the posterior probabilities of the 3rd patient in the test set, at 12 months (1 year):\n\np$data$distr[3, 12, ]\n\n [1] 0.26546909 0.27505937 0.21151435 0.46700513 0.26178380 0.24040003 0.29946469 0.52357780 0.40833108 0.40367780\n[11] 0.27027392 0.31781286 0.54151844 0.34460027 0.41826554 0.41866367 0.33694401 0.34511270 0.47244492 0.49423660\n[21] 0.42069678 0.20095489 0.48696980 0.48409357 0.35649439 0.47969355 0.16355660 0.33728105 0.40245228 0.42418033\n[31] 0.36336145 0.48181667 0.51858238 0.49635078 0.37238179 0.26694030 0.52219952 0.48992897 0.08572207 0.30306005\n[41] 0.33881682 0.33463870 0.29102074 0.43176131 0.38554545 0.38053756 0.36808776 0.13772665 0.21898264 0.14552514\n\n\nWorking with the $distr interface and Arrdist objects is very efficient as we will see later for predicting survival estimates.\n\n\n\n\n\n\nTip\n\n\n\nIn survival analysis, \\(S(t) = 1 - F(t)\\), where \\(S(t)\\) the survival function and \\(F(t)\\) the cumulative distribution function (cdf). The latter can be interpreted as risk or probability of death up to time \\(t\\).\nWe can verify the above from the prediction object:\n\nsurv_array = 1 - distr6::gprm(p$distr, \"cdf\") # 3d array\ntestthat::expect_equal(p$data$distr, surv_array)\n\n\n\n\n\ncrank\ncrank is the expected mortality (Sonabend, Bender, and Vollmer 2022) which is the sum of the predicted cumulative hazard function (as is done in random survival forest models). Higher values denote larger risk. To calculate crank, we need a survival matrix. So we have to choose which 3rd dimension we should use from the predicted survival array. This is what the which.curve parameter of the learner does:\n\nlearner$param_set$get_values()$which.curve\n\n[1] 0.5\n\n\nThe default value (\\(0.5\\) quantile) is the median survival probability. It could be any other quantile (e.g. \\(0.25\\)). Other possible values for which.curve are mean or a number denoting the exact posterior draw to extract (e.g. the last one, which.curve = 50)." + }, + { + "objectID": "gallery/technical/2023-10-25-bart-survival/index.html#feature-importance", + "href": "gallery/technical/2023-10-25-bart-survival/index.html#feature-importance", + "title": "Survival modeling in mlr3 using Bayesian Additive Regression Trees (BART)", + "section": "Feature importance", + "text": "Feature importance\nDefault score is the observed count of each feature in the trees (so the higher the score, the more important the feature):\n\nlearner$param_set$values$importance\n\n[1] \"count\"\n\nlearner$importance()\n\n sex meal.cal inst pat.karno ph.karno wt.loss age ph.ecog \n 7.84 7.46 7.08 6.76 6.60 6.46 5.48 5.42" + }, + { + "objectID": "gallery/technical/2023-10-25-bart-survival/index.html#mcmc-diagnostics", + "href": "gallery/technical/2023-10-25-bart-survival/index.html#mcmc-diagnostics", + "title": "Survival modeling in mlr3 using Bayesian Additive Regression Trees (BART)", + "section": "MCMC Diagnostics", + "text": "MCMC Diagnostics\nBART uses internally MCMC (Markov Chain Monte Carlo) to sample from the posterior survival distribution. We need to check that MCMC has converged, meaning that the chains have reached a stationary distribution that approximates the true posterior survival distribution (otherwise the predictions may be inaccurate, misleading and unreliable).\nWe use Geweke’s convergence diagnostic test as it is implemented in the BART R package. We choose 10 random patients from the train set to evaluate the MCMC convergence.\n\n# predictions on the train set\np_train = learner$predict(task, row_ids = part$train)\n\n# choose 10 patients from the train set randomly and make a list\nids = as.list(sample(length(part$train), 10))\n\nz_list = lapply(ids, function(id) {\n # matrix with columns => time points and rows => posterior draws\n post_surv = 1 - t(distr6::gprm(p_train$distr[id], \"cdf\")[1,,])\n BART::gewekediag(post_surv)$z # get the z-scores\n})\n\n# plot the z scores vs time for all patients\ndplyr::bind_rows(z_list) %>%\n tidyr::pivot_longer(cols = everything()) %>%\n mutate(name = as.numeric(name)) %>%\n ggplot(aes(x = name, y = value)) +\n geom_point() +\n labs(x = \"Time (months)\", y = \"Z-scores\") +\n # add critical values for a = 0.05\n geom_hline(yintercept = 1.96, linetype = 'dashed', color = \"red\") +\n geom_hline(yintercept = -1.96, linetype = 'dashed', color = \"red\") +\n theme_bw(base_size = 14)\n\n\n\n\nGeweke plot for MCMC diagnostics. Z-scores for the difference in the mean survival prediction between the first 10% and last 50% part of a Markov chain. The predictions are taken from 10 random patients in the train set. Red lines indicate the a = 0.05 critical line. Only a few z-scores exceed the 95% limits so we conclude that convergence has been attained." + }, + { + "objectID": "gallery/technical/2023-10-25-bart-survival/index.html#performance-test-set", + "href": "gallery/technical/2023-10-25-bart-survival/index.html#performance-test-set", + "title": "Survival modeling in mlr3 using Bayesian Additive Regression Trees (BART)", + "section": "Performance (test set)", + "text": "Performance (test set)\nWe will use the following survival metrics:\n\nIntegrated Brier Score (requires a survival distribution prediction - distr)\nRight-Censored Log loss (requires a survival distribution prediction - distr)\nUno’s C-index (requires a continuous ranking score prediction - crank)\n\nFor the first two measures we will use the ERV (Explained Residual Variation) version, which standardizes the scores against a Kaplan-Meier (KM) baseline (Sonabend et al. 2022). This means that values close to \\(0\\) represent performance similar to a KM model, negative values denote worse performance than KM and \\(1\\) is the absolute best possible score.\n\nmeasures = list(\n msr(\"surv.graf\", ERV = TRUE),\n msr(\"surv.rcll\", ERV = TRUE),\n msr(\"surv.cindex\", weight_meth = \"G2\", id = \"surv.cindex.uno\")\n)\n\nfor (measure in measures) {\n print(p$score(measure, task = task, train_set = part$train))\n}\n\n surv.graf \n-0.09950096 \n surv.rcll \n-0.02622117 \nsurv.cindex.uno \n 0.551951 \n\n\n\n\n\n\n\n\nNote\n\n\n\nAll metrics use by default the median survival distribution from the 3d array, no matter what is the which.curve argument during the learner’s construction." + }, + { + "objectID": "gallery/technical/2023-10-25-bart-survival/index.html#resampling", + "href": "gallery/technical/2023-10-25-bart-survival/index.html#resampling", + "title": "Survival modeling in mlr3 using Bayesian Additive Regression Trees (BART)", + "section": "Resampling", + "text": "Resampling\nPerforming resampling with the BART learner is very easy using mlr3.\nWe first stratify the data by status, so that in each resampling the proportion of censored vs un-censored patients remains the same:\n\ntask$col_roles$stratum = 'status'\ntask$strata\n\n N row_id\n <int> <list>\n1: 165 1,2,4,5,7,8,...\n2: 63 3, 6,38,68,71,83,...\n\n\n\nrr = resample(task, learner, resampling = rsmp(\"cv\", folds = 5), store_backends = TRUE)\n\nINFO [11:41:53.078] [mlr3] Applying learner 'surv.bart' on task 'lung' (iter 1/5)\nINFO [11:41:55.545] [mlr3] Applying learner 'surv.bart' on task 'lung' (iter 2/5)\nINFO [11:41:57.937] [mlr3] Applying learner 'surv.bart' on task 'lung' (iter 3/5)\nINFO [11:42:00.417] [mlr3] Applying learner 'surv.bart' on task 'lung' (iter 4/5)\nINFO [11:42:03.357] [mlr3] Applying learner 'surv.bart' on task 'lung' (iter 5/5)\n\n\nNo errors or warnings:\n\nrr$errors\n\nEmpty data.table (0 rows and 2 cols): iteration,msg\n\nrr$warnings\n\nEmpty data.table (0 rows and 2 cols): iteration,msg\n\n\nPerformance in each fold:\n\nrr$score(measures)\n\n task_id learner_id resampling_id iteration surv.graf surv.rcll surv.cindex.uno\n <char> <char> <char> <int> <num> <num> <num>\n1: lung surv.bart cv 1 -0.312614598 -0.102013166 0.5869665\n2: lung surv.bart cv 2 -0.103181391 -0.009579343 0.5502903\n3: lung surv.bart cv 3 0.001448263 0.338851363 0.6178001\n4: lung surv.bart cv 4 -0.044161171 0.003691073 0.6157215\n5: lung surv.bart cv 5 -0.043129352 0.157902047 0.5688389\nHidden columns: task, learner, resampling, prediction\n\n\nMean cross-validation performance:\n\nrr$aggregate(measures)\n\n surv.graf surv.rcll surv.cindex.uno \n -0.1003276 0.0777704 0.5879235" + }, + { + "objectID": "gallery/technical/2023-10-25-bart-survival/index.html#uncertainty-quantification-in-survival-prediction", + "href": "gallery/technical/2023-10-25-bart-survival/index.html#uncertainty-quantification-in-survival-prediction", + "title": "Survival modeling in mlr3 using Bayesian Additive Regression Trees (BART)", + "section": "Uncertainty Quantification in Survival Prediction", + "text": "Uncertainty Quantification in Survival Prediction\nWe will choose two patients from the test set and plot their survival prediction posterior estimates.\nLet’s choose the patients with the worst and the best survival time:\n\ndeath_times = p$truth[,1]\nsort(death_times)\n\n [1] 3 5 5 6 6 6 7 8 8 8 8 10 10 10 12 12 12 13 15 16 17 18 27\n\nworst_indx = which(death_times == min(death_times))[1] # died first\nbest_indx = which(death_times == max(death_times))[1] # died last\n\npatient_ids = c(worst_indx, best_indx)\npatient_ids # which patient IDs\n\n[1] 5 18\n\ndeath_times = death_times[patient_ids]\ndeath_times # 1st is worst, 2nd is best\n\n[1] 3 27\n\n\nSubset Arrdist to only the above 2 patients:\n\narrd = p$distr[patient_ids]\narrd\n\nArrdist(2x31x50) \n\n\nWe choose time points (in months) for the survival estimates:\n\nmonths = seq(1, 36) # 1 month - 3 years\n\nWe use the $distr interface and the $survival property to get survival probabilities from an Arrdist object as well as the quantile credible intervals (CIs). The median survival probabilities can be extracted as follows:\n\nmed = arrd$survival(months) # 'med' for median\n\ncolnames(med) = paste0(patient_ids, \"_med\")\nmed = as_tibble(med) %>% add_column(month = months)\nhead(med)\n\n# A tibble: 6 × 3\n `5_med` `18_med` month\n <dbl> <dbl> <int>\n1 0.874 0.981 1\n2 0.767 0.962 2\n3 0.670 0.945 3\n4 0.569 0.927 4\n5 0.465 0.901 5\n6 0.366 0.869 6\n\n\nWe can briefly verify model’s predictions: 1st patient survival probabilities on any month are lower (worst) compared to the 2nd patient.\nNote that subsetting an Arrdist (3d array) creates a Matdist (2d matrix), for example we can explicitly get the median survival probabilities:\n\nmatd_median = arrd[, 0.5] # median\nhead(matd_median$survival(months)) # same as with `arrd`\n\n [,1] [,2]\n1 0.8741127 0.9808363\n2 0.7670382 0.9621618\n3 0.6701276 0.9450867\n4 0.5688809 0.9272284\n5 0.4647686 0.9007042\n6 0.3660939 0.8687270\n\n\nUsing the mean posterior survival probabilities or the ones from the last posterior draw is also possible and can be done as follows:\n\nmatd_mean = arrd[, \"mean\"] # mean (if needed)\nhead(matd_mean$survival(months))\n\n [,1] [,2]\n1 0.8652006 0.9748463\n2 0.7533538 0.9521817\n3 0.6560050 0.9293229\n4 0.5623555 0.9051549\n5 0.4750038 0.8758896\n6 0.3815333 0.8360373\n\nmatd_50draw = arrd[, 50] # the 50th posterior draw\nhead(matd_50draw$survival(months))\n\n [,1] [,2]\n1 0.9178342 0.9920982\n2 0.8424195 0.9842589\n3 0.7732014 0.9764815\n4 0.7096707 0.9687656\n5 0.6029119 0.9495583\n6 0.5122132 0.9307318\n\n\nTo get the CIs we will subset the Arrdist using a quantile number (0-1), which extracts a Matdist based on the cdf. The survival function is 1 - cdf, so low and upper bounds are reversed:\n\nlow = arrd[, 0.975]$survival(months) # 2.5% bound\nhigh = arrd[, 0.025]$survival(months) # 97.5% bound\ncolnames(low) = paste0(patient_ids, \"_low\")\ncolnames(high) = paste0(patient_ids, \"_high\")\nlow = as_tibble(low)\nhigh = as_tibble(high)\n\nThe median posterior survival probabilities for the two patient of interest and the corresponding CI bounds in a tidy format are:\n\nsurv_tbl =\n bind_cols(low, med, high) %>%\n pivot_longer(cols = !month, values_to = \"surv\",\n names_to = c(\"patient_id\", \".value\"), names_sep = \"_\") %>%\n relocate(patient_id)\nsurv_tbl\n\n# A tibble: 72 × 5\n patient_id month low med high\n <chr> <int> <dbl> <dbl> <dbl>\n 1 5 1 0.713 0.874 0.953\n 2 18 1 0.929 0.981 0.996\n 3 5 2 0.508 0.767 0.903\n 4 18 2 0.863 0.962 0.991\n 5 5 3 0.362 0.670 0.855\n 6 18 3 0.801 0.945 0.985\n 7 5 4 0.244 0.569 0.804\n 8 18 4 0.734 0.927 0.977\n 9 5 5 0.146 0.465 0.748\n10 18 5 0.654 0.901 0.969\n# ℹ 62 more rows\n\n\nWe draw survival curves with the uncertainty for the survival probability quantified:\n\nmy_colors = c(\"#E41A1C\", \"#4DAF4A\")\nnames(my_colors) = patient_ids\n\nsurv_tbl %>%\n ggplot(aes(x = month, y = med)) +\n geom_step(aes(color = patient_id), linewidth = 1) +\n xlab('Time (Months)') +\n ylab('Survival Probability') +\n geom_ribbon(aes(ymin = low, ymax = high, fill = patient_id),\n alpha = 0.3, show.legend = F) +\n geom_vline(xintercept = death_times[1], linetype = 'dashed', color = my_colors[1]) +\n geom_vline(xintercept = death_times[2], linetype = 'dashed', color = my_colors[2]) +\n theme_bw(base_size = 14) +\n scale_color_manual(values = my_colors) +\n scale_fill_manual(values = my_colors) +\n guides(color = guide_legend(title = \"Patient ID\"))\n\n\n\n\nUncertainty quantification for the survival prediction of two patients in the test set using 95% credible intervals. The two vertical lines correspond to the reported time of death (in months) for the two patients." + }, + { + "objectID": "gallery/technical/2023-10-25-bart-survival/index.html#partial-dependence-plot", + "href": "gallery/technical/2023-10-25-bart-survival/index.html#partial-dependence-plot", + "title": "Survival modeling in mlr3 using Bayesian Additive Regression Trees (BART)", + "section": "Partial Dependence Plot", + "text": "Partial Dependence Plot\nWe will use a Partial Dependence Plot (PDP) (Friedman 2001) to visualize how much different are males vs females in terms of their average survival predictions across time.\n\n\n\n\n\n\nNote\n\n\n\nPDPs assume that features are independent. In our case we need to check that sex doesn’t correlate with any of the other features used for training the BART learner. Since sex is a categorical feature, we fit a linear model using as target variable every other feature in the data (\\(lm(feature \\sim sex)\\)) and conduct an ANOVA (ANalysis Of VAriance) to get the variance explained or \\(R^2\\). The square root of that value is the correlation measure we want.\n\n\n\n# code from https://christophm.github.io/interpretable-ml-book/ale.html\nmycor = function(cnames, data) {\n x.num = data[, cnames[1], with = FALSE][[1]]\n x.cat = data[, cnames[2], with = FALSE][[1]]\n # R^2 = Cor(X, Y)^2 in simple linear regression\n sqrt(summary(lm(x.num ~ x.cat))$r.squared)\n}\n\ncnames = c(\"sex\")\ncombs = expand.grid(y = setdiff(colnames(d), \"sex\"), x = cnames)\ncombs$cor = apply(combs, 1, mycor, data = task$data()) # use the train set\ncombs\n\n y x cor\n1 time sex 0.12941337\n2 status sex 0.24343282\n3 age sex 0.12216709\n4 inst sex 0.07826337\n5 meal.cal sex 0.18389545\n6 pat.karno sex 0.04132443\n7 ph.ecog sex 0.02564987\n8 ph.karno sex 0.01702471\n9 wt.loss sex 0.13431983\n\n\nsex doesn’t correlate strongly with any other feature, so we can compute the PDP:\n\n# create two datasets: one with males and one with females\n# all other features remain the same (use train data, 205 patients)\nd = task$data(rows = part$train) # `rows = part$test` to use the test set\n\nd$sex = 1\ntask_males = as_task_surv(d, time = 'time', event = 'status', id = 'lung-males')\nd$sex = 0\ntask_females = as_task_surv(d, time = 'time', event = 'status', id = 'lung-females')\n\n# make predictions\np_males = learner$predict(task_males)\np_females = learner$predict(task_females)\n\n# take the median posterior survival probability\nsurv_males = p_males$distr$survival(months) # patients x times\nsurv_females = p_females$distr$survival(months) # patients x times\n\n# tidy up data: average and quantiles across patients\ndata_males =\n apply(surv_males, 1, function(row) {\n tibble(\n low = quantile(row, probs = 0.025),\n avg = mean(row),\n high = quantile(row, probs = 0.975)\n )\n }) %>%\n bind_rows() %>%\n add_column(sex = 'male', month = months, .before = 1)\n\ndata_females =\n apply(surv_females, 1, function(row) {\n tibble(\n low = quantile(row, probs = 0.025),\n avg = mean(row),\n high = quantile(row, probs = 0.975)\n )\n }) %>%\n bind_rows() %>%\n add_column(sex = 'female', month = months, .before = 1)\n\npdp_tbl = bind_rows(data_males, data_females)\npdp_tbl\n\n# A tibble: 72 × 5\n sex month low avg high\n <chr> <int> <dbl> <dbl> <dbl>\n 1 male 1 0.836 0.942 0.981\n 2 male 2 0.704 0.889 0.963\n 3 male 3 0.587 0.839 0.943\n 4 male 4 0.488 0.788 0.924\n 5 male 5 0.392 0.732 0.897\n 6 male 6 0.304 0.663 0.860\n 7 male 7 0.234 0.601 0.829\n 8 male 8 0.172 0.550 0.799\n 9 male 9 0.130 0.503 0.766\n10 male 10 0.0945 0.455 0.733\n# ℹ 62 more rows\n\n\n\nmy_colors = c(\"#E41A1C\", \"#4DAF4A\")\nnames(my_colors) = c('male', 'female')\n\npdp_tbl %>%\n ggplot(aes(x = month, y = avg)) +\n geom_step(aes(color = sex), linewidth = 1) +\n xlab('Time (Months)') +\n ylab('Survival Probability') +\n geom_ribbon(aes(ymin = low, ymax = high, fill = sex), alpha = 0.2, show.legend = F) +\n theme_bw(base_size = 14) +\n scale_color_manual(values = my_colors) +\n scale_fill_manual(values = my_colors)\n\n\n\n\nFriedman’s partial dependence function with 95% prediction intervals: males vs females. Females show on average larger survival estimates compared to men, across all time points. Overlapping shaded area represents men and women that have similar survival characteristics." + }, + { + "objectID": "gallery/technical/2023-02-27-land-cover-classification/index.html", + "href": "gallery/technical/2023-02-27-land-cover-classification/index.html", + "title": "Spatial Data in the mlr3 Ecosystem", + "section": "", + "text": "Scope\nWorking with spatial data in R requires a lot of data wrangling e.g. reading from different file formats, converting between spatial formats, creating tables from point layers, and predicting spatial raster images. The goal of mlr3spatial is to simplify these workflows within the mlr3 ecosystem. As a practical example, we will perform a land cover classification for the city of Leipzig, Germany. Figure 1 illustrates the typical workflow for this type of task: Load the training data, create a spatial task, train a learner with it, and predict the final raster image.\n\n\n\n\n\n\n%%{ init: { 'flowchart': { 'curve': 'bump' } } }%%\n\nflowchart LR\n subgraph files[Files]\n vector[Vector]\n raster[Raster]\n end\n subgraph load[Load Data]\n sf\n terra\n end\n vector --> sf\n raster --> terra\n subgraph train_model[Train Model]\n task[Task]\n learner[Learner]\n end\n terra --> prediction_raster\n task --> learner\n sf --> task\n subgraph predict[Spatial Prediction]\n prediction_raster[Raster Image]\n end\n learner --> prediction_raster\n\n\n\n\nFigure 1: Spatial prediction workflow in mlr3spatial.\n\n\n\n\n\nWe assume that you are familiar with the mlr3 ecosystem and know the basic concepts of remote sensing. If not, we recommend reading the mlr3book first. If you are interested in spatial resampling, check out the book chapter on spatial analysis.\n\n\nLand Cover Classification\nLand cover is the physical material or vegetation that covers the surface of the earth, including both natural and human-made features. Understanding land cover patterns and changes over time is critical for addressing global environmental challenges, such as climate change, land degradation, and loss of biodiversity. Land cover classification is the process of assigning land cover classes to pixels in a raster image. With mlr3spatial, we can easily perform a land cover classification within the mlr3 ecosystem.\nBefore we can start the land cover classification, we need to load the necessary packages. The mlr3spatial package relies on terra for processing raster data and sf for vector data. These widely used packages read all common raster and vector formats. Additionally, the stars and raster packages are supported.\n\nlibrary(mlr3verse)\nlibrary(mlr3spatial)\nlibrary(terra, exclude = \"resample\")\nlibrary(sf)\n\nWe will work with a Sentinel-2 scene of the city of Leipzig which consists of 7 bands with a 10 or 20m spatial resolution and an NDVI band. The data is included in the mlr3spatial package. We use the terra::rast() to load the TIFF raster file.\n\nleipzig_raster = rast(system.file(\"extdata\", \"leipzig_raster.tif\", package = \"mlr3spatial\"))\nleipzig_raster\n\nclass : SpatRaster \ndimensions : 206, 154, 8 (nrow, ncol, nlyr)\nresolution : 10, 10 (x, y)\nextent : 731810, 733350, 5692030, 5694090 (xmin, xmax, ymin, ymax)\ncoord. ref. : WGS 84 / UTM zone 32N (EPSG:32632) \nsource : leipzig_raster.tif \nnames : b02, b03, b04, b06, b07, b08, ... \nmin values : 846, 645, 366, 375, 401, 374, ... \nmax values : 4705, 4880, 5451, 4330, 5162, 5749, ... \n\n\nThe training data is a GeoPackage point layer with land cover labels and spectral features. We load the file and create a simple feature point layer.\n\nleipzig_vector = read_sf(system.file(\"extdata\", \"leipzig_points.gpkg\", package = \"mlr3spatial\"), stringsAsFactors = TRUE)\nleipzig_vector\n\nSimple feature collection with 97 features and 9 fields\nGeometry type: POINT\nDimension: XY\nBounding box: xmin: 731930.5 ymin: 5692136 xmax: 733220.3 ymax: 5693968\nProjected CRS: WGS 84 / UTM zone 32N\n# A tibble: 97 × 10\n b02 b03 b04 b06 b07 b08 b11 ndvi land_cover geom\n <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <fct> <POINT [m]>\n 1 903 772 426 2998 4240 4029 1816 0.809 forest (732480.1 5693957)\n 2 1270 1256 1081 1998 2493 2957 2073 0.465 urban (732217.4 5692769)\n 3 1033 996 777 2117 2748 2799 1595 0.565 urban (732737.2 5692469)\n 4 962 773 500 465 505 396 153 -0.116 water (733169.3 5692777)\n 5 1576 1527 1626 1715 1745 1768 1980 0.0418 urban (732202.2 5692644)\n 6 1125 1185 920 3058 3818 3758 2682 0.607 pasture (732153 5693059)\n 7 880 746 424 2502 3500 3397 1469 0.778 forest (731937.9 5693722)\n 8 1332 1251 1385 1663 1799 1640 1910 0.0843 urban (732416.2 5692324)\n 9 940 741 475 452 515 400 139 -0.0857 water (732933.7 5693344)\n10 902 802 454 2764 3821 3666 1567 0.780 forest (732411.3 5693352)\n# ℹ 87 more rows\n\n\nWe plot both layers to get an overview of the data. The training points are located in the districts of Lindenau and Zentrum West.\n\n\nCode\nlibrary(ggplot2)\nlibrary(tidyterra, exclude = \"filter\")\n\nggplot() +\n geom_spatraster_rgb(data = leipzig_raster, r = 3, g = 2, b = 1, max_col_value = 5451) +\n geom_spatvector(data = leipzig_vector, aes(color = land_cover)) +\n scale_color_viridis_d(name = \"Land cover\", labels = c(\"Forest\", \"Pastures\", \"Urban\", \"Water\")) +\n theme_minimal()\n\n\n\n\n\n\n\n\n\nThe as_task_classif_st() function directly creates a spatial task from the point layer. This makes it unnecessary to transform the point layer to a data.frame with coordinates. Spatial tasks additionally store the coordinates of the training points. The coordinates are useful when estimating the performance of the model with spatial resampling.\n\ntask = as_task_classif_st(leipzig_vector, target = \"land_cover\")\ntask\n\n<TaskClassifST:leipzig_vector> (97 x 9)\n* Target: land_cover\n* Properties: multiclass\n* Features (8):\n - dbl (8): b02, b03, b04, b06, b07, b08, b11, ndvi\n* Coordinates:\n X Y\n 1: 732480.1 5693957\n 2: 732217.4 5692769\n 3: 732737.2 5692469\n 4: 733169.3 5692777\n 5: 732202.2 5692644\n--- \n93: 733018.7 5692342\n94: 732551.4 5692887\n95: 732520.4 5692589\n96: 732542.2 5692204\n97: 732437.8 5692300\n\n\nNow we can train a model with the task. We use a simple decision tree learner from the rpart package. The \"classif_st\" task is a specialization of the \"classif\" task and therefore works with all \"classif\" learners.\n\nlearner = lrn(\"classif.rpart\")\nlearner$train(task)\n\nTo get a complete land cover classification of Leipzig, we have to predict on each pixel and return a raster image with these predictions. The $predict() method of the learner only works for tabular data. To predict a raster image, we use the predict_spatial() function.\n\n# predict land cover map\nland_cover = predict_spatial(leipzig_raster, learner)\n\n\n\nCode\nggplot() +\n geom_spatraster(data = land_cover) +\n scale_fill_viridis_d(name = \"Land cover\", labels = c(\"Forest\", \"Pastures\", \"Urban\", \"Water\")) +\n theme_minimal()\n\n\n\n\n\n\n\n\n\n\n\nConclusion\nWorking with spatial data in R is very easy with the mlr3spatial package. You can quickly train a model with a point layer and predict a raster image. The mlr3spatial package is still in development and we are looking forward to your feedback and contributions." + }, + { + "objectID": "gallery/pipelines/2020-06-15-target-transformations-via-pipelines/index.html", + "href": "gallery/pipelines/2020-06-15-target-transformations-via-pipelines/index.html", + "title": "Target Transformations via Pipelines", + "section": "", + "text": "Transforming the target variable often can lead to predictive improvement and is a widely used tool. Typical transformations are for example the \\(\\log\\) transformation of the target aiming at minimizing (right) skewness, or the Box Cox and Yeo-Johnson transformations being more flexible but having a similar goal.\nOne option to perform, e.g., a \\(\\log\\) transformation would be to manually transform the target prior to training a Learner (and also predicting from it) and then manually invert this transformation via \\(\\exp\\) after predicting from the Learner. This is quite cumbersome, especially if a transformation and inverse transformation require information about both the training and prediction data.\nIn this post, we show how to do various kinds of target transformations using mlr3pipelines and explain the design of the target transformation and inversion PipeOps.\nYou will:\n\nlearn how to do simple target transformations using PipeOpTargetMutate\nbe introduced to the abstract base class to implement custom target transformations, PipeOpTargetTrafo\nimplement a custom target transformation PipeOp, PipeOpTargetTrafoBoxCox\n\nAs a prerequisite, you should be quite familiar with mlr3pipelines, i.e, know about the $state field of PipeOps, input and output channels, as well as Graphs. We will start with a PipeOp for simple target transformations, PipeOpTargetMutate.\nWe load the most important packages for this example.\n\nlibrary(mlr3)\nlibrary(mlr3learners)\nlibrary(mlr3pipelines)\nlibrary(paradox)\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\n\nIn all sections we will use the mtcars regression task with mpg being a numerical, positive target:\n\ntask = tsk(\"mtcars\")\nsummary(task$data(cols = task$target_names))\n\n mpg \n Min. :10.40 \n 1st Qu.:15.43 \n Median :19.20 \n Mean :20.09 \n 3rd Qu.:22.80 \n Max. :33.90 \n\n\nMoreover, as a Learner we will use an ordinary linear regression learner:\n\nlearner_lm = lrn(\"regr.lm\")\n\n\nSimple Target Transformations\nThe term simple refers to transformations that are given by a function of the target, relying on no other arguments (constants are of course allowed). The most prominent example is given by the \\(\\log\\) transformation which we can later invert by applying the \\(\\exp\\) transformation.\nIf you are only interested in doing such a transformation and you do not have the time to read more of this post, simply use the following syntactic sugar:\n\ng_ppl = ppl(\"targettrafo\", graph = learner_lm)\ng_ppl$param_set$values$targetmutate.trafo = function(x) log(x)\ng_ppl$param_set$values$targetmutate.inverter = function(x) list(response = exp(x$response))\n\nThis constructs a Graph that will \\(\\log\\) transform the target prior to training the linear regression learner (or predicting from it) and \\(\\exp\\) transform the target after predicting from it. Note that you can supply any other Learner or even a whole Graph as the graph argument.\nNow, we will go into more detail about how this actually works:\nWe can perform a \\(\\log\\) transformation of our numerical, positive target, mpg, using PipeOpTargetMutate (by default, ppl(\"targettrafo\") uses this target transformation PipeOp):\n\ntrafo = po(\"targetmutate\", param_vals = list(trafo = function(x) log(x)))\n\nWe have to specify the trafo parameter as a function of x (which will internally be evaluated to be the target of the Task): trafo = function(x) log(x)). In principle, this is all that is needed to transform the target prior to training a Learner (or predicting from it), i.e., if we now train this PipeOp, we see that the target is transformed as specified:\n\ntrafo$train(list(task))$output$data(cols = task$target_names)\n\n mpg\n 1: 3.044522\n 2: 3.044522\n 3: 3.126761\n 4: 3.063391\n 5: 2.928524\n 6: 2.895912\n 7: 2.660260\n 8: 3.194583\n 9: 3.126761\n10: 2.954910\n11: 2.879198\n12: 2.797281\n13: 2.850707\n14: 2.721295\n15: 2.341806\n16: 2.341806\n17: 2.687847\n18: 3.478158\n19: 3.414443\n20: 3.523415\n21: 3.068053\n22: 2.740840\n23: 2.721295\n24: 2.587764\n25: 2.954910\n26: 3.306887\n27: 3.258097\n28: 3.414443\n29: 2.760010\n30: 2.980619\n31: 2.708050\n32: 3.063391\n mpg\n\n\nAfter having predicted from the Learner we could then proceed to apply the inverse transformation function in a similar manner. However, in mlr3pipelines, we decided to go with a more unified design of handling target transformations. In all target transformation PipeOps also the inverse transformation function of the target has to be specified. Therefore, in PipeOpTargetMutate, the parameter inverter also has to be correctly specified:\n\ntrafo$param_set$values$inverter = function(x) list(response = exp(x$response))\n\nInternally, this function will be applied to the data.table downstream of a Prediction object without the $row_id and $truth columns, and we specify that the $response column should be transformed. Note that applying the inverse transformation will typically only be done to the $response column, because transforming standard errors or probabilities is often not straightforward.\nTo actually carry out the inverse transformation function after predicting from the Learner, we then rely on PipeOpTargetInvert. PipeOpTargetInvert has an empty ParamSet and its sole purpose is to apply the inverse transformation function after having predicted from a Learner (note that this whole design of target transformations may seem somewhat over-engineered at first glance, however, we will learn of its advantages when we later move to the advanced section).\nPipeOpTargetInvert has two input channels named \"fun\" and \"prediction\". During training, both take NULL as input (because this is what a Learner’s \"output\" output and PipeOpTargetMutate’s \"fun\" output will return during training). During prediction, the \"prediction\" input takes a Prediction, and the \"fun\" input takes the \"fun\" output from PipeOpTargetMutate (you may have noticed already, that PipeOpTargetMutate has actually two outputs, \"fun\" and \"output\", with \"fun\" returning NULL during training and a function during prediction, while \"output\" always returns the transformed input Task). We can see this, if we look at:\n\ntrafo$output\n\n name train predict\n1: fun NULL function\n2: output Task Task\n\ntrafo$predict(list(task))\n\n$fun\nfunction(inputs) {\n assert_list(inputs, len = 1L, types = \"Prediction\")\n list(private$.invert(inputs[[1L]], predict_phase_state))\n }\n<bytecode: 0x555be761be00>\n<environment: 0x555be76215b0>\n\n$output\n<TaskRegr:mtcars> (32 x 11): Motor Trends\n* Target: mpg\n* Properties: -\n* Features (10):\n - dbl (10): am, carb, cyl, disp, drat, gear, hp, qsec, vs, wt\n\n\nWe will talk more about such technical details in the advanced section. For now, to finally construct our target transformation pipeline, we build a Graph:\n\ng = Graph$new()\ng$add_pipeop(trafo)\ng$add_pipeop(learner_lm)\ng$add_pipeop(po(\"targetinvert\"))\n\nManually connecting the edges is quite cumbersome. First we connect the \"output\" output of \"targetmutate\" to the \"input\" input of \"regr.lm\":\n\ng$add_edge(src_id = \"targetmutate\", dst_id = \"regr.lm\",\n src_channel = 2, dst_channel = 1)\n\nThen we connect the \"output\" output of \"regr.lm\" to the \"prediction\" input of \"targetinvert\":\n\ng$add_edge(src_id = \"regr.lm\", dst_id = \"targetinvert\",\n src_channel = 1, dst_channel = 2)\n\nFinally, we connect the \"fun\" output of \"targetmutate\" to the \"fun\" input of \"targetinvert\":\n\ng$add_edge(src_id = \"targetmutate\", dst_id = \"targetinvert\",\n src_channel = 1, dst_channel = 1)\n\nThis graph (which is conceptually the same graph as constructed via the ppl(\"targettrafo\") syntactic sugar above) looks like the following:\n\ng$plot(html = FALSE)\n\n\n\n\n\n\n\n\nWe can then finally call $train() and $predict() (prior to this we wrap the Graph in a GraphLearner):\n\ngl = GraphLearner$new(g)\ngl$train(task)\ngl$state\n\n$model\n$model$targetmutate\nlist()\n\n$model$regr.lm\n$model$regr.lm$model\n\nCall:\nstats::lm(formula = task$formula(), data = task$data())\n\nCoefficients:\n(Intercept) am carb cyl disp drat gear hp qsec \n 2.776e+00 4.738e-02 -2.012e-02 7.657e-03 4.989e-05 2.220e-02 5.925e-02 -8.964e-04 3.077e-02 \n vs wt \n -2.874e-03 -1.723e-01 \n\n\n$model$regr.lm$log\nEmpty data.table (0 rows and 3 cols): stage,class,msg\n\n$model$regr.lm$train_time\n[1] 0.012\n\n$model$regr.lm$param_vals\nnamed list()\n\n$model$regr.lm$task_hash\n[1] \"6ca8c90cdf732078\"\n\n$model$regr.lm$data_prototype\nEmpty data.table (0 rows and 11 cols): mpg,am,carb,cyl,disp,drat...\n\n$model$regr.lm$task_prototype\nEmpty data.table (0 rows and 11 cols): mpg,am,carb,cyl,disp,drat...\n\n$model$regr.lm$mlr3_version\n[1] '0.16.1'\n\n$model$regr.lm$train_task\n<TaskRegr:mtcars> (32 x 11): Motor Trends\n* Target: mpg\n* Properties: -\n* Features (10):\n - dbl (10): am, carb, cyl, disp, drat, gear, hp, qsec, vs, wt\n\n\n$model$targetinvert\nlist()\n\n\n$log\nEmpty data.table (0 rows and 3 cols): stage,class,msg\n\n$train_time\n[1] 0.098\n\n$param_vals\n$param_vals$targetmutate.trafo\nfunction(x) log(x)\n<bytecode: 0x555be6fb60f0>\n\n$param_vals$targetmutate.inverter\nfunction(x) list(response = exp(x$response))\n\n\n$task_hash\n[1] \"58a137d2055e8406\"\n\n$data_prototype\nEmpty data.table (0 rows and 11 cols): mpg,am,carb,cyl,disp,drat...\n\n$task_prototype\nEmpty data.table (0 rows and 11 cols): mpg,am,carb,cyl,disp,drat...\n\n$mlr3_version\n[1] '0.16.1'\n\n$train_task\n<TaskRegr:mtcars> (32 x 11): Motor Trends\n* Target: mpg\n* Properties: -\n* Features (10):\n - dbl (10): am, carb, cyl, disp, drat, gear, hp, qsec, vs, wt\n\ngl$predict(task)\n\n<PredictionRegr> for 32 observations:\n row_ids truth response\n 1 21.0 21.67976\n 2 21.0 21.10831\n 3 22.8 25.73690\n--- \n 30 19.7 19.58533\n 31 15.0 14.11015\n 32 21.4 23.11105\n\n\nand contrast this with $train() and $predict() of the naive linear regression learner (also look at the estimated coefficients of the linear regression contained in $state$model):\n\nlearner_lm$train(task)\nlearner_lm$state\n\n$model\n\nCall:\nstats::lm(formula = task$formula(), data = task$data())\n\nCoefficients:\n(Intercept) am carb cyl disp drat gear hp qsec \n 12.30337 2.52023 -0.19942 -0.11144 0.01334 0.78711 0.65541 -0.02148 0.82104 \n vs wt \n 0.31776 -3.71530 \n\n\n$log\nEmpty data.table (0 rows and 3 cols): stage,class,msg\n\n$train_time\n[1] 0.004\n\n$param_vals\nnamed list()\n\n$task_hash\n[1] \"58a137d2055e8406\"\n\n$data_prototype\nEmpty data.table (0 rows and 11 cols): mpg,am,carb,cyl,disp,drat...\n\n$task_prototype\nEmpty data.table (0 rows and 11 cols): mpg,am,carb,cyl,disp,drat...\n\n$mlr3_version\n[1] '0.16.1'\n\n$train_task\n<TaskRegr:mtcars> (32 x 11): Motor Trends\n* Target: mpg\n* Properties: -\n* Features (10):\n - dbl (10): am, carb, cyl, disp, drat, gear, hp, qsec, vs, wt\n\nlearner_lm$predict(task)\n\n<PredictionRegr> for 32 observations:\n row_ids truth response\n 1 21.0 22.59951\n 2 21.0 22.11189\n 3 22.8 26.25064\n--- \n 30 19.7 19.69383\n 31 15.0 13.94112\n 32 21.4 24.36827\n\n\nYou should continue reading, if you are interested in more advanced target transformations, i.e., where the transformation and inverse transformation require information about both the training and prediction data.\nFirst we will introduce the abstract base class for doing target transformations, PipeOpTargetTrafo, from which PipeOpTargetMutate inherits.\n\n\nAbstract Base Class: PipeOpTargetTrafo\nNo matter how “complicated” the actual target transformation and inverse transformation may be, applying the inverse transformation function after having predicted from a Learner will always be done via PipeOpTargetInvert (as already outlined above, PipeOpTargetInvert has an empty ParamSet and its sole purpose is to apply the inverse transformation function after having predicted from a Learner). All Graphs for doing target transformations will therefore look similar like the simple one above, i.e., a target transformation PipeOp followed by some Learner or a whole Graph, followed by PipeOpTargetInvert. Therefore, using ppl(\"targettrafo\") to construct such Graphs is highly recommended.\nTo allow for more advanced target transformations, we now have a closer look at the abstract base class, PipeOpTargetTrafo:\nPipeOpTargetTrafo has one input channel, named \"input\" taking a Task both during training and prediction. It’s two output channels are named \"fun\" and \"output\". During training \"fun\" returns NULL and during prediction \"fun\" returns a function that will be used by PipeOpTargetInvert to perform the inverse target transformation on PipeOpTargetInvert’s \"prediction\" input. \"output\" returns the modified input Task both during training and prediction.\nSubclasses can overload up to four functions:\n\n.get_state() takes the input Task and returns a list() which will internally be used to set the $state. Typically it is sensible to make use of the $state during .transform() and .train_invert(). The base implementation returns list() and should be overloaded if setting the state is desired.\n.transform() takes the input Task and returns a modified Task (i.e., the Task with the transformed target). This is the main function for doing the actual target transformation. Note that .get_state() is evaluated a single time during training right before .transform() and therefore, you can rely on the $state that has been set. To update the input Task with respect to the transformed target, subclasses should make use of the convert_task() function and drop the original target from the Task. .transform() also accepts a phase argument that will receive \"train\" during training and \"predict\" during prediction. This can be used to enable different behavior during training and prediction. .transform() should always be overloaded by subclasses.\n.train_invert() takes the input Task and returns a predict_phase_state object. This can be anything. Note that .train_invert() should not modify the input Task. The base implementation returns a list with a single argument, the $truth column of the input Task and should be overloaded if a more training-phase-dependent state is desired.\n.invert() takes a Prediction and a predict_phase_state object as inputs and returns a Prediction. This is the main function for specifying the actual inverse target transformation that will later be carried out by PipeOpTargetInvert. Internally a private helper function , .invert_help() will construct the function that will be returned by the \"fun\" output of PipeOpTargetTrafo so that PipeOpTargetInvert can later simply dispatch this inverse target transformation on its \"prediction\" input.\n\nThe supposed workflow of a class inherited from PipeOpTargetTrafo is given in the following figure:\n\n\n\n\n\n\n\n\n\nTo solidify our understanding we will design a new target transformation PipeOp in the next section: PipeOpTargetTrafoBoxCox\n\n\nHands on: PipeOpTargetTrafoBoxCox\n\nlibrary(R6)\n\nThe Box-Cox transformation of a target \\(y_{i}\\) is given as:\n\\[y_{i}(\\lambda) = \\begin{cases}\n\\frac{y_{i}^{\\lambda} - 1}{\\lambda} & \\text{if}~\\lambda \\neq 0; \\\\\n\\log(y_{i}) & \\text{if}~\\lambda = 0\n\\end{cases}\\]\nmlr3pipelines already supports the Box-Cox transformation for numerical, positive features, see ?PipeOpBoxCox.\nHere we will design a PipeOp to apply the Box-Cox transformation as a target transformation. The \\(\\lambda\\) parameter of the transformation is estimated during training and used for both the training and prediction transformation. After predicting from a Learner we will as always apply the inverse transformation function. To do the actual transformation we will use bestNormalize::boxcox().\nFirst, we inherit from PipeOpTargetTrafo and overload the initialize() function:\n\nPipeOpTargetTrafoBoxCox = R6Class(\"PipeOpTargetTrafoBoxCox\",\n inherit = PipeOpTargetTrafo,\n public = list(\n initialize = function(id = \"targettrafoboxcox\", param_vals = list()) {\n param_set = ps(\n standardize = p_lgl(default = TRUE, tags = c(\"train\", \"boxcox\")),\n eps = p_dbl(default = 0.001, lower = 0, tags = c(\"train\", \"boxcox\")),\n lower = p_dbl(default = -1L, tags = c(\"train\", \"boxcox\")),\n upper = p_dbl(default = 2L, tags = c(\"train\", \"boxcox\"))\n )\n super$initialize(id = id, param_set = param_set, param_vals = param_vals,\n packages = \"bestNormalize\", task_type_in = \"TaskRegr\",\n task_type_out = \"TaskRegr\")\n }\n ),\n private = list(\n\n .get_state = function(task) {\n ...\n },\n\n .transform = function(task, phase) {\n ...\n },\n\n .train_invert = function(task) {\n ...\n },\n\n .invert = function(prediction, predict_phase_state) {\n ...\n }\n )\n)\n\nAs parameters, we allow \"standardize\" (whether to center and scale the transformed values to attempt a standard normal distribution), \"eps\" (tolerance parameter to identify if the \\(\\lambda\\) parameter is equal to zero), \"lower\" (lower value for the estimation of the \\(\\lambda\\) parameter) and \"upper\" (upper value for the estimation of the \\(\\lambda\\) parameter). Note that we set task_type_in = \"TaskRegr\" and task_type_out = \"TaskRegr\" to specify that this PipeOp only works for regression Tasks.\nSecond, we overload the four functions as mentioned above.\nWe start with .get_state(). We extract the target and apply the Box-Cox transformation to the target. This yields an object of class \"boxcox\" which we will wrap in a list() and set as the $state (bc$x.t = NULL and bc$x = NULL is done to save some memory because we do not need the transformed original data and original data later):\n\n .get_state = function(task) {\n target = task$data(cols = task$target_names)[[1L]]\n bc = mlr3misc::invoke(bestNormalize::boxcox, target,\n .args = self$param_set$get_values(tags = \"boxcox\"))\n bc$x.t = NULL\n bc$x = NULL\n list(bc = bc)\n },\n\nNext, we tackle .transform(). This is quite straightforward, because objects of class \"boxcox\" have their own predict method which we can use here to carry out the actual Box-Cox transformation based on the learned \\(\\lambda\\) parameter as stored in the \"boxcox\" object in the $state (both during training and prediction). We then rename the target, add it to the task and finally update the task with respect to this new target:\n\n .transform = function(task, phase) {\n target = task$data(cols = task$target_names)[[1L]]\n new_target = as.data.table(predict(self$state$bc, newdata = target))\n colnames(new_target) = paste0(task$target_names, \".bc\")\n task$cbind(new_target)\n convert_task(task, target = colnames(new_target),\n drop_original_target = TRUE)\n },\n\nTime to overload .train_invert(). This is even more straightforward, because the prediction method for objects of class \"boxcox\" directly allows for inverting the transformation via setting the argument inverse = TRUE. Therefore, we only need the \"boxcox\" object stored in the $state along the $truth column of the input Task (remember that this list will later be available as the predict_phase_state object):\n\n .train_invert = function(task) {\n list(truth = task$truth(), bc = self$state$bc)\n },\n\nFinally, we overload .invert(). We extract the truth from the predict_phase_state and the response from the Prediction. We then apply the inverse Box-Cox transformation to the response based on the \\(\\lambda\\) parameter and the mean and standard deviation learned during training, relying on the predict_phase_state object. Finally, we construct a new Prediction object:\n\n .invert = function(prediction, predict_phase_state) {\n truth = predict_phase_state$truth\n response = predict(predict_phase_state$bc, newdata = prediction$response,\n inverse = TRUE)\n PredictionRegr$new(row_ids = prediction$row_ids, truth = truth,\n response = response)\n }\n\nNote that this PipeOp is ill-equipped to handle the case of predict_type = \"se\", i.e., we always only return a response prediction (as outlined above, this is the case for most target transformations, because transforming standard errors or probabilities of a prediction is often not straightforward). We could of course check whether the predict_type is set to \"se\" and if this is the case, return NA as the standard errors.\nTo construct our final target transformation Graph with our linear regression learner, we again simply make use of ppl(\"targettrafo\"):\n\ng_bc = ppl(\"targettrafo\", graph = learner_lm,\n trafo_pipeop = PipeOpTargetTrafoBoxCox$new())\n\nThe following plot should already look quite familiar:\n\ng_bc$plot(html = FALSE)\n\n\n\n\n\n\n\n\nFinally we $train() and $predict() on the task (again, we wrap the Graph in a GraphLearner):\n\ngl_bc = GraphLearner$new(g_bc)\ngl_bc$train(task)\ngl_bc$state\n\n$model\n$model$regr.lm\n$model$regr.lm$model\n\nCall:\nstats::lm(formula = task$formula(), data = task$data())\n\nCoefficients:\n(Intercept) am carb cyl disp drat gear hp qsec \n -0.6272999 0.1670950 -0.0663126 0.0237529 0.0002376 0.0759944 0.1963335 -0.0030367 0.1043210 \n vs wt \n -0.0080166 -0.5800635 \n\n\n$model$regr.lm$log\nEmpty data.table (0 rows and 3 cols): stage,class,msg\n\n$model$regr.lm$train_time\n[1] 0.007\n\n$model$regr.lm$param_vals\nnamed list()\n\n$model$regr.lm$task_hash\n[1] \"612ab4e0ad596159\"\n\n$model$regr.lm$data_prototype\nEmpty data.table (0 rows and 11 cols): mpg.bc,am,carb,cyl,disp,drat...\n\n$model$regr.lm$task_prototype\nEmpty data.table (0 rows and 11 cols): mpg.bc,am,carb,cyl,disp,drat...\n\n$model$regr.lm$mlr3_version\n[1] '0.16.1'\n\n$model$regr.lm$train_task\n<TaskRegr:mtcars> (32 x 11): Motor Trends\n* Target: mpg.bc\n* Properties: -\n* Features (10):\n - dbl (10): am, carb, cyl, disp, drat, gear, hp, qsec, vs, wt\n\n\n$model$targettrafoboxcox\n$model$targettrafoboxcox$bc\nStandardized Box Cox Transformation with 32 nonmissing obs.:\n Estimated statistics:\n - lambda = 0.02955701 \n - mean (before standardization) = 3.092016 \n - sd (before standardization) = 0.324959 \n\n\n$model$targetinvert\nlist()\n\n\n$log\nEmpty data.table (0 rows and 3 cols): stage,class,msg\n\n$train_time\n[1] 0.075\n\n$param_vals\nnamed list()\n\n$task_hash\n[1] \"58a137d2055e8406\"\n\n$data_prototype\nEmpty data.table (0 rows and 11 cols): mpg,am,carb,cyl,disp,drat...\n\n$task_prototype\nEmpty data.table (0 rows and 11 cols): mpg,am,carb,cyl,disp,drat...\n\n$mlr3_version\n[1] '0.16.1'\n\n$train_task\n<TaskRegr:mtcars> (32 x 11): Motor Trends\n* Target: mpg\n* Properties: -\n* Features (10):\n - dbl (10): am, carb, cyl, disp, drat, gear, hp, qsec, vs, wt\n\ngl_bc$predict(task)\n\n<PredictionRegr> for 32 observations:\n row_ids truth response\n 1 21.0 21.70854\n 2 21.0 21.13946\n 3 22.8 25.75242\n--- \n 30 19.7 19.58934\n 31 15.0 14.10658\n 32 21.4 23.15263\n\n\nWe could now proceed to benchmark our different target transformations:\n\nbg = benchmark_grid(list(task), learners = list(learner_lm, gl, gl_bc),\n resamplings = list(rsmp(\"cv\", folds = 10)))\nbmr = benchmark(bg)\n\n\nbmr$aggregate(msr(\"regr.mse\"))\n\n nr task_id learner_id resampling_id iters regr.mse\n1: 1 mtcars regr.lm cv 10 11.866071\n2: 2 mtcars targetmutate.regr.lm.targetinvert cv 10 7.793303\n3: 3 mtcars targettrafoboxcox.regr.lm.targetinvert cv 10 8.230192\nHidden columns: resample_result" + }, + { + "objectID": "gallery/pipelines/2020-04-18-regression-chains/index.html", + "href": "gallery/pipelines/2020-04-18-regression-chains/index.html", + "title": "Regression Chains", + "section": "", + "text": "In this tutorial we demonstrate how to use mlr3pipelines to handle multi-target regression by arranging regression models as a chain, i.e., creating a linear sequence of regression models.\n\nRegression Chains\nIn a simple regression chain, regression models are arranged in a linear sequence. Here, the first model will use the input to predict a single output and the second model will use the input and the prediction output of the first model to make its own prediction and so on. For more details, see e.g. Spyromitros-Xioufis et al. (2016).\n\n\nBefore you start\nThe following sections describe an approach towards working with tasks that have multiple targets. E.g., in the example below, we have three target variables \\(y_{1}\\) to \\(y_{3}\\). This type of Task can be created via the mlr3multioutput package (currently under development) in the future. mlr3multioutput will also offer simple chaining approaches as pre-built pipelines (so called ppls). The current goal of this post is to show how such modeling steps can be written as a relatively small amount of pipeline steps and how such steps can be put together. Writing pipelines with such steps allows for great flexibility in modeling more complicated scenarios such as the ones described below.\n\n\nPrerequisites\nWe load the mlr3verse package which pulls in the most important packages for this example.\n\nlibrary(mlr3verse)\n\nLoading required package: mlr3\n\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\n\n\n\nData\nIn the following, we rely on some toy data. We simulate 100 responses to three target variables, \\(y_{1}\\), \\(y_{2}\\), and \\(y_{3}\\) following a multivariate normal distribution with a mean and covariance matrix of:\n\nlibrary(data.table)\nlibrary(mvtnorm)\nset.seed(2409)\nn = 100\n(mean <- c(y1 = 1, y2 = 2, y3 = 3))\n\ny1 y2 y3 \n 1 2 3 \n\n(sigma <- matrix(c(1, -0.5, 0.25, -0.5, 1, -0.25, 0.25, -0.25, 1),\n nrow = 3, ncol = 3, byrow = TRUE\n))\n\n [,1] [,2] [,3]\n[1,] 1.00 -0.50 0.25\n[2,] -0.50 1.00 -0.25\n[3,] 0.25 -0.25 1.00\n\nY = rmvnorm(n, mean = mean, sigma = sigma)\n\nThe feature variables \\(x_{1}\\), and \\(x_{2}\\) are simulated as follows: \\(x_{1}\\) is simply given by \\(y_{1}\\) and an independent normally distributed error term and \\(x_{2}\\) is given by \\(y_{2}\\) and an independent normally distributed error term.\n\nx1 = Y[, 1] + rnorm(n, sd = 0.1)\nx2 = Y[, 2] + rnorm(n, sd = 0.1)\n\nThe final data is given as:\n\ndata = as.data.table(cbind(Y, x1, x2))\nstr(data)\n\nClasses 'data.table' and 'data.frame': 100 obs. of 5 variables:\n $ y1: num 0.681 1.836 0.355 1.783 0.974 ...\n $ y2: num 2.33 1.735 3.126 0.691 1.573 ...\n $ y3: num 3.19 3.14 2.74 4.31 2.77 ...\n $ x1: num 0.788 1.754 0.174 1.844 1.05 ...\n $ x2: num 2.336 1.665 2.967 0.651 1.634 ...\n - attr(*, \".internal.selfref\")=<externalptr> \n\n\nThis simulates a situation where we have multiple target variables that are correlated with each other, such that predicting them along with each other can improve the resulting prediction model. As a real-world example for such a situation, consider e.g. hospital data, where time spent in the ICU (not known a priori) heavily influences the cost incurred by a patient’s treatment.\n\n\n3D Visualization of the Data\nIf you feel confident to already have a good feeling of the data, feel free to skip this section. If not, you can use the rgl package to play around with the following four 3D plots with either the feature variables or \\(y_{1}\\) and \\(y_{2}\\) on the x- and y-axis and the target variables on the respective z-axes:\n\nlibrary(rgl)\ncolfun = colorRampPalette(c(\"#161B1D\", \"#ADD8E6\"))\n\n\nsetorder(data, y1)\nplot3d(data$x1, data$x2, data$y1,\n xlab = \"x1\", ylab = \"x2\", zlab = \"y1\",\n type = \"s\", radius = 0.1, col = colfun(n)\n)\n\n\nsetorder(data, y2)\nplot3d(data$x1, data$x2, data$y2,\n xlab = \"x1\", ylab = \"x2\", zlab = \"y2\",\n type = \"s\", radius = 0.1, col = colfun(n)\n)\n\n\nsetorder(data, y3)\nplot3d(data$x1, data$x2, data$y3,\n xlab = \"x1\", ylab = \"x2\", zlab = \"y3\",\n type = \"s\", radius = 0.1, col = colfun(n)\n)\n\n\nsetorder(data, y3)\nplot3d(data$y1, data$y2, data$y3,\n xlab = \"y1\", ylab = \"y2\", zlab = \"y3\",\n type = \"s\", radius = 0.1, col = colfun(n)\n)\n\n\n\nBuilding the Pipeline\nIn our regression chain, the first model will predict \\(y_{1}\\). Therefore, we initialize our Task with respect to this target:\n\ntask = as_task_regr(data, id = \"multiregression\", target = \"y1\")\n\nAs Learners we will use simple linear regression models. Our pipeline building the regression chain then has to do the following:\n\nUse the input to predict \\(y_{1}\\) within the first learner (i.e., \\(y_{1} \\sim x_{1} + x_{2}\\)).\nCombine the input with the prediction of \\(y_{1}\\), \\(\\hat{y_{1}}\\) and use this to predict \\(y_{2}\\) within the second learner (i.e., \\(y_{2} \\sim x_{1} + x_{2} + \\hat{y_{1}}\\)).\nCombine the input with the prediction of \\(y_{2}\\) and use this to predict \\(y_{3}\\) within the final third learner (i.e., \\(y_{3} \\sim x_{1} + x_{2} + \\hat{y_{1}} + \\hat{y_{2}}\\)).\n\nTo combine predictions of a Learner with the previous input, we rely on PipeOpLearnerCV and PipeOpNOP arranged in parallel via gunion() combined via PipeOpFeatureUnion. To drop the respective remaining target variables as features, we rely on PipeOpColRoles. The first step of predicting \\(y_{1}\\) looks like the following:\n\nstep1 = po(\"copy\", outnum = 2, id = \"copy1\") %>>%\n gunion(list(\n po(\"colroles\",\n id = \"drop_y2_y3\",\n new_role = list(y2 = character(), y3 = character())\n ) %>>%\n po(\"learner_cv\", learner = lrn(\"regr.lm\"), id = \"y1_learner\"),\n po(\"nop\", id = \"nop1\")\n )) %>>%\n po(\"featureunion\", id = \"union1\")\nstep1$plot(html = FALSE)\n\n\n\n\n\n\n\n\nTraining using the input Task, shows us how the output and the $state look like:\n\nstep1_out = step1$train(task)[[1]]\nstep1_out\n\n<TaskRegr:multiregression> (100 x 6)\n* Target: y1\n* Properties: -\n* Features (5):\n - dbl (5): x1, x2, y1_learner.response, y2, y3\n\nstep1$state\n\n$copy1\nlist()\n\n$drop_y2_y3\n$drop_y2_y3$dt_columns\n[1] \"x1\" \"x2\" \"y2\" \"y3\"\n\n$drop_y2_y3$affected_cols\n[1] \"x1\" \"x2\" \"y2\" \"y3\"\n\n$drop_y2_y3$intasklayout\n id type\n1: x1 numeric\n2: x2 numeric\n3: y2 numeric\n4: y3 numeric\n\n$drop_y2_y3$outtasklayout\n id type\n1: x1 numeric\n2: x2 numeric\n\n$drop_y2_y3$outtaskshell\nEmpty data.table (0 rows and 3 cols): y1,x1,x2\n\n\n$y1_learner\n$y1_learner$model\n\nCall:\nstats::lm(formula = task$formula(), data = task$data())\n\nCoefficients:\n(Intercept) x1 x2 \n -0.03762 0.99851 0.01364 \n\n\n$y1_learner$log\nEmpty data.table (0 rows and 3 cols): stage,class,msg\n\n$y1_learner$train_time\n[1] 0.004\n\n$y1_learner$param_vals\nnamed list()\n\n$y1_learner$task_hash\n[1] \"933a5b384a9aaebf\"\n\n$y1_learner$data_prototype\nEmpty data.table (0 rows and 3 cols): y1,x1,x2\n\n$y1_learner$task_prototype\nEmpty data.table (0 rows and 3 cols): y1,x1,x2\n\n$y1_learner$mlr3_version\n[1] '0.16.1'\n\n$y1_learner$train_task\n<TaskRegr:multiregression> (100 x 3)\n* Target: y1\n* Properties: -\n* Features (2):\n - dbl (2): x1, x2\n\n$y1_learner$affected_cols\n[1] \"x1\" \"x2\"\n\n$y1_learner$intasklayout\n id type\n1: x1 numeric\n2: x2 numeric\n\n$y1_learner$outtasklayout\n id type\n1: y1_learner.response numeric\n\n$y1_learner$outtaskshell\nEmpty data.table (0 rows and 2 cols): y1,y1_learner.response\n\n\n$nop1\nlist()\n\n$union1\nlist()\n\n\nWithin the second step we then have to define \\(y_{2}\\) as the new target. This can be done using PipeOpUpdateTarget (note that PipeOpUpdateTarget currently is not exported but will be in a future version). By default, PipeOpUpdateTarget drops the original target from the feature set, here \\(y_{1}\\).\n\nmlr_pipeops$add(\"update_target\", mlr3pipelines:::PipeOpUpdateTarget)\n\n\nstep2 = po(\"update_target\",\n id = \"y2_target\",\n new_target_name = \"y2\"\n) %>>%\n po(\"copy\", outnum = 2, id = \"copy2\") %>>%\n gunion(list(\n po(\"colroles\",\n id = \"drop_y3\",\n new_role = list(y3 = character())\n ) %>>%\n po(\"learner_cv\", learner = lrn(\"regr.lm\"), id = \"y2_learner\"),\n po(\"nop\", id = \"nop2\")\n )) %>>%\n po(\"featureunion\", id = \"union2\")\n\nAgain, we can train to see how the output and $state look like, but now using the output of step1 as the input:\n\nstep2_out = step2$train(step1_out)[[1]]\nstep2_out\n\n<TaskRegr:multiregression> (100 x 6)\n* Target: y2\n* Properties: -\n* Features (5):\n - dbl (5): x1, x2, y1_learner.response, y2_learner.response, y3\n\nstep2$state\n\n$y2_target\nlist()\n\n$copy2\nlist()\n\n$drop_y3\n$drop_y3$dt_columns\n[1] \"x1\" \"x2\" \"y1_learner.response\" \"y3\" \n\n$drop_y3$affected_cols\n[1] \"y1_learner.response\" \"x1\" \"x2\" \"y3\" \n\n$drop_y3$intasklayout\n id type\n1: x1 numeric\n2: x2 numeric\n3: y1_learner.response numeric\n4: y3 numeric\n\n$drop_y3$outtasklayout\n id type\n1: x1 numeric\n2: x2 numeric\n3: y1_learner.response numeric\n\n$drop_y3$outtaskshell\nEmpty data.table (0 rows and 4 cols): y2,y1_learner.response,x1,x2\n\n\n$y2_learner\n$y2_learner$model\n\nCall:\nstats::lm(formula = task$formula(), data = task$data())\n\nCoefficients:\n (Intercept) y1_learner.response x1 x2 \n 0.07135 0.22773 -0.25186 0.97877 \n\n\n$y2_learner$log\nEmpty data.table (0 rows and 3 cols): stage,class,msg\n\n$y2_learner$train_time\n[1] 0.01\n\n$y2_learner$param_vals\nnamed list()\n\n$y2_learner$task_hash\n[1] \"1bc5196bab655ff5\"\n\n$y2_learner$data_prototype\nEmpty data.table (0 rows and 4 cols): y2,y1_learner.response,x1,x2\n\n$y2_learner$task_prototype\nEmpty data.table (0 rows and 4 cols): y2,y1_learner.response,x1,x2\n\n$y2_learner$mlr3_version\n[1] '0.16.1'\n\n$y2_learner$train_task\n<TaskRegr:multiregression> (100 x 4)\n* Target: y2\n* Properties: -\n* Features (3):\n - dbl (3): x1, x2, y1_learner.response\n\n$y2_learner$affected_cols\n[1] \"y1_learner.response\" \"x1\" \"x2\" \n\n$y2_learner$intasklayout\n id type\n1: x1 numeric\n2: x2 numeric\n3: y1_learner.response numeric\n\n$y2_learner$outtasklayout\n id type\n1: y2_learner.response numeric\n\n$y2_learner$outtaskshell\nEmpty data.table (0 rows and 2 cols): y2,y2_learner.response\n\n\n$nop2\nlist()\n\n$union2\nlist()\n\n\nIn the final third step we define \\(y_{3}\\) as the new target (again, PipeOpUpdateTarget drops the previous original target from the feature set, here \\(y_{2}\\)):\n\nstep3 = po(\"update_target\",\n id = \"y3_target\",\n new_target_name = \"y3\"\n) %>>%\n po(\"learner\", learner = lrn(\"regr.lm\"), id = \"y3_learner\")\n\nUsing the output of step2 as input:\n\nstep3_out = step3$train(step2_out)[[1]]\nstep3_out\n\nNULL\n\nstep3$state\n\n$y3_target\nlist()\n\n$y3_learner\n$y3_learner$model\n\nCall:\nstats::lm(formula = task$formula(), data = task$data())\n\nCoefficients:\n (Intercept) y2_learner.response y1_learner.response x1 x2 \n 2.6445 0.8155 3.8776 -3.5217 -0.7304 \n\n\n$y3_learner$log\nEmpty data.table (0 rows and 3 cols): stage,class,msg\n\n$y3_learner$train_time\n[1] 0.013\n\n$y3_learner$param_vals\nnamed list()\n\n$y3_learner$task_hash\n[1] \"24dbd64658d33d6d\"\n\n$y3_learner$data_prototype\nEmpty data.table (0 rows and 5 cols): y3,y2_learner.response,y1_learner.response,x1,x2\n\n$y3_learner$task_prototype\nEmpty data.table (0 rows and 5 cols): y3,y2_learner.response,y1_learner.response,x1,x2\n\n$y3_learner$mlr3_version\n[1] '0.16.1'\n\n$y3_learner$train_task\n<TaskRegr:multiregression> (100 x 5)\n* Target: y3\n* Properties: -\n* Features (4):\n - dbl (4): x1, x2, y1_learner.response, y2_learner.response\n\n\nThe complete pipeline, more precisely Graph, looks like the following:\n\ngraph = step1 %>>% step2 %>>% step3\ngraph$plot(html = FALSE)\n\n\n\n\n\n\n\n\n\n\nEvaluating the Pipeline\nBy wrapping our Graph in a GraphLearner, we can perform 3-fold cross-validation and get an estimated average of the root-mean-square error (of course, in a real world setting splitting the data in a training and test set should have been done):\n\nlearner = as_learner(graph)\nrr = resample(task, learner, rsmp(\"cv\", folds = 3))\nrr$aggregate(msr(\"regr.mse\"))\n\n regr.mse \n0.7265587 \n\n\n\n\nPredicting with the Pipeline\nFor completeness, we also show how a prediction step without having any target variable data available would look like:\n\ndata_predict = as.data.table(cbind(x1, x2, y1 = NA, y2 = NA, y3 = NA))\nlearner$train(task)\nlearner$predict_newdata(data_predict)\n\n<PredictionRegr> for 100 observations:\n row_ids truth response\n 1 NA 3.116960\n 2 NA 3.327345\n 3 NA 3.010821\n--- \n 98 NA 3.462541\n 99 NA 3.020585\n 100 NA 3.664326\n\n\nNote that we have to initialize the Task with \\(y_{1}\\) as the target but the pipeline will automatically predict \\(y_{3}\\) in the final step as our final target, which was our ultimate goal here.\n\n\n\n\n\nReferences\n\nSpyromitros-Xioufis, Eleftherios, Grigorios Tsoumakas, William Groves, and Ioannis Vlahavas. 2016. “Multi-Target Regression via Input Space Expansion: Treating Targets as Inputs.” Machine Learning 104 (1): 55–98. https://doi.org/10.1007/s10994-016-5546-z." + }, + { + "objectID": "gallery/pipelines/2020-04-23-pipelines-selectors-branches/index.html", + "href": "gallery/pipelines/2020-04-23-pipelines-selectors-branches/index.html", + "title": "Pipelines, Selectors, Branches", + "section": "", + "text": "mlr3pipelines offers a very flexible way to create data preprocessing steps. This is achieved by a modular approach using PipeOps. For detailed overview check the mlr3book.\nRecommended prior readings:\n\nmlr3pipelines tutorial - german credit\nImpute missing variables .\n\nThis post covers:\n\nHow to apply different preprocessing steps on different features\nHow to branch different preprocessing steps, which allows to select the best performing path\nHow to tune the whole pipeline" + }, + { + "objectID": "gallery/pipelines/2020-04-23-pipelines-selectors-branches/index.html#intro", + "href": "gallery/pipelines/2020-04-23-pipelines-selectors-branches/index.html#intro", + "title": "Pipelines, Selectors, Branches", + "section": "", + "text": "mlr3pipelines offers a very flexible way to create data preprocessing steps. This is achieved by a modular approach using PipeOps. For detailed overview check the mlr3book.\nRecommended prior readings:\n\nmlr3pipelines tutorial - german credit\nImpute missing variables .\n\nThis post covers:\n\nHow to apply different preprocessing steps on different features\nHow to branch different preprocessing steps, which allows to select the best performing path\nHow to tune the whole pipeline" + }, + { + "objectID": "gallery/pipelines/2020-04-23-pipelines-selectors-branches/index.html#prerequisites", + "href": "gallery/pipelines/2020-04-23-pipelines-selectors-branches/index.html#prerequisites", + "title": "Pipelines, Selectors, Branches", + "section": "Prerequisites", + "text": "Prerequisites\nWe load the mlr3verse package which pulls in the most important packages for this example.\n\nlibrary(mlr3verse)\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\nlgr::get_logger(\"bbotk\")$set_threshold(\"warn\")\n\nThe Pima Indian Diabetes classification task will be used.\n\ntask_pima = tsk(\"pima\")\nskimr::skim(task_pima$data())\n\n\nData summary\n\n\nName\ntask_pima$data()\n\n\nNumber of rows\n768\n\n\nNumber of columns\n9\n\n\nKey\nNULL\n\n\n_______________________\n\n\n\nColumn type frequency:\n\n\n\nfactor\n1\n\n\nnumeric\n8\n\n\n________________________\n\n\n\nGroup variables\nNone\n\n\n\nVariable type: factor\n\n\n\n\n\n\n\n\n\n\n\nskim_variable\nn_missing\ncomplete_rate\nordered\nn_unique\ntop_counts\n\n\n\n\ndiabetes\n0\n1\nFALSE\n2\nneg: 500, pos: 268\n\n\n\nVariable type: numeric\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nskim_variable\nn_missing\ncomplete_rate\nmean\nsd\np0\np25\np50\np75\np100\nhist\n\n\n\n\nage\n0\n1.00\n33.24\n11.76\n21.00\n24.00\n29.00\n41.00\n81.00\n▇▃▁▁▁\n\n\nglucose\n5\n0.99\n121.69\n30.54\n44.00\n99.00\n117.00\n141.00\n199.00\n▁▇▇▃▂\n\n\ninsulin\n374\n0.51\n155.55\n118.78\n14.00\n76.25\n125.00\n190.00\n846.00\n▇▂▁▁▁\n\n\nmass\n11\n0.99\n32.46\n6.92\n18.20\n27.50\n32.30\n36.60\n67.10\n▅▇▃▁▁\n\n\npedigree\n0\n1.00\n0.47\n0.33\n0.08\n0.24\n0.37\n0.63\n2.42\n▇▃▁▁▁\n\n\npregnant\n0\n1.00\n3.85\n3.37\n0.00\n1.00\n3.00\n6.00\n17.00\n▇▃▂▁▁\n\n\npressure\n35\n0.95\n72.41\n12.38\n24.00\n64.00\n72.00\n80.00\n122.00\n▁▃▇▂▁\n\n\ntriceps\n227\n0.70\n29.15\n10.48\n7.00\n22.00\n29.00\n36.00\n99.00\n▆▇▁▁▁" + }, + { + "objectID": "gallery/pipelines/2020-04-23-pipelines-selectors-branches/index.html#selection-of-features-for-preprocessing-steps", + "href": "gallery/pipelines/2020-04-23-pipelines-selectors-branches/index.html#selection-of-features-for-preprocessing-steps", + "title": "Pipelines, Selectors, Branches", + "section": "Selection of features for preprocessing steps", + "text": "Selection of features for preprocessing steps\nSeveral features of the pima task have missing values:\n\ntask_pima$missings()\n\ndiabetes age glucose insulin mass pedigree pregnant pressure triceps \n 0 0 5 374 11 0 0 35 227 \n\n\nA common approach in such situations is to impute the missing values and to add a missing indicator column as explained in the Impute missing variables post. Suppose we want to use\n\nPipeOpImputeHist on features “glucose”, “mass” and “pressure” which have only few missing values and\nPipeOpImputeMedian on features “insulin” and “triceps” which have much more missing values.\n\nIn the following subsections, we show two approaches to implement this.\n\n1. Consider all features and apply the preprocessing step only to certain features\nUsing the affect_columns argument of a PipeOp to define the variables on which a PipeOp will operate with an appropriate Selector function:\n\n# imputes values based on histogram\nimputer_hist = po(\"imputehist\",\n affect_columns = selector_name(c(\"glucose\", \"mass\", \"pressure\")))\n# imputes values using the median\nimputer_median = po(\"imputemedian\",\n affect_columns = selector_name(c(\"insulin\", \"triceps\")))\n# adds an indicator column for each feature with missing values\nmiss_ind = po(\"missind\")\n\nWhen PipeOps are constructed this way, they will perform the specified preprocessing step on the appropriate features and pass all the input features to the subsequent steps:\n\n# no missings in \"glucose\", \"mass\" and \"pressure\"\nimputer_hist$train(list(task_pima))[[1]]$missings()\n\ndiabetes age insulin pedigree pregnant triceps glucose mass pressure \n 0 0 374 0 0 227 0 0 0 \n\n# no missings in \"insulin\" and \"triceps\"\nimputer_median$train(list(task_pima))[[1]]$missings()\n\ndiabetes age glucose mass pedigree pregnant pressure insulin triceps \n 0 0 5 11 0 0 35 0 0 \n\n\nWe construct a pipeline that combines imputer_hist and imputer_median. Here, imputer_hist will impute the features “glucose”, “mass” and “pressure”, and imputer_median will impute “insulin” and “triceps”. In each preprocessing step, all the input features are passed to the next step. In the end, we obtain a data set without missing values:\n\n# combine the two impuation methods\nimpute_graph = imputer_hist %>>% imputer_median\nimpute_graph$plot(html = FALSE)\n\n\n\n\n\n\n\nimpute_graph$train(task_pima)[[1]]$missings()\n\ndiabetes age pedigree pregnant glucose mass pressure insulin triceps \n 0 0 0 0 0 0 0 0 0 \n\n\nThe PipeOpMissInd operator replaces features with missing values with a missing value indicator:\n\nmiss_ind$train(list(task_pima))[[1]]$data()\n\n diabetes missing_glucose missing_insulin missing_mass missing_pressure missing_triceps\n 1: pos present missing present present present\n 2: neg present missing present present present\n 3: pos present missing present present missing\n 4: neg present present present present present\n 5: pos present present present present present\n --- \n764: neg present present present present present\n765: neg present missing present present present\n766: neg present present present present present\n767: pos present missing present present missing\n768: neg present missing present present present\n\n\nObviously, this step can not be applied to the already imputed data as there are no missing values. If we want to combine the previous two imputation steps with a third step that adds missing value indicators, we would need to PipeOpCopy the data two times and supply the first copy to impute_graph and the second copy to miss_ind using gunion(). Finally, the two outputs can be combined with PipeOpFeatureUnion:\n\nimpute_missind = po(\"copy\", 2) %>>%\n gunion(list(impute_graph, miss_ind)) %>>%\n po(\"featureunion\")\nimpute_missind$plot(html = FALSE)\n\n\n\n\n\n\n\n\n\nimpute_missind$train(task_pima)[[1]]$data()\n\n diabetes age pedigree pregnant glucose mass pressure insulin triceps missing_glucose missing_insulin missing_mass\n 1: pos 50 0.627 6 148 33.6 72 125 35 present missing present\n 2: neg 31 0.351 1 85 26.6 66 125 29 present missing present\n 3: pos 32 0.672 8 183 23.3 64 125 29 present missing present\n 4: neg 21 0.167 1 89 28.1 66 94 23 present present present\n 5: pos 33 2.288 0 137 43.1 40 168 35 present present present\n --- \n764: neg 63 0.171 10 101 32.9 76 180 48 present present present\n765: neg 27 0.340 2 122 36.8 70 125 27 present missing present\n766: neg 30 0.245 5 121 26.2 72 112 23 present present present\n767: pos 47 0.349 1 126 30.1 60 125 29 present missing present\n768: neg 23 0.315 1 93 30.4 70 125 31 present missing present\n missing_pressure missing_triceps\n 1: present present\n 2: present present\n 3: present missing\n 4: present present\n 5: present present\n --- \n764: present present\n765: present present\n766: present present\n767: present missing\n768: present present\n\n\n\n\n2. Select the features for each preprocessing step and apply the preprocessing steps to this subset\nWe can use the PipeOpSelect to select the appropriate features and then apply the desired impute PipeOp on them:\n\nimputer_hist_2 = po(\"select\",\n selector = selector_name(c(\"glucose\", \"mass\", \"pressure\")),\n id = \"slct1\") %>>% # unique id so we can combine it in a pipeline with other select PipeOps\n po(\"imputehist\")\n\nimputer_hist_2$plot(html = FALSE)\n\n\n\n\n\n\n\n\n\nimputer_hist_2$train(task_pima)[[1]]$data()\n\n diabetes glucose mass pressure\n 1: pos 148 33.6 72\n 2: neg 85 26.6 66\n 3: pos 183 23.3 64\n 4: neg 89 28.1 66\n 5: pos 137 43.1 40\n --- \n764: neg 101 32.9 76\n765: neg 122 36.8 70\n766: neg 121 26.2 72\n767: pos 126 30.1 60\n768: neg 93 30.4 70\n\n\n\nimputer_median_2 =\n po(\"select\", selector = selector_name(c(\"insulin\", \"triceps\")), id = \"slct2\") %>>%\n po(\"imputemedian\")\n\nimputer_median_2$train(task_pima)[[1]]$data()\n\n diabetes insulin triceps\n 1: pos 125 35\n 2: neg 125 29\n 3: pos 125 29\n 4: neg 94 23\n 5: pos 168 35\n --- \n764: neg 180 48\n765: neg 125 27\n766: neg 112 23\n767: pos 125 29\n768: neg 125 31\n\n\nTo reproduce the result of the fist example (1.), we need to copy the data four times and apply imputer_hist_2, imputer_median_2 and miss_ind on each of the three copies. The fourth copy is required to select the features without missing values and to append it to the final result. We can do this as follows:\n\nother_features = task_pima$feature_names[task_pima$missings()[-1] == 0]\n\nimputer_missind_2 = po(\"copy\", 4) %>>%\n gunion(list(imputer_hist_2,\n imputer_median_2,\n miss_ind,\n po(\"select\", selector = selector_name(other_features), id = \"slct3\"))) %>>%\n po(\"featureunion\")\n\nimputer_missind_2$plot(html = FALSE)\n\n\n\n\n\n\n\n\n\nimputer_missind_2$train(task_pima)[[1]]$data()\n\n diabetes glucose mass pressure insulin triceps missing_glucose missing_insulin missing_mass missing_pressure\n 1: pos 148 33.6 72 125 35 present missing present present\n 2: neg 85 26.6 66 125 29 present missing present present\n 3: pos 183 23.3 64 125 29 present missing present present\n 4: neg 89 28.1 66 94 23 present present present present\n 5: pos 137 43.1 40 168 35 present present present present\n --- \n764: neg 101 32.9 76 180 48 present present present present\n765: neg 122 36.8 70 125 27 present missing present present\n766: neg 121 26.2 72 112 23 present present present present\n767: pos 126 30.1 60 125 29 present missing present present\n768: neg 93 30.4 70 125 31 present missing present present\n missing_triceps age pedigree pregnant\n 1: present 50 0.627 6\n 2: present 31 0.351 1\n 3: missing 32 0.672 8\n 4: present 21 0.167 1\n 5: present 33 2.288 0\n --- \n764: present 63 0.171 10\n765: present 27 0.340 2\n766: present 30 0.245 5\n767: missing 47 0.349 1\n768: present 23 0.315 1\n\n\nNote that when there is one input channel, it is automatically copied as many times as needed for the downstream PipeOps. In other words, the code above works also without po(\"copy\", 4):\n\nimputer_missind_3 = gunion(list(imputer_hist_2,\n imputer_median_2,\n miss_ind,\n po(\"select\", selector = selector_name(other_features), id = \"slct3\"))) %>>%\n po(\"featureunion\")\n\nimputer_missind_3$train(task_pima)[[1]]$data()\n\n diabetes glucose mass pressure insulin triceps missing_glucose missing_insulin missing_mass missing_pressure\n 1: pos 148 33.6 72 125 35 present missing present present\n 2: neg 85 26.6 66 125 29 present missing present present\n 3: pos 183 23.3 64 125 29 present missing present present\n 4: neg 89 28.1 66 94 23 present present present present\n 5: pos 137 43.1 40 168 35 present present present present\n --- \n764: neg 101 32.9 76 180 48 present present present present\n765: neg 122 36.8 70 125 27 present missing present present\n766: neg 121 26.2 72 112 23 present present present present\n767: pos 126 30.1 60 125 29 present missing present present\n768: neg 93 30.4 70 125 31 present missing present present\n missing_triceps age pedigree pregnant\n 1: present 50 0.627 6\n 2: present 31 0.351 1\n 3: missing 32 0.672 8\n 4: present 21 0.167 1\n 5: present 33 2.288 0\n --- \n764: present 63 0.171 10\n765: present 27 0.340 2\n766: present 30 0.245 5\n767: missing 47 0.349 1\n768: present 23 0.315 1\n\n\nUsually, po(\"copy\") is required when there are more than one input channels and multiple output channels, and their numbers do not match." + }, + { + "objectID": "gallery/pipelines/2020-04-23-pipelines-selectors-branches/index.html#branching", + "href": "gallery/pipelines/2020-04-23-pipelines-selectors-branches/index.html#branching", + "title": "Pipelines, Selectors, Branches", + "section": "Branching", + "text": "Branching\nWe can not know if the combination of a learner with this preprocessing graph will benefit from the imputation steps and the added missing value indicators. Maybe it would have been better to just use imputemedian on all the variables. We could investigate this assumption by adding an alternative path to the graph with the mentioned imputemedian. This is possible using the “branch” PipeOp:\n\nimputer_median_3 = po(\"imputemedian\", id = \"simple_median\") # add the id so it does not clash with `imputer_median`\n\nbranches = c(\"impute_missind\", \"simple_median\") # names of the branches\n\ngraph_branch = po(\"branch\", branches) %>>%\n gunion(list(impute_missind, imputer_median_3)) %>>%\n po(\"unbranch\")\n\ngraph_branch$plot(html = FALSE)" + }, + { + "objectID": "gallery/pipelines/2020-04-23-pipelines-selectors-branches/index.html#tuning-the-pipeline", + "href": "gallery/pipelines/2020-04-23-pipelines-selectors-branches/index.html#tuning-the-pipeline", + "title": "Pipelines, Selectors, Branches", + "section": "Tuning the pipeline", + "text": "Tuning the pipeline\nTo finalize the graph, we combine it with a rpart learner:\n\ngraph = graph_branch %>>%\n lrn(\"classif.rpart\")\n\ngraph$plot(html = FALSE)\n\n\n\n\n\n\n\n\nTo define the parameters to be tuned, we first check the available ones in the graph:\n\nas.data.table(graph$param_set)[, .(id, class, lower, upper, nlevels)]\n\n id class lower upper nlevels\n 1: branch.selection ParamFct NA NA 2\n 2: imputehist.affect_columns ParamUty NA NA Inf\n 3: imputemedian.affect_columns ParamUty NA NA Inf\n 4: missind.which ParamFct NA NA 2\n 5: missind.type ParamFct NA NA 4\n 6: missind.affect_columns ParamUty NA NA Inf\n 7: simple_median.affect_columns ParamUty NA NA Inf\n 8: classif.rpart.cp ParamDbl 0 1 Inf\n 9: classif.rpart.keep_model ParamLgl NA NA 2\n10: classif.rpart.maxcompete ParamInt 0 Inf Inf\n11: classif.rpart.maxdepth ParamInt 1 30 30\n12: classif.rpart.maxsurrogate ParamInt 0 Inf Inf\n13: classif.rpart.minbucket ParamInt 1 Inf Inf\n14: classif.rpart.minsplit ParamInt 1 Inf Inf\n15: classif.rpart.surrogatestyle ParamInt 0 1 2\n16: classif.rpart.usesurrogate ParamInt 0 2 3\n17: classif.rpart.xval ParamInt 0 Inf Inf\n\n\nWe decide to jointly tune the \"branch.selection\", \"classif.rpart.cp\" and \"classif.rpart.minbucket\" hyperparameters:\n\nsearch_space = ps(\n branch.selection = p_fct(c(\"impute_missind\", \"simple_median\")),\n classif.rpart.cp = p_dbl(0.001, 0.1),\n classif.rpart.minbucket = p_int(1, 10))\n\nIn order to tune the graph, it needs to be converted to a learner:\n\ngraph_learner = as_learner(graph)\n\ncv3 = rsmp(\"cv\", folds = 3)\n\ncv3$instantiate(task_pima) # to generate folds for cross validation\n\ninstance = tune(\n tuner = tnr(\"random_search\"),\n task = task_pima,\n learner = graph_learner,\n resampling = rsmp(\"cv\", folds = 3),\n measure = msr(\"classif.ce\"),\n search_space = search_space,\n term_evals = 5)\n\nas.data.table(instance$archive, unnest = NULL, exclude_columns = c(\"x_domain\", \"uhash\", \"resample_result\"))\n\n branch.selection classif.rpart.cp classif.rpart.minbucket classif.ce runtime_learners timestamp batch_nr\n1: simple_median 0.02172886 2 0.2799479 2.774 2023-11-02 16:33:12 1\n2: impute_missind 0.07525939 1 0.2760417 2.701 2023-11-02 16:33:25 2\n3: impute_missind 0.09207969 3 0.2773438 1.031 2023-11-02 16:33:36 3\n4: impute_missind 0.03984117 6 0.2721354 2.184 2023-11-02 16:33:47 4\n5: impute_missind 0.09872643 7 0.2773438 2.507 2023-11-02 16:33:57 5\n warnings errors\n1: 0 0\n2: 0 0\n3: 0 0\n4: 0 0\n5: 0 0\n\n\nThe best performance in this short tuned experiment was achieved with:\n\ninstance$result\n\n branch.selection classif.rpart.cp classif.rpart.minbucket learner_param_vals x_domain classif.ce\n1: impute_missind 0.03984117 6 <list[9]> <list[3]> 0.2721354" + }, + { + "objectID": "gallery/pipelines/2020-04-23-pipelines-selectors-branches/index.html#conclusion", + "href": "gallery/pipelines/2020-04-23-pipelines-selectors-branches/index.html#conclusion", + "title": "Pipelines, Selectors, Branches", + "section": "Conclusion", + "text": "Conclusion\nThis post shows ways on how to specify features on which preprocessing steps are to be performed. In addition it shows how to create alternative paths in the learner graph. The preprocessing steps that can be used are not limited to imputation. Check the list of available PipeOp." + }, + { + "objectID": "gallery/pipelines/2020-04-27-tuning-stacking/index.html", + "href": "gallery/pipelines/2020-04-27-tuning-stacking/index.html", + "title": "Tuning a Stacked Learner", + "section": "", + "text": "Multilevel stacking is an ensemble technique, where predictions of several learners are added as new features to extend the orginal data on different levels. On each level, the extended data is used to train a new level of learners. This can be repeated for several iterations until a final learner is trained. To avoid overfitting, it is advisable to use test set (out-of-bag) predictions in each level.\nIn this post, a multilevel stacking example will be created using mlr3pipelines and tuned using mlr3tuning . A similar example is available in the mlr3book. However, we additionally explain how to tune the hyperparameters of the whole ensemble and each underlying learner jointly.\nIn our stacking example, we proceed as follows:\n\nLevel 0: Based on the input data, we train three learners (rpart, glmnet and lda) on a sparser feature space obtained using different feature filter methods from mlr3filters to obtain slightly decorrelated predictions. The test set predictions of these learners are attached to the original data (used in level 0) and will serve as input for the learners in level 1.\nLevel 1: We transform this extended data using PCA, on which we then train additional three learners (rpart, glmnet and lda). The test set predictions of the level 1 learners are attached to input data used in level 1.\nFinally, we train a final ranger learner to the data extended by level 1. Note that the number of features selected by the feature filter method in level 0 and the number of principal components retained in level 1 will be jointly tuned with some other hyperparameters of the learners in each level." + }, + { + "objectID": "gallery/pipelines/2020-04-27-tuning-stacking/index.html#intro", + "href": "gallery/pipelines/2020-04-27-tuning-stacking/index.html#intro", + "title": "Tuning a Stacked Learner", + "section": "", + "text": "Multilevel stacking is an ensemble technique, where predictions of several learners are added as new features to extend the orginal data on different levels. On each level, the extended data is used to train a new level of learners. This can be repeated for several iterations until a final learner is trained. To avoid overfitting, it is advisable to use test set (out-of-bag) predictions in each level.\nIn this post, a multilevel stacking example will be created using mlr3pipelines and tuned using mlr3tuning . A similar example is available in the mlr3book. However, we additionally explain how to tune the hyperparameters of the whole ensemble and each underlying learner jointly.\nIn our stacking example, we proceed as follows:\n\nLevel 0: Based on the input data, we train three learners (rpart, glmnet and lda) on a sparser feature space obtained using different feature filter methods from mlr3filters to obtain slightly decorrelated predictions. The test set predictions of these learners are attached to the original data (used in level 0) and will serve as input for the learners in level 1.\nLevel 1: We transform this extended data using PCA, on which we then train additional three learners (rpart, glmnet and lda). The test set predictions of the level 1 learners are attached to input data used in level 1.\nFinally, we train a final ranger learner to the data extended by level 1. Note that the number of features selected by the feature filter method in level 0 and the number of principal components retained in level 1 will be jointly tuned with some other hyperparameters of the learners in each level." + }, + { + "objectID": "gallery/pipelines/2020-04-27-tuning-stacking/index.html#prerequisites", + "href": "gallery/pipelines/2020-04-27-tuning-stacking/index.html#prerequisites", + "title": "Tuning a Stacked Learner", + "section": "Prerequisites", + "text": "Prerequisites\nWe load the mlr3verse package which pulls in the most important packages for this example. The mlr3learners package loads additional learners.\n\nlibrary(mlr3verse)\nlibrary(mlr3learners)\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\nlgr::get_logger(\"bbotk\")$set_threshold(\"warn\")\n\nFor the stacking example, we use the sonar classification task:\n\ntask_sonar = tsk(\"sonar\")\ntask_sonar$col_roles$stratum = task_sonar$target_names # stratification" + }, + { + "objectID": "gallery/pipelines/2020-04-27-tuning-stacking/index.html#pipeline-creation", + "href": "gallery/pipelines/2020-04-27-tuning-stacking/index.html#pipeline-creation", + "title": "Tuning a Stacked Learner", + "section": "Pipeline creation", + "text": "Pipeline creation\n\nLevel 0\nAs mentioned, the level 0 learners are rpart, glmnet and lda:\n\nlearner_rpart = lrn(\"classif.rpart\", predict_type = \"prob\")\nlearner_glmnet = lrn(\"classif.glmnet\", predict_type = \"prob\")\nlearner_lda = lrn(\"classif.lda\", predict_type = \"prob\")\n\nTo create the learner out-of-bag predictions, we use PipeOpLearnerCV:\n\ncv1_rpart = po(\"learner_cv\", learner_rpart, id = \"rprt_1\")\ncv1_glmnet = po(\"learner_cv\", learner_glmnet, id = \"glmnet_1\")\ncv1_lda = po(\"learner_cv\", learner_lda, id = \"lda_1\")\n\nA sparser representation of the input data in level 0 is obtained using the following filters:\n\nanova = po(\"filter\", flt(\"anova\"), id = \"filt1\")\nmrmr = po(\"filter\", flt(\"mrmr\"), id = \"filt2\")\nfind_cor = po(\"filter\", flt(\"find_correlation\"), id = \"filt3\")\n\nTo summarize these steps into level 0, we use the gunion() function. The out-of-bag predictions of all level 0 learners is attached using PipeOpFeatureUnion along with the original data passed via PipeOpNOP:\n\nlevel0 = gunion(list(\n anova %>>% cv1_rpart,\n mrmr %>>% cv1_glmnet,\n find_cor %>>% cv1_lda,\n po(\"nop\", id = \"nop1\"))) %>>%\n po(\"featureunion\", id = \"union1\")\n\nWe can have a look at the graph from level 0:\n\nlevel0$plot(html = FALSE)\n\n\n\n\n\n\n\n\n\n\nLevel 1\nNow, we create the level 1 learners:\n\ncv2_rpart = po(\"learner_cv\", learner_rpart, id = \"rprt_2\")\ncv2_glmnet = po(\"learner_cv\", learner_glmnet, id = \"glmnet_2\")\ncv2_lda = po(\"learner_cv\", learner_lda, id = \"lda_2\")\n\nAll level 1 learners will use PipeOpPCA transformed data as input:\n\nlevel1 = level0 %>>%\n po(\"copy\", 4) %>>%\n gunion(list(\n po(\"pca\", id = \"pca2_1\", param_vals = list(scale. = TRUE)) %>>% cv2_rpart,\n po(\"pca\", id = \"pca2_2\", param_vals = list(scale. = TRUE)) %>>% cv2_glmnet,\n po(\"pca\", id = \"pca2_3\", param_vals = list(scale. = TRUE)) %>>% cv2_lda,\n po(\"nop\", id = \"nop2\"))) %>>%\n po(\"featureunion\", id = \"union2\")\n\nWe can have a look at the graph from level 1:\n\nlevel1$plot(html = FALSE)\n\n\n\n\n\n\n\n\nThe out-of-bag predictions of the level 1 learners are attached to the input data from level 1 and a final ranger learner will be trained:\n\nranger_lrn = lrn(\"classif.ranger\", predict_type = \"prob\")\n\nensemble = level1 %>>% ranger_lrn\nensemble$plot(html = FALSE)\n\n\n\n\n\n\n\n\n\n\nDefining the tuning space\nIn order to tune the ensemble’s hyperparameter jointly, we define the search space using ParamSet from the paradox package:\n\nsearch_space_ensemble = ps(\n filt1.filter.nfeat = p_int(5, 50),\n filt2.filter.nfeat = p_int(5, 50),\n filt3.filter.nfeat = p_int(5, 50),\n pca2_1.rank. = p_int(3, 50),\n pca2_2.rank. = p_int(3, 50),\n pca2_3.rank. = p_int(3, 20),\n rprt_1.cp = p_dbl(0.001, 0.1),\n rprt_1.minbucket = p_int(1, 10),\n glmnet_1.alpha = p_dbl(0, 1),\n rprt_2.cp = p_dbl(0.001, 0.1),\n rprt_2.minbucket = p_int(1, 10),\n glmnet_2.alpha = p_dbl(0, 1),\n classif.ranger.mtry = p_int(1, 10),\n classif.ranger.sample.fraction = p_dbl(0.5, 1),\n classif.ranger.num.trees = p_int(50, 200))\n\n\n\nPerformance comparison\nEven with a simple ensemble, there is quite a few things to setup. We compare the performance of the ensemble with a simple tuned ranger learner.\nTo proceed, we convert the ensemble pipeline as a GraphLearner:\n\nlearner_ensemble = as_learner(ensemble)\nlearner_ensemble$id = \"ensemble\"\nlearner_ensemble$predict_type = \"prob\"\n\nWe define the search space for the simple ranger learner:\n\nsearch_space_ranger = ps(\n mtry = p_int(1, 10),\n sample.fraction = p_dbl(0.5, 1),\n num.trees = p_int(50, 200))\n\nFor performance comparison, we use the benchmark() function that requires a design incorporating a list of learners and a list of tasks. Here, we have two learners (the simple ranger learner and the ensemble) and one task. Since we want to tune the simple ranger learner as well as the whole ensemble learner, we need to create an AutoTuner for each learner to be compared. To do so, we need to define a resampling strategy for the tuning in the inner loop (we use 3-fold cross-validation) and for the final evaluation (outer loop) use use holdout validation:\n\ninner_resampling = rsmp(\"cv\", folds = 3)\n\n# AutoTuner for the ensemble learner\nat_1 = auto_tuner(\n tuner = tnr(\"random_search\"),\n learner = learner_ensemble,\n resampling = inner_resampling,\n measure = msr(\"classif.auc\"),\n search_space = search_space_ensemble,\n term_evals = 3) # to limit running time\n\n# AutoTuner for the simple ranger learner\nat_2 = auto_tuner(\n tuner = tnr(\"random_search\"),\n learner = ranger_lrn,\n resampling = inner_resampling,\n measure = msr(\"classif.auc\"),\n search_space = search_space_ranger,\n term_evals = 3) # to limit running time\n\n# Define the list of learners\nlearners = list(at_1, at_2)\n\n# For benchmarking, we use a simple holdout\nouter_resampling = rsmp(\"holdout\")\nouter_resampling$instantiate(task_sonar)\n\ndesign = benchmark_grid(\n tasks = task_sonar,\n learners = learners,\n resamplings = outer_resampling\n)\n\n\nbmr = benchmark(design, store_models = TRUE)\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $predict()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $predict()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $predict()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $predict()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $predict()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $predict()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $predict()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $predict()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $predict()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $predict()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $predict()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $predict()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $predict()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $predict()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $predict()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $predict()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $predict()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $predict()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $train()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $train()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_1's $predict()\n\n\nWarning: Multiple lambdas have been fit. Lambda will be set to 0.01 (see parameter 's').\nThis happened PipeOp glmnet_2's $predict()\n\n\n\nbmr$aggregate(msr(\"classif.auc\"))[, .(nr, task_id, learner_id, resampling_id, iters, classif.auc)]\n\nFor a more reliable comparison, the number of evaluation of the random search should be increased." + }, + { + "objectID": "gallery/pipelines/2020-04-27-tuning-stacking/index.html#conclusion", + "href": "gallery/pipelines/2020-04-27-tuning-stacking/index.html#conclusion", + "title": "Tuning a Stacked Learner", + "section": "Conclusion", + "text": "Conclusion\nThis example shows the versatility of mlr3pipelines. By using more learners, varied representations of the data set as well as more levels, a powerful yet compute hungry pipeline can be created. It is important to note that care should be taken to avoid name clashes of pipeline objects." + }, + { + "objectID": "gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html", + "href": "gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html", + "title": "German Credit Series - Pipelines", + "section": "", + "text": "This is the third part of a serial of use cases with the German credit dataset. The other parts of this series can be found here:\n\nPart I - Basics\nPart II - Tuning\n\nIn this tutorial, we continue working with the German credit dataset. We already used different Learners on it and tried to optimize their hyperparameters. Now we will do four additional things:\n\nWe preprocess the data as an integrated step of the model fitting process\nWe tune the associated preprocessing parameters\nWe stack multiple Learners in an ensemble model\nWe discuss some techniques that make Learners able to tackle challenging datasets that they could not handle otherwise (we are going to outline what challenging means in particular later on)" + }, + { + "objectID": "gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html#outline", + "href": "gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html#outline", + "title": "German Credit Series - Pipelines", + "section": "", + "text": "This is the third part of a serial of use cases with the German credit dataset. The other parts of this series can be found here:\n\nPart I - Basics\nPart II - Tuning\n\nIn this tutorial, we continue working with the German credit dataset. We already used different Learners on it and tried to optimize their hyperparameters. Now we will do four additional things:\n\nWe preprocess the data as an integrated step of the model fitting process\nWe tune the associated preprocessing parameters\nWe stack multiple Learners in an ensemble model\nWe discuss some techniques that make Learners able to tackle challenging datasets that they could not handle otherwise (we are going to outline what challenging means in particular later on)" + }, + { + "objectID": "gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html#prerequisites", + "href": "gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html#prerequisites", + "title": "German Credit Series - Pipelines", + "section": "Prerequisites", + "text": "Prerequisites\nFirst, load the packages we are going to use:\n\nlibrary(\"mlr3verse\")\nlibrary(\"data.table\")\nlibrary(\"ggplot2\")\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\nlgr::get_logger(\"bbotk\")$set_threshold(\"warn\")\n\nWe again use the German credit dataset, but will restrict ourselves to the factorial features. To make things interesting or to make it a bit harder for our Learners, we introduce missing values in the dataset:\n\ntask = tsk(\"german_credit\")\ncredit_full = task$data()\ncredit = credit_full[, sapply(credit_full, FUN = is.factor), with = FALSE]\n\n# sample values to NA\ncredit = credit[, lapply(.SD, function(x) {\n x[sample(c(TRUE, NA), length(x), replace = TRUE, prob = c(.9, .1))]\n})]\ncredit$credit_risk = credit_full$credit_risk\ntask = TaskClassif$new(\"GermanCredit\", credit, \"credit_risk\")\n\nWe instantiate a Resampling instance for this Task to be able to compare resampling performance:\n\ncv10 = rsmp(\"cv\")$instantiate(task)\n\nWe also might want to use multiple cores to reduce long run times of tuning runs.\n\nfuture::plan(\"multiprocess\")" + }, + { + "objectID": "gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html#intro", + "href": "gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html#intro", + "title": "German Credit Series - Pipelines", + "section": "Intro", + "text": "Intro\nIn this use case, we will take a look at composite machine learning algorithms that may incorporate data preprocessing or the combination of multiple Learners (“ensemble methods”).\nWe use the mlr3pipelines package that enables us to chain PipeOps into data flow Graphs.\nAvailable PipeOps are listed in the mlr_pipeops dictionary:\n\nmlr_pipeops\n\n<DictionaryPipeOp> with 64 stored values\nKeys: boxcox, branch, chunk, classbalancing, classifavg, classweights, colapply, collapsefactors, colroles,\n copy, datefeatures, encode, encodeimpact, encodelmer, featureunion, filter, fixfactors, histbin, ica,\n imputeconstant, imputehist, imputelearner, imputemean, imputemedian, imputemode, imputeoor, imputesample,\n kernelpca, learner, learner_cv, missind, modelmatrix, multiplicityexply, multiplicityimply, mutate, nmf,\n nop, ovrsplit, ovrunite, pca, proxy, quantilebin, randomprojection, randomresponse, regravg,\n removeconstants, renamecolumns, replicate, scale, scalemaxabs, scalerange, select, smote, spatialsign,\n subsample, targetinvert, targetmutate, targettrafoscalerange, textvectorizer, threshold, tunethreshold,\n unbranch, vtreat, yeojohnson" + }, + { + "objectID": "gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html#missing-value-imputation", + "href": "gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html#missing-value-imputation", + "title": "German Credit Series - Pipelines", + "section": "Missing Value Imputation", + "text": "Missing Value Imputation\nWe have just introduced missing values into our data. While some Learners can deal with missing value, many cannot. Trying to train a random forest fails because of this:\n\nranger = lrn(\"classif.ranger\")\nranger$train(task)\n\nError: Task 'GermanCredit' has missing values in column(s) 'credit_history', 'employment_duration', 'foreign_worker', 'housing', 'installment_rate', 'job', 'number_credits', 'other_debtors', 'other_installment_plans', 'people_liable', 'personal_status_sex', 'present_residence', 'property', 'purpose', 'savings', 'status', 'telephone', but learner 'classif.ranger' does not support this\n\n\nWe can perform imputation of missing values using a PipeOp. To find out which imputation PipeOps are available, we do the following:\n\nmlr_pipeops$keys(\"^impute\")\n\n[1] \"imputeconstant\" \"imputehist\" \"imputelearner\" \"imputemean\" \"imputemedian\" \"imputemode\" \n[7] \"imputeoor\" \"imputesample\" \n\n\nWe choose to impute factorial features using a new level (via PipeOpImputeOOR). Let’s use the PipeOp itself to create an imputed Task. This shows us how the PipeOp actually works:\n\nimputer = po(\"imputeoor\")\ntask_imputed = imputer$train(list(task))[[1]]\ntask_imputed$missings()\nhead(task_imputed$data())\n\n\n\n\n\n\n\nWe do not only need complete data during training but also during prediction. Using the same imputation heuristic for both is the most consistent strategy. This way the imputation strategy can, in fact, be seen as a part of the complete learner (which could be tuned).\nIf we used the imputed Task for Resampling, we would leak information from the test set into the training set. Therefore, it is mandatory to attach the imputation operator to the Learner itself, creating a GraphLearner:\n\ngraph_learner_ranger = as_learner(po(\"imputeoor\") %>>% ranger)\n\ngraph_learner_ranger$train(task)\n\nThis GraphLearner can be used for resampling – like an ordinary Learner:\n\nrr = resample(task, learner = graph_learner_ranger, resampling = cv10)\nrr$aggregate()\n\nclassif.ce \n 0.287" + }, + { + "objectID": "gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html#feature-filtering", + "href": "gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html#feature-filtering", + "title": "German Credit Series - Pipelines", + "section": "Feature Filtering", + "text": "Feature Filtering\nTypically, sparse models, i.e. having models with few(er) features, are desirable. This is due to a variety of reasons, e.g., enhanced interpretability or decreased costs of acquiring data. Furthermore, sparse models may actually be associated with increased performance (especially if overfitting is anticipated). We can use feature filter to only keep features with the highest information. Filters are implemented in the mlr3filters package and listed in the following dictionary:\n\nmlr_filters\n\n<DictionaryFilter> with 21 stored values\nKeys: anova, auc, carscore, carsurvscore, cmim, correlation, disr, find_correlation, importance,\n information_gain, jmi, jmim, kruskal_test, mim, mrmr, njmim, performance, permutation, relief,\n selected_features, variance\n\n\nWe apply the FilterMIM (mutual information maximization) Filter as implemented in the praznik package. This Filter allows for the selection of the top-k features of best mutual information.\n\nfilter = flt(\"mim\")\nfilter$calculate(task_imputed)$scores\n\n status credit_history savings purpose property \n 1.0000 0.9375 0.8750 0.8125 0.7500 \n housing employment_duration other_installment_plans personal_status_sex other_debtors \n 0.6875 0.6250 0.5625 0.5000 0.4375 \n installment_rate foreign_worker job number_credits telephone \n 0.3750 0.3125 0.2500 0.1875 0.1250 \n present_residence people_liable \n 0.0625 0.0000 \n\n\nMaking use of this Filter, you may wonder at which costs the reduction of the feature space comes. We can investigate the trade-off between features and performance by tuning. We incorporate our filtering strategy into the pipeline using PipeOpFilter. Like before, we need to perform imputation as the Filter also relies on complete data:\n\nfpipe = po(\"imputeoor\") %>>% po(\"filter\", flt(\"mim\"), filter.nfeat = 3)\nfpipe$train(task)[[1]]$head()\n\n credit_risk credit_history savings\n1: good all credits at this bank paid back duly ... >= 1000 DM\n2: bad no credits taken/all credits paid back duly unknown/no savings account\n3: good all credits at this bank paid back duly unknown/no savings account\n4: good no credits taken/all credits paid back duly unknown/no savings account\n5: bad existing credits paid back duly till now unknown/no savings account\n6: good .MISSING ... >= 1000 DM\n status\n1: no checking account\n2: ... < 0 DM\n3: ... >= 200 DM / salary for at least 1 year\n4: no checking account\n5: no checking account\n6: ... >= 200 DM / salary for at least 1 year\n\n\nWe can now tune over the mim.filter.nfeat parameter. It steers how many features are kept by the Filter and eventually used by the learner:\n\nsearch_space = ps(\n mim.filter.nfeat = p_int(lower = 1, upper = length(task$feature_names))\n)\n\nThe problem is one-dimensional (i.e. only one parameter is tuned). Thus, we make use of a grid search. For higher dimensions, strategies like random search are more appropriate. The tuning procedure may take some time:\n\ninstance = tune(\n tuner = tnr(\"grid_search\"),\n task,\n learner = fpipe %>>% lrn(\"classif.ranger\"),\n resampling = cv10,\n measure = msr(\"classif.ce\"),\n search_space = search_space)\n\nWe can plot the performance against the number of features. If we do so, we see the possible trade-off between sparsity and predictive performance:\n\nautoplot(instance, type = \"marginal\")" + }, + { + "objectID": "gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html#stacking", + "href": "gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html#stacking", + "title": "German Credit Series - Pipelines", + "section": "Stacking", + "text": "Stacking\nWe want to build a model that is based on the predictions of other Learners. This means that we are in the state that we need predictions already during training. This is a very specific case that is luckily handled by PipeOpLearnerCV. PipeOpLearnerCV performs cross-validation during the training phase and returns the cross-validated predictions. We use \"prob\" predictions because they carry more information than response prediction:\n\ngraph_stack = po(\"imputeoor\") %>>%\n gunion(list(\n po(\"learner_cv\", lrn(\"classif.ranger\", predict_type = \"prob\")),\n po(\"learner_cv\", lrn(\"classif.kknn\", predict_type = \"prob\")))) %>>%\n po(\"featureunion\") %>>% lrn(\"classif.log_reg\")\n\nWe built a pretty complex Graph already. Therefore, we plot it:\n\ngraph_stack$plot(html = FALSE)\n\n\n\n\n\n\n\n\nWe now compare the performance of the stacked learner to the performance of the individual Learners:\n\ngrid = benchmark_grid(\n task = task,\n learner = list(\n graph_stack,\n as_learner(po(\"imputeoor\") %>>% lrn(\"classif.ranger\")),\n as_learner(po(\"imputeoor\") %>>% lrn(\"classif.kknn\")),\n as_learner(po(\"imputeoor\") %>>% lrn(\"classif.log_reg\"))),\n resampling = cv10)\n\nbmr = benchmark(grid)\n\n\n\n learner_id classif.ce\n1: imputeoor.classif.ranger.classif.kknn.featureunion.classif.log_reg 0.282\n2: imputeoor.classif.ranger 0.292\n3: imputeoor.classif.kknn 0.299\n4: imputeoor.classif.log_reg 0.283\n\n\nIf we train the stacked learner and look into the final Learner (the logistic regression), we can see how “important” each Learner of the stacked learner is:\n\ngraph_stack$train(task)\n\n$classif.log_reg.output\nNULL\n\nsummary(graph_stack$pipeops$classif.log_reg$state$model)\n\n\nCall:\nstats::glm(formula = task$formula(), family = \"binomial\", data = data, \n model = FALSE)\n\nCoefficients: (2 not defined because of singularities)\n Estimate Std. Error z value Pr(>|z|) \n(Intercept) -3.3179 0.3527 -9.406 < 2e-16 ***\nclassif.ranger.prob.good 5.4010 0.5648 9.563 < 2e-16 ***\nclassif.ranger.prob.bad NA NA NA NA \nclassif.kknn.prob.good 0.8502 0.3169 2.683 0.00729 ** \nclassif.kknn.prob.bad NA NA NA NA \n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n\n(Dispersion parameter for binomial family taken to be 1)\n\n Null deviance: 1221.7 on 999 degrees of freedom\nResidual deviance: 1054.1 on 997 degrees of freedom\nAIC: 1060.1\n\nNumber of Fisher Scoring iterations: 4\n\n\nThe random forest has a higher contribution." + }, + { + "objectID": "gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html#robustify-preventing-new-prediction-factor-levels-and-other-problems", + "href": "gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html#robustify-preventing-new-prediction-factor-levels-and-other-problems", + "title": "German Credit Series - Pipelines", + "section": "Robustify: Preventing new Prediction Factor Levels and other Problems", + "text": "Robustify: Preventing new Prediction Factor Levels and other Problems\nWe now shift the context, using the complete German credit dataset:\n\ntask = tsk(\"german_credit\")\n\nThere is a potential practical problem for both, small data sets and data sets with covariates having many factor levels: It may occur that not all possible factor levels have been used by the Learner during training. This happens because these rare instances are simply not sampled. The prediction then may fail because the Learner does not know how to handle unseen factor levels:\n\ntask_unseen = task$clone()$filter(1:30)\nlearner_logreg = lrn(\"classif.log_reg\")\nlearner_logreg$train(task_unseen)\nlearner_logreg$predict(task)\n\nError in model.frame.default(Terms, newdata, na.action = na.action, xlev = object$xlevels): factor job has new levels unemployed/unskilled - non-resident\n\n\nNot only logistic regression but also many other Learners cannot handle new levels during prediction. Thus, we use PipeOpFixFactors to prevent that. PipeOpFixFactors introduces NA values for unseen levels. This means that we may need to impute afterwards. To solve this issue we can use PipeOpImputeSample, but with affect_columns set to only factorial features.\nAnother observation is that all-constant features may also be a problem:\n\ntask_constant = task$clone()$filter(1:2)\nlearner_logreg = lrn(\"classif.log_reg\")\nlearner_logreg$train(task_constant)\n\nError in `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]): contrasts can be applied only to factors with 2 or more levels\n\n\nThis can be fixed using PipeOpRemoveConstants.\nBoth, handling unseen levels and all-constant features can be handled simultaneously using the following Graph:\n\nrobustify = po(\"fixfactors\") %>>%\n po(\"removeconstants\") %>>%\n po(\"imputesample\", affect_columns = selector_type(c(\"ordered\", \"factor\")))\n\nrobustify$plot(html = FALSE)\n\n\n\n\n\n\n\n\nThis robust learner works even in very pathological conditions:\n\ngraph_learner_robustify = as_learner(robustify %>>% learner_logreg)\n\ngraph_learner_robustify$train(task_constant)\ngraph_learner_robustify$predict(task)\n\n<PredictionClassif> for 1000 observations:\n row_ids truth response\n 1 good good\n 2 bad bad\n 3 good good\n--- \n 998 good bad\n 999 bad bad\n 1000 good bad" + }, + { + "objectID": "gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html#your-ideas", + "href": "gallery/basic/2020-03-11-mlr3pipelines-tutorial-german-credit/index.html#your-ideas", + "title": "German Credit Series - Pipelines", + "section": "Your Ideas", + "text": "Your Ideas\nThere are various possibilities for preprocessing with PipeOps. You can try different methods for preprocessing and training. Feel free to discover this variety by yourself! Here are only a few hints that help when working with PipeOps:\n\nIt is not allowed to have two PipeOps with the same ID in a Graph\n\nInitialize a PipeOp with po(\"...\", id = \"xyz\") to change its ID on construction\n\nIf you build large Graphs involving complicated optimizations, like many \"learner_cv\", they may need a long time to train\nUse the affect_columns parameter if you want a PipeOp to only operate on part of the data\nUse po(\"select\") if you want to remove certain columns (possibly only along a single branch of multiple parallel branches). Both take selector_xxx() arguments, e.g. selector_type(\"integer\")\nYou may get the best performance if you actually inspect the features and see what kind of transformations work best for them (know your data!)\nSee what PipeOps are available by inspecting mlr_pipeops$keys(), and get help about them using ?mlr_pipeops_xxx" + }, + { + "objectID": "gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index.html", + "href": "gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index.html", + "title": "German Credit Series - Tuning", + "section": "", + "text": "This is the second part of a serial of tutorials. The other parts of this series can be found here:\n\nPart I - Basics\nPart III - Pipelines\n\nWe will continue working with the German credit dataset. In Part I, we peeked into the dataset by using and comparing some learners with their default parameters. We will now see how to:\n\nTune hyperparameters for a given problem\nPerform nested resampling" + }, + { + "objectID": "gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index.html#evaluation", + "href": "gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index.html#evaluation", + "title": "German Credit Series - Tuning", + "section": "Evaluation", + "text": "Evaluation\nWe will evaluate all hyperparameter configurations using 10-fold cross-validation. We use a fixed train-test split, i.e. the same splits for each evaluation. Otherwise, some evaluation could get unusually “hard” splits, which would make comparisons unfair.\n\ncv10 = rsmp(\"cv\", folds = 10)\n\n# fix the train-test splits using the $instantiate() method\ncv10$instantiate(task)\n\n# have a look at the test set instances per fold\ncv10$instance\n\n row_id fold\n 1: 18 1\n 2: 19 1\n 3: 35 1\n 4: 38 1\n 5: 55 1\n --- \n 996: 973 10\n 997: 975 10\n 998: 981 10\n 999: 993 10\n1000: 998 10" + }, + { + "objectID": "gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index.html#search-space-and-problem-definition", + "href": "gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index.html#search-space-and-problem-definition", + "title": "German Credit Series - Tuning", + "section": "Search Space and Problem Definition", + "text": "Search Space and Problem Definition\nFirst, we need to decide what Learner we want to optimize. We will use LearnerClassifKKNN, the “kernelized” k-nearest neighbor classifier. We will use kknn as a normal kNN without weighting first (i.e., using the rectangular kernel):\n\nknn = lrn(\"classif.kknn\", predict_type = \"prob\", kernel = \"rectangular\")\n\nAs a next step, we decide what parameters we optimize over. Before that, though, we are interested in the parameter set on which we could tune:\n\nknn$param_set\n\n\n\n id class lower upper nlevels\n1: k ParamInt 1 Inf Inf\n2: distance ParamDbl 0 Inf Inf\n3: kernel ParamFct NA NA 10\n4: scale ParamLgl NA NA 2\n5: ykernel ParamUty NA NA Inf\n6: store_model ParamLgl NA NA 2\n\n\nWe first tune the k parameter (i.e. the number of nearest neighbors), between 3 to 20. Second, we tune the distance function, allowing L1 and L2 distances. To do so, we use the paradox package to define a search space (see the online vignette for a more complete introduction.\n\nsearch_space = ps(\n k = p_int(3, 20),\n distance = p_int(1, 2)\n)\n\nAs a next step, we define a TuningInstanceSingleCrit that represents the problem we are trying to optimize.\n\ninstance_grid = TuningInstanceSingleCrit$new(\n task = task,\n learner = knn,\n resampling = cv10,\n measure = msr(\"classif.ce\"),\n terminator = trm(\"none\"),\n search_space = search_space\n)" + }, + { + "objectID": "gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index.html#grid-search", + "href": "gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index.html#grid-search", + "title": "German Credit Series - Tuning", + "section": "Grid Search", + "text": "Grid Search\nAfter having set up a tuning instance, we can start tuning. Before that, we need a tuning strategy, though. A simple tuning method is to try all possible combinations of parameters: Grid Search. While it is very intuitive and simple, it is inefficient if the search space is large. For this simple use case, it suffices, though. We get the grid_search tuner via:\n\ntuner_grid = tnr(\"grid_search\", resolution = 18, batch_size = 36)\n\nTuning works by calling $optimize(). Note that the tuning procedure modifies our tuning instance (as usual for R6 class objects). The result can be found in the instance object. Before tuning it is empty:\n\ninstance_grid$result\n\nNULL\n\n\nNow, we tune:\n\ntuner_grid$optimize(instance_grid)\n\n k distance learner_param_vals x_domain classif.ce\n1: 7 1 <list[3]> <list[2]> 0.25\n\n\nThe result is returned by $optimize() together with its performance. It can be also accessed with the $result slot:\n\ninstance_grid$result\n\n k distance learner_param_vals x_domain classif.ce\n1: 7 1 <list[3]> <list[2]> 0.25\n\n\nWe can also look at the Archive of evaluated configurations:\n\nhead(as.data.table(instance_grid$archive))\n\n\n\n k distance classif.ce runtime_learners timestamp batch_nr warnings errors\n1: 3 1 0.273 1.458 2023-10-30 15:10:10 1 0 0\n2: 3 2 0.280 0.435 2023-10-30 15:10:10 1 0 0\n3: 4 1 0.290 0.790 2023-10-30 15:10:10 1 0 0\n4: 4 2 0.266 0.658 2023-10-30 15:10:10 1 0 0\n5: 5 1 0.268 0.716 2023-10-30 15:10:10 1 0 0\n6: 5 2 0.256 0.374 2023-10-30 15:10:10 1 0 0\n\n\nWe plot the performances depending on the sampled k and distance:\n\nggplot(as.data.table(instance_grid$archive),\n aes(x = k, y = classif.ce, color = as.factor(distance))) +\n geom_line() + geom_point(size = 3)\n\n\n\n\n\n\n\n\nOn average, the Euclidean distance (distance = 2) seems to work better. However, there is much randomness introduced by the resampling instance. So you, the reader, may see a different result, when you run the experiment yourself and set a different random seed. For k, we find that values between 7 and 13 perform well." + }, + { + "objectID": "gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index.html#random-search-and-transformation", + "href": "gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index.html#random-search-and-transformation", + "title": "German Credit Series - Tuning", + "section": "Random Search and Transformation", + "text": "Random Search and Transformation\nLet’s have a look at a larger search space. For example, we could tune all available parameters and limit k to large values (50). We also now tune the distance param continuously from 1 to 3 as a double and tune distance kernel and whether we scale the features.\nWe may find two problems when doing so:\nFirst, the resulting difference in performance between k = 3 and k = 4 is probably larger than the difference between k = 49 and k = 50. While 4 is 33% larger than 3, 50 is only 2 percent larger than 49. To account for this we will use a transformation function for k and optimize in log-space. We define the range for k from log(3) to log(50) and exponentiate in the transformation. Now, as k has become a double instead of an int (in the search space, before transformation), we round it in the extra_trafo.\n\nsearch_space_large = ps(\n k = p_dbl(log(3), log(50)),\n distance = p_dbl(1, 3),\n kernel = p_fct(c(\"rectangular\", \"gaussian\", \"rank\", \"optimal\")),\n scale = p_lgl(),\n .extra_trafo = function(x, param_set) {\n x$k = round(exp(x$k))\n x\n }\n)\n\nThe second problem is that grid search may (and often will) take a long time. For instance, trying out three different values for k, distance, kernel, and the two values for scale will take 54 evaluations. Because of this, we use a different search algorithm, namely the Random Search. We need to specify in the tuning instance a termination criterion. The criterion tells the search algorithm when to stop. Here, we will terminate after 36 evaluations:\n\ntuner_random = tnr(\"random_search\", batch_size = 36)\n\ninstance_random = TuningInstanceSingleCrit$new(\n task = task,\n learner = knn,\n resampling = cv10,\n measure = msr(\"classif.ce\"),\n terminator = trm(\"evals\", n_evals = 36),\n search_space = search_space_large\n)\n\n\ntuner_random$optimize(instance_random)\n\n k distance kernel scale learner_param_vals x_domain classif.ce\n1: 1.683743 1.985146 gaussian TRUE <list[4]> <list[4]> 0.254\n\n\nLike before, we can review the Archive. It includes the points before and after the transformation. The archive includes a column for each parameter the Tuner sampled on the search space (values before the transformation) and additional columns with prefix x_domain_* that refer to the parameters used by the learner (values after the transformation):\n\nas.data.table(instance_random$archive)\n\n\n\n\n\n\n\nLet’s now investigate the performance by parameters. This is especially easy using visualization:\n\nggplot(as.data.table(instance_random$archive),\n aes(x = x_domain_k, y = classif.ce, color = x_domain_scale)) +\n geom_point(size = 3) + geom_line()\n\n\n\n\n\n\n\n\nThe previous plot suggests that scale has a strong influence on performance. For the kernel, there does not seem to be a strong influence:\n\nggplot(as.data.table(instance_random$archive),\n aes(x = x_domain_k, y = classif.ce, color = x_domain_kernel)) +\n geom_point(size = 3) + geom_line()" + }, + { + "objectID": "gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index.html#example-tuning-with-a-larger-budget", + "href": "gallery/basic/2020-03-11-mlr3tuning-tutorial-german-credit/index.html#example-tuning-with-a-larger-budget", + "title": "German Credit Series - Tuning", + "section": "Example: Tuning With A Larger Budget", + "text": "Example: Tuning With A Larger Budget\nIt is always interesting to look at what could have been. The following dataset contains an optimization run result with 3600 evaluations – more than above by a factor of 100:\n\n\n\n\n\n\nThe scale effect is just as visible as before with fewer data:\n\nggplot(perfdata, aes(x = x_domain_k, y = classif.ce, color = scale)) +\n geom_point(size = 2, alpha = 0.3)\n\n\n\n\n\n\n\n\nNow, there seems to be a visible pattern by kernel as well:\n\nggplot(perfdata, aes(x = x_domain_k, y = classif.ce, color = kernel)) +\n geom_point(size = 2, alpha = 0.3)\n\n\n\n\n\n\n\n\nIn fact, if we zoom in to (5, 40) \\(\\times\\) (0.23, 0.28) and do decrease smoothing we see that different kernels have their optimum at different values of k:\n\nggplot(perfdata, aes(x = x_domain_k, y = classif.ce, color = kernel,\n group = interaction(kernel, scale))) +\n geom_point(size = 2, alpha = 0.3) + geom_smooth() +\n xlim(5, 40) + ylim(0.23, 0.28)\n\n`geom_smooth()` using method = 'loess' and formula = 'y ~ x'\n\n\n\n\n\n\n\n\n\nWhat about the distance parameter? If we select all results with k between 10 and 20 and plot distance and kernel we see an approximate relationship:\n\nggplot(perfdata[x_domain_k > 10 & x_domain_k < 20 & scale == TRUE],\n aes(x = distance, y = classif.ce, color = kernel)) +\n geom_point(size = 2) + geom_smooth()\n\n`geom_smooth()` using method = 'loess' and formula = 'y ~ x'\n\n\n\n\n\n\n\n\n\nIn sum our observations are: The scale parameter is very influential, and scaling is beneficial. The distance type seems to be the least influential. There seems to be an interaction between ‘k’ and ‘kernel’." + }, + { + "objectID": "gallery/basic/2020-03-30-imbalanced-data/index.html", + "href": "gallery/basic/2020-03-30-imbalanced-data/index.html", + "title": "Imbalanced Data Handling with mlr3", + "section": "", + "text": "This use case compares different approaches to handle class imbalance for the Optical Recognition of Handwritten Digits (optdigits) binary classification data set using the mlr3 package. We mainly focus on undersampling the majority class, oversampling the minority class, and the SMOTE imbalance correction (Chawla et al. 2002) that enriches the minority class with synthetic data. The use case requires prior knowledge in basic ML concepts (issues imbalanced data, hyperparameter tuning, nested cross-validation). The R packages mlr3, mlr3pipelines and mlr3tuning will be used. You can find most of the content here also in the mlr3book explained in a more detailed way.\nThese steps are performed:\n\nRetrieve data sets from OpenML\nDefine imbalance correction pipeline Graphs (undersampling, oversampling and SMOTE) with mlr3pipelines\nAutotune the Graph together with a learner using mlr3tuning\nBenchmark the autotuned Graph and visualize the results using mlr3viz" + }, + { + "objectID": "gallery/basic/2020-03-30-imbalanced-data/index.html#visualize-benchmark-results", + "href": "gallery/basic/2020-03-30-imbalanced-data/index.html#visualize-benchmark-results", + "title": "Imbalanced Data Handling with mlr3", + "section": "Visualize benchmark results", + "text": "Visualize benchmark results\n\nbmr$aggregate(measure)\n\n nr task_id learner_id resampling_id iters classif.fbeta\n1: 1 optdigits undersample.ranger.tuned holdout 1 0.9453552\n2: 2 optdigits oversample.ranger.tuned holdout 1 0.9508197\n3: 3 optdigits smote.ranger.tuned holdout 1 0.9539295\nHidden columns: resample_result\n\n# one value per boxplot since we used holdout as outer resampling\nautoplot(bmr, measure = measure)" + }, + { + "objectID": "gallery/basic/2020-03-30-imbalanced-data/index.html#visualize-the-tuning-path", + "href": "gallery/basic/2020-03-30-imbalanced-data/index.html#visualize-the-tuning-path", + "title": "Imbalanced Data Handling with mlr3", + "section": "Visualize the tuning path", + "text": "Visualize the tuning path\nWith store_models = TRUE we allow the benchmark() function to store each single model that was computed during tuning. Therefore, we can plot the tuning path of the best learner from the subsampling iterations:\n\nlibrary(ggplot2)\nbmr_data_learners = as.data.table(bmr)$learner\nutune_path = bmr_data_learners[[1]]$model$tuning_instance$archive$data\nutune_gg = ggplot(utune_path, aes(x = undersample.ratio, y = classif.fbeta)) +\n geom_point(size = 3) +\n geom_line() + ylim(0.9, 1)\n\notune_path = bmr_data_learners[[2]]$model$tuning_instance$archive$data\notune_gg = ggplot(otune_path, aes(x = oversample.ratio, y = classif.fbeta)) +\n geom_point(size = 3) +\n geom_line() + ylim(0.9, 1)\n\nstune_path = bmr_data_learners[[3]]$model$tuning_instance$archive$data\nstune_gg = ggplot(stune_path, aes(\n x = smote.dup_size,\n y = classif.fbeta, col = factor(smote.K))) +\n geom_point(size = 3) +\n geom_line() + ylim(0.9, 1)\n\nlibrary(ggpubr)\nggarrange(utune_gg, otune_gg, stune_gg, common.legend = TRUE, nrow = 1)\n\n\n\n\n\n\n\n\nThe results show that oversampling the minority class (for simple oversampling as well as for SMOTE) and undersampling the majority class yield a better performance for this specific data set." + }, + { + "objectID": "gallery/basic/2020-08-14-comparison-of-decision-boundaries/index.html", + "href": "gallery/basic/2020-08-14-comparison-of-decision-boundaries/index.html", + "title": "Comparison of Decision Boundaries of Classification Learners", + "section": "", + "text": "The visualization of decision boundaries helps to understand what the pros and cons of individual classification learners are. This posts demonstrates how to create such plots.\nWe load the mlr3 package.\nlibrary(\"mlr3\")\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")" + }, + { + "objectID": "gallery/basic/2020-08-14-comparison-of-decision-boundaries/index.html#artificial-data-sets", + "href": "gallery/basic/2020-08-14-comparison-of-decision-boundaries/index.html#artificial-data-sets", + "title": "Comparison of Decision Boundaries of Classification Learners", + "section": "Artificial Data Sets", + "text": "Artificial Data Sets\nThe three artificial data sets are generated by task generators (implemented in mlr3):\n\nN <- 200\ntasks <- list(\n tgen(\"xor\")$generate(N),\n tgen(\"moons\")$generate(N),\n tgen(\"circle\")$generate(N)\n)\n\n\nXOR\nPoints are distributed on a 2-dimensional cube with corners \\((\\pm 1, \\pm 1)\\). Class is \"red\" if \\(x\\) and \\(y\\) have the same sign, and \"black\" otherwise.\n\nplot(tgen(\"xor\"))\n\n\n\n\n\n\n\n\n\n\nCircle\nTwo circles with same center but different radii. Points in the smaller circle are \"black\", points only in the larger circle are \"red\".\n\nplot(tgen(\"circle\"))\n\n\n\n\n\n\n\n\n\n\nMoons\nTwo interleaving half circles (“moons”).\n\nplot(tgen(\"moons\"))" + }, + { + "objectID": "gallery/basic/2020-08-14-comparison-of-decision-boundaries/index.html#learners", + "href": "gallery/basic/2020-08-14-comparison-of-decision-boundaries/index.html#learners", + "title": "Comparison of Decision Boundaries of Classification Learners", + "section": "Learners", + "text": "Learners\nWe consider the following learners:\n\nlibrary(\"mlr3learners\")\n\nlearners <- list(\n # k-nearest neighbours classifier\n lrn(\"classif.kknn\", id = \"kkn\", predict_type = \"prob\", k = 3),\n\n # linear svm\n lrn(\"classif.svm\", id = \"lin. svm\", predict_type = \"prob\", kernel = \"linear\"),\n\n # radial-basis function svm\n lrn(\"classif.svm\",\n id = \"rbf svm\", predict_type = \"prob\", kernel = \"radial\",\n gamma = 2, cost = 1, type = \"C-classification\"\n ),\n\n # naive bayes\n lrn(\"classif.naive_bayes\", id = \"naive bayes\", predict_type = \"prob\"),\n\n # single decision tree\n lrn(\"classif.rpart\", id = \"tree\", predict_type = \"prob\", cp = 0, maxdepth = 5),\n\n # random forest\n lrn(\"classif.ranger\", id = \"random forest\", predict_type = \"prob\")\n)\n\nThe hyperparameters are chosen in a way that the decision boundaries look “typical” for the respective classifier. Of course, with different hyperparameters, results may look very different." + }, + { + "objectID": "gallery/basic/2020-08-14-comparison-of-decision-boundaries/index.html#fitting-the-models", + "href": "gallery/basic/2020-08-14-comparison-of-decision-boundaries/index.html#fitting-the-models", + "title": "Comparison of Decision Boundaries of Classification Learners", + "section": "Fitting the Models", + "text": "Fitting the Models\nTo apply each learner on each task, we first build an exhaustive grid design of experiments with benchmark_grid() and then pass it to benchmark() to do the actual work. A simple holdout resampling is used here:\n\ndesign <- benchmark_grid(\n tasks = tasks,\n learners = learners,\n resamplings = rsmp(\"holdout\")\n)\n\nbmr <- benchmark(design, store_models = TRUE)\n\nA quick look into the performance values:\n\nperf <- bmr$aggregate(msr(\"classif.acc\"))[, c(\"task_id\", \"learner_id\", \"classif.acc\")]\nperf\n\n task_id learner_id classif.acc\n 1: xor_200 kkn 0.9402985\n 2: xor_200 lin. svm 0.5223881\n 3: xor_200 rbf svm 0.9701493\n 4: xor_200 naive bayes 0.4328358\n 5: xor_200 tree 0.9402985\n 6: xor_200 random forest 1.0000000\n 7: moons_200 kkn 1.0000000\n 8: moons_200 lin. svm 0.8805970\n 9: moons_200 rbf svm 1.0000000\n10: moons_200 naive bayes 0.8955224\n11: moons_200 tree 0.8955224\n12: moons_200 random forest 0.9552239\n13: circle_200 kkn 0.8805970\n14: circle_200 lin. svm 0.4925373\n15: circle_200 rbf svm 0.8955224\n16: circle_200 naive bayes 0.7014925\n17: circle_200 tree 0.7462687\n18: circle_200 random forest 0.7761194" + }, + { + "objectID": "gallery/basic/2020-08-14-comparison-of-decision-boundaries/index.html#plotting", + "href": "gallery/basic/2020-08-14-comparison-of-decision-boundaries/index.html#plotting", + "title": "Comparison of Decision Boundaries of Classification Learners", + "section": "Plotting", + "text": "Plotting\nTo generate the plots, we iterate over the individual ResampleResult objects stored in the BenchmarkResult, and in each iteration we store the plot of the learner prediction generated by the mlr3viz package.\n\nlibrary(\"mlr3viz\")\n\nn <- bmr$n_resample_results\nplots <- vector(\"list\", n)\nfor (i in seq_len(n)) {\n rr <- bmr$resample_result(i)\n plots[[i]] <- autoplot(rr, type = \"prediction\")\n}\n\nWe now have a list of plots. Each one can be printed individually:\n\nprint(plots[[1]])\n\n\n\n\n\n\n\n\nNote that only observations from the test data is plotted as points.\nTo get a nice annotated overview, we arranged all plots together in a single pdf file. The number in the upper right is the respective accuracy on the test set.\n\npdf(file = \"plot_learner_prediction.pdf\", width = 20, height = 6)\nntasks <- length(tasks)\nnlearners <- length(learners)\nm <- msr(\"classif.acc\")\n\n# for each plot\nfor (i in seq_along(plots)) {\n plots[[i]] <- plots[[i]] +\n # remove legend\n ggplot2::theme(legend.position = \"none\") +\n # remove labs\n ggplot2::xlab(\"\") + ggplot2::ylab(\"\") +\n # add accuracy score as annotation\n ggplot2::annotate(\"text\",\n label = sprintf(\"%.2f\", bmr$resample_result(i)$aggregate(m)),\n x = Inf, y = Inf, vjust = 2, hjust = 1.5\n )\n}\n\n# for each plot of the first column\nfor (i in seq_len(ntasks)) {\n ii <- (i - 1) * nlearners + 1L\n plots[[ii]] <- plots[[ii]] + ggplot2::ylab(sub(\"_[0-9]+$\", \"\", tasks[[i]]$id))\n}\n\n# for each plot of the first row\nfor (i in seq_len(nlearners)) {\n plots[[i]] <- plots[[i]] + ggplot2::ggtitle(learners[[i]]$id)\n}\n\ngridExtra::grid.arrange(grobs = plots, nrow = length(tasks))\ndev.off()\n\nAs you can see, the decision boundaries look very different. Some are linear, others are parallel to the axis, and yet others are highly non-linear. The boundaries are partly very smooth with a slow transition of probabilities, others are very abrupt. All these properties are important during model selection, and should be considered for your problem at hand." + }, + { + "objectID": "gallery/basic/2020-01-30-impute-missing-levels/index.html", + "href": "gallery/basic/2020-01-30-impute-missing-levels/index.html", + "title": "Impute Missing Variables", + "section": "", + "text": "This tutorial assumes familiarity with the basics of mlr3pipelines. Consult the mlr3book if some aspects are not fully understandable. It deals with the problem of missing data.\nThe random forest implementation in the package ranger unfortunately does not support missing values. Therefore, it is required to impute missing features before passing the data to the learner.\nWe show how to use mlr3pipelines to augment the ranger learner with automatic imputation.\nWe load the mlr3verse package which pulls in the most important packages for this example.\n\nlibrary(mlr3verse)\n\nLoading required package: mlr3\n\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")" + }, + { + "objectID": "gallery/basic/2020-01-30-impute-missing-levels/index.html#prerequisites", + "href": "gallery/basic/2020-01-30-impute-missing-levels/index.html#prerequisites", + "title": "Impute Missing Variables", + "section": "", + "text": "This tutorial assumes familiarity with the basics of mlr3pipelines. Consult the mlr3book if some aspects are not fully understandable. It deals with the problem of missing data.\nThe random forest implementation in the package ranger unfortunately does not support missing values. Therefore, it is required to impute missing features before passing the data to the learner.\nWe show how to use mlr3pipelines to augment the ranger learner with automatic imputation.\nWe load the mlr3verse package which pulls in the most important packages for this example.\n\nlibrary(mlr3verse)\n\nLoading required package: mlr3\n\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")" + }, + { + "objectID": "gallery/basic/2020-01-30-impute-missing-levels/index.html#construct-the-base-objects", + "href": "gallery/basic/2020-01-30-impute-missing-levels/index.html#construct-the-base-objects", + "title": "Impute Missing Variables", + "section": "Construct the Base Objects", + "text": "Construct the Base Objects\nFirst, we take an example task with missing values (pima) and create the ranger learner:\n\nlibrary(mlr3learners)\n\ntask = tsk(\"pima\")\nprint(task)\n\n<TaskClassif:pima> (768 x 9): Pima Indian Diabetes\n* Target: diabetes\n* Properties: twoclass\n* Features (8):\n - dbl (8): age, glucose, insulin, mass, pedigree, pregnant, pressure, triceps\n\nlearner = lrn(\"classif.ranger\")\nprint(learner)\n\n<LearnerClassifRanger:classif.ranger>\n* Model: -\n* Parameters: num.threads=1\n* Packages: mlr3, mlr3learners, ranger\n* Predict Types: [response], prob\n* Feature Types: logical, integer, numeric, character, factor, ordered\n* Properties: hotstart_backward, importance, multiclass, oob_error, twoclass, weights\n\n\nWe can now inspect the task for missing values. task$missings() returns the count of missing values for each variable.\n\ntask$missings()\n\ndiabetes age glucose insulin mass pedigree pregnant pressure triceps \n 0 0 5 374 11 0 0 35 227 \n\n\nAdditionally, we can see that the ranger learner can not handle missing values:\n\nlearner$properties\n\n[1] \"hotstart_backward\" \"importance\" \"multiclass\" \"oob_error\" \"twoclass\" \n[6] \"weights\" \n\n\nFor comparison, other learners, e.g. the rpart learner can handle missing values internally.\n\nlrn(\"classif.rpart\")$properties\n\n[1] \"importance\" \"missings\" \"multiclass\" \"selected_features\" \"twoclass\" \n[6] \"weights\" \n\n\nBefore we dive deeper, we quickly try to visualize the columns with many missing values:\n\nautoplot(task$clone()$select(c(\"insulin\", \"triceps\")), type = \"pairs\")" + }, + { + "objectID": "gallery/basic/2020-01-30-impute-missing-levels/index.html#operators-overview", + "href": "gallery/basic/2020-01-30-impute-missing-levels/index.html#operators-overview", + "title": "Impute Missing Variables", + "section": "Operators overview", + "text": "Operators overview\nAn overview over implemented PipeOps for imputation can be obtained like so:\n\nas.data.table(mlr_pipeops)[tags %in% \"missings\", list(key)]\n\n key\n1: imputeconstant\n2: imputehist\n3: imputelearner\n4: imputemean\n5: imputemedian\n6: imputemode\n7: imputeoor\n8: imputesample" + }, + { + "objectID": "gallery/basic/2020-01-30-impute-missing-levels/index.html#construct-operators", + "href": "gallery/basic/2020-01-30-impute-missing-levels/index.html#construct-operators", + "title": "Impute Missing Variables", + "section": "Construct Operators", + "text": "Construct Operators\nmlr3pipelines contains several imputation methods. We focus on rather simple ones, and show how to impute missing values for factor features and numeric features respectively.\nSince our task only has numeric features, we do not need to deal with imputing factor levels, and can instead concentrate on imputing numeric values:\nWe do this in a two-step process: * We create new indicator columns, that tells us whether the value of a feature is “missing” or “present”. We achieve this using the missind PipeOp.\n\nAfterwards, we impute every missing value by sampling from the histogram of the respective column. We achieve this using the imputehist PipeOp.\n\nWe also have to make sure to apply the pipe operators in the correct order!\n\nimp_missind = po(\"missind\")\nimp_num = po(\"imputehist\", affect_columns = selector_type(\"numeric\"))\n\nIn order to better understand we can look at the results of every PipeOp separately.\nWe can manually trigger the PipeOp to test the operator on our task:\n\ntask_ext = imp_missind$train(list(task))[[1]]\ntask_ext$data()\n\n diabetes missing_glucose missing_insulin missing_mass missing_pressure missing_triceps\n 1: pos present missing present present present\n 2: neg present missing present present present\n 3: pos present missing present present missing\n 4: neg present present present present present\n 5: pos present present present present present\n --- \n764: neg present present present present present\n765: neg present missing present present present\n766: neg present present present present present\n767: pos present missing present present missing\n768: neg present missing present present present\n\n\nFor imputehist, we can do the same:\n\ntask_ext = imp_num$train(list(task))[[1]]\ntask_ext$data()\n\n diabetes age pedigree pregnant glucose insulin mass pressure triceps\n 1: pos 50 0.627 6 148 163.11747 33.6 72 35.000000\n 2: neg 31 0.351 1 85 160.63628 26.6 66 29.000000\n 3: pos 32 0.672 8 183 297.18282 23.3 64 8.204983\n 4: neg 21 0.167 1 89 94.00000 28.1 66 23.000000\n 5: pos 33 2.288 0 137 168.00000 43.1 40 35.000000\n --- \n764: neg 63 0.171 10 101 180.00000 32.9 76 48.000000\n765: neg 27 0.340 2 122 83.69836 36.8 70 27.000000\n766: neg 30 0.245 5 121 112.00000 26.2 72 23.000000\n767: pos 47 0.349 1 126 68.49318 30.1 60 24.460702\n768: neg 23 0.315 1 93 17.80534 30.4 70 31.000000\n\n\nThis time we obtain the imputed data set without missing values.\n\ntask_ext$missings()\n\ndiabetes age pedigree pregnant glucose insulin mass pressure triceps \n 0 0 0 0 0 0 0 0 0" + }, + { + "objectID": "gallery/basic/2020-01-30-impute-missing-levels/index.html#putting-everything-together", + "href": "gallery/basic/2020-01-30-impute-missing-levels/index.html#putting-everything-together", + "title": "Impute Missing Variables", + "section": "Putting everything together", + "text": "Putting everything together\nNow we have to put all PipeOps together in order to form a graph that handles imputation automatically.\nWe do this by creating a Graph that copies the data twice, processes each copy using the respective imputation method and afterwards unions the features. For this we need the following two PipeOps : * copy: Creates copies of the data. * featureunion Merges the two tasks together.\n\ngraph = po(\"copy\", 2) %>>%\n gunion(list(imp_missind, imp_num)) %>>%\n po(\"featureunion\")\n\nas a last step we append the learner we planned on using:\n\ngraph = graph %>>% po(learner)\n\nWe can now visualize the resulting graph:\n\ngraph$plot()" + }, + { + "objectID": "gallery/basic/2020-01-30-impute-missing-levels/index.html#resampling", + "href": "gallery/basic/2020-01-30-impute-missing-levels/index.html#resampling", + "title": "Impute Missing Variables", + "section": "Resampling", + "text": "Resampling\nCorrect imputation is especially important when applying imputation to held-out data during the predict step. If applied incorrectly, imputation could leak info from the test set, which potentially skews our performance estimates. mlr3pipelines takes this complexity away from the user and handles correct imputation internally.\nBy wrapping this graph into a GraphLearner, we can now train resample the full graph, here with a 3-fold cross validation:\n\ngraph_learner = as_learner(graph)\nrr = resample(task, graph_learner, rsmp(\"cv\", folds = 3))\nrr$aggregate()\n\nclassif.ce \n 0.2330729" + }, + { + "objectID": "gallery/basic/2020-01-30-impute-missing-levels/index.html#missing-values-during-prediction", + "href": "gallery/basic/2020-01-30-impute-missing-levels/index.html#missing-values-during-prediction", + "title": "Impute Missing Variables", + "section": "Missing values during prediction", + "text": "Missing values during prediction\nIn some cases, we have missing values only in the data we want to predict on. In order to showcase this, we create a copy of the task with several more missing columns.\n\ndt = task$data()\ndt[1:10, \"age\"] = NA\ndt[30:70, \"pedigree\"] = NA\ntask_2 = as_task_classif(dt, id = \"pima2\", target = \"diabetes\")\n\nAnd now we learn on task, while trying to predict on task_2.\n\ngraph_learner$train(task)\ngraph_learner$predict(task_2)\n\n<PredictionClassif> for 768 observations:\n row_ids truth response\n 1 pos pos\n 2 neg neg\n 3 pos pos\n--- \n 766 neg neg\n 767 pos pos\n 768 neg neg" + }, + { + "objectID": "gallery/basic/2020-01-30-impute-missing-levels/index.html#missing-factor-features", + "href": "gallery/basic/2020-01-30-impute-missing-levels/index.html#missing-factor-features", + "title": "Impute Missing Variables", + "section": "Missing factor features", + "text": "Missing factor features\nFor factor features, the process works analogously. Instead of using imputehist, we can for example use imputeoor. This will simply replace every NA in each factor variable with a new value missing.\nA full graph might the look like this:\n\nimp_missind = po(\"missind\", affect_columns = NULL, which = \"all\")\nimp_fct = po(\"imputeoor\", affect_columns = selector_type(\"factor\"))\ngraph = po(\"copy\", 2) %>>%\n gunion(list(imp_missind, imp_num %>>% imp_fct)) %>>%\n po(\"featureunion\")\n\nNote that we specify the parameter affect_columns = NULL when initializing missind, because we also want indicator columns for our factor features. By default, affect_columns would be set to selector_invert(selector_type(c(\"factor\", \"ordered\", \"character\"))). We also set the parameter which to \"all\" to add indicator columns for all features, regardless whether values were missing during training or not.\nIn order to test out our new graph, we again create a situation where our task has missing factor levels. As the (pima) task does not have any factor levels, we use the famous (boston_housing) task.\n\n# task_bh_1 is the training data without missings\ntask_bh_1 = tsk(\"boston_housing\")\n\n# task_bh_2 is the prediction data with missings\ndt = task_bh_1$data()\ndt[1:10, chas := NA][20:30, rm := NA]\ntask_bh_2 = as_task_regr(dt, id = \"bh\", target = \"medv\")\n\nNow we train on task_bh_1 and predict on task_bh_2:\n\ngraph_learner = as_learner(graph %>>% po(lrn(\"regr.ranger\")))\ngraph_learner$train(task_bh_1)\ngraph_learner$predict(task_bh_2)\n\n<PredictionRegr> for 506 observations:\n row_ids truth response\n 1 24.0 25.16204\n 2 21.6 22.21102\n 3 34.7 33.84124\n--- \n 504 23.9 23.68916\n 505 22.0 22.20551\n 506 11.9 16.14491\n\n\nSuccess! We learned how to deal with missing values in less than 10 minutes." + }, + { + "objectID": "gallery/basic/2020-03-11-basics-german-credit/index.html", + "href": "gallery/basic/2020-03-11-basics-german-credit/index.html", + "title": "German Credit Series - Basics", + "section": "", + "text": "This is the first part in a serial of tutorials. The other parts of this series can be found here:\n\nPart II - Tuning\nPart III - Pipelines\n\nWe will walk through this tutorial interactively. The text is kept short to be followed in real time." + }, + { + "objectID": "gallery/basic/2020-03-11-basics-german-credit/index.html#intro", + "href": "gallery/basic/2020-03-11-basics-german-credit/index.html#intro", + "title": "German Credit Series - Basics", + "section": "", + "text": "This is the first part in a serial of tutorials. The other parts of this series can be found here:\n\nPart II - Tuning\nPart III - Pipelines\n\nWe will walk through this tutorial interactively. The text is kept short to be followed in real time." + }, + { + "objectID": "gallery/basic/2020-03-11-basics-german-credit/index.html#prerequisites", + "href": "gallery/basic/2020-03-11-basics-german-credit/index.html#prerequisites", + "title": "German Credit Series - Basics", + "section": "Prerequisites", + "text": "Prerequisites\nEnsure all packages used in this tutorial are installed. This includes the mlr3verse package, as well as other packages for data handling, cleaning and visualization which we are going to use (data.table, ggplot2, rchallenge, and skimr).\nThen, load the main packages we are going to use:\n\nlibrary(\"mlr3verse\")\nlibrary(\"mlr3learners\")\nlibrary(\"mlr3tuning\")\nlibrary(\"data.table\")\nlibrary(\"ggplot2\")\n\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")" + }, + { + "objectID": "gallery/basic/2020-03-11-basics-german-credit/index.html#machine-learning-use-case-german-credit-data", + "href": "gallery/basic/2020-03-11-basics-german-credit/index.html#machine-learning-use-case-german-credit-data", + "title": "German Credit Series - Basics", + "section": "Machine Learning Use Case: German Credit Data", + "text": "Machine Learning Use Case: German Credit Data\nThe German credit data was originally donated in 1994 by Prof. Dr. Hans Hoffman of the University of Hamburg. A description can be found at the UCI repository. The goal is to classify people by their credit risk (good or bad) using 20 personal, demographic and financial features:\n\n\n\n\n\n\n\nFeature Name\nDescription\n\n\n\n\nage\nage in years\n\n\namount\namount asked by applicant\n\n\ncredit_history\npast credit history of applicant at this bank\n\n\nduration\nduration of the credit in months\n\n\nemployment_duration\npresent employment since\n\n\nforeign_worker\nis applicant foreign worker?\n\n\nhousing\ntype of apartment rented, owned, for free / no payment\n\n\ninstallment_rate\ninstallment rate in percentage of disposable income\n\n\njob\ncurrent job information\n\n\nnumber_credits\nnumber of existing credits at this bank\n\n\nother_debtors\nother debtors/guarantors present?\n\n\nother_installment_plans\nother installment plans the applicant is paying\n\n\npeople_liable\nnumber of people being liable to provide maintenance\n\n\npersonal_status_sex\ncombination of sex and personal status of applicant\n\n\npresent_residence\npresent residence since\n\n\nproperty\nproperties that applicant has\n\n\npurpose\nreason customer is applying for a loan\n\n\nsavings\nsavings accounts/bonds at this bank\n\n\nstatus\nstatus/balance of checking account at this bank\n\n\ntelephone\nis there any telephone registered for this customer?\n\n\n\n\nImporting the Data\nThe dataset we are going to use is a transformed version of this German credit dataset, as provided by the rchallenge package (this transformed dataset was proposed by Ulrike Grömping, with factors instead of dummy variables and corrected features):\n\ndata(\"german\", package = \"rchallenge\")\n\nFirst, we’ll do a thorough investigation of the dataset.\n\n\nExploring the Data\nWe can get a quick overview of our dataset using R’s summary function:\n\ndim(german)\n\n[1] 1000 21\n\nstr(german)\n\n'data.frame': 1000 obs. of 21 variables:\n $ status : Factor w/ 4 levels \"no checking account\",..: 1 1 2 1 1 1 1 1 4 2 ...\n $ duration : int 18 9 12 12 12 10 8 6 18 24 ...\n $ credit_history : Factor w/ 5 levels \"delay in paying off in the past\",..: 5 5 3 5 5 5 5 5 5 3 ...\n $ purpose : Factor w/ 11 levels \"others\",\"car (new)\",..: 3 1 10 1 1 1 1 1 4 4 ...\n $ amount : int 1049 2799 841 2122 2171 2241 3398 1361 1098 3758 ...\n $ savings : Factor w/ 5 levels \"unknown/no savings account\",..: 1 1 2 1 1 1 1 1 1 3 ...\n $ employment_duration : Factor w/ 5 levels \"unemployed\",\"< 1 yr\",..: 2 3 4 3 3 2 4 2 1 1 ...\n $ installment_rate : Ord.factor w/ 4 levels \">= 35\"<\"25 <= ... < 35\"<..: 4 2 2 3 4 1 1 2 4 1 ...\n $ personal_status_sex : Factor w/ 4 levels \"male : divorced/separated\",..: 2 3 2 3 3 3 3 3 2 2 ...\n $ other_debtors : Factor w/ 3 levels \"none\",\"co-applicant\",..: 1 1 1 1 1 1 1 1 1 1 ...\n $ present_residence : Ord.factor w/ 4 levels \"< 1 yr\"<\"1 <= ... < 4 yrs\"<..: 4 2 4 2 4 3 4 4 4 4 ...\n $ property : Factor w/ 4 levels \"unknown / no property\",..: 2 1 1 1 2 1 1 1 3 4 ...\n $ age : int 21 36 23 39 38 48 39 40 65 23 ...\n $ other_installment_plans: Factor w/ 3 levels \"bank\",\"stores\",..: 3 3 3 3 1 3 3 3 3 3 ...\n $ housing : Factor w/ 3 levels \"for free\",\"rent\",..: 1 1 1 1 2 1 2 2 2 1 ...\n $ number_credits : Ord.factor w/ 4 levels \"1\"<\"2-3\"<\"4-5\"<..: 1 2 1 2 2 2 2 1 2 1 ...\n $ job : Factor w/ 4 levels \"unemployed/unskilled - non-resident\",..: 3 3 2 2 2 2 2 2 1 1 ...\n $ people_liable : Factor w/ 2 levels \"3 or more\",\"0 to 2\": 2 1 2 1 2 1 2 1 2 2 ...\n $ telephone : Factor w/ 2 levels \"no\",\"yes (under customer name)\": 1 1 1 1 1 1 1 1 1 1 ...\n $ foreign_worker : Factor w/ 2 levels \"yes\",\"no\": 2 2 2 1 1 1 1 1 2 2 ...\n $ credit_risk : Factor w/ 2 levels \"bad\",\"good\": 2 2 2 2 2 2 2 2 2 2 ...\n\n\nOur dataset has 1000 observations and 21 columns. The variable we want to predict is credit_risk (either good or bad), i.e., we aim to classify people by their credit risk.\nWe also recommend the skimr package as it creates very well readable and understandable overviews:\n\nskimr::skim(german)\n\n\nData summary\n\n\nName\ngerman\n\n\nNumber of rows\n1000\n\n\nNumber of columns\n21\n\n\n_______________________\n\n\n\nColumn type frequency:\n\n\n\nfactor\n18\n\n\nnumeric\n3\n\n\n________________________\n\n\n\nGroup variables\nNone\n\n\n\nVariable type: factor\n\n\n\n\n\n\n\n\n\n\n\nskim_variable\nn_missing\ncomplete_rate\nordered\nn_unique\ntop_counts\n\n\n\n\nstatus\n0\n1\nFALSE\n4\n…: 394, no : 274, …: 269, 0<=: 63\n\n\ncredit_history\n0\n1\nFALSE\n5\nno : 530, all: 293, exi: 88, cri: 49\n\n\npurpose\n0\n1\nFALSE\n10\nfur: 280, oth: 234, car: 181, car: 103\n\n\nsavings\n0\n1\nFALSE\n5\nunk: 603, …: 183, …: 103, 100: 63\n\n\nemployment_duration\n0\n1\nFALSE\n5\n1 <: 339, >= : 253, 4 <: 174, < 1: 172\n\n\ninstallment_rate\n0\n1\nTRUE\n4\n< 2: 476, 25 : 231, 20 : 157, >= : 136\n\n\npersonal_status_sex\n0\n1\nFALSE\n4\nmal: 548, fem: 310, fem: 92, mal: 50\n\n\nother_debtors\n0\n1\nFALSE\n3\nnon: 907, gua: 52, co-: 41\n\n\npresent_residence\n0\n1\nTRUE\n4\n>= : 413, 1 <: 308, 4 <: 149, < 1: 130\n\n\nproperty\n0\n1\nFALSE\n4\nbui: 332, unk: 282, car: 232, rea: 154\n\n\nother_installment_plans\n0\n1\nFALSE\n3\nnon: 814, ban: 139, sto: 47\n\n\nhousing\n0\n1\nFALSE\n3\nren: 714, for: 179, own: 107\n\n\nnumber_credits\n0\n1\nTRUE\n4\n1: 633, 2-3: 333, 4-5: 28, >= : 6\n\n\njob\n0\n1\nFALSE\n4\nski: 630, uns: 200, man: 148, une: 22\n\n\npeople_liable\n0\n1\nFALSE\n2\n0 t: 845, 3 o: 155\n\n\ntelephone\n0\n1\nFALSE\n2\nno: 596, yes: 404\n\n\nforeign_worker\n0\n1\nFALSE\n2\nno: 963, yes: 37\n\n\ncredit_risk\n0\n1\nFALSE\n2\ngoo: 700, bad: 300\n\n\n\nVariable type: numeric\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nskim_variable\nn_missing\ncomplete_rate\nmean\nsd\np0\np25\np50\np75\np100\nhist\n\n\n\n\nduration\n0\n1\n20.90\n12.06\n4\n12.0\n18.0\n24.00\n72\n▇▇▂▁▁\n\n\namount\n0\n1\n3271.25\n2822.75\n250\n1365.5\n2319.5\n3972.25\n18424\n▇▂▁▁▁\n\n\nage\n0\n1\n35.54\n11.35\n19\n27.0\n33.0\n42.00\n75\n▇▆▃▁▁\n\n\n\n\n\nDuring an exploratory analysis meaningful discoveries could be:\n\nSkewed distributions\nMissing values\nEmpty / rare factor variables\n\nAn explanatory analysis is crucial to get a feeling for your data. On the other hand the data can be validated this way. Non-plausible data can be investigated or outliers can be removed.\nAfter feeling confident with the data, we want to do modeling now." + }, + { + "objectID": "gallery/basic/2020-03-11-basics-german-credit/index.html#modeling", + "href": "gallery/basic/2020-03-11-basics-german-credit/index.html#modeling", + "title": "German Credit Series - Basics", + "section": "Modeling", + "text": "Modeling\nConsidering how we are going to tackle the problem of classifying the credit risk relates closely to what mlr3 entities we will use.\nThe typical questions that arise when building a machine learning workflow are:\n\nWhat is the problem we are trying to solve?\nWhat are appropriate learning algorithms?\nHow do we evaluate “good” performance?\n\nMore systematically in mlr3 they can be expressed via five components:\n\nThe Task definition.\nThe Learner definition.\nThe training.\nThe prediction.\nThe evaluation via one or multiple Measures.\n\n\nTask Definition\nFirst, we are interested in the target which we want to model. Most supervised machine learning problems are regression or classification problems. However, note that other problems include unsupervised learning or time-to-event data (covered in mlr3proba).\nWithin mlr3, to distinguish between these problems, we define Tasks. If we want to solve a classification problem, we define a classification task – TaskClassif. For a regression problem, we define a regression task – TaskRegr.\nIn our case it is clearly our objective to model or predict the binary factor variable credit_risk. Thus, we define a TaskClassif:\n\ntask = as_task_classif(german, id = \"GermanCredit\", target = \"credit_risk\")\n\nNote that the German credit data is also given as an example task which ships with the mlr3 package. Thus, you actually don’t need to construct it yourself, just call tsk(\"german_credit\") to retrieve the object from the dictionary mlr_tasks.\n\n\nLearner Definition\nAfter having decided what should be modeled, we need to decide on how. This means we need to decide which learning algorithms, or Learners are appropriate. Using prior knowledge (e.g. knowing that it is a classification task or assuming that the classes are linearly separable) one ends up with one or more suitable Learners.\nMany learners can be obtained via the mlr3learners package. Additionally, many learners are provided via the mlr3extralearners package, from GitHub. These two resources combined account for a large fraction of standard learning algorithms. As mlr3 usually only wraps learners from packages, it is even easy to create a formal Learner by yourself. You may find the section about extending mlr3 in the mlr3book very helpful. If you happen to write your own Learner in mlr3, we would be happy if you share it with the mlr3 community.\nAll available Learners (i.e. all which you have installed from mlr3, mlr3learners, mlr3extralearners, or self-written ones) are registered in the dictionary mlr_learners:\n\nmlr_learners\n\n<DictionaryLearner> with 134 stored values\nKeys: classif.AdaBoostM1, classif.bart, classif.C50, classif.catboost, classif.cforest, classif.ctree,\n classif.cv_glmnet, classif.debug, classif.earth, classif.featureless, classif.fnn, classif.gam,\n classif.gamboost, classif.gausspr, classif.gbm, classif.glmboost, classif.glmer, classif.glmnet,\n classif.IBk, classif.J48, classif.JRip, classif.kknn, classif.ksvm, classif.lda, classif.liblinear,\n classif.lightgbm, classif.LMT, classif.log_reg, classif.lssvm, classif.mob, classif.multinom,\n classif.naive_bayes, classif.nnet, classif.OneR, classif.PART, classif.qda, classif.randomForest,\n classif.ranger, classif.rfsrc, classif.rpart, classif.svm, classif.xgboost, clust.agnes, clust.ap,\n clust.cmeans, clust.cobweb, clust.dbscan, clust.diana, clust.em, clust.fanny, clust.featureless,\n clust.ff, clust.hclust, clust.kkmeans, clust.kmeans, clust.MBatchKMeans, clust.mclust, clust.meanshift,\n clust.pam, clust.SimpleKMeans, clust.xmeans, dens.kde_ks, dens.locfit, dens.logspline, dens.mixed,\n dens.nonpar, dens.pen, dens.plug, dens.spline, regr.bart, regr.catboost, regr.cforest, regr.ctree,\n regr.cubist, regr.cv_glmnet, regr.debug, regr.earth, regr.featureless, regr.fnn, regr.gam, regr.gamboost,\n regr.gausspr, regr.gbm, regr.glm, regr.glmboost, regr.glmnet, regr.IBk, regr.kknn, regr.km, regr.ksvm,\n regr.liblinear, regr.lightgbm, regr.lm, regr.lmer, regr.M5Rules, regr.mars, regr.mob, regr.nnet,\n regr.randomForest, regr.ranger, regr.rfsrc, regr.rpart, regr.rsm, regr.rvm, regr.svm, regr.xgboost,\n surv.akritas, surv.aorsf, surv.blackboost, surv.cforest, surv.coxboost, surv.coxtime, surv.ctree,\n surv.cv_coxboost, surv.cv_glmnet, surv.deephit, surv.deepsurv, surv.dnnsurv, surv.flexible,\n surv.gamboost, surv.gbm, surv.glmboost, surv.glmnet, surv.loghaz, surv.mboost, surv.nelson,\n surv.obliqueRSF, surv.parametric, surv.pchazard, surv.penalized, surv.ranger, surv.rfsrc, surv.svm,\n surv.xgboost\n\n\nFor our problem, a suitable learner could be one of the following: Logistic regression, CART, random forest (or many more).\nA learner can be initialized with the lrn() function and the name of the learner, e.g., lrn(\"classif.xxx\"). Use ?mlr_learners_xxx to open the help page of a learner named xxx.\nFor example, a logistic regression can be initialized in the following manner (logistic regression uses R’s glm() function and is provided by the mlr3learners package):\n\nlibrary(\"mlr3learners\")\nlearner_logreg = lrn(\"classif.log_reg\")\nprint(learner_logreg)\n\n<LearnerClassifLogReg:classif.log_reg>\n* Model: -\n* Parameters: list()\n* Packages: mlr3, mlr3learners, stats\n* Predict Types: [response], prob\n* Feature Types: logical, integer, numeric, character, factor, ordered\n* Properties: loglik, twoclass\n\n\n\n\nTraining\nTraining is the procedure, where a model is fitted on the (training) data.\n\nLogistic Regression\nWe start with the example of the logistic regression. However, you will immediately see that the procedure generalizes to any learner very easily.\nAn initialized learner can be trained on data using $train():\n\nlearner_logreg$train(task)\n\nTypically, in machine learning, one does not use the full data which is available but a subset, the so-called training data.\nTo efficiently perform a split of the data one could do the following:\n\ntrain_set = sample(task$row_ids, 0.8 * task$nrow)\ntest_set = setdiff(task$row_ids, train_set)\n\n80 percent of the data is used for training. The remaining 20 percent are used for evaluation at a subsequent later point in time. train_set is an integer vector referring to the selected rows of the original dataset:\n\nhead(train_set)\n\n[1] 836 679 129 930 509 471\n\n\nIn mlr3 the training with a subset of the data can be declared by the additional argument row_ids = train_set:\n\nlearner_logreg$train(task, row_ids = train_set)\n\nThe fitted model can be accessed via:\n\nlearner_logreg$model\n\n\nCall: stats::glm(formula = task$formula(), family = \"binomial\", data = data, \n model = FALSE)\n\nCoefficients:\n (Intercept) age \n 0.0688846 -0.0159818 \n amount credit_historycritical account/other credits elsewhere \n 0.0001329 0.4580373 \ncredit_historyno credits taken/all credits paid back duly credit_historyexisting credits paid back duly till now \n -0.5087518 -1.0249187 \n credit_historyall credits at this bank paid back duly duration \n -1.5582920 0.0360543 \n employment_duration< 1 yr employment_duration1 <= ... < 4 yrs \n 0.0720620 -0.1262893 \n employment_duration4 <= ... < 7 yrs employment_duration>= 7 yrs \n -0.5589136 -0.1545512 \n foreign_workerno housingrent \n 1.3647905 -0.6199554 \n housingown installment_rate.L \n -0.6851413 0.8838467 \n installment_rate.Q installment_rate.C \n -0.0385000 -0.1072466 \n jobunskilled - resident jobskilled employee/official \n 0.9797910 0.7657897 \n jobmanager/self-empl./highly qualif. employee number_credits.L \n 0.5793418 0.4081443 \n number_credits.Q number_credits.C \n -0.3386148 -0.0262034 \n other_debtorsco-applicant other_debtorsguarantor \n 0.4995457 -0.4840799 \n other_installment_plansstores other_installment_plansnone \n 0.1844457 -0.2035917 \n people_liable0 to 2 personal_status_sexfemale : non-single or male : single \n -0.2306212 -0.2797497 \n personal_status_sexmale : married/widowed personal_status_sexfemale : single \n -0.7947385 -0.4173530 \n present_residence.L present_residence.Q \n 0.0948244 -0.4654771 \n present_residence.C propertycar or other \n 0.2317025 0.2583020 \n propertybuilding soc. savings agr./life insurance propertyreal estate \n 0.2595201 0.6821534 \n purposecar (new) purposecar (used) \n -1.5120761 -0.6224479 \n purposefurniture/equipment purposeradio/television \n -0.7776132 -0.1649750 \n purposedomestic appliances purposerepairs \n 0.1966830 0.3824875 \n purposevacation purposeretraining \n -1.9184037 -0.9364954 \n purposebusiness savings... < 100 DM \n -1.2647440 -0.2148135 \n savings100 <= ... < 500 DM savings500 <= ... < 1000 DM \n -0.5445696 -1.4241969 \n savings... >= 1000 DM status... < 0 DM \n -1.0478097 -0.4584854 \n status0<= ... < 200 DM status... >= 200 DM / salary for at least 1 year \n -0.8798435 -1.7552018 \n telephoneyes (under customer name) \n -0.1798432 \n\nDegrees of Freedom: 799 Total (i.e. Null); 745 Residual\nNull Deviance: 980.7 \nResidual Deviance: 702.6 AIC: 812.6\n\n\nThe stored object is a normal glm object and all its S3 methods work as expected:\n\nclass(learner_logreg$model)\n\n[1] \"glm\" \"lm\" \n\nsummary(learner_logreg$model)\n\n\nCall:\nstats::glm(formula = task$formula(), family = \"binomial\", data = data, \n model = FALSE)\n\nDeviance Residuals: \n Min 1Q Median 3Q Max \n-2.3992 -0.6812 -0.3642 0.6939 2.7540 \n\nCoefficients:\n Estimate Std. Error z value Pr(>|z|) \n(Intercept) 0.0688846 1.3333299 0.052 0.958797 \nage -0.0159818 0.0105444 -1.516 0.129605 \namount 0.0001329 0.0000502 2.647 0.008110 ** \ncredit_historycritical account/other credits elsewhere 0.4580373 0.6523911 0.702 0.482623 \ncredit_historyno credits taken/all credits paid back duly -0.5087518 0.4802925 -1.059 0.289484 \ncredit_historyexisting credits paid back duly till now -1.0249188 0.5343038 -1.918 0.055082 . \ncredit_historyall credits at this bank paid back duly -1.5582920 0.4858084 -3.208 0.001338 ** \nduration 0.0360543 0.0106583 3.383 0.000718 ***\nemployment_duration< 1 yr 0.0720620 0.4845297 0.149 0.881770 \nemployment_duration1 <= ... < 4 yrs -0.1262893 0.4577516 -0.276 0.782632 \nemployment_duration4 <= ... < 7 yrs -0.5589136 0.5016876 -1.114 0.265250 \nemployment_duration>= 7 yrs -0.1545512 0.4625121 -0.334 0.738262 \nforeign_workerno 1.3647905 0.6425196 2.124 0.033660 * \nhousingrent -0.6199554 0.2705326 -2.292 0.021928 * \nhousingown -0.6851413 0.5581021 -1.228 0.219587 \ninstallment_rate.L 0.8838467 0.2472850 3.574 0.000351 ***\ninstallment_rate.Q -0.0385001 0.2217440 -0.174 0.862161 \ninstallment_rate.C -0.1072466 0.2281857 -0.470 0.638357 \njobunskilled - resident 0.9797910 0.7877153 1.244 0.213559 \njobskilled employee/official 0.7657897 0.7627061 1.004 0.315358 \njobmanager/self-empl./highly qualif. employee 0.5793418 0.7790492 0.744 0.457087 \nnumber_credits.L 0.4081443 0.7356488 0.555 0.579026 \nnumber_credits.Q -0.3386148 0.6189845 -0.547 0.584345 \nnumber_credits.C -0.0262034 0.4717322 -0.056 0.955703 \nother_debtorsco-applicant 0.4995457 0.4504675 1.109 0.267452 \nother_debtorsguarantor -0.4840799 0.4744964 -1.020 0.307635 \nother_installment_plansstores 0.1844457 0.4733765 0.390 0.696804 \nother_installment_plansnone -0.2035917 0.2881916 -0.706 0.479911 \npeople_liable0 to 2 -0.2306212 0.2905750 -0.794 0.427386 \npersonal_status_sexfemale : non-single or male : single -0.2797497 0.4602069 -0.608 0.543268 \npersonal_status_sexmale : married/widowed -0.7947384 0.4513890 -1.761 0.078297 . \npersonal_status_sexfemale : single -0.4173530 0.5348044 -0.780 0.435165 \npresent_residence.L 0.0948244 0.2496873 0.380 0.704114 \npresent_residence.Q -0.4654771 0.2293239 -2.030 0.042379 * \npresent_residence.C 0.2317025 0.2240902 1.034 0.301150 \npropertycar or other 0.2583020 0.2934956 0.880 0.378812 \npropertybuilding soc. savings agr./life insurance 0.2595201 0.2712751 0.957 0.338735 \npropertyreal estate 0.6821535 0.4931574 1.383 0.166592 \npurposecar (new) -1.5120761 0.4173677 -3.623 0.000291 ***\npurposecar (used) -0.6224479 0.2979802 -2.089 0.036718 * \npurposefurniture/equipment -0.7776132 0.2803938 -2.773 0.005549 ** \npurposeradio/television -0.1649750 0.8289212 -0.199 0.842244 \npurposedomestic appliances 0.1966830 0.6322897 0.311 0.755751 \npurposerepairs 0.3824875 0.4657037 0.821 0.411469 \npurposevacation -1.9184037 1.1948196 -1.606 0.108362 \npurposeretraining -0.9364954 0.4014654 -2.333 0.019664 * \npurposebusiness -1.2647440 0.8064326 -1.568 0.116807 \nsavings... < 100 DM -0.2148135 0.3235401 -0.664 0.506724 \nsavings100 <= ... < 500 DM -0.5445696 0.5037257 -1.081 0.279660 \nsavings500 <= ... < 1000 DM -1.4241969 0.6223390 -2.288 0.022111 * \nsavings... >= 1000 DM -1.0478097 0.3067055 -3.416 0.000635 ***\nstatus... < 0 DM -0.4584854 0.2481344 -1.848 0.064641 . \nstatus0<= ... < 200 DM -0.8798435 0.4219102 -2.085 0.037035 * \nstatus... >= 200 DM / salary for at least 1 year -1.7552018 0.2629099 -6.676 2.45e-11 ***\ntelephoneyes (under customer name) -0.1798432 0.2322797 -0.774 0.438781 \n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n\n(Dispersion parameter for binomial family taken to be 1)\n\n Null deviance: 980.75 on 799 degrees of freedom\nResidual deviance: 702.58 on 745 degrees of freedom\nAIC: 812.58\n\nNumber of Fisher Scoring iterations: 5\n\n\n\n\nRandom Forest\nJust like the logistic regression, we could train a random forest instead. We use the fast implementation from the ranger package. For this, we first need to define the learner and then actually train it.\nWe now additionally supply the importance argument (importance = \"permutation\"). Doing so, we override the default and let the learner do feature importance determination based on permutation feature importance:\n\nlearner_rf = lrn(\"classif.ranger\", importance = \"permutation\")\nlearner_rf$train(task, row_ids = train_set)\n\nWe can access the importance values using $importance():\n\nlearner_rf$importance()\n\n status duration amount credit_history savings \n 0.0352305897 0.0220794319 0.0126390139 0.0118909925 0.0097629159 \n age property employment_duration installment_rate other_debtors \n 0.0089588614 0.0065744135 0.0054059438 0.0039772325 0.0029554567 \n purpose job housing personal_status_sex present_residence \n 0.0029153698 0.0019001816 0.0017784386 0.0016809300 0.0012840096 \n telephone number_credits other_installment_plans people_liable foreign_worker \n 0.0010803276 0.0009842075 0.0004556746 0.0003807613 0.0003657158 \n\n\nIn order to obtain a plot for the importance values, we convert the importance to a data.table and then process it with ggplot2:\n\nimportance = as.data.table(learner_rf$importance(), keep.rownames = TRUE)\ncolnames(importance) = c(\"Feature\", \"Importance\")\nggplot(importance, aes(x = reorder(Feature, Importance), y = Importance)) +\n geom_col() + coord_flip() + xlab(\"\")\n\n\n\n\n\n\n\n\n\n\n\nPrediction\nLet’s see what the models predict.\nAfter training a model, the model can be used for prediction. Usually, prediction is the main purpose of machine learning models.\nIn our case, the model can be used to classify new credit applicants w.r.t. their associated credit risk (good vs. bad) on the basis of the features. Typically, machine learning models predict numeric values. In the regression case this is very natural. For classification, most models predict scores or probabilities. Based on these values, one can derive class predictions.\n\nPredict Classes\nFirst, we directly predict classes:\n\nprediction_logreg = learner_logreg$predict(task, row_ids = test_set)\nprediction_rf = learner_rf$predict(task, row_ids = test_set)\n\n\nprediction_logreg\n\n<PredictionClassif> for 200 observations:\n row_ids truth response\n 18 good good\n 23 bad bad\n 26 good good\n--- \n 996 bad good\n 997 bad bad\n 1000 bad good\n\n\n\nprediction_rf\n\n<PredictionClassif> for 200 observations:\n row_ids truth response\n 18 good good\n 23 bad bad\n 26 good good\n--- \n 996 bad bad\n 997 bad good\n 1000 bad good\n\n\nThe $predict() method returns a Prediction object. It can be converted to a data.table if one wants to use it downstream.\nWe can also display the prediction results aggregated in a confusion matrix:\n\nprediction_logreg$confusion\n\n truth\nresponse bad good\n bad 28 17\n good 30 125\n\nprediction_rf$confusion\n\n truth\nresponse bad good\n bad 24 13\n good 34 129\n\n\n\n\nPredict Probabilities\nMost learners may not only predict a class variable (“response”), but also their degree of “belief” / “uncertainty” in a given response. Typically, we achieve this by setting the $predict_type slot of a Learner to \"prob\". Sometimes this needs to be done before the learner is trained. Alternatively, we can directly create the learner with this option: lrn(\"classif.log_reg\", predict_type = \"prob\").\n\nlearner_logreg$predict_type = \"prob\"\n\n\nlearner_logreg$predict(task, row_ids = test_set)\n\n<PredictionClassif> for 200 observations:\n row_ids truth response prob.bad prob.good\n 18 good good 0.24602549 0.7539745\n 23 bad bad 0.88286383 0.1171362\n 26 good good 0.05730414 0.9426959\n--- \n 996 bad good 0.49783778 0.5021622\n 997 bad bad 0.59947093 0.4005291\n 1000 bad good 0.42568263 0.5743174\n\n\nNote that sometimes one needs to be cautious when dealing with the probability interpretation of the predictions.\n\n\n\nPerformance Evaluation\nTo measure the performance of a learner on new unseen data, we usually mimic the scenario of unseen data by splitting up the data into training and test set. The training set is used for training the learner, and the test set is only used for predicting and evaluating the performance of the trained learner. Numerous resampling methods (cross-validation, bootstrap) repeat the splitting process in different ways.\nWithin mlr3, we need to specify the resampling strategy using the rsmp() function:\n\nresampling = rsmp(\"holdout\", ratio = 2/3)\nprint(resampling)\n\n<ResamplingHoldout>: Holdout\n* Iterations: 1\n* Instantiated: FALSE\n* Parameters: ratio=0.6667\n\n\nHere, we use “holdout”, a simple train-test split (with just one iteration). We use the resample() function to undertake the resampling calculation:\n\nres = resample(task, learner = learner_logreg, resampling = resampling)\nres\n\n<ResampleResult> of 1 iterations\n* Task: GermanCredit\n* Learner: classif.log_reg\n* Warnings: 0 in 0 iterations\n* Errors: 0 in 0 iterations\n\n\nThe default score of the measure is included in the $aggregate() slot:\n\nres$aggregate()\n\nclassif.ce \n 0.2432432 \n\n\nThe default measure in this scenario is the classification error. Lower is better.\nWe can easily run different resampling strategies, e.g. repeated holdout (\"subsampling\"), or cross validation. Most methods perform repeated train/predict cycles on different data subsets and aggregate the result (usually as the mean). Doing this manually would require us to write loops. mlr3 does the job for us:\n\nresampling = rsmp(\"subsampling\", repeats = 10)\nrr = resample(task, learner = learner_logreg, resampling = resampling)\nrr$aggregate()\n\nclassif.ce \n 0.2474474 \n\n\nInstead, we could also run cross-validation:\n\nresampling = resampling = rsmp(\"cv\", folds = 10)\nrr = resample(task, learner = learner_logreg, resampling = resampling)\nrr$aggregate()\n\nclassif.ce \n 0.257 \n\n\nmlr3 features scores for many more measures. Here, we apply mlr_measures_classif.fpr for the false positive rate, and mlr_measures_classif.fnr for the false negative rate. Multiple measures can be provided as a list of measures (which can directly be constructed via msrs():\n\n# false positive rate\nrr$aggregate(msr(\"classif.fpr\"))\n\nclassif.fpr \n 0.1472895 \n\n# false positive rate and false negative\nmeasures = msrs(c(\"classif.fpr\", \"classif.fnr\"))\nrr$aggregate(measures)\n\nclassif.fpr classif.fnr \n 0.1472895 0.5197922 \n\n\nThere are a few more resampling methods, and quite a few more measures (implemented in mlr3measures). They are automatically registered in the respective dictionaries:\n\nmlr_resamplings\n\n<DictionaryResampling> with 9 stored values\nKeys: bootstrap, custom, custom_cv, cv, holdout, insample, loo, repeated_cv, subsampling\n\nmlr_measures\n\n<DictionaryMeasure> with 67 stored values\nKeys: aic, bic, classif.acc, classif.auc, classif.bacc, classif.bbrier, classif.ce, classif.costs,\n classif.dor, classif.fbeta, classif.fdr, classif.fn, classif.fnr, classif.fomr, classif.fp, classif.fpr,\n classif.logloss, classif.mauc_au1p, classif.mauc_au1u, classif.mauc_aunp, classif.mauc_aunu,\n classif.mbrier, classif.mcc, classif.npv, classif.ppv, classif.prauc, classif.precision, classif.recall,\n classif.sensitivity, classif.specificity, classif.tn, classif.tnr, classif.tp, classif.tpr, clust.ch,\n clust.db, clust.dunn, clust.silhouette, clust.wss, debug_classif, oob_error, regr.bias, regr.ktau,\n regr.mae, regr.mape, regr.maxae, regr.medae, regr.medse, regr.mse, regr.msle, regr.pbias, regr.rae,\n regr.rmse, regr.rmsle, regr.rrse, regr.rse, regr.rsq, regr.sae, regr.smape, regr.srho, regr.sse,\n selected_features, sim.jaccard, sim.phi, time_both, time_predict, time_train\n\n\nTo get help on a resampling method, use ?mlr_resamplings_xxx, for a measure do ?mlr_measures_xxx. You can also browse the mlr3 reference online.\nNote that some measures, for example AUC, require the prediction of probabilities.\n\n\nPerformance Comparison and Benchmarks\nWe could compare Learners by evaluating resample() for each of them manually. However, benchmark() automatically performs resampling evaluations for multiple learners and tasks. benchmark_grid() creates fully crossed designs: Multiple Learners for multiple Tasks are compared w.r.t. multiple Resamplings.\n\nlearners = lrns(c(\"classif.log_reg\", \"classif.ranger\"), predict_type = \"prob\")\ngrid = benchmark_grid(\n tasks = task,\n learners = learners,\n resamplings = rsmp(\"cv\", folds = 10)\n)\nbmr = benchmark(grid)\n\nCareful, large benchmarks may take a long time! This one should take less than a minute, however. In general, we want to use parallelization to speed things up on multi-core machines. For parallelization, mlr3 relies on the future package:\n\n# future::plan(\"multicore\") # uncomment for parallelization\n\nIn the benchmark we can compare different measures. Here, we look at the misclassification rate and the AUC:\n\nmeasures = msrs(c(\"classif.ce\", \"classif.auc\"))\nperformances = bmr$aggregate(measures)\nperformances[, c(\"learner_id\", \"classif.ce\", \"classif.auc\")]\n\n learner_id classif.ce classif.auc\n1: classif.log_reg 0.250 0.7646559\n2: classif.ranger 0.239 0.7977865\n\n\nWe see that the two models perform very similarly." + }, + { + "objectID": "gallery/basic/2020-03-11-basics-german-credit/index.html#deviating-from-hyperparameters-defaults", + "href": "gallery/basic/2020-03-11-basics-german-credit/index.html#deviating-from-hyperparameters-defaults", + "title": "German Credit Series - Basics", + "section": "Deviating from hyperparameters defaults", + "text": "Deviating from hyperparameters defaults\nThe previously shown techniques build the backbone of a mlr3-featured machine learning workflow. However, in most cases one would never proceed in the way we did. While many R packages have carefully selected default settings, they will not perform optimally in any scenario. Typically, we can select the values of such hyperparameters. The (hyper)parameters of a Learner can be accessed and set via its ParamSet $param_set:\n\nlearner_rf$param_set\n\n<ParamSet>\n id class lower upper nlevels default parents value\n 1: alpha ParamDbl -Inf Inf Inf 0.5 \n 2: always.split.variables ParamUty NA NA Inf <NoDefault[3]> \n 3: class.weights ParamUty NA NA Inf \n 4: holdout ParamLgl NA NA 2 FALSE \n 5: importance ParamFct NA NA 4 <NoDefault[3]> permutation\n 6: keep.inbag ParamLgl NA NA 2 FALSE \n 7: max.depth ParamInt 0 Inf Inf \n 8: min.node.size ParamInt 1 Inf Inf \n 9: min.prop ParamDbl -Inf Inf Inf 0.1 \n10: minprop ParamDbl -Inf Inf Inf 0.1 \n11: mtry ParamInt 1 Inf Inf <NoDefault[3]> \n12: mtry.ratio ParamDbl 0 1 Inf <NoDefault[3]> \n13: num.random.splits ParamInt 1 Inf Inf 1 splitrule \n14: num.threads ParamInt 1 Inf Inf 1 1\n15: num.trees ParamInt 1 Inf Inf 500 \n16: oob.error ParamLgl NA NA 2 TRUE \n17: regularization.factor ParamUty NA NA Inf 1 \n18: regularization.usedepth ParamLgl NA NA 2 FALSE \n19: replace ParamLgl NA NA 2 TRUE \n20: respect.unordered.factors ParamFct NA NA 3 ignore \n21: sample.fraction ParamDbl 0 1 Inf <NoDefault[3]> \n22: save.memory ParamLgl NA NA 2 FALSE \n23: scale.permutation.importance ParamLgl NA NA 2 FALSE importance \n24: se.method ParamFct NA NA 2 infjack \n25: seed ParamInt -Inf Inf Inf \n26: split.select.weights ParamUty NA NA Inf \n27: splitrule ParamFct NA NA 3 gini \n28: verbose ParamLgl NA NA 2 TRUE \n29: write.forest ParamLgl NA NA 2 TRUE \n id class lower upper nlevels default parents value\n\nlearner_rf$param_set$values = list(verbose = FALSE)\n\nWe can choose parameters for our learners in two distinct manners. If we have prior knowledge on how the learner should be (hyper-)parameterized, the way to go would be manually entering the parameters in the parameter set. In most cases, however, we would want to tune the learner so that it can search “good” model configurations itself. For now, we only want to compare a few models.\nTo get an idea on which parameters can be manipulated, we can investigate the parameters of the original package version or look into the parameter set of the learner:\n\n## ?ranger::ranger\nas.data.table(learner_rf$param_set)[, .(id, class, lower, upper)]\n\n id class lower upper\n 1: alpha ParamDbl -Inf Inf\n 2: always.split.variables ParamUty NA NA\n 3: class.weights ParamUty NA NA\n 4: holdout ParamLgl NA NA\n 5: importance ParamFct NA NA\n 6: keep.inbag ParamLgl NA NA\n 7: max.depth ParamInt 0 Inf\n 8: min.node.size ParamInt 1 Inf\n 9: min.prop ParamDbl -Inf Inf\n10: minprop ParamDbl -Inf Inf\n11: mtry ParamInt 1 Inf\n12: mtry.ratio ParamDbl 0 1\n13: num.random.splits ParamInt 1 Inf\n14: num.threads ParamInt 1 Inf\n15: num.trees ParamInt 1 Inf\n16: oob.error ParamLgl NA NA\n17: regularization.factor ParamUty NA NA\n18: regularization.usedepth ParamLgl NA NA\n19: replace ParamLgl NA NA\n20: respect.unordered.factors ParamFct NA NA\n21: sample.fraction ParamDbl 0 1\n22: save.memory ParamLgl NA NA\n23: scale.permutation.importance ParamLgl NA NA\n24: se.method ParamFct NA NA\n25: seed ParamInt -Inf Inf\n26: split.select.weights ParamUty NA NA\n27: splitrule ParamFct NA NA\n28: verbose ParamLgl NA NA\n29: write.forest ParamLgl NA NA\n id class lower upper\n\n\nFor the random forest two meaningful parameters which steer model complexity are num.trees and mtry. num.trees defaults to 500 and mtry to floor(sqrt(ncol(data) - 1)), in our case 4.\nIn the following we aim to train three different learners:\n\nThe default random forest.\nA random forest with low num.trees and low mtry.\nA random forest with high num.trees and high mtry.\n\nWe will benchmark their performance on the German credit dataset. For this we construct the three learners and set the parameters accordingly:\n\nrf_med = lrn(\"classif.ranger\", id = \"med\", predict_type = \"prob\")\n\nrf_low = lrn(\"classif.ranger\", id = \"low\", predict_type = \"prob\",\n num.trees = 5, mtry = 2)\n\nrf_high = lrn(\"classif.ranger\", id = \"high\", predict_type = \"prob\",\n num.trees = 1000, mtry = 11)\n\nOnce the learners are defined, we can benchmark them:\n\nlearners = list(rf_low, rf_med, rf_high)\ngrid = benchmark_grid(\n tasks = task,\n learners = learners,\n resamplings = rsmp(\"cv\", folds = 10)\n)\n\n\nbmr = benchmark(grid)\nprint(bmr)\n\n<BenchmarkResult> of 30 rows with 3 resampling runs\n nr task_id learner_id resampling_id iters warnings errors\n 1 GermanCredit low cv 10 0 0\n 2 GermanCredit med cv 10 0 0\n 3 GermanCredit high cv 10 0 0\n\n\nWe compare misclassification rate and AUC again:\n\nmeasures = msrs(c(\"classif.ce\", \"classif.auc\"))\nperformances = bmr$aggregate(measures)\nperformances[, .(learner_id, classif.ce, classif.auc)]\n\n learner_id classif.ce classif.auc\n1: low 0.278 0.7287261\n2: med 0.240 0.7973700\n3: high 0.233 0.7891017\n\nautoplot(bmr)\n\n\n\n\n\n\n\n\nThe “low” settings seem to underfit a bit, the “high” setting is comparable to the default setting “med”." + }, + { + "objectID": "gallery/basic/2020-03-11-basics-german-credit/index.html#outlook", + "href": "gallery/basic/2020-03-11-basics-german-credit/index.html#outlook", + "title": "German Credit Series - Basics", + "section": "Outlook", + "text": "Outlook\nThis tutorial was a detailed introduction to machine learning workflows within mlr3. Having followed this tutorial you should be able to run your first models yourself. Next to that we spiked into performance evaluation and benchmarking. Furthermore, we showed how to customize learners.\nThe next parts of the tutorial will go more into depth into additional mlr3 topics:\n\nPart II - Tuning introduces you to the mlr3tuning package\nPart III - Pipelines introduces you to the mlr3pipelines package" + }, + { + "objectID": "gallery/basic/2020-05-04-moneyball/index.html", + "href": "gallery/basic/2020-05-04-moneyball/index.html", + "title": "mlr3 and OpenML - Moneyball Use Case", + "section": "", + "text": "This use case shows how to easily work with datasets available via OpenML into an mlr3 workflow.\nThe following operations are illustrated:" + }, + { + "objectID": "gallery/basic/2020-05-04-moneyball/index.html#prerequisites", + "href": "gallery/basic/2020-05-04-moneyball/index.html#prerequisites", + "title": "mlr3 and OpenML - Moneyball Use Case", + "section": "Prerequisites", + "text": "Prerequisites\n\n# various functions of the mlr3 ecosystem\nlibrary(\"mlr3verse\")\n# about a dozen reasonable learners\nlibrary(\"mlr3learners\")\n# retrieving the data\nlibrary(\"OpenML\")\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")" + }, + { + "objectID": "gallery/basic/2020-05-04-moneyball/index.html#retrieving-the-data-from-openml", + "href": "gallery/basic/2020-05-04-moneyball/index.html#retrieving-the-data-from-openml", + "title": "mlr3 and OpenML - Moneyball Use Case", + "section": "Retrieving the data from OpenML", + "text": "Retrieving the data from OpenML\nWe can use the OpenML package to retrieve data (and more) straight away. OpenML is is an inclusive movement to build an open, organized, online ecosystem for machine learning. Typically, you can retrieve the data with an data.id. The id can be found on OpenML. We choose the data set 41021. The related web page can be accessed here. This data set was uploaded by Joaquin Vanschoren.\n\noml_data = getOMLDataSet(data.id = 41021)\n\nDownloading from 'http://www.openml.org/api/v1/data/41021' to '/tmp/RtmpIRWjZy/cache/datasets/41021/description.xml'.\n\n\nDownloading from 'https://api.openml.org/data/v1/download/18626236/Moneyball.arff' to '/tmp/RtmpIRWjZy/cache/datasets/41021/dataset.arff'\n\n\nLoading required package: readr\n\n\nThe description indicates that the data set is associated with baseball or more precisely the story of Moneyball.\n\nhead(as.data.table(oml_data))\n\n\n\n\n\n\n\nHowever, the description within the OpenML object is not very detailed. The previously referenced page however states the following:\nIn the early 2000s, Billy Beane and Paul DePodesta worked for the Oakland Athletics. During their work there, they disrupted the game of baseball. They didn’t do it using a bat or glove, and they certainly didn’t do it by throwing money at the issue; in fact, money was the issue. They didn’t have enough of it, but they were still expected to keep up with teams that had more substantial endorsements. This is where Statistics came riding down the hillside on a white horse to save the day. This data set contains some of the information that was available to Beane and DePodesta in the early 2000s, and it can be used to better understand their methods.\nThis data set contains a set of variables that Beane and DePodesta emphasized in their work. They determined that statistics like on-base percentage (obp) and slugging percentage (slg) were very important when it came to scoring runs, however, they were largely undervalued by most scouts at the time. This translated to a gold mine for Beane and DePodesta. Since these players weren’t being looked at by other teams, they could recruit these players on a small budget. The variables are as follows:\n\nteam\nleague\nyear\nruns scored (rs)\nruns allowed (ra)\nwins (w)\non-base percentage (obp)\nslugging percentage (slg)\nbatting average (ba)\nplayoffs (binary)\nrankseason\nrankplayoffs\ngames played (g)\nopponent on-base percentage (oobp)\nopponent slugging percentage (oslg)\n\nWhile Beane and DePodesta defined most of these statistics and measures for individual players, this data set is on the team level.\nThese statistics seem very informative if you are into baseball. If baseball of rather obscure to you, simply take these features as given or give this article a quick read.\nFinally, note that the moneyball dataset is also included in the mlr3data package where you can get the preprocessed (integers properly encoded as such, etc.) data via:\n\ndata(\"moneyball\", package = \"mlr3data\")\nskimr::skim(moneyball)\n\n\nData summary\n\n\nName\nmoneyball\n\n\nNumber of rows\n1232\n\n\nNumber of columns\n15\n\n\n_______________________\n\n\n\nColumn type frequency:\n\n\n\nfactor\n6\n\n\nnumeric\n9\n\n\n________________________\n\n\n\nGroup variables\nNone\n\n\n\nVariable type: factor\n\n\n\n\n\n\n\n\n\n\n\nskim_variable\nn_missing\ncomplete_rate\nordered\nn_unique\ntop_counts\n\n\n\n\nteam\n0\n1.0\nFALSE\n39\nBAL: 47, BOS: 47, CHC: 47, CHW: 47\n\n\nleague\n0\n1.0\nFALSE\n2\nAL: 616, NL: 616\n\n\nplayoffs\n0\n1.0\nFALSE\n2\n0: 988, 1: 244\n\n\nrankseason\n988\n0.2\nFALSE\n8\n2: 53, 1: 52, 3: 44, 4: 44\n\n\nrankplayoffs\n988\n0.2\nFALSE\n5\n3: 80, 4: 68, 1: 47, 2: 47\n\n\ng\n0\n1.0\nFALSE\n8\n162: 954, 161: 139, 163: 93, 160: 23\n\n\n\nVariable type: numeric\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nskim_variable\nn_missing\ncomplete_rate\nmean\nsd\np0\np25\np50\np75\np100\nhist\n\n\n\n\nyear\n0\n1.00\n1988.96\n14.82\n1962.00\n1976.75\n1989.00\n2002.00\n2012.00\n▆▆▇▆▇\n\n\nrs\n0\n1.00\n715.08\n91.53\n463.00\n652.00\n711.00\n775.00\n1009.00\n▁▆▇▃▁\n\n\nra\n0\n1.00\n715.08\n93.08\n472.00\n649.75\n709.00\n774.25\n1103.00\n▂▇▆▂▁\n\n\nw\n0\n1.00\n80.90\n11.46\n40.00\n73.00\n81.00\n89.00\n116.00\n▁▃▇▆▁\n\n\nobp\n0\n1.00\n0.33\n0.02\n0.28\n0.32\n0.33\n0.34\n0.37\n▁▃▇▅▁\n\n\nslg\n0\n1.00\n0.40\n0.03\n0.30\n0.38\n0.40\n0.42\n0.49\n▁▅▇▅▁\n\n\nba\n0\n1.00\n0.26\n0.01\n0.21\n0.25\n0.26\n0.27\n0.29\n▁▂▇▆▂\n\n\noobp\n812\n0.34\n0.33\n0.02\n0.29\n0.32\n0.33\n0.34\n0.38\n▂▇▇▃▁\n\n\noslg\n812\n0.34\n0.42\n0.03\n0.35\n0.40\n0.42\n0.44\n0.50\n▁▆▇▅▁\n\n\n\n\n\nThe summary shows how this data we are dealing with looks like: Some data is missing, however, this has structural reasons. There are 39 teams with each maximally 47 years (1962 - 2012). For 988 cases the information on rankseason and rankplayoffs is missing. This is since these simply did not reach the playoffs and hence have no reported rank.\n\nsummary(moneyball[moneyball$playoffs == 0, c(\"rankseason\", \"rankplayoffs\")])\n\n rankseason rankplayoffs\n 1 : 0 1 : 0 \n 2 : 0 2 : 0 \n 3 : 0 3 : 0 \n 4 : 0 4 : 0 \n 5 : 0 5 : 0 \n (Other): 0 NA's:988 \n NA's :988 \n\n\nOn the other hand, oobp and oslg have \\(812\\) missing values. It seems as if these measures were not available before \\(1998\\).\n\nlibrary(ggplot2)\nlibrary(naniar)\n\nggplot(moneyball, aes(x = year, y = oobp)) +\n geom_miss_point()\n\n\n\n\n\n\n\n\nWe seem to have a missing data problem. Typically, in this case, we have three options: They are:\n\nComplete case analysis: Exclude all observation with missing values.\nComplete feature analysis: Exclude all features with missing values.\nMissing value imputation: Use a model to “guess” the missing values (based on the underlying distribution of the data.\n\nUsually, missing value imputation is preferred over the first two. However, in machine learning, one can try out all options and see which performs best for the underlying problem. For now, we limit ourselves to a rather simple imputation technique, imputation by randomly sampling from the univariate distribution. Note that this does not take the multivariate distribution into account properly and that there are more elaborate approaches. We only aim to impute oobp and oslg. For the other missing (categorical) features, we simply add a new level which indicates that information is missing (i.e. all missing values belong to).\nIt is important to note that in this case here the vast majority of information on the features is missing. In this case, imputation is performed to not throw away the existing information of the features.\nmlr3 has some solutions for that within the mlr3pipelines package. We start with an easy PipeOp which only performs numeric imputation.\n\nimp_num = po(\"imputehist\", affect_columns = selector_type(c(\"integer\", \"numeric\")))\n\nNext, we append the second imputation job for factors.\n\nimp_fct = po(\"imputeoor\", affect_columns = selector_type(\"factor\"))\ngraph = imp_num %>>% imp_fct\ngraph$plot(html = FALSE)" + }, + { + "objectID": "gallery/basic/2020-05-04-moneyball/index.html#creating-tasks-and-learners", + "href": "gallery/basic/2020-05-04-moneyball/index.html#creating-tasks-and-learners", + "title": "mlr3 and OpenML - Moneyball Use Case", + "section": "Creating tasks and learners", + "text": "Creating tasks and learners\nThe fact that there is missing data does not affect the task definition. The task determines what is the problem to be solved by machine learning. We want to explain the runs scored (rs). rs is an important measure as a run is equivalent to a ‘point’ scored in other sports. Naturally, the aim of a coach should be to maximise runs scored and minimise runs allowed. As runs scored and runs allowed are both legitimate targets we ignore the runs allowed here. The task is defined by:\n\n# creates a `mlr3` task from scratch, from a data.frame\n# 'target' names the column in the dataset we want to learn to predict\ntask = as_task_regr(moneyball, target = \"rs\")\ntask$missings()\n\n\n\n\n\n\n\nThe $missings() method indicates what we already knew: our missing values. Missing values are not always a problem. Some learners can deal with them pretty well. However, we want to use a random forest for our task.\n\n# creates a learner\ntest_learner = lrn(\"regr.ranger\")\n\n# displays the properties\ntest_learner$properties\n\n[1] \"hotstart_backward\" \"importance\" \"oob_error\" \"weights\" \n\n\nTypically, in mlr3 the $properties field would tell us whether missing values are a problem to this learner or not. As it is not listed here, the random forest cannot deal with missing values.\nAs we aim to use imputation beforehand, we incorporate it into the learner. Our selected learner is going to be a random forest from the ranger package.\nOne can allow the embedding of the preprocessing (imputation) into a learner by creating a PipeOpLearner. This special Learner can be put into a graph together with the imputer.\n\n# convert learner to pipeop learner and set hyperparameter\npipeop_learner = po(lrn(\"regr.ranger\"), num.trees = 1000, importance = \"permutation\")\n\n# add pipeop learner to graph and create graph learner\ngraph_learner = as_learner(graph %>>% pipeop_learner)\n\nThe final graph looks like the following:\n\ngraph_learner$graph$plot(html = FALSE)" + }, + { + "objectID": "gallery/basic/2020-05-04-moneyball/index.html#train-and-predict", + "href": "gallery/basic/2020-05-04-moneyball/index.html#train-and-predict", + "title": "mlr3 and OpenML - Moneyball Use Case", + "section": "Train and predict", + "text": "Train and predict\nTo get a feeling of how our model performs we simply train the Learner on a subset of the data and predict the hold-out data.\n\n# defines the training and testing data; 95% is used for training\ntrain_set = sample(task$nrow, 0.95 * task$nrow)\ntest_set = setdiff(seq_len(task$nrow), train_set)\n\n# train learner on subset of task\ngraph_learner$train(task, row_ids = train_set)\n\n# predict using held out observations\nprediction = graph_learner$predict(task, row_ids = test_set)\n\nhead(as.data.table(prediction))\n\n\n\n\n\n\n\nViewing the predicted values it seems like the model predicts reasonable values that are fairly close to the truth." + }, + { + "objectID": "gallery/basic/2020-05-04-moneyball/index.html#evaluation-resampling", + "href": "gallery/basic/2020-05-04-moneyball/index.html#evaluation-resampling", + "title": "mlr3 and OpenML - Moneyball Use Case", + "section": "Evaluation & Resampling", + "text": "Evaluation & Resampling\nWhile the prediction indicated that the model is doing what it is supposed to, we want to have a more systematic understanding of the model performance. That means we want to know by how much our model is away from the truth on average. Cross-validation investigates this question. In mlr3 10-fold cross-validation is constructed as follows:\n\ncv10 = rsmp(\"cv\", folds = 10)\nrr = resample(task, graph_learner, cv10)\n\nWe choose some of the performance measures provided by:\n\nas.data.table(mlr_measures)\n\n\n\n\n\n\n\nWe choose the mean absolute error and the mean squared error.\n\nrr$score(msrs(c(\"regr.mae\", \"regr.mse\")))\n\n\n\n\n\n\n\nWe can also compute now by how much our model was on average wrong when predicting the runs scored.\n\nrr$aggregate(msr(\"regr.mae\"))\n\nregr.mae \n19.39997 \n\n\nThat seems not too bad. Considering that on average approximately 715 runs per team per season have been scored.\n\nmean(moneyball$rs)\n\n[1] 715.082" + }, + { + "objectID": "gallery/basic/2020-05-04-moneyball/index.html#performance-boost-of-imputation", + "href": "gallery/basic/2020-05-04-moneyball/index.html#performance-boost-of-imputation", + "title": "mlr3 and OpenML - Moneyball Use Case", + "section": "Performance boost of imputation", + "text": "Performance boost of imputation\nTo assess if imputation was beneficial, we can compare our current learner with a learner which ignores the missing features. Normally, one would set up a benchmark for this. However, we want to keep things short in this use case. Thus, we only set up the alternative learner (with identical hyperparameters) and compare the 10-fold cross-validated mean absolute error.\nAs we are mostly interested in the numeric imputation we leave the remaining graph as it is.\n\nimpute_oor = po(\"imputeoor\", affect_columns = selector_type(\"factor\"))\n\nSubsequently, we create a pipeline with PipeOpSelect.\n\nfeature_names = colnames(moneyball)[!sapply(moneyball, anyNA)]\nfeature_names = c(feature_names[feature_names %in% task$feature_names],\n \"rankseason\", \"rankplayoffs\")\nselect_na = po(\"select\", selector = selector_name(feature_names))\n\ngraph_2 = impute_oor %>>% select_na\ngraph_2$plot(html = FALSE)\n\n\n\n\n\n\n\n\nNow we complete the learner and apply resampling as before.\n\ngraph_learner_2 = as_learner(graph_2 %>>% pipeop_learner)\nrr_2 = resample(task, graph_learner_2, cv10)\nrr_2$aggregate(msr(\"regr.mae\"))\n\nregr.mae \n19.03752 \n\n\nSurprisingly, the performance seems to be approximately the same. That means that the imputed features seem not very helpful. We can use the variable.importance of the random forest.\n\nsort(graph_learner$model$regr.ranger$model$variable.importance, decreasing = TRUE)\n\n\n\n\n\n\n\nWe see that according to this the left out oobp and oslg seem to have solely rudimentary explanatory power. This may be because there were simply too many instances or because the features are themselves not very powerful." + }, + { + "objectID": "gallery/basic/2020-05-04-moneyball/index.html#conclusion", + "href": "gallery/basic/2020-05-04-moneyball/index.html#conclusion", + "title": "mlr3 and OpenML - Moneyball Use Case", + "section": "Conclusion", + "text": "Conclusion\nSo, to sum up, what we have learned: We can access very cool data straight away with the OpenML package. (We are working on a better direct implementation into mlr3 at the moment.) We can work with missing data very well in mlr3. Nevertheless, we discovered that sometimes imputation does not lead to the intended goals. We also learned how to use some PipeOps from the mlr3pipelines package.\nBut most importantly, we found a way to predict the runs scored of MLB teams.\nIf you want to know more, read the mlr3book and the documentation of the mentioned packages." + }, + { + "objectID": "gallery/optimization/2023-02-07-recursive-feature-elimination/index.html", + "href": "gallery/optimization/2023-02-07-recursive-feature-elimination/index.html", + "title": "Recursive Feature Elimination on the Sonar Data Set", + "section": "", + "text": "Scope\nFeature selection is the process of finding an optimal subset of features in order to improve the performance, interpretability and robustness of machine learning algorithms. In this article, we introduce the wrapper feature selection method Recursive Feature Elimination. Wrapper methods iteratively select features that optimize a performance measure. As an example, we will search for the optimal set of features for a gradient boosting machine and support vector machine on the Sonar data set. We assume that you are already familiar with the basic building blocks of the mlr3 ecosystem. If you are new to feature selection, we recommend reading the feature selection chapter of the mlr3book first.\n\n\nRecursive Feature Elimination\nRecursive Feature Elimination (RFE) is a widely used feature selection method for high-dimensional data sets. The idea is to iteratively remove the least predictive feature from a model until the desired number of features is reached. This feature is determined by the built-in feature importance method of the model. Currently, RFE works with support vector machines (SVM), decision tree algorithms and gradient boosting machines (GBM). Supported learners are tagged with the \"importance\" property. For a full list of supported learners, see the learner page on the mlr-org website and search for \"importance\".\nGuyon et al. (2002) developed the RFE algorithm for SVMs (SVM-RFE) to select informative genes in cancer classification. The importance of the features is given by the weight vector of a linear support vector machine. This method was later extended to other machine learning algorithms. The only requirement is that the models can internally measure the feature importance. The random forest algorithm offers multiple options for measuring feature importance. The commonly used methods are the mean decrease in accuracy (MDA) and the mean decrease in impurity (MDI). The MDA measures the decrease in accuracy for a feature if it was randomly permuted in the out-of-bag sample. The MDI is the total reduction in node impurity when the feature is used for splitting. Gradient boosting algorithms like XGBoost, LightGBM and GBM use similar methods to measure the importance of the features.\nResampling strategies can be combined with the algorithm in different ways. The frameworks scikit-learn (Pedregosa et al. 2011) and caret (Kuhn 2008) implement a variant called recursive feature elimination with cross-validation (RFE-CV) that estimates the optimal number of features with cross-validation first. Then one more RFE is carried out on the complete dataset with the optimal number of features as the final feature set size. The RFE implementation in mlr3 can rank and aggregate importance scores across resampling iterations. We will explore both variants in more detail below.\nmlr3fselect is the feature selection package of the mlr3 ecosystem. It implements the RFE and RFE-CV algorithm. We load all packages of the ecosystem with the mlr3verse package.\n\nlibrary(mlr3verse)\n\nWe retrieve the RFE optimizer with the fs() function.\n\noptimizer = fs(\"rfe\",\n n_features = 1,\n feature_number = 1,\n aggregation = \"rank\")\n\nThe algorithm has multiple control parameters. The optimizer stops when the number of features equals n_features. The parameters feature_number, feature_fraction and subset_size determine the number of features that are removed in each iteration. The feature_number option removes a fixed number of features in each iteration, whereas feature_fraction removes a fraction of the features. The subset_size argument is a vector that specifies exactly how many features are removed in each iteration. The parameters are mutually exclusive and the default is feature_fraction = 0.5. Usually, RFE fits a new model in each resampling iteration and calculates the feature importance again. We can deactivate this behavior by setting recursive = FALSE. The selection of feature subsets in all iterations is then based solely on the importance scores of the first model trained with all features. When running an RFE with a resampling strategy like cross-validation, multiple models and importance scores are generated. The aggregation parameter determines how the importance scores are aggregated. The option \"rank\" ranks the importance scores in each iteration and then averages the ranks of the features. The feature with the lowest average rank is removed. The option \"mean\" averages the importance scores of the features across the iterations. The \"mean\" should only be used if the learner’s importance scores can be reasonably averaged.\n\n\nTask\nThe objective of the Sonar data set is to predict whether a sonar signal bounced off a metal cylinder or a rock. The data set includes 60 numerical features (see Figure 1).\n\ntask = tsk(\"sonar\")\n\n\n\nCode\nlibrary(ggplot2)\nlibrary(data.table)\n\ndata = melt(as.data.table(task), id.vars = task$target_names, measure.vars = task$feature_names)\ndata = data[c(\"V1\", \"V10\", \"V11\", \"V12\", \"V13\", \"V14\"), , on = \"variable\"]\n\nggplot(data, aes(x = value, fill = Class)) +\n geom_density(alpha = 0.5) +\n facet_wrap(~ variable, ncol = 6, scales = \"free\") +\n scale_fill_viridis_d(end = 0.8) +\n theme_minimal() +\n theme(axis.title.x = element_blank())\n\n\n\n\n\n\n\n\nFigure 1: Distribution of the first 5 features in the Sonar dataset.\n\n\n\n\n\n\n\nGradient Boosting Machine\nWe start with the GBM learner and set the predict type to \"prob\" to obtain class probabilities.\n\nlearner = lrn(\"classif.gbm\",\n distribution = \"bernoulli\",\n predict_type = \"prob\")\n\nNow we define the feature selection problem by using the fsi() function that constructs an FSelectInstanceSingleCrit. In addition to the task and learner, we have to select a resampling strategy and performance measure to determine how the performance of a feature subset is evaluated. We pass the \"none\" terminator because the n_features parameter of the optimizer determines when the feature selection stops.\n\ninstance = fsi(\n task = task,\n learner = learner,\n resampling = rsmp(\"cv\", folds = 6),\n measures = msr(\"classif.auc\"),\n terminator = trm(\"none\"))\n\nWe are now ready to start the RFE. To do this, we simply pass the instance to the $optimize() method of the optimizer.\n\noptimizer$optimize(instance)\n\nThe optimizer saves the best feature set and the corresponding estimated performance in instance$result.\nFigure 2 shows the optimization path of the feature selection. We observe that the performance increases first as the number of features decreases. As soon as informative features are removed, the performance drops.\n\n\nCode\nlibrary(viridisLite)\nlibrary(mlr3misc)\n\ndata = as.data.table(instance$archive)\ndata[, n:= map_int(importance, length)]\n\nggplot(data, aes(x = n, y = classif.auc)) +\n geom_line(\n color = viridis(1, begin = 0.5),\n linewidth = 1) +\n geom_point(\n fill = viridis(1, begin = 0.5),\n shape = 21,\n size = 3,\n stroke = 0.5,\n alpha = 0.8) +\n xlab(\"Number of Features\") +\n scale_x_reverse() +\n theme_minimal()\n\n\n\n\n\n\n\n\nFigure 2: Performance of the gradient-boosting models depending on the number of features.\n\n\n\n\n\nThe importance scores of the feature sets are recorded in the archive.\n\nas.data.table(instance$archive)[, list(features, classif.auc, importance)]\n\n features classif.auc importance\n 1: V1,V10,V11,V12,V13,V14,... 0.8929304 58.83333,58.83333,54.50000,54.00000,53.33333,52.50000,...\n 2: V1,V10,V11,V12,V13,V15,... 0.9177811 57.33333,56.00000,54.00000,53.66667,50.50000,50.00000,...\n 3: V1,V10,V11,V12,V13,V15,... 0.9045253 54.83333,54.66667,54.66667,53.00000,51.83333,51.33333,...\n 4: V1,V10,V11,V12,V13,V15,... 0.8927833 56.00000,55.83333,53.00000,52.00000,50.16667,50.00000,...\n 5: V1,V10,V11,V12,V13,V15,... 0.9016274 55.50000,53.50000,51.33333,50.00000,49.00000,48.50000,...\n--- \n56: V11,V12,V16,V48,V9 0.8311625 4.166667,3.333333,2.833333,2.500000,2.166667\n57: V11,V12,V16,V9 0.8216772 3.833333,2.666667,2.000000,1.500000\n58: V11,V12,V16 0.8065807 2.833333,1.833333,1.333333\n59: V11,V12 0.8023780 1.833333,1.166667\n60: V11 0.7515904 1\n\n\n\n\nSupport Vector Machine\nNow we will select the optimal feature set for an SVM with a linear kernel. The importance scores are the weights of the model.\n\nlearner = lrn(\"classif.svm\",\n type = \"C-classification\",\n kernel = \"linear\",\n predict_type = \"prob\")\n\nThe SVM learner does not support the calculation of importance scores at first. The reason is that importance scores cannot be determined with all kernels. This can be seen by the missing \"importance\" property.\n\nlearner$properties\n\n[1] \"multiclass\" \"twoclass\" \n\n\nUsing the \"mlr3fselect.svm_rfe\" callback however makes it possible to use a linear SVM with the RFE optimizer. The callback adds the $importance() method internally to the learner. We load the callback with the clbk() function and pass it as the \"callback\" argument to fsi().\n\ninstance = fsi(\n task = task,\n learner = learner,\n resampling = rsmp(\"cv\", folds = 6),\n measures = msr(\"classif.auc\"),\n terminator = trm(\"none\"),\n callback = clbk(\"mlr3fselect.svm_rfe\"))\n\nWe start the feature selection.\n\noptimizer$optimize(instance)\n\nFigure 3 shows the average performance of the SVMs depending on the number of features. We can see that the performance increases significantly with a reduced feature set.\n\n\nCode\nlibrary(viridisLite)\nlibrary(mlr3misc)\n\ndata = as.data.table(instance$archive)\ndata[, n:= map_int(importance, length)]\n\nggplot(data, aes(x = n, y = classif.auc)) +\n geom_line(\n color = viridis(1, begin = 0.5),\n linewidth = 1) +\n geom_point(\n fill = viridis(1, begin = 0.5),\n shape = 21,\n size = 3,\n stroke = 0.5,\n alpha = 0.8) +\n xlab(\"Number of Features\") +\n scale_x_reverse() +\n theme_minimal()\n\n\n\n\n\n\n\n\nFigure 3: Performance of the support vector machines depending on the number of features.\n\n\n\n\n\nFor datasets with a lot of features, it is more efficient to remove several features per iteration. We show an example where 25% of the features are removed in each iteration.\n\noptimizer = fs(\"rfe\", n_features = 1, feature_fraction = 0.75)\n\ninstance = fsi(\n task = task,\n learner = learner,\n resampling = rsmp(\"cv\", folds = 6),\n measures = msr(\"classif.auc\"),\n terminator = trm(\"none\"),\n callback = clbk(\"mlr3fselect.svm_rfe\"))\n\noptimizer$optimize(instance)\n\nFigure 4 shows a similar optimization curve as Figure 3 but with fewer evaluated feature sets.\n\n\nCode\nlibrary(viridisLite)\nlibrary(mlr3misc)\n\ndata = as.data.table(instance$archive)\ndata[, n:= map_int(importance, length)]\n\nggplot(data, aes(x = n, y = classif.auc)) +\n geom_line(\n color = viridis(1, begin = 0.5),\n linewidth = 1) +\n geom_point(\n fill = viridis(1, begin = 0.5),\n shape = 21,\n size = 3,\n stroke = 0.5,\n alpha = 0.8) +\n xlab(\"Number of Features\") +\n scale_x_reverse() +\n theme_minimal()\n\n\n\n\n\n\n\n\nFigure 4: Optimization path of the feature selection.\n\n\n\n\n\n\n\nRecursive Feature Elimination with Cross Validation\nRFE-CV estimates the optimal number of features before selecting a feature set. For this, an RFE is run in each resampling iteration and the number of features with the best mean performance is selected (see Figure 5). Then one more RFE is carried out on the complete dataset with the optimal number of features as the final feature set size.\n\n\n\n\n\n\n%%{ init: { 'flowchart': { 'curve': 'bump' } } }%%\nflowchart TB\n cross-validation[3-Fold Cross-Validation]\n cross-validation-->rfe-1\n cross-validation-->rfe-2\n cross-validation-->rfe-3\n subgraph rfe-1[RFE 1]\n direction TB\n f14[4 Features]\n f13[3 Features]\n f12[2 Features]\n f11[1 Features]\n f14-->f13-->f12-->f11\n style f13 fill:#ccea84\n end\n subgraph rfe-2[RFE 2]\n direction TB\n f24[4 Features]\n f23[3 Features]\n f22[2 Features]\n f21[1 Features]\n f24-->f23-->f22-->f21\n style f23 fill:#ccea84\n end\n subgraph rfe-3[RFE 3]\n direction TB\n f34[4 Features]\n f33[3 Features]\n f32[2 Features]\n f31[1 Features]\n f34-->f33-->f32-->f31\n style f33 fill:#ccea84\n end\n all_obs[All Observations]\n rfe-1-->all_obs\n rfe-2-->all_obs\n rfe-3-->all_obs\n all_obs --> rfe\n subgraph rfe[RFE]\n direction TB\n f54[4 Features]\n f53[3 Features]\n f54-->f53\n style f53 fill:#8e6698\n end\n\n\n\n\nFigure 5: Example of an RFE-CV. The optimal number of features is estimated with a 3-fold cross-validation. One RFE is executed with each train-test split (RFE 1 to RFE 3). The number of features with the best mean performance (green rectangles) is used as the size of the final feature set. A final RFE is performed on all observations. The algorithm stops when the optimal feature set size is reached (purple rectangle) and the optimized feature set is returned.\n\n\n\n\n\nWe retrieve the RFE-CV optimizer. RFE-CV has almost the same control parameters as the RFE optimizer. The only difference is that no aggregation is needed.\n\noptimizer = fs(\"rfecv\",\n n_features = 1,\n feature_number = 1)\n\nThe chosen resampling strategy is used to estimate the optimal number of features. The 6-fold cross-validation results in 6 RFE runs. You can choose any other resampling strategy with multiple iterations. Let’s start the feature selection.\n\nlearner = lrn(\"classif.svm\",\n type = \"C-classification\",\n kernel = \"linear\",\n predict_type = \"prob\")\n\ninstance = fsi(\n task = task,\n learner = learner,\n resampling = rsmp(\"cv\", folds = 6),\n measures = msr(\"classif.auc\"),\n terminator = trm(\"none\"),\n callback = clbk(\"mlr3fselect.svm_rfe\"))\n\noptimizer$optimize(instance)\n\n\n\n\n\n\n\nWarning\n\n\n\nThe performance of the optimal feature set is calculated on the complete data set and should not be reported as the performance of the final model. Estimate the performance of the final model with nested resampling.\n\n\nWe visualize the selection of the optimal number of features. Each point is the mean performance of the number of features. We achieved the best performance with 19 features.\n\n\nCode\nlibrary(ggplot2)\nlibrary(viridisLite)\nlibrary(mlr3misc)\n\ndata = as.data.table(instance$archive)[!is.na(iteration), ]\naggr = data[, list(\"y\" = mean(unlist(.SD))), by = \"batch_nr\", .SDcols = \"classif.auc\"]\naggr[, batch_nr := 61 - batch_nr]\n\ndata[, n:= map_int(importance, length)]\n\nggplot(aggr, aes(x = batch_nr, y = y)) +\n geom_line(\n color = viridis(1, begin = 0.5),\n linewidth = 1) +\n geom_point(\n fill = viridis(1, begin = 0.5),\n shape = 21,\n size = 3,\n stroke = 0.5,\n alpha = 0.8) +\n geom_vline(\n xintercept = aggr[y == max(y)]$batch_nr,\n colour = viridis(1, begin = 0.33),\n linetype = 3\n ) +\n xlab(\"Number of Features\") +\n ylab(\"Mean AUC\") +\n scale_x_reverse() +\n theme_minimal()\n\n\n\n\n\n\n\n\nFigure 6: Estimation of the optimal number of features. The best mean performance is achieved with 19 features (blue line).\n\n\n\n\n\nThe archive contains the extra column \"iteration\" that indicates in which resampling iteration the feature set was evaluated. The feature subsets of the final RFE run have no value in the \"iteration\" column because they were evaluated on the complete data set.\n\nas.data.table(instance$archive)[, list(features, classif.auc, iteration, importance)]\n\n features classif.auc iteration importance\n 1: V1,V10,V11,V12,V13,V14,... 0.8782895 1 2.864018,1.532774,1.408485,1.399930,1.326165,1.167745,...\n 2: V1,V10,V11,V12,V13,V14,... 0.7026144 2 2.056442,1.706077,1.258703,1.191762,1.190752,1.178514,...\n 3: V1,V10,V11,V12,V13,V14,... 0.8790850 3 1.950412,1.887710,1.820891,1.616219,1.231928,1.138675,...\n 4: V1,V10,V11,V12,V13,V14,... 0.8125000 4 2.6958580,1.5623759,1.4990138,1.3902109,0.9385757,0.9232132,...\n 5: V1,V10,V11,V12,V13,V14,... 0.8807018 5 2.487483,1.470778,1.356517,1.033764,0.635383,0.575074,...\n --- \n398: V1,V11,V12,V16,V23,V3,... 0.9605275 NA 2.0089739,1.1047492,1.0011253,0.6602411,0.6015470,0.5431803,...\n399: V1,V12,V16,V23,V3,V30,... 0.9595988 NA 1.8337471,1.1937962,0.9853467,0.7751384,0.7296726,0.6222569,...\n400: V1,V12,V16,V23,V3,V30,... 0.9589486 NA 1.8824952,1.2468164,1.0106654,0.8090618,0.6983925,0.6568389,...\n401: V1,V12,V16,V23,V3,V30,... 0.9559766 NA 2.3872902,0.9094028,0.8809098,0.8277941,0.7841591,0.7792772,...\n402: V1,V12,V16,V23,V3,V30,... 0.9521687 NA 1.9485133,1.1482257,1.1098823,0.9591012,0.8234140,0.8118616,...\n\n\n\n\nFinal Model\nThe learner we use to make predictions on new data is called the final model. The final model is trained with the optimal feature set on the full data set. The optimal set consists of 19 features and is stored in instance$result_feature_set. We subset the task to the optimal feature set and train the learner.\n\ntask$select(instance$result_feature_set)\nlearner$train(task)\n\nThe trained model can now be used to predict new, external data.\n\n\nConclusion\nThe RFE algorithm is a valuable feature selection method, especially for high-dimensional datasets with only a few observations. The numerous settings of the algorithm in mlr3 make it possible to apply it to many datasets and learners. If you want to know more about feature selection in general, we recommend having a look at our book.\n\n\n\n\n\nReferences\n\nGuyon, Isabelle, Jason Weston, Stephen Barnhill, and Vladimir Vapnik. 2002. “Gene Selection for Cancer Classification Using Support Vector Machines.” Machine Learning 46 (1): 389–422. https://doi.org/10.1023/A:1012487302797.\n\n\nKuhn, Max. 2008. “Building Predictive Models in r Using the Caret Package.” Journal of Statistical Software 28 (November): 1–26. https://doi.org/10.18637/jss.v028.i05.\n\n\nPedregosa, Fabian, Gaël Varoquaux, Alexandre Gramfort, Vincent Michel, Bertrand Thirion, Olivier Grisel, Mathieu Blondel, et al. 2011. “Scikit-Learn: Machine Learning in Python.” Journal of Machine Learning Research 12 (85): 2825–30. http://jmlr.org/papers/v12/pedregosa11a.html." + }, + { + "objectID": "gallery/optimization/2023-01-31-default-configuration/index.html", + "href": "gallery/optimization/2023-01-31-default-configuration/index.html", + "title": "Default Hyperparameter Configuration", + "section": "", + "text": "Scope\nThe predictive performance of modern machine learning algorithms is highly dependent on the choice of their hyperparameter configuration. Options for setting hyperparameters are tuning, manual selection by the user, and using the default configuration of the algorithm. The default configurations are chosen to work with a wide range of data sets but they usually do not achieve the best predictive performance. When tuning a learner in mlr3, we can run the default configuration as a baseline. Seeing how well it performs will tell us whether tuning pays off. If the optimized configurations perform worse, we could expand the search space or try a different optimization algorithm. Of course, it could also be that tuning on the given data set is simply not worth it.\nProbst, Boulesteix, and Bischl (2019) studied the tunability of machine learning algorithms. They found that the tunability of algorithms varies widely. Algorithms like glmnet and XGBoost are highly tunable, while algorithms like random forests work well with their default configuration. The highly tunable algorithms should thus beat their baselines more easily with optimized hyperparameters. In this article, we will tune the hyperparameters of a random forest and compare the performance of the default configuration with the optimized configurations.\n\n\nExample\nWe tune the hyperparameters of the ranger learner on the spam data set. The search space is taken from Bischl et al. (2021).\n\nlibrary(mlr3verse)\n\nlearner = lrn(\"classif.ranger\",\n mtry.ratio = to_tune(0, 1),\n replace = to_tune(),\n sample.fraction = to_tune(1e-1, 1),\n num.trees = to_tune(1, 2000)\n)\n\nWhen creating the tuning instance, we set evaluate_default = TRUE to test the default hyperparameter configuration. The default configuration is evaluated in the first batch of the tuning run. The other batches use the specified tuning method. In this example, they are randomly drawn configurations.\n\ninstance = tune(\n tuner = tnr(\"random_search\", batch_size = 5),\n task = tsk(\"spam\"),\n learner = learner,\n resampling = rsmp (\"holdout\"),\n measures = msr(\"classif.ce\"),\n term_evals = 51,\n evaluate_default = TRUE\n)\n\nThe default configuration is recorded in the first row of the archive. The other rows contain the results of the random search.\n\nas.data.table(instance$archive)[, .(batch_nr, mtry.ratio, replace, sample.fraction, num.trees, classif.ce)]\n\n batch_nr mtry.ratio replace sample.fraction num.trees classif.ce\n 1: 1 0.122807018 TRUE 1.0000000 500 0.04954368\n 2: 2 0.285388074 TRUE 0.1794772 204 0.06584094\n 3: 2 0.097424099 FALSE 0.9475526 1441 0.04237288\n 4: 2 0.008888587 FALSE 0.3216562 1868 0.08409387\n 5: 2 0.335543330 TRUE 0.8122653 106 0.05345502\n--- \n47: 11 0.788995735 FALSE 0.3692454 344 0.06258149\n48: 11 0.459305038 TRUE 0.3153485 1354 0.06258149\n49: 11 0.220334408 TRUE 0.9357554 817 0.05345502\n50: 11 0.868385877 TRUE 0.6743246 1040 0.06127771\n51: 11 0.015417312 FALSE 0.5627943 1836 0.08213820\n\n\nWe plot the performances of the evaluated hyperparameter configurations. The blue line connects the best configuration of each batch. We see that the default configuration already performs well and the optimized configurations can not beat it.\n\nlibrary(mlr3viz)\n\nautoplot(instance, type = \"performance\")\n\n\n\n\n\n\n\n\n\n\nConlcusion\nThe time required to test the default configuration is negligible compared to the time required to run the hyperparameter optimization. It gives us a valuable indication of whether our tuning is properly configured. Running the default configuration as a baseline is a good practice that should be used in every tuning run.\n\n\n\n\n\nReferences\n\nBischl, Bernd, Martin Binder, Michel Lang, Tobias Pielok, Jakob Richter, Stefan Coors, Janek Thomas, et al. 2021. “Hyperparameter Optimization: Foundations, Algorithms, Best Practices and Open Challenges.” arXiv:2107.05847 [Cs, Stat], July. http://arxiv.org/abs/2107.05847.\n\n\nProbst, Philipp, Anne-Laure Boulesteix, and Bernd Bischl. 2019. “Tunability: Importance of Hyperparameters of Machine Learning Algorithms.” Journal of Machine Learning Research 20 (53): 1–32. http://jmlr.org/papers/v20/18-444.html." + }, + { + "objectID": "gallery/optimization/2020-10-14-threshold-tuning/index.html", + "href": "gallery/optimization/2020-10-14-threshold-tuning/index.html", + "title": "Threshold Tuning for Classification Tasks", + "section": "", + "text": "Predicting probabilities in classification tasks allows us to adjust the probability thresholds required for assigning an observation to a certain class. This can lead to improved classification performance, especially for cases where we e.g. aim to balance off metrics such as false positive and false negative rates.\nThis is for example often done in ROC Analysis. The mlr3book also has a chapter on ROC Analysis) for the interested reader. This post does not focus on ROC analysis, but instead focusses on the general problem of adjusting classification thresholds for arbitrary metrics.\nThis post assumes some familiarity with the mlr3, and also the mlr3pipelines and mlr3tuning packages, as both are used during the post. The mlr3book contains more details on those two packages. This post is a more in-depth version of the article on threshold tuning in the mlr3book." + }, + { + "objectID": "gallery/optimization/2020-10-14-threshold-tuning/index.html#intro", + "href": "gallery/optimization/2020-10-14-threshold-tuning/index.html#intro", + "title": "Threshold Tuning for Classification Tasks", + "section": "", + "text": "Predicting probabilities in classification tasks allows us to adjust the probability thresholds required for assigning an observation to a certain class. This can lead to improved classification performance, especially for cases where we e.g. aim to balance off metrics such as false positive and false negative rates.\nThis is for example often done in ROC Analysis. The mlr3book also has a chapter on ROC Analysis) for the interested reader. This post does not focus on ROC analysis, but instead focusses on the general problem of adjusting classification thresholds for arbitrary metrics.\nThis post assumes some familiarity with the mlr3, and also the mlr3pipelines and mlr3tuning packages, as both are used during the post. The mlr3book contains more details on those two packages. This post is a more in-depth version of the article on threshold tuning in the mlr3book." + }, + { + "objectID": "gallery/optimization/2020-10-14-threshold-tuning/index.html#prerequisites", + "href": "gallery/optimization/2020-10-14-threshold-tuning/index.html#prerequisites", + "title": "Threshold Tuning for Classification Tasks", + "section": "Prerequisites", + "text": "Prerequisites\nWe load the mlr3verse package which pulls in the most important packages for this example.\n\nlibrary(mlr3verse)\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\nlgr::get_logger(\"bbotk\")$set_threshold(\"warn\")" + }, + { + "objectID": "gallery/optimization/2020-10-14-threshold-tuning/index.html#thresholds-a-short-intro", + "href": "gallery/optimization/2020-10-14-threshold-tuning/index.html#thresholds-a-short-intro", + "title": "Threshold Tuning for Classification Tasks", + "section": "Thresholds: A short intro", + "text": "Thresholds: A short intro\nIn order to understand thresholds, we will quickly showcase the effect of setting different thresholds:\nFirst we create a learner that predicts probabilities and use it to predict on holdout data, storing the prediction.\n\nlearner = lrn(\"classif.rpart\", predict_type = \"prob\")\nrr = resample(tsk(\"pima\"), learner, rsmp(\"holdout\"))\nprd = rr$prediction()\nprd\n\n<PredictionClassif> for 256 observations:\n row_ids truth response prob.pos prob.neg\n 4 neg neg 0.1057692 0.8942308\n 6 neg neg 0.0200000 0.9800000\n 10 pos neg 0.1428571 0.8571429\n--- \n 764 neg neg 0.2777778 0.7222222\n 766 neg neg 0.0200000 0.9800000\n 767 pos pos 0.8000000 0.2000000\n\n\nIf we now look at the confusion matrix, the off-diagonal elements are errors made by our model (false positives and false negatives) while on-diagol ements are where our model predicted correctly.\n\n# Print confusion matrix\nprd$confusion\n\n truth\nresponse pos neg\n pos 53 27\n neg 37 139\n\n# Print False Positives and False Negatives\nprd$score(list(msr(\"classif.fp\"), msr(\"classif.fn\")))\n\nclassif.fp classif.fn \n 27 37 \n\n\nBy adjusting the classification threshold, in this case the probability required to predict the positive class, we can now trade off predicting more positive cases (first row) against predicting fewer negative cases (second row) or vice versa.\n\n# Lower threshold: More positives\nprd$set_threshold(0.25)$confusion\n\n truth\nresponse pos neg\n pos 78 71\n neg 12 95\n\n\n\n# Higher threshold: Fewer positives\nprd$set_threshold(0.75)$confusion\n\n truth\nresponse pos neg\n pos 52 20\n neg 38 146\n\n\nThis threshold value can now be adjusted optimally for a given measure, such as accuracy. How this can be done is discussed in the following section." + }, + { + "objectID": "gallery/optimization/2020-10-14-threshold-tuning/index.html#adjusting-thresholds-two-strategies", + "href": "gallery/optimization/2020-10-14-threshold-tuning/index.html#adjusting-thresholds-two-strategies", + "title": "Threshold Tuning for Classification Tasks", + "section": "Adjusting thresholds: Two strategies", + "text": "Adjusting thresholds: Two strategies\nCurrently mlr3pipelines offers two main strategies towards adjusting classification thresholds. We can either expose the thresholds as a hyperparameter of the Learner by using PipeOpThreshold. This allows us to tune the thresholds via an outside optimizer from mlr3tuning.\nAlternatively, we can also use PipeOpTuneThreshold which automatically tunes the threshold after each learner fit.\nIn this blog-post, we’ll go through both strategies." + }, + { + "objectID": "gallery/optimization/2020-10-14-threshold-tuning/index.html#pipeopthreshold", + "href": "gallery/optimization/2020-10-14-threshold-tuning/index.html#pipeopthreshold", + "title": "Threshold Tuning for Classification Tasks", + "section": "PipeOpThreshold", + "text": "PipeOpThreshold\nPipeOpThreshold can be put directly after a Learner.\nA simple example would be:\n\ngr = lrn(\"classif.rpart\", predict_type = \"prob\") %>>% po(\"threshold\")\nl = GraphLearner$new(gr)\n\nNote, that predict_type = “prob” is required for po(\"threshold\") to have any effect.\nThe thresholds are now exposed as a hyperparameter of the GraphLearner we created:\n\nas.data.table(l$param_set)[, .(id, class, lower, upper, nlevels)]\n\n id class lower upper nlevels\n 1: classif.rpart.cp ParamDbl 0 1 Inf\n 2: classif.rpart.keep_model ParamLgl NA NA 2\n 3: classif.rpart.maxcompete ParamInt 0 Inf Inf\n 4: classif.rpart.maxdepth ParamInt 1 30 30\n 5: classif.rpart.maxsurrogate ParamInt 0 Inf Inf\n 6: classif.rpart.minbucket ParamInt 1 Inf Inf\n 7: classif.rpart.minsplit ParamInt 1 Inf Inf\n 8: classif.rpart.surrogatestyle ParamInt 0 1 2\n 9: classif.rpart.usesurrogate ParamInt 0 2 3\n10: classif.rpart.xval ParamInt 0 Inf Inf\n11: threshold.thresholds ParamUty NA NA Inf\n\n\nWe can now tune those thresholds from the outside as follows:\nBefore tuning, we have to define which hyperparameters we want to tune over. In this example, we only tune over the thresholds parameter of the threshold PipeOp. you can easily imagine, that we can also jointly tune over additional hyperparameters, i.e. rpart’s cp parameter.\nAs the Task we aim to optimize for is a binary task, we can simply specify the threshold parameter:\n\nsearch_space = ps(\n threshold.thresholds = p_dbl(lower = 0, upper = 1)\n)\n\nWe now create a AutoTuner, which automatically tunes the supplied learner over the ParamSet we supplied above.\n\nat = auto_tuner(\n tuner = tnr(\"random_search\"),\n learner = l,\n resampling = rsmp(\"cv\", folds = 3L),\n measure = msr(\"classif.ce\"),\n search_space = search_space,\n term_evals = 5L,\n)\n\nat$train(tsk(\"german_credit\"))\n\nFor multi-class Tasks, this is a little more complicated. We have to use a trafo to transform a set of ParamDbl into the desired format for threshold.thresholds: A named numeric vector containing the thresholds. This can be easily achieved via a trafo function:\n\nsearch_space = ps(\n versicolor = p_dbl(lower = 0, upper = 1),\n setosa = p_dbl(lower = 0, upper = 1),\n virginica = p_dbl(lower = 0, upper = 1),\n .extra_trafo = function(x, param_set) {\n list(threshold.thresholds = mlr3misc::map_dbl(x, identity))\n }\n)\n\nInside the .exta_trafo, we simply collect all set params into a named vector via map_dbl and store it in the threshold.thresholds slot expected by the learner.\nAgain, we create a AutoTuner, which automatically tunes the supplied learner over the ParamSet we supplied above.\n\nat_2 = auto_tuner(\n tuner = tnr(\"random_search\"),\n learner = l,\n resampling = rsmp(\"cv\", folds = 3L),\n measure = msr(\"classif.ce\"),\n search_space = search_space,\n term_evals = 5L,\n)\n\nat_2$train(tsk(\"iris\"))\n\nOne drawback of this strategy is, that this requires us to fit a new model for each new threshold setting. While setting a threshold and computing performance is relatively cheap, fitting the learner is often more computationally demanding. A better strategy is therefore often to optimize the thresholds separately after each model fit." + }, + { + "objectID": "gallery/optimization/2020-10-14-threshold-tuning/index.html#pipeoptunethreshold", + "href": "gallery/optimization/2020-10-14-threshold-tuning/index.html#pipeoptunethreshold", + "title": "Threshold Tuning for Classification Tasks", + "section": "PipeOpTuneThreshold", + "text": "PipeOpTuneThreshold\nPipeOpTuneThreshold on the other hand works together with PipeOpLearnerCV. It directly optimizes the cross-validated predictions made by this PipeOp.\nA simple example would be:\n\ngr = po(\"learner_cv\", lrn(\"classif.rpart\", predict_type = \"prob\")) %>>%\n po(\"tunethreshold\")\nl2 = GraphLearner$new(gr)\n\nNote, that predict_type = “prob” is required for po(\"tunethreshold\") to have any effect. Additionally, note that this time no threshold parameter is exposed, it is automatically tuned internally.\n\nas.data.table(l2$param_set)[, .(id, class, lower, upper, nlevels)]\n\n id class lower upper nlevels\n 1: classif.rpart.resampling.method ParamFct NA NA 2\n 2: classif.rpart.resampling.folds ParamInt 2 Inf Inf\n 3: classif.rpart.resampling.keep_response ParamLgl NA NA 2\n 4: classif.rpart.cp ParamDbl 0 1 Inf\n 5: classif.rpart.keep_model ParamLgl NA NA 2\n 6: classif.rpart.maxcompete ParamInt 0 Inf Inf\n 7: classif.rpart.maxdepth ParamInt 1 30 30\n 8: classif.rpart.maxsurrogate ParamInt 0 Inf Inf\n 9: classif.rpart.minbucket ParamInt 1 Inf Inf\n10: classif.rpart.minsplit ParamInt 1 Inf Inf\n11: classif.rpart.surrogatestyle ParamInt 0 1 2\n12: classif.rpart.usesurrogate ParamInt 0 2 3\n13: classif.rpart.xval ParamInt 0 Inf Inf\n14: classif.rpart.affect_columns ParamUty NA NA Inf\n15: tunethreshold.measure ParamUty NA NA Inf\n16: tunethreshold.optimizer ParamUty NA NA Inf\n17: tunethreshold.log_level ParamUty NA NA Inf\n\n\nIf we now use the GraphLearner, it automatically adjusts the thresholds during prediction.\nNote that we can set ResamplingInsample as a resampling strategy for PipeOpLearnerCV in order to evaluate predictions on the “training” data. This is generally not advised, as it might lead to over-fitting on the thresholds but can significantly reduce runtime.\nFinally, we can compare no threshold tuning to the tunethreshold approach:\n\nComparison of the approaches\n\nbmr = benchmark(benchmark_grid(\n learners = list(no_tuning = lrn(\"classif.rpart\"), internal = l2),\n tasks = tsk(\"german_credit\"),\n rsmp(\"cv\", folds = 3L)\n))\n\n\nbmr$aggregate(list(msr(\"classif.ce\"), msr(\"classif.fnr\")))\n\n nr task_id learner_id resampling_id iters classif.ce classif.fnr\n1: 1 german_credit classif.rpart cv 3 0.2760095 0.12723983\n2: 2 german_credit classif.rpart.tunethreshold cv 3 0.2879916 0.04485325\nHidden columns: resample_result" + }, + { + "objectID": "gallery/optimization/2021-03-12-practical-tuning-series-tuning-and-parallel-processing/index.html", + "href": "gallery/optimization/2021-03-12-practical-tuning-series-tuning-and-parallel-processing/index.html", + "title": "Practical Tuning Series - Tuning and Parallel Processing", + "section": "", + "text": "Scope\nThis is the fourth part of the practical tuning series. The other parts can be found here:\n\nPart I - Tune a Support Vector Machine\nPart II - Tune a Preprocessing Pipeline\nPart III - Build an Automated Machine Learning System\n\nIn this post, we teach how to run various jobs in mlr3 in parallel. The goal is to map computational jobs (e.g. evaluation of one configuration) to a pool of workers (usually physical CPU cores, sometimes remote computational nodes) to reduce the run time needed for tuning.\n\n\nPrerequisites\nWe load the mlr3verse package which pulls in the most important packages for this example. Additionally, make sure you have installed the packages future and future.apply.\n\nlibrary(mlr3verse)\n\nWe decrease the verbosity of the logger to keep the output clearly represented. The lgr package is used for logging in all mlr3 packages. The mlr3 logger prints the logging messages from the base package, whereas the bbotk logger is responsible for logging messages from the optimization packages (e.g. mlr3tuning ).\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\nlgr::get_logger(\"bbotk\")$set_threshold(\"warn\")\n\n\n\nParallel Backend\nThe workers are specified by the parallel backend which orchestrates starting up, shutting down, and communication with the workers. On a single machine, multisession and multicore are common backends. The multisession backend spawns new background R processes. It is available on all platforms.\n\nfuture::plan(\"multisession\")\n\nThe multicore backend uses forked R processes which allows the workers to access R objects in a shared memory. This reduces the overhead since R objects are only copied in memory if they are modified. Unfortunately, forking processes is not supported on Windows and when running R from within RStudio.\n\nfuture::plan(\"multicore\")\n\nBoth backends support the workers argument that specifies the number of used cores.\nUse this code if your code should run with the multicore backend when possible.\n\nif (future::supportsMulticore()) {\n future::plan(future::multicore)\n} else {\n future::plan(future::multisession)\n}\n\n\n\nResampling\nThe resample() and benchmark() functions in mlr3 can be executed in parallel. The parallelization is triggered by simply declaring a plan via future::plan().\n\nfuture::plan(\"multisession\")\n\ntask = tsk(\"pima\")\nlearner = lrn(\"classif.rpart\") # classification tree\nresampling = rsmp(\"cv\", folds = 3)\n\nresample(task, learner, resampling)\n\n<ResampleResult> with 3 resampling iterations\n task_id learner_id resampling_id iteration warnings errors\n pima classif.rpart cv 1 0 0\n pima classif.rpart cv 2 0 0\n pima classif.rpart cv 3 0 0\n\n\nThe 3-fold cross-validation gives us 3 jobs since each resampling iteration is executed in parallel.\nThe benchmark() function accepts a design of experiments as input where each experiment is defined as a combination of a task, a learner, and a resampling strategy. For each experiment, resampling is performed. The nested loop over experiments and resampling iterations is flattened so that all resampling iterations of all experiments can be executed in parallel.\n\nfuture::plan(\"multisession\")\n\ntasks = list(tsk(\"pima\"), tsk(\"iris\"))\nlearner = lrn(\"classif.rpart\")\nresampling = rsmp(\"cv\", folds = 3)\n\ngrid = benchmark_grid(tasks, learner, resampling)\n\nbenchmark(grid)\n\n<BenchmarkResult> of 6 rows with 2 resampling runs\n nr task_id learner_id resampling_id iters warnings errors\n 1 pima classif.rpart cv 3 0 0\n 2 iris classif.rpart cv 3 0 0\n\n\nThe 2 experiments and the 3-fold cross-validation result in 6 jobs which are executed in parallel.\n\n\nTuning\nThe mlr3tuning package internally calls benchmark() during tuning. If the tuner is capable of suggesting multiple configurations per iteration (such as random search, grid search, or hyperband), these configurations represent individual experiments, and the loop flattening of benchmark() is triggered. E.g., all resampling iterations of all hyperparameter configurations on a grid can be executed in parallel.\n\nfuture::plan(\"multisession\")\n\nlearner = lrn(\"classif.rpart\")\nlearner$param_set$values$cp = to_tune(0.001, 0.1)\nlearner$param_set$values$minsplit = to_tune(1, 10)\n\ninstance = tune(\n tuner = tnr(\"random_search\", batch_size = 5), # random search suggests 5 configurations per batch\n task = tsk(\"pima\"),\n learner = learner,\n resampling = rsmp(\"cv\", folds = 3),\n measure = msr(\"classif.ce\"),\n term_evals = 10\n)\n\nThe batch size of 5 and the 3-fold cross-validation gives us 15 jobs. This is done twice because of the limit of 10 evaluations in total.\n\n\nNested Resampling\nNested resampling results in two nested resampling loops. For this, an AutoTuner is passed to resample() or benchmark(). We can choose different parallelization backends for the inner and outer resampling loop, respectively. We just have to pass a list of backends.\n\n# Runs the outer loop in parallel and the inner loop sequentially\nfuture::plan(list(\"multisession\", \"sequential\"))\n\n# Runs the outer loop sequentially and the inner loop in parallel\nfuture::plan(list(\"sequential\", \"multisession\"))\n\nlearner = lrn(\"classif.rpart\")\nlearner$param_set$values$cp = to_tune(0.001, 0.1)\nlearner$param_set$values$minsplit = to_tune(1, 10)\n\nrr = tune_nested(\n tuner = tnr(\"random_search\", batch_size = 5), # random search suggests 5 configurations per batch\n task = tsk(\"pima\"),\n learner = learner,\n inner_resampling = rsmp (\"cv\", folds = 3),\n outer_resampling = rsmp(\"cv\", folds = 3),\n measure = msr(\"classif.ce\"),\n term_evals = 10\n)\n\nWhile nesting real parallelization backends is often unintended and causes unnecessary overhead, it is useful in some distributed computing setups. It can be achieved with future by forcing a fixed number of workers for each loop.\n\n# Runs both loops in parallel\nfuture::plan(list(future::tweak(\"multisession\", workers = 2),\n future::tweak(\"multisession\", workers = 4)))\n\nThis example would run on 8 cores (= 2 * 4) on the local machine.\n\n\nResources\nThe mlr3book includes a chapters on parallelization. The mlr3cheatsheets contain frequently used commands and workflows of mlr3." + }, + { + "objectID": "gallery/optimization/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/index.html", + "href": "gallery/optimization/2021-03-10-practical-tuning-series-tune-a-preprocessing-pipeline/index.html", + "title": "Practical Tuning Series - Tune a Preprocessing Pipeline", + "section": "", + "text": "Scope\nThis is the second part of the practical tuning series. The other parts can be found here:\n\nPart I - Tune a Support Vector Machine\nPart III - Build an Automated Machine Learning System\nPart IV - Tuning and Parallel Processing\n\nIn this post, we build a simple preprocessing pipeline and tune it. For this, we are using the mlr3pipelines extension package. First, we start by imputing missing values in the Pima Indians Diabetes data set. After that, we encode a factor column to numerical dummy columns in the data set. Next, we combine both preprocessing steps to a Graph and create a GraphLearner. Finally, nested resampling is used to compare the performance of two imputation methods.\n\n\nPrerequisites\nWe load the mlr3verse package which pulls in the most important packages for this example.\n\nlibrary(mlr3verse)\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented. The lgr package is used for logging in all mlr3 packages. The mlr3 logger prints the logging messages from the base package, whereas the bbotk logger is responsible for logging messages from the optimization packages (e.g. mlr3tuning ).\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\nlgr::get_logger(\"bbotk\")$set_threshold(\"warn\")\n\nIn this example, we use the Pima Indians Diabetes data set which is used to predict whether or not a patient has diabetes. The patients are characterized by 8 numeric features of which some have missing values. We alter the data set by categorizing the feature pressure (blood pressure) into the categories \"low\", \"mid\", and \"high\".\n\n# retrieve the task from mlr3\ntask = tsk(\"pima\")\n\n# create data frame with categorized pressure feature\ndata = task$data(cols = \"pressure\")\nbreaks = quantile(data$pressure, probs = c(0, 0.33, 0.66, 1), na.rm = TRUE)\ndata$pressure = cut(data$pressure, breaks, labels = c(\"low\", \"mid\", \"high\"))\n\n# overwrite the feature in the task\ntask$cbind(data)\n\n# generate a quick textual overview\nskimr::skim(task$data())\n\n\nData summary\n\n\nName\ntask$data()\n\n\nNumber of rows\n768\n\n\nNumber of columns\n9\n\n\nKey\nNULL\n\n\n_______________________\n\n\n\nColumn type frequency:\n\n\n\nfactor\n2\n\n\nnumeric\n7\n\n\n________________________\n\n\n\nGroup variables\nNone\n\n\n\nVariable type: factor\n\n\n\n\n\n\n\n\n\n\n\nskim_variable\nn_missing\ncomplete_rate\nordered\nn_unique\ntop_counts\n\n\n\n\ndiabetes\n0\n1.00\nFALSE\n2\nneg: 500, pos: 268\n\n\npressure\n36\n0.95\nFALSE\n3\nlow: 282, mid: 245, hig: 205\n\n\n\nVariable type: numeric\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nskim_variable\nn_missing\ncomplete_rate\nmean\nsd\np0\np25\np50\np75\np100\nhist\n\n\n\n\nage\n0\n1.00\n33.24\n11.76\n21.00\n24.00\n29.00\n41.00\n81.00\n▇▃▁▁▁\n\n\nglucose\n5\n0.99\n121.69\n30.54\n44.00\n99.00\n117.00\n141.00\n199.00\n▁▇▇▃▂\n\n\ninsulin\n374\n0.51\n155.55\n118.78\n14.00\n76.25\n125.00\n190.00\n846.00\n▇▂▁▁▁\n\n\nmass\n11\n0.99\n32.46\n6.92\n18.20\n27.50\n32.30\n36.60\n67.10\n▅▇▃▁▁\n\n\npedigree\n0\n1.00\n0.47\n0.33\n0.08\n0.24\n0.37\n0.63\n2.42\n▇▃▁▁▁\n\n\npregnant\n0\n1.00\n3.85\n3.37\n0.00\n1.00\n3.00\n6.00\n17.00\n▇▃▂▁▁\n\n\ntriceps\n227\n0.70\n29.15\n10.48\n7.00\n22.00\n29.00\n36.00\n99.00\n▆▇▁▁▁\n\n\n\n\n\nWe choose the xgboost algorithm from the xgboost package as learner.\n\nlearner = lrn(\"classif.xgboost\", nrounds = 100, id = \"xgboost\", verbose = 0)\n\n\n\nMissing Values\nThe task has missing data in five columns.\n\nround(task$missings() / task$nrow, 2)\n\ndiabetes age glucose insulin mass pedigree pregnant pressure triceps \n 0.00 0.00 0.01 0.49 0.01 0.00 0.00 0.05 0.30 \n\n\nThe xgboost learner has an internal method for handling missing data but some learners cannot handle missing values. We will try to beat the internal method in terms of predictive performance. The mlr3pipelines package offers various methods to impute missing values.\n\nmlr_pipeops$keys(\"^impute\")\n\n[1] \"imputeconstant\" \"imputehist\" \"imputelearner\" \"imputemean\" \"imputemedian\" \"imputemode\" \n[7] \"imputeoor\" \"imputesample\" \n\n\nWe choose the PipeOpImputeOOR that adds the new factor level \".MISSING\". to factorial features and imputes numerical features by constant values shifted below the minimum (default) or above the maximum.\n\nimputer = po(\"imputeoor\")\nprint(imputer)\n\nPipeOp: <imputeoor> (not trained)\nvalues: <min=TRUE, offset=1, multiplier=1>\nInput channels <name [train type, predict type]>:\n input [Task,Task]\nOutput channels <name [train type, predict type]>:\n output [Task,Task]\n\n\nAs the output suggests, the in- and output of this pipe operator is a Task for both the training and the predict step. We can manually train the pipe operator to check its functionality:\n\ntask_imputed = imputer$train(list(task))[[1]]\ntask_imputed$missings()\n\ndiabetes age pedigree pregnant glucose insulin mass pressure triceps \n 0 0 0 0 0 0 0 0 0 \n\n\nLet’s compare an observation with missing values to the observation with imputed observation.\n\nrbind(\n task$data()[8,],\n task_imputed$data()[8,]\n)\n\n diabetes age glucose insulin mass pedigree pregnant pressure triceps\n1: neg 29 115 NA 35.3 0.134 10 <NA> NA\n2: neg 29 115 -819 35.3 0.134 10 .MISSING -86\n\n\nNote that OOR imputation is in particular useful for tree-based models, but should not be used for linear models or distance-based models.\n\n\nFactor Encoding\nThe xgboost learner cannot handle categorical features. Therefore, we must to convert factor columns to numerical dummy columns. For this, we argument the xgboost learner with automatic factor encoding.\nThe PipeOpEncode encodes factor columns with one of six methods. In this example, we use one-hot encoding which creates a new binary column for each factor level.\n\nfactor_encoding = po(\"encode\", method = \"one-hot\")\n\nWe manually trigger the encoding on the task.\n\nfactor_encoding$train(list(task))\n\n$output\n<TaskClassif:pima> (768 x 11): Pima Indian Diabetes\n* Target: diabetes\n* Properties: twoclass\n* Features (10):\n - dbl (10): age, glucose, insulin, mass, pedigree, pregnant, pressure.high, pressure.low, pressure.mid,\n triceps\n\n\nThe factor column pressure has been converted to the three binary columns \"pressure.low\", \"pressure.mid\", and \"pressure.high\".\n\n\nConstructing the Pipeline\nWe created two preprocessing steps which could be used to create a new task with encoded factor variables and imputed missing values. However, if we do this before resampling, information from the test can leak into our training step which typically leads to overoptimistic performance measures. To avoid this, we add the preprocessing steps to the Learner itself, creating a GraphLearner. For this, we create a Graph first.\n\ngraph = po(\"encode\") %>>%\n po(\"imputeoor\") %>>%\n learner\nplot(graph, html = FALSE)\n\n\n\n\n\n\n\n\nWe use as_learner() to wrap the Graph into a GraphLearner with which allows us to use the graph like a normal learner.\n\ngraph_learner = as_learner(graph)\n\n# short learner id for printing\ngraph_learner$id = \"graph_learner\"\n\nThe GraphLearner can be trained and used for making predictions. Instead of calling $train() or $predict() manually, we will directly use it for resampling. We choose a 3-fold cross-validation as the resampling strategy.\n\nresampling = rsmp(\"cv\", folds = 3)\n\nrr = resample(task = task, learner = graph_learner, resampling = resampling)\n\n\nrr$score()[, c(\"iteration\", \"task_id\", \"learner_id\", \"resampling_id\", \"classif.ce\"), with = FALSE]\n\n iteration task_id learner_id resampling_id classif.ce\n1: 1 pima graph_learner cv 0.2851562\n2: 2 pima graph_learner cv 0.2460938\n3: 3 pima graph_learner cv 0.2968750\n\n\nFor each resampling iteration, the following steps are performed:\n\nThe task is subsetted to the training indices.\nThe factor encoder replaces factor features with dummy columns in the training task.\nThe OOR imputer determines values to impute from the training task and then replaces all missing values with learned imputation values.\nThe learner is applied on the modified training task and the model is stored inside the learner.\n\nNext is the predict step:\n\nThe task is subsetted to the test indices.\nThe factor encoder replaces all factor features with dummy columns in the test task.\nThe OOR imputer replaces all missing values of the test task with the imputation values learned on the training set.\nThe learner’s predict method is applied on the modified test task.\n\nBy following this procedure, it is guaranteed that no information can leak from the training step to the predict step.\n\n\nTuning the Pipeline\nLet’s have a look at the parameter set of the GraphLearner. It consists of the xgboost hyperparameters, and additionally, the parameter of the PipeOp encode and imputeoor. All hyperparameters are prefixed with the id of the respective PipeOp or learner.\n\nas.data.table(graph_learner$param_set)[, c(\"id\", \"class\", \"lower\", \"upper\", \"nlevels\"), with = FALSE]\n\n id class lower upper nlevels\n 1: encode.method ParamFct NA NA 5\n 2: encode.affect_columns ParamUty NA NA Inf\n 3: imputeoor.min ParamLgl NA NA 2\n 4: imputeoor.offset ParamDbl 0 Inf Inf\n 5: imputeoor.multiplier ParamDbl 0 Inf Inf\n 6: imputeoor.affect_columns ParamUty NA NA Inf\n 7: xgboost.alpha ParamDbl 0 Inf Inf\n 8: xgboost.approxcontrib ParamLgl NA NA 2\n 9: xgboost.base_score ParamDbl -Inf Inf Inf\n10: xgboost.booster ParamFct NA NA 3\n11: xgboost.callbacks ParamUty NA NA Inf\n12: xgboost.colsample_bylevel ParamDbl 0 1 Inf\n13: xgboost.colsample_bynode ParamDbl 0 1 Inf\n14: xgboost.colsample_bytree ParamDbl 0 1 Inf\n15: xgboost.disable_default_eval_metric ParamLgl NA NA 2\n16: xgboost.early_stopping_rounds ParamInt 1 Inf Inf\n17: xgboost.early_stopping_set ParamFct NA NA 3\n18: xgboost.eta ParamDbl 0 1 Inf\n19: xgboost.eval_metric ParamUty NA NA Inf\n20: xgboost.feature_selector ParamFct NA NA 5\n21: xgboost.feval ParamUty NA NA Inf\n22: xgboost.gamma ParamDbl 0 Inf Inf\n23: xgboost.grow_policy ParamFct NA NA 2\n24: xgboost.interaction_constraints ParamUty NA NA Inf\n25: xgboost.iterationrange ParamUty NA NA Inf\n26: xgboost.lambda ParamDbl 0 Inf Inf\n27: xgboost.lambda_bias ParamDbl 0 Inf Inf\n28: xgboost.max_bin ParamInt 2 Inf Inf\n29: xgboost.max_delta_step ParamDbl 0 Inf Inf\n30: xgboost.max_depth ParamInt 0 Inf Inf\n31: xgboost.max_leaves ParamInt 0 Inf Inf\n32: xgboost.maximize ParamLgl NA NA 2\n33: xgboost.min_child_weight ParamDbl 0 Inf Inf\n34: xgboost.missing ParamDbl -Inf Inf Inf\n35: xgboost.monotone_constraints ParamUty NA NA Inf\n36: xgboost.normalize_type ParamFct NA NA 2\n37: xgboost.nrounds ParamInt 1 Inf Inf\n38: xgboost.nthread ParamInt 1 Inf Inf\n39: xgboost.ntreelimit ParamInt 1 Inf Inf\n40: xgboost.num_parallel_tree ParamInt 1 Inf Inf\n41: xgboost.objective ParamUty NA NA Inf\n42: xgboost.one_drop ParamLgl NA NA 2\n43: xgboost.outputmargin ParamLgl NA NA 2\n44: xgboost.predcontrib ParamLgl NA NA 2\n45: xgboost.predictor ParamFct NA NA 2\n46: xgboost.predinteraction ParamLgl NA NA 2\n47: xgboost.predleaf ParamLgl NA NA 2\n48: xgboost.print_every_n ParamInt 1 Inf Inf\n49: xgboost.process_type ParamFct NA NA 2\n50: xgboost.rate_drop ParamDbl 0 1 Inf\n51: xgboost.refresh_leaf ParamLgl NA NA 2\n52: xgboost.reshape ParamLgl NA NA 2\n53: xgboost.seed_per_iteration ParamLgl NA NA 2\n54: xgboost.sampling_method ParamFct NA NA 2\n55: xgboost.sample_type ParamFct NA NA 2\n56: xgboost.save_name ParamUty NA NA Inf\n57: xgboost.save_period ParamInt 0 Inf Inf\n58: xgboost.scale_pos_weight ParamDbl -Inf Inf Inf\n59: xgboost.skip_drop ParamDbl 0 1 Inf\n60: xgboost.strict_shape ParamLgl NA NA 2\n61: xgboost.subsample ParamDbl 0 1 Inf\n62: xgboost.top_k ParamInt 0 Inf Inf\n63: xgboost.training ParamLgl NA NA 2\n64: xgboost.tree_method ParamFct NA NA 5\n65: xgboost.tweedie_variance_power ParamDbl 1 2 Inf\n66: xgboost.updater ParamUty NA NA Inf\n67: xgboost.verbose ParamInt 0 2 3\n68: xgboost.watchlist ParamUty NA NA Inf\n69: xgboost.xgb_model ParamUty NA NA Inf\n id class lower upper nlevels\n\n\nWe will tune the encode method.\n\ngraph_learner$param_set$values$encode.method = to_tune(c(\"one-hot\", \"treatment\"))\n\nWe define a tuning instance and use grid search since we want to try all encode methods.\n\ninstance = tune(\n tuner = tnr(\"grid_search\"),\n task = task,\n learner = graph_learner,\n resampling = rsmp(\"cv\", folds = 3),\n measure = msr(\"classif.ce\")\n)\n\nThe archive shows us the performance of the model with different encoding methods.\n\nprint(instance$archive)\n\n<ArchiveTuning> with 2 evaluations\n encode.method classif.ce batch_nr warnings errors\n1: treatment 0.26 1 0 0\n2: one-hot 0.26 2 0 0\n\n\n\n\nNested Resampling\nWe create one GraphLearner with imputeoor and test it against a GraphLearner that uses the internal imputation method of xgboost. Applying nested resampling ensures a fair comparison of the predictive performances.\n\ngraph_1 = po(\"encode\") %>>%\n learner\ngraph_learner_1 = GraphLearner$new(graph_1)\n\ngraph_learner_1$param_set$values$encode.method = to_tune(c(\"one-hot\", \"treatment\"))\n\nat_1 = AutoTuner$new(\n learner = graph_learner_1,\n resampling = resampling,\n measure = msr(\"classif.ce\"),\n terminator = trm(\"none\"),\n tuner = tnr(\"grid_search\"),\n store_models = TRUE\n)\n\n\ngraph_2 = po(\"encode\") %>>%\n po(\"imputeoor\") %>>%\n learner\ngraph_learner_2 = GraphLearner$new(graph_2)\n\ngraph_learner_2$param_set$values$encode.method = to_tune(c(\"one-hot\", \"treatment\"))\n\nat_2 = AutoTuner$new(\n learner = graph_learner_2,\n resampling = resampling,\n measure = msr(\"classif.ce\"),\n terminator = trm(\"none\"),\n tuner = tnr(\"grid_search\"),\n store_models = TRUE\n)\n\nWe run the benchmark.\n\nresampling_outer = rsmp(\"cv\", folds = 3)\ndesign = benchmark_grid(task, list(at_1, at_2), resampling_outer)\n\nbmr = benchmark(design, store_models = TRUE)\n\nWe compare the aggregated performances on the outer test sets which give us an unbiased performance estimate of the GraphLearners with the different encoding methods.\n\nbmr$aggregate()\n\n nr task_id learner_id resampling_id iters classif.ce\n1: 1 pima encode.xgboost.tuned cv 3 0.2578125\n2: 2 pima encode.imputeoor.xgboost.tuned cv 3 0.2630208\nHidden columns: resample_result\n\nautoplot(bmr)\n\n\n\n\n\n\n\n\nNote that in practice, it is required to tune preprocessing hyperparameters jointly with the hyperparameters of the learner. Otherwise, comparing preprocessing steps is not feasible and can lead to wrong conclusions.\nApplying nested resampling can be shortened by using the auto_tuner()-shortcut.\n\ngraph_1 = po(\"encode\") %>>% learner\ngraph_learner_1 = as_learner(graph_1)\ngraph_learner_1$param_set$values$encode.method = to_tune(c(\"one-hot\", \"treatment\"))\n\nat_1 = auto_tuner(\n method = \"grid_search\",\n learner = graph_learner_1,\n resampling = resampling,\n measure = msr(\"classif.ce\"),\n store_models = TRUE)\n\ngraph_2 = po(\"encode\") %>>% po(\"imputeoor\") %>>% learner\ngraph_learner_2 = as_learner(graph_2)\ngraph_learner_2$param_set$values$encode.method = to_tune(c(\"one-hot\", \"treatment\"))\n\nat_2 = auto_tuner(\n method = \"grid_search\",\n learner = graph_learner_2,\n resampling = resampling,\n measure = msr(\"classif.ce\"),\n store_models = TRUE)\n\ndesign = benchmark_grid(task, list(at_1, at_2), rsmp(\"cv\", folds = 3))\n\nbmr = benchmark(design, store_models = TRUE)\n\n\n\nFinal Model\nWe train the chosen GraphLearner with the AutoTuner to get a final model with optimized hyperparameters.\n\nat_2$train(task)\n\nThe trained model can now be used to make predictions on new data at_2$predict(). The pipeline ensures that the preprocessing is always a part of the train and predict step.\n\n\nResources\nThe mlr3book includes chapters on pipelines and hyperparameter tuning. The mlr3cheatsheets contain frequently used commands and workflows of mlr3." + }, + { + "objectID": "gallery/optimization/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index.html", + "href": "gallery/optimization/2021-03-11-practical-tuning-series-build-an-automated-machine-learning-system/index.html", + "title": "Practical Tuning Series - Build an Automated Machine Learning System", + "section": "", + "text": "Scope\nThis is the third part of the practical tuning series. The other parts can be found here:\n\nPart I - Tune a Support Vector Machine\nPart II - Tune a Preprocessing Pipeline\nPart IV - Tuning and Parallel Processing\n\nIn this post, we implement a simple automated machine learning (AutoML) system which includes preprocessing, a switch between multiple learners and hyperparameter tuning. For this, we build a pipeline with the mlr3pipelines extension package. Additionally, we use nested resampling to get an unbiased performance estimate of our AutoML system.\n\n\nPrerequisites\nWe load the mlr3verse package which pulls in the most important packages for this example.\n\nlibrary(mlr3verse)\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented. The lgr package is used for logging in all mlr3 packages. The mlr3 logger prints the logging messages from the base package, whereas the bbotk logger is responsible for logging messages from the optimization packages (e.g. mlr3tuning ).\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\nlgr::get_logger(\"bbotk\")$set_threshold(\"warn\")\n\nIn this example, we use the Pima Indians Diabetes data set which is used to to predict whether or not a patient has diabetes. The patients are characterized by 8 numeric features and some have missing values.\n\ntask = tsk(\"pima\")\n\n\n\nBranching\nWe use three popular machine learning algorithms: k-nearest-neighbors, support vector machines and random forests.\n\nlearners = list(\n lrn(\"classif.kknn\", id = \"kknn\"),\n lrn(\"classif.svm\", id = \"svm\", type = \"C-classification\"),\n lrn(\"classif.ranger\", id = \"ranger\")\n)\n\nThe PipeOpBranch allows us to specify multiple alternatives paths. In this graph, the paths lead to the different learner models. The selection hyperparameter controls which path is executed i.e., which learner is used to fit a model. It is important to use the PipeOpBranch after the branching so that the outputs are merged into one result object. We visualize the graph with branching below.\n\ngraph =\n po(\"branch\", options = c(\"kknn\", \"svm\", \"ranger\")) %>>%\n gunion(lapply(learners, po)) %>>%\n po(\"unbranch\")\ngraph$plot(html = FALSE)\n\n\n\n\n\n\n\n\nAlternatively, we can use the ppl()-shortcut to load a predefined graph from the mlr_graphs dictionary. For this, the learner list must be named.\n\nlearners = list(\n kknn = lrn(\"classif.kknn\", id = \"kknn\"),\n svm = lrn(\"classif.svm\", id = \"svm\", type = \"C-classification\"),\n ranger = lrn(\"classif.ranger\", id = \"ranger\")\n)\n\ngraph = ppl(\"branch\", lapply(learners, po))\n\n\n\nPreprocessing\nThe task has missing data in five columns.\n\nround(task$missings() / task$nrow, 2)\n\ndiabetes age glucose insulin mass pedigree pregnant pressure triceps \n 0.00 0.00 0.01 0.49 0.01 0.00 0.00 0.05 0.30 \n\n\nThe pipeline \"robustify\" function creates a preprocessing pipeline based on our task. The resulting pipeline imputes missing values with PipeOpImputeHist and creates a dummy column (PipeOpMissInd) which indicates the imputed missing values. Internally, this creates two paths and the results are combined with PipeOpFeatureUnion. In contrast to PipeOpBranch, both paths are executed. Additionally, \"robustify\" adds PipeOpEncode to encode factor columns and PipeOpRemoveConstants to remove features with a constant value.\n\ngraph = ppl(\"robustify\", task = task, factors_to_numeric = TRUE) %>>%\n graph\nplot(graph, html = FALSE)\n\n\n\n\n\n\n\n\nWe could also create the preprocessing pipeline manually.\n\ngunion(list(po(\"imputehist\"),\n po(\"missind\", affect_columns = selector_type(c(\"numeric\", \"integer\"))))) %>>%\n po(\"featureunion\") %>>%\n po(\"encode\") %>>%\n po(\"removeconstants\")\n\nGraph with 5 PipeOps:\n ID State sccssors prdcssors\n imputehist <<UNTRAINED>> featureunion \n missind <<UNTRAINED>> featureunion \n featureunion <<UNTRAINED>> encode imputehist,missind\n encode <<UNTRAINED>> removeconstants featureunion\n removeconstants <<UNTRAINED>> encode\n\n\n\n\nGraph Learner\nWe use as_learner() to create a GraphLearner which encapsulates the pipeline and can be used like a learner.\n\ngraph_learner = as_learner(graph)\n\nThe parameter set of the graph learner includes all hyperparameters from all contained learners. The hyperparameter ids are prefixed with the corresponding learner ids. The hyperparameter branch.selection controls which learner is used.\n\nas.data.table(graph_learner$param_set)[, .(id, class, lower, upper, nlevels)]\n\n id class lower upper nlevels\n 1: removeconstants_prerobustify.ratio ParamDbl 0 1 Inf\n 2: removeconstants_prerobustify.rel_tol ParamDbl 0 Inf Inf\n 3: removeconstants_prerobustify.abs_tol ParamDbl 0 Inf Inf\n 4: removeconstants_prerobustify.na_ignore ParamLgl NA NA 2\n 5: removeconstants_prerobustify.affect_columns ParamUty NA NA Inf\n 6: imputehist.affect_columns ParamUty NA NA Inf\n 7: missind.which ParamFct NA NA 2\n 8: missind.type ParamFct NA NA 4\n 9: missind.affect_columns ParamUty NA NA Inf\n10: imputesample.affect_columns ParamUty NA NA Inf\n11: encode.method ParamFct NA NA 5\n12: encode.affect_columns ParamUty NA NA Inf\n13: removeconstants_postrobustify.ratio ParamDbl 0 1 Inf\n14: removeconstants_postrobustify.rel_tol ParamDbl 0 Inf Inf\n15: removeconstants_postrobustify.abs_tol ParamDbl 0 Inf Inf\n16: removeconstants_postrobustify.na_ignore ParamLgl NA NA 2\n17: removeconstants_postrobustify.affect_columns ParamUty NA NA Inf\n18: kknn.k ParamInt 1 Inf Inf\n19: kknn.distance ParamDbl 0 Inf Inf\n20: kknn.kernel ParamFct NA NA 10\n21: kknn.scale ParamLgl NA NA 2\n22: kknn.ykernel ParamUty NA NA Inf\n23: kknn.store_model ParamLgl NA NA 2\n24: svm.cachesize ParamDbl -Inf Inf Inf\n25: svm.class.weights ParamUty NA NA Inf\n26: svm.coef0 ParamDbl -Inf Inf Inf\n27: svm.cost ParamDbl 0 Inf Inf\n28: svm.cross ParamInt 0 Inf Inf\n29: svm.decision.values ParamLgl NA NA 2\n30: svm.degree ParamInt 1 Inf Inf\n31: svm.epsilon ParamDbl 0 Inf Inf\n32: svm.fitted ParamLgl NA NA 2\n33: svm.gamma ParamDbl 0 Inf Inf\n34: svm.kernel ParamFct NA NA 4\n35: svm.nu ParamDbl -Inf Inf Inf\n36: svm.scale ParamUty NA NA Inf\n37: svm.shrinking ParamLgl NA NA 2\n38: svm.tolerance ParamDbl 0 Inf Inf\n39: svm.type ParamFct NA NA 2\n40: ranger.alpha ParamDbl -Inf Inf Inf\n41: ranger.always.split.variables ParamUty NA NA Inf\n42: ranger.class.weights ParamUty NA NA Inf\n43: ranger.holdout ParamLgl NA NA 2\n44: ranger.importance ParamFct NA NA 4\n45: ranger.keep.inbag ParamLgl NA NA 2\n46: ranger.max.depth ParamInt 0 Inf Inf\n47: ranger.min.node.size ParamInt 1 Inf Inf\n48: ranger.min.prop ParamDbl -Inf Inf Inf\n49: ranger.minprop ParamDbl -Inf Inf Inf\n50: ranger.mtry ParamInt 1 Inf Inf\n51: ranger.mtry.ratio ParamDbl 0 1 Inf\n52: ranger.num.random.splits ParamInt 1 Inf Inf\n53: ranger.num.threads ParamInt 1 Inf Inf\n54: ranger.num.trees ParamInt 1 Inf Inf\n55: ranger.oob.error ParamLgl NA NA 2\n56: ranger.regularization.factor ParamUty NA NA Inf\n57: ranger.regularization.usedepth ParamLgl NA NA 2\n58: ranger.replace ParamLgl NA NA 2\n59: ranger.respect.unordered.factors ParamFct NA NA 3\n60: ranger.sample.fraction ParamDbl 0 1 Inf\n61: ranger.save.memory ParamLgl NA NA 2\n62: ranger.scale.permutation.importance ParamLgl NA NA 2\n63: ranger.se.method ParamFct NA NA 2\n64: ranger.seed ParamInt -Inf Inf Inf\n65: ranger.split.select.weights ParamUty NA NA Inf\n66: ranger.splitrule ParamFct NA NA 3\n67: ranger.verbose ParamLgl NA NA 2\n68: ranger.write.forest ParamLgl NA NA 2\n69: branch.selection ParamFct NA NA 3\n id class lower upper nlevels\n\n\n\n\nTune the pipeline\nWe will only tune one hyperparameter for each learner in this example. Additionally, we tune the branching parameter which selects one of the three learners. We have to specify that a hyperparameter is only valid for a certain learner by using depends = branch.selection == <learner_id>.\n\n# branch\ngraph_learner$param_set$values$branch.selection =\n to_tune(c(\"kknn\", \"svm\", \"ranger\"))\n\n# kknn\ngraph_learner$param_set$values$kknn.k =\n to_tune(p_int(3, 50, logscale = TRUE, depends = branch.selection == \"kknn\"))\n\n# svm\ngraph_learner$param_set$values$svm.cost =\n to_tune(p_dbl(-1, 1, trafo = function(x) 10^x, depends = branch.selection == \"svm\"))\n\n# ranger\ngraph_learner$param_set$values$ranger.mtry =\n to_tune(p_int(1, 8, depends = branch.selection == \"ranger\"))\n\n# short learner id for printing\ngraph_learner$id = \"graph_learner\"\n\nWe define a tuning instance and select a random search which is stopped after 20 evaluated configurations.\n\ninstance = tune(\n tuner = tnr(\"random_search\"),\n task = task,\n learner = graph_learner,\n resampling = rsmp(\"cv\", folds = 3),\n measure = msr(\"classif.ce\"),\n term_evals = 20\n)\n\nThe following shows a quick way to visualize the tuning results.\n\nautoplot(instance, type = \"marginal\",\n cols_x = c(\"x_domain_kknn.k\", \"x_domain_svm.cost\", \"ranger.mtry\"))\n\n\n\n\n\n\n\n\n\n\nFinal Model\nWe add the optimized hyperparameters to the graph learner and train the learner on the full dataset.\n\nlearner = as_learner(graph)\nlearner$param_set$values = instance$result_learner_param_vals\nlearner$train(task)\n\nThe trained model can now be used to make predictions on new data. A common mistake is to report the performance estimated on the resampling sets on which the tuning was performed (instance$result_y) as the model’s performance. Instead we have to use nested resampling to get an unbiased performance estimate.\n\n\nNested Resampling\nWe use nested resampling to get an unbiased estimate of the predictive performance of our graph learner.\n\ngraph_learner = as_learner(graph)\ngraph_learner$param_set$values$branch.selection =\n to_tune(c(\"kknn\", \"svm\", \"ranger\"))\ngraph_learner$param_set$values$kknn.k =\n to_tune(p_int(3, 50, logscale = TRUE, depends = branch.selection == \"kknn\"))\ngraph_learner$param_set$values$svm.cost =\n to_tune(p_dbl(-1, 1, trafo = function(x) 10^x, depends = branch.selection == \"svm\"))\ngraph_learner$param_set$values$ranger.mtry =\n to_tune(p_int(1, 8, depends = branch.selection == \"ranger\"))\ngraph_learner$id = \"graph_learner\"\n\ninner_resampling = rsmp(\"cv\", folds = 3)\nat = AutoTuner$new(\n learner = graph_learner,\n resampling = inner_resampling,\n measure = msr(\"classif.ce\"),\n terminator = trm(\"evals\", n_evals = 10),\n tuner = tnr(\"random_search\")\n)\n\nouter_resampling = rsmp(\"cv\", folds = 3)\nrr = resample(task, at, outer_resampling, store_models = TRUE)\n\nWe check the inner tuning results for stable hyperparameters. This means that the selected hyperparameters should not vary too much. We might observe unstable models in this example because the small data set and the low number of resampling iterations might introduce too much randomness. Usually, we aim for the selection of stable hyperparameters for all outer training sets.\n\nextract_inner_tuning_results(rr)\n\n\n\n\n\n\n\nNext, we want to compare the predictive performances estimated on the outer resampling to the inner resampling. Significantly lower predictive performances on the outer resampling indicate that the models with the optimized hyperparameters overfit the data.\n\nrr$score()[, .(iteration, task_id, learner_id, resampling_id, classif.ce)]\n\n iteration task_id learner_id resampling_id classif.ce\n1: 1 pima graph_learner.tuned cv 0.2265625\n2: 2 pima graph_learner.tuned cv 0.2382812\n3: 3 pima graph_learner.tuned cv 0.2656250\n\n\nThe aggregated performance of all outer resampling iterations is essentially the unbiased performance of the graph learner with optimal hyperparameter found by random search.\n\nrr$aggregate()\n\nclassif.ce \n 0.2434896 \n\n\nApplying nested resampling can be shortened by using the tune_nested()-shortcut.\n\ngraph_learner = as_learner(graph)\ngraph_learner$param_set$values$branch.selection =\n to_tune(c(\"kknn\", \"svm\", \"ranger\"))\ngraph_learner$param_set$values$kknn.k =\n to_tune(p_int(3, 50, logscale = TRUE, depends = branch.selection == \"kknn\"))\ngraph_learner$param_set$values$svm.cost =\n to_tune(p_dbl(-1, 1, trafo = function(x) 10^x, depends = branch.selection == \"svm\"))\ngraph_learner$param_set$values$ranger.mtry =\n to_tune(p_int(1, 8, depends = branch.selection == \"ranger\"))\ngraph_learner$id = \"graph_learner\"\n\nrr = tune_nested(\n tuner = tnr(\"random_search\"),\n task = task,\n learner = graph_learner,\n inner_resampling = rsmp(\"cv\", folds = 3),\n outer_resampling = rsmp(\"cv\", folds = 3),\n measure = msr(\"classif.ce\"),\n term_evals = 10,\n)\n\n\n\nResources\nThe mlr3book includes chapters on pipelines and hyperparameter tuning. The mlr3cheatsheets contain frequently used commands and workflows of mlr3." + }, + { + "objectID": "gallery/optimization/2022-11-04-early-stopping-with-xgboost/index.html", + "href": "gallery/optimization/2022-11-04-early-stopping-with-xgboost/index.html", + "title": "Early Stopping with XGBoost", + "section": "", + "text": "Scope\nIn this post, we use early stopping to reduce overfitting when training an XGBoost model. We start with a short recap on early stopping and overfitting. After that, we use the early stopping mechanism of XGBoost and train a model on the Spam Classification data set. Finally we show how to simultaneously tune hyperparameters and use early stopping. The reader should be familiar with tuning in the mlr3 ecosystem.\n\n\nEarly Stopping\nEarly stopping is a technique used to reduce overfitting when fitting a model in an iterative process. Overfitting occurs when a model fits increasingly to the training data but the performance on unseen data decreases. This means the model’s training error decreases, while its test performance deteriorates. When using early stopping, the performance is monitored on a test set, and the training stops when performance decreases in a specific number of iterations.\n\n\nXGBoost with Early Stopping\nWe initialize the random number generator with a fixed seed for reproducibility. The mlr3verse package provides all functions required for this example.\n\nset.seed(7832)\n\nlibrary(mlr3verse)\n\nWhen training an XGBoost model, we can use early stopping to find the optimal number of boosting rounds. The partition() function splits the observations of the task into two disjoint sets. We use 80% of observations to train the model and the remaining 20% as the test set to monitor the performance.\n\ntask = tsk(\"spam\")\nsplit = partition(task, ratio = 0.8)\ntask$set_row_roles(split$test, \"test\")\n\nThe early_stopping_set parameter controls which set is used to monitor the performance. Additionally, we need to define the range in which the performance must increase with early_stopping_rounds and the maximum number of boosting rounds with nrounds. In this example, the training is stopped when the classification error is not decreasing for 100 rounds or 1000 rounds are reached.\n\nlearner = lrn(\"classif.xgboost\",\n nrounds = 1000,\n early_stopping_rounds = 100,\n early_stopping_set = \"test\",\n eval_metric = \"error\"\n)\n\nWe train the learner with early stopping.\n\nlearner$train(task)\n\nThe $evaluation_log of the model stores the performance scores on the training and test set. Figure 1 shows that the classification error on the training set decreases, whereas the error on the test set increases after 20 rounds.\n\n\nCode\nlibrary(ggplot2)\nlibrary(data.table)\n\ndata = melt(\n learner$model$evaluation_log,\n id.vars = \"iter\",\n variable.name = \"set\",\n value.name = \"error\"\n)\n\nggplot(data, aes(x = iter, y = error, group = set)) +\n geom_line(aes(color = set)) +\n geom_vline(aes(xintercept = learner$model$best_iteration), color = \"grey\") +\n scale_colour_manual(values=c(\"#f8766d\", \"#00b0f6\"), labels = c(\"Train\", \"Test\")) +\n labs(x = \"Rounds\", y = \"Classification Error\", color = \"Set\") +\n theme_minimal()\n\n\n\n\n\nComparison between train and test set classification error.\n\n\n\n\nThe slot $best_iteration contains the optimal number of boosting rounds.\n\nlearner$model$best_iteration\n\n[1] 20\n\n\nNote that, learner$predict() will use the model from the last iteration, not the best one. See the next section on how to fit a model with the optimal number of boosting rounds and hyperparameter configuration.\n\n\nTuning\nIn this section, we want to tune the hyperparameters of an XGBoost model and find the optimal number of boosting rounds in one go. For this, we need the early stopping callback which handles early stopping during the tuning process. The performance of a hyperparameter configuration is evaluated with a resampling strategy while tuning e.g. 3-fold cross-validation. In each resampling iteration, a new XGBoost model is trained and early stopping is used to find the optimal number of boosting rounds. This results in three different optimal numbers of boosting rounds for one hyperparameter configuration when applying 3-fold cross-validation. The callback picks the maximum of the three values and writes it to the archive. It uses the maximum value because the final model is fitted on the complete data set. Now let’s start with a practical example.\nFirst, we load the XGBoost learner and set the early stopping parameters.\n\nlearner = lrn(\"classif.xgboost\",\n nrounds = 1000,\n early_stopping_rounds = 100,\n early_stopping_set = \"test\"\n)\n\nNext, we load a predefined tuning space from the mlr3tuningspaces package. The tuning space includes the most commonly tuned parameters of XGBoost.\n\ntuning_space = lts(\"classif.xgboost.default\")\nas.data.table(tuning_space)\n\n id lower upper logscale\n1: eta 1e-04 1 TRUE\n2: nrounds 1e+00 5000 FALSE\n3: max_depth 1e+00 20 FALSE\n4: colsample_bytree 1e-01 1 FALSE\n5: colsample_bylevel 1e-01 1 FALSE\n6: lambda 1e-03 1000 TRUE\n7: alpha 1e-03 1000 TRUE\n8: subsample 1e-01 1 FALSE\n\n\nWe argument the learner with the tuning space.\n\nlearner = lts(learner)\n\nThe default tuning space contains the nrounds hyperparameter. We have to overwrite it with an upper bound for early stopping.\n\nlearner$param_set$set_values(nrounds = 1000)\n\nWe run a small batch of random hyperparameter configurations.\n\ninstance = tune(\n tuner = tnr(\"random_search\", batch_size = 2),\n task = task,\n learner = learner,\n resampling = rsmp(\"cv\", folds = 3),\n measure = msr(\"classif.ce\"),\n term_evals = 4,\n callbacks = clbk(\"mlr3tuning.early_stopping\")\n)\n\nWe can see that the optimal number of boosting rounds (max_nrounds) strongly depends on the other hyperparameters.\n\nas.data.table(instance$archive)[, list(batch_nr, max_nrounds, eta, max_depth, colsample_bytree, colsample_bylevel, lambda, alpha, subsample)]\n\n batch_nr max_nrounds eta max_depth colsample_bytree colsample_bylevel lambda alpha subsample\n1: 1 1000 -4.129996 13 0.5466492 0.3051989 -0.9448420 2.535477 0.5454539\n2: 1 998 -3.338899 8 0.6193478 0.7392354 -2.2338126 1.793921 0.2294161\n3: 2 1000 -6.059897 5 0.6118892 0.5445475 -6.5698270 5.414224 0.9635730\n4: 2 1000 -4.528129 1 0.1094186 0.2526143 -0.7535105 -3.041829 0.5934376\n\n\nIn the best hyperparameter configuration, the value of nrounds is replaced by max_nrounds and early stopping is deactivated.\n\ninstance$result_learner_param_vals\n\n$nrounds\n[1] 998\n\n$nthread\n[1] 1\n\n$verbose\n[1] 0\n\n$early_stopping_set\n[1] \"none\"\n\n$eta\n[1] 0.03547598\n\n$max_depth\n[1] 8\n\n$colsample_bytree\n[1] 0.6193478\n\n$colsample_bylevel\n[1] 0.7392354\n\n$lambda\n[1] 0.1071192\n\n$alpha\n[1] 6.012984\n\n$subsample\n[1] 0.2294161\n\n\nFinally, fit the final model on the complete data set.\n\nlearner = lrn(\"classif.xgboost\")\nlearner$param_set$values = instance$result_learner_param_vals\nlearner$train(task)\n\nThe trained model can now be used to make predictions on new data.\nWe can also use the AutoTuner to get a tuned XGBoost model. Note that, early stopping is deactivated when the final model is fitted." + }, + { + "objectID": "gallery/optimization/2023-01-16-hyperband-subsampling/index.html", + "href": "gallery/optimization/2023-01-16-hyperband-subsampling/index.html", + "title": "Hyperband Series - Data Set Subsampling", + "section": "", + "text": "Scope\nWe continue working with the Hyperband optimization algorithm (Li et al. 2018). The previous post used the number of boosting iterations of an XGBoost model as the resource. However, Hyperband is not limited to machine learning algorithms that are trained iteratively. The resource can also be the number of features, the training time of a model, or the size of the training data set. In this post, we will tune a support vector machine and use the size of the training data set as the fidelity parameter. The time to train a support vector machine and the performance increases with the size of the data set. This makes the data set size a suitable fidelity parameter for Hyperband. This is the second part of the Hyperband series. The first part can be found here Hyperband Series - Iterative Training. If you don’t know much about Hyperband, check out the first post which explains the algorithm in detail. We assume that you are already familiar with tuning in the mlr3 ecosystem. If not, you should start with the book chapter on optimization or the Hyperparameter Optimization on the Palmer Penguins Data Set post. A little knowledge about mlr3pipelines is beneficial but not necessary to understand the example.\n\n\nHyperparameter Optimization\nIn this post, we will optimize the hyperparameters of the support vector machine on the Sonar data set. We begin by constructing a classification machine by setting type to \"C-classification\".\n\nlibrary(\"mlr3verse\")\n\nlearner = lrn(\"classif.svm\", id = \"svm\", type = \"C-classification\")\n\nThe mlr3pipelines package features a PipeOp for subsampling.\n\npo(\"subsample\")\n\nPipeOp: <subsample> (not trained)\nvalues: <frac=0.6321, stratify=FALSE, replace=FALSE>\nInput channels <name [train type, predict type]>:\n input [Task,Task]\nOutput channels <name [train type, predict type]>:\n output [Task,Task]\n\n\nThe PipeOp controls the size of the training data set with the frac parameter. We connect the PipeOp with the learner and get a GraphLearner.\n\ngraph_learner = as_learner(\n po(\"subsample\") %>>%\n learner\n)\n\nThe graph learner subsamples and then fits a support vector machine on the data subset. The parameter set of the graph learner is a combination of the parameter sets of the PipeOp and learner.\n\nas.data.table(graph_learner$param_set)[, .(id, lower, upper, levels)]\n\n id lower upper levels\n 1: subsample.frac 0 Inf \n 2: subsample.stratify NA NA TRUE,FALSE\n 3: subsample.replace NA NA TRUE,FALSE\n 4: svm.cachesize -Inf Inf \n 5: svm.class.weights NA NA \n--- \n15: svm.nu -Inf Inf \n16: svm.scale NA NA \n17: svm.shrinking NA NA TRUE,FALSE\n18: svm.tolerance 0 Inf \n19: svm.type NA NA C-classification,nu-classification\n\n\nNext, we create the search space. We use TuneToken to mark which hyperparameters should be tuned. We have to prefix the hyperparameters with the id of the PipeOps. The subsample.frac is the fidelity parameter that must be tagged with \"budget\" in the search space. The data set size is increased from 3.7% to 100%. For the other hyperparameters, we took the search space for support vector machines from the Kuehn et al. (2018) article. This search space works for a wide range of data sets.\n\ngraph_learner$param_set$set_values(\n subsample.frac = to_tune(p_dbl(3^-3, 1, tags = \"budget\")),\n svm.kernel = to_tune(c(\"linear\", \"polynomial\", \"radial\")),\n svm.cost = to_tune(1e-4, 1e3, logscale = TRUE),\n svm.gamma = to_tune(1e-4, 1e3, logscale = TRUE),\n svm.tolerance = to_tune(1e-4, 2, logscale = TRUE),\n svm.degree = to_tune(2, 5)\n)\n\nSupport vector machines often crash or never finish the training with certain hyperparameter configurations. We set a timeout of 30 seconds and a fallback learner to handle these cases.\n\ngraph_learner$encapsulate = c(train = \"evaluate\", predict = \"evaluate\")\ngraph_learner$timeout = c(train = 30, predict = 30)\ngraph_learner$fallback = lrn(\"classif.featureless\")\n\nLet’s create the tuning instance. We use the \"none\" terminator because Hyperband controls the termination itself.\n\ninstance = ti(\n task = tsk(\"sonar\"),\n learner = graph_learner,\n resampling = rsmp(\"cv\", folds = 3),\n measures = msr(\"classif.ce\"),\n terminator = trm(\"none\")\n)\ninstance\n\n<TuningInstanceSingleCrit>\n* State: Not optimized\n* Objective: <ObjectiveTuning:subsample.svm_on_sonar>\n* Search Space:\n id class lower upper nlevels\n1: subsample.frac ParamDbl 0.03703704 1.0000000 Inf\n2: svm.cost ParamDbl -9.21034037 6.9077553 Inf\n3: svm.degree ParamInt 2.00000000 5.0000000 4\n4: svm.gamma ParamDbl -9.21034037 6.9077553 Inf\n5: svm.kernel ParamFct NA NA 3\n6: svm.tolerance ParamDbl -9.21034037 0.6931472 Inf\n* Terminator: <TerminatorNone>\n\n\nWe load the Hyperband tuner and set eta = 3.\n\nlibrary(\"mlr3hyperband\")\n\ntuner = tnr(\"hyperband\", eta = 3)\n\nUsing eta = 3 and a lower bound of 3.7% for the data set size, results in the following schedule. Configurations with the same data set size are evaluated in parallel.\n\n\n\n\n\n\nNow we are ready to start the tuning.\n\ntuner$optimize(instance)\n\nThe best model is a support vector machine with a polynomial kernel.\n\ninstance$result[, .(subsample.frac, svm.cost, svm.degree, svm.gamma, svm.kernel, svm.tolerance, classif.ce)]\n\n subsample.frac svm.cost svm.degree svm.gamma svm.kernel svm.tolerance classif.ce\n1: 1 1.871535 3 -2.60663 polynomial -4.573951 0.1491373\n\n\nThe archive contains all evaluated configurations. We look at the 8 configurations that were evaluated on the complete data set. The configuration with the best classification error on the full data set was sampled in bracket 2. The classification error was estimated to be 26% on 33% of the data set and increased to 19% on the full data set (see green line in Figure 1).\n\n\n\n\n\n\n\n\nFigure 1: Optimization path of the 8 configurations evaluated on the complete data set.\n\n\n\n\n\n\n\nConclusion\nUsing the data set size as the budget parameter in Hyperband allows the tuning of machine learning models that are not trained iteratively. We have tried to keep the runtime of the example low. For your optimization, you should use cross-validation and run multiple iterations of Hyperband.\n\n\n\n\n\n\n\n\nReferences\n\nKuehn, Daniel, Philipp Probst, Janek Thomas, and Bernd Bischl. 2018. “Automatic Exploration of Machine Learning Experiments on OpenML.” https://arxiv.org/abs/1806.10961.\n\n\nLi, Lisha, Kevin Jamieson, Giulia DeSalvo, Afshin Rostamizadeh, and Ameet Talwalkar. 2018. “Hyperband: A Novel Bandit-Based Approach to Hyperparameter Optimization.” Journal of Machine Learning Research 18 (185): 1–52. https://jmlr.org/papers/v18/16-558.html." + }, + { + "objectID": "team/about-raphael.html", + "href": "team/about-raphael.html", + "title": "Raphael Sonabend", + "section": "", + "text": "Postdoc at Imperial College London. I am the main developer of mlr3proba and also the previous maintainer of mlr3extralearners." + }, + { + "objectID": "team/about-sebastian.html", + "href": "team/about-sebastian.html", + "title": "Sebastian Fischer", + "section": "", + "text": "Research Engineer at LMU Munich. Working on mlr3torch, mlr3oml and maintaining mlr3extralearners." + }, + { + "objectID": "team/about-lars.html", + "href": "team/about-lars.html", + "title": "Lars Kotthoff", + "section": "", + "text": "Computer Science Professor at University of Wyoming, contributes small pieces here and there." + }, + { + "objectID": "team/about-patrick.html", + "href": "team/about-patrick.html", + "title": "Patrick Schratz", + "section": "", + "text": "R consultant in Zurich, Switzerland. PhD Candidate in environmental modeling. Mainly contributing to spatiotemporal packages. Maintainer of the old mlr package." + }, + { + "objectID": "team/about-bernd.html", + "href": "team/about-bernd.html", + "title": "Bernd Bischl", + "section": "", + "text": "Professor of Statistical Learning and Data Science at the LMU Munich. I created mlr a long time ago at the beginning of my PhD. Nowadays, I spend most of my time in project supervision, code reviews and helping to design new parts of the framework. I was part of the design process of nearly all parts of the new mlr3, but nearly all code has been written by the other developers." + }, + { + "objectID": "team.html", + "href": "team.html", + "title": "Team", + "section": "", + "text": "Team\n\n\n\n\n\n\n\n\n\nBernd Bischl\n\nProfessor of Statistical Learning and Data Science at the LMU Munich. I created mlr a long time ago at the beginning of my PhD. Nowadays, I spend most of my time in project supervision, code reviews and helping to design new parts of the framework. I was part of the design process of nearly all parts of the new mlr3, but nearly all code has been written by the other developers.\n\n\n\n\n\n\n\n\nMichel Lang\n\nPostdoc at the TU Dortmund and one of the main developers of mlr. I've worked on many internal parts of mlr and started to implement support for survival analysis. Now main developer of mlr3.\n\n\n\n\n\n\n\n\nMarc Becker\n\nResearch engineer at the LMU Munich and main developer of the mlr3 optimization packages.\n\n\n\n\n\n\n\n\nRaphael Sonabend\n\nPostdoc at Imperial College London. I was the main developer of mlr3proba and also the previous maintainer of mlr3extralearners.\n\n\n\n\n\n\n\n\nSebastian Fischer\n\nResearch Engineer at LMU Munich. Is working on mlr3torch, mlr3oml and maintains mlr3extralearners.\n\n\n\n\n\n\n\n\nLars Kotthoff\n\nComputer Science Professor at University of Wyoming, contributes small pieces here and there.\n\n\n\n\n\n\n\n\nFlorian Pfisterer\n\nPhD Student at LMU Munich. I am interested in projects on the intersection of Meta-Learning, AutoML and Algorithmic Fairness. Mainly working on mlr3pipelines and mlr3keras/mlr3torch\n\n\n\n\n\n\n\n\nLennart Schneider\n\nPhD Student at LMU Munich. Interested in black box optimization, HPO and AutoML. Mainly working on mlr3mbo.\n\n\n\n\n\n\n\n\nJohn Zobolas\n\nPostdoc Researcher in Clinical AI at the Institute for Cancer Research in Oslo. I am the main developer and maintainer of mlr3proba." + }, + { + "objectID": "tasks.html", + "href": "tasks.html", + "title": "Tasks", + "section": "", + "text": "The mlr3 packages also ship with some data sets, readily usable as Task objects. The goal of these tasks is to quickly demonstrate the capabilities of the packages.\n\n\n\n\n\n\n\n\nCreate a classification task from the data set in the palmerpenguins package.\n\nlibrary(\"mlr3verse\")\n\n# create a task\ntask = tsk(\"breast_cancer\")\ntask\n\n<TaskClassif:breast_cancer> (683 x 10): Wisconsin Breast Cancer\n* Target: class\n* Properties: twoclass\n* Features (9):\n - ord (9): bare_nuclei, bl_cromatin, cell_shape, cell_size,\n cl_thickness, epith_c_size, marg_adhesion, mitoses, normal_nucleoli\n\n# get the dimensions\nc(task$nrow, task$ncol)\n\n[1] 683 10\n\n# check for missing values\ntask$missings()\n\n class bare_nuclei bl_cromatin cell_shape cell_size \n 0 0 0 0 0 \n cl_thickness epith_c_size marg_adhesion mitoses normal_nucleoli \n 0 0 0 0 0 \n\n# plot class frequencies\nautoplot(task)" + }, + { + "objectID": "tasks.html#example-usage", + "href": "tasks.html#example-usage", + "title": "Tasks", + "section": "", + "text": "Create a classification task from the data set in the palmerpenguins package.\n\nlibrary(\"mlr3verse\")\n\n# create a task\ntask = tsk(\"breast_cancer\")\ntask\n\n<TaskClassif:breast_cancer> (683 x 10): Wisconsin Breast Cancer\n* Target: class\n* Properties: twoclass\n* Features (9):\n - ord (9): bare_nuclei, bl_cromatin, cell_shape, cell_size,\n cl_thickness, epith_c_size, marg_adhesion, mitoses, normal_nucleoli\n\n# get the dimensions\nc(task$nrow, task$ncol)\n\n[1] 683 10\n\n# check for missing values\ntask$missings()\n\n class bare_nuclei bl_cromatin cell_shape cell_size \n 0 0 0 0 0 \n cl_thickness epith_c_size marg_adhesion mitoses normal_nucleoli \n 0 0 0 0 0 \n\n# plot class frequencies\nautoplot(task)" + }, + { + "objectID": "graphs.html", + "href": "graphs.html", + "title": "Graphs", + "section": "", + "text": "Graphs\nGraphs are predefined arrangements of PipeOp objects from the mlr3pipelines package. The goal is to simplify some popular operations which usually consist of multiple steps." + }, + { + "objectID": "ecosystem.html", + "href": "ecosystem.html", + "title": "Ecosystem", + "section": "", + "text": "The mlr3 ecosystem is a collection of R packages for machine learning. The base package mlr3 only provides the basic building blocks for machine learning. The extensions packages extent mlr3 with functionality for additional task types, learning algorithms, tuning algorithms, feature selection strategies, visualizations or preprocessing capabilities. The packages are listed bellow with a short description. For more information about the packages, check out their respective homepages.\nThe dot next to the package name indicates the lifecycle stage.\nIf you use our packages in your research, please cite our articles on mlr3 (Lang et al. 2019), mlr3proba (Sonabend et al. 2021) or mlr3pipelines (Binder et al. 2021). To get the citation information of other packages, call\ncitation(\"[package]\")" + }, + { + "objectID": "ecosystem.html#core", + "href": "ecosystem.html#core", + "title": "Ecosystem", + "section": " Core", + "text": "Core\n\n\n\n\n\nmlr3\n\n\nBasic building blocks for machine learning.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3verse\n\n\nMeta-package intended to simplify both installation and loading of packages from the mlr3 ecosystem.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3pipelines\n\n\nDataflow programming toolkit." + }, + { + "objectID": "ecosystem.html#learners", + "href": "ecosystem.html#learners", + "title": "Ecosystem", + "section": " Learners", + "text": "Learners\n\n\n\n\n\nmlr3learners\n\n\nEssential learners for mlr3, maintained by the mlr-org team.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3extralearners\n\n\nExtra learners for mlr3, implemented by the community.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3torch\n\n\nDeep learning with torch." + }, + { + "objectID": "ecosystem.html#tuning-optimization", + "href": "ecosystem.html#tuning-optimization", + "title": "Ecosystem", + "section": " Tuning & Optimization", + "text": "Tuning & Optimization\n\n\n\n\n\nmlr3tuning\n\n\nHyperparameter tuning for mlr3 learners.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3tuningspaces\n\n\nCollection of search spaces for hyperparameter tuning.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3hyperband\n\n\nSuccessive halving and hyperband tuner for mlr3tuning.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3mbo\n\n\nModel-based optimization for mlr3tuning.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmiesmuschel\n\n\nFlexible mixed integer evolutionary strategies.\n\n\n\n\n\n\n\n\n\n\n\nbbotk\n\n\nBlack-box optimization toolkit.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3automl\n\n\nAutomated machine learning." + }, + { + "objectID": "ecosystem.html#tasks-and-datatypes", + "href": "ecosystem.html#tasks-and-datatypes", + "title": "Ecosystem", + "section": " Tasks and Datatypes", + "text": "Tasks and Datatypes\n\n\n\n\n\nmlr3spatiotempcv\n\n\nSpatiotemporal resampling and visualization methods.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3cluster\n\n\nCluster analysis.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3proba\n\n\nProbabilistic predictions.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3spatial\n\n\nSpatial data backends and prediction functions.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3fda\n\n\nFunctional Data Analysis.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3fairness\n\n\nFairness in Machine Learning.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3temporal\n\n\nTime series analysis." + }, + { + "objectID": "ecosystem.html#feature-selection", + "href": "ecosystem.html#feature-selection", + "title": "Ecosystem", + "section": " Feature Selection", + "text": "Feature Selection\n\n\n\n\n\nmlr3filters\n\n\nFilter Feature Selection.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3fselect\n\n\nWrapper Feature Selection." + }, + { + "objectID": "ecosystem.html#data", + "href": "ecosystem.html#data", + "title": "Ecosystem", + "section": " Data", + "text": "Data\n\n\n\n\n\nmlr3db\n\n\nData backend to transparently work with databases.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3oml\n\n\nConnector to OpenML.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3data\n\n\nData sets and tasks." + }, + { + "objectID": "ecosystem.html#analysis", + "href": "ecosystem.html#analysis", + "title": "Ecosystem", + "section": " Analysis", + "text": "Analysis\n\n\n\n\n\nmlr3viz\n\n\nVisualizations for tasks, predictions, resample results and benchmarks.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3benchmark\n\n\nAnalysis and tools for benchmarking.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3inferr\n\n\nStatistical methods for inference on the generalization error.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3summary\n\n\nSummary methods for mlr3." + }, + { + "objectID": "ecosystem.html#other", + "href": "ecosystem.html#other", + "title": "Ecosystem", + "section": " Other", + "text": "Other\n\n\n\n\n\nparadox\n\n\nUniversal parameter space description and tools.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3misc\n\n\nMiscellaneous helper functions for mlr3.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmlr3measures\n\n\nPerformance measures for supervised learning." + }, + { + "objectID": "ecosystem.html#parallelization", + "href": "ecosystem.html#parallelization", + "title": "Ecosystem", + "section": " Parallelization", + "text": "Parallelization\n\n\n\n\n\nmlr3batchmark\n\n\nConnector between mlr3 and batchtools.\n\n\n\n\n\n\n\n\n\n\n\nrush\n\n\nAsynchronous parallelization." + }, + { + "objectID": "tuning_spaces.html", + "href": "tuning_spaces.html", + "title": "Tuning Spaces", + "section": "", + "text": "The package mlr3tuningspaces ships with some predefined tuning spaces for hyperparameter optimization. See the respective manual page for the article from which they were extracted.\n\n\n\n\n\n\n\n\nLoad a tuning space for the classification tree learner from the Bischl et al. (2021) article.\n\nlibrary(mlr3verse)\n\n# load learner and set search space\nlearner = lts(lrn(\"classif.rpart\"))\n\n# retrieve task\ntask = tsk(\"pima\")\n\n# load tuner and set batch size\ntuner = tnr(\"random_search\", batch_size = 10)\n\n# hyperparameter tuning on the pima data set\ninstance = tune(\n tuner = tnr(\"grid_search\", resolution = 5, batch_size = 25),\n task = task,\n learner = learner,\n resampling = rsmp(\"holdout\"),\n measure = msr(\"classif.ce\"),\n)\n\n# best performing hyperparameter configuration\ninstance$result\n\n cp minbucket minsplit learner_param_vals x_domain classif.ce\n <num> <num> <num> <list> <list> <num>\n1: -9.21034 0 4.859812 <list[4]> <list[3]> 0.2109375\n\n# fit final model on complete data set\nlearner$param_set$values = instance$result_learner_param_vals\nlearner$train(task)\n\nprint(learner)\n\n<LearnerClassifRpart:classif.rpart>: Classification Tree\n* Model: rpart\n* Parameters: cp=0.0001, minbucket=1, minsplit=128, xval=0\n* Packages: mlr3, rpart\n* Predict Types: [response], prob\n* Feature Types: logical, integer, numeric, factor, ordered\n* Properties: importance, missings, multiclass, selected_features,\n twoclass, weights" + }, + { + "objectID": "tuning_spaces.html#example-usage", + "href": "tuning_spaces.html#example-usage", + "title": "Tuning Spaces", + "section": "", + "text": "Load a tuning space for the classification tree learner from the Bischl et al. (2021) article.\n\nlibrary(mlr3verse)\n\n# load learner and set search space\nlearner = lts(lrn(\"classif.rpart\"))\n\n# retrieve task\ntask = tsk(\"pima\")\n\n# load tuner and set batch size\ntuner = tnr(\"random_search\", batch_size = 10)\n\n# hyperparameter tuning on the pima data set\ninstance = tune(\n tuner = tnr(\"grid_search\", resolution = 5, batch_size = 25),\n task = task,\n learner = learner,\n resampling = rsmp(\"holdout\"),\n measure = msr(\"classif.ce\"),\n)\n\n# best performing hyperparameter configuration\ninstance$result\n\n cp minbucket minsplit learner_param_vals x_domain classif.ce\n <num> <num> <num> <list> <list> <num>\n1: -9.21034 0 4.859812 <list[4]> <list[3]> 0.2109375\n\n# fit final model on complete data set\nlearner$param_set$values = instance$result_learner_param_vals\nlearner$train(task)\n\nprint(learner)\n\n<LearnerClassifRpart:classif.rpart>: Classification Tree\n* Model: rpart\n* Parameters: cp=0.0001, minbucket=1, minsplit=128, xval=0\n* Packages: mlr3, rpart\n* Predict Types: [response], prob\n* Feature Types: logical, integer, numeric, factor, ordered\n* Properties: importance, missings, multiclass, selected_features,\n twoclass, weights" + }, + { + "objectID": "terminators.html", + "href": "terminators.html", + "title": "Terminators", + "section": "", + "text": "Stop tuning when a performance level is reached.\n\nlibrary(mlr3verse)\n\n# load terminator and set performance level\nterminator = trm(\"perf_reached\", level = 0.25)\n\n# load tuner\ntuner = tnr(\"random_search\", batch_size = 10)\n\n# retrieve task\ntask = tsk(\"pima\")\n\n# load learner and set search space\nlearner = lts(lrn(\"classif.rpart\"))\n\n# set instance\ninstance = TuningInstanceSingleCrit$new(\n task = task,\n learner = learner,\n resampling = rsmp(\"holdout\"),\n measure = msr(\"classif.ce\"),\n terminator = terminator\n)\n\n# hyperparameter tuning on the pima data set\ntuner$optimize(instance)\n\n# best performing hyperparameter configuration\ninstance$result\n\n# fit final model on complete data set\nlearner$param_set$values = instance$result_learner_param_vals\nlearner$train(task)\n\nprint(learner)" + }, + { + "objectID": "terminators.html#example-usage", + "href": "terminators.html#example-usage", + "title": "Terminators", + "section": "", + "text": "Stop tuning when a performance level is reached.\n\nlibrary(mlr3verse)\n\n# load terminator and set performance level\nterminator = trm(\"perf_reached\", level = 0.25)\n\n# load tuner\ntuner = tnr(\"random_search\", batch_size = 10)\n\n# retrieve task\ntask = tsk(\"pima\")\n\n# load learner and set search space\nlearner = lts(lrn(\"classif.rpart\"))\n\n# set instance\ninstance = TuningInstanceSingleCrit$new(\n task = task,\n learner = learner,\n resampling = rsmp(\"holdout\"),\n measure = msr(\"classif.ce\"),\n terminator = terminator\n)\n\n# hyperparameter tuning on the pima data set\ntuner$optimize(instance)\n\n# best performing hyperparameter configuration\ninstance$result\n\n# fit final model on complete data set\nlearner$param_set$values = instance$result_learner_param_vals\nlearner$train(task)\n\nprint(learner)" + }, + { + "objectID": "faq.html", + "href": "faq.html", + "title": "Frequently Asked Questions", + "section": "", + "text": "Why is there only the rpart learner?\nHow can I use parallelization?\nWhy is the parallelization with the future package slow?\nWhy is the parallelization of tuning slow?\nWhy are the CPUs on my system not fully utilized when using parallelization?\nHow can I use time constraints when tuning?\nWhy is method X slower when used via mlr3?\nPreprocessing factor levels\nMemory Problems\nHow can I suppress logging output of learners on the R console\nA learner trained with an old mlr3 version does not work anymore\nCaching of knitr/rmarkdown chunks does not work with mlr3\nHow to keep all mlr3 packages up-to-date?" + }, + { + "objectID": "faq.html#learner", + "href": "faq.html#learner", + "title": "Frequently Asked Questions", + "section": "Why is there only the rpart learner?", + "text": "Why is there only the rpart learner?\nThe base package mlr3 ships only with regression and classification trees from the rpart package and some learners for debugging. A selection of popular learners can be found in the extension package mlr3learners. Survival learners are provided by mlr3proba, cluster learners via mlr3cluster. Additional learners can be found in the extension packages mlr3extralearners. If your favorite learner is missing, please open a learner request. An overview of all learners can be found on our website." + }, + { + "objectID": "faq.html#parallelization", + "href": "faq.html#parallelization", + "title": "Frequently Asked Questions", + "section": "How can I use parallelization?", + "text": "How can I use parallelization?\nParallelization is supported when training learners, resampling, tuning and predicting. We recommend reading the section about Parallelization in the mlr3book." + }, + { + "objectID": "faq.html#parallelization-slow", + "href": "faq.html#parallelization-slow", + "title": "Frequently Asked Questions", + "section": "Why is the parallelization with the future package slow?", + "text": "Why is the parallelization with the future package slow?\nStarting and terminating workers as well as possible communication between workers comes at a price in the form of additionally required runtime which is called parallelization overhead. This overhead strongly varies between parallelization backends and must be carefully weighed against the runtime of the sequential execution to determine if parallelization is worth the effort. When resampling or tuning a fast-fitting learner, it helps to chunk multiple resampling iterations into a single computational job. The option mlr3.exec_chunk_bins determines the number of chunks to split the resampling iterations into. For example, when running a benchmark with 100 resampling iterations, options(\"mlr3.exec_chunk_bins\" = 4) creates 4 computational jobs with 25 resampling iterations each. This reduces the parallelization overhead and speeds up the execution." + }, + { + "objectID": "faq.html#tuning-slow", + "href": "faq.html#tuning-slow", + "title": "Frequently Asked Questions", + "section": "Why is the parallelization of tuning slow?", + "text": "Why is the parallelization of tuning slow?\nTuning can also suffer from the parallelization overhead described above. Additionally, the batch size of the tuner can have a large impact on the runtime. Setting an optimal batch size is explained in the section Parallelization of Tuning of the mlr3book." + }, + { + "objectID": "faq.html#parallelization-cpu", + "href": "faq.html#parallelization-cpu", + "title": "Frequently Asked Questions", + "section": "Why are the CPUs on my system not fully utilized when using parallelization?", + "text": "Why are the CPUs on my system not fully utilized when using parallelization?\nIf there are few jobs with dissimilar runtimes, the system may end up waiting for the last chunk to finish, while other resources are idle. This is referred to as synchronization overhead. When minimizing the synchronization overhead, a too large chunk size can lead to a situation where the last chunk takes much longer than the others. This can be avoided by setting mlr3.exec_chunk_bins to a smaller value than the number of cores available on the system." + }, + { + "objectID": "faq.html#how-can-i-use-time-constraints-when-tuning", + "href": "faq.html#how-can-i-use-time-constraints-when-tuning", + "title": "Frequently Asked Questions", + "section": "How can I use time constraints when tuning?", + "text": "How can I use time constraints when tuning?\nTime constraints can be set for individual learners, tuning processes, and nested resampling. The gallery post Time constraints in the mlr3 ecosystem provides an overview of the different options." + }, + { + "objectID": "faq.html#mlr3-default-slower", + "href": "faq.html#mlr3-default-slower", + "title": "Frequently Asked Questions", + "section": "Why is method X slower when used via mlr3?", + "text": "Why is method X slower when used via mlr3?\nBy default, we set the number of threads of learners to 1 to avoid conflicts with parallelization. Therefore, the default configuration of a learner may be significantly slower than the default configuration of the method when used directly." + }, + { + "objectID": "faq.html#factor-levels", + "href": "faq.html#factor-levels", + "title": "Frequently Asked Questions", + "section": "Preprocessing factor levels", + "text": "Preprocessing factor levels\nWhen working with mlr3, it is important to avoid using special characters in the levels of factor variables. The presence of symbols such as +, -, <, >, =, or spaces in the factor levels can cause errors during model training (depends on the learner used and if the formula interface is utilized, e.g. as in the surv.parametric learner). While underscores (_) and dots (.) are generally safe to use, other special characters should be avoided. To ensure smooth operation and prevent errors, please follow these guidelines:\n\nUse descriptive labels with no special characters: Assign meaningful and descriptive labels to factor levels that do not include special characters. For example, instead of 60+ for a factor level of an age feature, use 60_above.\nUse factor encoding: Incorporate a pre-processing step in your data pipeline (e.g. see mlr_pipeops_encode to make sure factors are one-hot encoded, alleviating problems that may arise from factor levels that incorporate strange symbols." + }, + { + "objectID": "faq.html#memory-problems", + "href": "faq.html#memory-problems", + "title": "Frequently Asked Questions", + "section": "Memory Problems", + "text": "Memory Problems\nOne explanation for why mlr3 might in some cases use an unusual amount of memory, is when packages are installed with the --with-keep.source flag. This configuration option is enabled by default when managing dependencies via renv, see issue #1713. To opt out of this default run the code below, e.g. by adding it to your .Rprofile:\n\noptions(\"install.opts\" = \"--without-keep.source\")" + }, + { + "objectID": "faq.html#suppress-output", + "href": "faq.html#suppress-output", + "title": "Frequently Asked Questions", + "section": "How can I suppress logging output of learners on the R console", + "text": "How can I suppress logging output of learners on the R console\nSome learners are quite verbose during their train or predict step, and this clutters the R console. Note that this is different than controlling the generic mlr3 logger, which is covered under Logging. Most of these learners provide some option in their paramset to control output behavior. Another option is to simply use Encapsulation, likely in the evaluate mode, running the learner in the same R session, but with caught exceptions and redirected output.\n\nlibrary(mlr3)\nlibrary(mlr3learners)\nmytask = tsk(\"iris\")\n# manual option\nmylearner = lrn(\"classif.nnet\", trace = TRUE)\n# generic option\nmylearner$encapsulate = c(train = \"evaluate\", predict = \"evaluate\")\nmylearner$train(mytask)" + }, + { + "objectID": "faq.html#old-model-broken", + "href": "faq.html#old-model-broken", + "title": "Frequently Asked Questions", + "section": "A learner trained with an old mlr3 version does not work anymore", + "text": "A learner trained with an old mlr3 version does not work anymore\nIt is possible that a saved Learner that was trained with an old mlr3 version does not work with a different version of mlr3. In general, we recommend saving the computational environment using a tool like renv so this can later be restored and avoiding such situations alltogether. If this is not an option, a possible workaround is to construct the same learner in the currently used mlr3 version and manually set its $state to the one of the saved learner. This is illustrated below:\n\nUsing an old mlr3 version:\n\nlearner = lrn(\"classif.rpart\")\nlearner$train(tsk(\"iris\"))\nsaveRDS(learner, \"learner.rds\")\n\nWith a subsequent mlr3 version:\n\nlearner = lrn(\"classif.rpart\")\nlearner_old = readRDS(\"learner.rds\")\nlearner$state = learner_old$state\n\n\nNote that this is risky and not guaranteed to work because of various reasons: * You might have now loaded a different version of the learner library (in this case the rpart pacakge). * The internals (such as the structure of the internal $state) might have changed between the versions.\nTherefore, be careful when attempting this solution and double-check that the learner behaves sensibly." + }, + { + "objectID": "faq.html#caching-knitr", + "href": "faq.html#caching-knitr", + "title": "Frequently Asked Questions", + "section": "Caching of knitr/rmarkdown chunks does not work with mlr3", + "text": "Caching of knitr/rmarkdown chunks does not work with mlr3\n{knitr} per default uses R’s lazy-load database to store the results of individual chunks. The lazy-load database is an internal feature of R, and has issues handling active bindings (https://github.com/r-lib/R6/issues/152). Fortunately, it is possible to disable lazy-loading by setting the chunk option cache.lazy to FALSE:\n\nknitr::opts_chunk$set(cache = TRUE, cache.lazy = FALSE)" + }, + { + "objectID": "faq.html#update-packages", + "href": "faq.html#update-packages", + "title": "Frequently Asked Questions", + "section": "How to keep all mlr3 packages up-to-date?", + "text": "How to keep all mlr3 packages up-to-date?\nEither run R’s update.packages() to update all installed packages, or run\ndevtools::update_packages(\"mlr3verse\", dependencies = TRUE)\nto update only packages from the mlr3verse. Note that this also updates recursive dependencies not listed as a direct import." + }, + { + "objectID": "learners.html", + "href": "learners.html", + "title": "Learners", + "section": "", + "text": "To keep the dependencies on other packages reasonable, the base package mlr3 only ships with with regression and classification trees from the rpart package and some learners for debugging. A subjective selection of implementations for essential ML algorithms can be found in mlr3learners package. Survival learners are provided by mlr3proba, cluster learners via mlr3cluster. Additional learners, including some learners which are not yet to be considered stable or which are not available on CRAN, are connected via the mlr3extralearners package. For neural networks, see the mlr3torch extension.\n\n\n\n\n\n\n\n\nFit a classification tree on the Wisconsin Breast Cancer Data Set and predict on left-out observations.\n\nlibrary(\"mlr3verse\")\n\n# retrieve the task\ntask = tsk(\"breast_cancer\")\n\n# split into two partitions\nsplit = partition(task)\n\n# retrieve a learner\nlearner = lrn(\"classif.rpart\", keep_model = TRUE, predict_type = \"prob\")\n\n# fit decision tree\nlearner$train(task, split$train)\n\n# access learned model\nlearner$model\n\nn= 457 \n\nnode), split, n, loss, yval, (yprob)\n * denotes terminal node\n\n 1) root 457 160 benign (0.35010941 0.64989059) \n 2) cell_size=3,4,5,6,7,8,9,10 179 26 malignant (0.85474860 0.14525140) \n 4) bare_nuclei=3,4,5,6,7,8,9,10 148 8 malignant (0.94594595 0.05405405) *\n 5) bare_nuclei=1,2 31 13 benign (0.41935484 0.58064516) \n 10) cell_size=4,5,6,7,8,9,10 14 2 malignant (0.85714286 0.14285714) *\n 11) cell_size=1,2,3 17 1 benign (0.05882353 0.94117647) *\n 3) cell_size=1,2 278 7 benign (0.02517986 0.97482014) *\n\n# predict on data frame with new data\npredictions = learner$predict_newdata(task$data(split$test))\n\n# predict on subset of the task\npredictions = learner$predict(task, split$test)\n\n# inspect predictions\npredictions\n\n<PredictionClassif> for 226 observations:\n row_ids truth response prob.malignant prob.benign\n 2 benign malignant 0.94594595 0.05405405\n 3 benign benign 0.02517986 0.97482014\n 4 benign malignant 0.94594595 0.05405405\n--- \n 665 malignant malignant 0.94594595 0.05405405\n 676 malignant malignant 0.94594595 0.05405405\n 682 malignant malignant 0.94594595 0.05405405\n\npredictions$score(msr(\"classif.auc\"))\n\nclassif.auc \n 0.9476879 \n\nautoplot(predictions, type = \"roc\")" + }, + { + "objectID": "learners.html#example-usage", + "href": "learners.html#example-usage", + "title": "Learners", + "section": "", + "text": "Fit a classification tree on the Wisconsin Breast Cancer Data Set and predict on left-out observations.\n\nlibrary(\"mlr3verse\")\n\n# retrieve the task\ntask = tsk(\"breast_cancer\")\n\n# split into two partitions\nsplit = partition(task)\n\n# retrieve a learner\nlearner = lrn(\"classif.rpart\", keep_model = TRUE, predict_type = \"prob\")\n\n# fit decision tree\nlearner$train(task, split$train)\n\n# access learned model\nlearner$model\n\nn= 457 \n\nnode), split, n, loss, yval, (yprob)\n * denotes terminal node\n\n 1) root 457 160 benign (0.35010941 0.64989059) \n 2) cell_size=3,4,5,6,7,8,9,10 179 26 malignant (0.85474860 0.14525140) \n 4) bare_nuclei=3,4,5,6,7,8,9,10 148 8 malignant (0.94594595 0.05405405) *\n 5) bare_nuclei=1,2 31 13 benign (0.41935484 0.58064516) \n 10) cell_size=4,5,6,7,8,9,10 14 2 malignant (0.85714286 0.14285714) *\n 11) cell_size=1,2,3 17 1 benign (0.05882353 0.94117647) *\n 3) cell_size=1,2 278 7 benign (0.02517986 0.97482014) *\n\n# predict on data frame with new data\npredictions = learner$predict_newdata(task$data(split$test))\n\n# predict on subset of the task\npredictions = learner$predict(task, split$test)\n\n# inspect predictions\npredictions\n\n<PredictionClassif> for 226 observations:\n row_ids truth response prob.malignant prob.benign\n 2 benign malignant 0.94594595 0.05405405\n 3 benign benign 0.02517986 0.97482014\n 4 benign malignant 0.94594595 0.05405405\n--- \n 665 malignant malignant 0.94594595 0.05405405\n 676 malignant malignant 0.94594595 0.05405405\n 682 malignant malignant 0.94594595 0.05405405\n\npredictions$score(msr(\"classif.auc\"))\n\nclassif.auc \n 0.9476879 \n\nautoplot(predictions, type = \"roc\")" + }, + { + "objectID": "gallery.html", + "href": "gallery.html", + "title": "Gallery", + "section": "", + "text": "In the gallery, you find case studies and demos. The posts are mostly about specific features and cover advanced topics. If you are completely new to mlr3 or machine learning, you should start with the book. Pick a post from one of the four categories or browse all posts sorted by date.\n\n\n\n \n \n \n \n\n\n \n \n Time constraints in the mlr3 ecosystem\n Set time limits for learners, tuning and nested resampling.\n\n \n \n \n Analyzing the Runtime Performance of tidymodels and mlr3\n Compare the runtime performance of tidymodels and mlr3.\n\n \n \n \n Survival modeling in mlr3 using Bayesian Additive Regression Trees (BART)\n Demonstrate use of survival BART on the lung dataset via mlr3proba and distr6.\n\n \n \n \n Spatial Data in the mlr3 Ecosystem\n Run a land cover classification of the city of Leipzig.\n\n \n \n \n Recursive Feature Elimination on the Sonar Data Set\n Utilize the built-in feature importance of models.\n\n \n \n\n\nNo matching items\n\n\n \n\n\n \n See all posts \n \n \n\n\n\n\n\n \n \n \n \n\n\n \n \n Basic Machine Learning on Iris data set\n Learn the basic operations train, predict, score, resample, and benchmark.\n\n \n \n \n Imbalanced Data Handling\n Handle imbalanced data with oversampling, undersampling, and SMOTE imbalance correction.\n\n \n \n \n Resampling - Stratified, Blocked and Predefined\n Apply stratified, block and custom resampling.\n\n \n \n \n Factor Encoding\n Encode factor variables in a task.\n\n \n \n \n German Credit Series\n Train, tune and pipeline different machine learning algorithms.\n\n \n \n\n\nNo matching items\n\n\n \n See all posts \n \n \n\n\n\n\n\n \n \n \n \n\n\n \n \n Hyperparameter Optimization on the Palmer Penguins Data Set\n Optimize the hyperparameters of a classification tree with a few lines of code.\n\n \n \n \n Introduction to the mlr3tuningspaces Package\n Apply predefined search spaces from scientific articles.\n\n \n \n \n Early Stopping with XGBoost\n Simultaneously optimize hyperparameters and use early stopping.\n\n \n \n \n Recursive Feature Elimination on the Sonar Data Set\n Utilize the built-in feature importance of models.\n\n \n \n \n Hyperband Series\n Use the Hyperband optimizer with different budget parameters.\n\n \n \n \n Practical Tuning Series\n Start with a tuned SVM and finish with a AutoML model.\n\n \n \n\n\nNo matching items\n\n\n \n See all posts \n \n \n\n\n\n\n\n \n \n \n \n\n\n \n \n A Pipeline for the Titanic Data Set\n Create new features and impute missing values with a pipeline.\n\n \n \n \n Pipelines, Selectors, Branches\n Build a preprocessing pipeline with branching.\n\n \n \n \n Target Transformations via Pipelines\n Transform the target variable.\n\n \n \n \n Tuning a Complex Graph\n Tune a preprocessing pipeline and multiple tuners at once.\n\n \n \n\n\nNo matching items\n\n\n \n See all posts \n \n \n\n\n\n\n\n \n \n \n \n\n\n \n \n Time constraints in the mlr3 ecosystem\n Set time limits for learners, tuning and nested resampling.\n\n \n \n \n Production Example Using Plumber and Docker\n Write a REST API using plumber and deploy it using Docker.\n\n \n \n \n Visualization in mlr3\n Quickly plot objects of the mlr3 ecosystem.\n\n \n \n \n Spatial Data in the mlr3 Ecosystem\n Run a land cover classification of the city of Leipzig.\n\n \n \n\n\nNo matching items\n\n\n \n See all posts" + }, + { + "objectID": "gallery.html#latest", + "href": "gallery.html#latest", + "title": "Gallery", + "section": "", + "text": "Time constraints in the mlr3 ecosystem\n Set time limits for learners, tuning and nested resampling.\n\n \n \n \n Analyzing the Runtime Performance of tidymodels and mlr3\n Compare the runtime performance of tidymodels and mlr3.\n\n \n \n \n Survival modeling in mlr3 using Bayesian Additive Regression Trees (BART)\n Demonstrate use of survival BART on the lung dataset via mlr3proba and distr6.\n\n \n \n \n Spatial Data in the mlr3 Ecosystem\n Run a land cover classification of the city of Leipzig.\n\n \n \n \n Recursive Feature Elimination on the Sonar Data Set\n Utilize the built-in feature importance of models.\n\n \n \n\n\nNo matching items\n\n\n \n\n\n \n See all posts" + }, + { + "objectID": "gallery.html#train-and-evaluate-models", + "href": "gallery.html#train-and-evaluate-models", + "title": "Gallery", + "section": "", + "text": "Basic Machine Learning on Iris data set\n Learn the basic operations train, predict, score, resample, and benchmark.\n\n \n \n \n Imbalanced Data Handling\n Handle imbalanced data with oversampling, undersampling, and SMOTE imbalance correction.\n\n \n \n \n Resampling - Stratified, Blocked and Predefined\n Apply stratified, block and custom resampling.\n\n \n \n \n Factor Encoding\n Encode factor variables in a task.\n\n \n \n \n German Credit Series\n Train, tune and pipeline different machine learning algorithms.\n\n \n \n\n\nNo matching items\n\n\n \n See all posts" + }, + { + "objectID": "gallery.html#optimize-models", + "href": "gallery.html#optimize-models", + "title": "Gallery", + "section": "", + "text": "Hyperparameter Optimization on the Palmer Penguins Data Set\n Optimize the hyperparameters of a classification tree with a few lines of code.\n\n \n \n \n Introduction to the mlr3tuningspaces Package\n Apply predefined search spaces from scientific articles.\n\n \n \n \n Early Stopping with XGBoost\n Simultaneously optimize hyperparameters and use early stopping.\n\n \n \n \n Recursive Feature Elimination on the Sonar Data Set\n Utilize the built-in feature importance of models.\n\n \n \n \n Hyperband Series\n Use the Hyperband optimizer with different budget parameters.\n\n \n \n \n Practical Tuning Series\n Start with a tuned SVM and finish with a AutoML model.\n\n \n \n\n\nNo matching items\n\n\n \n See all posts" + }, + { + "objectID": "gallery.html#build-pipelines", + "href": "gallery.html#build-pipelines", + "title": "Gallery", + "section": "", + "text": "A Pipeline for the Titanic Data Set\n Create new features and impute missing values with a pipeline.\n\n \n \n \n Pipelines, Selectors, Branches\n Build a preprocessing pipeline with branching.\n\n \n \n \n Target Transformations via Pipelines\n Transform the target variable.\n\n \n \n \n Tuning a Complex Graph\n Tune a preprocessing pipeline and multiple tuners at once.\n\n \n \n\n\nNo matching items\n\n\n \n See all posts" + }, + { + "objectID": "gallery.html#apply-technical-tools-and-run-special-tasks", + "href": "gallery.html#apply-technical-tools-and-run-special-tasks", + "title": "Gallery", + "section": "", + "text": "Time constraints in the mlr3 ecosystem\n Set time limits for learners, tuning and nested resampling.\n\n \n \n \n Production Example Using Plumber and Docker\n Write a REST API using plumber and deploy it using Docker.\n\n \n \n \n Visualization in mlr3\n Quickly plot objects of the mlr3 ecosystem.\n\n \n \n \n Spatial Data in the mlr3 Ecosystem\n Run a land cover classification of the city of Leipzig.\n\n \n \n\n\nNo matching items\n\n\n \n See all posts" + }, + { + "objectID": "resamplings.html", + "href": "resamplings.html", + "title": "Resamplings", + "section": "", + "text": "Resamplings split the observations multiple times into two sets: training and test. The former is used to fit the model, the latter is used to evaluate the predictions. The Resampling objects provide an abstraction for this procedure while respecting stratification as well as grouping/blocking if this is required by the Task.\nIf only a single split is required (i.e., a holdout split), the partition() function provides a single split into training and test set.\n\n\n\n\n\n\n\n\nFit a Random Forest on the Wisconsin Breast Cancer Data Set using a 3-fold cross validation.\n\nlibrary(\"mlr3verse\")\n\nLoading required package: mlr3\n\n# retrieve the task\ntask = tsk(\"breast_cancer\")\n\n# retrieve a learner\nlearner = lrn(\"classif.ranger\")\n\n# retrieve resampling strategy\nresampling = rsmp(\"cv\", folds = 3)\n\n# perform resampling\nrr = resample(task, learner, resampling)\n\nINFO [18:11:42.354] [mlr3] Applying learner 'classif.ranger' on task 'breast_cancer' (iter 1/3)\nINFO [18:11:42.925] [mlr3] Applying learner 'classif.ranger' on task 'breast_cancer' (iter 2/3)\nINFO [18:11:43.001] [mlr3] Applying learner 'classif.ranger' on task 'breast_cancer' (iter 3/3)\n\nrr\n\n<ResampleResult> with 3 resampling iterations\n task_id learner_id resampling_id iteration warnings errors\n breast_cancer classif.ranger cv 1 0 0\n breast_cancer classif.ranger cv 2 0 0\n breast_cancer classif.ranger cv 3 0 0" + }, + { + "objectID": "resamplings.html#example-usage", + "href": "resamplings.html#example-usage", + "title": "Resamplings", + "section": "", + "text": "Fit a Random Forest on the Wisconsin Breast Cancer Data Set using a 3-fold cross validation.\n\nlibrary(\"mlr3verse\")\n\nLoading required package: mlr3\n\n# retrieve the task\ntask = tsk(\"breast_cancer\")\n\n# retrieve a learner\nlearner = lrn(\"classif.ranger\")\n\n# retrieve resampling strategy\nresampling = rsmp(\"cv\", folds = 3)\n\n# perform resampling\nrr = resample(task, learner, resampling)\n\nINFO [18:11:42.354] [mlr3] Applying learner 'classif.ranger' on task 'breast_cancer' (iter 1/3)\nINFO [18:11:42.925] [mlr3] Applying learner 'classif.ranger' on task 'breast_cancer' (iter 2/3)\nINFO [18:11:43.001] [mlr3] Applying learner 'classif.ranger' on task 'breast_cancer' (iter 3/3)\n\nrr\n\n<ResampleResult> with 3 resampling iterations\n task_id learner_id resampling_id iteration warnings errors\n breast_cancer classif.ranger cv 1 0 0\n breast_cancer classif.ranger cv 2 0 0\n breast_cancer classif.ranger cv 3 0 0" + }, + { + "objectID": "support.html", + "href": "support.html", + "title": "Support", + "section": "", + "text": "Questions regarding the software can be asked on Stack Overflow, where you can use the mlr3 tag." + }, + { + "objectID": "support.html#stackoverflow", + "href": "support.html#stackoverflow", + "title": "Support", + "section": "", + "text": "Questions regarding the software can be asked on Stack Overflow, where you can use the mlr3 tag." + }, + { + "objectID": "support.html#github", + "href": "support.html#github", + "title": "Support", + "section": "GitHub", + "text": "GitHub\nFor bug reports, suggestions, or feature requests please raise an issue in the corresponding GitHub repository. Your issue will be addressed sooner if you provide a reproducible example - e.g. using the reprex R package - and if you open it in the correct repository." + }, + { + "objectID": "support.html#mattermost", + "href": "support.html#mattermost", + "title": "Support", + "section": "Mattermost", + "text": "Mattermost\nYou can join our public Mattermost channel." + }, + { + "objectID": "measures.html", + "href": "measures.html", + "title": "Measures", + "section": "", + "text": "Measures\nMeasures operate on Prediction objects generated by learners. They quantify the prediction by comparing prediction with ground truth. The Measure objects provide an abstraction for a plethora of performance measures." + }, + { + "objectID": "tuners.html", + "href": "tuners.html", + "title": "Tuners", + "section": "", + "text": "Popular black-box optimization techniques are implemented in the bbotk package. The corresponding connectors to for tuning hyperparameters of learners or pipelines reside as Tuner objects in package mlr3tuning. Additionally, packages mlr3hyperband and mlr3mbo provide some modern and sophisticated approaches.\nAll tuners operator on box-constrained tuning spaces which have to be defined by the user. Some popular spaces from literature are readily available as tuning spaces.\n\n\n\n\n\n\n\n\nTune the hyperparameters of a classification tree on the Palmer Penguins data set with random search.\n\nlibrary(mlr3verse)\n\n# retrieve task\ntask = tsk(\"penguins\")\n\n# load learner and set search space\nlearner = lrn(\"classif.rpart\",\n cp = to_tune(1e-04, 1e-1, logscale = TRUE),\n minsplit = to_tune(2, 128, logscale = TRUE)\n)\n\n# load tuner and set batch size\ntuner = tnr(\"random_search\", batch_size = 10)\n\n# hyperparameter tuning on the palmer penguins data set\ninstance = tune(\n tuner = tuner,\n task = task,\n learner = learner,\n resampling = rsmp(\"holdout\"),\n measure = msr(\"classif.ce\"),\n term_evals = 50\n)\n\n# best performing hyperparameter configuration\ninstance$result\n\n cp minsplit learner_param_vals x_domain classif.ce\n <num> <num> <list> <list> <num>\n1: -6.726085 2.257884 <list[3]> <list[2]> 0.05217391\n\n# surface plot\nautoplot(instance, type = \"surface\")\n\n\n\n\n\n\n\n# fit final model on complete data set\nlearner$param_set$values = instance$result_learner_param_vals\nlearner$train(task)\n\nprint(learner)\n\n<LearnerClassifRpart:classif.rpart>: Classification Tree\n* Model: rpart\n* Parameters: cp=0.001199, minsplit=9, xval=0\n* Packages: mlr3, rpart\n* Predict Types: [response], prob\n* Feature Types: logical, integer, numeric, factor, ordered\n* Properties: importance, missings, multiclass, selected_features,\n twoclass, weights" + }, + { + "objectID": "tuners.html#example-usage", + "href": "tuners.html#example-usage", + "title": "Tuners", + "section": "", + "text": "Tune the hyperparameters of a classification tree on the Palmer Penguins data set with random search.\n\nlibrary(mlr3verse)\n\n# retrieve task\ntask = tsk(\"penguins\")\n\n# load learner and set search space\nlearner = lrn(\"classif.rpart\",\n cp = to_tune(1e-04, 1e-1, logscale = TRUE),\n minsplit = to_tune(2, 128, logscale = TRUE)\n)\n\n# load tuner and set batch size\ntuner = tnr(\"random_search\", batch_size = 10)\n\n# hyperparameter tuning on the palmer penguins data set\ninstance = tune(\n tuner = tuner,\n task = task,\n learner = learner,\n resampling = rsmp(\"holdout\"),\n measure = msr(\"classif.ce\"),\n term_evals = 50\n)\n\n# best performing hyperparameter configuration\ninstance$result\n\n cp minsplit learner_param_vals x_domain classif.ce\n <num> <num> <list> <list> <num>\n1: -6.726085 2.257884 <list[3]> <list[2]> 0.05217391\n\n# surface plot\nautoplot(instance, type = \"surface\")\n\n\n\n\n\n\n\n# fit final model on complete data set\nlearner$param_set$values = instance$result_learner_param_vals\nlearner$train(task)\n\nprint(learner)\n\n<LearnerClassifRpart:classif.rpart>: Classification Tree\n* Model: rpart\n* Parameters: cp=0.001199, minsplit=9, xval=0\n* Packages: mlr3, rpart\n* Predict Types: [response], prob\n* Feature Types: logical, integer, numeric, factor, ordered\n* Properties: importance, missings, multiclass, selected_features,\n twoclass, weights" + }, + { + "objectID": "contributing.html", + "href": "contributing.html", + "title": "Contributing", + "section": "", + "text": "You are welcome to open a Pull Request on GitHub. Before doing so, please read our PR Guidelines.\nIf you\n\nwant to add a new Learner, PipeOp or Measure you can check out the chapter extending of the mlr3 book.\nare interested in creating a new R package for the mlr3 ecosystem or collaborate on an existing one, you can contact us on Mattermost.\n\nAdditional developer information lives in the mlr3 GitHub Wiki." + }, + { + "objectID": "gallery-all.html", + "href": "gallery-all.html", + "title": "All Posts", + "section": "", + "text": "All Posts\n\n\n \n \n Time constraints in the mlr3 ecosystem\n Set time limits for learners, tuning and nested resampling.\n\n 2023-12-21 - Marc Becker\n \n \n \n Analyzing the Runtime Performance of tidymodels and mlr3\n Compare the runtime performance of tidymodels and mlr3.\n\n 2023-10-30 - Marc Becker\n \n \n \n Survival modeling in mlr3 using Bayesian Additive Regression Trees (BART)\n Demonstrate use of survival BART on the lung dataset via mlr3proba and distr6.\n\n 2023-10-25 - John Zobolas\n \n \n \n Spatial Data in the mlr3 Ecosystem\n Run a land cover classification of the city of Leipzig.\n\n 2023-02-27 - Marc Becker\n \n \n \n Recursive Feature Elimination on the Sonar Data Set\n Utilize the built-in feature importance of models.\n\n 2023-02-07 - Marc Becker\n \n \n \n Shadow Variable Search on the Pima Indian Diabetes Data Set\n Run a feature selection with permutated features.\n\n 2023-02-01 - Marc Becker, Sebastian Fischer\n \n \n \n Default Hyperparameter Configuration\n Run the default hyperparameter configuration of learners as a baseline.\n\n 2023-01-31 - Marc Becker\n \n \n \n Hyperband Series - Data Set Subsampling\n Optimize the hyperparameters of a Support Vector Machine with Hyperband.\n\n 2023-01-16 - Marc Becker, Sebastian Fischer\n \n \n \n Hotstarting\n Resume the training of learners.\n\n 2023-01-16 - Marc Becker, Sebastian Fischer\n \n \n \n Hyperband Series - Iterative Training\n Optimize the hyperparameters of an XGBoost model with Hyperband.\n\n 2023-01-15 - Marc Becker, Sebastian Fischer\n \n \n \n Visualization in mlr3\n Quickly plot the mlr3 ecosystem.\n\n 2022-12-22 - Marc Becker\n \n \n \n Hyperparameter Optimization on the Palmer Penguins Data Set\n Optimize the hyperparameters of a classification tree with a few lines of code.\n\n 2022-11-10 - Marc Becker\n \n \n \n Early Stopping with XGBoost\n Simultaneously optimize hyperparameters and use early stopping.\n\n 2022-11-09 - Marc Becker\n \n \n \n Introduction to mlr3tuningspaces\n Apply predefined search spaces from scientific articles.\n\n 2021-07-06 - Marc Becker\n \n \n \n Practical Tuning Series - Tuning and Parallel Processing\n Run various jobs in mlr3 in parallel.\n\n 2021-03-12 - Marc Becker, Theresa Ullmann, Michel Lang, Bernd Bischl, Jakob Richter, Martin Binder\n \n \n \n Practical Tuning Series - Build an Automated Machine Learning System\n Implement a simple automated machine learning system.\n\n 2021-03-11 - Marc Becker, Theresa Ullmann, Michel Lang, Bernd Bischl, Jakob Richter, Martin Binder\n \n \n \n Practical Tuning Series - Tune a Preprocessing Pipeline\n Build a simple preprocessing pipeline and tune it.\n\n 2021-03-10 - Marc Becker, Theresa Ullmann, Michel Lang, Bernd Bischl, Jakob Richter, Martin Binder\n \n \n \n Practical Tuning Series - Tune a Support Vector Machine\n Optimize the hyperparameters of a support vector machine.\n\n 2021-03-09 - Marc Becker, Theresa Ullmann, Michel Lang, Bernd Bischl, Jakob Richter, Martin Binder\n \n \n \n Tuning a Complex Graph\n Tune a preprocessing pipeline and multiple tuners at once.\n\n 2021-02-03 - Lennart Schneider\n \n \n \n Integer Hyperparameters in Tuners for Real-valued Search Spaces\n Optimize integer hyperparameters with tuners that can only propose real numbers.\n\n 2021-01-19 - Marc Becker\n \n \n \n Feature Selection on the Titanic Data Set\n Run a feature selection with different algorithms and use nested resampling.\n\n 2021-01-08 - Marc Becker\n \n \n \n Threshold Tuning for Classification Tasks\n Adjust the probability thresholds of classes.\n\n 2020-10-14 - Florian Pfisterer\n \n \n \n Introduction to mlr3keras - Boston Housing\n This use case provides an introduction to mlr3keras via the boston housing dataset.\n\n 2020-09-11 - Florian Pfisterer\n \n \n \n Liver Patient Classification Based on Diagnostic Measures\n Tune and benchmark pipelines.\n\n 2020-09-11 - Julian Lange, Jae-Eun Nam, Viet Tran, Simon Wiegrebe, Henri Funk (Editor)\n \n \n \n Comparison of Decision Boundaries of Classification Learners\n Visualize the decision boundaries of multiple classification learners on some artificial data sets.\n\n 2020-08-14 - Michel Lang\n \n \n \n A Production Example Using Plumber and Docker\n Write a REST API using plumber and deploy it using Docker.\n\n 2020-08-13 - Lennart Schneider\n \n \n \n Target Transformations via Pipelines\n Transform the target variable.\n\n 2020-06-15 - Lennart Schneider\n \n \n \n mlr3 and OpenML - Moneyball Use Case\n Download data from OpenML data and impute missing values.\n\n 2020-05-04 - Philipp Kopper\n \n \n \n Feature Engineering of Date-Time Variables\n Engineer features using date-time variables.\n\n 2020-05-02 - Lennart Schneider\n \n \n \n Tuning a Stacked Learner\n Tune a multilevel stacking model.\n\n 2020-04-27 - Milan Dragicevic, Giuseppe Casalicchio\n \n \n \n A Pipeline for the Titanic Data Set - Advanced\n Create new features and impute missing values with a pipeline.\n\n 2020-04-27 - Florian Pfisterer\n \n \n \n Pipelines, Selectors, Branches\n Build a preprocessing pipeline with branching.\n\n 2020-04-23 - Milan Dragicevic, Giuseppe Casalicchio\n \n \n \n Regression Chains\n Handle multi-target regression with regression chains.\n\n 2020-04-18 - Lennart Schneider\n \n \n \n Resampling - Stratified, Blocked and Predefined\n Apply stratified, block and custom resampling.\n\n 2020-03-30 - Milan Dragicevic, Giuseppe Casalicchio\n \n \n \n Imbalanced Data Handling with mlr3\n Handle imbalanced data with oversampling, undersampling, and SMOTE imbalance correction.\n\n 2020-03-30 - Giuseppe Casalicchio\n \n \n \n mlr3 Basics on \"Iris\" - Hello World!\n Learn the basic operations train, predict, score, resample, and benchmark.\n\n 2020-03-18 - Bernd Bischl\n \n \n \n A Pipeline for the Titanic Data Set - Basics\n Build a graph.\n\n 2020-03-12 - Florian Pfisterer\n \n \n \n German Credit Series - Basics\n Train different models.\n\n 2020-03-11 - Martin Binder, Florian Pfisterer, Michel Lang\n \n \n \n German Credit Series - Tuning\n Optimize Hyperparameters and apply nested resampling.\n\n 2020-03-11 - Martin Binder, Florian Pfisterer\n \n \n \n German Credit Series - Pipelines\n Impute missing values, filter features and stack Learners.\n\n 2020-03-11 - Martin Binder, Florian Pfisterer\n \n \n \n Select Uncorrelated Features\n Remove correlated features with a pipeline.\n\n 2020-02-25 - Martin Binder, Florian Pfisterer\n \n \n \n Tuning Over Multiple Learners\n Tune over multiple learners for a single task.\n\n 2020-02-01 - Jakob Richter, Bernd Bischl\n \n \n \n Impute Missing Variables\n Augment a Random Forest with automatic imputation.\n\n 2020-01-31 - Florian Pfisterer\n \n \n \n Encode Factor Levels for xgboost\n Encode factor variables in a task.\n\n 2020-01-31 - Michel Lang\n \n \n \n House Prices in King County\n Apply multiple preprocessing steps, fit a model and visualize the results.\n\n 2020-01-30 - Florian Pfisterer\n \n \n\n\nNo matching items" + }, + { + "objectID": "gallery-all-optimization.html", + "href": "gallery-all-optimization.html", + "title": "Optimize Models", + "section": "", + "text": "Optimize Models\n\n\n \n \n Recursive Feature Elimination on the Sonar Data Set\n Utilize the built-in feature importance of models.\n\n 2023-02-07 - Marc Becker\n \n \n \n Shadow Variable Search on the Pima Indian Diabetes Data Set\n Run a feature selection with permutated features.\n\n 2023-02-01 - Marc Becker, Sebastian Fischer\n \n \n \n Default Hyperparameter Configuration\n Run the default hyperparameter configuration of learners as a baseline.\n\n 2023-01-31 - Marc Becker\n \n \n \n Hyperband Series - Data Set Subsampling\n Optimize the hyperparameters of a Support Vector Machine with Hyperband.\n\n 2023-01-16 - Marc Becker, Sebastian Fischer\n \n \n \n Hotstarting\n Resume the training of learners.\n\n 2023-01-16 - Marc Becker, Sebastian Fischer\n \n \n \n Hyperband Series - Iterative Training\n Optimize the hyperparameters of an XGBoost model with Hyperband.\n\n 2023-01-15 - Marc Becker, Sebastian Fischer\n \n \n \n Hyperparameter Optimization on the Palmer Penguins Data Set\n Optimize the hyperparameters of a classification tree with a few lines of code.\n\n 2022-11-10 - Marc Becker\n \n \n \n Early Stopping with XGBoost\n Simultaneously optimize hyperparameters and use early stopping.\n\n 2022-11-09 - Marc Becker\n \n \n \n Introduction to mlr3tuningspaces\n Apply predefined search spaces from scientific articles.\n\n 2021-07-06 - Marc Becker\n \n \n \n Practical Tuning Series - Tuning and Parallel Processing\n Run various jobs in mlr3 in parallel.\n\n 2021-03-12 - Marc Becker, Theresa Ullmann, Michel Lang, Bernd Bischl, Jakob Richter, Martin Binder\n \n \n \n Practical Tuning Series - Build an Automated Machine Learning System\n Implement a simple automated machine learning system.\n\n 2021-03-11 - Marc Becker, Theresa Ullmann, Michel Lang, Bernd Bischl, Jakob Richter, Martin Binder\n \n \n \n Practical Tuning Series - Tune a Preprocessing Pipeline\n Build a simple preprocessing pipeline and tune it.\n\n 2021-03-10 - Marc Becker, Theresa Ullmann, Michel Lang, Bernd Bischl, Jakob Richter, Martin Binder\n \n \n \n Practical Tuning Series - Tune a Support Vector Machine\n Optimize the hyperparameters of a support vector machine.\n\n 2021-03-09 - Marc Becker, Theresa Ullmann, Michel Lang, Bernd Bischl, Jakob Richter, Martin Binder\n \n \n \n Integer Hyperparameters in Tuners for Real-valued Search Spaces\n Optimize integer hyperparameters with tuners that can only propose real numbers.\n\n 2021-01-19 - Marc Becker\n \n \n \n Feature Selection on the Titanic Data Set\n Run a feature selection with different algorithms and use nested resampling.\n\n 2021-01-08 - Marc Becker\n \n \n \n Threshold Tuning for Classification Tasks\n Adjust the probability thresholds of classes.\n\n 2020-10-14 - Florian Pfisterer\n \n \n\n\nNo matching items" + }, + { + "objectID": "gallery-all-pipelines.html", + "href": "gallery-all-pipelines.html", + "title": "Build Pipelines", + "section": "", + "text": "Build Pipelines\n\n\n \n \n Tuning a Complex Graph\n Tune a preprocessing pipeline and multiple tuners at once.\n\n 2021-02-03 - Lennart Schneider\n \n \n \n Liver Patient Classification Based on Diagnostic Measures\n Tune and benchmark pipelines.\n\n 2020-09-11 - Julian Lange, Jae-Eun Nam, Viet Tran, Simon Wiegrebe, Henri Funk (Editor)\n \n \n \n Target Transformations via Pipelines\n Transform the target variable.\n\n 2020-06-15 - Lennart Schneider\n \n \n \n Tuning a Stacked Learner\n Tune a multilevel stacking model.\n\n 2020-04-27 - Milan Dragicevic, Giuseppe Casalicchio\n \n \n \n A Pipeline for the Titanic Data Set - Advanced\n Create new features and impute missing values with a pipeline.\n\n 2020-04-27 - Florian Pfisterer\n \n \n \n Pipelines, Selectors, Branches\n Build a preprocessing pipeline with branching.\n\n 2020-04-23 - Milan Dragicevic, Giuseppe Casalicchio\n \n \n \n Regression Chains\n Handle multi-target regression with regression chains.\n\n 2020-04-18 - Lennart Schneider\n \n \n \n A Pipeline for the Titanic Data Set - Basics\n Build a graph.\n\n 2020-03-12 - Florian Pfisterer\n \n \n \n Tuning Over Multiple Learners\n Tune over multiple learners for a single task.\n\n 2020-02-01 - Jakob Richter, Bernd Bischl\n \n \n\n\nNo matching items" + }, + { + "objectID": "book.html", + "href": "book.html", + "title": "Book", + "section": "", + "text": "The “mlr3book” is a free manual written in an online-book style available in two versions.\nIt is the main reference for the mlr3 ecosystem.\n\nHTML\nPDF" + }, + { + "objectID": "dependencies.html", + "href": "dependencies.html", + "title": "Dependencies", + "section": "", + "text": "mlr3 tries to be light on dependencies. The following packages are at runtime:\n\nparallelly: Helper functions for parallelization. No extra recursive dependencies.\nfuture.apply: Resampling and benchmarking is parallelized with the future abstraction interfacing many parallel backends.\nbackports: Ensures backward compatibility with older R releases. Developed by members of the mlr team. No recursive dependencies.\ncheckmate: Fast argument checks. Developed by members of the mlr team. No extra recursive dependencies.\nmlr3misc: Miscellaneous functions used in multiple mlr3 extension packages. Developed by the mlr team.\nparadox: Descriptions for parameters and parameter sets. Developed by the mlr team. No extra recursive dependencies.\nR6: Reference class objects. No recursive dependencies.\ndata.table: Extension of R’s data.frame. No recursive dependencies.\ndigest (via mlr3misc): Hash digests. No recursive dependencies.\nuuid: Create unique string identifiers. No recursive dependencies.\nlgr: Logging facility. No extra recursive dependencies.\nmlr3measures: Performance measures. No extra recursive dependencies.\nmlbench: A collection of machine learning data sets. No dependencies.\npalmerpenguins: A classification data set about penguins, used on examples and provided as a toy task. No dependencies." + }, + { + "objectID": "blogroll.html", + "href": "blogroll.html", + "title": "Blogroll", + "section": "", + "text": "https://www.r-bloggers.com/" + }, + { + "objectID": "filters.html", + "href": "filters.html", + "title": "Feature Selection Filter", + "section": "", + "text": "Feature Filters quantify the importance of each feature of a Task by assigning them a numerical score. In a second step, features can be selected by either selecting a fixed absolute or relative frequency of the best features, or by thresholding on the score value.\nThe Filter PipeOp allows to use filters as a preprocessing step.\n\n\n\n\n\n\n\n\nUse the \\(-\\log_{10}()\\)-transformed \\(p\\)-values of a Kruskal-Wallis rank sum test (implemented in kruskal.test()) for filtering features of the Pima Indian Diabetes tasks.\n\nlibrary(\"mlr3verse\")\n\nLoading required package: mlr3\n\n# retrieve a task\ntask = tsk(\"pima\")\n\n# retrieve a filter\nfilter = flt(\"kruskal_test\")\n\n# calculate scores\nfilter$calculate(task)\n\n# access scores\nfilter$scores\n\n glucose age mass insulin triceps pregnant pedigree pressure \n39.885381 16.942901 16.740864 13.127828 9.158113 7.426955 5.922431 5.788607 \n\n# plot scores\nautoplot(filter)\n\n\n\n\n\n\n\n# subset task to 3 most important features\ntask$select(head(names(filter$scores), 3))\ntask$feature_names\n\n[1] \"age\" \"glucose\" \"mass\"" + }, + { + "objectID": "filters.html#example-usage", + "href": "filters.html#example-usage", + "title": "Feature Selection Filter", + "section": "", + "text": "Use the \\(-\\log_{10}()\\)-transformed \\(p\\)-values of a Kruskal-Wallis rank sum test (implemented in kruskal.test()) for filtering features of the Pima Indian Diabetes tasks.\n\nlibrary(\"mlr3verse\")\n\nLoading required package: mlr3\n\n# retrieve a task\ntask = tsk(\"pima\")\n\n# retrieve a filter\nfilter = flt(\"kruskal_test\")\n\n# calculate scores\nfilter$calculate(task)\n\n# access scores\nfilter$scores\n\n glucose age mass insulin triceps pregnant pedigree pressure \n39.885381 16.942901 16.740864 13.127828 9.158113 7.426955 5.922431 5.788607 \n\n# plot scores\nautoplot(filter)\n\n\n\n\n\n\n\n# subset task to 3 most important features\ntask$select(head(names(filter$scores), 3))\ntask$feature_names\n\n[1] \"age\" \"glucose\" \"mass\"" + }, + { + "objectID": "gallery-all-technical.html", + "href": "gallery-all-technical.html", + "title": "Customize and Apply Technical Tools", + "section": "", + "text": "Customize and Apply Technical Tools\n\n\n \n \n Time constraints in the mlr3 ecosystem\n Set time limits for learners, tuning and nested resampling.\n\n 2023-12-21 - Marc Becker\n \n \n \n Analyzing the Runtime Performance of tidymodels and mlr3\n Compare the runtime performance of tidymodels and mlr3.\n\n 2023-10-30 - Marc Becker\n \n \n \n Survival modeling in mlr3 using Bayesian Additive Regression Trees (BART)\n Demonstrate use of survival BART on the lung dataset via mlr3proba and distr6.\n\n 2023-10-25 - John Zobolas\n \n \n \n Spatial Data in the mlr3 Ecosystem\n Run a land cover classification of the city of Leipzig.\n\n 2023-02-27 - Marc Becker\n \n \n \n Visualization in mlr3\n Quickly plot the mlr3 ecosystem.\n\n 2022-12-22 - Marc Becker\n \n \n \n A Production Example Using Plumber and Docker\n Write a REST API using plumber and deploy it using Docker.\n\n 2020-08-13 - Lennart Schneider\n \n \n\n\nNo matching items" + }, + { + "objectID": "torch_pipeops.html", + "href": "torch_pipeops.html", + "title": "Torch Pipeline Operators", + "section": "", + "text": "Torch Pipeline Operators\nmlr3torch supports a number of PipeOp building blocks to define neural networks, including preprocessing and data augmentation steps." + }, + { + "objectID": "team/about-michel.html", + "href": "team/about-michel.html", + "title": "Michel Lang", + "section": "", + "text": "Postdoc at the TU Dortmund and one of the main developers of mlr. I’ve worked on many internal parts of mlr and started to implement support for survival analysis. Now main developer of mlr3." + }, + { + "objectID": "team/about-florian.html", + "href": "team/about-florian.html", + "title": "Florian Pfisterer", + "section": "", + "text": "PhD Student at LMU Munich. I am interested in projects on the intersection of Meta-Learning, AutoML and Algorithmic Fairness. Mainly working on mlr3pipelines and mlr3keras/mlr3torch." + }, + { + "objectID": "team/about-marc.html", + "href": "team/about-marc.html", + "title": "Marc Becker", + "section": "", + "text": "Research engineer at the LMU Munich and main developer of the mlr3 optimization packages." + }, + { + "objectID": "team/about-lennart.html", + "href": "team/about-lennart.html", + "title": "Lennart Schneider", + "section": "", + "text": "PhD Student at LMU Munich. Interested in black box optimization, HPO and AutoML. Mainly working on mlr3mbo." + }, + { + "objectID": "gallery/optimization/2021-01-19-integer-hyperparameters-in-tuners-for-real-valued-search-spaces/index.html", + "href": "gallery/optimization/2021-01-19-integer-hyperparameters-in-tuners-for-real-valued-search-spaces/index.html", + "title": "Integer Hyperparameters in Tuners for Real-valued Search Spaces", + "section": "", + "text": "Tuner for real-valued search spaces are not able to tune on integer hyperparameters. However, it is possible to round the real values proposed by a Tuner to integers before passing them to the learner in the evaluation. We show how to apply a parameter transformation to a ParamSet and use this set in the tuning process.\nWe load the mlr3verse package which pulls in the most important packages for this example.\n\nlibrary(mlr3verse)\n\nLoading required package: mlr3\n\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\nlgr::get_logger(\"bbotk\")$set_threshold(\"warn\")" + }, + { + "objectID": "gallery/optimization/2021-01-19-integer-hyperparameters-in-tuners-for-real-valued-search-spaces/index.html#introduction", + "href": "gallery/optimization/2021-01-19-integer-hyperparameters-in-tuners-for-real-valued-search-spaces/index.html#introduction", + "title": "Integer Hyperparameters in Tuners for Real-valued Search Spaces", + "section": "", + "text": "Tuner for real-valued search spaces are not able to tune on integer hyperparameters. However, it is possible to round the real values proposed by a Tuner to integers before passing them to the learner in the evaluation. We show how to apply a parameter transformation to a ParamSet and use this set in the tuning process.\nWe load the mlr3verse package which pulls in the most important packages for this example.\n\nlibrary(mlr3verse)\n\nLoading required package: mlr3\n\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\nlgr::get_logger(\"bbotk\")$set_threshold(\"warn\")" + }, + { + "objectID": "gallery/optimization/2021-01-19-integer-hyperparameters-in-tuners-for-real-valued-search-spaces/index.html#task-and-learner", + "href": "gallery/optimization/2021-01-19-integer-hyperparameters-in-tuners-for-real-valued-search-spaces/index.html#task-and-learner", + "title": "Integer Hyperparameters in Tuners for Real-valued Search Spaces", + "section": "Task and Learner", + "text": "Task and Learner\nIn this example, we use the k-Nearest-Neighbor classification learner. We want to tune the integer-valued hyperparameter k which defines the numbers of neighbors.\n\nlearner = lrn(\"classif.kknn\")\nprint(learner$param_set$params$k)\n\n id class lower upper levels default\n1: k ParamInt 1 Inf 7" + }, + { + "objectID": "gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/index.html", + "href": "gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/index.html", + "title": "Hyperparameter Optimization on the Palmer Penguins Data Set", + "section": "", + "text": "In this post, we optimize the hyperparameters of a simple classification tree on the Palmer Penguins data set with only a few lines of code.\nFirst, we introduce tuning spaces and show the importance of transformation functions. Next, we execute the tuning and present the basic building blocks of tuning in mlr3. Finally, we fit a classification tree with optimized hyperparameters on the full data set." + }, + { + "objectID": "gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/index.html#transformations", + "href": "gallery/optimization/2022-11-10-hyperparameter-optimization-on-the-palmer-penguins/index.html#transformations", + "title": "Hyperparameter Optimization on the Palmer Penguins Data Set", + "section": "Transformations", + "text": "Transformations\nThe column logscale indicates that the hyperparameters are tuned on the logarithmic scale. The tuning algorithm proposes hyperparameter values that are transformed with the exponential function before they are passed to the learner. For example, the cp parameter is bounded between 0 and 1. The tuning algorithm searches between log(1e-04) and log(1e-01) but the learner gets the transformed values between 1e-04 and 1e-01. Using the log transformation emphasizes smaller cp values but also creates large values.\n\nlts(\"classif.rpart.default\")\n\n<TuningSpace:classif.rpart.default>: Classification Rpart with Default\n id lower upper levels logscale\n <char> <num> <num> <list> <lgcl>\n1: minsplit 2e+00 128.0 TRUE\n2: minbucket 1e+00 64.0 TRUE\n3: cp 1e-04 0.1 TRUE" + }, + { + "objectID": "gallery/optimization/2021-07-06-introduction-to-mlr3tuningspaces/index.html", + "href": "gallery/optimization/2021-07-06-introduction-to-mlr3tuningspaces/index.html", + "title": "Introduction to mlr3tuningspaces", + "section": "", + "text": "Scope\nThe package mlr3tuningspaces offers a selection of published search spaces for many popular machine learning algorithms. In this post, we show how to tune a mlr3 learners with these search spaces.\n\n\nPrerequisites\nThe packages mlr3verse and mlr3tuningspaces are required for this demonstration:\n\nlibrary(mlr3verse)\nlibrary(mlr3tuningspaces)\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\nlgr::get_logger(\"bbotk\")$set_threshold(\"warn\")\n\nIn the example, we use the pima indian diabetes data set which is used to predict whether or not a patient has diabetes. The patients are characterized by 8 numeric features, some of them have missing values.\n\n# retrieve the task from mlr3\ntask = tsk(\"pima\")\n\n# generate a quick textual overview using the skimr package\nskimr::skim(task$data())\n\n\nData summary\n\n\nName\ntask$data()\n\n\nNumber of rows\n768\n\n\nNumber of columns\n9\n\n\nKey\nNULL\n\n\n_______________________\n\n\n\nColumn type frequency:\n\n\n\nfactor\n1\n\n\nnumeric\n8\n\n\n________________________\n\n\n\nGroup variables\nNone\n\n\n\nVariable type: factor\n\n\n\n\n\n\n\n\n\n\n\nskim_variable\nn_missing\ncomplete_rate\nordered\nn_unique\ntop_counts\n\n\n\n\ndiabetes\n0\n1\nFALSE\n2\nneg: 500, pos: 268\n\n\n\nVariable type: numeric\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nskim_variable\nn_missing\ncomplete_rate\nmean\nsd\np0\np25\np50\np75\np100\nhist\n\n\n\n\nage\n0\n1.00\n33.24\n11.76\n21.00\n24.00\n29.00\n41.00\n81.00\n▇▃▁▁▁\n\n\nglucose\n5\n0.99\n121.69\n30.54\n44.00\n99.00\n117.00\n141.00\n199.00\n▁▇▇▃▂\n\n\ninsulin\n374\n0.51\n155.55\n118.78\n14.00\n76.25\n125.00\n190.00\n846.00\n▇▂▁▁▁\n\n\nmass\n11\n0.99\n32.46\n6.92\n18.20\n27.50\n32.30\n36.60\n67.10\n▅▇▃▁▁\n\n\npedigree\n0\n1.00\n0.47\n0.33\n0.08\n0.24\n0.37\n0.63\n2.42\n▇▃▁▁▁\n\n\npregnant\n0\n1.00\n3.85\n3.37\n0.00\n1.00\n3.00\n6.00\n17.00\n▇▃▂▁▁\n\n\npressure\n35\n0.95\n72.41\n12.38\n24.00\n64.00\n72.00\n80.00\n122.00\n▁▃▇▂▁\n\n\ntriceps\n227\n0.70\n29.15\n10.48\n7.00\n22.00\n29.00\n36.00\n99.00\n▆▇▁▁▁\n\n\n\n\n\n\n\nTuning Search Space\nFor tuning, it is important to create a search space that defines the type and range of the hyperparameters. A learner stores all information about its hyperparameters in the slot $param_set. Usually, we have to chose a subset of hyperparameters we want to tune.\n\nlrn(\"classif.rpart\")$param_set\n\n<ParamSet>\n id class lower upper nlevels default value\n 1: cp ParamDbl 0 1 Inf 0.01 \n 2: keep_model ParamLgl NA NA 2 FALSE \n 3: maxcompete ParamInt 0 Inf Inf 4 \n 4: maxdepth ParamInt 1 30 30 30 \n 5: maxsurrogate ParamInt 0 Inf Inf 5 \n 6: minbucket ParamInt 1 Inf Inf <NoDefault[3]> \n 7: minsplit ParamInt 1 Inf Inf 20 \n 8: surrogatestyle ParamInt 0 1 2 0 \n 9: usesurrogate ParamInt 0 2 3 2 \n10: xval ParamInt 0 Inf Inf 10 0\n\n\n\n\nPackage\nAt the heart of mlr3tuningspaces is the R6 class TuningSpace. It stores a list of TuneToken, helper functions and additional meta information. The list of TuneToken can be directly applied to the $values slot of a learner’s ParamSet. The search spaces are stored in the mlr_tuning_spaces dictionary.\n\nas.data.table(mlr_tuning_spaces)\n\n key label learner n_values\n 1: classif.glmnet.default Classification GLM with Default classif.glmnet 2\n 2: classif.glmnet.rbv1 Classification GLM with RandomBot classif.glmnet 2\n 3: classif.glmnet.rbv2 Classification GLM with RandomBot classif.glmnet 2\n 4: classif.kknn.default Classification KKNN with Default classif.kknn 3\n 5: classif.kknn.rbv1 Classification KKNN with RandomBot classif.kknn 1\n 6: classif.kknn.rbv2 Classification KKNN with RandomBot classif.kknn 1\n 7: classif.ranger.default Classification Ranger with Default classif.ranger 4\n 8: classif.ranger.rbv1 Classification Ranger with RandomBot classif.ranger 6\n 9: classif.ranger.rbv2 Classification Ranger with RandomBot classif.ranger 8\n10: classif.rpart.default Classification Rpart with Default classif.rpart 3\n11: classif.rpart.rbv1 Classification Rpart with RandomBot classif.rpart 4\n12: classif.rpart.rbv2 Classification Rpart with RandomBot classif.rpart 4\n13: classif.svm.default Classification SVM with Default classif.svm 4\n14: classif.svm.rbv1 Classification SVM with RandomBot classif.svm 4\n15: classif.svm.rbv2 Classification SVM with RandomBot classif.svm 5\n16: classif.xgboost.default Classification XGBoost with Default classif.xgboost 8\n17: classif.xgboost.rbv1 Classification XGBoost with RandomBot classif.xgboost 10\n18: classif.xgboost.rbv2 Classification XGBoost with RandomBot classif.xgboost 13\n19: regr.glmnet.default Regression GLM with Default regr.glmnet 2\n20: regr.glmnet.rbv1 Regression GLM with RandomBot regr.glmnet 2\n21: regr.glmnet.rbv2 Regression GLM with RandomBot regr.glmnet 2\n22: regr.kknn.default Regression KKNN with Default regr.kknn 3\n23: regr.kknn.rbv1 Regression KKNN with RandomBot regr.kknn 1\n24: regr.kknn.rbv2 Regression KKNN with RandomBot regr.kknn 1\n25: regr.ranger.default Regression Ranger with Default regr.ranger 4\n26: regr.ranger.rbv1 Regression Ranger with RandomBot regr.ranger 6\n27: regr.ranger.rbv2 Regression Ranger with RandomBot regr.ranger 7\n28: regr.rpart.default Regression Rpart with Default regr.rpart 3\n29: regr.rpart.rbv1 Regression Rpart with RandomBot regr.rpart 4\n30: regr.rpart.rbv2 Regression Rpart with RandomBot regr.rpart 4\n31: regr.svm.default Regression SVM with Default regr.svm 4\n32: regr.svm.rbv1 Regression SVM with RandomBot regr.svm 4\n33: regr.svm.rbv2 Regression SVM with RandomBot regr.svm 5\n34: regr.xgboost.default Regression XGBoost with Default regr.xgboost 8\n35: regr.xgboost.rbv1 Regression XGBoost with RandomBot regr.xgboost 10\n36: regr.xgboost.rbv2 Regression XGBoost with RandomBot regr.xgboost 13\n key label learner n_values\n\n\nWe can use the sugar function lts() to retrieve a TuningSpace.\n\ntuning_space_rpart = lts(\"classif.rpart.default\")\ntuning_space_rpart\n\n<TuningSpace:classif.rpart.default>: Classification Rpart with Default\n id lower upper levels logscale\n1: minsplit 2e+00 128.0 TRUE\n2: minbucket 1e+00 64.0 TRUE\n3: cp 1e-04 0.1 TRUE\n\n\nThe $values slot contains the list of of TuneToken.\n\ntuning_space_rpart$values\n\n$minsplit\nTuning over:\nrange [2, 128] (log scale)\n\n\n$minbucket\nTuning over:\nrange [1, 64] (log scale)\n\n\n$cp\nTuning over:\nrange [1e-04, 0.1] (log scale)\n\n\nWe apply the search space and tune the learner.\n\nlearner = lrn(\"classif.rpart\")\n\nlearner$param_set$values = tuning_space_rpart$values\n\ninstance = tune(\n tuner = tnr(\"random_search\"),\n task = tsk(\"pima\"),\n learner = learner,\n resampling = rsmp (\"holdout\"),\n measure = msr(\"classif.ce\"),\n term_evals = 10)\n\ninstance$result\n\n minsplit minbucket cp learner_param_vals x_domain classif.ce\n1: 3.40059 1.963618 -4.114895 <list[3]> <list[3]> 0.2539062\n\n\nWe can also get the learner with search space already applied from the TuningSpace.\n\nlearner = tuning_space_rpart$get_learner()\nprint(learner$param_set)\n\n<ParamSet>\n id class lower upper nlevels default value\n 1: cp ParamDbl 0 1 Inf 0.01 <RangeTuneToken[2]>\n 2: keep_model ParamLgl NA NA 2 FALSE \n 3: maxcompete ParamInt 0 Inf Inf 4 \n 4: maxdepth ParamInt 1 30 30 30 \n 5: maxsurrogate ParamInt 0 Inf Inf 5 \n 6: minbucket ParamInt 1 Inf Inf <NoDefault[3]> <RangeTuneToken[2]>\n 7: minsplit ParamInt 1 Inf Inf 20 <RangeTuneToken[2]>\n 8: surrogatestyle ParamInt 0 1 2 0 \n 9: usesurrogate ParamInt 0 2 3 2 \n10: xval ParamInt 0 Inf Inf 10 0\n\n\nThis method also allows to set constant parameters.\n\nlearner = tuning_space_rpart$get_learner(maxdepth = 15)\nprint(learner$param_set)\n\n<ParamSet>\n id class lower upper nlevels default value\n 1: cp ParamDbl 0 1 Inf 0.01 <RangeTuneToken[2]>\n 2: keep_model ParamLgl NA NA 2 FALSE \n 3: maxcompete ParamInt 0 Inf Inf 4 \n 4: maxdepth ParamInt 1 30 30 30 15\n 5: maxsurrogate ParamInt 0 Inf Inf 5 \n 6: minbucket ParamInt 1 Inf Inf <NoDefault[3]> <RangeTuneToken[2]>\n 7: minsplit ParamInt 1 Inf Inf 20 <RangeTuneToken[2]>\n 8: surrogatestyle ParamInt 0 1 2 0 \n 9: usesurrogate ParamInt 0 2 3 2 \n10: xval ParamInt 0 Inf Inf 10 0\n\n\nThe lts() function sets the default search space directly to a learner.\n\nlearner = lts(lrn(\"classif.rpart\", maxdepth = 15))\nprint(learner$param_set)\n\n<ParamSet>\n id class lower upper nlevels default value\n 1: cp ParamDbl 0 1 Inf 0.01 <RangeTuneToken[2]>\n 2: keep_model ParamLgl NA NA 2 FALSE \n 3: maxcompete ParamInt 0 Inf Inf 4 \n 4: maxdepth ParamInt 1 30 30 30 15\n 5: maxsurrogate ParamInt 0 Inf Inf 5 \n 6: minbucket ParamInt 1 Inf Inf <NoDefault[3]> <RangeTuneToken[2]>\n 7: minsplit ParamInt 1 Inf Inf 20 <RangeTuneToken[2]>\n 8: surrogatestyle ParamInt 0 1 2 0 \n 9: usesurrogate ParamInt 0 2 3 2 \n10: xval ParamInt 0 Inf Inf 10 0" + }, + { + "objectID": "gallery/optimization/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/index.html", + "href": "gallery/optimization/2021-03-09-practical-tuning-series-tune-a-support-vector-machine/index.html", + "title": "Practical Tuning Series - Tune a Support Vector Machine", + "section": "", + "text": "requireNamespace(\"DiceKriging\")\n\nLoading required namespace: DiceKriging\n\n\n\nScope\nThis is the first part of the practical tuning series. The other parts can be found here:\n\nPart II - Tune a Preprocessing Pipeline\nPart III - Build an Automated Machine Learning System\nPart IV - Tuning and Parallel Processing\n\nIn this post, we demonstrate how to optimize the hyperparameters of a support vector machine (SVM). We are using the mlr3 machine learning framework with the mlr3tuning extension package.\nFirst, we start by showing the basic building blocks of mlr3tuning and tune the cost and gamma hyperparameters of an SVM with a radial basis function on the Iris data set. After that, we use transformations to tune the both hyperparameters on the logarithmic scale. Next, we explain the importance of dependencies to tune hyperparameters like degree which are dependent on the choice of kernel. After that, we fit an SVM with optimized hyperparameters on the full dataset. Finally, nested resampling is used to compute an unbiased performance estimate of our tuned SVM.\n\n\nPrerequisites\nWe load the mlr3verse package which pulls in the most important packages for this example.\n\nlibrary(mlr3verse)\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented. The lgr package is used for logging in all mlr3 packages. The mlr3 logger prints the logging messages from the base package, whereas the bbotk logger is responsible for logging messages from the optimization packages (e.g. mlr3tuning ).\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\nlgr::get_logger(\"bbotk\")$set_threshold(\"warn\")\n\nIn the example, we use the Iris data set which classifies 150 flowers in three species of Iris. The flowers are characterized by sepal length and width and petal length and width. The Iris data set allows us to quickly fit models to it. However, the influence of hyperparameter tuning on the predictive performance might be minor. Other data sets might give more meaningful tuning results.\n\n# retrieve the task from mlr3\ntask = tsk(\"iris\")\n\n# generate a quick textual overview using the skimr package\nskimr::skim(task$data())\n\n\nData summary\n\n\nName\ntask$data()\n\n\nNumber of rows\n150\n\n\nNumber of columns\n5\n\n\nKey\nNULL\n\n\n_______________________\n\n\n\nColumn type frequency:\n\n\n\nfactor\n1\n\n\nnumeric\n4\n\n\n________________________\n\n\n\nGroup variables\nNone\n\n\n\nVariable type: factor\n\n\n\n\n\n\n\n\n\n\n\nskim_variable\nn_missing\ncomplete_rate\nordered\nn_unique\ntop_counts\n\n\n\n\nSpecies\n0\n1\nFALSE\n3\nset: 50, ver: 50, vir: 50\n\n\n\nVariable type: numeric\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nskim_variable\nn_missing\ncomplete_rate\nmean\nsd\np0\np25\np50\np75\np100\nhist\n\n\n\n\nPetal.Length\n0\n1\n3.76\n1.77\n1.0\n1.6\n4.35\n5.1\n6.9\n▇▁▆▇▂\n\n\nPetal.Width\n0\n1\n1.20\n0.76\n0.1\n0.3\n1.30\n1.8\n2.5\n▇▁▇▅▃\n\n\nSepal.Length\n0\n1\n5.84\n0.83\n4.3\n5.1\n5.80\n6.4\n7.9\n▆▇▇▅▂\n\n\nSepal.Width\n0\n1\n3.06\n0.44\n2.0\n2.8\n3.00\n3.3\n4.4\n▁▆▇▂▁\n\n\n\n\n\nWe choose the support vector machine implementation from the e1071 package (which is based on LIBSVM) and use it as a classification machine by setting type to \"C-classification\".\n\nlearner = lrn(\"classif.svm\", type = \"C-classification\", kernel = \"radial\")\n\n\n\nTuning Search Space\nFor tuning, it is important to create a search space that defines the type and range of the hyperparameters. A learner stores all information about its hyperparameters in the slot $param_set. Not all parameters are tunable. We have to choose a subset of the hyperparameters we want to tune.\n\nas.data.table(learner$param_set)[, .(id, class, lower, upper, nlevels)]\n\nWe use the to_tune() function to define the range over which the hyperparameter should be tuned. We opt for the cost and gamma hyperparameters of the radial kernel and set the tuning ranges with lower and upper bounds.\n\nlearner$param_set$values$cost = to_tune(0.1, 10)\nlearner$param_set$values$gamma = to_tune(0, 5)\n\n\n\nTuning\nWe specify how to evaluate the performance of the different hyperparameter configurations. For this, we choose 3-fold cross validation as the resampling strategy and the classification error as the performance measure.\n\nresampling = rsmp(\"cv\", folds = 3)\nmeasure = msr(\"classif.ce\")\n\nUsually, we have to select a budget for the tuning. This is done by choosing a Terminator, which stops the tuning e.g. after a performance level is reached or after a given time. However, some tuners like grid search terminate themselves. In this case, we choose a terminator that never stops and the tuning is not stopped before all grid points are evaluated.\n\nterminator = trm(\"none\")\n\nAt this point, we can construct a TuningInstanceSingleCrit that describes the tuning problem.\n\ninstance = TuningInstanceSingleCrit$new(\n task = task,\n learner = learner,\n resampling = resampling,\n measure = measure,\n terminator = terminator\n)\n\nprint(instance)\n\n<TuningInstanceSingleCrit>\n* State: Not optimized\n* Objective: <ObjectiveTuning:classif.svm_on_iris>\n* Search Space:\n id class lower upper nlevels\n1: cost ParamDbl 0.1 10 Inf\n2: gamma ParamDbl 0.0 5 Inf\n* Terminator: <TerminatorNone>\n\n\nFinally, we have to choose a Tuner. Grid Search discretizes numeric parameters into a given resolution and constructs a grid from the Cartesian product of these sets. Categorical parameters produce a grid over all levels specified in the search space. In this example, we only use a resolution of 5 to keep the runtime low. Usually, a higher resolution is used to create a denser grid.\n\ntuner = tnr(\"grid_search\", resolution = 5)\n\nprint(tuner)\n\n<TunerGridSearch>: Grid Search\n* Parameters: resolution=5, batch_size=1\n* Parameter classes: ParamLgl, ParamInt, ParamDbl, ParamFct\n* Properties: dependencies, single-crit, multi-crit\n* Packages: mlr3tuning\n\n\nWe can preview the proposed configurations by using generate_design_grid(). This function is internally executed by TunerGridSearch.\n\ngenerate_design_grid(learner$param_set$search_space(), resolution = 5)\n\n<Design> with 25 rows:\n cost gamma\n 1: 0.100 0.00\n 2: 0.100 1.25\n 3: 0.100 2.50\n 4: 0.100 3.75\n 5: 0.100 5.00\n 6: 2.575 0.00\n 7: 2.575 1.25\n 8: 2.575 2.50\n 9: 2.575 3.75\n10: 2.575 5.00\n11: 5.050 0.00\n12: 5.050 1.25\n13: 5.050 2.50\n14: 5.050 3.75\n15: 5.050 5.00\n16: 7.525 0.00\n17: 7.525 1.25\n18: 7.525 2.50\n19: 7.525 3.75\n20: 7.525 5.00\n21: 10.000 0.00\n22: 10.000 1.25\n23: 10.000 2.50\n24: 10.000 3.75\n25: 10.000 5.00\n cost gamma\n\n\nWe trigger the tuning by passing the TuningInstanceSingleCrit to the $optimize() method of the Tuner. The instance is modified in-place.\n\ntuner$optimize(instance)\n\n cost gamma learner_param_vals x_domain classif.ce\n1: 5.05 1.25 <list[4]> <list[2]> 0.06\n\n\nWe plot the performances depending on the evaluated cost and gamma values.\n\nautoplot(instance, type = \"surface\", cols_x = c(\"cost\", \"gamma\"),\n learner = lrn(\"regr.km\"))\n\n\n\n\n\n\n\n\n\n\nThe points mark the evaluated cost and gamma values. We should not infer the performance of new values from the heatmap since it is only an interpolation. However, we can see the general interaction between the hyperparameters.\nTuning a learner can be shortened by using the tune()-shortcut.\n\nlearner = lrn(\"classif.svm\", type = \"C-classification\", kernel = \"radial\")\nlearner$param_set$values$cost = to_tune(0.1, 10)\nlearner$param_set$values$gamma = to_tune(0, 5)\n\ninstance = tune(\n tuner = tnr(\"grid_search\", resolution = 5),\n task = tsk(\"iris\"),\n learner = learner,\n resampling = rsmp (\"holdout\"),\n measure = msr(\"classif.ce\")\n)\n\n\n\nTransformation\nNext, we want to tune the cost and gamma hyperparameter more efficiently. It is recommended to tune cost and gamma on the logarithmic scale (Hsu, Chang, and Lin 2003). The log transformation emphasizes smaller cost and gamma values but also creates large values. Therefore, we use a log transformation to emphasize this region of the search space with a denser grid.\nGenerally speaking, transformations can be used to convert hyperparameters to a new scale. These transformations are applied before the proposed configuration is passed to the Learner. We can directly define the transformation in the to_tune() function. The lower and upper bound is set on the original scale.\n\nlearner = lrn(\"classif.svm\", type = \"C-classification\", kernel = \"radial\")\n\n# tune from 2^-15 to 2^15 on a log scale\nlearner$param_set$values$cost = to_tune(p_dbl(-15, 15, trafo = function(x) 2^x))\n\n# tune from 2^-15 to 2^5 on a log scale\nlearner$param_set$values$gamma = to_tune(p_dbl(-15, 5, trafo = function(x) 2^x))\n\nTransformations to the log scale are the ones most commonly used. We can use a shortcut for this transformation. The lower and upper bound is set on the transformed scale.\n\nlearner$param_set$values$cost = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))\nlearner$param_set$values$gamma = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))\n\nWe use the tune()-shortcut to run the tuning.\n\ninstance = tune(\n tuner = tnr(\"grid_search\", resolution = 5),\n task = task,\n learner = learner,\n resampling = resampling,\n measure = measure\n)\n\nThe hyperparameter values after the transformation are stored in the x_domain column as lists. We can expand these lists into multiple columns by using as.data.table(). The hyperparameter names are prefixed by x_domain.\n\nas.data.table(instance$archive)[, .(cost, gamma, x_domain_cost, x_domain_gamma)]\n\n cost gamma x_domain_cost x_domain_gamma\n 1: -5.756463 -11.512925 3.162278e-03 1.000000e-05\n 2: 0.000000 11.512925 1.000000e+00 1.000000e+05\n 3: -11.512925 11.512925 1.000000e-05 1.000000e+05\n 4: 11.512925 5.756463 1.000000e+05 3.162278e+02\n 5: -11.512925 0.000000 1.000000e-05 1.000000e+00\n 6: 11.512925 -5.756463 1.000000e+05 3.162278e-03\n 7: 11.512925 0.000000 1.000000e+05 1.000000e+00\n 8: -11.512925 5.756463 1.000000e-05 3.162278e+02\n 9: 0.000000 0.000000 1.000000e+00 1.000000e+00\n10: 5.756463 0.000000 3.162278e+02 1.000000e+00\n11: 0.000000 -5.756463 1.000000e+00 3.162278e-03\n12: 0.000000 -11.512925 1.000000e+00 1.000000e-05\n13: -5.756463 -5.756463 3.162278e-03 3.162278e-03\n14: 11.512925 -11.512925 1.000000e+05 1.000000e-05\n15: 5.756463 11.512925 3.162278e+02 1.000000e+05\n16: 0.000000 5.756463 1.000000e+00 3.162278e+02\n17: -5.756463 0.000000 3.162278e-03 1.000000e+00\n18: 5.756463 -11.512925 3.162278e+02 1.000000e-05\n19: -5.756463 11.512925 3.162278e-03 1.000000e+05\n20: 11.512925 11.512925 1.000000e+05 1.000000e+05\n21: 5.756463 -5.756463 3.162278e+02 3.162278e-03\n22: -11.512925 -11.512925 1.000000e-05 1.000000e-05\n23: -11.512925 -5.756463 1.000000e-05 3.162278e-03\n24: 5.756463 5.756463 3.162278e+02 3.162278e+02\n25: -5.756463 5.756463 3.162278e-03 3.162278e+02\n cost gamma x_domain_cost x_domain_gamma\n\n\nWe plot the performances depending on the evaluated cost and gamma values.\n\nlibrary(ggplot2)\nlibrary(scales)\nautoplot(instance, type = \"points\", cols_x = c(\"x_domain_cost\", \"x_domain_gamma\")) +\n scale_x_continuous(\n trans = log2_trans(),\n breaks = trans_breaks(\"log10\", function(x) 10^x),\n labels = trans_format(\"log10\", math_format(10^.x))) +\n scale_y_continuous(\n trans = log2_trans(),\n breaks = trans_breaks(\"log10\", function(x) 10^x),\n labels = trans_format(\"log10\", math_format(10^.x)))\n\n\n\n\n\n\n\n\n\n\nDependencies\nDependencies ensure that certain parameters are only proposed depending on values of other hyperparameters. We want to tune the degree hyperparameter that is only needed for the polynomial kernel.\n\nlearner = lrn(\"classif.svm\", type = \"C-classification\")\n\nlearner$param_set$values$cost = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))\nlearner$param_set$values$gamma = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))\n\nlearner$param_set$values$kernel = to_tune(c(\"polynomial\", \"radial\"))\nlearner$param_set$values$degree = to_tune(1, 4)\n\nThe dependencies are already stored in the learner parameter set.\n\nlearner$param_set$deps\n\n id on cond\n1: cost type <CondEqual[9]>\n2: nu type <CondEqual[9]>\n3: degree kernel <CondEqual[9]>\n4: coef0 kernel <CondAnyOf[9]>\n5: gamma kernel <CondAnyOf[9]>\n\n\nThe gamma hyperparameter depends on the kernel being polynomial, radial or sigmoid\n\nlearner$param_set$deps$cond[[5]]\n\nCondAnyOf: x ∈ {polynomial, radial, sigmoid}\n\n\nwhereas the degree hyperparameter is solely used by the polynomial kernel.\n\nlearner$param_set$deps$cond[[3]]\n\nCondEqual: x = polynomial\n\n\nWe preview the grid to show the effect of the dependencies.\n\ngenerate_design_grid(learner$param_set$search_space(), resolution = 2)\n\n<Design> with 12 rows:\n cost gamma kernel degree\n 1: -11.51293 -11.51293 polynomial 1\n 2: -11.51293 -11.51293 polynomial 4\n 3: -11.51293 -11.51293 radial NA\n 4: -11.51293 11.51293 polynomial 1\n 5: -11.51293 11.51293 polynomial 4\n 6: -11.51293 11.51293 radial NA\n 7: 11.51293 -11.51293 polynomial 1\n 8: 11.51293 -11.51293 polynomial 4\n 9: 11.51293 -11.51293 radial NA\n10: 11.51293 11.51293 polynomial 1\n11: 11.51293 11.51293 polynomial 4\n12: 11.51293 11.51293 radial NA\n\n\nThe value for degree is NA if the dependency on the kernel is not satisfied.\nWe use the tune()-shortcut to run the tuning.\n\ninstance = tune(\n tuner = tnr(\"grid_search\", resolution = 3),\n task = task,\n learner = learner,\n resampling = resampling,\n measure = measure\n)\n\n\ninstance$result\n\n cost gamma kernel degree learner_param_vals x_domain classif.ce\n1: 0 11.51293 polynomial 1 <list[5]> <list[4]> 0.02666667\n\n\n\n\nFinal Model\nWe add the optimized hyperparameters to the learner and train the learner on the full dataset.\n\nlearner = lrn(\"classif.svm\")\nlearner$param_set$values = instance$result_learner_param_vals\nlearner$train(task)\n\nThe trained model can now be used to make predictions on new data. A common mistake is to report the performance estimated on the resampling sets on which the tuning was performed (instance$result_y) as the model’s performance. These scores might be biased and overestimate the ability of the fitted model to predict with new data. Instead, we have to use nested resampling to get an unbiased performance estimate.\n\n\nNested Resampling\nTuning should not be performed on the same resampling sets which are used for evaluating the model itself, since this would result in a biased performance estimate. Nested resampling uses an outer and inner resampling to separate the tuning from the performance estimation of the model. We can use the AutoTuner class for running nested resampling. The AutoTuner wraps a Learner and tunes the hyperparameter of the learner during $train(). This is our inner resampling loop.\n\nlearner = lrn(\"classif.svm\", type = \"C-classification\")\nlearner$param_set$values$cost = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))\nlearner$param_set$values$gamma = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))\nlearner$param_set$values$kernel = to_tune(c(\"polynomial\", \"radial\"))\nlearner$param_set$values$degree = to_tune(1, 4)\n\nresampling_inner = rsmp(\"cv\", folds = 3)\nterminator = trm(\"none\")\ntuner = tnr(\"grid_search\", resolution = 3)\n\nat = AutoTuner$new(\n learner = learner,\n resampling = resampling_inner,\n measure = measure,\n terminator = terminator,\n tuner = tuner,\n store_models = TRUE)\n\nWe put the AutoTuner into a resample() call to get the outer resampling loop.\n\nresampling_outer = rsmp(\"cv\", folds = 3)\nrr = resample(task = task, learner = at, resampling = resampling_outer, store_models = TRUE)\n\nWe check the inner tuning results for stable hyperparameters. This means that the selected hyperparameters should not vary too much. We might observe unstable models in this example because the small data set and the low number of resampling iterations might introduce too much randomness. Usually, we aim for the selection of stable hyperparameters for all outer training sets.\n\nextract_inner_tuning_results(rr)[, .SD, .SDcols = !c(\"learner_param_vals\", \"x_domain\")]\n\n iteration cost gamma kernel degree classif.ce task_id learner_id resampling_id\n1: 1 0.00000 0.00000 polynomial 1 0.03000594 iris classif.svm.tuned cv\n2: 2 0.00000 0.00000 polynomial 1 0.03000594 iris classif.svm.tuned cv\n3: 3 11.51293 -11.51293 radial NA 0.02020202 iris classif.svm.tuned cv\n\n\nNext, we want to compare the predictive performances estimated on the outer resampling to the inner resampling (extract_inner_tuning_results(rr)). Significantly lower predictive performances on the outer resampling indicate that the models with the optimized hyperparameters overfit the data.\n\nrr$score()[, .(iteration, task_id, learner_id, resampling_id, classif.ce)]\n\n iteration task_id learner_id resampling_id classif.ce\n1: 1 iris classif.svm.tuned cv 0.04\n2: 2 iris classif.svm.tuned cv 0.06\n3: 3 iris classif.svm.tuned cv 0.00\n\n\nThe archives of the AutoTuners allows us to inspect all evaluated hyperparameters configurations with the associated predictive performances.\n\nextract_inner_tuning_archives(rr, unnest = NULL, exclude_columns = c(\"resample_result\", \"uhash\", \"x_domain\", \"timestamp\"))\n\n iteration cost gamma kernel degree classif.ce runtime_learners batch_nr warnings errors task_id\n 1: 1 0.00000 -11.51293 polynomial 2 0.68033274 0.017 1 0 0 iris\n 2: 1 0.00000 -11.51293 radial NA 0.64111705 0.017 2 0 0 iris\n 3: 1 0.00000 0.00000 polynomial 1 0.03000594 0.017 3 0 0 iris\n 4: 1 11.51293 0.00000 polynomial 1 0.05050505 0.012 4 0 0 iris\n 5: 1 11.51293 11.51293 radial NA 0.66013072 0.014 5 0 0 iris\n --- \n104: 3 11.51293 -11.51293 polynomial 2 0.68924540 0.013 32 0 0 iris\n105: 3 -11.51293 -11.51293 radial NA 0.68924540 0.012 33 0 0 iris\n106: 3 -11.51293 11.51293 polynomial 4 0.11883541 0.015 34 0 0 iris\n107: 3 0.00000 -11.51293 polynomial 4 0.68924540 0.015 35 0 0 iris\n108: 3 11.51293 11.51293 polynomial 1 0.06951872 0.725 36 0 0 iris\n learner_id resampling_id\n 1: classif.svm.tuned cv\n 2: classif.svm.tuned cv\n 3: classif.svm.tuned cv\n 4: classif.svm.tuned cv\n 5: classif.svm.tuned cv\n --- \n104: classif.svm.tuned cv\n105: classif.svm.tuned cv\n106: classif.svm.tuned cv\n107: classif.svm.tuned cv\n108: classif.svm.tuned cv\n\n\nThe aggregated performance of all outer resampling iterations is essentially the unbiased performance of an SVM with optimal hyperparameter found by grid search.\n\nrr$aggregate()\n\nclassif.ce \n0.03333333 \n\n\nApplying nested resampling can be shortened by using the tune_nested()-shortcut.\n\nlearner = lrn(\"classif.svm\", type = \"C-classification\")\nlearner$param_set$values$cost = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))\nlearner$param_set$values$gamma = to_tune(p_dbl(1e-5, 1e5, logscale = TRUE))\nlearner$param_set$values$kernel = to_tune(c(\"polynomial\", \"radial\"))\nlearner$param_set$values$degree = to_tune(1, 4)\n\nrr = tune_nested(\n tuner = tnr(\"grid_search\", resolution = 3),\n task = tsk(\"iris\"),\n learner = learner,\n inner_resampling = rsmp (\"cv\", folds = 3),\n outer_resampling = rsmp(\"cv\", folds = 3),\n measure = msr(\"classif.ce\"),\n)\n\n\n\nResources\nThe mlr3book includes chapters on tuning spaces and hyperparameter tuning. The mlr3cheatsheets contain frequently used commands and workflows of mlr3.\n\n\n\n\n\nReferences\n\nHsu, Chih-wei, Chih-chung Chang, and Chih-Jen Lin. 2003. “A Practical Guide to Support Vector Classification.”" + }, + { + "objectID": "gallery/optimization/2023-01-16-hotstart/index.html", + "href": "gallery/optimization/2023-01-16-hotstart/index.html", + "title": "Hotstarting", + "section": "", + "text": "Scope\nHotstarting a learner resumes the training from an already fitted model. An example would be to train an already fit XGBoost model for an additional 500 boosting iterations. In mlr3, we call this process Hotstarting, where a learner has access to a cache of already trained models which is called a mlr3::HoststartStack We distinguish between forward and backward hotstarting. We start this post with backward hotstarting and then talk about the less efficient forward hotstarting.\n\n\nBackward Hotstarting\nIn this example, we optimize the hyperparameters of a random forest and use hotstarting to reduce the runtime. Hotstarting a random forest backwards is very simple. The model remains unchanged and only a subset of the trees is used for prediction i.e. a new model is not fitted. For example, a random forest is trained with 1000 trees and a specific hyperparameter configuration. If another random forest with 500 trees but with the same hyperparameter configuration has to be trained, the model with 1000 trees is copied and only 500 trees are used for prediction.\nWe load the ranger learner and set the search space from the Bischl et al. (2021) article.\n\nlibrary(mlr3verse)\n\nlearner = lrn(\"classif.ranger\",\n mtry.ratio = to_tune(0, 1),\n replace = to_tune(),\n sample.fraction = to_tune(1e-1, 1),\n num.trees = to_tune(1, 2000)\n)\n\nWe activate hotstarting with the allow_hotstart option. When running a grid search with hotstarting, the grid is sorted by the hot start parameter. This means the models with 2000 trees are trained first. The models with less than 2000 trees hot start on the 2000 trees models which allows the training to be completed immediately.\n\ninstance = tune(\n tuner = tnr(\"grid_search\", resolution = 5, batch_size = 5),\n task = tsk(\"spam\"),\n learner = learner,\n resampling = rsmp(\"holdout\"),\n measure = msr(\"classif.ce\"),\n allow_hotstart = TRUE\n)\n\nFor comparison, we perform the same tuning without hotstarting.\n\ninstance_2 = tune(\n tuner = tnr(\"grid_search\", resolution = 5, batch_size = 5),\n task = tsk(\"spam\"),\n learner = learner,\n resampling = rsmp(\"holdout\"),\n measure = msr(\"classif.ce\"),\n allow_hotstart = FALSE\n)\n\nWe plot the time of completion of each batch (see Figure 1). Each batch includes 5 configurations. We can see that tuning with hotstarting is slower at first. As soon as all models are fitted with 2000 trees, the tuning runs much faster and overtakes the tuning without hotstarting.\n\n\n\n\n\n\n\n\nFigure 1: Time of completion of each batch with and without hotstarting.\n\n\n\n\n\n\n\nForward Hotstarting\nForward hotstarting is currently only supported by XGBoost. However, we have observed that hotstarting only provides a speed advantage for very large datasets and models with more than 5000 boosting rounds. The reason is that copying the models from the main process to the workers is a major bottleneck. The parallelization package future copies the models sequentially to the workers. Consequently, it takes a long time until the last worker can even start. Moreover, copying itself consumes a lot of time, and copying the model back from the worker blocks the main process again. During the development process, we overestimated the speed benefits of hotstarting and underestimated the overhead of parallelization. We can therefore only advise against using forward hotstarting during tuning. It is much more efficient to use the internal early-stopping mechanism of XGBoost. This eliminates the need to copy models to the worker. See the gallery post on early stopping for an example. We might improve the efficiency of the hotstarting mechanism in the future, if there are convincing use cases.\n\n\nManual Hotstarting\nNevertheless, forward hotstarting can be useful without parallelization. If you have an already trained model and want to add more boosting iteration to it. In this example, the learner_5000 is the already trained model. We create a new learner with the same hyperparameters but double the number of boosting iteration. To activate hotstarting, we create a HotstartStack and copy it to the $hotstart_stack slot of the new learner.\n\ntask = tsk(\"spam\")\n\nlearner_5000 = lrn(\"classif.xgboost\", nrounds = 5000, eta = 0.1)\nlearner_5000$train(task)\n\nlearner_10000 = lrn(\"classif.xgboost\", nrounds = 10000, eta = 0.1)\nlearner_10000$hotstart_stack = HotstartStack$new(learner_5000)\nlearner_10000$train(task)\n\nTraining the initial model took 59.885 seconds.\n\nlearner_5000$state$train_time\n\n[1] 59.885\n\n\nAdding 5000 boosting rounds took 46.837 seconds.\n\nlearner_10000$state$train_time - learner_5000$state$train_time\n\n[1] 46.837\n\n\nTraining the model from the beginning would have taken about two minutes. This means, without parallelization, we get the expected speed advantage.\n\n\nConclusion\nWe have seen how mlr3 enables to reduce the training time, by building on a hotstart stack of already trained learners. One has to be careful, however, when using forward hotstarting during tuning because of the high parallelization overhead that arises from copying the models between the processes. If a model has an internal early stopping implementation, it should usually be relied upon instead of using the mlr3 hotstarting mechanism. However, manual forward hotstarting can be helpful in some situations when we do not want to train a large model from the beginning.\n\n\n\n\n\nReferences\n\nBischl, Bernd, Martin Binder, Michel Lang, Tobias Pielok, Jakob Richter, Stefan Coors, Janek Thomas, et al. 2021. “Hyperparameter Optimization: Foundations, Algorithms, Best Practices and Open Challenges.” arXiv:2107.05847 [Cs, Stat], July. http://arxiv.org/abs/2107.05847." + }, + { + "objectID": "gallery/optimization/2023-02-01-shadow-variable-search/index.html", + "href": "gallery/optimization/2023-02-01-shadow-variable-search/index.html", + "title": "Shadow Variable Search on the Pima Indian Diabetes Data Set", + "section": "", + "text": "Scope\nFeature selection is the process of finding an optimal set of features to improve the performance, interpretability and robustness of machine learning algorithms. In this article, we introduce the Shadow Variable Search algorithm which is a wrapper method for feature selection. Wrapper methods iteratively add features to the model that optimize a performance measure. As an example, we will search for the optimal set of features for a support vector machine on the Pima Indian Diabetes data set. We assume that you are already familiar with the basic building blocks of the mlr3 ecosystem. If you are new to feature selection, we recommend reading the feature selection chapter of the mlr3book first. Some knowledge about mlr3pipelines is beneficial but not necessary to understand the example.\n\n\nShadow Variable Search\nAdding shadow variables to a data set is a well-known method in machine learning (Wu, Boos, and Stefanski 2007; Thomas et al. 2017). The idea is to add permutated copies of the original features to the data set. These permutated copies are called shadow variables or pseudovariables and the permutation breaks any relationship with the target variable, making them useless for prediction. The subsequent search is similar to the sequential forward selection algorithm, where one new feature is added in each iteration of the algorithm. This new feature is selected as the one that improves the performance of the model the most. This selection is computationally expensive, as one model for each of the not yet included features has to be trained. The difference between shadow variable search and sequential forward selection is that the former uses the selection of a shadow variable as the termination criterion. Selecting a shadow variable means that the best improvement is achieved by adding a feature that is unrelated to the target variable. Consequently, the variables not yet selected are most likely also correlated to the target variable only by chance. Therefore, only the previously selected features have a true influence on the target variable.\nmlr3fselect is the feature selection package of the mlr3 ecosystem. It implements the shadow variable search algorithm. We load all packages of the ecosystem with the mlr3verse package.\n\nlibrary(mlr3verse)\n\nWe retrieve the shadow variable search optimizer with the fs() function. The algorithm has no control parameters.\n\noptimizer = fs(\"shadow_variable_search\")\n\n\n\nTask and Learner\nThe objective of the Pima Indian Diabetes data set is to predict whether a person has diabetes or not. The data set includes 768 patients with 8 measurements (see Figure 1).\n\ntask = tsk(\"pima\")\n\n\n\nCode\nlibrary(ggplot2)\nlibrary(data.table)\n\ndata = melt(as.data.table(task), id.vars = task$target_names, measure.vars = task$feature_names)\n\nggplot(data, aes(x = value, fill = diabetes)) +\n geom_density(alpha = 0.5) +\n facet_wrap(~ variable, ncol = 8, scales = \"free\") +\n scale_fill_viridis_d(end = 0.8) +\n theme_minimal() +\n theme(axis.title.x = element_blank())\n\n\n\n\n\n\n\n\nFigure 1: Distribution of the features in the Pima Indian Diabetes data set.\n\n\n\n\n\nThe data set contains missing values.\n\ntask$missings()\n\ndiabetes age glucose insulin mass pedigree pregnant pressure triceps \n 0 0 5 374 11 0 0 35 227 \n\n\nSupport vector machines cannot handle missing values. We impute the missing values with the histogram imputation method.\n\nlearner = po(\"imputehist\") %>>% lrn(\"classif.svm\", predict_type = \"prob\")\n\n\n\nFeature Selection\nNow we define the feature selection problem by using the fsi() function that constructs an FSelectInstanceSingleCrit. In addition to the task and learner, we have to select a resampling strategy and performance measure to determine how the performance of a feature subset is evaluated. We pass the \"none\" terminator because the shadow variable search algorithm terminates by itself.\n\ninstance = fsi(\n task = task,\n learner = learner,\n resampling = rsmp(\"cv\", folds = 3),\n measures = msr(\"classif.auc\"),\n terminator = trm(\"none\")\n)\n\nWe are now ready to start the shadow variable search. To do this, we simply pass the instance to the $optimize() method of the optimizer.\n\noptimizer$optimize(instance)\n\n age glucose insulin mass pedigree pregnant pressure triceps features classif.auc\n1: TRUE TRUE FALSE TRUE TRUE FALSE FALSE FALSE age,glucose,mass,pedigree 0.835165\n\n\nThe optimizer returns the best feature set and the corresponding estimated performance.\nFigure 2 shows the optimization path of the feature selection. The feature glucose was selected first and in the following iterations age, mass and pedigree. Then a shadow variable was selected and the feature selection was terminated.\n\n\nCode\nlibrary(data.table)\nlibrary(ggplot2)\nlibrary(mlr3misc)\nlibrary(viridisLite)\n\ndata = as.data.table(instance$archive)[order(-classif.auc), head(.SD, 1), by = batch_nr][order(batch_nr)]\ndata[, features := map_chr(features, str_collapse)]\ndata[, batch_nr := as.character(batch_nr)]\n\nggplot(data, aes(x = batch_nr, y = classif.auc)) +\n geom_bar(\n stat = \"identity\",\n width = 0.5,\n fill = viridis(1, begin = 0.5),\n alpha = 0.8) +\n geom_text(\n data = data,\n mapping = aes(x = batch_nr, y = 0, label = features),\n hjust = 0,\n nudge_y = 0.05,\n color = \"white\",\n size = 5\n ) +\n coord_flip() +\n xlab(\"Iteration\") +\n theme_minimal()\n\n\n\n\n\n\n\n\nFigure 2: Optimization path of the shadow variable search.\n\n\n\n\n\nThe archive contains all evaluated feature sets. We can see that each feature has a corresponding shadow variable. We only show the variables age, glucose and insulin and their shadow variables here.\n\nas.data.table(instance$archive)[, .(age, glucose, insulin, permuted__age, permuted__glucose, permuted__insulin, classif.auc)]\n\n age glucose insulin permuted__age permuted__glucose permuted__insulin classif.auc\n 1: TRUE FALSE FALSE FALSE FALSE FALSE 0.6437052\n 2: FALSE TRUE FALSE FALSE FALSE FALSE 0.7598155\n 3: FALSE FALSE TRUE FALSE FALSE FALSE 0.4900280\n 4: FALSE FALSE FALSE FALSE FALSE FALSE 0.6424026\n 5: FALSE FALSE FALSE FALSE FALSE FALSE 0.5690107\n--- \n54: TRUE TRUE FALSE FALSE FALSE FALSE 0.8266713\n55: TRUE TRUE FALSE FALSE FALSE FALSE 0.8063568\n56: TRUE TRUE FALSE FALSE FALSE FALSE 0.8244232\n57: TRUE TRUE FALSE FALSE FALSE FALSE 0.8234605\n58: TRUE TRUE FALSE FALSE FALSE FALSE 0.8164784\n\n\n\n\nFinal Model\nThe learner we use to make predictions on new data is called the final model. The final model is trained with the optimal feature set on the full data set. We subset the task to the optimal feature set and train the learner.\n\ntask$select(instance$result_feature_set)\nlearner$train(task)\n\nThe trained model can now be used to predict new, external data.\n\n\nConclusion\nThe shadow variable search is a fast feature selection method that is easy to use. More information on the theoretical background can be found in Wu, Boos, and Stefanski (2007) and Thomas et al. (2017). If you want to know more about feature selection in general, we recommend having a look at our book.\n\n\n\n\n\nReferences\n\nThomas, Janek, Tobias Hepp, Andreas Mayr, and Bernd Bischl. 2017. “Probing for Sparse and Fast Variable Selection with Model-Based Boosting.” Computational and Mathematical Methods in Medicine 2017 (July): e1421409. https://doi.org/10.1155/2017/1421409.\n\n\nWu, Yujun, Dennis D Boos, and Leonard A Stefanski. 2007. “Controlling Variable Selection by the Addition of Pseudovariables.” Journal of the American Statistical Association 102 (477): 235–43. https://doi.org/10.1198/016214506000000843." + }, + { + "objectID": "gallery/optimization/2023-01-15-hyperband-xgboost/index.html", + "href": "gallery/optimization/2023-01-15-hyperband-xgboost/index.html", + "title": "Hyperband Series - Iterative Training", + "section": "", + "text": "Scope\nIncreasingly large data sets and search spaces make hyperparameter optimization a time-consuming task. Hyperband (Li et al. 2018) solves this by approximating the performance of a configuration on a simplified version of the problem such as a small subset of the training data, with just a few training epochs in a neural network, or with only a small number of iterations in a gradient-boosting model. After starting randomly sampled configurations, Hyperband iteratively allocates more resources to promising configurations and terminates low-performing ones. This type of optimization is called multi-fidelity optimization. The fidelity parameter is part of the search space and controls the tradeoff between the runtime and accuracy of the performance approximation. In this post, we will optimize XGBoost and use the number of boosting iterations as the fidelity parameter. This means Hyperband will allocate more boosting iterations to well-performing configurations. The number of boosting iterations increases the time to train a model and improves the performance until the model is overfitting to the training data. It is therefore a suitable fidelity parameter. We assume that you are already familiar with tuning in the mlr3 ecosystem. If not, you should start with the book chapter on optimization or the Hyperparameter Optimization on the Palmer Penguins Data Set post. This is the first part of the Hyperband series. The second part can be found here Hyperband Series - Data Set Subsampling.\n\n\nHyperband\nHyperband is an advancement of the Successive Halving algorithm by Jamieson and Talwalkar (2016). Successive Halving is initialized with the number of starting configurations \\(n\\), the proportion of configurations discarded in each stage \\(\\eta\\), and the minimum \\(r{_{min}}\\) and maximum \\(r{_{max}}\\) budget of a single evaluation. The algorithm starts by sampling \\(n\\) random configurations and allocating the minimum budget \\(r{_{min}}\\) to them. The configurations are evaluated and \\(\\frac{1}{\\eta}\\) of the worst-performing configurations are discarded. The remaining configurations are promoted to the next stage and evaluated on a larger budget. This continues until one or more configurations are evaluated on the maximum budget \\(r{_{max}}\\) and the best performing configuration is selected. The number of stages is calculated so that each stage consumes approximately the same budget. This sometimes results in the minimum budget having to be slightly adjusted by the algorithm. Successive Halving has the disadvantage that is not clear whether we should choose a large \\(n\\) and try many configurations on a small budget or choose a small \\(n\\) and train more configurations on the full budget.\nHyperband solves this problem by running Successive Halving with different numbers of stating configurations. The algorithm is initialized with the same parameters as Successive Halving but without \\(n\\). Each run of Successive Halving is called a bracket and starts with a different budget \\(r{_{0}}\\). A smaller starting budget means that more configurations can be tried out. The most explorative bracket allocated the minimum budget \\(r{_{min}}\\). The next bracket increases the starting budget by a factor of \\(\\eta\\). In each bracket, the starting budget increases further until the last bracket \\(s = 0\\) essentially performs a random search with the full budget \\(r{_{max}}\\). The number of brackets \\(s{_{max}} + 1\\) is calculated with \\(s{_{max}} = {\\log_\\eta \\frac{r{_{max}} }{r{_{min}}}}\\). Under the condition that \\(r{_{0}}\\) increases by \\(\\eta\\) with each bracket, \\(r{_{min}}\\) sometimes has to be adjusted slightly in order not to use more than \\(r{_{max}}\\) resources in the last bracket. The number of configurations in the base stages is calculated so that each bracket uses approximately the same amount of budget. The following table shows a full run of the Hyperband algorithm. The bracket \\(s = 3\\) is the most explorative bracket and \\(s = 0\\) performance a random search on the full budget.\n\n\n\n\n\n\n\n\nFigure 1: Hyperband schedule with \\(\\eta = 2\\) , \\(r{_{min}} = 1\\) and \\(r{_{max}} = 8\\)\n\n\n\n\nThe Hyperband implementation in mlr3hyperband evaluates configurations with the same budget in parallel. This results in all brackets finishing at approximately the same time. The colors in Figure 1 indicate batches that are evaluated in parallel.\n\n\nHyperparameter Optimization\nIn this practical example, we will optimize the hyperparameters of XGBoost on the Spam data set. We begin by loading the XGBoost learner..\n\nlibrary(\"mlr3verse\")\n\nlearner = lrn(\"classif.xgboost\")\n\nThe next thing we do is define the search space. The nrounds parameter controls the number of boosting iterations. We set a range from 16 to 128 boosting iterations. This is used as \\(r{_{min}}\\) and \\(r{_{max}}\\) by the Hyperband algorithm. We need to tag the parameter with \"budget\" to identify it as a fidelity parameter. For the other hyperparameters, we take the search space for XGBoost from the Bischl et al. (2021) article. This search space works for a wide range of data sets.\n\nlearner$param_set$set_values(\n nrounds = to_tune(p_int(16, 128, tags = \"budget\")),\n eta = to_tune(1e-4, 1, logscale = TRUE),\n max_depth = to_tune(1, 20),\n colsample_bytree = to_tune(1e-1, 1),\n colsample_bylevel = to_tune(1e-1, 1),\n lambda = to_tune(1e-3, 1e3, logscale = TRUE),\n alpha = to_tune(1e-3, 1e3, logscale = TRUE),\n subsample = to_tune(1e-1, 1)\n)\n\nWe construct the tuning instance. We use the \"none\" terminator because Hyperband terminates itself when all brackets are evaluated.\n\ninstance = ti(\n task = tsk(\"spam\"),\n learner = learner,\n resampling = rsmp(\"holdout\"),\n measures = msr(\"classif.ce\"),\n terminator = trm(\"none\")\n)\ninstance\n\n<TuningInstanceSingleCrit>\n* State: Not optimized\n* Objective: <ObjectiveTuning:classif.xgboost_on_spam>\n* Search Space:\n id class lower upper nlevels\n <char> <char> <num> <num> <num>\n1: nrounds ParamInt 16.000000 128.000000 113\n2: eta ParamDbl -9.210340 0.000000 Inf\n3: max_depth ParamInt 1.000000 20.000000 20\n4: colsample_bytree ParamDbl 0.100000 1.000000 Inf\n5: colsample_bylevel ParamDbl 0.100000 1.000000 Inf\n6: lambda ParamDbl -6.907755 6.907755 Inf\n7: alpha ParamDbl -6.907755 6.907755 Inf\n8: subsample ParamDbl 0.100000 1.000000 Inf\n* Terminator: <TerminatorNone>\n\n\nWe load the Hyperband tuner and set eta = 2. Hyperband can start from the beginning when the last bracket is evaluated. We control the number of Hyperband runs with the repetition argument. The setting repetition = Inf is useful when a terminator should stop the optimization.\n\nlibrary(\"mlr3hyperband\")\n\ntuner = tnr(\"hyperband\", eta = 2, repetitions = 1)\n\nThe Hyperband implementation in mlr3hyperband evaluates configurations with the same budget in parallel. This results in all brackets finishing at approximately the same time. You can think of it as going diagonally through Figure 1. Using eta = 2 and a range from 16 to 128 boosting iterations results in the following schedule.\n\n\n\n\n\n\nNow we are ready to start the tuning.\n\ntuner$optimize(instance)\n\nThe result of a run is the configuration with the best performance. This does not necessarily have to be a configuration evaluated with the highest budget since we can overfit the data with too many boosting iterations.\n\ninstance$result[, .(nrounds, eta, max_depth, colsample_bytree, colsample_bylevel, lambda, alpha, subsample)]\n\n nrounds eta max_depth colsample_bytree colsample_bylevel lambda alpha subsample\n <num> <num> <int> <num> <num> <num> <num> <num>\n1: 128 -1.985313 8 0.4828647 0.3001509 -3.816118 -4.998944 0.4464856\n\n\nThe archive of a Hyperband run has the additional columns \"bracket\" and \"stage\".\n\nas.data.table(instance$archive)[, .(bracket, stage, classif.ce, eta, max_depth, colsample_bytree)]\n\n bracket stage classif.ce eta max_depth colsample_bytree\n <int> <num> <num> <num> <int> <num>\n 1: 3 0 0.09061278 -3.6110452 20 0.2671318\n 2: 3 0 0.06388527 -1.9853130 8 0.4828647\n 3: 3 0 0.11147327 -2.8428844 3 0.3152709\n 4: 3 0 0.07301173 -3.9228523 19 0.5369803\n 5: 3 0 0.07953064 -3.6486183 17 0.2039727\n--- \n31: 0 0 0.06258149 -1.8578637 9 0.7343156\n32: 3 3 0.03976532 -1.9853130 8 0.4828647\n33: 2 2 0.03976532 -0.9898459 4 0.2534038\n34: 1 1 0.05345502 -2.5345314 13 0.5260946\n35: 1 1 0.06714472 -8.5597326 16 0.9890136\n\n\n\n\nConclusion\nThe handling of Hyperband in mlr3tuning is very similar to that of other tuners. We only have to select an additional fidelity parameter and tag it with \"budget\". We have tried to keep the runtime of the example low. For your optimization, you should use cross-validation and increase the maximum number of boosting rounds. The Bischl et al. (2021) search space suggests 5000 boosting rounds. Check out our next post on Hyperband which uses the size of the training data set as the fidelity parameter.\n\n\n\n\n\nReferences\n\nBischl, Bernd, Martin Binder, Michel Lang, Tobias Pielok, Jakob Richter, Stefan Coors, Janek Thomas, et al. 2021. “Hyperparameter Optimization: Foundations, Algorithms, Best Practices and Open Challenges.” arXiv:2107.05847 [Cs, Stat], July. http://arxiv.org/abs/2107.05847.\n\n\nJamieson, Kevin, and Ameet Talwalkar. 2016. “Non-Stochastic Best Arm Identification and Hyperparameter Optimization.” In Proceedings of the 19th International Conference on Artificial Intelligence and Statistics, edited by Arthur Gretton and Christian C. Robert, 51:240–48. Proceedings of Machine Learning Research. Cadiz, Spain: PMLR. http://proceedings.mlr.press/v51/jamieson16.html.\n\n\nLi, Lisha, Kevin Jamieson, Giulia DeSalvo, Afshin Rostamizadeh, and Ameet Talwalkar. 2018. “Hyperband: A Novel Bandit-Based Approach to Hyperparameter Optimization.” Journal of Machine Learning Research 18 (185): 1–52. https://jmlr.org/papers/v18/16-558.html." + }, + { + "objectID": "gallery/optimization/2020-09-14-mlr3fselect-basic/index.html", + "href": "gallery/optimization/2020-09-14-mlr3fselect-basic/index.html", + "title": "Feature Selection on the Titanic Data Set", + "section": "", + "text": "In this tutorial, we introduce the mlr3fselect package by comparing feature selection methods on the Titanic disaster data set. The objective of feature selection is to enhance the interpretability of models, speed up the learning process and increase the predictive performance.\nWe load the mlr3verse package which pulls in the most important packages for this example.\n\nlibrary(mlr3verse)\nlibrary(mlr3fselect)\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\nlgr::get_logger(\"bbotk\")$set_threshold(\"warn\")" + }, + { + "objectID": "gallery/optimization/2020-09-14-mlr3fselect-basic/index.html#introduction", + "href": "gallery/optimization/2020-09-14-mlr3fselect-basic/index.html#introduction", + "title": "Feature Selection on the Titanic Data Set", + "section": "", + "text": "In this tutorial, we introduce the mlr3fselect package by comparing feature selection methods on the Titanic disaster data set. The objective of feature selection is to enhance the interpretability of models, speed up the learning process and increase the predictive performance.\nWe load the mlr3verse package which pulls in the most important packages for this example.\n\nlibrary(mlr3verse)\nlibrary(mlr3fselect)\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\nlgr::get_logger(\"bbotk\")$set_threshold(\"warn\")" + }, + { + "objectID": "gallery/optimization/2020-09-14-mlr3fselect-basic/index.html#titanic-data-set", + "href": "gallery/optimization/2020-09-14-mlr3fselect-basic/index.html#titanic-data-set", + "title": "Feature Selection on the Titanic Data Set", + "section": "Titanic Data Set", + "text": "Titanic Data Set\nThe Titanic data set contains data for 887 Titanic passengers, including whether they survived when the Titanic sank. Our goal will be to predict the survival of the Titanic passengers.\nAfter loading the data set from the mlr3data package, we impute the missing age values with the median age of the passengers, set missing embarked values to \"s\" and remove character features. We could use feature engineering to create new features from the character features, however we want to focus on feature selection in this tutorial.\nIn addition to the survived column, the reduced data set contains the following attributes for each passenger:\n\n\n\nFeature\nDescription\n\n\n\n\nage\nAge\n\n\nsex\nSex\n\n\nsib_sp\nNumber of siblings / spouses aboard\n\n\nparch\nNumber of parents / children aboard\n\n\nfare\nAmount paid for the ticket\n\n\npc_class\nPassenger class\n\n\nembarked\nPort of embarkation\n\n\n\n\nlibrary(mlr3data)\n\ndata(\"titanic\", package = \"mlr3data\")\ntitanic$age[is.na(titanic$age)] = median(titanic$age, na.rm = TRUE)\ntitanic$embarked[is.na(titanic$embarked)] = \"S\"\ntitanic$ticket = NULL\ntitanic$name = NULL\ntitanic$cabin = NULL\ntitanic = titanic[!is.na(titanic$survived),]\n\nWe construct a binary classification task.\n\ntask = as_task_classif(titanic, target = \"survived\", positive = \"yes\")" + }, + { + "objectID": "gallery/optimization/2020-09-14-mlr3fselect-basic/index.html#model", + "href": "gallery/optimization/2020-09-14-mlr3fselect-basic/index.html#model", + "title": "Feature Selection on the Titanic Data Set", + "section": "Model", + "text": "Model\nWe use the logistic regression learner provided by the mlr3learners package.\n\nlibrary(mlr3learners)\n\nlearner = lrn(\"classif.log_reg\")\n\nTo evaluate the predictive performance, we choose a 3-fold cross-validation and the classification error as the measure.\n\nresampling = rsmp(\"cv\", folds = 3)\nmeasure = msr(\"classif.ce\")\n\nresampling$instantiate(task)" + }, + { + "objectID": "gallery/optimization/2020-09-14-mlr3fselect-basic/index.html#classes", + "href": "gallery/optimization/2020-09-14-mlr3fselect-basic/index.html#classes", + "title": "Feature Selection on the Titanic Data Set", + "section": "Classes", + "text": "Classes\nThe FSelectInstanceSingleCrit class specifies a general feature selection scenario. It includes the ObjectiveFSelect object that encodes the black box objective function which is optimized by a feature selection algorithm. The evaluated feature sets are stored in an ArchiveFSelect object. The archive provides a method for querying the best performing feature set.\nThe Terminator classes determine when to stop the feature selection. In this example we choose a terminator that stops the feature selection after 10 seconds. The sugar functions trm() and trms() can be used to retrieve terminators from the mlr_terminators dictionary.\n\nterminator = trm(\"run_time\", secs = 10)\nFSelectInstanceSingleCrit$new(\n task = task,\n learner = learner,\n resampling = resampling,\n measure = measure,\n terminator = terminator)\n\n<FSelectInstanceSingleCrit>\n* State: Not optimized\n* Objective: <ObjectiveFSelect:classif.log_reg_on_titanic>\n* Terminator: <TerminatorRunTime>\n\n\nThe FSelector subclasses describe the feature selection strategy. The sugar function fs() can be used to retrieve feature selection algorithms from the mlr_fselectors dictionary.\n\nmlr_fselectors\n\n<DictionaryFSelector> with 8 stored values\nKeys: design_points, exhaustive_search, genetic_search, random_search, rfe, rfecv, sequential,\n shadow_variable_search" + }, + { + "objectID": "gallery/optimization/2020-09-14-mlr3fselect-basic/index.html#random-search", + "href": "gallery/optimization/2020-09-14-mlr3fselect-basic/index.html#random-search", + "title": "Feature Selection on the Titanic Data Set", + "section": "Random search", + "text": "Random search\nRandom search randomly draws feature sets and evaluates them in batches. We retrieve the FSelectorRandomSearch class with the fs() sugar function and choose TerminatorEvals. We set the n_evals parameter to 10 which means that 10 feature sets are evaluated.\n\nterminator = trm(\"evals\", n_evals = 10)\ninstance = FSelectInstanceSingleCrit$new(\n task = task,\n learner = learner,\n resampling = resampling,\n measure = measure,\n terminator = terminator)\nfselector = fs(\"random_search\", batch_size = 5)\n\nThe feature selection is started by passing the FSelectInstanceSingleCrit object to the $optimize() method of FSelectorRandomSearch which generates the feature sets. These features set are internally passed to the $eval_batch() method of FSelectInstanceSingleCrit which evaluates them with the objective function and stores the results in the archive. This general interaction between the objects of mlr3fselect stays the same for the different feature selection methods. However, the way how new feature sets are generated differs depending on the chosen FSelector subclass.\n\nfselector$optimize(instance)\n\n age embarked fare parch pclass sex sib_sp features classif.ce\n1: TRUE FALSE TRUE TRUE TRUE TRUE TRUE age,fare,parch,pclass,sex,sib_sp 0.2020202\n\n\nThe ArchiveFSelect stores a data.table::data.table() which consists of the evaluated feature sets and the corresponding estimated predictive performances.\n\nas.data.table(instance$archive, exclude_columns = c(\"runtime_learners\", \"resample_result\", \"uhash\"))\n\n age embarked fare parch pclass sex sib_sp classif.ce timestamp batch_nr warnings errors\n 1: TRUE TRUE TRUE TRUE TRUE TRUE TRUE 0.2031425 2023-11-01 09:35:52 1 0 0\n 2: TRUE FALSE FALSE FALSE FALSE FALSE TRUE 0.3838384 2023-11-01 09:35:52 1 0 0\n 3: FALSE FALSE FALSE TRUE FALSE FALSE TRUE 0.3804714 2023-11-01 09:35:52 1 0 0\n 4: FALSE FALSE TRUE FALSE FALSE FALSE FALSE 0.3288440 2023-11-01 09:35:52 1 0 0\n 5: FALSE FALSE TRUE FALSE FALSE TRUE FALSE 0.2188552 2023-11-01 09:35:52 1 0 0\n 6: FALSE FALSE FALSE FALSE TRUE FALSE FALSE 0.3209877 2023-11-01 09:36:40 2 0 0\n 7: TRUE FALSE FALSE FALSE FALSE FALSE TRUE 0.3838384 2023-11-01 09:36:40 2 0 0\n 8: TRUE FALSE TRUE TRUE TRUE TRUE TRUE 0.2020202 2023-11-01 09:36:40 2 0 0\n 9: TRUE TRUE TRUE TRUE TRUE TRUE TRUE 0.2031425 2023-11-01 09:36:40 2 0 0\n10: TRUE FALSE TRUE TRUE FALSE FALSE FALSE 0.3389450 2023-11-01 09:36:40 2 0 0\n features\n 1: age,embarked,fare,parch,pclass,sex,...\n 2: age,sib_sp\n 3: parch,sib_sp\n 4: fare\n 5: fare,sex\n 6: pclass\n 7: age,sib_sp\n 8: age,fare,parch,pclass,sex,sib_sp\n 9: age,embarked,fare,parch,pclass,sex,...\n10: age,fare,parch\n\n\nThe associated resampling iterations can be accessed in the BenchmarkResult by calling\n\ninstance$archive$benchmark_result\n\n<BenchmarkResult> of 30 rows with 10 resampling runs\n nr task_id learner_id resampling_id iters warnings errors\n 1 titanic classif.log_reg cv 3 0 0\n 2 titanic classif.log_reg cv 3 0 0\n 3 titanic classif.log_reg cv 3 0 0\n 4 titanic classif.log_reg cv 3 0 0\n 5 titanic classif.log_reg cv 3 0 0\n 6 titanic classif.log_reg cv 3 0 0\n 7 titanic classif.log_reg cv 3 0 0\n 8 titanic classif.log_reg cv 3 0 0\n 9 titanic classif.log_reg cv 3 0 0\n 10 titanic classif.log_reg cv 3 0 0\n\n\nWe retrieve the best performing feature set with\n\ninstance$result\n\n age embarked fare parch pclass sex sib_sp features classif.ce\n1: TRUE FALSE TRUE TRUE TRUE TRUE TRUE age,fare,parch,pclass,sex,sib_sp 0.2020202" + }, + { + "objectID": "gallery/optimization/2020-09-14-mlr3fselect-basic/index.html#sequential-forward-selection", + "href": "gallery/optimization/2020-09-14-mlr3fselect-basic/index.html#sequential-forward-selection", + "title": "Feature Selection on the Titanic Data Set", + "section": "Sequential forward selection", + "text": "Sequential forward selection\nWe try sequential forward selection. We chose TerminatorStagnation that stops the feature selection if the predictive performance does not increase anymore.\n\nterminator = trm(\"stagnation\", iters = 5)\ninstance = FSelectInstanceSingleCrit$new(\n task = task,\n learner = learner,\n resampling = resampling,\n measure = measure,\n terminator = terminator)\n\nfselector = fs(\"sequential\")\nfselector$optimize(instance)\n\n age embarked fare parch pclass sex sib_sp features classif.ce\n1: FALSE FALSE FALSE TRUE TRUE TRUE TRUE parch,pclass,sex,sib_sp 0.1964085\n\n\nThe FSelectorSequential object has a special method for displaying the optimization path of the sequential feature selection.\n\nfselector$optimization_path(instance)\n\n age embarked fare parch pclass sex sib_sp classif.ce batch_nr\n1: TRUE FALSE FALSE FALSE FALSE FALSE FALSE 0.3838384 1\n2: TRUE FALSE FALSE FALSE FALSE TRUE FALSE 0.2132435 2\n3: TRUE FALSE FALSE FALSE FALSE TRUE TRUE 0.2087542 3\n4: TRUE FALSE FALSE FALSE TRUE TRUE TRUE 0.2143659 4\n5: TRUE FALSE FALSE TRUE TRUE TRUE TRUE 0.2065095 5\n6: TRUE FALSE TRUE TRUE TRUE TRUE TRUE 0.2020202 6" + }, + { + "objectID": "gallery/optimization/2020-09-14-mlr3fselect-basic/index.html#recursive-feature-elimination", + "href": "gallery/optimization/2020-09-14-mlr3fselect-basic/index.html#recursive-feature-elimination", + "title": "Feature Selection on the Titanic Data Set", + "section": "Recursive feature elimination", + "text": "Recursive feature elimination\nRecursive feature elimination utilizes the $importance() method of learners. In each iteration the feature(s) with the lowest importance score is dropped. We choose the non-recursive algorithm (recursive = FALSE) which calculates the feature importance once on the complete feature set. The recursive version (recursive = TRUE) recomputes the feature importance on the reduced feature set in every iteration.\n\nlearner = lrn(\"classif.ranger\", importance = \"impurity\")\nterminator = trm(\"none\")\ninstance = FSelectInstanceSingleCrit$new(\n task = task,\n learner = learner,\n resampling = resampling,\n measure = measure,\n terminator = terminator,\n store_models = TRUE)\n\nfselector = fs(\"rfe\", recursive = FALSE)\nfselector$optimize(instance)\n\n age embarked fare parch pclass sex sib_sp features classif.ce\n1: TRUE TRUE TRUE TRUE TRUE TRUE TRUE age,embarked,fare,parch,pclass,sex,... 0.1694725\n\n\nWe access the results.\n\nas.data.table(instance$archive, exclude_columns = c(\"runtime_learners\", \"timestamp\", \"batch_nr\", \"resample_result\", \"uhash\"))\n\n age embarked fare parch pclass sex sib_sp classif.ce warnings errors importance\n1: TRUE TRUE TRUE TRUE TRUE TRUE TRUE 0.1694725 0 0 7,6,5,4,3,2,...\n2: TRUE FALSE TRUE FALSE FALSE TRUE FALSE 0.2132435 0 0 7,6,5\n features\n1: age,embarked,fare,parch,pclass,sex,...\n2: age,fare,sex" + }, + { + "objectID": "gallery/optimization/2020-09-14-mlr3fselect-basic/index.html#nested-resampling", + "href": "gallery/optimization/2020-09-14-mlr3fselect-basic/index.html#nested-resampling", + "title": "Feature Selection on the Titanic Data Set", + "section": "Nested resampling", + "text": "Nested resampling\nIt is a common mistake to report the predictive performance estimated on resampling sets during the feature selection as the performance that can be expected from the combined feature selection and model training. The repeated evaluation of the model might leak information about the test sets into the model and thus leads to over-fitting and over-optimistic performance results. Nested resampling uses an outer and inner resampling to separate the feature selection from the performance estimation of the model. We can use the AutoFSelector class for running nested resampling. The AutoFSelector essentially combines a given Learner and feature selection method into a Learner with internal automatic feature selection. The inner resampling loop that is used to determine the best feature set is conducted internally each time the AutoFSelector Learner object is trained.\n\nresampling_inner = rsmp(\"cv\", folds = 5)\nmeasure = msr(\"classif.ce\")\n\nat = AutoFSelector$new(\n learner = learner,\n resampling = resampling_inner,\n measure = measure,\n terminator = terminator,\n fselect = fs(\"sequential\"),\n store_models = TRUE)\n\nWe put the AutoFSelector into a resample() call to get the outer resampling loop.\n\nresampling_outer = rsmp(\"cv\", folds = 3)\n\nrr = resample(task, at, resampling_outer, store_models = TRUE)\n\nThe aggregated performance of all outer resampling iterations is the unbiased predictive performance we can expected from the logistic regression model with an optimized feature set found by sequential selection.\n\nrr$aggregate()\n\nclassif.ce \n 0.1829405 \n\n\nWe check whether the feature sets that were selected in the inner resampling are stable. The selected feature sets should not differ too much. We might observe unstable models in this example because the small data set and the low number of resampling iterations might introduces too much randomness. Usually, we aim for the selection of similar feature sets for all outer training sets.\n\nextract_inner_fselect_results(rr)\n\n\n\n\n\n\n\nNext, we want to compare the predictive performances estimated on the outer resampling to the inner resampling. Significantly lower predictive performances on the outer resampling indicate that the models with the optimized feature sets overfit the data.\n\nrr$score()[, .(iteration, task_id, learner_id, resampling_id, classif.ce)]\n\n iteration task_id learner_id resampling_id classif.ce\n1: 1 titanic classif.ranger.fselector cv 0.1515152\n2: 2 titanic classif.ranger.fselector cv 0.1952862\n3: 3 titanic classif.ranger.fselector cv 0.2020202\n\n\nThe archives of the AutoFSelectors gives us all evaluated feature sets with the associated predictive performances.\n\nextract_inner_fselect_archives(rr)" + }, + { + "objectID": "gallery/optimization/2020-09-14-mlr3fselect-basic/index.html#shortcuts", + "href": "gallery/optimization/2020-09-14-mlr3fselect-basic/index.html#shortcuts", + "title": "Feature Selection on the Titanic Data Set", + "section": "Shortcuts", + "text": "Shortcuts\nSelecting a feature subset can be shortened by using the fselect()-shortcut.\n\ninstance = fselect(\n tuner = tnr( \"random_search\",\n task = tsk(\"iris\"),\n learner = lrn(\"classif.log_reg\"),\n resampling = rsmp(\"cv\", folds = 3),\n measure = msr(\"classif.ce\"),\n term_evals = 10\n)\n\nApplying nested resampling can be shortened by using the fselect_nested()-shortcut.\n\nrr = fselect_nested(\n tuner = tnr(\"random_search\"),\n task = tsk(\"iris\"),\n learner = lrn(\"classif.log_reg\"),\n inner_resampling = rsmp (\"cv\", folds = 3),\n outer_resampling = rsmp(\"cv\", folds = 3),\n measure = msr(\"classif.ce\"),\n term_evals = 10\n)" + }, + { + "objectID": "gallery/basic/2020-01-30-house-prices-in-king-county/index.html", + "href": "gallery/basic/2020-01-30-house-prices-in-king-county/index.html", + "title": "House Prices in King County", + "section": "", + "text": "The use-case illustrated below touches on the following concepts:\nThe relevant sections in the mlr3book are linked to for the reader’s convenience.\nThis use case shows how to model housing price data in King County. Following features are illustrated:\nWe load the mlr3verse package which pulls in the most important packages for this example.\nlibrary(mlr3verse)\n\nLoading required package: mlr3\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\nlgr::get_logger(\"bbotk\")$set_threshold(\"warn\")" + }, + { + "objectID": "gallery/basic/2020-01-30-house-prices-in-king-county/index.html#use-case-regr-houses", + "href": "gallery/basic/2020-01-30-house-prices-in-king-county/index.html#use-case-regr-houses", + "title": "House Prices in King County", + "section": "House Price Prediction in King County", + "text": "House Price Prediction in King County\nWe use the kc_housing dataset contained in the package mlr3data in order to provide a use-case for the application of mlr3 on real-world data.\n\ndata(\"kc_housing\", package = \"mlr3data\")\n\n\nExploratory Data Analysis\nIn order to get a quick impression of our data, we perform some initial Exploratory Data Analysis. This helps us to get a first impression of our data and might help us arrive at additional features that can help with the prediction of the house prices.\nWe can get a quick overview using R’s summary function:\n\nsummary(kc_housing)\n\n date price bedrooms bathrooms sqft_living sqft_lot \n Min. :2014-05-02 00:00:00.0 Min. : 75000 Min. : 0.000 Min. :0.000 Min. : 290 Min. : 520 \n 1st Qu.:2014-07-22 00:00:00.0 1st Qu.: 321950 1st Qu.: 3.000 1st Qu.:1.750 1st Qu.: 1427 1st Qu.: 5040 \n Median :2014-10-16 00:00:00.0 Median : 450000 Median : 3.000 Median :2.250 Median : 1910 Median : 7618 \n Mean :2014-10-29 03:58:09.9 Mean : 540088 Mean : 3.371 Mean :2.115 Mean : 2080 Mean : 15107 \n 3rd Qu.:2015-02-17 00:00:00.0 3rd Qu.: 645000 3rd Qu.: 4.000 3rd Qu.:2.500 3rd Qu.: 2550 3rd Qu.: 10688 \n Max. :2015-05-27 00:00:00.0 Max. :7700000 Max. :33.000 Max. :8.000 Max. :13540 Max. :1651359 \n \n floors waterfront view condition grade sqft_above sqft_basement \n Min. :1.000 Mode :logical Min. :0.0000 Min. :1.000 Min. : 1.000 Min. : 290 Min. : 10.0 \n 1st Qu.:1.000 FALSE:21450 1st Qu.:0.0000 1st Qu.:3.000 1st Qu.: 7.000 1st Qu.:1190 1st Qu.: 450.0 \n Median :1.500 TRUE :163 Median :0.0000 Median :3.000 Median : 7.000 Median :1560 Median : 700.0 \n Mean :1.494 Mean :0.2343 Mean :3.409 Mean : 7.657 Mean :1788 Mean : 742.4 \n 3rd Qu.:2.000 3rd Qu.:0.0000 3rd Qu.:4.000 3rd Qu.: 8.000 3rd Qu.:2210 3rd Qu.: 980.0 \n Max. :3.500 Max. :4.0000 Max. :5.000 Max. :13.000 Max. :9410 Max. :4820.0 \n NA's :13126 \n yr_built yr_renovated zipcode lat long sqft_living15 sqft_lot15 \n Min. :1900 Min. :1934 Min. :98001 Min. :47.16 Min. :-122.5 Min. : 399 Min. : 651 \n 1st Qu.:1951 1st Qu.:1987 1st Qu.:98033 1st Qu.:47.47 1st Qu.:-122.3 1st Qu.:1490 1st Qu.: 5100 \n Median :1975 Median :2000 Median :98065 Median :47.57 Median :-122.2 Median :1840 Median : 7620 \n Mean :1971 Mean :1996 Mean :98078 Mean :47.56 Mean :-122.2 Mean :1987 Mean : 12768 \n 3rd Qu.:1997 3rd Qu.:2007 3rd Qu.:98118 3rd Qu.:47.68 3rd Qu.:-122.1 3rd Qu.:2360 3rd Qu.: 10083 \n Max. :2015 Max. :2015 Max. :98199 Max. :47.78 Max. :-121.3 Max. :6210 Max. :871200 \n NA's :20699 \n\ndim(kc_housing)\n\n[1] 21613 20\n\n\nOur dataset has 21613 observations and 20 columns. The variable we want to predict is price. In addition to the price column, we have several other columns:\n\nid: A unique identifier for every house.\ndate: A date column, indicating when the house was sold. This column is currently not encoded as a date and requires some preprocessing.\nzipcode: A column indicating the ZIP code. This is a categorical variable with many factor levels.\nlong, lat The longitude and latitude of the house\n... several other numeric columns providing information about the house, such as number of rooms, square feet etc.\n\nBefore we continue with the analysis, we preprocess some features so that they are stored in the correct format.\nFirst we convert the date column to numeric. To do so, we convert the date to the POSIXct date/time class with the anytime package. Next, use difftime() to convert to days since the first day recorded in the data set:\n\nlibrary(anytime)\ndates = anytime(kc_housing$date)\nkc_housing$date = as.numeric(difftime(dates, min(dates), units = \"days\"))\n\nAfterwards, we convert the zip code to a factor:\n\nkc_housing$zipcode = as.factor(kc_housing$zipcode)\n\nAnd add a new column renovated indicating whether a house was renovated at some point.\n\nkc_housing$renovated = as.numeric(!is.na(kc_housing$yr_renovated))\nkc_housing$has_basement = as.numeric(!is.na(kc_housing$sqft_basement))\n\nWe drop the id column which provides no information about the house prices:\n\nkc_housing$id = NULL\n\nAdditionally, we convert the price from Dollar to units of 1000 Dollar to improve readability.\n\nkc_housing$price = kc_housing$price / 1000\n\nAdditionally, for now we simply drop the columns that have missing values, as some of our learners can not deal with them. A better option to deal with missing values would be imputation, i.e. replacing missing values with valid ones. We will deal with this in a separate article.\n\nkc_housing$yr_renovated = NULL\nkc_housing$sqft_basement = NULL\n\nWe can now plot the density of the price to get a first impression on its distribution.\n\nlibrary(ggplot2)\nggplot(kc_housing, aes(x = price)) + geom_density()\n\n\n\n\n\n\n\n\nWe can see that the prices for most houses lie between 75.000 and 1.5 million dollars. There are few extreme values of up to 7.7 million dollars.\nFeature engineering often allows us to incorporate additional knowledge about the data and underlying processes. This can often greatly enhance predictive performance. A simple example: A house which has yr_renovated == 0 means that is has not been renovated yet. Additionally, we want to drop features which should not have any influence (id column).\nAfter those initial manipulations, we load all required packages and create a TaskRegr containing our data.\n\ntsk = as_task_regr(kc_housing, target = \"price\")\n\nWe can inspect associations between variables using mlr3viz’s autoplot function in order to get some good first impressions for our data. Note, that this does in no way prevent us from using other powerful plot functions of our choice on the original data.\n\nDistribution of the price:\nThe outcome we want to predict is the price variable. The autoplot function provides a good first glimpse on our data. As the resulting object is a ggplot2 object, we can use faceting and other functions from ggplot2 in order to enhance plots.\n\nautoplot(tsk) + facet_wrap(~renovated)\n\n\n\n\n\n\n\n\nWe can observe that renovated flats seem to achieve higher sales values, and this might thus be a relevant feature.\nAdditionally, we can for example look at the condition of the house. Again, we clearly can see that the price rises with increasing condition.\n\nautoplot(tsk) + facet_wrap(~condition)\n\n\n\n\n\n\n\n\n\n\nAssociation between variables\nIn addition to the association with the target variable, the association between the features can also lead to interesting insights. We investigate using variables associated with the quality and size of the house. Note that we use $clone() and $select() to clone the task and select only a subset of the features for the autoplot function, as autoplot per default uses all features. The task is cloned before we select features in order to keep the original task intact.\n\n# Variables associated with quality\nautoplot(tsk$clone()$select(tsk$feature_names[c(3, 17)]), type = \"pairs\")\n\nRegistered S3 method overwritten by 'GGally':\n method from \n +.gg ggplot2\n\n\n`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.\n`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.\n\n\n\n\n\n\n\n\n\n\nautoplot(tsk$clone()$select(tsk$feature_names[c(9:12)]), type = \"pairs\")\n\n\n\n\n\n\n\n\n\n\n\nSplitting into train and test data\nIn mlr3, we do not create train and test data sets, but instead keep only a vector of train and test indices.\n\ntrain.idx = sample(seq_len(tsk$nrow), 0.7 * tsk$nrow)\ntest.idx = setdiff(seq_len(tsk$nrow), train.idx)\n\nWe can do the same for our task:\n\ntask_train = tsk$clone()$filter(train.idx)\ntask_test = tsk$clone()$filter(test.idx)\n\n\n\nA first model: Decision Tree\nDecision trees cannot only be used as a powerful tool for predictive models but also for exploratory data analysis. In order to fit a decision tree, we first get the regr.rpart learner from the mlr_learners dictionary by using the sugar function lrn.\nFor now, we leave out the zipcode variable, as we also have the latitude and longitude of each house. Again, we use $clone(), so we do not change the original task.\n\ntsk_nozip = task_train$clone()$select(setdiff(tsk$feature_names, \"zipcode\"))\n\n# Get the learner\nlrn = lrn(\"regr.rpart\")\n\n# And train on the task\nlrn$train(tsk_nozip, row_ids = train.idx)\n\n\nplot(lrn$model)\ntext(lrn$model)\n\n\n\n\n\n\n\n\nThe learned tree relies on several variables in order to distinguish between cheaper and pricier houses. The features we split along are grade, sqft_living, but also some features related to the area (longitude and latitude). We can visualize the price across different regions in order to get more info:\n\n# Load the ggmap package in order to visualize on a map\nlibrary(ggmap)\n\n# And create a quick plot for the price\nqmplot(long, lat, maptype = \"watercolor\", color = log(price),\n data = kc_housing[train.idx[1:3000], ]) +\n scale_colour_viridis_c()\n\n\n\n\n\n\n\n# And the zipcode\nqmplot(long, lat, maptype = \"watercolor\", color = zipcode,\n data = kc_housing[train.idx[1:3000], ]) + guides(color = FALSE)\n\nWarning: The `<scale>` argument of `guides()` cannot be `FALSE`. Use \"none\" instead as of ggplot2 3.3.4.\n\n\n\n\n\n\n\n\n\nWe can see that the price is clearly associated with the zipcode when comparing then two plots. As a result, we might want to indeed use the zipcode column in our future endeavors.\n\n\nA first baseline: Decision Tree\nAfter getting an initial idea for our data, we might want to construct a first baseline, in order to see what a simple model already can achieve.\nWe use resample() with 3-fold cross-validation on our training data in order to get a reliable estimate of the algorithm’s performance on future data. Before we start with defining and training learners, we create a Resampling in order to make sure that we always compare on exactly the same data.\n\ncv3 = rsmp(\"cv\", folds = 3)\n\nFor the cross-validation we only use the training data by cloning the task and selecting only observations from the training set.\n\nlrn_rpart = lrn(\"regr.rpart\")\nres = resample(task = task_train, lrn_rpart, cv3)\nres$score(msr(\"regr.rmse\"))\n\n task_id learner_id resampling_id iteration regr.rmse\n1: kc_housing regr.rpart cv 1 205.7541\n2: kc_housing regr.rpart cv 2 205.6597\n3: kc_housing regr.rpart cv 3 213.3846\nHidden columns: task, learner, resampling, prediction\n\nsprintf(\"RMSE of the simple rpart: %s\", round(sqrt(res$aggregate()), 2))\n\n[1] \"RMSE of the simple rpart: 208.3\"\n\n\n\n\nMany Trees: Random Forest\nWe might be able to improve upon the RMSE using more powerful learners. We first load the mlr3learners package, which contains the ranger learner (a package which implements the “Random Forest” algorithm).\n\nlibrary(mlr3learners)\nlrn_ranger = lrn(\"regr.ranger\", num.trees = 15L)\nres = resample(task = task_train, lrn_ranger, cv3)\nres$score(msr(\"regr.rmse\"))\n\n task_id learner_id resampling_id iteration regr.rmse\n1: kc_housing regr.ranger cv 1 142.2424\n2: kc_housing regr.ranger cv 2 161.6867\n3: kc_housing regr.ranger cv 3 138.2549\nHidden columns: task, learner, resampling, prediction\n\nsprintf(\"RMSE of the simple ranger: %s\", round(sqrt(res$aggregate()), 2))\n\n[1] \"RMSE of the simple ranger: 147.75\"\n\n\nOften tuning RandomForest methods does not increase predictive performances substantially. If time permits, it can nonetheless lead to improvements and should thus be performed. In this case, we resort to tune a different kind of model: Gradient Boosted Decision Trees from the package xgboost.\n\n\nA better baseline: AutoTuner\nTuning can often further improve the performance. In this case, we tune the xgboost learner in order to see whether this can improve performance. For the AutoTuner we have to specify a Termination Criterion (how long the tuning should run) a Tuner (which tuning method to use) and a ParamSet (which space we might want to search through). For now, we do not use the zipcode column, as xgboost cannot naturally deal with categorical features. The AutoTuner automatically performs nested cross-validation.\n\nlrn_xgb = lrn(\"regr.xgboost\")\n\n# Define the search space\nsearch_space = ps(\n eta = p_dbl(lower = 0.2, upper = .4),\n min_child_weight = p_dbl(lower = 1, upper = 20),\n subsample = p_dbl(lower = .7, upper = .8),\n colsample_bytree = p_dbl(lower = .9, upper = 1),\n colsample_bylevel = p_dbl(lower = .5, upper = .7),\n nrounds = p_int(lower = 1L, upper = 25))\n\nat = auto_tuner(\n tuner = tnr(\"random_search\", batch_size = 40),\n learner = lrn_xgb,\n resampling = rsmp(\"holdout\"),\n measure = msr(\"regr.rmse\"),\n search_space = search_space,\n term_evals = 10)\n\n\n# And resample the AutoTuner\nres = resample(tsk_nozip, at, cv3, store_models = TRUE)\n\n\nres$score(msr(\"regr.rmse\"))\n\n task_id learner_id resampling_id iteration regr.rmse\n1: kc_housing regr.xgboost.tuned cv 1 147.0554\n2: kc_housing regr.xgboost.tuned cv 2 136.4282\n3: kc_housing regr.xgboost.tuned cv 3 132.4484\nHidden columns: task, learner, resampling, prediction\n\nsprintf(\"RMSE of the tuned xgboost: %s\", round(sqrt(res$aggregate()), 2))\n\n[1] \"RMSE of the tuned xgboost: 138.78\"\n\n\nWe can obtain the resulting parameters in the respective splits by accessing the ResampleResult.\n\nsapply(res$learners, function(x) x$learner$param_set$values)[-2, ]\n\n [,1] [,2] [,3] \nnrounds 25 23 24 \nverbose 0 0 0 \nearly_stopping_set \"none\" \"none\" \"none\" \neta 0.220869 0.3809271 0.2115116\nmin_child_weight 1.885109 7.472919 1.910491 \nsubsample 0.7542127 0.7884631 0.7000357\ncolsample_bytree 0.9032271 0.9675298 0.9120812\ncolsample_bylevel 0.5259713 0.6817893 0.630818 \n\n\nNOTE: To keep runtime low, we only tune parts of the hyperparameter space of xgboost in this example. Additionally, we only allow for \\(10\\) random search iterations, which is usually too little for real-world applications. Nonetheless, we are able to obtain an improved performance when comparing to the ranger model.\nIn order to further improve our results we have several options:\n\nFind or engineer better features\nRemove Features to avoid overfitting\nObtain additional data (often prohibitive)\nTry more models\nImprove the tuning\n\nIncrease the tuning budget\nEnlarge the tuning search space\nUse a more efficient tuning algorithm\n\nStacking and Ensembles\n\nBelow we will investigate some of those possibilities and investigate whether this improves performance.\n\n\nAdvanced: Engineering Features: Mutating ZIP-Codes\nIn order to better cluster the zip codes, we compute a new feature: med_price: It computes the median price in each zip-code. This might help our model to improve the prediction. This is equivalent to impact encoding more information:\nWe can equip a learner with impact encoding using mlr3pipelines. More information on mlr3pipelines can be obtained from other posts.\n\nlrn_impact = po(\"encodeimpact\", affect_columns = selector_name(\"zipcode\")) %>>% lrn(\"regr.ranger\")\n\nAgain, we run resample() and compute the RMSE.\n\nres = resample(task = task_train, lrn_impact, cv3)\n\n\nres$score(msr(\"regr.rmse\"))\n\n task_id learner_id resampling_id iteration regr.rmse\n1: kc_housing encodeimpact.regr.ranger cv 1 119.4597\n2: kc_housing encodeimpact.regr.ranger cv 2 146.3315\n3: kc_housing encodeimpact.regr.ranger cv 3 125.4193\nHidden columns: task, learner, resampling, prediction\n\nsprintf(\"RMSE of ranger with med_price: %s\", round(sqrt(res$aggregate()), 2))\n\n[1] \"RMSE of ranger with med_price: 130.91\"\n\n\n\n\nAdvanced: Obtaining a sparser model\nIn many cases, we might want to have a sparse model. For this purpose we can use a mlr3filters::Filter implemented in mlr3filters. This can prevent our learner from overfitting make it easier for humans to interpret models as fewer variables influence the resulting prediction.\nIn this example, we use PipeOpFilter (via po(\"filter\", ...)) to add a feature-filter before training the model. For a more in-depth insight, refer to the sections on mlr3pipelines and mlr3filters in the mlr3 book: Feature Selection and Pipelines.\n\nfilter = flt(\"mrmr\")\n\nThe resulting RMSE is slightly higher, and at the same time we only use \\(12\\) features.\n\ngraph = po(\"filter\", filter, param_vals = list(filter.nfeat = 12)) %>>% po(\"learner\", lrn(\"regr.ranger\"))\nlrn_filter = as_learner(graph)\nres = resample(task = task_train, lrn_filter, cv3)\n\n\nres$score(msr(\"regr.rmse\"))\n\n task_id learner_id resampling_id iteration regr.rmse\n1: kc_housing mrmr.regr.ranger cv 1 152.6009\n2: kc_housing mrmr.regr.ranger cv 2 156.7883\n3: kc_housing mrmr.regr.ranger cv 3 149.0143\nHidden columns: task, learner, resampling, prediction\n\nsprintf(\"RMSE of ranger with filtering: %s\", round(sqrt(res$aggregate()), 2))\n\n[1] \"RMSE of ranger with filtering: 152.83\"" + }, + { + "objectID": "gallery/basic/2020-01-30-house-prices-in-king-county/index.html#summary", + "href": "gallery/basic/2020-01-30-house-prices-in-king-county/index.html#summary", + "title": "House Prices in King County", + "section": "Summary:", + "text": "Summary:\nWe have seen different ways to improve models with respect to our criteria by:\n\nChoosing a suitable algorithm\nChoosing good hyperparameters (tuning)\nFiltering features\nEngineering new features\n\nA combination of all the above would most likely yield an even better model. This is left as an exercise to the reader.\nThe best model we found in this example is the ranger model with the added med_price feature. In a final step, we now want to assess the model’s quality on the held-out data we stored in our task_test. In order to do so, and to prevent data leakage, we can only add the median price from the training data.\n\nlibrary(data.table)\n\ndata = task_train$data(cols = c(\"price\", \"zipcode\"))\ndata[, med_price := median(price), by = \"zipcode\"]\ntest_data = task_test$data(cols = \"zipcode\")\ntest = merge(test_data, unique(data[, .(zipcode, med_price)]), all.x = TRUE)\ntask_test$cbind(test)\n\nNow we can use the augmented task_test to predict on new data.\n\nlrn_ranger$train(task_train)\npred = lrn_ranger$predict(task_test)\npred$score(msr(\"regr.rmse\"))\n\nregr.rmse \n 145.01" + }, + { + "objectID": "gallery/basic/2020-03-30-stratification-blocking/index.html", + "href": "gallery/basic/2020-03-30-stratification-blocking/index.html", + "title": "Resampling - Stratified, Blocked and Predefined", + "section": "", + "text": "Intro\nWhen evaluating machine learning algorithms through resampling, it is preferable that each train/test partition will be a representative subset of the whole data set. This post covers three ways to achieve such reliable resampling procedures:\n\nStratified resampling for classification problems where each train/test split maintains the target class distribution of the original data set.\nBlock resampling where a grouping factor determines which observations should be together in train/test splits.\nCustom resampling using predefined and manually created folds for the train/test splits.\n\n\n\nPrerequisites\nWe load the most important packages for this post.\n\nlibrary(mlr3verse)\nlibrary(mlbench)\nlibrary(data.table)\n\nWe initialize the random number generator with a fixed seed for reproducibility.\n\nset.seed(7832)\n\n\n\nStratified resampling\nIn classification tasks, the ratio of the target class distribution should be similar in each train/test split, which is achieved by stratification. This is particularly useful in the case of imbalanced classes and small data sets.\nStratification can also be performed with respect to explanatory categorical variables to ensure that all subgroups are represented in all training and test sets.\nIn mlr3, each Task has a slot $col_roles. This slot shows general roles certain features will have throughout different stages of the machine learning process. At least, the $col_roles slot shows which variables will be used as features and as the target. However, the $col_roles slot can be more diverse and some variables might even serve multiple roles. We can specify the variable used for stratification in task$col_roles$stratum. This will be illustrated in the following example using the german_credit data:\n\ntask_gc = tsk(\"german_credit\")\ntask_gc$col_roles\n\n$feature\n [1] \"age\" \"amount\" \"credit_history\" \"duration\" \n [5] \"employment_duration\" \"foreign_worker\" \"housing\" \"installment_rate\" \n [9] \"job\" \"number_credits\" \"other_debtors\" \"other_installment_plans\"\n[13] \"people_liable\" \"personal_status_sex\" \"present_residence\" \"property\" \n[17] \"purpose\" \"savings\" \"status\" \"telephone\" \n\n$target\n[1] \"credit_risk\"\n\n$name\ncharacter(0)\n\n$order\ncharacter(0)\n\n$stratum\ncharacter(0)\n\n$group\ncharacter(0)\n\n$weight\ncharacter(0)\n\n\nWe use the target feature called credit_risk to specify stratification with respect to the target variable:\n\ntask_gc$col_roles$stratum = \"credit_risk\"\n# alternatively task_gc$col_roles$stratum = task_gc$col_roles$target\n\nAfter the specification of task$col_roles$stratum, the active binding task$strata will show the number of observations in each group and the corresponding row id’s:\n\ntask_gc$strata\n\n N row_id\n1: 700 1,3,4,6,7,8,...\n2: 300 2, 5,10,11,12,14,...\n\n\nSpecify 3-fold cross validation and instantiate the resampling on the task:\n\ncv3 = rsmp(\"cv\", folds = 3)\ncv3$instantiate(task_gc)\ncv3$instance\n\n row_id fold\n 1: 7 1\n 2: 8 1\n 3: 9 1\n 4: 17 1\n 5: 22 1\n --- \n 996: 959 3\n 997: 967 3\n 998: 980 3\n 999: 984 3\n1000: 999 3\n\n\nCheck if the target class distribution is similar in each fold:\n\ndt = merge(cv3$instance, task_gc$data()[, row_id := .I], by = \"row_id\")\ndt[, .(class_ratio = sum(credit_risk == \"bad\") /\n sum(credit_risk == \"good\")), by = fold]\n\n fold class_ratio\n1: 2 0.4291845\n2: 3 0.4291845\n3: 1 0.4273504\n\n\nAnd compare it with the target class distribution from the whole data set:\n\ndt[, .(class_ratio = sum(credit_risk == \"bad\") / sum(credit_risk == \"good\"))]\n\n class_ratio\n1: 0.4285714\n\n\nNote that the variable used for stratification does not necessarily have to be the target class. In fact, multiple categorical features can be used for stratification to maintain their frequency distribution in each fold:\n\ntask_gc$col_roles$stratum = c(\"housing\", \"telephone\")\ntask_gc$strata\n\n N row_id\n1: 280 1,13,20,21,26,30,...\n2: 433 2, 3, 7, 9,10,14,...\n3: 47 4, 5, 45, 76,134,192,...\n4: 61 6,19,37,55,63,69,...\n5: 63 8, 48, 60, 72, 96,100,...\n6: 116 11,12,15,22,23,28,...\n\n\nTo illustrate if stratification based on multiple categorical features works, we need to instantiate the CV folds again as we changed the features used for stratification:\n\ncv3$instantiate(task_gc)\ncv3$instance\n\n row_id fold\n 1: 13 1\n 2: 21 1\n 3: 31 1\n 4: 33 1\n 5: 43 1\n --- \n 996: 945 3\n 997: 973 3\n 998: 974 3\n 999: 986 3\n1000: 993 3\n\n\nAgain, we check the relative frequency of observations in each group (combination of housing and telephone) across all folds:\n\ndt = merge(cv3$instance, task_gc$data()[, row_id := .I], by = \"row_id\")\ndt = dt[, .(freq = .N), by = list(fold, housing, telephone)]\ndt = dcast(dt, housing + telephone ~ fold)\n\nUsing 'freq' as value column. Use 'value.var' to override\n\ndt[, c(3:5) := lapply(.SD, function(x) x / sum(x)), .SDcols = 3:5]\ndt\n\n housing telephone 1 2 3\n1: for free no 0.11607143 0.11711712 0.11480363\n2: for free yes (under customer name) 0.06250000 0.06306306 0.06344411\n3: rent no 0.43154762 0.43243243 0.43504532\n4: rent yes (under customer name) 0.27976190 0.27927928 0.28096677\n5: own no 0.04761905 0.04804805 0.04531722\n6: own yes (under customer name) 0.06250000 0.06006006 0.06042296\n\n\nAnd compare it with the relative frequency from the whole data set:\n\ntask_gc$data()[, .(freq = .N / max(.I)),\n by = list(housing, telephone)\n][order(housing, telephone), ]\n\n housing telephone freq\n1: for free no 0.11681772\n2: for free yes (under customer name) 0.06415479\n3: rent no 0.43300000\n4: rent yes (under customer name) 0.28084253\n5: own no 0.04895833\n6: own yes (under customer name) 0.06106106\n\n\nIt is evident that in each fold, the combination of housing and telephone have similar frequencies that also coincide with the frequencies from the whole data set.\n\n\nBlock resampling\nAn additional concern when specifying resampling is respecting the natural grouping of the data. Blocking refers to the situation where subsets of observations belong together and must not be separated during resampling. Hence, for one train/test set pair the entire block is either in the training set or in the test set.\nThe following example is based on the BreastCancer data set from the mlbench package:\n\ndata(BreastCancer, package = \"mlbench\")\ntask_bc = as_task_classif(BreastCancer, target = \"Class\", positive = \"malignant\")\n\nIn the BreastCancer data set, for example, several observations have the same “Id” (Sample code number) which implies these are samples taken from the same patient at different times.\n\n# Let's count how many observation actually have the same Id more than once\nsum(table(BreastCancer$Id) > 1)\n\n[1] 46\n\n\nThere are 46 Id’s with more than one observation (row).\nThe model trained on this data set will be used to predict cancer status of new patients. Hence, we have to make sure that each Id occurs exactly in one fold, so that all observations with the same Id should be either used for training or for evaluating the model. This way, we get less biased performance estimates via k-fold cross validation. The following example will illustrate block cross validation which can be achieved by specifying a blocking factor in the task$col_roles$group slot:\n\n# Use Id column as block factor\ntask_bc$col_roles$group = \"Id\"\n# Remove Id from feature\n# task_bc$col_roles$feature = setdiff(task_bc$col_roles$feature, \"Id\")\ncv5 = rsmp(\"cv\", folds = 5)\nset.seed(123)\ncv5$instantiate(task_bc)\ncv5$instance\n\n row_id fold\n 1: 1016277 1\n 2: 1044572 1\n 3: 1049815 1\n 4: 1050718 1\n 5: 1054590 1\n --- \n641: 1369821 5\n642: 1371026 5\n643: 1371920 5\n644: 714039 5\n645: 841769 5\n\n\nIn this case, the row_id column of the cv5$instance slot refers to values of the grouping variable “Id”. Additionally, the number of rows of the cv5$instance is the same as the number of unique groups:\n\nall(cv5$instance$row_id %in% BreastCancer$Id)\n\n[1] TRUE\n\nnrow(cv5$instance) == length(unique(BreastCancer$Id))\n\n[1] TRUE\n\n\nIf the specified blocking groups are respected, each Id appears only in exactly one fold. To inspect if blocking was successful when generating the folds we count how often each Id appears in a specific fold and print the Ids that appear in more than one fold:\n\ndt = merge(task_bc$data(), cv5$instance, by.x = \"Id\", by.y = \"row_id\")\ndt = dt[, .(unique_folds = length(unique(fold))), by = Id]\ndt[unique_folds > 1, ]\n\nEmpty data.table (0 rows and 2 cols): Id,unique_folds\n\n\nAs expected, the table is empty as there are no Id’s present in more than one fold.\n\n\nResampling with predefined folds\nIn some use cases, it might be necessary to use predefined folds. When using k-fold cross validation without repetition this can be achieved by manually creating a feature used to denote folds and assigning it to the task$col_roles$group slot. First, we create a vector that contains 5 predefined folds:\n\nfolds = sample(rep(1:5, length.out = nrow(BreastCancer)),\n size = nrow(BreastCancer),\n replace = F\n)\nhead(folds, 20)\n\n [1] 2 2 4 1 5 2 5 3 1 5 4 3 3 4 5 3 3 5 2 4\n\ntable(folds)\n\nfolds\n 1 2 3 4 5 \n140 140 140 140 139 \n\n\nThis vector is now added to the data set and will be used as grouping factor just as when defining block resampling:\n\ntask_bc = TaskClassif$new(\n id = \"BreastCancer\",\n backend = data.frame(BreastCancer, foldIds = as.factor(folds)),\n target = \"Class\",\n positive = \"malignant\"\n)\ntask_bc$col_roles$group = \"foldIds\"\n# Remove \"foldIds\" from features\n# task_bc$col_roles$feature = setdiff(task_bc$col_roles$feature, \"foldIds\")\n\nWe now instantiate a 5-fold CV that will respect the predefined folds:\n\ncv5 = rsmp(\"cv\", folds = 5)\ncv5$instantiate(task_bc)\ncv5$instance\n\n row_id fold\n1: 1 1\n2: 2 2\n3: 3 3\n4: 4 4\n5: 5 5\n\n\nSince we have only five predefined folds, the cv5$instance data table has five rows and shows which of our foldIds values (contained in the row_id column) will belong to which instantiated fold. To check if the predefined groups are respected, we count how often each foldIds appears in a specific fold:\n\ndt = merge(task_bc$data(), cv5$instance, by.x = \"foldIds\", by.y = \"row_id\")\ndt[, .(unique_folds = length(unique(fold))), by = foldIds]\n\n foldIds unique_folds\n1: 1 1\n2: 2 1\n3: 3 1\n4: 4 1\n5: 5 1\n\n\nThere are five groups and each foldIds appears only in exactly one fold. This means that each instantiated fold corresponds to one of the predefined folds.\nThe previous example does not cover how to perform repeated k-fold CV or time series CV with predefined indices. This is possible via the mlr_resamplings_custom to which a list of predefined train and test indices can be assigned. In the following example, a custom resampling is created using indices created by caret::createMultiFolds():\n\ntask_gc = tsk(\"german_credit\")\ntrain_ind = caret::createMultiFolds(task_gc$truth(), k = 5, times = 10)\ntest_ind = lapply(train_ind, function(x) setdiff(1:task_gc$nrow, x))\nrc = rsmp(\"custom\")\nrc$instantiate(task_gc, train_ind, test_ind)\n\nWe now check if the instantiated custom resampling contains the intended folds:\n\n# check it for the first fold\nall.equal(train_ind[[1]], rc$train_set(1))\n\n[1] TRUE\n\n# check it for all folds\nunlist(lapply(1:rc$iters, function(i) all.equal(train_ind[[i]], rc$train_set(i))))\n\n [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n[24] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n[47] TRUE TRUE TRUE TRUE\n\n\n\n\nConclusions\nThis post shows how to control the resampling process when using mlr3 in order to account for data specificities." + }, + { + "objectID": "gallery/basic/2020-02-25-remove-correlated-features/index.html", + "href": "gallery/basic/2020-02-25-remove-correlated-features/index.html", + "title": "Select Uncorrelated Features", + "section": "", + "text": "The following example describes a situation where we aim to remove correlated features. This in essence means, that we drop features until no features have a correlation higher than a given cutoff. This is often useful when we for example want to use linear models." + }, + { + "objectID": "gallery/basic/2020-02-25-remove-correlated-features/index.html#prerequisites", + "href": "gallery/basic/2020-02-25-remove-correlated-features/index.html#prerequisites", + "title": "Select Uncorrelated Features", + "section": "Prerequisites", + "text": "Prerequisites\nThis tutorial assumes familiarity with the basics of mlr3pipelines. Consult the mlr3book if some aspects are not fully understandable. Additionally, we compare different cutoff values via tuning using the mlr3tuning package. Again, the mlr3book has an intro to mlr3tuning and paradox.\nThe example describes a very involved use-case, where the behavior of PipeOpSelect is manipulated via a trafo on it’s ParamSet" + }, + { + "objectID": "gallery/basic/2020-02-25-remove-correlated-features/index.html#getting-started", + "href": "gallery/basic/2020-02-25-remove-correlated-features/index.html#getting-started", + "title": "Select Uncorrelated Features", + "section": "Getting started", + "text": "Getting started\nWe load the mlr3verse package which pulls in the most important packages for this example.\n\nlibrary(mlr3verse)\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\nlgr::get_logger(\"bbotk\")$set_threshold(\"warn\")\n\nThe basic pipeline looks as follows: We use PipeOpSelect to select a set of variables followed by a rpart learner.\n\ngraph_learner = po(\"select\") %>>% lrn(\"classif.rpart\")\n\nNow we get to the magic:\nWe want to use the function caret::findCorrelation() from the caret package in order to select uncorrelated variables. This function has a cutoff parameter, that specifies the maximum correlation allowed between variables. In order to expose this variable as a numeric parameter we can tune over we specify the following ParamSet:\n\nsearch_space = ps(cutoff = p_dbl(0, 1))\n\nWe define a function select_cutoff that takes as input a Task and returns a list of features we aim to keep.\nNow we use a trafo to transform the cutoff into a set of variables, which is what PipeOpSelect can work with. Note that we use x$cutoff = NULL in order to remove the temporary parameter we introduced, as PipeOpSelect does not know what to do with it.\n\nsearch_space$trafo = function(x, param_set) {\n cutoff = x$cutoff\n x$select.selector = function(task) {\n fn = task$feature_names\n data = task$data(cols = fn)\n drop = caret::findCorrelation(cor(data), cutoff = cutoff, exact = TRUE, names = TRUE)\n setdiff(fn, drop)\n }\n x$cutoff = NULL\n x\n}\n\nIf you are not sure, you understand the trafo concept, consult the mlr3book. It has a section on the trafo concept.\nNow we tune over different values for cutoff.\n\ninstance = tune(\n tuner = tnr(\"grid_search\"),\n task = tsk(\"iris\"),\n learner = graph_learner,\n resampling = rsmp(\"cv\", folds = 3L),\n measure = msr(\"classif.ce\"),\n search_space = search_space,\n # don't need the following line for optimization, this is for\n # demonstration that different features were selected\n store_models = TRUE)\n\nIn order to demonstrate that different cutoff values result in different features being selected, we can run the following to inspect the trained models. Note this inspects only the trained models of the first CV fold of each evaluated model. The features being excluded depends on the training data seen by the pipeline and may be different in different folds, even at the same cutoff value.\n\nas.data.table(instance$archive)[\n order(cutoff),\n list(cutoff, classif.ce,\n featurenames = lapply(resample_result, function(x) {\n x$learners[[1]]$model$classif.rpart$train_task$feature_names\n }\n ))]\n\n cutoff classif.ce featurenames\n 1: 0.0000000 0.28666667 Sepal.Length\n 2: 0.1111111 0.28666667 Sepal.Length\n 3: 0.2222222 0.28666667 Sepal.Length\n 4: 0.3333333 0.27333333 Sepal.Length,Sepal.Width\n 5: 0.4444444 0.27333333 Sepal.Length,Sepal.Width\n 6: 0.5555556 0.27333333 Sepal.Length,Sepal.Width\n 7: 0.6666667 0.27333333 Sepal.Length,Sepal.Width\n 8: 0.7777778 0.27333333 Sepal.Length,Sepal.Width\n 9: 0.8888889 0.04000000 Petal.Width,Sepal.Length,Sepal.Width\n10: 1.0000000 0.06666667 Petal.Length,Petal.Width,Sepal.Length,Sepal.Width\n\n\nVoila, we created our own PipeOp, that uses very advanced knowledge of mlr3pipelines and paradox in only few lines of code." + }, + { + "objectID": "gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index.html", + "href": "gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index.html", + "title": "Feature Engineering of Date-Time Variables", + "section": "", + "text": "In this tutorial, we demonstrate how mlr3pipelines can be used to easily engineer features based on date-time variables. Relying on the Bike Sharing Dataset and the ranger learner we compare the root mean square error (RMSE) of a random forest using the original features (baseline), to the RMSE of a random forest using newly engineered features on top of the original ones." + }, + { + "objectID": "gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index.html#motivation", + "href": "gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index.html#motivation", + "title": "Feature Engineering of Date-Time Variables", + "section": "Motivation", + "text": "Motivation\nA single date-time variable (i.e., a POSIXct column) contains plenty of information ranging from year, month, day, hour, minute and second to other features such as week of the year, or day of the week. Moreover, most of these features are of cyclical nature, i.e., the eleventh and twelfth hour of a day are one hour apart, but so are the 23rd hour and midnight of the other day (see also this blog post and fastai for more information).\nNot respecting this cyclical nature results in treating hours on a linear continuum. One way to handle a cyclical feature \\(\\mathbf{x}\\) is to compute the sine and cosine transformation of \\(\\frac{2 \\pi \\mathbf{x}}{\\mathbf{x}_{\\text{max}}}\\), with \\(\\mathbf{x}_{\\text{max}} = 24\\) for hours and \\(60\\) for minutes and seconds.\nThis results in a two-dimensional representation of the feature:\n\n\n\n\n\n\n\n\n\nmlr3pipelines provides the PipeOpDateFeatures pipeline which can be used to automatically engineer features based on POSIXct columns, including handling of cyclical features.\nThis is useful as most learners naturally cannot handle dates and POSIXct variables and therefore require conversion prior to training." + }, + { + "objectID": "gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index.html#prerequisites", + "href": "gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index.html#prerequisites", + "title": "Feature Engineering of Date-Time Variables", + "section": "Prerequisites", + "text": "Prerequisites\nWe load the mlr3verse package which pulls in the most important packages for this example. The mlr3learners package loads additional learners.\n\nlibrary(mlr3verse)\nlibrary(mlr3learners)\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")" + }, + { + "objectID": "gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index.html#bike-sharing", + "href": "gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index.html#bike-sharing", + "title": "Feature Engineering of Date-Time Variables", + "section": "Bike Sharing", + "text": "Bike Sharing\nThe Bike Sharing Dataset contains the hourly count of rental bikes between years 2011 and 2012 in Capital bikeshare system with the corresponding weather and seasonal information. The dataset can be downloaded from the UCI Machine Learning Repository. After reading in the data, we fix some factor levels, and convert some data types:\nThe Bike Sharing Dataset contains the hourly count of rental bikes between years 2011 and 2012 in Capital bikeshare system with the corresponding weather and seasonal information. We load the data set from the mlr3data package.\n\ndata(\"bike_sharing\", package = \"mlr3data\")\n\nOur goal will be to predict the total number of rented bikes on a given day: cnt.\n\nskimr::skim(bike_sharing)\n\n\nData summary\n\n\nName\nbike_sharing\n\n\nNumber of rows\n17379\n\n\nNumber of columns\n14\n\n\nKey\nNULL\n\n\n_______________________\n\n\n\nColumn type frequency:\n\n\n\ncharacter\n1\n\n\nfactor\n2\n\n\nlogical\n2\n\n\nnumeric\n9\n\n\n________________________\n\n\n\nGroup variables\nNone\n\n\n\nVariable type: character\n\n\n\n\n\n\n\n\n\n\n\n\n\nskim_variable\nn_missing\ncomplete_rate\nmin\nmax\nempty\nn_unique\nwhitespace\n\n\n\n\ndate\n0\n1\n10\n10\n0\n731\n0\n\n\n\nVariable type: factor\n\n\n\n\n\n\n\n\n\n\n\nskim_variable\nn_missing\ncomplete_rate\nordered\nn_unique\ntop_counts\n\n\n\n\nseason\n0\n1\nFALSE\n4\nsum: 4496, spr: 4409, win: 4242, fal: 4232\n\n\nweather\n0\n1\nFALSE\n4\n1: 11413, 2: 4544, 3: 1419, 4: 3\n\n\n\nVariable type: logical\n\n\n\nskim_variable\nn_missing\ncomplete_rate\nmean\ncount\n\n\n\n\nholiday\n0\n1\n0.03\nFAL: 16879, TRU: 500\n\n\nworking_day\n0\n1\n0.68\nTRU: 11865, FAL: 5514\n\n\n\nVariable type: numeric\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nskim_variable\nn_missing\ncomplete_rate\nmean\nsd\np0\np25\np50\np75\np100\nhist\n\n\n\n\nyear\n0\n1\n0.50\n0.50\n0.00\n0.00\n1.00\n1.00\n1.00\n▇▁▁▁▇\n\n\nmonth\n0\n1\n6.54\n3.44\n1.00\n4.00\n7.00\n10.00\n12.00\n▇▆▆▅▇\n\n\nhour\n0\n1\n11.55\n6.91\n0.00\n6.00\n12.00\n18.00\n23.00\n▇▇▆▇▇\n\n\nweekday\n0\n1\n3.00\n2.01\n0.00\n1.00\n3.00\n5.00\n6.00\n▇▃▃▃▇\n\n\ntemperature\n0\n1\n0.50\n0.19\n0.02\n0.34\n0.50\n0.66\n1.00\n▂▇▇▇▁\n\n\napparent_temperature\n0\n1\n0.48\n0.17\n0.00\n0.33\n0.48\n0.62\n1.00\n▁▆▇▆▁\n\n\nhumidity\n0\n1\n0.63\n0.19\n0.00\n0.48\n0.63\n0.78\n1.00\n▁▃▇▇▆\n\n\nwindspeed\n0\n1\n0.19\n0.12\n0.00\n0.10\n0.19\n0.25\n0.85\n▇▆▂▁▁\n\n\ncount\n0\n1\n189.46\n181.39\n1.00\n40.00\n142.00\n281.00\n977.00\n▇▃▁▁▁\n\n\n\n\n\nThe original dataset does not contain a POSIXct column, but we can easily generate one based on the other variables available (note that as no information regarding minutes and seconds is available, we set them to :00:00):\n\nbike_sharing$date = as.POSIXct(paste0(bike_sharing$date, \" \", bike_sharing$hour, \":00:00\"),\n tz = \"GMT\", format = \"%Y-%m-%d %H:%M:%S\")" + }, + { + "objectID": "gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index.html#baseline-random-forest", + "href": "gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index.html#baseline-random-forest", + "title": "Feature Engineering of Date-Time Variables", + "section": "Baseline Random Forest", + "text": "Baseline Random Forest\nWe construct a new regression task and keep a holdout set.\n\ntask = as_task_regr(bike_sharing, target = \"count\")\n\nvalidation_set = sample(seq_len(task$nrow), size = 0.3 * task$nrow)\n\ntask$set_row_roles(validation_set, roles = \"holdout\")\n\nTo estimate the performance on unseen data, we will use a 3-fold cross-validation. Note that this involves validating on past data, which is usually bad practice but should suffice for this example:\n\ncv3 = rsmp(\"cv\", folds = 3)\n\nTo obtain reliable estimates on how well our model generalizes to the future, we would have to split our training and test sets according to the date variable.\nAs our baseline model, we use a random forest, ranger learner. For the baseline, we dropdate, our new POSIXct variable which we will only use later.\n\nlearner_ranger = lrn(\"regr.ranger\")\ntask_ranger = task$clone()\ntask_ranger$select(setdiff(task$feature_names, c(\"date\")))\n\nWe can then use resample() with 3-fold cross-validation:\n\nrr_ranger = resample(task_ranger, learner = learner_ranger, resampling = cv3)\n\nrr_ranger$score(msr(\"regr.mse\"))[, .(iteration, task_id, learner_id, resampling_id, regr.mse)]\n\n iteration task_id learner_id resampling_id regr.mse\n1: 1 bike_sharing regr.ranger cv 4543.904\n2: 2 bike_sharing regr.ranger cv 4276.996\n3: 3 bike_sharing regr.ranger cv 4767.763\n\n\nWe calculate the average RMSE.\n\nrr_ranger$aggregate()\n\nregr.mse \n4529.554 \n\n\nWe now want to improve our baseline model by using newly engineered features based on the date POSIXct column." + }, + { + "objectID": "gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index.html#pipeopdatefeatures", + "href": "gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index.html#pipeopdatefeatures", + "title": "Feature Engineering of Date-Time Variables", + "section": "PipeOpDateFeatures", + "text": "PipeOpDateFeatures\nTo engineer new features we use PipeOpDateFeatures. This pipeline automatically dispatches on POSIXct columns of the data and by default adds plenty of new date-time related features. Here, we want to add all except for minute and second, because this information is not available. As we additionally want to use cyclical versions of the features we set cyclic = TRUE:\n\npipeop_date = po(\"datefeatures\", cyclic = TRUE, minute = FALSE, second = FALSE)\n\nTraining this pipeline will result in simply adding the new features (and removing the original POSIXct feature(s) used for the feature engineering, see also the keep_date_var parameter). In our task, we can now drop the features, yr, mnth, hr, and weekday, because our pipeline will generate these anyways:\n\ntask_ex = task$clone()\ntask_ex$select(setdiff(task$feature_names,\n c(\"instant\", \"dteday\", \"yr\", \"mnth\", \"hr\", \"weekday\", \"casual\", \"registered\")))\n\npipeop_date$train(list(task_ex))\n\n$output\n<TaskRegr:bike_sharing> (12166 x 32)\n* Target: count\n* Properties: -\n* Features (31):\n - dbl (23): apparent_temperature, date.day_of_month, date.day_of_month_cos, date.day_of_month_sin,\n date.day_of_week, date.day_of_week_cos, date.day_of_week_sin, date.day_of_year, date.day_of_year_cos,\n date.day_of_year_sin, date.hour, date.hour_cos, date.hour_sin, date.month, date.month_cos,\n date.month_sin, date.week_of_year, date.week_of_year_cos, date.week_of_year_sin, date.year, humidity,\n temperature, windspeed\n - lgl (3): date.is_day, holiday, working_day\n - int (3): hour, month, year\n - fct (2): season, weather\n\n\nNote that it may be useful to familiarize yourself with PipeOpRemoveConstants which can be used after the feature engineering to remove features that are constant. PipeOpDateFeatures does not do this step automatically.\nTo combine this feature engineering step with a random forest, ranger learner, we now construct a GraphLearner." + }, + { + "objectID": "gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index.html#using-the-new-features-in-a-graphlearner", + "href": "gallery/basic/2020-05-02-feature-engineering-of-date-time-variables/index.html#using-the-new-features-in-a-graphlearner", + "title": "Feature Engineering of Date-Time Variables", + "section": "Using the New Features in a GraphLearner", + "text": "Using the New Features in a GraphLearner\nWe create a GraphLearner consisting of the PipeOpDateFeatures pipeline and a ranger learner. This GraphLearner then behaves like any other Learner:\n\ngraph = po(\"datefeatures\", cyclic = TRUE, minute = FALSE, second = FALSE) %>>%\n lrn(\"regr.ranger\")\n\ngraph_learner = as_learner(graph)\n\nplot(graph, html = FALSE)\n\n\n\n\n\n\n\n\nUsing resample() with 3-fold cross-validation on the task yields:\n\ntask_graph_learner = task$clone()\ntask_graph_learner$select(setdiff(task$feature_names,\n c(\"instant\", \"dteday\", \"yr\", \"mnth\", \"hr\", \"weekday\", \"casual\", \"registered\")))\n\nrr_graph_learner = resample(task_graph_learner, learner = graph_learner, resampling = cv3)\n\nrr_graph_learner$score(msr(\"regr.mse\"))\n\n task_id learner_id resampling_id iteration regr.mse\n1: bike_sharing datefeatures.regr.ranger cv 1 2521.642\n2: bike_sharing datefeatures.regr.ranger cv 2 2229.746\n3: bike_sharing datefeatures.regr.ranger cv 3 2254.390\nHidden columns: task, learner, resampling, prediction\n\n\n\n\n\n\n\n\nWe calculate the average RMSE.\n\nrr_graph_learner$aggregate()\n\nregr.mse \n2335.259 \n\n\nand therefore improved by almost 94%!\nFinally, we fit our GraphLearner on the complete training set and predict on the validation set:\n\ntask$select(setdiff(task$feature_names, c(\"year\", \"month\", \"hour\", \"weekday\")))\n\ngraph_learner$train(task)\n\nprediction = graph_learner$predict(task, row_ids = task$row_roles$validation)\n\nWhere we can obtain the RMSE on the held-out validation data.\n\nprediction$score(msr(\"regr.mse\"))\n\nregr.mse \n460.0281" + }, + { + "objectID": "gallery/basic/2020-01-31-encode-factors-for-xgboost/index.html", + "href": "gallery/basic/2020-01-31-encode-factors-for-xgboost/index.html", + "title": "Encode Factor Levels for xgboost", + "section": "", + "text": "The package xgboost unfortunately does not support handling of categorical features. Therefore, it is required to manually convert factor columns to numerical dummy features. We show how to use mlr3pipelines to augment the xgboost learner with an automatic factor encoding.\nWe load the mlr3verse package which pulls in the most important packages for this example.\nlibrary(mlr3verse)\n\nLoading required package: mlr3\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")" + }, + { + "objectID": "gallery/basic/2020-01-31-encode-factors-for-xgboost/index.html#construct-the-base-objects", + "href": "gallery/basic/2020-01-31-encode-factors-for-xgboost/index.html#construct-the-base-objects", + "title": "Encode Factor Levels for xgboost", + "section": "Construct the Base Objects", + "text": "Construct the Base Objects\nFirst, we take an example task with factors (german_credit) and create the xgboost learner:\n\nlibrary(mlr3learners)\n\ntask = tsk(\"german_credit\")\nprint(task)\n\n<TaskClassif:german_credit> (1000 x 21): German Credit\n* Target: credit_risk\n* Properties: twoclass\n* Features (20):\n - fct (14): credit_history, employment_duration, foreign_worker, housing, job, other_debtors,\n other_installment_plans, people_liable, personal_status_sex, property, purpose, savings, status,\n telephone\n - int (3): age, amount, duration\n - ord (3): installment_rate, number_credits, present_residence\n\nlearner = lrn(\"classif.xgboost\", nrounds = 100)\nprint(learner)\n\n<LearnerClassifXgboost:classif.xgboost>\n* Model: -\n* Parameters: nrounds=100, nthread=1, verbose=0, early_stopping_set=none\n* Packages: mlr3, mlr3learners, xgboost\n* Predict Types: [response], prob\n* Feature Types: logical, integer, numeric\n* Properties: hotstart_forward, importance, missings, multiclass, twoclass, weights\n\n\nWe now compare the feature types of the task and the supported feature types:\n\nunique(task$feature_types$type)\n\n[1] \"integer\" \"factor\" \"ordered\"\n\nlearner$feature_types\n\n[1] \"logical\" \"integer\" \"numeric\"\n\nsetdiff(task$feature_types$type, learner$feature_types)\n\n[1] \"factor\" \"ordered\"\n\n\nIn this example, we have to convert factors and ordered factors to numeric columns to apply the xgboost learner. Because xgboost is based on decision trees (at least in its default settings), it is perfectly fine to convert the ordered factors to integer. Unordered factors must still be encoded though." + }, + { + "objectID": "gallery/basic/2020-01-31-encode-factors-for-xgboost/index.html#construct-pipeline", + "href": "gallery/basic/2020-01-31-encode-factors-for-xgboost/index.html#construct-pipeline", + "title": "Encode Factor Levels for xgboost", + "section": "Construct Pipeline", + "text": "Construct Pipeline\nFinally, we construct a linear pipeline consisting of\n\nthe factor encoder fencoder,\nthe ordered factor converter ord_to_int, and\nthe xgboost base learner.\n\n\ngraph = fencoder %>>% ord_to_int %>>% learner\nprint(graph)\n\nGraph with 3 PipeOps:\n ID State sccssors prdcssors\n encode <list> colapply \n colapply <list> classif.xgboost encode\n classif.xgboost <<UNTRAINED>> colapply\n\n\nThe pipeline is wrapped in a GraphLearner so that it behaves like a regular learner:\n\ngraph_learner = as_learner(graph)\n\nWe can now apply the new learner on the task, here with a 3-fold cross validation:\n\nrr = resample(task, graph_learner, rsmp(\"cv\", folds = 3))\nrr$aggregate()\n\nclassif.ce \n 0.2620435 \n\n\nSuccess! We augmented xgboost with handling of factors and ordered factors. If we combine this learner with a tuner from mlr3tuning, we get a universal and competitive learner." + }, + { + "objectID": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html", + "href": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html", + "title": "mlr3 Basics on “Iris” - Hello World!", + "section": "", + "text": "This use case shows how to use the basic mlr3 package on the iris Task, so it’s our “Hello World” example. It assumes no prior knowledge in ML or mlr3. You can find most of the content here also in the mlr3book in a more detailed way. Hence we will not make a lot of general comments, but keep it hands-on and short.\nThe following operations are shown:\n\nCreating Tasks and Learners\nTraining and predicting\nResampling / cross-validation\nInstalling more Learners\nBenchmarking to compare multiple Learners" + }, + { + "objectID": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html#goals-and-prerequisites", + "href": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html#goals-and-prerequisites", + "title": "mlr3 Basics on “Iris” - Hello World!", + "section": "", + "text": "This use case shows how to use the basic mlr3 package on the iris Task, so it’s our “Hello World” example. It assumes no prior knowledge in ML or mlr3. You can find most of the content here also in the mlr3book in a more detailed way. Hence we will not make a lot of general comments, but keep it hands-on and short.\nThe following operations are shown:\n\nCreating Tasks and Learners\nTraining and predicting\nResampling / cross-validation\nInstalling more Learners\nBenchmarking to compare multiple Learners" + }, + { + "objectID": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html#loading-basic-packages", + "href": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html#loading-basic-packages", + "title": "mlr3 Basics on “Iris” - Hello World!", + "section": "Loading basic packages", + "text": "Loading basic packages\nWe load the mlr3verse package which pulls in the most important packages for this example. The mlr3learners package loads additional learners.\n\nlibrary(mlr3verse)\nlibrary(mlr3learners)\n\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")" + }, + { + "objectID": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html#creating-tasks-and-learners", + "href": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html#creating-tasks-and-learners", + "title": "mlr3 Basics on “Iris” - Hello World!", + "section": "Creating tasks and learners", + "text": "Creating tasks and learners\nLet’s work on the canonical, simple iris data set, and try out some ML algorithms. We will start by using a decision tree with default settings.\n\n# creates mlr3 task from scratch, from a data.frame\n# 'target' names the column in the dataset we want to learn to predict\ntask = as_task_classif(iris, target = \"Species\")\n# in this case we could also take the iris example from mlr3's dictionary of shipped example tasks\n# 2 equivalent calls to create a task. The second is just sugar for the user.\ntask = mlr_tasks$get(\"iris\")\ntask = tsk(\"iris\")\nprint(task)\n\n<TaskClassif:iris> (150 x 5): Iris Flowers\n* Target: Species\n* Properties: multiclass\n* Features (4):\n - dbl (4): Petal.Length, Petal.Width, Sepal.Length, Sepal.Width\n\n# create learner from dictionary of mlr3learners\n# 2 equivalent calls:\nlearner_1 = mlr_learners$get(\"classif.rpart\")\nlearner_1 = lrn(\"classif.rpart\")\nprint(learner_1)\n\n<LearnerClassifRpart:classif.rpart>: Classification Tree\n* Model: -\n* Parameters: xval=0\n* Packages: mlr3, rpart\n* Predict Types: [response], prob\n* Feature Types: logical, integer, numeric, factor, ordered\n* Properties: importance, missings, multiclass, selected_features, twoclass, weights" + }, + { + "objectID": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html#train-and-predict", + "href": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html#train-and-predict", + "title": "mlr3 Basics on “Iris” - Hello World!", + "section": "Train and predict", + "text": "Train and predict\nNow the usual ML operations: Train on some observations, predict on others.\n\n# train learner on subset of task\nlearner_1$train(task, row_ids = 1:120)\n# this is what the decision tree looks like\nprint(learner_1$model)\n\nn= 120 \n\nnode), split, n, loss, yval, (yprob)\n * denotes terminal node\n\n1) root 120 70 setosa (0.41666667 0.41666667 0.16666667) \n 2) Petal.Length< 2.45 50 0 setosa (1.00000000 0.00000000 0.00000000) *\n 3) Petal.Length>=2.45 70 20 versicolor (0.00000000 0.71428571 0.28571429) \n 6) Petal.Length< 4.95 49 1 versicolor (0.00000000 0.97959184 0.02040816) *\n 7) Petal.Length>=4.95 21 2 virginica (0.00000000 0.09523810 0.90476190) *\n\n# predict using observations from task\nprediction = learner_1$predict(task, row_ids = 121:150)\n# predict using \"new\" observations from an external data.frame\nprediction = learner_1$predict_newdata(newdata = iris[121:150, ])\nprint(prediction)\n\n<PredictionClassif> for 30 observations:\n row_ids truth response\n 1 virginica virginica\n 2 virginica versicolor\n 3 virginica virginica\n--- \n 28 virginica virginica\n 29 virginica virginica\n 30 virginica virginica" + }, + { + "objectID": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html#evaluation", + "href": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html#evaluation", + "title": "mlr3 Basics on “Iris” - Hello World!", + "section": "Evaluation", + "text": "Evaluation\nLet’s score our Prediction object with some metrics. And take a deeper look by inspecting the confusion matrix.\n\nhead(as.data.table(mlr_measures))\n\n key label task_type packages predict_type task_properties\n1: aic Akaike Information Criterion <NA> mlr3 <NA> \n2: bic Bayesian Information Criterion <NA> mlr3 <NA> \n3: classif.acc Classification Accuracy classif mlr3,mlr3measures response \n4: classif.auc Area Under the ROC Curve classif mlr3,mlr3measures prob twoclass\n5: classif.bacc Balanced Accuracy classif mlr3,mlr3measures response \n6: classif.bbrier Binary Brier Score classif mlr3,mlr3measures prob twoclass\n\nscores = prediction$score(msr(\"classif.acc\"))\nprint(scores)\n\nclassif.acc \n 0.8333333 \n\nscores = prediction$score(msrs(c(\"classif.acc\", \"classif.ce\")))\nprint(scores)\n\nclassif.acc classif.ce \n 0.8333333 0.1666667 \n\ncm = prediction$confusion\nprint(cm)\n\n truth\nresponse setosa versicolor virginica\n setosa 0 0 0\n versicolor 0 0 5\n virginica 0 0 25" + }, + { + "objectID": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html#changing-hyperpars", + "href": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html#changing-hyperpars", + "title": "mlr3 Basics on “Iris” - Hello World!", + "section": "Changing hyperpars", + "text": "Changing hyperpars\nThe Learner contains information about all parameters that can be configured, including data type, constraints, defaults, etc. We can change the hyperparameters either during construction of later through an active binding.\n\nas.data.table(learner_1$param_set)[, .(id, class, lower, upper, nlevels)]\n\n id class lower upper nlevels\n 1: cp ParamDbl 0 1 Inf\n 2: keep_model ParamLgl NA NA 2\n 3: maxcompete ParamInt 0 Inf Inf\n 4: maxdepth ParamInt 1 30 30\n 5: maxsurrogate ParamInt 0 Inf Inf\n 6: minbucket ParamInt 1 Inf Inf\n 7: minsplit ParamInt 1 Inf Inf\n 8: surrogatestyle ParamInt 0 1 2\n 9: usesurrogate ParamInt 0 2 3\n10: xval ParamInt 0 Inf Inf\n\n\n\nlearner_2 = lrn(\"classif.rpart\", predict_type = \"prob\", minsplit = 50)\nlearner_2$param_set$values$minsplit = 50" + }, + { + "objectID": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html#resampling", + "href": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html#resampling", + "title": "mlr3 Basics on “Iris” - Hello World!", + "section": "Resampling", + "text": "Resampling\nResampling simply repeats the train-predict-score loop and collects all results in a nice data.table::data.table().\n\ncv10 = rsmp(\"cv\", folds = 10)\nrr = resample(task, learner_1, cv10)\nprint(rr)\n\n<ResampleResult> with 10 resampling iterations\n task_id learner_id resampling_id iteration warnings errors\n iris classif.rpart cv 1 0 0\n iris classif.rpart cv 2 0 0\n iris classif.rpart cv 3 0 0\n iris classif.rpart cv 4 0 0\n iris classif.rpart cv 5 0 0\n iris classif.rpart cv 6 0 0\n iris classif.rpart cv 7 0 0\n iris classif.rpart cv 8 0 0\n iris classif.rpart cv 9 0 0\n iris classif.rpart cv 10 0 0\n\n\n\nrr$score(msrs(c(\"classif.acc\", \"classif.ce\")))[, .(iteration, task_id, learner_id, resampling_id, classif.ce)]\n\n iteration task_id learner_id resampling_id classif.ce\n 1: 1 iris classif.rpart cv 0.06666667\n 2: 2 iris classif.rpart cv 0.00000000\n 3: 3 iris classif.rpart cv 0.06666667\n 4: 4 iris classif.rpart cv 0.06666667\n 5: 5 iris classif.rpart cv 0.20000000\n 6: 6 iris classif.rpart cv 0.06666667\n 7: 7 iris classif.rpart cv 0.06666667\n 8: 8 iris classif.rpart cv 0.00000000\n 9: 9 iris classif.rpart cv 0.00000000\n10: 10 iris classif.rpart cv 0.20000000\n\n\n\n# get all predictions nicely concatenated in a table\nprediction = rr$prediction()\nas.data.table(prediction)\n\n row_ids truth response\n 1: 5 setosa setosa\n 2: 7 setosa setosa\n 3: 26 setosa setosa\n 4: 34 setosa setosa\n 5: 55 versicolor versicolor\n --- \n146: 100 versicolor versicolor\n147: 113 virginica virginica\n148: 124 virginica virginica\n149: 136 virginica virginica\n150: 139 virginica versicolor\n\n\n\ncm = prediction$confusion\nprint(cm)\n\n truth\nresponse setosa versicolor virginica\n setosa 50 0 0\n versicolor 0 45 6\n virginica 0 5 44" + }, + { + "objectID": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html#populating-the-learner-dictionary", + "href": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html#populating-the-learner-dictionary", + "title": "mlr3 Basics on “Iris” - Hello World!", + "section": "Populating the learner dictionary", + "text": "Populating the learner dictionary\nmlr3learners ships out with a dozen different popular Learners. We can list them from the dictionary. If we want more, we can install an extension package, mlr3extralearners, from GitHub. Note how after loading mlr3extralearners the dictionary increases in size.\n\nhead(as.data.table(mlr_learners)[, c(\"key\", \"packages\")])\n\n key packages\n1: classif.cv_glmnet mlr3,mlr3learners,glmnet\n2: classif.debug mlr3\n3: classif.featureless mlr3\n4: classif.glmnet mlr3,mlr3learners,glmnet\n5: classif.kknn mlr3,mlr3learners,kknn\n6: classif.lda mlr3,mlr3learners,MASS\n\nlibrary(mlr3extralearners)\nprint(as.data.table(mlr_learners)[, c(\"key\", \"packages\")])\n\n key packages\n 1: classif.AdaBoostM1 mlr3,mlr3extralearners,RWeka\n 2: classif.C50 mlr3,mlr3extralearners,C50\n 3: classif.IBk mlr3,mlr3extralearners,RWeka\n 4: classif.J48 mlr3,mlr3extralearners,RWeka\n 5: classif.JRip mlr3,mlr3extralearners,RWeka\n --- \n137: surv.priority_lasso mlr3,mlr3proba,prioritylasso\n138: surv.ranger mlr3,mlr3proba,mlr3extralearners,ranger\n139: surv.rfsrc mlr3,mlr3proba,mlr3extralearners,randomForestSRC,pracma\n140: surv.svm mlr3,mlr3proba,mlr3extralearners,survivalsvm\n141: surv.xgboost mlr3,mlr3proba,mlr3extralearners,xgboost" + }, + { + "objectID": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html#benchmarking-multiple-learners", + "href": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html#benchmarking-multiple-learners", + "title": "mlr3 Basics on “Iris” - Hello World!", + "section": "Benchmarking multiple learners", + "text": "Benchmarking multiple learners\nThe benchmark function can conveniently compare `r ref(“Learner”, “Learners”) on the same dataset(s).\n\nlearners = list(learner_1, learner_2, lrn(\"classif.randomForest\"))\ngrid = benchmark_grid(task, learners, cv10)\nbmr = benchmark(grid)\nprint(bmr)\n\n<BenchmarkResult> of 30 rows with 3 resampling runs\n nr task_id learner_id resampling_id iters warnings errors\n 1 iris classif.rpart cv 10 0 0\n 2 iris classif.rpart cv 10 0 0\n 3 iris classif.randomForest cv 10 0 0\n\nprint(bmr$aggregate(measures = msrs(c(\"classif.acc\", \"classif.ce\"))))\n\n nr task_id learner_id resampling_id iters classif.acc classif.ce\n1: 1 iris classif.rpart cv 10 0.9266667 0.07333333\n2: 2 iris classif.rpart cv 10 0.9266667 0.07333333\n3: 3 iris classif.randomForest cv 10 0.9533333 0.04666667\nHidden columns: resample_result" + }, + { + "objectID": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html#conclusion", + "href": "gallery/basic/2020-03-18-iris-mlr3-basics/index.html#conclusion", + "title": "mlr3 Basics on “Iris” - Hello World!", + "section": "Conclusion", + "text": "Conclusion\nWe left out a lot of details and other features. If you want to know more, read the mlr3book and the documentation of the mentioned packages." + }, + { + "objectID": "gallery/basic/2021-01-20-keras/index.html", + "href": "gallery/basic/2021-01-20-keras/index.html", + "title": "Introduction to mlr3keras - Boston Housing", + "section": "", + "text": "The following article describes how to fit a Neural Network learner to the boston_housing dataset. This article is part of the mlr3keras vignette. For additional information or help on mlr3keras, please consult the mlr3keras website." + }, + { + "objectID": "gallery/pipelines/2020-03-12-intro-pipelines-titanic/index.html", + "href": "gallery/pipelines/2020-03-12-intro-pipelines-titanic/index.html", + "title": "A Pipeline for the Titanic Data Set - Basics", + "section": "", + "text": "We load the mlr3verse package which pulls in the most important packages for this example. The mlr3learners package loads additional learners. The data is part of the mlr3data package.\n\nlibrary(mlr3verse)\nlibrary(mlr3learners)\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\n\nThe titanic data is very interesting to analyze, even though it is part of many tutorials and showcases. This is because it requires many steps often required in real-world applications of machine learning techniques, such as missing value imputation, handling factors and others.\nThe following features are illustrated in this use case section:\n\nSummarizing the data set\nVisualizing data\nSplitting data into train and test data sets\nDefining a task and a learner" + }, + { + "objectID": "gallery/pipelines/2020-03-12-intro-pipelines-titanic/index.html#intro", + "href": "gallery/pipelines/2020-03-12-intro-pipelines-titanic/index.html#intro", + "title": "A Pipeline for the Titanic Data Set - Basics", + "section": "", + "text": "We load the mlr3verse package which pulls in the most important packages for this example. The mlr3learners package loads additional learners. The data is part of the mlr3data package.\n\nlibrary(mlr3verse)\nlibrary(mlr3learners)\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\n\nThe titanic data is very interesting to analyze, even though it is part of many tutorials and showcases. This is because it requires many steps often required in real-world applications of machine learning techniques, such as missing value imputation, handling factors and others.\nThe following features are illustrated in this use case section:\n\nSummarizing the data set\nVisualizing data\nSplitting data into train and test data sets\nDefining a task and a learner" + }, + { + "objectID": "gallery/pipelines/2020-03-12-intro-pipelines-titanic/index.html#exploratory-data-analysis", + "href": "gallery/pipelines/2020-03-12-intro-pipelines-titanic/index.html#exploratory-data-analysis", + "title": "A Pipeline for the Titanic Data Set - Basics", + "section": "Exploratory Data Analysis", + "text": "Exploratory Data Analysis\nWith the dataset, we get an explanation of the meanings of the different variables:\n\n\n\nVariables\nDescription\n\n\n\n\nsurvived\nSurvival\n\n\nname\nName\n\n\nage\nAge\n\n\nsex\nSex\n\n\nsib_sp\nNumber of siblings / spouses aboard\n\n\nparch\nNumber of parents / children aboard\n\n\nfare\nAmount paid for the ticket\n\n\npc_class\nPassenger class\n\n\nembarked\nPort of embarkation\n\n\nticket\nTicket number\n\n\ncabin\nCabin\n\n\n\nWe can use the skimr package in order to get a first overview of the data:\n\ndata(\"titanic\", package = \"mlr3data\")\n\nskimr::skim(titanic)\n\n\nData summary\n\n\nName\ntitanic\n\n\nNumber of rows\n1309\n\n\nNumber of columns\n11\n\n\n_______________________\n\n\n\nColumn type frequency:\n\n\n\ncharacter\n3\n\n\nfactor\n4\n\n\nnumeric\n4\n\n\n________________________\n\n\n\nGroup variables\nNone\n\n\n\nVariable type: character\n\n\n\n\n\n\n\n\n\n\n\n\n\nskim_variable\nn_missing\ncomplete_rate\nmin\nmax\nempty\nn_unique\nwhitespace\n\n\n\n\nname\n0\n1.00\n12\n82\n0\n1307\n0\n\n\nticket\n0\n1.00\n3\n18\n0\n929\n0\n\n\ncabin\n1014\n0.23\n1\n15\n0\n186\n0\n\n\n\nVariable type: factor\n\n\n\n\n\n\n\n\n\n\n\nskim_variable\nn_missing\ncomplete_rate\nordered\nn_unique\ntop_counts\n\n\n\n\nsurvived\n418\n0.68\nFALSE\n2\nno: 549, yes: 342\n\n\npclass\n0\n1.00\nTRUE\n3\n3: 709, 1: 323, 2: 277\n\n\nsex\n0\n1.00\nFALSE\n2\nmal: 843, fem: 466\n\n\nembarked\n2\n1.00\nFALSE\n3\nS: 914, C: 270, Q: 123\n\n\n\nVariable type: numeric\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nskim_variable\nn_missing\ncomplete_rate\nmean\nsd\np0\np25\np50\np75\np100\nhist\n\n\n\n\nage\n263\n0.8\n29.88\n14.41\n0.17\n21.0\n28.00\n39.00\n80.00\n▂▇▅▂▁\n\n\nsib_sp\n0\n1.0\n0.50\n1.04\n0.00\n0.0\n0.00\n1.00\n8.00\n▇▁▁▁▁\n\n\nparch\n0\n1.0\n0.39\n0.87\n0.00\n0.0\n0.00\n0.00\n9.00\n▇▁▁▁▁\n\n\nfare\n1\n1.0\n33.30\n51.76\n0.00\n7.9\n14.45\n31.27\n512.33\n▇▁▁▁▁\n\n\n\n\n\nWe can now create a Task from our data. As we want to classify whether the person survived or not, we will create a TaskClassif. We’ll ignore the ‘titanic_test’ data for now and come back to it later." + }, + { + "objectID": "gallery/pipelines/2020-03-12-intro-pipelines-titanic/index.html#a-first-model", + "href": "gallery/pipelines/2020-03-12-intro-pipelines-titanic/index.html#a-first-model", + "title": "A Pipeline for the Titanic Data Set - Basics", + "section": "A first model", + "text": "A first model\nIn order to obtain solutions comparable to official leaderboards, such as the ones available from kaggle, we split the data into train and validation set before doing any further analysis. Here we are using the predefined split used by Kaggle.\n\ntask = as_task_classif(titanic, target = \"survived\", positive = \"yes\")\ntask$set_row_roles(892:1309, \"holdout\")\ntask\n\n<TaskClassif:titanic> (891 x 11)\n* Target: survived\n* Properties: twoclass\n* Features (10):\n - chr (3): cabin, name, ticket\n - dbl (2): age, fare\n - fct (2): embarked, sex\n - int (2): parch, sib_sp\n - ord (1): pclass\n\n\nOur Task currently has \\(3\\) features of type character, which we don’t really know how to handle: “Cabin”, “Name”, “Ticket” and “PassengerId”. Additionally, from our skimr::skim() of the data, we have seen, that they have many unique values (up to 891).\nWe’ll drop them for now and see how we can deal with them later on.\n\ntask$select(cols = setdiff(task$feature_names, c(\"cabin\", \"name\", \"ticket\")))\n\nAdditionally, we create a resampling instance that allows to compare data.\n\ncv3 = rsmp(\"cv\", folds = 3L)$instantiate(task)\n\nTo get a first impression of what performance we can fit a simple decision tree:\n\nlearner = mlr_learners$get(\"classif.rpart\")\n# or shorter:\nlearner = lrn(\"classif.rpart\")\n\nrr = resample(task, learner, cv3, store_models = TRUE)\n\nrr$aggregate(msr(\"classif.acc\"))\n\nclassif.acc \n 0.8013468 \n\n\nSo our model should have a minimal accuracy of 0.80 in order to improve over the simple decision tree. In order to improve more, we might need to do some feature engineering." + }, + { + "objectID": "gallery/pipelines/2020-02-01-tuning-multiplexer/index.html", + "href": "gallery/pipelines/2020-02-01-tuning-multiplexer/index.html", + "title": "Tuning Over Multiple Learners", + "section": "", + "text": "This use case shows how to tune over multiple learners for a single task. You will learn the following:\n\nBuild a pipeline that can switch between multiple learners\nDefine the hyperparameter search space for the pipeline\nRun a random or grid search (or any other tuner, always works the same)\nRun nested resampling for unbiased performance estimates\n\nThis is an advanced use case. What should you know before:\n\nmlr3 basics\nmlr3tuning basics, especially AutoTuner\nmlr3pipelines, especially branching\n\n\nThe Setup\nAssume, you are given some ML task and what to compare a couple of learners, probably because you want to select the best of them at the end of the analysis. That’s a super standard scenario, it actually sounds so common that you might wonder: Why an (advanced) blog post about this? With pipelines? We will consider 2 cases: (a) Running the learners in their default, so without tuning, and (b) with tuning.\nWe load the mlr3verse package which pulls in the most important packages for this example. The mlr3learners package loads additional learners.\n\nlibrary(mlr3verse)\nlibrary(mlr3tuning)\nlibrary(mlr3learners)\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\nlgr::get_logger(\"bbotk\")$set_threshold(\"warn\")\n\nLet’s define our learners.\n\nlearners = list(\n lrn(\"classif.xgboost\", id = \"xgb\", eval_metric = \"logloss\"),\n lrn(\"classif.ranger\", id = \"rf\")\n)\nlearners_ids = sapply(learners, function(x) x$id)\n\ntask = tsk(\"sonar\") # some random data for this demo\ninner_cv2 = rsmp(\"cv\", folds = 2) # inner loop for nested CV\nouter_cv5 = rsmp(\"cv\", folds = 5) # outer loop for nested CV\n\n\n\nDefault Parameters\n\n\nThe Benchmark-Table Approach\nAssume we don’t want to perform tuning and or with running all learner in their respective defaults. Simply run benchmark on the learners and the tasks. That tabulates our results nicely and shows us what works best.\n\ngrid = benchmark_grid(task, learners, outer_cv5)\nbmr = benchmark(grid)\nbmr$aggregate(measures = msr(\"classif.ce\"))\n\n nr task_id learner_id resampling_id iters classif.ce\n1: 1 sonar xgb cv 5 0.2736353\n2: 2 sonar rf cv 5 0.1973287\nHidden columns: resample_result\n\n\n\n\nThe Pipelines Approach\nOk, why would we ever want to change the simple approach above - and use pipelines / tuning for this? Three reasons:\n\nWhat we are doing with benchmark() is actually statistically flawed, insofar if we report the error of the numerically best method from the benchmark table as its estimated future performance. If we do that we have “optimized on the CV” (we basically ran a grid search over our learners!) and we know that this is will produce optimistically biased results. NB: This is a somewhat ridiculous criticism if we are going over only a handful of options, and the bias will be very small. But it will be noticeable if we do this over hundreds of learners, so it is important to understand the underlying problem. This is a somewhat subtle point, and this gallery post is more about technical hints for mlr3, so we will stop this discussion here.\nFor some tuning algorithms, you might have a chance to more efficiently select from the set of algorithms than running the full benchmark. Because of the categorical nature of the problem, you will not be able to learn stuff like “If learner A works bad, I don’t have to try learner B”, but you can potentially save some resampling iterations. Assume you have so select from 100 candidates, experiments are expensive, and you use a 20-fold CV. If learner A has super-bad results in the first 5 folds of the CV, you might already want to stop here. “Racing” would be such a tuning algorithm.\nIt helps us to foreshadow what comes later in this post where we tune the learners.\n\nThe pipeline just has a single purpose in this example: It should allow us to switch between different learners, depending on a hyperparameter. The pipe consists of three elements:\n\nbranch pipes incoming data to one of the following elements, on different data channels. We can name these channel on construction with options.\nour learners (combined with gunion())\nunbranch combines the forked paths at the end.\n\n\ngraph =\n po(\"branch\", options = learners_ids) %>>%\n gunion(lapply(learners, po)) %>>%\n po(\"unbranch\")\nplot(graph, html = FALSE)\n\n\n\n\n\n\n\n\nThe pipeline has now quite a lot of available hyperparameters. It includes all hyperparameters from all contained learners. But as we don’t tune them here (yet), we don’t care (yet). But the first hyperparameter is special. branch.selection controls over which (named) branching channel our data flows.\n\ngraph$param_set$ids()\n\n [1] \"branch.selection\" \"xgb.alpha\" \"xgb.approxcontrib\" \n [4] \"xgb.base_score\" \"xgb.booster\" \"xgb.callbacks\" \n [7] \"xgb.colsample_bylevel\" \"xgb.colsample_bynode\" \"xgb.colsample_bytree\" \n[10] \"xgb.disable_default_eval_metric\" \"xgb.early_stopping_rounds\" \"xgb.early_stopping_set\" \n[13] \"xgb.eta\" \"xgb.eval_metric\" \"xgb.feature_selector\" \n[16] \"xgb.feval\" \"xgb.gamma\" \"xgb.grow_policy\" \n[19] \"xgb.interaction_constraints\" \"xgb.iterationrange\" \"xgb.lambda\" \n[22] \"xgb.lambda_bias\" \"xgb.max_bin\" \"xgb.max_delta_step\" \n[25] \"xgb.max_depth\" \"xgb.max_leaves\" \"xgb.maximize\" \n[28] \"xgb.min_child_weight\" \"xgb.missing\" \"xgb.monotone_constraints\" \n[31] \"xgb.normalize_type\" \"xgb.nrounds\" \"xgb.nthread\" \n[34] \"xgb.ntreelimit\" \"xgb.num_parallel_tree\" \"xgb.objective\" \n[37] \"xgb.one_drop\" \"xgb.outputmargin\" \"xgb.predcontrib\" \n[40] \"xgb.predictor\" \"xgb.predinteraction\" \"xgb.predleaf\" \n[43] \"xgb.print_every_n\" \"xgb.process_type\" \"xgb.rate_drop\" \n[46] \"xgb.refresh_leaf\" \"xgb.reshape\" \"xgb.seed_per_iteration\" \n[49] \"xgb.sampling_method\" \"xgb.sample_type\" \"xgb.save_name\" \n[52] \"xgb.save_period\" \"xgb.scale_pos_weight\" \"xgb.skip_drop\" \n[55] \"xgb.strict_shape\" \"xgb.subsample\" \"xgb.top_k\" \n[58] \"xgb.training\" \"xgb.tree_method\" \"xgb.tweedie_variance_power\" \n[61] \"xgb.updater\" \"xgb.verbose\" \"xgb.watchlist\" \n[64] \"xgb.xgb_model\" \"rf.alpha\" \"rf.always.split.variables\" \n[67] \"rf.class.weights\" \"rf.holdout\" \"rf.importance\" \n[70] \"rf.keep.inbag\" \"rf.max.depth\" \"rf.min.node.size\" \n[73] \"rf.min.prop\" \"rf.minprop\" \"rf.mtry\" \n[76] \"rf.mtry.ratio\" \"rf.num.random.splits\" \"rf.num.threads\" \n[79] \"rf.num.trees\" \"rf.oob.error\" \"rf.regularization.factor\" \n[82] \"rf.regularization.usedepth\" \"rf.replace\" \"rf.respect.unordered.factors\" \n[85] \"rf.sample.fraction\" \"rf.save.memory\" \"rf.scale.permutation.importance\"\n[88] \"rf.se.method\" \"rf.seed\" \"rf.split.select.weights\" \n[91] \"rf.splitrule\" \"rf.verbose\" \"rf.write.forest\" \n\ngraph$param_set$params$branch.selection\n\n id class lower upper levels default\n1: branch.selection ParamFct NA NA xgb,rf <NoDefault[3]>\n\n\nWe can now tune over this pipeline, and probably running grid search seems a good idea to “touch” every available learner. NB: We have now written down in (much more complicated code) what we did before with benchmark.\n\ngraph_learner = as_learner(graph)\ngraph_learner$id = \"g\"\n\nsearch_space = ps(\n branch.selection = p_fct(c(\"rf\", \"xgb\"))\n)\n\ninstance = tune(\n tuner = tnr(\"grid_search\"),\n task = task,\n learner = graph_learner,\n resampling = inner_cv2,\n measure = msr(\"classif.ce\"),\n search_space = search_space\n)\n\nas.data.table(instance$archive)[, list(branch.selection, classif.ce)]\n\n branch.selection classif.ce\n1: rf 0.1778846\n2: xgb 0.3269231\n\n\nBut: Via this approach we can now get unbiased performance results via nested resampling and using the AutoTuner (which would make much more sense if we would select from 100 models and not 2).\n\nat = auto_tuner(\n tuner = tnr(\"grid_search\"),\n learner = graph_learner,\n resampling = inner_cv2,\n measure = msr(\"classif.ce\"),\n search_space = search_space\n)\n\nrr = resample(task, at, outer_cv5, store_models = TRUE)\n\nAccess inner tuning result.\n\nextract_inner_tuning_results(rr)[, list(iteration, branch.selection, classif.ce)]\n\n iteration branch.selection classif.ce\n1: 1 rf 0.2349398\n2: 2 rf 0.1626506\n3: 3 rf 0.3012048\n4: 4 rf 0.2813396\n5: 5 rf 0.2932444\n\n\nAccess inner tuning archives.\n\nextract_inner_tuning_archives(rr)[, list(iteration, branch.selection, classif.ce, resample_result)]\n\n iteration branch.selection classif.ce resample_result\n 1: 1 rf 0.2349398 <ResampleResult[21]>\n 2: 1 xgb 0.2469880 <ResampleResult[21]>\n 3: 2 rf 0.1626506 <ResampleResult[21]>\n 4: 2 xgb 0.2530120 <ResampleResult[21]>\n 5: 3 xgb 0.3795181 <ResampleResult[21]>\n 6: 3 rf 0.3012048 <ResampleResult[21]>\n 7: 4 xgb 0.3714859 <ResampleResult[21]>\n 8: 4 rf 0.2813396 <ResampleResult[21]>\n 9: 5 xgb 0.3353414 <ResampleResult[21]>\n10: 5 rf 0.2932444 <ResampleResult[21]>\n\n\n\n\nModel-Selection and Tuning with Pipelines\nNow let’s select from our given set of models and tune their hyperparameters. One way to do this is to define a search space for each individual learner, wrap them all with the AutoTuner, then call benchmark() on them. As this is pretty standard, we will skip this here, and show an even neater option, where you can tune over models and hyperparameters in one go. If you have quite a large space of potential learners and combine this with an efficient tuning algorithm, this can save quite some time in tuning as you can learn during optimization which options work best and focus on them. NB: Many AutoML systems work in a very similar way.\n\n\nDefine the Search Space\nRemember, that the pipeline contains a joint set of all contained hyperparameters. Prefixed with the respective PipeOp ID, to make names unique.\n\nas.data.table(graph$param_set)[, list(id, class, lower, upper, nlevels)]\n\n id class lower upper nlevels\n 1: branch.selection ParamFct NA NA 2\n 2: xgb.alpha ParamDbl 0 Inf Inf\n 3: xgb.approxcontrib ParamLgl NA NA 2\n 4: xgb.base_score ParamDbl -Inf Inf Inf\n 5: xgb.booster ParamFct NA NA 3\n 6: xgb.callbacks ParamUty NA NA Inf\n 7: xgb.colsample_bylevel ParamDbl 0 1 Inf\n 8: xgb.colsample_bynode ParamDbl 0 1 Inf\n 9: xgb.colsample_bytree ParamDbl 0 1 Inf\n10: xgb.disable_default_eval_metric ParamLgl NA NA 2\n11: xgb.early_stopping_rounds ParamInt 1 Inf Inf\n12: xgb.early_stopping_set ParamFct NA NA 3\n13: xgb.eta ParamDbl 0 1 Inf\n14: xgb.eval_metric ParamUty NA NA Inf\n15: xgb.feature_selector ParamFct NA NA 5\n16: xgb.feval ParamUty NA NA Inf\n17: xgb.gamma ParamDbl 0 Inf Inf\n18: xgb.grow_policy ParamFct NA NA 2\n19: xgb.interaction_constraints ParamUty NA NA Inf\n20: xgb.iterationrange ParamUty NA NA Inf\n21: xgb.lambda ParamDbl 0 Inf Inf\n22: xgb.lambda_bias ParamDbl 0 Inf Inf\n23: xgb.max_bin ParamInt 2 Inf Inf\n24: xgb.max_delta_step ParamDbl 0 Inf Inf\n25: xgb.max_depth ParamInt 0 Inf Inf\n26: xgb.max_leaves ParamInt 0 Inf Inf\n27: xgb.maximize ParamLgl NA NA 2\n28: xgb.min_child_weight ParamDbl 0 Inf Inf\n29: xgb.missing ParamDbl -Inf Inf Inf\n30: xgb.monotone_constraints ParamUty NA NA Inf\n31: xgb.normalize_type ParamFct NA NA 2\n32: xgb.nrounds ParamInt 1 Inf Inf\n33: xgb.nthread ParamInt 1 Inf Inf\n34: xgb.ntreelimit ParamInt 1 Inf Inf\n35: xgb.num_parallel_tree ParamInt 1 Inf Inf\n36: xgb.objective ParamUty NA NA Inf\n37: xgb.one_drop ParamLgl NA NA 2\n38: xgb.outputmargin ParamLgl NA NA 2\n39: xgb.predcontrib ParamLgl NA NA 2\n40: xgb.predictor ParamFct NA NA 2\n41: xgb.predinteraction ParamLgl NA NA 2\n42: xgb.predleaf ParamLgl NA NA 2\n43: xgb.print_every_n ParamInt 1 Inf Inf\n44: xgb.process_type ParamFct NA NA 2\n45: xgb.rate_drop ParamDbl 0 1 Inf\n46: xgb.refresh_leaf ParamLgl NA NA 2\n47: xgb.reshape ParamLgl NA NA 2\n48: xgb.seed_per_iteration ParamLgl NA NA 2\n49: xgb.sampling_method ParamFct NA NA 2\n50: xgb.sample_type ParamFct NA NA 2\n51: xgb.save_name ParamUty NA NA Inf\n52: xgb.save_period ParamInt 0 Inf Inf\n53: xgb.scale_pos_weight ParamDbl -Inf Inf Inf\n54: xgb.skip_drop ParamDbl 0 1 Inf\n55: xgb.strict_shape ParamLgl NA NA 2\n56: xgb.subsample ParamDbl 0 1 Inf\n57: xgb.top_k ParamInt 0 Inf Inf\n58: xgb.training ParamLgl NA NA 2\n59: xgb.tree_method ParamFct NA NA 5\n60: xgb.tweedie_variance_power ParamDbl 1 2 Inf\n61: xgb.updater ParamUty NA NA Inf\n62: xgb.verbose ParamInt 0 2 3\n63: xgb.watchlist ParamUty NA NA Inf\n64: xgb.xgb_model ParamUty NA NA Inf\n65: rf.alpha ParamDbl -Inf Inf Inf\n66: rf.always.split.variables ParamUty NA NA Inf\n67: rf.class.weights ParamUty NA NA Inf\n68: rf.holdout ParamLgl NA NA 2\n69: rf.importance ParamFct NA NA 4\n70: rf.keep.inbag ParamLgl NA NA 2\n71: rf.max.depth ParamInt 0 Inf Inf\n72: rf.min.node.size ParamInt 1 Inf Inf\n73: rf.min.prop ParamDbl -Inf Inf Inf\n74: rf.minprop ParamDbl -Inf Inf Inf\n75: rf.mtry ParamInt 1 Inf Inf\n76: rf.mtry.ratio ParamDbl 0 1 Inf\n77: rf.num.random.splits ParamInt 1 Inf Inf\n78: rf.num.threads ParamInt 1 Inf Inf\n79: rf.num.trees ParamInt 1 Inf Inf\n80: rf.oob.error ParamLgl NA NA 2\n81: rf.regularization.factor ParamUty NA NA Inf\n82: rf.regularization.usedepth ParamLgl NA NA 2\n83: rf.replace ParamLgl NA NA 2\n84: rf.respect.unordered.factors ParamFct NA NA 3\n85: rf.sample.fraction ParamDbl 0 1 Inf\n86: rf.save.memory ParamLgl NA NA 2\n87: rf.scale.permutation.importance ParamLgl NA NA 2\n88: rf.se.method ParamFct NA NA 2\n89: rf.seed ParamInt -Inf Inf Inf\n90: rf.split.select.weights ParamUty NA NA Inf\n91: rf.splitrule ParamFct NA NA 3\n92: rf.verbose ParamLgl NA NA 2\n93: rf.write.forest ParamLgl NA NA 2\n id class lower upper nlevels\n\n\nWe decide to tune the mtry parameter of the random forest and the nrounds parameter of xgboost. Additionally, we tune branching parameter that selects our learner.\nWe also have to reflect the hierarchical order of the parameter sets (admittedly, this is somewhat inconvenient). We can only set the mtry value if the pipe is configured to use the random forest (ranger). The same applies for the xgboost parameter.\n\nsearch_space = ps(\n branch.selection = p_fct(c(\"rf\", \"xgb\")),\n rf.mtry = p_int(1L, 20L, depends = branch.selection == \"rf\"),\n xgb.nrounds = p_int(1, 500, depends = branch.selection == \"xgb\"))\n\n\n\nTune the Pipeline with a Random Search\nVery similar code as before, we just swap out the search space. And now use random search.\n\ninstance = tune(\n tuner = tnr(\"random_search\"),\n task = task,\n learner = graph_learner,\n resampling = inner_cv2,\n measure = msr(\"classif.ce\"),\n term_evals = 10,\n search_space = search_space\n)\n\nas.data.table(instance$archive)[, list(branch.selection, xgb.nrounds, rf.mtry, classif.ce)]\n\n branch.selection xgb.nrounds rf.mtry classif.ce\n 1: xgb 292 NA 0.1875000\n 2: rf NA 19 0.2692308\n 3: rf NA 5 0.2307692\n 4: xgb 229 NA 0.1875000\n 5: xgb 301 NA 0.1875000\n 6: rf NA 20 0.2596154\n 7: rf NA 8 0.2355769\n 8: rf NA 2 0.2355769\n 9: rf NA 5 0.2500000\n10: rf NA 18 0.2451923\n\n\nThe following shows a quick way to visualize the tuning results.\n\nautoplot(instance, cols_x = c(\"xgb.nrounds\",\"rf.mtry\"))\n\n\n\n\n\n\n\n\nNested resampling, now really needed:\n\nrr = tune_nested(\n tuner = tnr(\"grid_search\"),\n task = task,\n learner = graph_learner,\n inner_resampling = inner_cv2,\n outer_resampling = outer_cv5,\n measure = msr(\"classif.ce\"),\n term_evals = 10L,\n search_space = search_space)\n\nAccess inner tuning result.\n\nextract_inner_tuning_results(rr)[, list(iteration, branch.selection, classif.ce)]\n\n iteration branch.selection classif.ce\n1: 1 rf 0.2108434\n2: 2 rf 0.1807229\n3: 3 rf 0.2289157\n4: 4 xgb 0.1915519\n5: 5 rf 0.1858147" + }, + { + "objectID": "gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index.html", + "href": "gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index.html", + "title": "A Pipeline for the Titanic Data Set - Advanced", + "section": "", + "text": "This is the second post of the titanic use case series. You can find the first use case here.\nIn this section we will focus on more advanced usage of mlr3pipelines . Specifically, this section illustrates the different options when it comes to data imputation and feature engineering. Furthermore, the section shows how to benchmark, feature engineer and compare our results.\nWe load the mlr3verse package which pulls in the most important packages for this example. The mlr3learners package loads additional learners. The data is part of the mlr3data package.\nlibrary(mlr3verse)\nlibrary(mlr3learners)\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\nlgr::get_logger(\"bbotk\")$set_threshold(\"warn\")\nfuture::plan(\"multicore\")\nAs in the basics chapter, we use the titanic data set. To recap we have undertaken the following steps:\ndata(\"titanic\", package = \"mlr3data\")\n\n# setting up the task\ntask = as_task_classif(titanic, target = \"survived\", positive = \"yes\")\ntask$set_row_roles(892:1309, \"holdout\")\ntask$select(cols = setdiff(task$feature_names, c(\"cabin\", \"name\", \"ticket\")))\n\n# setting up the learner\nlearner = lrn(\"classif.rpart\")\n\n#setting up our resampling method\nresampling = rsmp(\"cv\", folds = 3L)$instantiate(task)\n\nres = resample(task, learner, resampling, store_models = TRUE)" + }, + { + "objectID": "gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index.html#imputation", + "href": "gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index.html#imputation", + "title": "A Pipeline for the Titanic Data Set - Advanced", + "section": "Imputation", + "text": "Imputation\nA very simple way to do this to just impute a constant value for each feature. We could i.e. impute every character or factor column with missing and every numeric column with -999. And depending on the model, this might actually be fine. This approach has a few drawbacks though:\n\n-999 could be a real value in the data.\nimputing -999 skews the distribution of the data, which might result in bad models.\n\nAs a result, instead of imputing a constant value, we will do two things: * Draw samples from each numeric features’ histogram using PipeOpImputeHist * Add an additional column for each variable that indicates whether a value was missing or not. If the information that a value was missing is important, this column contains this information.\nThis imputation scheme is called ‘imputation with constants’ and is already implemented in mlr3pipelines . It can be done using PipeOpImputeConstant.\nRemember that we are trying to optimize our predictive power by using a random forest model (mlr_learners_classif.ranger). Now, random forest models do not naturally handle missing values which is the reason why we need imputation. Before imputation, our data looks as follows:\n\ntask$missings()\n\nsurvived age embarked fare parch pclass sex sib_sp \n 0 177 2 0 0 0 0 0 \n\n\nLet’s first deal with the categorical variables:\n\npo_newlvl = po(\"imputeoor\")\ntask_newlvl = po_newlvl$train(list(task))[[1]]\n\nNote that we use the PipeOp in an unusual way, which is why the syntax does not look very clean. We’ll learn how to use a full graph below.\nFirst, let’s look at the result:\n\ntask_newlvl$missings()\n\nsurvived fare parch pclass sex sib_sp age embarked \n 0 0 0 0 0 0 0 0 \n\n\nCool! embarked does not have missing values anymore. Note that PipeOpImputeOOR by default affects character, factor and ordered columns.\nFor the numeric features we want to do two things, impute values and add an indicator column. In order to do this, we need a more complicated structure, a Graph.\nOur po_indicator creates the indicator column. We tell it to only do this for numeric and integer columns via its param_vals, and additionally tell it to create a numeric column (0 = “not missing”, 1 = “missing”).\n\npo_indicator = po(\"missind\",\n affect_columns = selector_type(c(\"numeric\", \"integer\")), type = \"numeric\")\n\nNow we can simultaneously impute features from the histogram and create indicator columns. This can be achieved using the gunion function, which puts two operations in parallel:\n\ngraph = gunion(list(po_indicator, po(\"imputehist\")))\ngraph = graph %>>% po(\"featureunion\")\n\nAfterwards, we cbind the resulting data using po(\"featureunion\"), connecting the different operations using our graph connector: %>>%. We can now also connect the newlvl imputation:\n\ngraph = graph %>>% po(\"imputeoor\")\n\nand see what happens when we now train the whole Graph:\n\ntask_imputed = graph$clone()$train(task)[[1]]\ntask_imputed$missings()\n\n survived missing_age pclass sex fare parch sib_sp age embarked \n 0 0 0 0 0 0 0 0 0 \n\n\nAwesome, now we do not have any missing values!\n\nautoplot(task_imputed)\n\n\n\n\n\n\n\n\nWe could now use task_imputed for resampling and see whether a ranger model does better. But this is dangerous! If we preprocess all training data at once, data could leak through the different cross-validation folds. In order to do this properly, we have to process the training data in every fold separately. Luckily, this is automatically handled in our Graph, if we use it through a GraphLearner.\nWe can simply append a ranger learner to the Graph and create a GraphLearner from this.\n\ngraph_learner = as_learner(graph$clone() %>>%\n po(\"imputesample\") %>>%\n po(\"fixfactors\") %>>%\n po(learner))\n\nWe needed to use the following commands for the Graph: * PipeOpFixFactors: Removes empty factor levels and removes factor levels that do not exist during training. * PipeOpImputeSample: In some cases, if missing factor levels do not occur during training but only while predicting, PipeOpImputeOOR does not create a new level. For those, we sample a random value.\n\nrr = resample(task, graph_learner, resampling, store_models = TRUE)\nrr$aggregate(msr(\"classif.acc\"))\n\nclassif.acc \n 0.7934905 \n\n\nSo our model has not improved heavily, currently it has an accuracy of 0.79." + }, + { + "objectID": "gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index.html#feature-engineering", + "href": "gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index.html#feature-engineering", + "title": "A Pipeline for the Titanic Data Set - Advanced", + "section": "Feature Engineering", + "text": "Feature Engineering\nWe will do this using PipeOpMutate in order to showcase the power of mlr3pipelines . Additionally, we will make use of the character columns. Hence, we will re-select them:\n\ntask$col_roles$feature = c(task$feature_names, c(\"cabin\", \"name\", \"ticket\"))\n\n\nlibrary(\"stringi\")\npo_ftextract = po(\"mutate\", mutation = list(\n fare_per_person = ~ fare / (parch + sib_sp + 1),\n deck = ~ factor(stri_sub(cabin, 1, 1)),\n title = ~ factor(stri_match(name, regex = \", (.*)\\\\.\")[, 2]),\n surname = ~ factor(stri_match(name, regex = \"(.*),\")[, 2]),\n ticket_prefix = ~ factor(stri_replace_all_fixed(stri_trim(stri_match(ticket, regex = \"(.*) \")[, 2]), \".\", \"\"))\n))\n\nQuickly checking what happens:\n\ntask_eng = po_ftextract$clone()$train(list(task))[[1]]\ntask_eng$data()\n\n survived age embarked fare parch pclass sex sib_sp cabin name\n 1: no 22 S 7.2500 0 3 male 1 <NA> Braund, Mr. Owen Harris\n 2: yes 38 C 71.2833 0 1 female 1 C85 Cumings, Mrs. John Bradley (Florence Briggs Thayer)\n 3: yes 26 S 7.9250 0 3 female 0 <NA> Heikkinen, Miss. Laina\n 4: yes 35 S 53.1000 0 1 female 1 C123 Futrelle, Mrs. Jacques Heath (Lily May Peel)\n 5: no 35 S 8.0500 0 3 male 0 <NA> Allen, Mr. William Henry\n --- \n887: no 27 S 13.0000 0 2 male 0 <NA> Montvila, Rev. Juozas\n888: yes 19 S 30.0000 0 1 female 0 B42 Graham, Miss. Margaret Edith\n889: no NA S 23.4500 2 3 female 1 <NA> Johnston, Miss. Catherine Helen \"Carrie\"\n890: yes 26 C 30.0000 0 1 male 0 C148 Behr, Mr. Karl Howell\n891: no 32 Q 7.7500 0 3 male 0 <NA> Dooley, Mr. Patrick\n ticket fare_per_person deck title surname ticket_prefix\n 1: A/5 21171 3.62500 <NA> Mr Braund A/5\n 2: PC 17599 35.64165 C Mrs Cumings PC\n 3: STON/O2. 3101282 7.92500 <NA> Miss Heikkinen STON/O2\n 4: 113803 26.55000 C Mrs Futrelle <NA>\n 5: 373450 8.05000 <NA> Mr Allen <NA>\n --- \n887: 211536 13.00000 <NA> Rev Montvila <NA>\n888: 112053 30.00000 B Miss Graham <NA>\n889: W./C. 6607 5.86250 <NA> Miss Johnston W/C\n890: 111369 30.00000 C Mr Behr <NA>\n891: 370376 7.75000 <NA> Mr Dooley <NA>\n\n\n\nautoplot(task_eng$clone()$select(c(\"sex\", \"age\")), type = \"pairs\")\n\nRegistered S3 method overwritten by 'GGally':\n method from \n +.gg ggplot2\n\n\nWarning: Removed 177 rows containing non-finite values (`stat_boxplot()`).\n\n\n`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.\n\n\nWarning: Removed 177 rows containing non-finite values (`stat_bin()`).\n\n\nWarning: Removed 177 rows containing non-finite values (`stat_density()`).\n\n\nWarning: Removed 177 rows containing non-finite values (`stat_boxplot()`).\n\n\n`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.\n\n\nWarning: Removed 177 rows containing non-finite values (`stat_bin()`).\n\n\n\n\n\n\n\n\n\nNow we can put everything together again, we concatenate our new PipeOp with the Graph created above and use PipeOpSelect in order to de-select the character features we used for feature extraction. Additionally, we collapse the ‘surname’, so only surnames that make up more than 0.6 % of the data are kept.\nIn summary, we do the following:\n\nmutate: The po_ftextract we defined above extracts additional features from the data.\ncollapsefactors: Removes factor levels that make up less then 3 % of the data.\nselect: Drops character columns.\ngunion: Puts two PipeOps in parallel.\n\nmissind: po_indicator adds a column for each numeric with the info whether the value is NA or not.\nimputehist: Imputes numeric and integer columns by sampling from the histogram.\n\nfeatureunion: Cbind’s parallel data streams.\nimputeoor: Imputes factor and ordered columns.\nfixfactors: Removes empty factor levels and removes factor levels that do not exist during training.\nimputesample: In some cases, if missing factor levels do not occur during training but only while predicting, imputeoor does not create a new level. For those, we sample a random value.\nLearner: Appends a learner to the Graph.\n\nThe full graph we created is the following:\n\nlearner = lrn(\"classif.ranger\", num.trees = 500, min.node.size = 4)\n\n\ngraph_final = po_ftextract %>>%\n po(\"collapsefactors\", param_vals = list(no_collapse_above_prevalence = 0.03)) %>>%\n po(\"select\", param_vals = list(selector = selector_invert(selector_type(\"character\")))) %>>%\n gunion(list(po_indicator, po(\"imputehist\"))) %>>%\n po(\"featureunion\") %>>%\n po(\"imputeoor\") %>>%\n po(\"fixfactors\") %>>%\n po(\"imputesample\") %>>%\n po(learner)" + }, + { + "objectID": "gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index.html#evaluation", + "href": "gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index.html#evaluation", + "title": "A Pipeline for the Titanic Data Set - Advanced", + "section": "Evaluation", + "text": "Evaluation\nLet us see if things have improved:\n\ngraph_learner = as_learner(graph_final)\n\nrr = resample(task, graph_learner, resampling, store_models = TRUE)\n\nrr$aggregate(msr(\"classif.acc\"))\n\nclassif.acc \n 0.8249158 \n\n\nWe have improved even more!" + }, + { + "objectID": "gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index.html#benchmarking", + "href": "gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index.html#benchmarking", + "title": "A Pipeline for the Titanic Data Set - Advanced", + "section": "Benchmarking", + "text": "Benchmarking\nTo undertake benchmarking, we need to set up a benchmarking design. The first step is creating a list with the learners we used, namely the learners form the first and second part of this use case.\n\nlearners = list(\n lrn(\"classif.rpart\", predict_type = \"prob\"),\n lrn(\"classif.ranger\", predict_type = \"prob\")\n)\n\nNow we can define our benchmark design. This is done to ensure exhaustive and consistent resampling for all learners. This step is needed to execute over the same train/test split for each task.\n\nbm_design = benchmark_grid(task_imputed, learners, rsmp(\"cv\", folds = 10))\nbmr = benchmark(bm_design, store_models = TRUE)\nprint(bmr)\n\n<BenchmarkResult> of 20 rows with 2 resampling runs\n nr task_id learner_id resampling_id iters warnings errors\n 1 titanic classif.rpart cv 10 0 0\n 2 titanic classif.ranger cv 10 0 0\n\n\nSo, where do we go from here? We could for instance use a boxplot:\n\nautoplot(bmr)\n\n\n\n\n\n\n\n\nFurther we are able to compare sensitivity and specificity. Here we need to ensure that the benchmark results only contain a single Task:\n\nautoplot(bmr$clone()$filter(task_id = \"titanic\"), type = \"roc\")\n\n\n\n\n\n\n\n\nMoreover, one can compare the precision-recall:\n\n# Precision vs Recall\nggplot2::autoplot(bmr, type = \"prc\")\n\n\n\n\n\n\n\n\nAs one can see, there are various options when it comes to benchmarking and visualizing. You could have a look at some other use cases in our gallery for inspiration." + }, + { + "objectID": "gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index.html#future", + "href": "gallery/pipelines/2020-04-27-mlr3pipelines-Imputation-titanic/index.html#future", + "title": "A Pipeline for the Titanic Data Set - Advanced", + "section": "Future", + "text": "Future\nIn this case we have examined a number of different features, but there are many more things to explore! We could extract even more information from the different features and see what happens. But now you are left to yourself! There are many kaggle kernels that treat the Titanic Dataset available. This can be a great starter to find even better models." + }, + { + "objectID": "gallery/pipelines/2020-09-11-liver-patient-classification/index.html", + "href": "gallery/pipelines/2020-09-11-liver-patient-classification/index.html", + "title": "Liver Patient Classification Based on Diagnostic Measures", + "section": "", + "text": "The following examples were created as part of the Introduction to Machine Learning Lecture at LMU Munich. The goal of the project was to create and compare one or several machine learning pipelines for the problem at hand together with exploratory analysis and an exposition of results. The posts were contributed to the mlr3gallery by the authors and edited for better legibility by the editor. We want to thank the authors for allowing us to publish their results. Note, that correctness of the results can not be guaranteed.\n\n\nThis tutorial assumes familiarity with the basics of mlr3tuning and mlr3pipelines. Consult the mlr3book if some aspects are not fully understandable. We load the most important packages for this example.\n\nlibrary(mlr3verse)\nlibrary(dplyr)\nlibrary(tidyr)\nlibrary(DataExplorer)\nlibrary(ggplot2)\nlibrary(gridExtra)\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\nlgr::get_logger(\"bbotk\")$set_threshold(\"warn\")\n\nNote, that expensive calculations are pre-saved in rds files in this tutorial to save computational time.\nMachine learning (ML), a branch of both computer science and statistics, in conjunction with new computing technologies has been transforming research and industries across the board over the past decade. A prime example for this is the healthcare industry, where applications of ML, as well as artificial intelligence in general, have become more and more popular in recent years. One very frequently researched and applied use of ML in the medical field is the area of disease identification and diagnosis. ML technologies have shown potential in detecting anomalies and diseases through pattern recognition, even though an entirely digital diagnosis by a computer is probably still something for the far future. However, suitable and reliable models estimating the risk of diseases could help real doctors make quicker and better decisions today already. In this use case we examined machine learning algorithms and learners for the specific application of liver disease detection. The task is therefore a binary classification task to predict whether a patient has liver disease or not based on some common diagnostic measurements. This report is organized as follows. Section 1 introduces the data and section 2 provides more in-depth data exploration. Section 3 presents learners and their hyperparameter tuning while section 4, dealing with model fitting and benchmarking, presents results and conclusions." + }, + { + "objectID": "gallery/pipelines/2020-09-11-liver-patient-classification/index.html#prerequisites", + "href": "gallery/pipelines/2020-09-11-liver-patient-classification/index.html#prerequisites", + "title": "Liver Patient Classification Based on Diagnostic Measures", + "section": "", + "text": "This tutorial assumes familiarity with the basics of mlr3tuning and mlr3pipelines. Consult the mlr3book if some aspects are not fully understandable. We load the most important packages for this example.\n\nlibrary(mlr3verse)\nlibrary(dplyr)\nlibrary(tidyr)\nlibrary(DataExplorer)\nlibrary(ggplot2)\nlibrary(gridExtra)\n\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented.\n\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\nlgr::get_logger(\"bbotk\")$set_threshold(\"warn\")\n\nNote, that expensive calculations are pre-saved in rds files in this tutorial to save computational time.\nMachine learning (ML), a branch of both computer science and statistics, in conjunction with new computing technologies has been transforming research and industries across the board over the past decade. A prime example for this is the healthcare industry, where applications of ML, as well as artificial intelligence in general, have become more and more popular in recent years. One very frequently researched and applied use of ML in the medical field is the area of disease identification and diagnosis. ML technologies have shown potential in detecting anomalies and diseases through pattern recognition, even though an entirely digital diagnosis by a computer is probably still something for the far future. However, suitable and reliable models estimating the risk of diseases could help real doctors make quicker and better decisions today already. In this use case we examined machine learning algorithms and learners for the specific application of liver disease detection. The task is therefore a binary classification task to predict whether a patient has liver disease or not based on some common diagnostic measurements. This report is organized as follows. Section 1 introduces the data and section 2 provides more in-depth data exploration. Section 3 presents learners and their hyperparameter tuning while section 4, dealing with model fitting and benchmarking, presents results and conclusions." + }, + { + "objectID": "gallery/pipelines/2020-09-11-liver-patient-classification/index.html#univariate-distribution", + "href": "gallery/pipelines/2020-09-11-liver-patient-classification/index.html#univariate-distribution", + "title": "Liver Patient Classification Based on Diagnostic Measures", + "section": "Univariate distribution", + "text": "Univariate distribution\nNext, we looked into the univariate distribution of each of the variables. We began with the target and the only discrete feature, gender, which are both binary.\n\n\n\n\n\n\n\n\n\nThe distribution of the target variable is quite imbalanced, as the barplot shows: the number of patients with and without liver disease equals 416 and 167, respectively. The underrepresentation of a class, in our case those without liver disease, might worsen the performance of ML models. In order to examine this, we additionally fitted the models on a dataset where we randomly over-sampled the minority class, resulting in a perfectly balanced dataset. Furthermore, we applied stratified sampling to ensure the proportion of the classes is maintained during cross-validation.\nThe only discrete feature gender is quite imbalanced, too. As one can see in the next section, this proportion is also observed within each target class. Prior to that, we looked into the distributions of the metric features.\n\n\n\n\n\n\n\n\n\nStrikingly, some of the metric features are extremely right-skewed and contain several extreme values. To reduce the impact of outliers and since some models assume normality of features, we log-transformed these variables." + }, + { + "objectID": "gallery/pipelines/2020-09-11-liver-patient-classification/index.html#features-by-class", + "href": "gallery/pipelines/2020-09-11-liver-patient-classification/index.html#features-by-class", + "title": "Liver Patient Classification Based on Diagnostic Measures", + "section": "Features by class", + "text": "Features by class\nTo picture the relationship between the target and the features, we analysed the distributions of the features by class. First, we examined the discrete feature gender.\n\n\n\n\n\n\n\n\n\nThe percentage of males in the “disease” class is slightly higher, but overall the difference is small. Besides that, the gender imbalance can be observed in both classes, as we mentioned before. To see the differences in metric features, we compare the following boxplots, where right-skewed features are not log-transformed yet.\n\n\n\n\n\n\n\n\n\nExcept for the total amount of protein, for each feature we obtain differences between the median values of the two classes. Notably, in the case of strongly right-skewed features the “disease” class contains far more extreme values than the “no disease” class, which is probably because of its larger size. This effect is weakened by log-transforming such features, as can be seen in the boxplots below. Moreover, the dispersion in the class “disease” is greater for these features, as the length of the boxes indicates. Overall, the features seem to be correlated to the target, so it makes sense to use them for this task and model their relationship with the target.\n\n\n\n\n\n\n\n\n\nNote, that the same result can be achieved more easily by using PipeOpMutate from mlr3pipelines. This PipeOp provides a smooth implementation to scale numeric features for mlr3 tasks." + }, + { + "objectID": "gallery/pipelines/2020-09-11-liver-patient-classification/index.html#correlation", + "href": "gallery/pipelines/2020-09-11-liver-patient-classification/index.html#correlation", + "title": "Liver Patient Classification Based on Diagnostic Measures", + "section": "Correlation", + "text": "Correlation\nAs we mentioned in the description of the data, there are features that are indirectly measured by another one. This suggests that they are highly correlated. Some of the models we want to compare assume independent features or have problems with multicollinearity. Therefore, we checked for correlations between features.\n\n\nRegistered S3 method overwritten by 'GGally':\n method from \n +.gg ggplot2\n\n\nWarning in cor(data, use = method[1], method = method[2]): the standard deviation is zero\n\n\n\n\n\n\n\n\n\nFor four of the pairs we obtained a very high correlation coefficient. Looking at these features, it is clear they affect each other. As the complexity of the model should be minimized and due to multicollinearity concerns, we decided to take only one of each pair. When deciding on which features to keep, we chose those that are more specific and relevant regarding liver disease. Therefore, we chose albumin over the ratio between albumin and globulin and also over the total amount of protein. The same argument applies to using the amount of direct bilirubin instead of the total amount of bilirubin. Regarding aspartate transaminase and alanine transaminase, it was not clear which one to use, especially since we have no given real world implementation for the task and no medical training. Since we did not notice any fundamental differences in the data for these two features, we arbitrarily chose aspartate transaminase." + }, + { + "objectID": "gallery/pipelines/2020-09-11-liver-patient-classification/index.html#final-dataset", + "href": "gallery/pipelines/2020-09-11-liver-patient-classification/index.html#final-dataset", + "title": "Liver Patient Classification Based on Diagnostic Measures", + "section": "Final Dataset", + "text": "Final Dataset\n\n## Reducing, transforming and scaling dataset\nilpd = ilpd %>%\n select(-total_bilirubin, -alanine_transaminase, -total_protein,\n -albumin_globulin_ratio) %>%\n mutate(\n # Recode gender\n gender = as.numeric(ifelse(gender == \"Female\", 1, 0)),\n # Remove labels for class\n diseased = factor(ifelse(diseased == \"yes\", 1, 0)),\n # Log for features with skewed distributions\n alkaline_phosphatase = log(alkaline_phosphatase),\n aspartate_transaminase = log(aspartate_transaminase),\n direct_bilirubin = log(direct_bilirubin)\n )\n\npo_scale = po(\"scale\")\npo_scale$param_set$values$affect_columns =\n selector_name(c(\"age\", \"direct_bilirubin\", \"alkaline_phosphatase\",\n \"aspartate_transaminase\", \"albumin\"))\n\nLastly, we standardized all metric features, as different ranges and units might weigh features. This is especially important for the k-NN model. The following table shows the final dataset and the transformations we applied. Note: Different from log or other transformation, scaling depends on the data themselves. Scaling data before data are split leads to data leakage, were information of train and test set are shared. As Data Leakage causes higher performance, scaling should always be applied in each data split induced by the ML workflow separately. Therefore we strongly recommend the usage of PipeOpScale in such cases.\n\n\n\nVariable\nTransformation\n\n\n\n\nage\nscaled\n\n\nalbumin\nscaled\n\n\nalkaline_phosphatase\nscaled and log-transformed\n\n\naspartate_transaminase\nscaled and log-transformed\n\n\ndirect_bilirubin\nscaled and log-transformed\n\n\ndiseased\nnone\n\n\ngender\nnone" + }, + { + "objectID": "gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html", + "href": "gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html", + "title": "Tuning a Complex Graph", + "section": "", + "text": "# include: false\nrequireNamespace(\"bst\")\n\nLoading required namespace: bst\n\nrequireNamespace(\"fastICA\")\n\nLoading required namespace: fastICA\nIn this use case we show how to tune a rather complex graph consisting of different preprocessing steps and different learners where each preprocessing step and learner itself has parameters that can be tuned. You will learn the following:\nIdeally you already had a look at how to tune over multiple learners.\nFirst, we load the packages we will need:\nlibrary(mlr3verse)\nlibrary(mlr3learners)\nWe initialize the random number generator with a fixed seed for reproducibility, and decrease the verbosity of the logger to keep the output clearly represented. The lgr package is used for logging in all mlr3 packages. The mlr3 logger prints the logging messages from the base package, whereas the bbotk logger is responsible for logging messages from the optimization packages (e.g. mlr3tuning ).\nset.seed(7832)\nlgr::get_logger(\"mlr3\")$set_threshold(\"warn\")\nlgr::get_logger(\"bbotk\")$set_threshold(\"warn\")" + }, + { + "objectID": "gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html#data-and-task", + "href": "gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html#data-and-task", + "title": "Tuning a Complex Graph", + "section": "Data and Task", + "text": "Data and Task\nWe are going to work with some gene expression data included as a supplement in the bst package. The data consists of 2308 gene profiles in 63 training and 20 test samples. The following data preprocessing steps are done analogously as in vignette(\"khan\", package = \"bst\"):\n\ndatafile = system.file(\"extdata\", \"supplemental_data\", package = \"bst\")\ndat0 = read.delim(datafile, header = TRUE, skip = 1)[, -(1:2)]\ndat0 = t(dat0)\ndat = data.frame(dat0[!(rownames(dat0) %in%\n c(\"TEST.9\", \"TEST.13\", \"TEST.5\", \"TEST.3\", \"TEST.11\")), ])\ndat$class = as.factor(\n c(substr(rownames(dat)[1:63], start = 1, stop = 2),\n c(\"NB\", \"RM\", \"NB\", \"EW\", \"RM\", \"BL\", \"EW\", \"RM\", \"EW\", \"EW\", \"EW\", \"RM\",\n \"BL\", \"RM\", \"NB\", \"NB\", \"NB\", \"NB\", \"BL\", \"EW\")\n )\n)\n\nWe then construct our training and test Task :\n\ntask = as_task_classif(dat, target = \"class\", id = \"SRBCT\")\ntask_train = task$clone(deep = TRUE)\ntask_train$filter(1:63)\ntask_test = task$clone(deep = TRUE)\ntask_test$filter(64:83)" + }, + { + "objectID": "gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html#workflow", + "href": "gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html#workflow", + "title": "Tuning a Complex Graph", + "section": "Workflow", + "text": "Workflow\nOur graph will start with log transforming the features, followed by scaling them. Then, either a PCA or ICA is applied to extract principal / independent components followed by fitting a LDA or a ranger random forest is fitted without any preprocessing (the log transformation and scaling should most likely affect the LDA more than the ranger random forest). Regarding the PCA and ICA, both the number of principal / independent components are tuning parameters. Regarding the LDA, we can further choose different methods for estimating the mean and variance and regarding the ranger, we want to tune the mtry and num.tree parameters. Note that the PCA-LDA combination has already been successfully applied in different cancer diagnostic contexts when the feature space is of high dimensionality (Morais and Lima 2018).\nTo allow for switching between the PCA / ICA-LDA and ranger we can either use branching or proxy pipelines, i.e., PipeOpBranch and PipeOpUnbranch or PipeOpProxy. We will first cover branching in detail and later show how the same can be done using PipeOpProxy." + }, + { + "objectID": "gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html#baseline", + "href": "gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html#baseline", + "title": "Tuning a Complex Graph", + "section": "Baseline", + "text": "Baseline\nFirst, we have a look at the baseline classification accuracy of the LDA and ranger on the training task:\n\nbase = benchmark(benchmark_grid(\n task_train,\n learners = list(lrn(\"classif.lda\"), lrn(\"classif.ranger\")),\n resamplings = rsmp(\"cv\", folds = 3)))\n\nWarning in lda.default(x, grouping, ...): variables are collinear\n\nWarning in lda.default(x, grouping, ...): variables are collinear\n\nWarning in lda.default(x, grouping, ...): variables are collinear\n\nbase$aggregate(measures = msr(\"classif.acc\"))\n\n nr task_id learner_id resampling_id iters classif.acc\n1: 1 SRBCT classif.lda cv 3 0.6666667\n2: 2 SRBCT classif.ranger cv 3 0.9206349\nHidden columns: resample_result\n\n\nThe out-of-the-box ranger appears to already have good performance on the training task. Regarding the LDA, we do get a warning message that some features are colinear. This strongly suggests to reduce the dimensionality of the feature space. Let’s see if we can get some better performance, at least for the LDA." + }, + { + "objectID": "gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html#branching", + "href": "gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html#branching", + "title": "Tuning a Complex Graph", + "section": "Branching", + "text": "Branching\nOur graph starts with log transforming the features (we explicitly use base 10 only for better interpretability when inspecting the model later), using PipeOpColApply, followed by scaling the features using PipeOpScale. Then, the first branch allows for switching between the PCA / ICA-LDA and ranger, and within PCA / ICA-LDA, the second branch allows for switching between PCA and ICA:\n\ngraph1 =\n po(\"colapply\", applicator = function(x) log(x, base = 10)) %>>%\n po(\"scale\") %>>%\n # pca / ica followed by lda vs. ranger\n po(\"branch\", id = \"branch_learner\", options = c(\"pca_ica_lda\", \"ranger\")) %>>%\n gunion(list(\n po(\"branch\", id = \"branch_preproc_lda\", options = c(\"pca\", \"ica\")) %>>%\n gunion(list(\n po(\"pca\"), po(\"ica\")\n )) %>>%\n po(\"unbranch\", id = \"unbranch_preproc_lda\") %>>%\n lrn(\"classif.lda\"),\n lrn(\"classif.ranger\")\n )) %>>%\n po(\"unbranch\", id = \"unbranch_learner\")\n\nNote that the names of the options within each branch are arbitrary, but ideally they describe what is happening. Therefore we go with \"pca_ica_lda\" / \"ranger” and \"pca\" / \"ica\". Finally, we also could have used the branch ppl to make branching easier (we will come back to this in the Proxy section). The graph looks like the following:\n\ngraph1$plot(html = FALSE)\n\n\n\n\n\n\n\n\nWe can inspect the parameters of the ParamSet of the graph to see which parameters can be set:\n\ngraph1$param_set$ids()\n\n [1] \"colapply.applicator\" \"colapply.affect_columns\" \n [3] \"scale.center\" \"scale.scale\" \n [5] \"scale.robust\" \"scale.affect_columns\" \n [7] \"branch_learner.selection\" \"branch_preproc_lda.selection\" \n [9] \"pca.center\" \"pca.scale.\" \n[11] \"pca.rank.\" \"pca.affect_columns\" \n[13] \"ica.n.comp\" \"ica.alg.typ\" \n[15] \"ica.fun\" \"ica.alpha\" \n[17] \"ica.method\" \"ica.row.norm\" \n[19] \"ica.maxit\" \"ica.tol\" \n[21] \"ica.verbose\" \"ica.w.init\" \n[23] \"ica.affect_columns\" \"classif.lda.dimen\" \n[25] \"classif.lda.method\" \"classif.lda.nu\" \n[27] \"classif.lda.predict.method\" \"classif.lda.predict.prior\" \n[29] \"classif.lda.prior\" \"classif.lda.tol\" \n[31] \"classif.ranger.alpha\" \"classif.ranger.always.split.variables\" \n[33] \"classif.ranger.class.weights\" \"classif.ranger.holdout\" \n[35] \"classif.ranger.importance\" \"classif.ranger.keep.inbag\" \n[37] \"classif.ranger.max.depth\" \"classif.ranger.min.node.size\" \n[39] \"classif.ranger.min.prop\" \"classif.ranger.minprop\" \n[41] \"classif.ranger.mtry\" \"classif.ranger.mtry.ratio\" \n[43] \"classif.ranger.num.random.splits\" \"classif.ranger.num.threads\" \n[45] \"classif.ranger.num.trees\" \"classif.ranger.oob.error\" \n[47] \"classif.ranger.regularization.factor\" \"classif.ranger.regularization.usedepth\" \n[49] \"classif.ranger.replace\" \"classif.ranger.respect.unordered.factors\" \n[51] \"classif.ranger.sample.fraction\" \"classif.ranger.save.memory\" \n[53] \"classif.ranger.scale.permutation.importance\" \"classif.ranger.se.method\" \n[55] \"classif.ranger.seed\" \"classif.ranger.split.select.weights\" \n[57] \"classif.ranger.splitrule\" \"classif.ranger.verbose\" \n[59] \"classif.ranger.write.forest\" \n\n\nThe id’s are prefixed by the respective PipeOp they belong to, e.g., pca.rank. refers to the rank. parameter of PipeOpPCA." + }, + { + "objectID": "gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html#search-space", + "href": "gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html#search-space", + "title": "Tuning a Complex Graph", + "section": "Search Space", + "text": "Search Space\nOur graph either fits a LDA after applying PCA or ICA, or alternatively a ranger with no preprocessing. These two options each define selection parameters that we can tune. Moreover, within the respective PipeOp’s we want to tune the following parameters: pca.rank., ica.n.comp, classif.lda.method, classif.ranger.mtry, and classif.ranger.num.trees. The first two parameters are integers that in-principal could range from 1 to the number of features. However, for ICA, the upper bound must not exceed the number of observations and as we will later use 3-fold cross-validation as the resampling method for the tuning, we just set the upper bound to 30 (and do the same for PCA). Regarding the classif.lda.method we will only be interested in \"moment\" estimation vs. minimum volume ellipsoid covariance estimation (\"mve\"). Moreover, we set the lower bound of classif.ranger.mtry to 200 (which is around the number of features divided by 10) and the upper bound to 1000.\n\ntune_ps1 = ps(\n branch_learner.selection =\n p_fct(c(\"pca_ica_lda\", \"ranger\")),\n branch_preproc_lda.selection =\n p_fct(c(\"pca\", \"ica\"), depends = branch_learner.selection == \"pca_ica_lda\"),\n pca.rank. =\n p_int(1, 30, depends = branch_preproc_lda.selection == \"pca\"),\n ica.n.comp =\n p_int(1, 30, depends = branch_preproc_lda.selection == \"ica\"),\n classif.lda.method =\n p_fct(c(\"moment\", \"mve\"), depends = branch_preproc_lda.selection == \"ica\"),\n classif.ranger.mtry =\n p_int(200, 1000, depends = branch_learner.selection == \"ranger\"),\n classif.ranger.num.trees =\n p_int(500, 2000, depends = branch_learner.selection == \"ranger\"))\n\nThe parameter branch_learner.selection defines whether we go down the left (PCA / ICA followed by LDA) or the right branch (ranger). The parameter branch_preproc_lda.selection defines whether a PCA or ICA will be applied prior to the LDA. The other parameters directly belong to the ParamSet of the PCA / ICA / LDA / ranger. Note that it only makes sense to switch between PCA / ICA if the \"pca_ica_lda\" branch was selected beforehand. We have to specify this via the depends parameter.\nFinally, we also could have proceeded to tune the numeric parameters on a log scale. I.e., looking at pca.rank. the performance difference between rank 1 and 2 is probably much larger than between rank 29 and rank 30. The mlr3tuning Tutorial covers such transformations." + }, + { + "objectID": "gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html#tuning", + "href": "gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html#tuning", + "title": "Tuning a Complex Graph", + "section": "Tuning", + "text": "Tuning\nWe can now tune the parameters of our graph as defined in the search space with respect to a measure. We will use the classification accuracy. As a resampling method we use 3-fold cross-validation. We will use the TerminatorNone (i.e., no early termination) for terminating the tuning because we will apply a grid search (we use a grid search because it gives nicely plottable and understandable results but if there were much more parameters, random search or more intelligent optimization methods would be preferred to a grid search:\n\ntune1 = TuningInstanceSingleCrit$new(\n task_train,\n learner = graph1,\n resampling = rsmp(\"cv\", folds = 3),\n measure = msr(\"classif.acc\"),\n search_space = tune_ps1,\n terminator = trm(\"none\")\n)\n\nWe then perform a grid search using a resolution of 4 for the numeric parameters. The grid being used will look like the following (note that the dependencies we specified above are handled automatically):\n\ngenerate_design_grid(tune_ps1, resolution = 4)\n\n\n\n\n\n\n\nWe trigger the tuning.\n\ntuner_gs = tnr(\"grid_search\", resolution = 4, batch_size = 10)\ntuner_gs$optimize(tune1)\n\n branch_learner.selection branch_preproc_lda.selection pca.rank. ica.n.comp classif.lda.method classif.ranger.mtry\n1: pca_ica_lda ica NA 10 mve NA\n classif.ranger.num.trees learner_param_vals x_domain classif.acc\n1: NA <list[8]> <list[4]> 0.984127\n\n\nNow, we can inspect the results ordered by the classification accuracy:\n\nas.data.table(tune1$archive)[order(classif.acc), ]\n\n\n\n\n\n\n\nWe achieve very good accuracy using ranger, more or less regardless how mtry and num.trees are set. However, the LDA also shows very good accuracy when combined with PCA or ICA retaining 30 components.\nFor now, we decide to use ranger with mtry set to 200 and num.trees set to 1000.\nSetting these parameters manually in our graph, then training on the training task and predicting on the test task yields an accuracy of:\n\ngraph1$param_set$values$branch_learner.selection = \"ranger\"\ngraph1$param_set$values$classif.ranger.mtry = 200\ngraph1$param_set$values$classif.ranger.num.trees = 1000\ngraph1$train(task_train)\n\n$unbranch_learner.output\nNULL\n\ngraph1$predict(task_test)[[1L]]$score(msr(\"classif.acc\"))\n\nclassif.acc \n 1 \n\n\nNote that we also could have wrapped our graph in a GraphLearner and proceeded to use this as a learner in an AutoTuner." + }, + { + "objectID": "gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html#proxy", + "href": "gallery/pipelines/2021-02-03-tuning-a-complex-graph/tuning-a-complex-graph.html#proxy", + "title": "Tuning a Complex Graph", + "section": "Proxy", + "text": "Proxy\nInstead of using branches to split our graph with respect to the learner and preprocessing options, we can also use PipeOpProxy. PipeOpProxy accepts a single content parameter that can contain any other PipeOp or Graph. This is extremely flexible in the sense that we do not have to specify our options during construction. However, the parameters of the contained PipeOp or Graph are no longer directly contained in the ParamSet of the resulting graph. Therefore, when tuning the graph, we do have to make use of a trafo function.\n\ngraph2 =\n po(\"colapply\", applicator = function(x) log(x, base = 10)) %>>%\n po(\"scale\") %>>%\n po(\"proxy\")\n\nThis graph now looks like the following:\n\ngraph2$plot(html = FALSE)\n\n\n\n\n\n\n\n\nAt first, this may look like a linear graph. However, as the content parameter of PipeOpProxy can be tuned and set to contain any other PipeOp or Graph, this will allow for a similar non-linear graph as when doing branching.\n\ngraph2$param_set$ids()\n\n[1] \"colapply.applicator\" \"colapply.affect_columns\" \"scale.center\" \"scale.scale\" \n[5] \"scale.robust\" \"scale.affect_columns\" \"proxy.content\" \n\n\nWe can tune the graph by using the same search space as before. However, here the trafo function is of central importance to actually set our options and parameters:\n\ntune_ps2 = tune_ps1$clone(deep = TRUE)\n\nThe trafo function does all the work, i.e., selecting either the PCA / ICA-LDA or ranger as the proxy.content as well as setting the parameters of the respective preprocessing PipeOps and Learners.\n\nproxy_options = list(\n pca_ica_lda =\n ppl(\"branch\", graphs = list(pca = po(\"pca\"), ica = po(\"ica\"))) %>>%\n lrn(\"classif.lda\"),\n ranger = lrn(\"classif.ranger\")\n)\n\nAbove, we made use of the branch ppl allowing us to easily construct a branching graph. Of course we also could have use another nested PipeOpProxy to specify the preprocessing options (\"pca\" vs. \"ica\") within proxy_options if for some reason we do not want to do branching at all. The trafo function below selects one of the proxy_options from above and sets the respective parameters for the PCA, ICA, LDA and ranger. Here, the argument x is a list which will contain sampled / selected parameters from our ParamSet (in our case, tune_ps2). The return value is a list only including the appropriate proxy.content parameter. In each tuning iteration, the proxy.content parameter of our graph will be set to this value.\n\ntune_ps2$trafo = function(x, param_set) {\n proxy.content = proxy_options[[x$branch_learner.selection]]\n if (x$branch_learner.selection == \"pca_ica_lda\") {\n # pca_ica_lda\n proxy.content$param_set$values$branch.selection = x$branch_preproc_lda.selection\n if (x$branch_preproc_lda.selection == \"pca\") {\n proxy.content$param_set$values$pca.rank. = x$pca.rank.\n } else {\n proxy.content$param_set$values$ica.n.comp = x$ica.n.comp\n }\n proxy.content$param_set$values$classif.lda.method = x$classif.lda.method\n } else {\n # ranger\n proxy.content$param_set$values$mtry = x$classif.ranger.mtry\n proxy.content$param_set$values$num.trees = x$classif.ranger.num.trees\n }\n list(proxy.content = proxy.content)\n}\n\nI.e., suppose that the following parameters will be selected from our ParamSet:\n\nx = list(\n branch_learner.selection = \"ranger\",\n classif.ranger.mtry = 200,\n classif.ranger.num.trees = 500)\n\nThe trafo function will then return:\n\ntune_ps2$trafo(x)\n\n$proxy.content\n<LearnerClassifRanger:classif.ranger>\n* Model: -\n* Parameters: num.threads=1, mtry=200, num.trees=500\n* Packages: mlr3, mlr3learners, ranger\n* Predict Types: [response], prob\n* Feature Types: logical, integer, numeric, character, factor, ordered\n* Properties: hotstart_backward, importance, multiclass, oob_error, twoclass, weights\n\n\nTuning can be carried out analogously as done above:\n\ntune2 = TuningInstanceSingleCrit$new(\n task_train,\n learner = graph2,\n resampling = rsmp(\"cv\", folds = 3),\n measure = msr(\"classif.acc\"),\n search_space = tune_ps2,\n terminator = trm(\"none\")\n)\ntuner_gs$optimize(tune2)\n\n\nas.data.table(tune2$archive)[order(classif.acc), ]" + }, + { + "objectID": "gallery/technical/2020-08-13-a-production-example-using-plumber-and-docker/index.html", + "href": "gallery/technical/2020-08-13-a-production-example-using-plumber-and-docker/index.html", + "title": "A Production Example Using Plumber and Docker", + "section": "", + "text": "Production with R has come a long way. In this tutorial, we give a brief example on how to write a REST API and deploy it (relying on the mlr3 ecosystem for the actual training and predicting). Most of this tutorial was inspired by other excellent posts and vignettes:\n\nR can API and So Can You!\nUsing docker to deploy an R plumber API\nAzureContainer’s vignette\n\nAll files presented in this tutorial are available here.\n\nModeling Background\n\nlibrary(data.table)\nlibrary(mlr3)\nlibrary(mlr3pipelines)\n\nWe will use a subset of the boston_housing Task. Our goal is to predict the median value of owner-occupied homes in USD 1000’s (target medv), using the features crim, tax and town (just to have factor, integer, and numeric feature types):\n\ndata = tsk(\"boston_housing\")$data()\ndata = data[, c(\"medv\", \"crim\", \"tax\", \"town\")]\n\n\ntask = TaskRegr$new(\"boston\", backend = data, target = \"medv\")\n\nLet’s create a toy pipeline:\nRegarding modeling, we will keep it very simple and use the rpart learner. Missing numerical features (which could happen during prediction) will be imputed by their median via PipeOpImputeMedian, while missing factorial features will be imputed using a new level via PipeOpImputeOOR. As PipeOpImputeOOR will introduce a new level, \".MISSING\" to impute missing values, we also use PipeOpFixFactors:\n\ng = po(\"imputemedian\") %>>%\n po(\"imputeoor\") %>>%\n po(\"fixfactors\") %>>%\n lrn(\"regr.rpart\")\n\nWe wrap this Graph in a GraphLearner and can train on the Task:\n\ngl = GraphLearner$new(g)\ngl$train(task)\n\nWe can inspect the trained pipeline looking at:\n\ngl$model\n\nFurthermore, we can save the trained pipeline, i.e., as \"gl.rds\":\n\nsaveRDS(gl, \"gl.rds\")\n\nWe will also store some information regarding the features, i.e., the feature names, types and levels (you will later see, why we need to do this):\n\nfeature_info = list(\n feature_names = task$feature_names,\n feature_types = task$feature_types,\n levels = task$levels()\n)\nsaveRDS(feature_info, \"feature_info.rds\")\n\nPutting everything in a file, train_gl.R looks like the following, which we can then source before moving on:\n\n# train_gl.R\n\nlibrary(mlr3)\nlibrary(mlr3pipelines)\n\ndata = tsk(\"boston_housing\")$data()\ndata = data[, c(\"medv\", \"crim\", \"tax\", \"town\")]\ntask = TaskRegr$new(\"boston\", backend = data, target = \"medv\")\n\ng = po(\"imputemedian\") %>>%\n po(\"imputeoor\") %>>%\n po(\"fixfactors\") %>>%\n lrn(\"regr.rpart\")\n\ngl = GraphLearner$new(g)\n\ngl$train(task)\n\nsaveRDS(gl, \"gl.rds\")\n\nfeature_info = list(\n feature_names = task$feature_names,\n feature_types = task$feature_types,\n levels = task$levels()\n)\n\nsaveRDS(feature_info, \"feature_info.rds\")\n\nOur goal of our REST (representational state transfer) API (application programming interface) will be to predict the medv of a new observation, i.e., it should do something like the following:\n\nnewdata = data.table(crim = 3.14, tax = 691, town = \"Newton\")\ngl$predict_newdata(newdata)\n\n<PredictionRegr> for 1 observations:\n row_ids truth response\n 1 NA 32.23288\n\n\nHowever, in our REST API, the newdata will be received at an endpoint that accepts a particular input. In the next section we will use plumber to set up our web service.\n\n\nUsing plumber to set up our REST API\nThe package plumber allows us to create a REST API by simply commenting existing R code. plumber makes use of these comments to define the web service. Running plumber::plumb on the commented R file then results in a runnable web service that other systems can interact with over a network.\nAs an endpoint for predicting the medv, we will use a POST request. This will allow us to enclose data in the body of the request message. More precisely, we assume that the data will be provided in the JSON format.\nWhen a POST request containing the data (in JSON format) is received our code must then:\n\nconvert the input (in JSON format) to a data.table with all feature columns matching their feature type\npredict the medv based on the input using our trained pipeline and provide an output that can be understood by the client\n\nTo make sure that all features match their feature type, we will later use the following function stored in the R file fix_feature_types.R:\n\n# fix_feature_types.R\n\nfix_feature_types = function(feature, feature_name, feature_info) {\n id = match(feature_name, feature_info$feature_names)\n feature_type = feature_info$feature_types$type[id]\n switch(feature_type,\n \"logical\" = as.logical(feature),\n \"integer\" = as.integer(feature),\n \"numeric\" = as.numeric(feature),\n \"character\" = as.character(feature),\n \"factor\" = factor(feature, levels = feature_info$levels[[feature_name]],\n ordered = FALSE),\n \"ordered\" = factor(feature, levels = feature_info$levels[[feature_name]],\n ordered = TRUE),\n \"POSIXct\" = as.POSIXct(feature)\n )\n}\n\nfix_feature_types() can later be applied to the newdata, and will make sure, that all incoming features are converted to their expected feature type as in the original Task we used for training our pipeline (and this is the reason, why we stored the information about the features earlier). Note that in our tutorial we only have factor, integer, and numeric features, but fix_feature_types() should also work for all other supported feature_types listed in mlr_reflections$task_feature_types. However, it may need some customization depending on your own production environment to make the conversions meaningful.\nThe following R file, predict_gl.R loads our trained pipepline and feature information and provides an endpoint for a POST request, \"/predict_medv\". The incoming data then is converted using jsonlite::fromJSON. We expect the incoming data to either be JSON objects in an array or nested JSON objects and therefore we bind the converted vectors row-wise to a data.table using data.table::rbindlist. We then convert all features to their expected feature_types (using the fix_feature_types() function as defined above) and can finally predict the medv using our trained pipeline. As no default serialization from R6 objects to JSON objects exists (yet), we wrap the Prediction in a data.table (of course we could also only return the numeric prediction values):\n\n# predict_gl.R\n\nlibrary(data.table)\nlibrary(jsonlite)\nlibrary(mlr3)\nlibrary(mlr3pipelines)\n\nsource(\"fix_feature_types.R\")\n\ngl = readRDS(\"gl.rds\")\n\nfeature_info = readRDS(\"feature_info.rds\")\n\n#* @post /predict_medv\nfunction(req) {\n # get the JSON string from the post body\n newdata = fromJSON(req$postBody, simplifyVector = FALSE)\n # expect either JSON objects in an array or nested JSON objects\n newdata = rbindlist(newdata, use.names = TRUE)\n # convert all features in place to their expected feature_type\n newdata[, colnames(newdata) := mlr3misc::pmap(\n list(.SD, colnames(newdata)),\n fix_feature_types,\n feature_info = feature_info)]\n # predict and return as a data.table\n as.data.table(gl$predict_newdata(newdata))\n # or only the numeric values\n # gl$predict_newdata(newdata)$response\n}\n\nNote that the only difference to a regular R file is the comment\n\n#* @post /predict_medv`\n\ntelling plumber to construct the endpoint \"/predict_medv\" for a POST request.\nWe can then run plumber::plumb. The following code sets up the web service locally on your personal machine at port 1030 (we use such a high number because some systems require administrator rights to allow processes to listen to lower ports):\n\nlibrary(plumber)\nr = plumb(\"predict_gl.R\")\nr$run(port = 1030, host = \"0.0.0.0\")\n\nCongratulations, your first REST API is running on your local machine. We can test it by providing some data, using curl via the command line:\n\ncurl --data '[{\"crim\":3.14, \"tax\":691, \"town\":\"Newton\"}]' \"http://127.0.0.1:1030/predict_medv\"\n\nThis should return the predicted medv:\n\n[{\"row_id\":1,\"response\":\"32.2329\"}]\n\nAlternatively, we can also use the httr::POST function within R:\n\nnewdata = '[{\"crim\":3.14, \"tax\":691, \"town\":\"Newton\"}]'\nresp = httr::POST(url = \"http://127.0.0.1:1030/predict_medv\",\n body = newdata, encode = \"json\")\nhttr::content(resp)\n\nWe can further play around a bit more and provide more than a single new observation and also check whether our feature type conversion and missing value imputation works:\n\nnewdata = '[\n {\"crim\":3.14, \"tax\":691, \"town\":\"Newton\"},\n {\"crim\":\"not_a_number\", \"tax\":3.14, \"town\":\"Munich\"},\n {\"tax\":\"not_a_number\", \"town\":31, \"crim\":99}\n]'\nresp = httr::POST(url = \"http://127.0.0.1:1030/predict_medv\",\n body = newdata, encode = \"json\")\nhttr::content(resp)\n\nNote that you can also use jsonlite::toJSON to convert a data.frame to JSON data for your toy examples here.\nIn the following final section we want to use Docker to run a virtual machine as a container (an instance of a snapshot of a machine at a moment in time).\n\n\nUsing Docker to Deploy our REST API\nA Docker container image is a lightweight, standalone, executable package of software that includes everything needed to run an application. Suppose we want to run our REST API on an Amazon Web Service or Microsoft’s Azure Cloud. Then we can use a Docker container to easily set up our web service without going through the hassle of configuring manually our hosting instance.\nWe are going to need two things: An image and a container. An image defines the OS and software while the container is the actual running instance of the image. To build a Docker image we have to specify a Dockerfile. Note that it is sensible to set up the whole project in its own directory, e.g., ~/mlr3_api.\nEvery Dockerfile starts with a FROM statement describing the image we are building our image from. In our case we want an R based image that ideally already has plumber and its dependencies installed. Luckily, the trestletech/plumber image exists:\n\nFROM trestletech/plumber\n\nWe then install the R packages needed to set up our REST API (note that we can skip jsonlite, because plumber already depends on it):\n\nRUN R -e 'install.packages(c(\"data.table\", \"mlr3\", \"mlr3pipelines\"))'\n\nNext, we copy our trained pipeline (gl.rds), our stored feature information (feature_info.rds), our R file to convert features, (fix_feature_types.R) and our R file to predict (predict_gl.R) to a new directory /data and set this as the working directory:\n\nRUN mkdir /data\nCOPY gl.rds /data\nCOPY feature_info.rds /data\nCOPY fix_feature_types.R /data\nCOPY predict_gl.R /data\nWORKDIR /data\n\nFinally, we listen on port 1030 and start the server (this is analogously done as manually calling plumber::plumb on the predict_gl.R file and running it):\n\nEXPOSE 1030\nENTRYPOINT [\"R\", \"-e\", \\\n \"r = plumber::plumb('/data/predict_gl.R'); r$run(port = 1030, host = '0.0.0.0')\"]\n\nThe complete Dockerfile looks like the following:\n\nFROM trestletech/plumber\n\nRUN R -e 'install.packages(c(\"data.table\", \"mlr3\", \"mlr3misc\", \"mlr3pipelines\"))'\n\nRUN mkdir /data\nCOPY gl.rds /data\nCOPY feature_info.rds /data\nCOPY fix_feature_types.R /data\nCOPY predict_gl.R /data\nWORKDIR /data\n\nEXPOSE 1030\nENTRYPOINT [\"R\", \"-e\", \\\n \"r = plumber::plumb('/data/predict_gl.R'); r$run(port = 1030, host = '0.0.0.0')\"]\n\nTo build the image we open a terminal in the mlr3_api directory and run:\n\ndocker build -t mlr3-plumber-demo .\n\nThis may take quite some time.\nTo finally run the container, simply use:\n\ndocker run --rm -p 1030:1030 mlr3-plumber-demo\n\nYou can then proceed to provide some data via curl or httr::POST (to the same local address, because the Docker container is still running on your local machine).\nTo stop all running containers use:\n\ndocker stop $(docker ps -a -q)\n\nFinally, you can proceed to deploy your container to an Amazon Web Service or an Azure Cloud. For the latter, the package AzureContainers is especially helpful. If you do plan to do this note that the plumber service above is exposed over HTTP, and there is no authentication layer making it insecure. You may think about adding a layer of authentification and restricting the service to HTTPS." + }, + { + "objectID": "gallery/technical/2022-12-22-mlr3viz/index.html", + "href": "gallery/technical/2022-12-22-mlr3viz/index.html", + "title": "Visualization in mlr3", + "section": "", + "text": "We showcase the visualization functions of the mlr3 ecosystem. The mlr3viz package creates a plot for almost all mlr3 objects. This post displays all available plots with their reproducible code. We start with plots of the base mlr3 objects. This includes boxplots of tasks, dendrograms of cluster learners and ROC curves of predictions. After that, we tune a classification tree and visualize the results. Finally, we show visualizations for filters.\n\n\n\n\n\n\nNote\n\n\n\nThis article will be updated whenever a new plot is available in mlr3viz." + }, + { + "objectID": "gallery/technical/2022-12-22-mlr3viz/index.html#classification", + "href": "gallery/technical/2022-12-22-mlr3viz/index.html#classification", + "title": "Visualization in mlr3", + "section": "Classification", + "text": "Classification\nWe begin with plots of the classification task Palmer Penguins. We plot the class frequency of the target variable.\n\nlibrary(mlr3verse)\nlibrary(mlr3viz)\n\ntask = tsk(\"penguins\")\ntask$select(c(\"body_mass\", \"bill_length\"))\n\nautoplot(task, type = \"target\")\n\n\n\n\n\n\n\n\nThe \"duo\" plot shows the distribution of multiple features.\n\nautoplot(task, type = \"duo\")\n\n\n\n\n\n\n\n\nThe \"pairs\" plot shows the pairwise comparison of multiple features. The classes of the target variable are shown in different colors.\n\nautoplot(task, type = \"pairs\")" + }, + { + "objectID": "gallery/technical/2022-12-22-mlr3viz/index.html#regression", + "href": "gallery/technical/2022-12-22-mlr3viz/index.html#regression", + "title": "Visualization in mlr3", + "section": "Regression", + "text": "Regression\nNext, we plot the regression task mtcars. We create a boxplot of the target variable.\n\ntask = tsk(\"mtcars\")\ntask$select(c(\"am\", \"carb\"))\n\nautoplot(task, type = \"target\")\n\n\n\n\n\n\n\n\nThe \"pairs\" plot shows the pairwise comparison of mutiple features and the target variable.\n\nautoplot(task, type = \"pairs\")" + }, + { + "objectID": "gallery/technical/2022-12-22-mlr3viz/index.html#cluster", + "href": "gallery/technical/2022-12-22-mlr3viz/index.html#cluster", + "title": "Visualization in mlr3", + "section": "Cluster", + "text": "Cluster\nFinally, we plot the cluster task US Arrests. The \"pairs\" plot shows the pairwise comparison of mutiple features.\n\nlibrary(mlr3cluster)\n\ntask = mlr_tasks$get(\"usarrests\")\n\nautoplot(task, type = \"pairs\")" + }, + { + "objectID": "gallery/technical/2022-12-22-mlr3viz/index.html#classification-1", + "href": "gallery/technical/2022-12-22-mlr3viz/index.html#classification-1", + "title": "Visualization in mlr3", + "section": "Classification", + "text": "Classification\nThe \"prediction\" plot shows the decision boundary of a classification learner and the true class labels as points.\n\ntask = tsk(\"pima\")$select(c(\"age\", \"pedigree\"))\nlearner = lrn(\"classif.rpart\")\nlearner$train(task)\n\nautoplot(learner, type = \"prediction\", task)\n\n\n\n\n\n\n\n\nUsing probabilities.\n\ntask = tsk(\"pima\")$select(c(\"age\", \"pedigree\"))\nlearner = lrn(\"classif.rpart\", predict_type = \"prob\")\nlearner$train(task)\n\nautoplot(learner, type = \"prediction\", task)" + }, + { + "objectID": "gallery/technical/2022-12-22-mlr3viz/index.html#regression-1", + "href": "gallery/technical/2022-12-22-mlr3viz/index.html#regression-1", + "title": "Visualization in mlr3", + "section": "Regression", + "text": "Regression\nThe \"prediction\" plot of a regression learner illustrates the decision boundary and the true response as points.\n\ntask = tsk(\"boston_housing\")$select(\"age\")\nlearner = lrn(\"regr.rpart\")\nlearner$train(task)\n\nautoplot(learner, type = \"prediction\", task)\n\n\n\n\n\n\n\n\nWhen using two features, the response surface is plotted in the background.\n\ntask = tsk(\"boston_housing\")$select(c(\"age\", \"rm\"))\nlearner = lrn(\"regr.rpart\")\nlearner$train(task)\n\nautoplot(learner, type = \"prediction\", task)" + }, + { + "objectID": "gallery/technical/2022-12-22-mlr3viz/index.html#glmnet", + "href": "gallery/technical/2022-12-22-mlr3viz/index.html#glmnet", + "title": "Visualization in mlr3", + "section": "GLMNet", + "text": "GLMNet\nThe classification and regression GLMNet learner is equipped with a plot function.\n\nlibrary(mlr3data)\n\ntask = tsk(\"ilpd\")\ntask$select(setdiff(task$feature_names, \"gender\"))\nlearner = lrn(\"classif.glmnet\")\nlearner$train(task)\n\nautoplot(learner, type = \"ggfortify\")\n\n\n\n\n\n\n\n\n\ntask = tsk(\"mtcars\")\nlearner = lrn(\"regr.glmnet\")\nlearner$train(task)\n\nautoplot(learner, type = \"ggfortify\")" + }, + { + "objectID": "gallery/technical/2022-12-22-mlr3viz/index.html#rpart", + "href": "gallery/technical/2022-12-22-mlr3viz/index.html#rpart", + "title": "Visualization in mlr3", + "section": "Rpart", + "text": "Rpart\nWe plot a classification tree of the rpart package. We have to fit the learner with keep_model = TRUE to keep the model object.\n\ntask = tsk(\"penguins\")\nlearner = lrn(\"classif.rpart\", keep_model = TRUE)\nlearner$train(task)\n\nautoplot(learner, type = \"ggparty\")\n\n\n\n\n\n\n\n\nWe can also plot regression trees.\n\ntask = tsk(\"mtcars\")\nlearner = lrn(\"regr.rpart\", keep_model = TRUE)\nlearner$train(task)\n\nautoplot(learner, type = \"ggparty\")" + }, + { + "objectID": "gallery/technical/2022-12-22-mlr3viz/index.html#clusthierachical", + "href": "gallery/technical/2022-12-22-mlr3viz/index.html#clusthierachical", + "title": "Visualization in mlr3", + "section": "ClustHierachical", + "text": "ClustHierachical\nThe \"dend\" plot shows the result of the hierarchical clustering of the data.\n\nlibrary(mlr3cluster)\n\ntask = tsk(\"usarrests\")\nlearner = lrn(\"clust.hclust\")\nlearner$train(task)\n\nautoplot(learner, type = \"dend\", task = task)\n\n\n\n\n\n\n\n\nThe \"scree\" type plots the number of clusters and the height.\n\nautoplot(learner, type = \"scree\")" + }, + { + "objectID": "gallery/technical/2022-12-22-mlr3viz/index.html#classification-2", + "href": "gallery/technical/2022-12-22-mlr3viz/index.html#classification-2", + "title": "Visualization in mlr3", + "section": "Classification", + "text": "Classification\nWe plot the predictions of a classification learner. The \"stacked\" plot shows the predicted and true class labels.\n\ntask = tsk(\"spam\")\nlearner = lrn(\"classif.rpart\", predict_type = \"prob\")\npred = learner$train(task)$predict(task)\n\nautoplot(pred, type = \"stacked\")\n\n\n\n\n\n\n\n\nThe ROC curve plots the true positive rate against the false positive rate at different thresholds.\n\nautoplot(pred, type = \"roc\")\n\n\n\n\n\n\n\n\nThe precision-recall curve plots the precision against the recall at different thresholds.\n\nautoplot(pred, type = \"prc\")\n\n\n\n\n\n\n\n\nThe \"threshold\" plot varies the threshold of a binary classification and plots against the resulting performance.\n\nautoplot(pred, type = \"threshold\")" + }, + { + "objectID": "gallery/technical/2022-12-22-mlr3viz/index.html#regression-2", + "href": "gallery/technical/2022-12-22-mlr3viz/index.html#regression-2", + "title": "Visualization in mlr3", + "section": "Regression", + "text": "Regression\nThe predictions of a regression learner are often presented as a scatterplot of truth and predicted response.\n\ntask = tsk(\"boston_housing\")\nlearner = lrn(\"regr.rpart\")\npred = learner$train(task)$predict(task)\n\nautoplot(pred, type = \"xy\")\n\n\n\n\n\n\n\n\nAdditionally, we plot the response with the residuals.\n\nautoplot(pred, type = \"residual\")\n\n\n\n\n\n\n\n\nWe can also plot the distribution of the residuals.\n\nautoplot(pred, type = \"histogram\")" + }, + { + "objectID": "gallery/technical/2022-12-22-mlr3viz/index.html#cluster-1", + "href": "gallery/technical/2022-12-22-mlr3viz/index.html#cluster-1", + "title": "Visualization in mlr3", + "section": "Cluster", + "text": "Cluster\nThe predictions of a cluster learner are often presented as a scatterplot of the data points colored by the cluster.\n\nlibrary(mlr3cluster)\n\ntask = tsk(\"usarrests\")\nlearner = lrn(\"clust.kmeans\", centers = 3)\npred = learner$train(task)$predict(task)\n\nautoplot(pred, task, type = \"scatter\")\n\n\n\n\n\n\n\n\nThe \"sil\" plot shows the silhouette width of the clusters. The dashed line is the mean silhouette width.\n\nautoplot(pred, task, type = \"sil\")\n\n\n\n\n\n\n\n\nThe \"pca\" plot shows the first two principal components of the data colored by the cluster.\n\nautoplot(pred, task, type = \"pca\")" + }, + { + "objectID": "gallery/technical/2022-12-22-mlr3viz/index.html#classification-3", + "href": "gallery/technical/2022-12-22-mlr3viz/index.html#classification-3", + "title": "Visualization in mlr3", + "section": "Classification", + "text": "Classification\nThe \"boxplot\" shows the distribution of the performance measures.\n\ntask = tsk(\"sonar\")\nlearner = lrn(\"classif.rpart\", predict_type = \"prob\")\nresampling = rsmp(\"cv\")\nrr = resample(task, learner, resampling)\n\nautoplot(rr, type = \"boxplot\")\n\n\n\n\n\n\n\n\nWe can also plot the distribution of the performance measures as a “histogram”.\n\nautoplot(rr, type = \"histogram\")\n\n\n\n\n\n\n\n\nThe ROC curve plots the true positive rate against the false positive rate at different thresholds.\n\nautoplot(rr, type = \"roc\")\n\n\n\n\n\n\n\n\nThe precision-recall curve plots the precision against the recall at different thresholds.\n\nautoplot(rr, type = \"prc\")\n\n\n\n\n\n\n\n\nThe \"prediction\" plot shows two features and the predicted class in the background. Points mark the observations of the test set and the color presents the truth.\n\ntask = tsk(\"pima\")\ntask$filter(seq(100))\ntask$select(c(\"age\", \"glucose\"))\nlearner = lrn(\"classif.rpart\")\nresampling = rsmp(\"cv\", folds = 3)\nrr = resample(task, learner, resampling, store_models = TRUE)\n\nautoplot(rr, type = \"prediction\")\n\n\n\n\n\n\n\n\nAlternatively, we can plot class probabilities.\n\ntask = tsk(\"pima\")\ntask$filter(seq(100))\ntask$select(c(\"age\", \"glucose\"))\nlearner = lrn(\"classif.rpart\", predict_type = \"prob\")\nresampling = rsmp(\"cv\", folds = 3)\nrr = resample(task, learner, resampling, store_models = TRUE)\n\nautoplot(rr, type = \"prediction\")\n\n\n\n\n\n\n\n\nIn addition to the test set, we can also plot the train set.\n\ntask = tsk(\"pima\")\ntask$filter(seq(100))\ntask$select(c(\"age\", \"glucose\"))\nlearner = lrn(\"classif.rpart\", predict_type = \"prob\", predict_sets = c(\"train\", \"test\"))\nresampling = rsmp(\"cv\", folds = 3)\nrr = resample(task, learner, resampling, store_models = TRUE)\n\nautoplot(rr, type = \"prediction\", predict_sets = c(\"train\", \"test\"))\n\n\n\n\n\n\n\n\nThe \"prediction\" plot can also show categorical features.\n\ntask = tsk(\"german_credit\")\ntask$filter(seq(100))\ntask$select(c(\"housing\", \"employment_duration\"))\nlearner = lrn(\"classif.rpart\")\nresampling = rsmp(\"cv\", folds = 3)\nrr = resample(task, learner, resampling, store_models = TRUE)\n\nautoplot(rr, type = \"prediction\")" + }, + { + "objectID": "gallery/technical/2022-12-22-mlr3viz/index.html#regression-3", + "href": "gallery/technical/2022-12-22-mlr3viz/index.html#regression-3", + "title": "Visualization in mlr3", + "section": "Regression", + "text": "Regression\nThe “prediction” plot shows one feature and the response. Points mark the observations of the test set.\n\ntask = tsk(\"boston_housing\")\ntask$select(\"age\")\ntask$filter(seq(100))\nlearner = lrn(\"regr.rpart\")\nresampling = rsmp(\"cv\", folds = 3)\nrr = resample(task, learner, resampling, store_models = TRUE)\n\nautoplot(rr, type = \"prediction\")\n\n\n\n\n\n\n\n\nAdditionally, we can add confidence bounds.\n\ntask = tsk(\"boston_housing\")\ntask$select(\"age\")\ntask$filter(seq(100))\nlearner = lrn(\"regr.lm\", predict_type = \"se\")\nresampling = rsmp(\"cv\", folds = 3)\nrr = resample(task, learner, resampling, store_models = TRUE)\n\nautoplot(rr, type = \"prediction\")\n\n\n\n\n\n\n\n\nAnd add the train set.\n\ntask = tsk(\"boston_housing\")\ntask$select(\"age\")\ntask$filter(seq(100))\nlearner = lrn(\"regr.lm\", predict_type = \"se\", predict_sets = c(\"train\", \"test\"))\nresampling = rsmp(\"cv\", folds = 3)\nrr = resample(task, learner, resampling, store_models = TRUE)\n\nautoplot(rr, type = \"prediction\", predict_sets = c(\"train\", \"test\"))\n\n\n\n\n\n\n\n\nWe can also add the prediction surface to the background.\n\ntask = tsk(\"boston_housing\")\ntask$select(c(\"age\", \"rm\"))\ntask$filter(seq(100))\nlearner = lrn(\"regr.rpart\")\nresampling = rsmp(\"cv\", folds = 3)\nrr = resample(task, learner, resampling, store_models = TRUE)\n\nautoplot(rr, type = \"prediction\")" + }, + { + "objectID": "gallery/technical/2023-10-30-tidymodels/index.html", + "href": "gallery/technical/2023-10-30-tidymodels/index.html", + "title": "Analyzing the Runtime Performance of tidymodels and mlr3", + "section": "", + "text": "In the realm of data science, machine learning frameworks play an important role in streamlining and accelerating the development of analytical workflows. Among these, tidymodels and mlr3 stand out as prominent tools within the R community. They provide a unified interface for data preprocessing, model training, resampling and tuning. The streamlined and accelerated development process, while efficient, typically results in a trade-off concerning runtime performance. This article undertakes a detailed comparison of the runtime efficiency of tidymodels and mlr3, focusing on their performance in training, resampling, and tuning machine learning models. Specifically, we assess the time efficiency of these frameworks in running the rpart::rpart() and ranger::ranger() models, using the Sonar dataset as a test case. Additionally, the study delves into analyzing the runtime overhead of these frameworks by comparing their performance against training the models without a framework. Through this comparative analysis, the article aims to provide valuable insights into the operational trade-offs of using these advanced machine learning frameworks in practical data science applications." + }, + { + "objectID": "gallery/technical/2023-10-30-tidymodels/index.html#train-the-models", + "href": "gallery/technical/2023-10-30-tidymodels/index.html#train-the-models", + "title": "Analyzing the Runtime Performance of tidymodels and mlr3", + "section": "Train the Models", + "text": "Train the Models\nOur benchmark starts with the fundamental task of model training. To facilitate a direct comparison, we have structured our presentation into two distinct segments. On the left, we demonstrate the initialization of the rpart model, employing both mlr3 and tidymodels frameworks. The rpart model is a decision tree classifier, which is a simple and fast-fitting algorithm for classification tasks. Simultaneously, on the right, we turn our attention to the initialization of the ranger model, known for its efficient implementation of the random forest algorithm. Our aim is to mirror the configuration as closely as possible across both frameworks, maintaining consistency in parameters and settings.\n# tidymodels\ntm_mod = decision_tree() %>%\n set_engine(\"rpart\",\n xval = 0L) %>%\n set_mode(\"classification\")\n\n# mlr3\nlearner = lrn(\"classif.rpart\",\n xval = 0L)\n# tidymodels\ntm_mod = rand_forest(trees = 1000L) %>%\n set_engine(\"ranger\",\n num.threads = 1L,\n seed = 1) %>%\n set_mode(\"classification\")\n\n# mlr3\nlearner = lrn(\"classif.ranger\",\n num.trees = 1000L,\n num.threads = 1L,\n seed = 1,\n verbose = FALSE,\n predict_type = \"prob\")\n\n\n\n\n\nWe measure the runtime for the train functions within each framework. The result of the train function is a trained model in both frameworks. In addition, we invoke the rpart() and ranger() functions to establish a baseline for the minimum achievable runtime. This allows us to not only assess the efficiency of the train functions in each framework but also to understand how they perform relative to the base packages.\n\n# tidymodels train\nfit(tm_mod, formula, data = data)\n\n# mlr3 train\nlearner$train(task)\n\nWhen training an rpart model, tidymodels demonstrates superior speed, outperforming mlr3 (Table 1). Notably, the mlr3 package requires approximately twice the time compared to the baseline.\nA key observation from our results is the significant relative overhead when using a framework for rpart model training. Given that rpart inherently requires a shorter training time, the additional processing time introduced by the frameworks becomes more pronounced. This aspect highlights the trade-off between the convenience offered by these frameworks and their impact on runtime for quicker tasks.\nConversely, when we shift our focus to training a ranger model, the scenario changes (Table 2). Here, the runtime performance of ranger is strikingly similar across both tidymodels and mlr3. This equality in execution time can be attributed to the inherently longer training duration required by ranger models. As a result, the relative overhead introduced by either framework becomes minimal, effectively diminishing in the face of the more time-intensive training process. This pattern suggests that for more complex or time-consuming tasks, the choice of framework may have a less significant impact on overall runtime performance.\n\n\n\n\n\n\n\n\n\nTable 1: Average runtime in milliseconds of training rpart depending on the framework.\n\n\n\n\n\n\nFramework\nLQ\nMedian\nUQ\n\n\n\n\nbase\n11\n11\n12\n\n\nmlr3\n23\n23\n24\n\n\ntidymodels\n18\n18\n19\n\n\n\n\n\n\n\n\n\n\n\n\nTable 2: Average runtime in milliseconds of training ranger depending on the framework.\n\n\n\n\n\n\nFramework\nLQ\nMedian\nUQ\n\n\n\n\nbase\n286\n322\n347\n\n\nmlr3\n301\n335\n357\n\n\ntidymodels\n310\n342\n362" + }, + { + "objectID": "gallery/technical/2023-10-30-tidymodels/index.html#resample-sequential", + "href": "gallery/technical/2023-10-30-tidymodels/index.html#resample-sequential", + "title": "Analyzing the Runtime Performance of tidymodels and mlr3", + "section": "Resample Sequential", + "text": "Resample Sequential\nWe proceed to evaluate the runtime performance of the resampling functions within both frameworks, specifically under conditions without parallelization. This step involves the generation of resampling splits, including 3-fold, 6-fold, and 9-fold cross-validation. Additionally, we run a 100 times repeated 3-fold cross-validation.\nWe generate the same resampling splits for both frameworks. This consistency is key to ensuring that any observed differences in runtime are attributable to the frameworks themselves, rather than variations in the resampling process.\nIn our pursuit of a fair and balanced comparison, we address certain inherent differences between the two frameworks. Notably, tidymodels inherently includes scoring of the resampling results as part of its process. To align the comparison, we replicate this scoring step in mlr3, thus maintaining a level field for evaluation. Furthermore, mlr3 inherently saves predictions during the resampling process. To match this, we activate the saving of the predictions in tidymodels.\n\n# tidymodels resample\ncontrol = control_grid(save_pred = TRUE)\nmetrics = metric_set(accuracy)\n\ntm_wf =\n workflow() %>%\n add_model(tm_mod) %>%\n add_formula(formula)\n\nfit_resamples(tm_wf, folds, metrics = metrics, control = control)\n\n# mlr3 resample\nmeasure = msr(\"classif.acc\")\n\nrr = resample(task, learner, resampling)\nrr$score(measure)\n\nWhen resampling the fast-fitting rpart model, mlr3 demonstrates a notable edge in speed, as detailed in Table 3. In contrast, when it comes to resampling the more computationally intensive ranger models, the performance of tidymodels and mlr3 converges closely (Table 4). This parity in performance is particularly noteworthy, considering the differing internal mechanisms and optimizations of tidymodels and mlr3. A consistent trend observed across both frameworks is a linear increase in runtime proportional to the number of folds in cross-validation (Figure 1).\n\n\n\n\n\n\n\n\n\nTable 3: Average runtime in milliseconds of rpart depending on the framework and resampling strategy.\n\n\n\n\n\n\nFramework\nResampling\nLQ\nMedian\nUQ\n\n\n\n\nmlr3\ncv3\n188\n196\n210\n\n\ntidymodels\ncv3\n233\n242\n257\n\n\nmlr3\ncv6\n343\n357\n379\n\n\ntidymodels\ncv6\n401\n415\n436\n\n\nmlr3\ncv9\n500\n520\n548\n\n\ntidymodels\ncv9\n568\n588\n616\n\n\nmlr3\nrcv100\n15526\n16023\n16777\n\n\ntidymodels\nrcv100\n16409\n16876\n17527\n\n\n\n\n\n\n\n\n\n\n\n\nTable 4: Average runtime in milliseconds of ranger depending on the framework and resampling strategy.\n\n\n\n\n\n\nFramework\nResampling\nLQ\nMedian\nUQ\n\n\n\n\nmlr3\ncv3\n923\n1004\n1062\n\n\ntidymodels\ncv3\n916\n981\n1023\n\n\nmlr3\ncv6\n1990\n2159\n2272\n\n\ntidymodels\ncv6\n2089\n2176\n2239\n\n\nmlr3\ncv9\n3074\n3279\n3441\n\n\ntidymodels\ncv9\n3260\n3373\n3453\n\n\nmlr3\nrcv100\n85909\n88642\n91381\n\n\ntidymodels\nrcv100\n87828\n88822\n89843\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nFigure 1: Average runtime, measured in milliseconds, for cross-validations using rpart (displayed on the left) and ranger (on the right). The comparison encompasses variations across different frameworks and the number of folds in the cross-validation." + }, + { + "objectID": "gallery/technical/2023-10-30-tidymodels/index.html#resample-parallel", + "href": "gallery/technical/2023-10-30-tidymodels/index.html#resample-parallel", + "title": "Analyzing the Runtime Performance of tidymodels and mlr3", + "section": "Resample Parallel", + "text": "Resample Parallel\nWe conducted a second set of resampling function tests, this time incorporating parallelization to explore its impact on runtime efficiency. In this phase, we utilized doFuture and doParallel as the primary parallelization packages for tidymodels, recognizing their robust support and compatibility. Meanwhile, for mlr3, the future package was employed to facilitate parallel processing.\nOur findings, as presented in the respective tables (Table 5 and Table 6), reveal interesting dynamics about parallelization within the frameworks. When the number of folds in the resampling process is doubled, we observe only a marginal increase in the average runtime. This pattern suggests a significant overhead associated with initializing the parallel workers, a factor that becomes particularly influential in the overall efficiency of the parallelization process.\nIn the case of the rpart model, the parallelization overhead appears to outweigh the potential speedup benefits, as illustrated in the left section of Figure 2. This result indicates that for less complex models like rpart, where individual training times are relatively short, the initialization cost of parallel workers may not be sufficiently offset by the reduced processing time per fold.\nConversely, for the ranger model, the utilization of parallelization demonstrates a clear advantage over the sequential version, as evidenced in the right section of Figure 2. This finding underscores that for more computationally intensive models like ranger, which have longer individual training times, the benefits of parallel processing significantly overcome the initial overhead of worker setup. This differentiation highlights the importance of considering the complexity and inherent processing time of models when deciding to implement parallelization strategies in these frameworks.\n\n\n\n\n\n\n\n\n\nTable 5: Average runtime in milliseconds of mlr3 with future and rpart depending on the resampling strategy.\n\n\n\n\n\n\nResampling\nLQ\nMedian\nUQ\n\n\n\n\ncv3\n625\n655\n703\n\n\ncv6\n738\n771\n817\n\n\ncv9\n831\n875\n923\n\n\nrcv100\n8620\n9043\n9532\n\n\n\n\n\n\n\n\n\n\n\n\nTable 6: Average runtime in milliseconds of mlr3 with future and ranger depending on the resampling strategy.\n\n\n\n\n\n\nResampling\nLQ\nMedian\nUQ\n\n\n\n\ncv3\n836\n884\n943\n\n\ncv6\n1200\n1249\n1314\n\n\ncv9\n1577\n1634\n1706\n\n\nrcv100\n32047\n32483\n33022\n\n\n\n\n\n\n\n\n\n\nWhen paired with doFuture, tidymodels exhibits significantly slower runtime compared to the mlr3 package utilizing future (Table 7 and Table 8). We observed that tidymodels exports more data to the parallel workers, which notably exceeds that of mlr3. This substantial difference in data export could plausibly account for the observed slower runtime when using tidymodels on small tasks.\n\n\n\n\n\n\n\n\n\nTable 7: Average runtime in milliseconds of tidymodels with doFuture and rpart depending on the resampling strategy.\n\n\n\n\n\n\nResampling\nLQ\nMedian\nUQ\n\n\n\n\ncv3\n2778\n2817\n3019\n\n\ncv6\n2808\n2856\n3033\n\n\ncv9\n2935\n2975\n3170\n\n\nrcv100\n9154\n9302\n9489\n\n\n\n\n\n\n\n\n\n\n\n\nTable 8: Average runtime in milliseconds of tidymodels with doFuture and ranger depending on the resampling strategy.\n\n\n\n\n\n\nResampling\nLQ\nMedian\nUQ\n\n\n\n\ncv3\n2982\n3046\n3234\n\n\ncv6\n3282\n3366\n3543\n\n\ncv9\n3568\n3695\n3869\n\n\nrcv100\n27546\n27843\n28166\n\n\n\n\n\n\n\n\n\n\nThe utilization of the doParallel package demonstrates a notable improvement in handling smaller resampling tasks. In these scenarios, the resampling process consistently outperforms the mlr3 framework in terms of speed. However, it’s important to note that even with this enhanced performance, the doParallel package does not always surpass the efficiency of the sequential version, especially when working with the rpart model. This specific observation is illustrated in the left section of Figure 2.\n\n\n\n\n\n\n\n\n\nTable 9: Average runtime in milliseconds of tidymodels with doParallel and rpart depending on the resampling strategy.\n\n\n\n\n\n\nResampling\nLQ\nMedian\nUQ\n\n\n\n\ncv3\n557\n649\n863\n\n\ncv6\n602\n714\n910\n\n\ncv9\n661\n772\n968\n\n\nrcv100\n10609\n10820\n11071\n\n\n\n\n\n\n\n\n\n\n\n\nTable 10: Average runtime in milliseconds of tidymodels with doParallel and ranger depending on the resampling strategy.\n\n\n\n\n\n\nResampling\nLQ\nMedian\nUQ\n\n\n\n\ncv3\n684\n756\n948\n\n\ncv6\n1007\n1099\n1272\n\n\ncv9\n1360\n1461\n1625\n\n\nrcv100\n31205\n31486\n31793\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nFigure 2: Average runtime, measured in milliseconds, for cross-validations using rpart (displayed on the left) and ranger (on the right). The comparison encompasses variations across different frameworks, the number of folds in the cross-validation, and the implementation of parallelization.\n\n\n\n\n\nIn the context of repeated cross-validation, our findings underscore the efficacy of parallelization (Figure 3). Across all frameworks tested, the adoption of parallel processing techniques yields a significant increase in speed. This enhancement is particularly noticeable in larger resampling tasks, where the demands on computational resources are more substantial.\nInterestingly, within these more extensive resampling scenarios, the doFuture package emerges as a more efficient option compared to doParallel. This distinction is important, as it highlights the relative strengths of different parallelization packages under varying workload conditions. While doParallel shows proficiency in smaller tasks, doFuture demonstrates its capability to handle larger, more complex resampling processes with greater speed and efficiency.\n\n\n\n\n\n\n\n\nFigure 3: Average runtime, measured in seconds, of a 100 times repeated 3-fold cross-validation using rpart (displayed on the left) and ranger (on the right). The comparison encompasses variations across different frameworks and the implementation of parallelization." + }, + { + "objectID": "gallery/technical/2023-10-30-tidymodels/index.html#tune-sequential", + "href": "gallery/technical/2023-10-30-tidymodels/index.html#tune-sequential", + "title": "Analyzing the Runtime Performance of tidymodels and mlr3", + "section": "Tune Sequential", + "text": "Tune Sequential\nWe then shift our focus to assessing the runtime performance of the tuning functions. In this phase, the tidymodels package is utilized to evaluate a predefined grid, comprising a specific set of hyperparameter configurations. To ensure a balanced and comparable analysis, we employ the \"design_points\" tuner from the mlr3tuning package. This approach allows us to evaluate the same grid within the mlr3 framework, maintaining consistency across both platforms. The grid used for this comparison contains 200 hyperparameter configurations each, for both the rpart and ranger models. This approach helps us to understand how each framework handles the optimization of model hyperparameters, a key aspect of building effective and efficient machine learning models.\n# tidymodels\ntm_mod = decision_tree(\n cost_complexity = tune()) %>%\n set_engine(\"rpart\",\n xval = 0) %>%\n set_mode(\"classification\")\n\ntm_design = data.table(\n cost_complexity = seq(0.1, 0.2, length.out = 200))\n\n# mlr3\nlearner = lrn(\"classif.rpart\",\n xval = 0,\n cp = to_tune())\n\nmlr3_design = data.table(\n cp = seq(0.1, 0.2, length.out = 200))\n# tidymodels\ntm_mod = rand_forest(\n trees = tune()) %>%\n set_engine(\"ranger\",\n num.threads = 1L,\n seed = 1) %>%\n set_mode(\"classification\")\n\ntm_design = data.table(\n trees = seq(1000, 1199))\n\n# mlr3\nlearner = lrn(\"classif.ranger\",\n num.trees = to_tune(1, 10000),\n num.threads = 1L,\n seed = 1,\n verbose = FALSE,\n predict_type = \"prob\")\n\nmlr3_design = data.table(\n num.trees = seq(1000, 1199))\n\n\n\n\n\nWe measure the runtime of the tune functions within each framework. Both the tidymodels and mlr3 frameworks are tasked with identifying the optimal hyperparameter configuration.\n\n# tidymodels tune\ntune::tune_grid(\n tm_wf,\n resamples = resamples,\n grid = design,\n metrics = metrics)\n\n# mlr3 tune\ntuner = tnr(\"design_points\", design = design, batch_size = nrow(design))\nmlr3tuning::tune(\n tuner = tuner,\n task = task,\n learner = learner,\n resampling = resampling,\n measures = measure,\n store_benchmark_result = FALSE)\n\nIn our sequential tuning tests, mlr3 demonstrates a notable advantage in terms of speed. This finding is clearly evidenced in our results, as shown in Table Table 11 for the rpart model and Table Table 12 for the ranger model. The faster performance of mlr3 in these sequential runs highlights its efficiency in handling the tuning process without parallelization.\n\n\n\n\n\n\n\n\n\nTable 11: Average runtime in seconds of tuning 200 points of rpart depending on the framework.\n\n\n\n\n\n\nFramework\nLQ\nMedian\nUQ\n\n\n\n\nmlr3\n27\n27\n28\n\n\ntidymodels\n37\n37\n39\n\n\n\n\n\n\n\n\n\n\n\n\nTable 12: Average runtime in seconds of tuning 200 points of ranger depending on the framework.\n\n\n\n\n\n\nFramework\nLQ\nMedian\nUQ\n\n\n\n\nmlr3\n167\n171\n175\n\n\ntidymodels\n194\n195\n196" + }, + { + "objectID": "gallery/technical/2023-10-30-tidymodels/index.html#tune-parallel", + "href": "gallery/technical/2023-10-30-tidymodels/index.html#tune-parallel", + "title": "Analyzing the Runtime Performance of tidymodels and mlr3", + "section": "Tune Parallel", + "text": "Tune Parallel\nConcluding our analysis, we proceed to evaluate the runtime performance of the tune functions, this time implementing parallelization to enhance efficiency. For these runs, parallelization is executed on 3 cores.\nIn the case of mlr3, we opt for the largest possible chunk size. This strategic choice means that all points within the tuning grid are sent to the workers in a single batch, effectively minimizing the overhead typically associated with parallelization. This approach is crucial in reducing the time spent in distributing tasks across multiple cores, thereby streamlining the tuning process. On the other hand, the tidymodels package also operates with the same chunk size, but this setting is determined and managed internally within the framework.\nBy conducting these parallelization tests, we aim to provide a deeper understanding of how each framework handles the distribution and management of computational tasks during the tuning process, particularly in a parallel computing environment. This final set of measurements is important in painting a complete picture of the runtime performance of the tune functions across both tidymodels and mlr3 under different operational settings.\n\noptions(\"mlr3.exec_chunk_size\" = 200)\n\nOur analysis of the parallelized tuning functions reveals that the runtimes for mlr3 and tidymodels are remarkably similar. However, subtle differences emerge upon closer inspection. For instance, the mlr3 package exhibits a slightly faster performance when tuning the rpart model, as indicated in Table 13. In contrast, it falls marginally behind tidymodels in tuning the ranger model, as shown in Table 14.\nInterestingly, when considering the specific context of a 3-fold cross-validation, the doParallel package outperforms doFuture in terms of speed, as demonstrated in Figure 4. This outcome suggests that the choice of parallelization package can have a significant impact on tuning efficiency, particularly in scenarios with a smaller number of folds.\nA key takeaway from our study is the clear benefit of enabling parallelization, regardless of the chosen framework-backend combination. Activating parallelization consistently enhances performance, making it a highly recommended strategy for tuning machine learning models, especially in tasks involving extensive hyperparameter exploration or larger datasets. This conclusion underscores the value of parallel processing in modern machine learning workflows, offering a practical solution for accelerating model tuning across various computational settings.\n\n\n\n\n\n\n\n\n\nTable 13: Average runtime in seconds of tuning 200 points of rpart depending on the framework.\n\n\n\n\n\n\nFramework\nBackend\nLQ\nMedian\nUQ\n\n\n\n\nmlr3\nfuture\n11\n12\n12\n\n\ntidymodels\ndoFuture\n17\n17\n17\n\n\ntidymodels\ndoParallel\n13\n13\n13\n\n\n\n\n\n\n\n\n\n\n\n\nTable 14: Average runtime in seconds of tuning 200 points of ranger depending on the framework.\n\n\n\n\n\n\nFramework\nBackend\nLQ\nMedian\nUQ\n\n\n\n\nmlr3\nfuture\n54\n55\n55\n\n\ntidymodels\ndoFuture\n58\n58\n59\n\n\ntidymodels\ndoParallel\n54\n54\n55\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nFigure 4: Average runtime, measured in seconds, of a tuning 200 hyperparameter configurations of rpart (displayed on the left) and ranger (on the right). The comparison encompasses variations across different frameworks and the implementation of parallelization." + }, + { + "objectID": "resources.html", + "href": "resources.html", + "title": "Resources", + "section": "", + "text": "Entry points to learn about mlr3.\n\n\n\n\n\n\nCentral entry point to the mlr3verse.\n\n\n\n\n\n\n\n\nCollection of case studies and demos.\n\n\n\n\n\n\n\n\nThe mlr3 ecosystem is build on R6 classes. The link gives an introduction to R6.\n\n\n\n\n\n\n\n\nLink to the future framework that is used to parallelize functions in mlr3.\n\n\n\n\n\n\n\n\nLink to mlr3 developer wiki." + }, + { + "objectID": "resources.html#documentation", + "href": "resources.html#documentation", + "title": "Resources", + "section": "", + "text": "Entry points to learn about mlr3.\n\n\n\n\n\n\nCentral entry point to the mlr3verse.\n\n\n\n\n\n\n\n\nCollection of case studies and demos.\n\n\n\n\n\n\n\n\nThe mlr3 ecosystem is build on R6 classes. The link gives an introduction to R6.\n\n\n\n\n\n\n\n\nLink to the future framework that is used to parallelize functions in mlr3.\n\n\n\n\n\n\n\n\nLink to mlr3 developer wiki." + }, + { + "objectID": "resources.html#cheat-sheets", + "href": "resources.html#cheat-sheets", + "title": "Resources", + "section": "Cheat Sheets", + "text": "Cheat Sheets\nThe essential things neatly summarized. Perfectly printed out next to the keyboard or on a second monitor.\n\n\n\n\n\n\n \nmlr3\n\n\nCore package cheat sheet.\n\n\n\n\n\n\n\n\n \nmlr3tuning\n\n\nTuning cheat sheet.\n\n\n\n\n\n\n\n\n \nmlr3fselect\n\n\nFeature selection cheat sheet.\n\n\n\n\n\n\n\n\n \nmlr3pipelines\n\n\nPipelines cheat sheet." + }, + { + "objectID": "resources.html#videos", + "href": "resources.html#videos", + "title": "Resources", + "section": "Videos", + "text": "Videos\nRecorded tutorials and lectures we have given.\n\n\n\n\n\n\n \nuseR2019 talk\n\n\nShort intro to mlr3.\n\n\n\n\n\n\n\n\n \nuseR2019 talk\n\n\nShort intro to mlr3pipelines and mlr3tuning.\n\n\n\n\n\n\n\n\n \nuseR2020 tutorial\n\n\nTutorial on mlr3, mlr3tuning and mlr3pipelines.\n\n\n\n\n\n\n\n\n \nODSC talk 2021\n\n\nInto to mlr3spatiotempcv and mlr3spatial." + }, + { + "objectID": "resources.html#courseslectures", + "href": "resources.html#courseslectures", + "title": "Resources", + "section": "Courses/Lectures", + "text": "Courses/Lectures\nMaterial from teaching at our universities.\n\n\n\n\n\n\n \nI2ML course\n\n\nIntroduction to ML course. Free video lectures, slides, quizzes. Exercises use mlr3.\n\n\n\n\n\n\n\n\n \nmlr-outreach\n\n\nSlides and other material for teaching mlr3." + }, + { + "objectID": "resources.html#peer-reviewed-articles", + "href": "resources.html#peer-reviewed-articles", + "title": "Resources", + "section": "Peer-reviewed Articles", + "text": "Peer-reviewed Articles\nA more scientific view on our packages and the packages we depend on.\n\nLang et al. (2019): about the base package mlr3\nBinder et al. (2021): building machine learning pipelines with mlr3pipelines\nSonabend et al. (2021): probabilistic regression with mlr3proba (including survival analysis)\nBengtsson (2021): the parallelization framework package future we build upon\nLang (2017): package checkmate for argument checking and defensive programming\nLang, Bischl, and Surmann (2017): parallelization framework batchtools for high-performance computing clusters, used via future or mlr3batchmark" + }, + { + "objectID": "resources.html#tutorial-papers", + "href": "resources.html#tutorial-papers", + "title": "Resources", + "section": "Tutorial Papers", + "text": "Tutorial Papers\n\nPargent, Schoedel, and Stachl (2023): An Introduction to Machine Learning for Psychologists in R\nZhao et al. (2024): Tutorial on survival modeling with applications to omics data. Tutorial Website." + }, + { + "objectID": "documentation-listings/gallery.html", + "href": "documentation-listings/gallery.html", + "title": "Gallery", + "section": "", + "text": "foo" + }, + { + "objectID": "gallery-all-basic.html", + "href": "gallery-all-basic.html", + "title": "Train and Evaluate Models", + "section": "", + "text": "Train and Evaluate Models\n\n\n \n \n Introduction to mlr3keras - Boston Housing\n This use case provides an introduction to mlr3keras via the boston housing dataset.\n\n 2020-09-11 - Florian Pfisterer\n \n \n \n Comparison of Decision Boundaries of Classification Learners\n Visualize the decision boundaries of multiple classification learners on some artificial data sets.\n\n 2020-08-14 - Michel Lang\n \n \n \n mlr3 and OpenML - Moneyball Use Case\n Download data from OpenML data and impute missing values.\n\n 2020-05-04 - Philipp Kopper\n \n \n \n Feature Engineering of Date-Time Variables\n Engineer features using date-time variables.\n\n 2020-05-02 - Lennart Schneider\n \n \n \n Resampling - Stratified, Blocked and Predefined\n Apply stratified, block and custom resampling.\n\n 2020-03-30 - Milan Dragicevic, Giuseppe Casalicchio\n \n \n \n Imbalanced Data Handling with mlr3\n Handle imbalanced data with oversampling, undersampling, and SMOTE imbalance correction.\n\n 2020-03-30 - Giuseppe Casalicchio\n \n \n \n mlr3 Basics on \"Iris\" - Hello World!\n Learn the basic operations train, predict, score, resample, and benchmark.\n\n 2020-03-18 - Bernd Bischl\n \n \n \n German Credit Series - Basics\n Train different models.\n\n 2020-03-11 - Martin Binder, Florian Pfisterer, Michel Lang\n \n \n \n German Credit Series - Tuning\n Optimize Hyperparameters and apply nested resampling.\n\n 2020-03-11 - Martin Binder, Florian Pfisterer\n \n \n \n German Credit Series - Pipelines\n Impute missing values, filter features and stack Learners.\n\n 2020-03-11 - Martin Binder, Florian Pfisterer\n \n \n \n Select Uncorrelated Features\n Remove correlated features with a pipeline.\n\n 2020-02-25 - Martin Binder, Florian Pfisterer\n \n \n \n Impute Missing Variables\n Augment a Random Forest with automatic imputation.\n\n 2020-01-31 - Florian Pfisterer\n \n \n \n Encode Factor Levels for xgboost\n Encode factor variables in a task.\n\n 2020-01-31 - Michel Lang\n \n \n \n House Prices in King County\n Apply multiple preprocessing steps, fit a model and visualize the results.\n\n 2020-01-30 - Florian Pfisterer\n \n \n\n\nNo matching items" + } +] \ No newline at end of file diff --git a/site_libs/bootstrap/bootstrap-icons.css b/site_libs/bootstrap/bootstrap-icons.css new file mode 100644 index 00000000..285e4448 --- /dev/null +++ b/site_libs/bootstrap/bootstrap-icons.css @@ -0,0 +1,2078 @@ +/*! + * Bootstrap Icons v1.11.1 (https://icons.getbootstrap.com/) + * Copyright 2019-2023 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/icons/blob/main/LICENSE) + */ + +@font-face { + font-display: block; + font-family: "bootstrap-icons"; + src: +url("./bootstrap-icons.woff?2820a3852bdb9a5832199cc61cec4e65") format("woff"); +} + +.bi::before, +[class^="bi-"]::before, +[class*=" bi-"]::before { + display: inline-block; + font-family: bootstrap-icons !important; + font-style: normal; + font-weight: normal !important; + font-variant: normal; + text-transform: none; + line-height: 1; + vertical-align: -.125em; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.bi-123::before { content: "\f67f"; } +.bi-alarm-fill::before { content: "\f101"; } +.bi-alarm::before { content: "\f102"; } +.bi-align-bottom::before { content: "\f103"; } +.bi-align-center::before { content: "\f104"; } +.bi-align-end::before { content: "\f105"; } +.bi-align-middle::before { content: "\f106"; } +.bi-align-start::before { content: "\f107"; } +.bi-align-top::before { content: "\f108"; } +.bi-alt::before { content: "\f109"; } +.bi-app-indicator::before { content: "\f10a"; } +.bi-app::before { content: "\f10b"; } +.bi-archive-fill::before { content: "\f10c"; } +.bi-archive::before { content: "\f10d"; } +.bi-arrow-90deg-down::before { content: "\f10e"; } +.bi-arrow-90deg-left::before { content: "\f10f"; } +.bi-arrow-90deg-right::before { content: "\f110"; } +.bi-arrow-90deg-up::before { content: "\f111"; } +.bi-arrow-bar-down::before { content: "\f112"; } +.bi-arrow-bar-left::before { content: "\f113"; } +.bi-arrow-bar-right::before { content: "\f114"; } +.bi-arrow-bar-up::before { content: "\f115"; } +.bi-arrow-clockwise::before { content: "\f116"; } +.bi-arrow-counterclockwise::before { content: "\f117"; } +.bi-arrow-down-circle-fill::before { content: "\f118"; } +.bi-arrow-down-circle::before { content: "\f119"; } +.bi-arrow-down-left-circle-fill::before { content: "\f11a"; } +.bi-arrow-down-left-circle::before { content: "\f11b"; } +.bi-arrow-down-left-square-fill::before { content: "\f11c"; } +.bi-arrow-down-left-square::before { content: "\f11d"; } +.bi-arrow-down-left::before { content: "\f11e"; } +.bi-arrow-down-right-circle-fill::before { content: "\f11f"; } +.bi-arrow-down-right-circle::before { content: "\f120"; } +.bi-arrow-down-right-square-fill::before { content: "\f121"; } +.bi-arrow-down-right-square::before { content: "\f122"; } +.bi-arrow-down-right::before { content: "\f123"; } +.bi-arrow-down-short::before { content: "\f124"; } +.bi-arrow-down-square-fill::before { content: "\f125"; } +.bi-arrow-down-square::before { content: "\f126"; } +.bi-arrow-down-up::before { content: "\f127"; } +.bi-arrow-down::before { content: "\f128"; } +.bi-arrow-left-circle-fill::before { content: "\f129"; } +.bi-arrow-left-circle::before { content: "\f12a"; } +.bi-arrow-left-right::before { content: "\f12b"; } +.bi-arrow-left-short::before { content: "\f12c"; } +.bi-arrow-left-square-fill::before { content: "\f12d"; } +.bi-arrow-left-square::before { content: "\f12e"; } +.bi-arrow-left::before { content: "\f12f"; } +.bi-arrow-repeat::before { content: "\f130"; } +.bi-arrow-return-left::before { content: "\f131"; } +.bi-arrow-return-right::before { content: "\f132"; } +.bi-arrow-right-circle-fill::before { content: "\f133"; } +.bi-arrow-right-circle::before { content: "\f134"; } +.bi-arrow-right-short::before { content: "\f135"; } +.bi-arrow-right-square-fill::before { content: "\f136"; } +.bi-arrow-right-square::before { content: "\f137"; } +.bi-arrow-right::before { content: "\f138"; } +.bi-arrow-up-circle-fill::before { content: "\f139"; } +.bi-arrow-up-circle::before { content: "\f13a"; } +.bi-arrow-up-left-circle-fill::before { content: "\f13b"; } +.bi-arrow-up-left-circle::before { content: "\f13c"; } +.bi-arrow-up-left-square-fill::before { content: "\f13d"; } +.bi-arrow-up-left-square::before { content: "\f13e"; } +.bi-arrow-up-left::before { content: "\f13f"; } +.bi-arrow-up-right-circle-fill::before { content: "\f140"; } +.bi-arrow-up-right-circle::before { content: "\f141"; } +.bi-arrow-up-right-square-fill::before { content: "\f142"; } +.bi-arrow-up-right-square::before { content: "\f143"; } +.bi-arrow-up-right::before { content: "\f144"; } +.bi-arrow-up-short::before { content: "\f145"; } +.bi-arrow-up-square-fill::before { content: "\f146"; } +.bi-arrow-up-square::before { content: "\f147"; } +.bi-arrow-up::before { content: "\f148"; } +.bi-arrows-angle-contract::before { content: "\f149"; } +.bi-arrows-angle-expand::before { content: "\f14a"; } +.bi-arrows-collapse::before { content: "\f14b"; } +.bi-arrows-expand::before { content: "\f14c"; } +.bi-arrows-fullscreen::before { content: "\f14d"; } +.bi-arrows-move::before { content: "\f14e"; } +.bi-aspect-ratio-fill::before { content: "\f14f"; } +.bi-aspect-ratio::before { content: "\f150"; } +.bi-asterisk::before { content: "\f151"; } +.bi-at::before { content: "\f152"; } +.bi-award-fill::before { content: "\f153"; } +.bi-award::before { content: "\f154"; } +.bi-back::before { content: "\f155"; } +.bi-backspace-fill::before { content: "\f156"; } +.bi-backspace-reverse-fill::before { content: "\f157"; } +.bi-backspace-reverse::before { content: "\f158"; } +.bi-backspace::before { content: "\f159"; } +.bi-badge-3d-fill::before { content: "\f15a"; } +.bi-badge-3d::before { content: "\f15b"; } +.bi-badge-4k-fill::before { content: "\f15c"; } +.bi-badge-4k::before { content: "\f15d"; } +.bi-badge-8k-fill::before { content: "\f15e"; } +.bi-badge-8k::before { content: "\f15f"; } +.bi-badge-ad-fill::before { content: "\f160"; } +.bi-badge-ad::before { content: "\f161"; } +.bi-badge-ar-fill::before { content: "\f162"; } +.bi-badge-ar::before { content: "\f163"; } +.bi-badge-cc-fill::before { content: "\f164"; } +.bi-badge-cc::before { content: "\f165"; } +.bi-badge-hd-fill::before { content: "\f166"; } +.bi-badge-hd::before { content: "\f167"; } +.bi-badge-tm-fill::before { content: "\f168"; } +.bi-badge-tm::before { content: "\f169"; } +.bi-badge-vo-fill::before { content: "\f16a"; } +.bi-badge-vo::before { content: "\f16b"; } +.bi-badge-vr-fill::before { content: "\f16c"; } +.bi-badge-vr::before { content: "\f16d"; } +.bi-badge-wc-fill::before { content: "\f16e"; } +.bi-badge-wc::before { content: "\f16f"; } +.bi-bag-check-fill::before { content: "\f170"; } +.bi-bag-check::before { content: "\f171"; } +.bi-bag-dash-fill::before { content: "\f172"; } +.bi-bag-dash::before { content: "\f173"; } +.bi-bag-fill::before { content: "\f174"; } +.bi-bag-plus-fill::before { content: "\f175"; } +.bi-bag-plus::before { content: "\f176"; } +.bi-bag-x-fill::before { content: "\f177"; } +.bi-bag-x::before { content: "\f178"; } +.bi-bag::before { content: "\f179"; } +.bi-bar-chart-fill::before { content: "\f17a"; } +.bi-bar-chart-line-fill::before { content: "\f17b"; } +.bi-bar-chart-line::before { content: "\f17c"; } +.bi-bar-chart-steps::before { content: "\f17d"; } +.bi-bar-chart::before { content: "\f17e"; } +.bi-basket-fill::before { content: "\f17f"; } +.bi-basket::before { content: "\f180"; } +.bi-basket2-fill::before { content: "\f181"; } +.bi-basket2::before { content: "\f182"; } +.bi-basket3-fill::before { content: "\f183"; } +.bi-basket3::before { content: "\f184"; } +.bi-battery-charging::before { content: "\f185"; } +.bi-battery-full::before { content: "\f186"; } +.bi-battery-half::before { content: "\f187"; } +.bi-battery::before { content: "\f188"; } +.bi-bell-fill::before { content: "\f189"; } +.bi-bell::before { content: "\f18a"; } +.bi-bezier::before { content: "\f18b"; } +.bi-bezier2::before { content: "\f18c"; } +.bi-bicycle::before { content: "\f18d"; } +.bi-binoculars-fill::before { content: "\f18e"; } +.bi-binoculars::before { content: "\f18f"; } +.bi-blockquote-left::before { content: "\f190"; } +.bi-blockquote-right::before { content: "\f191"; } +.bi-book-fill::before { content: "\f192"; } +.bi-book-half::before { content: "\f193"; } +.bi-book::before { content: "\f194"; } +.bi-bookmark-check-fill::before { content: "\f195"; } +.bi-bookmark-check::before { content: "\f196"; } +.bi-bookmark-dash-fill::before { content: "\f197"; } +.bi-bookmark-dash::before { content: "\f198"; } +.bi-bookmark-fill::before { content: "\f199"; } +.bi-bookmark-heart-fill::before { content: "\f19a"; } +.bi-bookmark-heart::before { content: "\f19b"; } +.bi-bookmark-plus-fill::before { content: "\f19c"; } +.bi-bookmark-plus::before { content: "\f19d"; } +.bi-bookmark-star-fill::before { content: "\f19e"; } +.bi-bookmark-star::before { content: "\f19f"; } +.bi-bookmark-x-fill::before { content: "\f1a0"; } +.bi-bookmark-x::before { content: "\f1a1"; } +.bi-bookmark::before { content: "\f1a2"; } +.bi-bookmarks-fill::before { content: "\f1a3"; } +.bi-bookmarks::before { content: "\f1a4"; } +.bi-bookshelf::before { content: "\f1a5"; } +.bi-bootstrap-fill::before { content: "\f1a6"; } +.bi-bootstrap-reboot::before { content: "\f1a7"; } +.bi-bootstrap::before { content: "\f1a8"; } +.bi-border-all::before { content: "\f1a9"; } +.bi-border-bottom::before { content: "\f1aa"; } +.bi-border-center::before { content: "\f1ab"; } +.bi-border-inner::before { content: "\f1ac"; } +.bi-border-left::before { content: "\f1ad"; } +.bi-border-middle::before { content: "\f1ae"; } +.bi-border-outer::before { content: "\f1af"; } +.bi-border-right::before { content: "\f1b0"; } +.bi-border-style::before { content: "\f1b1"; } +.bi-border-top::before { content: "\f1b2"; } +.bi-border-width::before { content: "\f1b3"; } +.bi-border::before { content: "\f1b4"; } +.bi-bounding-box-circles::before { content: "\f1b5"; } +.bi-bounding-box::before { content: "\f1b6"; } +.bi-box-arrow-down-left::before { content: "\f1b7"; } +.bi-box-arrow-down-right::before { content: "\f1b8"; } +.bi-box-arrow-down::before { content: "\f1b9"; } +.bi-box-arrow-in-down-left::before { content: "\f1ba"; } +.bi-box-arrow-in-down-right::before { content: "\f1bb"; } +.bi-box-arrow-in-down::before { content: "\f1bc"; } +.bi-box-arrow-in-left::before { content: "\f1bd"; } +.bi-box-arrow-in-right::before { content: "\f1be"; } +.bi-box-arrow-in-up-left::before { content: "\f1bf"; } +.bi-box-arrow-in-up-right::before { content: "\f1c0"; } +.bi-box-arrow-in-up::before { content: "\f1c1"; } +.bi-box-arrow-left::before { content: "\f1c2"; } +.bi-box-arrow-right::before { content: "\f1c3"; } +.bi-box-arrow-up-left::before { content: "\f1c4"; } +.bi-box-arrow-up-right::before { content: "\f1c5"; } +.bi-box-arrow-up::before { content: "\f1c6"; } +.bi-box-seam::before { content: "\f1c7"; } +.bi-box::before { content: "\f1c8"; } +.bi-braces::before { content: "\f1c9"; } +.bi-bricks::before { content: "\f1ca"; } +.bi-briefcase-fill::before { content: "\f1cb"; } +.bi-briefcase::before { content: "\f1cc"; } +.bi-brightness-alt-high-fill::before { content: "\f1cd"; } +.bi-brightness-alt-high::before { content: "\f1ce"; } +.bi-brightness-alt-low-fill::before { content: "\f1cf"; } +.bi-brightness-alt-low::before { content: "\f1d0"; } +.bi-brightness-high-fill::before { content: "\f1d1"; } +.bi-brightness-high::before { content: "\f1d2"; } +.bi-brightness-low-fill::before { content: "\f1d3"; } +.bi-brightness-low::before { content: "\f1d4"; } +.bi-broadcast-pin::before { content: "\f1d5"; } +.bi-broadcast::before { content: "\f1d6"; } +.bi-brush-fill::before { content: "\f1d7"; } +.bi-brush::before { content: "\f1d8"; } +.bi-bucket-fill::before { content: "\f1d9"; } +.bi-bucket::before { content: "\f1da"; } +.bi-bug-fill::before { content: "\f1db"; } +.bi-bug::before { content: "\f1dc"; } +.bi-building::before { content: "\f1dd"; } +.bi-bullseye::before { content: "\f1de"; } +.bi-calculator-fill::before { content: "\f1df"; } +.bi-calculator::before { content: "\f1e0"; } +.bi-calendar-check-fill::before { content: "\f1e1"; } +.bi-calendar-check::before { content: "\f1e2"; } +.bi-calendar-date-fill::before { content: "\f1e3"; } +.bi-calendar-date::before { content: "\f1e4"; } +.bi-calendar-day-fill::before { content: "\f1e5"; } +.bi-calendar-day::before { content: "\f1e6"; } +.bi-calendar-event-fill::before { content: "\f1e7"; } +.bi-calendar-event::before { content: "\f1e8"; } +.bi-calendar-fill::before { content: "\f1e9"; } +.bi-calendar-minus-fill::before { content: "\f1ea"; } +.bi-calendar-minus::before { content: "\f1eb"; } +.bi-calendar-month-fill::before { content: "\f1ec"; } +.bi-calendar-month::before { content: "\f1ed"; } +.bi-calendar-plus-fill::before { content: "\f1ee"; } +.bi-calendar-plus::before { content: "\f1ef"; } +.bi-calendar-range-fill::before { content: "\f1f0"; } +.bi-calendar-range::before { content: "\f1f1"; } +.bi-calendar-week-fill::before { content: "\f1f2"; } +.bi-calendar-week::before { content: "\f1f3"; } +.bi-calendar-x-fill::before { content: "\f1f4"; } +.bi-calendar-x::before { content: "\f1f5"; } +.bi-calendar::before { content: "\f1f6"; } +.bi-calendar2-check-fill::before { content: "\f1f7"; } +.bi-calendar2-check::before { content: "\f1f8"; } +.bi-calendar2-date-fill::before { content: "\f1f9"; } +.bi-calendar2-date::before { content: "\f1fa"; } +.bi-calendar2-day-fill::before { content: "\f1fb"; } +.bi-calendar2-day::before { content: "\f1fc"; } +.bi-calendar2-event-fill::before { content: "\f1fd"; } +.bi-calendar2-event::before { content: "\f1fe"; } +.bi-calendar2-fill::before { content: "\f1ff"; } +.bi-calendar2-minus-fill::before { content: "\f200"; } +.bi-calendar2-minus::before { content: "\f201"; } +.bi-calendar2-month-fill::before { content: "\f202"; } +.bi-calendar2-month::before { content: "\f203"; } +.bi-calendar2-plus-fill::before { content: "\f204"; } +.bi-calendar2-plus::before { content: "\f205"; } +.bi-calendar2-range-fill::before { content: "\f206"; } +.bi-calendar2-range::before { content: "\f207"; } +.bi-calendar2-week-fill::before { content: "\f208"; } +.bi-calendar2-week::before { content: "\f209"; } +.bi-calendar2-x-fill::before { content: "\f20a"; } +.bi-calendar2-x::before { content: "\f20b"; } +.bi-calendar2::before { content: "\f20c"; } +.bi-calendar3-event-fill::before { content: "\f20d"; } +.bi-calendar3-event::before { content: "\f20e"; } +.bi-calendar3-fill::before { content: "\f20f"; } +.bi-calendar3-range-fill::before { content: "\f210"; } +.bi-calendar3-range::before { content: "\f211"; } +.bi-calendar3-week-fill::before { content: "\f212"; } +.bi-calendar3-week::before { content: "\f213"; } +.bi-calendar3::before { content: "\f214"; } +.bi-calendar4-event::before { content: "\f215"; } +.bi-calendar4-range::before { content: "\f216"; } +.bi-calendar4-week::before { content: "\f217"; } +.bi-calendar4::before { content: "\f218"; } +.bi-camera-fill::before { content: "\f219"; } +.bi-camera-reels-fill::before { content: "\f21a"; } +.bi-camera-reels::before { content: "\f21b"; } +.bi-camera-video-fill::before { content: "\f21c"; } +.bi-camera-video-off-fill::before { content: "\f21d"; } +.bi-camera-video-off::before { content: "\f21e"; } +.bi-camera-video::before { content: "\f21f"; } +.bi-camera::before { content: "\f220"; } +.bi-camera2::before { content: "\f221"; } +.bi-capslock-fill::before { content: "\f222"; } +.bi-capslock::before { content: "\f223"; } +.bi-card-checklist::before { content: "\f224"; } +.bi-card-heading::before { content: "\f225"; } +.bi-card-image::before { content: "\f226"; } +.bi-card-list::before { content: "\f227"; } +.bi-card-text::before { content: "\f228"; } +.bi-caret-down-fill::before { content: "\f229"; } +.bi-caret-down-square-fill::before { content: "\f22a"; } +.bi-caret-down-square::before { content: "\f22b"; } +.bi-caret-down::before { content: "\f22c"; } +.bi-caret-left-fill::before { content: "\f22d"; } +.bi-caret-left-square-fill::before { content: "\f22e"; } +.bi-caret-left-square::before { content: "\f22f"; } +.bi-caret-left::before { content: "\f230"; } +.bi-caret-right-fill::before { content: "\f231"; } +.bi-caret-right-square-fill::before { content: "\f232"; } +.bi-caret-right-square::before { content: "\f233"; } +.bi-caret-right::before { content: "\f234"; } +.bi-caret-up-fill::before { content: "\f235"; } +.bi-caret-up-square-fill::before { content: "\f236"; } +.bi-caret-up-square::before { content: "\f237"; } +.bi-caret-up::before { content: "\f238"; } +.bi-cart-check-fill::before { content: "\f239"; } +.bi-cart-check::before { content: "\f23a"; } +.bi-cart-dash-fill::before { content: "\f23b"; } +.bi-cart-dash::before { content: "\f23c"; } +.bi-cart-fill::before { content: "\f23d"; } +.bi-cart-plus-fill::before { content: "\f23e"; } +.bi-cart-plus::before { content: "\f23f"; } +.bi-cart-x-fill::before { content: "\f240"; } +.bi-cart-x::before { content: "\f241"; } +.bi-cart::before { content: "\f242"; } +.bi-cart2::before { content: "\f243"; } +.bi-cart3::before { content: "\f244"; } +.bi-cart4::before { content: "\f245"; } +.bi-cash-stack::before { content: "\f246"; } +.bi-cash::before { content: "\f247"; } +.bi-cast::before { content: "\f248"; } +.bi-chat-dots-fill::before { content: "\f249"; } +.bi-chat-dots::before { content: "\f24a"; } +.bi-chat-fill::before { content: "\f24b"; } +.bi-chat-left-dots-fill::before { content: "\f24c"; } +.bi-chat-left-dots::before { content: "\f24d"; } +.bi-chat-left-fill::before { content: "\f24e"; } +.bi-chat-left-quote-fill::before { content: "\f24f"; } +.bi-chat-left-quote::before { content: "\f250"; } +.bi-chat-left-text-fill::before { content: "\f251"; } +.bi-chat-left-text::before { content: "\f252"; } +.bi-chat-left::before { content: "\f253"; } +.bi-chat-quote-fill::before { content: "\f254"; } +.bi-chat-quote::before { content: "\f255"; } +.bi-chat-right-dots-fill::before { content: "\f256"; } +.bi-chat-right-dots::before { content: "\f257"; } +.bi-chat-right-fill::before { content: "\f258"; } +.bi-chat-right-quote-fill::before { content: "\f259"; } +.bi-chat-right-quote::before { content: "\f25a"; } +.bi-chat-right-text-fill::before { content: "\f25b"; } +.bi-chat-right-text::before { content: "\f25c"; } +.bi-chat-right::before { content: "\f25d"; } +.bi-chat-square-dots-fill::before { content: "\f25e"; } +.bi-chat-square-dots::before { content: "\f25f"; } +.bi-chat-square-fill::before { content: "\f260"; } +.bi-chat-square-quote-fill::before { content: "\f261"; } +.bi-chat-square-quote::before { content: "\f262"; } +.bi-chat-square-text-fill::before { content: "\f263"; } +.bi-chat-square-text::before { content: "\f264"; } +.bi-chat-square::before { content: "\f265"; } +.bi-chat-text-fill::before { content: "\f266"; } +.bi-chat-text::before { content: "\f267"; } +.bi-chat::before { content: "\f268"; } +.bi-check-all::before { content: "\f269"; } +.bi-check-circle-fill::before { content: "\f26a"; } +.bi-check-circle::before { content: "\f26b"; } +.bi-check-square-fill::before { content: "\f26c"; } +.bi-check-square::before { content: "\f26d"; } +.bi-check::before { content: "\f26e"; } +.bi-check2-all::before { content: "\f26f"; } +.bi-check2-circle::before { content: "\f270"; } +.bi-check2-square::before { content: "\f271"; } +.bi-check2::before { content: "\f272"; } +.bi-chevron-bar-contract::before { content: "\f273"; } +.bi-chevron-bar-down::before { content: "\f274"; } +.bi-chevron-bar-expand::before { content: "\f275"; } +.bi-chevron-bar-left::before { content: "\f276"; } +.bi-chevron-bar-right::before { content: "\f277"; } +.bi-chevron-bar-up::before { content: "\f278"; } +.bi-chevron-compact-down::before { content: "\f279"; } +.bi-chevron-compact-left::before { content: "\f27a"; } +.bi-chevron-compact-right::before { content: "\f27b"; } +.bi-chevron-compact-up::before { content: "\f27c"; } +.bi-chevron-contract::before { content: "\f27d"; } +.bi-chevron-double-down::before { content: "\f27e"; } +.bi-chevron-double-left::before { content: "\f27f"; } +.bi-chevron-double-right::before { content: "\f280"; } +.bi-chevron-double-up::before { content: "\f281"; } +.bi-chevron-down::before { content: "\f282"; } +.bi-chevron-expand::before { content: "\f283"; } +.bi-chevron-left::before { content: "\f284"; } +.bi-chevron-right::before { content: "\f285"; } +.bi-chevron-up::before { content: "\f286"; } +.bi-circle-fill::before { content: "\f287"; } +.bi-circle-half::before { content: "\f288"; } +.bi-circle-square::before { content: "\f289"; } +.bi-circle::before { content: "\f28a"; } +.bi-clipboard-check::before { content: "\f28b"; } +.bi-clipboard-data::before { content: "\f28c"; } +.bi-clipboard-minus::before { content: "\f28d"; } +.bi-clipboard-plus::before { content: "\f28e"; } +.bi-clipboard-x::before { content: "\f28f"; } +.bi-clipboard::before { content: "\f290"; } +.bi-clock-fill::before { content: "\f291"; } +.bi-clock-history::before { content: "\f292"; } +.bi-clock::before { content: "\f293"; } +.bi-cloud-arrow-down-fill::before { content: "\f294"; } +.bi-cloud-arrow-down::before { content: "\f295"; } +.bi-cloud-arrow-up-fill::before { content: "\f296"; } +.bi-cloud-arrow-up::before { content: "\f297"; } +.bi-cloud-check-fill::before { content: "\f298"; } +.bi-cloud-check::before { content: "\f299"; } +.bi-cloud-download-fill::before { content: "\f29a"; } +.bi-cloud-download::before { content: "\f29b"; } +.bi-cloud-drizzle-fill::before { content: "\f29c"; } +.bi-cloud-drizzle::before { content: "\f29d"; } +.bi-cloud-fill::before { content: "\f29e"; } +.bi-cloud-fog-fill::before { content: "\f29f"; } +.bi-cloud-fog::before { content: "\f2a0"; } +.bi-cloud-fog2-fill::before { content: "\f2a1"; } +.bi-cloud-fog2::before { content: "\f2a2"; } +.bi-cloud-hail-fill::before { content: "\f2a3"; } +.bi-cloud-hail::before { content: "\f2a4"; } +.bi-cloud-haze-fill::before { content: "\f2a6"; } +.bi-cloud-haze::before { content: "\f2a7"; } +.bi-cloud-haze2-fill::before { content: "\f2a8"; } +.bi-cloud-lightning-fill::before { content: "\f2a9"; } +.bi-cloud-lightning-rain-fill::before { content: "\f2aa"; } +.bi-cloud-lightning-rain::before { content: "\f2ab"; } +.bi-cloud-lightning::before { content: "\f2ac"; } +.bi-cloud-minus-fill::before { content: "\f2ad"; } +.bi-cloud-minus::before { content: "\f2ae"; } +.bi-cloud-moon-fill::before { content: "\f2af"; } +.bi-cloud-moon::before { content: "\f2b0"; } +.bi-cloud-plus-fill::before { content: "\f2b1"; } +.bi-cloud-plus::before { content: "\f2b2"; } +.bi-cloud-rain-fill::before { content: "\f2b3"; } +.bi-cloud-rain-heavy-fill::before { content: "\f2b4"; } +.bi-cloud-rain-heavy::before { content: "\f2b5"; } +.bi-cloud-rain::before { content: "\f2b6"; } +.bi-cloud-slash-fill::before { content: "\f2b7"; } +.bi-cloud-slash::before { content: "\f2b8"; } +.bi-cloud-sleet-fill::before { content: "\f2b9"; } +.bi-cloud-sleet::before { content: "\f2ba"; } +.bi-cloud-snow-fill::before { content: "\f2bb"; } +.bi-cloud-snow::before { content: "\f2bc"; } +.bi-cloud-sun-fill::before { content: "\f2bd"; } +.bi-cloud-sun::before { content: "\f2be"; } +.bi-cloud-upload-fill::before { content: "\f2bf"; } +.bi-cloud-upload::before { content: "\f2c0"; } +.bi-cloud::before { content: "\f2c1"; } +.bi-clouds-fill::before { content: "\f2c2"; } +.bi-clouds::before { content: "\f2c3"; } +.bi-cloudy-fill::before { content: "\f2c4"; } +.bi-cloudy::before { content: "\f2c5"; } +.bi-code-slash::before { content: "\f2c6"; } +.bi-code-square::before { content: "\f2c7"; } +.bi-code::before { content: "\f2c8"; } +.bi-collection-fill::before { content: "\f2c9"; } +.bi-collection-play-fill::before { content: "\f2ca"; } +.bi-collection-play::before { content: "\f2cb"; } +.bi-collection::before { content: "\f2cc"; } +.bi-columns-gap::before { content: "\f2cd"; } +.bi-columns::before { content: "\f2ce"; } +.bi-command::before { content: "\f2cf"; } +.bi-compass-fill::before { content: "\f2d0"; } +.bi-compass::before { content: "\f2d1"; } +.bi-cone-striped::before { content: "\f2d2"; } +.bi-cone::before { content: "\f2d3"; } +.bi-controller::before { content: "\f2d4"; } +.bi-cpu-fill::before { content: "\f2d5"; } +.bi-cpu::before { content: "\f2d6"; } +.bi-credit-card-2-back-fill::before { content: "\f2d7"; } +.bi-credit-card-2-back::before { content: "\f2d8"; } +.bi-credit-card-2-front-fill::before { content: "\f2d9"; } +.bi-credit-card-2-front::before { content: "\f2da"; } +.bi-credit-card-fill::before { content: "\f2db"; } +.bi-credit-card::before { content: "\f2dc"; } +.bi-crop::before { content: "\f2dd"; } +.bi-cup-fill::before { content: "\f2de"; } +.bi-cup-straw::before { content: "\f2df"; } +.bi-cup::before { content: "\f2e0"; } +.bi-cursor-fill::before { content: "\f2e1"; } +.bi-cursor-text::before { content: "\f2e2"; } +.bi-cursor::before { content: "\f2e3"; } +.bi-dash-circle-dotted::before { content: "\f2e4"; } +.bi-dash-circle-fill::before { content: "\f2e5"; } +.bi-dash-circle::before { content: "\f2e6"; } +.bi-dash-square-dotted::before { content: "\f2e7"; } +.bi-dash-square-fill::before { content: "\f2e8"; } +.bi-dash-square::before { content: "\f2e9"; } +.bi-dash::before { content: "\f2ea"; } +.bi-diagram-2-fill::before { content: "\f2eb"; } +.bi-diagram-2::before { content: "\f2ec"; } +.bi-diagram-3-fill::before { content: "\f2ed"; } +.bi-diagram-3::before { content: "\f2ee"; } +.bi-diamond-fill::before { content: "\f2ef"; } +.bi-diamond-half::before { content: "\f2f0"; } +.bi-diamond::before { content: "\f2f1"; } +.bi-dice-1-fill::before { content: "\f2f2"; } +.bi-dice-1::before { content: "\f2f3"; } +.bi-dice-2-fill::before { content: "\f2f4"; } +.bi-dice-2::before { content: "\f2f5"; } +.bi-dice-3-fill::before { content: "\f2f6"; } +.bi-dice-3::before { content: "\f2f7"; } +.bi-dice-4-fill::before { content: "\f2f8"; } +.bi-dice-4::before { content: "\f2f9"; } +.bi-dice-5-fill::before { content: "\f2fa"; } +.bi-dice-5::before { content: "\f2fb"; } +.bi-dice-6-fill::before { content: "\f2fc"; } +.bi-dice-6::before { content: "\f2fd"; } +.bi-disc-fill::before { content: "\f2fe"; } +.bi-disc::before { content: "\f2ff"; } +.bi-discord::before { content: "\f300"; } +.bi-display-fill::before { content: "\f301"; } +.bi-display::before { content: "\f302"; } +.bi-distribute-horizontal::before { content: "\f303"; } +.bi-distribute-vertical::before { content: "\f304"; } +.bi-door-closed-fill::before { content: "\f305"; } +.bi-door-closed::before { content: "\f306"; } +.bi-door-open-fill::before { content: "\f307"; } +.bi-door-open::before { content: "\f308"; } +.bi-dot::before { content: "\f309"; } +.bi-download::before { content: "\f30a"; } +.bi-droplet-fill::before { content: "\f30b"; } +.bi-droplet-half::before { content: "\f30c"; } +.bi-droplet::before { content: "\f30d"; } +.bi-earbuds::before { content: "\f30e"; } +.bi-easel-fill::before { content: "\f30f"; } +.bi-easel::before { content: "\f310"; } +.bi-egg-fill::before { content: "\f311"; } +.bi-egg-fried::before { content: "\f312"; } +.bi-egg::before { content: "\f313"; } +.bi-eject-fill::before { content: "\f314"; } +.bi-eject::before { content: "\f315"; } +.bi-emoji-angry-fill::before { content: "\f316"; } +.bi-emoji-angry::before { content: "\f317"; } +.bi-emoji-dizzy-fill::before { content: "\f318"; } +.bi-emoji-dizzy::before { content: "\f319"; } +.bi-emoji-expressionless-fill::before { content: "\f31a"; } +.bi-emoji-expressionless::before { content: "\f31b"; } +.bi-emoji-frown-fill::before { content: "\f31c"; } +.bi-emoji-frown::before { content: "\f31d"; } +.bi-emoji-heart-eyes-fill::before { content: "\f31e"; } +.bi-emoji-heart-eyes::before { content: "\f31f"; } +.bi-emoji-laughing-fill::before { content: "\f320"; } +.bi-emoji-laughing::before { content: "\f321"; } +.bi-emoji-neutral-fill::before { content: "\f322"; } +.bi-emoji-neutral::before { content: "\f323"; } +.bi-emoji-smile-fill::before { content: "\f324"; } +.bi-emoji-smile-upside-down-fill::before { content: "\f325"; } +.bi-emoji-smile-upside-down::before { content: "\f326"; } +.bi-emoji-smile::before { content: "\f327"; } +.bi-emoji-sunglasses-fill::before { content: "\f328"; } +.bi-emoji-sunglasses::before { content: "\f329"; } +.bi-emoji-wink-fill::before { content: "\f32a"; } +.bi-emoji-wink::before { content: "\f32b"; } +.bi-envelope-fill::before { content: "\f32c"; } +.bi-envelope-open-fill::before { content: "\f32d"; } +.bi-envelope-open::before { content: "\f32e"; } +.bi-envelope::before { content: "\f32f"; } +.bi-eraser-fill::before { content: "\f330"; } +.bi-eraser::before { content: "\f331"; } +.bi-exclamation-circle-fill::before { content: "\f332"; } +.bi-exclamation-circle::before { content: "\f333"; } +.bi-exclamation-diamond-fill::before { content: "\f334"; } +.bi-exclamation-diamond::before { content: "\f335"; } +.bi-exclamation-octagon-fill::before { content: "\f336"; } +.bi-exclamation-octagon::before { content: "\f337"; } +.bi-exclamation-square-fill::before { content: "\f338"; } +.bi-exclamation-square::before { content: "\f339"; } +.bi-exclamation-triangle-fill::before { content: "\f33a"; } +.bi-exclamation-triangle::before { content: "\f33b"; } +.bi-exclamation::before { content: "\f33c"; } +.bi-exclude::before { content: "\f33d"; } +.bi-eye-fill::before { content: "\f33e"; } +.bi-eye-slash-fill::before { content: "\f33f"; } +.bi-eye-slash::before { content: "\f340"; } +.bi-eye::before { content: "\f341"; } +.bi-eyedropper::before { content: "\f342"; } +.bi-eyeglasses::before { content: "\f343"; } +.bi-facebook::before { content: "\f344"; } +.bi-file-arrow-down-fill::before { content: "\f345"; } +.bi-file-arrow-down::before { content: "\f346"; } +.bi-file-arrow-up-fill::before { content: "\f347"; } +.bi-file-arrow-up::before { content: "\f348"; } +.bi-file-bar-graph-fill::before { content: "\f349"; } +.bi-file-bar-graph::before { content: "\f34a"; } +.bi-file-binary-fill::before { content: "\f34b"; } +.bi-file-binary::before { content: "\f34c"; } +.bi-file-break-fill::before { content: "\f34d"; } +.bi-file-break::before { content: "\f34e"; } +.bi-file-check-fill::before { content: "\f34f"; } +.bi-file-check::before { content: "\f350"; } +.bi-file-code-fill::before { content: "\f351"; } +.bi-file-code::before { content: "\f352"; } +.bi-file-diff-fill::before { content: "\f353"; } +.bi-file-diff::before { content: "\f354"; } +.bi-file-earmark-arrow-down-fill::before { content: "\f355"; } +.bi-file-earmark-arrow-down::before { content: "\f356"; } +.bi-file-earmark-arrow-up-fill::before { content: "\f357"; } +.bi-file-earmark-arrow-up::before { content: "\f358"; } +.bi-file-earmark-bar-graph-fill::before { content: "\f359"; } +.bi-file-earmark-bar-graph::before { content: "\f35a"; } +.bi-file-earmark-binary-fill::before { content: "\f35b"; } +.bi-file-earmark-binary::before { content: "\f35c"; } +.bi-file-earmark-break-fill::before { content: "\f35d"; } +.bi-file-earmark-break::before { content: "\f35e"; } +.bi-file-earmark-check-fill::before { content: "\f35f"; } +.bi-file-earmark-check::before { content: "\f360"; } +.bi-file-earmark-code-fill::before { content: "\f361"; } +.bi-file-earmark-code::before { content: "\f362"; } +.bi-file-earmark-diff-fill::before { content: "\f363"; } +.bi-file-earmark-diff::before { content: "\f364"; } +.bi-file-earmark-easel-fill::before { content: "\f365"; } +.bi-file-earmark-easel::before { content: "\f366"; } +.bi-file-earmark-excel-fill::before { content: "\f367"; } +.bi-file-earmark-excel::before { content: "\f368"; } +.bi-file-earmark-fill::before { content: "\f369"; } +.bi-file-earmark-font-fill::before { content: "\f36a"; } +.bi-file-earmark-font::before { content: "\f36b"; } +.bi-file-earmark-image-fill::before { content: "\f36c"; } +.bi-file-earmark-image::before { content: "\f36d"; } +.bi-file-earmark-lock-fill::before { content: "\f36e"; } +.bi-file-earmark-lock::before { content: "\f36f"; } +.bi-file-earmark-lock2-fill::before { content: "\f370"; } +.bi-file-earmark-lock2::before { content: "\f371"; } +.bi-file-earmark-medical-fill::before { content: "\f372"; } +.bi-file-earmark-medical::before { content: "\f373"; } +.bi-file-earmark-minus-fill::before { content: "\f374"; } +.bi-file-earmark-minus::before { content: "\f375"; } +.bi-file-earmark-music-fill::before { content: "\f376"; } +.bi-file-earmark-music::before { content: "\f377"; } +.bi-file-earmark-person-fill::before { content: "\f378"; } +.bi-file-earmark-person::before { content: "\f379"; } +.bi-file-earmark-play-fill::before { content: "\f37a"; } +.bi-file-earmark-play::before { content: "\f37b"; } +.bi-file-earmark-plus-fill::before { content: "\f37c"; } +.bi-file-earmark-plus::before { content: "\f37d"; } +.bi-file-earmark-post-fill::before { content: "\f37e"; } +.bi-file-earmark-post::before { content: "\f37f"; } +.bi-file-earmark-ppt-fill::before { content: "\f380"; } +.bi-file-earmark-ppt::before { content: "\f381"; } +.bi-file-earmark-richtext-fill::before { content: "\f382"; } +.bi-file-earmark-richtext::before { content: "\f383"; } +.bi-file-earmark-ruled-fill::before { content: "\f384"; } +.bi-file-earmark-ruled::before { content: "\f385"; } +.bi-file-earmark-slides-fill::before { content: "\f386"; } +.bi-file-earmark-slides::before { content: "\f387"; } +.bi-file-earmark-spreadsheet-fill::before { content: "\f388"; } +.bi-file-earmark-spreadsheet::before { content: "\f389"; } +.bi-file-earmark-text-fill::before { content: "\f38a"; } +.bi-file-earmark-text::before { content: "\f38b"; } +.bi-file-earmark-word-fill::before { content: "\f38c"; } +.bi-file-earmark-word::before { content: "\f38d"; } +.bi-file-earmark-x-fill::before { content: "\f38e"; } +.bi-file-earmark-x::before { content: "\f38f"; } +.bi-file-earmark-zip-fill::before { content: "\f390"; } +.bi-file-earmark-zip::before { content: "\f391"; } +.bi-file-earmark::before { content: "\f392"; } +.bi-file-easel-fill::before { content: "\f393"; } +.bi-file-easel::before { content: "\f394"; } +.bi-file-excel-fill::before { content: "\f395"; } +.bi-file-excel::before { content: "\f396"; } +.bi-file-fill::before { content: "\f397"; } +.bi-file-font-fill::before { content: "\f398"; } +.bi-file-font::before { content: "\f399"; } +.bi-file-image-fill::before { content: "\f39a"; } +.bi-file-image::before { content: "\f39b"; } +.bi-file-lock-fill::before { content: "\f39c"; } +.bi-file-lock::before { content: "\f39d"; } +.bi-file-lock2-fill::before { content: "\f39e"; } +.bi-file-lock2::before { content: "\f39f"; } +.bi-file-medical-fill::before { content: "\f3a0"; } +.bi-file-medical::before { content: "\f3a1"; } +.bi-file-minus-fill::before { content: "\f3a2"; } +.bi-file-minus::before { content: "\f3a3"; } +.bi-file-music-fill::before { content: "\f3a4"; } +.bi-file-music::before { content: "\f3a5"; } +.bi-file-person-fill::before { content: "\f3a6"; } +.bi-file-person::before { content: "\f3a7"; } +.bi-file-play-fill::before { content: "\f3a8"; } +.bi-file-play::before { content: "\f3a9"; } +.bi-file-plus-fill::before { content: "\f3aa"; } +.bi-file-plus::before { content: "\f3ab"; } +.bi-file-post-fill::before { content: "\f3ac"; } +.bi-file-post::before { content: "\f3ad"; } +.bi-file-ppt-fill::before { content: "\f3ae"; } +.bi-file-ppt::before { content: "\f3af"; } +.bi-file-richtext-fill::before { content: "\f3b0"; } +.bi-file-richtext::before { content: "\f3b1"; } +.bi-file-ruled-fill::before { content: "\f3b2"; } +.bi-file-ruled::before { content: "\f3b3"; } +.bi-file-slides-fill::before { content: "\f3b4"; } +.bi-file-slides::before { content: "\f3b5"; } +.bi-file-spreadsheet-fill::before { content: "\f3b6"; } +.bi-file-spreadsheet::before { content: "\f3b7"; } +.bi-file-text-fill::before { content: "\f3b8"; } +.bi-file-text::before { content: "\f3b9"; } +.bi-file-word-fill::before { content: "\f3ba"; } +.bi-file-word::before { content: "\f3bb"; } +.bi-file-x-fill::before { content: "\f3bc"; } +.bi-file-x::before { content: "\f3bd"; } +.bi-file-zip-fill::before { content: "\f3be"; } +.bi-file-zip::before { content: "\f3bf"; } +.bi-file::before { content: "\f3c0"; } +.bi-files-alt::before { content: "\f3c1"; } +.bi-files::before { content: "\f3c2"; } +.bi-film::before { content: "\f3c3"; } +.bi-filter-circle-fill::before { content: "\f3c4"; } +.bi-filter-circle::before { content: "\f3c5"; } +.bi-filter-left::before { content: "\f3c6"; } +.bi-filter-right::before { content: "\f3c7"; } +.bi-filter-square-fill::before { content: "\f3c8"; } +.bi-filter-square::before { content: "\f3c9"; } +.bi-filter::before { content: "\f3ca"; } +.bi-flag-fill::before { content: "\f3cb"; } +.bi-flag::before { content: "\f3cc"; } +.bi-flower1::before { content: "\f3cd"; } +.bi-flower2::before { content: "\f3ce"; } +.bi-flower3::before { content: "\f3cf"; } +.bi-folder-check::before { content: "\f3d0"; } +.bi-folder-fill::before { content: "\f3d1"; } +.bi-folder-minus::before { content: "\f3d2"; } +.bi-folder-plus::before { content: "\f3d3"; } +.bi-folder-symlink-fill::before { content: "\f3d4"; } +.bi-folder-symlink::before { content: "\f3d5"; } +.bi-folder-x::before { content: "\f3d6"; } +.bi-folder::before { content: "\f3d7"; } +.bi-folder2-open::before { content: "\f3d8"; } +.bi-folder2::before { content: "\f3d9"; } +.bi-fonts::before { content: "\f3da"; } +.bi-forward-fill::before { content: "\f3db"; } +.bi-forward::before { content: "\f3dc"; } +.bi-front::before { content: "\f3dd"; } +.bi-fullscreen-exit::before { content: "\f3de"; } +.bi-fullscreen::before { content: "\f3df"; } +.bi-funnel-fill::before { content: "\f3e0"; } +.bi-funnel::before { content: "\f3e1"; } +.bi-gear-fill::before { content: "\f3e2"; } +.bi-gear-wide-connected::before { content: "\f3e3"; } +.bi-gear-wide::before { content: "\f3e4"; } +.bi-gear::before { content: "\f3e5"; } +.bi-gem::before { content: "\f3e6"; } +.bi-geo-alt-fill::before { content: "\f3e7"; } +.bi-geo-alt::before { content: "\f3e8"; } +.bi-geo-fill::before { content: "\f3e9"; } +.bi-geo::before { content: "\f3ea"; } +.bi-gift-fill::before { content: "\f3eb"; } +.bi-gift::before { content: "\f3ec"; } +.bi-github::before { content: "\f3ed"; } +.bi-globe::before { content: "\f3ee"; } +.bi-globe2::before { content: "\f3ef"; } +.bi-google::before { content: "\f3f0"; } +.bi-graph-down::before { content: "\f3f1"; } +.bi-graph-up::before { content: "\f3f2"; } +.bi-grid-1x2-fill::before { content: "\f3f3"; } +.bi-grid-1x2::before { content: "\f3f4"; } +.bi-grid-3x2-gap-fill::before { content: "\f3f5"; } +.bi-grid-3x2-gap::before { content: "\f3f6"; } +.bi-grid-3x2::before { content: "\f3f7"; } +.bi-grid-3x3-gap-fill::before { content: "\f3f8"; } +.bi-grid-3x3-gap::before { content: "\f3f9"; } +.bi-grid-3x3::before { content: "\f3fa"; } +.bi-grid-fill::before { content: "\f3fb"; } +.bi-grid::before { content: "\f3fc"; } +.bi-grip-horizontal::before { content: "\f3fd"; } +.bi-grip-vertical::before { content: "\f3fe"; } +.bi-hammer::before { content: "\f3ff"; } +.bi-hand-index-fill::before { content: "\f400"; } +.bi-hand-index-thumb-fill::before { content: "\f401"; } +.bi-hand-index-thumb::before { content: "\f402"; } +.bi-hand-index::before { content: "\f403"; } +.bi-hand-thumbs-down-fill::before { content: "\f404"; } +.bi-hand-thumbs-down::before { content: "\f405"; } +.bi-hand-thumbs-up-fill::before { content: "\f406"; } +.bi-hand-thumbs-up::before { content: "\f407"; } +.bi-handbag-fill::before { content: "\f408"; } +.bi-handbag::before { content: "\f409"; } +.bi-hash::before { content: "\f40a"; } +.bi-hdd-fill::before { content: "\f40b"; } +.bi-hdd-network-fill::before { content: "\f40c"; } +.bi-hdd-network::before { content: "\f40d"; } +.bi-hdd-rack-fill::before { content: "\f40e"; } +.bi-hdd-rack::before { content: "\f40f"; } +.bi-hdd-stack-fill::before { content: "\f410"; } +.bi-hdd-stack::before { content: "\f411"; } +.bi-hdd::before { content: "\f412"; } +.bi-headphones::before { content: "\f413"; } +.bi-headset::before { content: "\f414"; } +.bi-heart-fill::before { content: "\f415"; } +.bi-heart-half::before { content: "\f416"; } +.bi-heart::before { content: "\f417"; } +.bi-heptagon-fill::before { content: "\f418"; } +.bi-heptagon-half::before { content: "\f419"; } +.bi-heptagon::before { content: "\f41a"; } +.bi-hexagon-fill::before { content: "\f41b"; } +.bi-hexagon-half::before { content: "\f41c"; } +.bi-hexagon::before { content: "\f41d"; } +.bi-hourglass-bottom::before { content: "\f41e"; } +.bi-hourglass-split::before { content: "\f41f"; } +.bi-hourglass-top::before { content: "\f420"; } +.bi-hourglass::before { content: "\f421"; } +.bi-house-door-fill::before { content: "\f422"; } +.bi-house-door::before { content: "\f423"; } +.bi-house-fill::before { content: "\f424"; } +.bi-house::before { content: "\f425"; } +.bi-hr::before { content: "\f426"; } +.bi-hurricane::before { content: "\f427"; } +.bi-image-alt::before { content: "\f428"; } +.bi-image-fill::before { content: "\f429"; } +.bi-image::before { content: "\f42a"; } +.bi-images::before { content: "\f42b"; } +.bi-inbox-fill::before { content: "\f42c"; } +.bi-inbox::before { content: "\f42d"; } +.bi-inboxes-fill::before { content: "\f42e"; } +.bi-inboxes::before { content: "\f42f"; } +.bi-info-circle-fill::before { content: "\f430"; } +.bi-info-circle::before { content: "\f431"; } +.bi-info-square-fill::before { content: "\f432"; } +.bi-info-square::before { content: "\f433"; } +.bi-info::before { content: "\f434"; } +.bi-input-cursor-text::before { content: "\f435"; } +.bi-input-cursor::before { content: "\f436"; } +.bi-instagram::before { content: "\f437"; } +.bi-intersect::before { content: "\f438"; } +.bi-journal-album::before { content: "\f439"; } +.bi-journal-arrow-down::before { content: "\f43a"; } +.bi-journal-arrow-up::before { content: "\f43b"; } +.bi-journal-bookmark-fill::before { content: "\f43c"; } +.bi-journal-bookmark::before { content: "\f43d"; } +.bi-journal-check::before { content: "\f43e"; } +.bi-journal-code::before { content: "\f43f"; } +.bi-journal-medical::before { content: "\f440"; } +.bi-journal-minus::before { content: "\f441"; } +.bi-journal-plus::before { content: "\f442"; } +.bi-journal-richtext::before { content: "\f443"; } +.bi-journal-text::before { content: "\f444"; } +.bi-journal-x::before { content: "\f445"; } +.bi-journal::before { content: "\f446"; } +.bi-journals::before { content: "\f447"; } +.bi-joystick::before { content: "\f448"; } +.bi-justify-left::before { content: "\f449"; } +.bi-justify-right::before { content: "\f44a"; } +.bi-justify::before { content: "\f44b"; } +.bi-kanban-fill::before { content: "\f44c"; } +.bi-kanban::before { content: "\f44d"; } +.bi-key-fill::before { content: "\f44e"; } +.bi-key::before { content: "\f44f"; } +.bi-keyboard-fill::before { content: "\f450"; } +.bi-keyboard::before { content: "\f451"; } +.bi-ladder::before { content: "\f452"; } +.bi-lamp-fill::before { content: "\f453"; } +.bi-lamp::before { content: "\f454"; } +.bi-laptop-fill::before { content: "\f455"; } +.bi-laptop::before { content: "\f456"; } +.bi-layer-backward::before { content: "\f457"; } +.bi-layer-forward::before { content: "\f458"; } +.bi-layers-fill::before { content: "\f459"; } +.bi-layers-half::before { content: "\f45a"; } +.bi-layers::before { content: "\f45b"; } +.bi-layout-sidebar-inset-reverse::before { content: "\f45c"; } +.bi-layout-sidebar-inset::before { content: "\f45d"; } +.bi-layout-sidebar-reverse::before { content: "\f45e"; } +.bi-layout-sidebar::before { content: "\f45f"; } +.bi-layout-split::before { content: "\f460"; } +.bi-layout-text-sidebar-reverse::before { content: "\f461"; } +.bi-layout-text-sidebar::before { content: "\f462"; } +.bi-layout-text-window-reverse::before { content: "\f463"; } +.bi-layout-text-window::before { content: "\f464"; } +.bi-layout-three-columns::before { content: "\f465"; } +.bi-layout-wtf::before { content: "\f466"; } +.bi-life-preserver::before { content: "\f467"; } +.bi-lightbulb-fill::before { content: "\f468"; } +.bi-lightbulb-off-fill::before { content: "\f469"; } +.bi-lightbulb-off::before { content: "\f46a"; } +.bi-lightbulb::before { content: "\f46b"; } +.bi-lightning-charge-fill::before { content: "\f46c"; } +.bi-lightning-charge::before { content: "\f46d"; } +.bi-lightning-fill::before { content: "\f46e"; } +.bi-lightning::before { content: "\f46f"; } +.bi-link-45deg::before { content: "\f470"; } +.bi-link::before { content: "\f471"; } +.bi-linkedin::before { content: "\f472"; } +.bi-list-check::before { content: "\f473"; } +.bi-list-nested::before { content: "\f474"; } +.bi-list-ol::before { content: "\f475"; } +.bi-list-stars::before { content: "\f476"; } +.bi-list-task::before { content: "\f477"; } +.bi-list-ul::before { content: "\f478"; } +.bi-list::before { content: "\f479"; } +.bi-lock-fill::before { content: "\f47a"; } +.bi-lock::before { content: "\f47b"; } +.bi-mailbox::before { content: "\f47c"; } +.bi-mailbox2::before { content: "\f47d"; } +.bi-map-fill::before { content: "\f47e"; } +.bi-map::before { content: "\f47f"; } +.bi-markdown-fill::before { content: "\f480"; } +.bi-markdown::before { content: "\f481"; } +.bi-mask::before { content: "\f482"; } +.bi-megaphone-fill::before { content: "\f483"; } +.bi-megaphone::before { content: "\f484"; } +.bi-menu-app-fill::before { content: "\f485"; } +.bi-menu-app::before { content: "\f486"; } +.bi-menu-button-fill::before { content: "\f487"; } +.bi-menu-button-wide-fill::before { content: "\f488"; } +.bi-menu-button-wide::before { content: "\f489"; } +.bi-menu-button::before { content: "\f48a"; } +.bi-menu-down::before { content: "\f48b"; } +.bi-menu-up::before { content: "\f48c"; } +.bi-mic-fill::before { content: "\f48d"; } +.bi-mic-mute-fill::before { content: "\f48e"; } +.bi-mic-mute::before { content: "\f48f"; } +.bi-mic::before { content: "\f490"; } +.bi-minecart-loaded::before { content: "\f491"; } +.bi-minecart::before { content: "\f492"; } +.bi-moisture::before { content: "\f493"; } +.bi-moon-fill::before { content: "\f494"; } +.bi-moon-stars-fill::before { content: "\f495"; } +.bi-moon-stars::before { content: "\f496"; } +.bi-moon::before { content: "\f497"; } +.bi-mouse-fill::before { content: "\f498"; } +.bi-mouse::before { content: "\f499"; } +.bi-mouse2-fill::before { content: "\f49a"; } +.bi-mouse2::before { content: "\f49b"; } +.bi-mouse3-fill::before { content: "\f49c"; } +.bi-mouse3::before { content: "\f49d"; } +.bi-music-note-beamed::before { content: "\f49e"; } +.bi-music-note-list::before { content: "\f49f"; } +.bi-music-note::before { content: "\f4a0"; } +.bi-music-player-fill::before { content: "\f4a1"; } +.bi-music-player::before { content: "\f4a2"; } +.bi-newspaper::before { content: "\f4a3"; } +.bi-node-minus-fill::before { content: "\f4a4"; } +.bi-node-minus::before { content: "\f4a5"; } +.bi-node-plus-fill::before { content: "\f4a6"; } +.bi-node-plus::before { content: "\f4a7"; } +.bi-nut-fill::before { content: "\f4a8"; } +.bi-nut::before { content: "\f4a9"; } +.bi-octagon-fill::before { content: "\f4aa"; } +.bi-octagon-half::before { content: "\f4ab"; } +.bi-octagon::before { content: "\f4ac"; } +.bi-option::before { content: "\f4ad"; } +.bi-outlet::before { content: "\f4ae"; } +.bi-paint-bucket::before { content: "\f4af"; } +.bi-palette-fill::before { content: "\f4b0"; } +.bi-palette::before { content: "\f4b1"; } +.bi-palette2::before { content: "\f4b2"; } +.bi-paperclip::before { content: "\f4b3"; } +.bi-paragraph::before { content: "\f4b4"; } +.bi-patch-check-fill::before { content: "\f4b5"; } +.bi-patch-check::before { content: "\f4b6"; } +.bi-patch-exclamation-fill::before { content: "\f4b7"; } +.bi-patch-exclamation::before { content: "\f4b8"; } +.bi-patch-minus-fill::before { content: "\f4b9"; } +.bi-patch-minus::before { content: "\f4ba"; } +.bi-patch-plus-fill::before { content: "\f4bb"; } +.bi-patch-plus::before { content: "\f4bc"; } +.bi-patch-question-fill::before { content: "\f4bd"; } +.bi-patch-question::before { content: "\f4be"; } +.bi-pause-btn-fill::before { content: "\f4bf"; } +.bi-pause-btn::before { content: "\f4c0"; } +.bi-pause-circle-fill::before { content: "\f4c1"; } +.bi-pause-circle::before { content: "\f4c2"; } +.bi-pause-fill::before { content: "\f4c3"; } +.bi-pause::before { content: "\f4c4"; } +.bi-peace-fill::before { content: "\f4c5"; } +.bi-peace::before { content: "\f4c6"; } +.bi-pen-fill::before { content: "\f4c7"; } +.bi-pen::before { content: "\f4c8"; } +.bi-pencil-fill::before { content: "\f4c9"; } +.bi-pencil-square::before { content: "\f4ca"; } +.bi-pencil::before { content: "\f4cb"; } +.bi-pentagon-fill::before { content: "\f4cc"; } +.bi-pentagon-half::before { content: "\f4cd"; } +.bi-pentagon::before { content: "\f4ce"; } +.bi-people-fill::before { content: "\f4cf"; } +.bi-people::before { content: "\f4d0"; } +.bi-percent::before { content: "\f4d1"; } +.bi-person-badge-fill::before { content: "\f4d2"; } +.bi-person-badge::before { content: "\f4d3"; } +.bi-person-bounding-box::before { content: "\f4d4"; } +.bi-person-check-fill::before { content: "\f4d5"; } +.bi-person-check::before { content: "\f4d6"; } +.bi-person-circle::before { content: "\f4d7"; } +.bi-person-dash-fill::before { content: "\f4d8"; } +.bi-person-dash::before { content: "\f4d9"; } +.bi-person-fill::before { content: "\f4da"; } +.bi-person-lines-fill::before { content: "\f4db"; } +.bi-person-plus-fill::before { content: "\f4dc"; } +.bi-person-plus::before { content: "\f4dd"; } +.bi-person-square::before { content: "\f4de"; } +.bi-person-x-fill::before { content: "\f4df"; } +.bi-person-x::before { content: "\f4e0"; } +.bi-person::before { content: "\f4e1"; } +.bi-phone-fill::before { content: "\f4e2"; } +.bi-phone-landscape-fill::before { content: "\f4e3"; } +.bi-phone-landscape::before { content: "\f4e4"; } +.bi-phone-vibrate-fill::before { content: "\f4e5"; } +.bi-phone-vibrate::before { content: "\f4e6"; } +.bi-phone::before { content: "\f4e7"; } +.bi-pie-chart-fill::before { content: "\f4e8"; } +.bi-pie-chart::before { content: "\f4e9"; } +.bi-pin-angle-fill::before { content: "\f4ea"; } +.bi-pin-angle::before { content: "\f4eb"; } +.bi-pin-fill::before { content: "\f4ec"; } +.bi-pin::before { content: "\f4ed"; } +.bi-pip-fill::before { content: "\f4ee"; } +.bi-pip::before { content: "\f4ef"; } +.bi-play-btn-fill::before { content: "\f4f0"; } +.bi-play-btn::before { content: "\f4f1"; } +.bi-play-circle-fill::before { content: "\f4f2"; } +.bi-play-circle::before { content: "\f4f3"; } +.bi-play-fill::before { content: "\f4f4"; } +.bi-play::before { content: "\f4f5"; } +.bi-plug-fill::before { content: "\f4f6"; } +.bi-plug::before { content: "\f4f7"; } +.bi-plus-circle-dotted::before { content: "\f4f8"; } +.bi-plus-circle-fill::before { content: "\f4f9"; } +.bi-plus-circle::before { content: "\f4fa"; } +.bi-plus-square-dotted::before { content: "\f4fb"; } +.bi-plus-square-fill::before { content: "\f4fc"; } +.bi-plus-square::before { content: "\f4fd"; } +.bi-plus::before { content: "\f4fe"; } +.bi-power::before { content: "\f4ff"; } +.bi-printer-fill::before { content: "\f500"; } +.bi-printer::before { content: "\f501"; } +.bi-puzzle-fill::before { content: "\f502"; } +.bi-puzzle::before { content: "\f503"; } +.bi-question-circle-fill::before { content: "\f504"; } +.bi-question-circle::before { content: "\f505"; } +.bi-question-diamond-fill::before { content: "\f506"; } +.bi-question-diamond::before { content: "\f507"; } +.bi-question-octagon-fill::before { content: "\f508"; } +.bi-question-octagon::before { content: "\f509"; } +.bi-question-square-fill::before { content: "\f50a"; } +.bi-question-square::before { content: "\f50b"; } +.bi-question::before { content: "\f50c"; } +.bi-rainbow::before { content: "\f50d"; } +.bi-receipt-cutoff::before { content: "\f50e"; } +.bi-receipt::before { content: "\f50f"; } +.bi-reception-0::before { content: "\f510"; } +.bi-reception-1::before { content: "\f511"; } +.bi-reception-2::before { content: "\f512"; } +.bi-reception-3::before { content: "\f513"; } +.bi-reception-4::before { content: "\f514"; } +.bi-record-btn-fill::before { content: "\f515"; } +.bi-record-btn::before { content: "\f516"; } +.bi-record-circle-fill::before { content: "\f517"; } +.bi-record-circle::before { content: "\f518"; } +.bi-record-fill::before { content: "\f519"; } +.bi-record::before { content: "\f51a"; } +.bi-record2-fill::before { content: "\f51b"; } +.bi-record2::before { content: "\f51c"; } +.bi-reply-all-fill::before { content: "\f51d"; } +.bi-reply-all::before { content: "\f51e"; } +.bi-reply-fill::before { content: "\f51f"; } +.bi-reply::before { content: "\f520"; } +.bi-rss-fill::before { content: "\f521"; } +.bi-rss::before { content: "\f522"; } +.bi-rulers::before { content: "\f523"; } +.bi-save-fill::before { content: "\f524"; } +.bi-save::before { content: "\f525"; } +.bi-save2-fill::before { content: "\f526"; } +.bi-save2::before { content: "\f527"; } +.bi-scissors::before { content: "\f528"; } +.bi-screwdriver::before { content: "\f529"; } +.bi-search::before { content: "\f52a"; } +.bi-segmented-nav::before { content: "\f52b"; } +.bi-server::before { content: "\f52c"; } +.bi-share-fill::before { content: "\f52d"; } +.bi-share::before { content: "\f52e"; } +.bi-shield-check::before { content: "\f52f"; } +.bi-shield-exclamation::before { content: "\f530"; } +.bi-shield-fill-check::before { content: "\f531"; } +.bi-shield-fill-exclamation::before { content: "\f532"; } +.bi-shield-fill-minus::before { content: "\f533"; } +.bi-shield-fill-plus::before { content: "\f534"; } +.bi-shield-fill-x::before { content: "\f535"; } +.bi-shield-fill::before { content: "\f536"; } +.bi-shield-lock-fill::before { content: "\f537"; } +.bi-shield-lock::before { content: "\f538"; } +.bi-shield-minus::before { content: "\f539"; } +.bi-shield-plus::before { content: "\f53a"; } +.bi-shield-shaded::before { content: "\f53b"; } +.bi-shield-slash-fill::before { content: "\f53c"; } +.bi-shield-slash::before { content: "\f53d"; } +.bi-shield-x::before { content: "\f53e"; } +.bi-shield::before { content: "\f53f"; } +.bi-shift-fill::before { content: "\f540"; } +.bi-shift::before { content: "\f541"; } +.bi-shop-window::before { content: "\f542"; } +.bi-shop::before { content: "\f543"; } +.bi-shuffle::before { content: "\f544"; } +.bi-signpost-2-fill::before { content: "\f545"; } +.bi-signpost-2::before { content: "\f546"; } +.bi-signpost-fill::before { content: "\f547"; } +.bi-signpost-split-fill::before { content: "\f548"; } +.bi-signpost-split::before { content: "\f549"; } +.bi-signpost::before { content: "\f54a"; } +.bi-sim-fill::before { content: "\f54b"; } +.bi-sim::before { content: "\f54c"; } +.bi-skip-backward-btn-fill::before { content: "\f54d"; } +.bi-skip-backward-btn::before { content: "\f54e"; } +.bi-skip-backward-circle-fill::before { content: "\f54f"; } +.bi-skip-backward-circle::before { content: "\f550"; } +.bi-skip-backward-fill::before { content: "\f551"; } +.bi-skip-backward::before { content: "\f552"; } +.bi-skip-end-btn-fill::before { content: "\f553"; } +.bi-skip-end-btn::before { content: "\f554"; } +.bi-skip-end-circle-fill::before { content: "\f555"; } +.bi-skip-end-circle::before { content: "\f556"; } +.bi-skip-end-fill::before { content: "\f557"; } +.bi-skip-end::before { content: "\f558"; } +.bi-skip-forward-btn-fill::before { content: "\f559"; } +.bi-skip-forward-btn::before { content: "\f55a"; } +.bi-skip-forward-circle-fill::before { content: "\f55b"; } +.bi-skip-forward-circle::before { content: "\f55c"; } +.bi-skip-forward-fill::before { content: "\f55d"; } +.bi-skip-forward::before { content: "\f55e"; } +.bi-skip-start-btn-fill::before { content: "\f55f"; } +.bi-skip-start-btn::before { content: "\f560"; } +.bi-skip-start-circle-fill::before { content: "\f561"; } +.bi-skip-start-circle::before { content: "\f562"; } +.bi-skip-start-fill::before { content: "\f563"; } +.bi-skip-start::before { content: "\f564"; } +.bi-slack::before { content: "\f565"; } +.bi-slash-circle-fill::before { content: "\f566"; } +.bi-slash-circle::before { content: "\f567"; } +.bi-slash-square-fill::before { content: "\f568"; } +.bi-slash-square::before { content: "\f569"; } +.bi-slash::before { content: "\f56a"; } +.bi-sliders::before { content: "\f56b"; } +.bi-smartwatch::before { content: "\f56c"; } +.bi-snow::before { content: "\f56d"; } +.bi-snow2::before { content: "\f56e"; } +.bi-snow3::before { content: "\f56f"; } +.bi-sort-alpha-down-alt::before { content: "\f570"; } +.bi-sort-alpha-down::before { content: "\f571"; } +.bi-sort-alpha-up-alt::before { content: "\f572"; } +.bi-sort-alpha-up::before { content: "\f573"; } +.bi-sort-down-alt::before { content: "\f574"; } +.bi-sort-down::before { content: "\f575"; } +.bi-sort-numeric-down-alt::before { content: "\f576"; } +.bi-sort-numeric-down::before { content: "\f577"; } +.bi-sort-numeric-up-alt::before { content: "\f578"; } +.bi-sort-numeric-up::before { content: "\f579"; } +.bi-sort-up-alt::before { content: "\f57a"; } +.bi-sort-up::before { content: "\f57b"; } +.bi-soundwave::before { content: "\f57c"; } +.bi-speaker-fill::before { content: "\f57d"; } +.bi-speaker::before { content: "\f57e"; } +.bi-speedometer::before { content: "\f57f"; } +.bi-speedometer2::before { content: "\f580"; } +.bi-spellcheck::before { content: "\f581"; } +.bi-square-fill::before { content: "\f582"; } +.bi-square-half::before { content: "\f583"; } +.bi-square::before { content: "\f584"; } +.bi-stack::before { content: "\f585"; } +.bi-star-fill::before { content: "\f586"; } +.bi-star-half::before { content: "\f587"; } +.bi-star::before { content: "\f588"; } +.bi-stars::before { content: "\f589"; } +.bi-stickies-fill::before { content: "\f58a"; } +.bi-stickies::before { content: "\f58b"; } +.bi-sticky-fill::before { content: "\f58c"; } +.bi-sticky::before { content: "\f58d"; } +.bi-stop-btn-fill::before { content: "\f58e"; } +.bi-stop-btn::before { content: "\f58f"; } +.bi-stop-circle-fill::before { content: "\f590"; } +.bi-stop-circle::before { content: "\f591"; } +.bi-stop-fill::before { content: "\f592"; } +.bi-stop::before { content: "\f593"; } +.bi-stoplights-fill::before { content: "\f594"; } +.bi-stoplights::before { content: "\f595"; } +.bi-stopwatch-fill::before { content: "\f596"; } +.bi-stopwatch::before { content: "\f597"; } +.bi-subtract::before { content: "\f598"; } +.bi-suit-club-fill::before { content: "\f599"; } +.bi-suit-club::before { content: "\f59a"; } +.bi-suit-diamond-fill::before { content: "\f59b"; } +.bi-suit-diamond::before { content: "\f59c"; } +.bi-suit-heart-fill::before { content: "\f59d"; } +.bi-suit-heart::before { content: "\f59e"; } +.bi-suit-spade-fill::before { content: "\f59f"; } +.bi-suit-spade::before { content: "\f5a0"; } +.bi-sun-fill::before { content: "\f5a1"; } +.bi-sun::before { content: "\f5a2"; } +.bi-sunglasses::before { content: "\f5a3"; } +.bi-sunrise-fill::before { content: "\f5a4"; } +.bi-sunrise::before { content: "\f5a5"; } +.bi-sunset-fill::before { content: "\f5a6"; } +.bi-sunset::before { content: "\f5a7"; } +.bi-symmetry-horizontal::before { content: "\f5a8"; } +.bi-symmetry-vertical::before { content: "\f5a9"; } +.bi-table::before { content: "\f5aa"; } +.bi-tablet-fill::before { content: "\f5ab"; } +.bi-tablet-landscape-fill::before { content: "\f5ac"; } +.bi-tablet-landscape::before { content: "\f5ad"; } +.bi-tablet::before { content: "\f5ae"; } +.bi-tag-fill::before { content: "\f5af"; } +.bi-tag::before { content: "\f5b0"; } +.bi-tags-fill::before { content: "\f5b1"; } +.bi-tags::before { content: "\f5b2"; } +.bi-telegram::before { content: "\f5b3"; } +.bi-telephone-fill::before { content: "\f5b4"; } +.bi-telephone-forward-fill::before { content: "\f5b5"; } +.bi-telephone-forward::before { content: "\f5b6"; } +.bi-telephone-inbound-fill::before { content: "\f5b7"; } +.bi-telephone-inbound::before { content: "\f5b8"; } +.bi-telephone-minus-fill::before { content: "\f5b9"; } +.bi-telephone-minus::before { content: "\f5ba"; } +.bi-telephone-outbound-fill::before { content: "\f5bb"; } +.bi-telephone-outbound::before { content: "\f5bc"; } +.bi-telephone-plus-fill::before { content: "\f5bd"; } +.bi-telephone-plus::before { content: "\f5be"; } +.bi-telephone-x-fill::before { content: "\f5bf"; } +.bi-telephone-x::before { content: "\f5c0"; } +.bi-telephone::before { content: "\f5c1"; } +.bi-terminal-fill::before { content: "\f5c2"; } +.bi-terminal::before { content: "\f5c3"; } +.bi-text-center::before { content: "\f5c4"; } +.bi-text-indent-left::before { content: "\f5c5"; } +.bi-text-indent-right::before { content: "\f5c6"; } +.bi-text-left::before { content: "\f5c7"; } +.bi-text-paragraph::before { content: "\f5c8"; } +.bi-text-right::before { content: "\f5c9"; } +.bi-textarea-resize::before { content: "\f5ca"; } +.bi-textarea-t::before { content: "\f5cb"; } +.bi-textarea::before { content: "\f5cc"; } +.bi-thermometer-half::before { content: "\f5cd"; } +.bi-thermometer-high::before { content: "\f5ce"; } +.bi-thermometer-low::before { content: "\f5cf"; } +.bi-thermometer-snow::before { content: "\f5d0"; } +.bi-thermometer-sun::before { content: "\f5d1"; } +.bi-thermometer::before { content: "\f5d2"; } +.bi-three-dots-vertical::before { content: "\f5d3"; } +.bi-three-dots::before { content: "\f5d4"; } +.bi-toggle-off::before { content: "\f5d5"; } +.bi-toggle-on::before { content: "\f5d6"; } +.bi-toggle2-off::before { content: "\f5d7"; } +.bi-toggle2-on::before { content: "\f5d8"; } +.bi-toggles::before { content: "\f5d9"; } +.bi-toggles2::before { content: "\f5da"; } +.bi-tools::before { content: "\f5db"; } +.bi-tornado::before { content: "\f5dc"; } +.bi-trash-fill::before { content: "\f5dd"; } +.bi-trash::before { content: "\f5de"; } +.bi-trash2-fill::before { content: "\f5df"; } +.bi-trash2::before { content: "\f5e0"; } +.bi-tree-fill::before { content: "\f5e1"; } +.bi-tree::before { content: "\f5e2"; } +.bi-triangle-fill::before { content: "\f5e3"; } +.bi-triangle-half::before { content: "\f5e4"; } +.bi-triangle::before { content: "\f5e5"; } +.bi-trophy-fill::before { content: "\f5e6"; } +.bi-trophy::before { content: "\f5e7"; } +.bi-tropical-storm::before { content: "\f5e8"; } +.bi-truck-flatbed::before { content: "\f5e9"; } +.bi-truck::before { content: "\f5ea"; } +.bi-tsunami::before { content: "\f5eb"; } +.bi-tv-fill::before { content: "\f5ec"; } +.bi-tv::before { content: "\f5ed"; } +.bi-twitch::before { content: "\f5ee"; } +.bi-twitter::before { content: "\f5ef"; } +.bi-type-bold::before { content: "\f5f0"; } +.bi-type-h1::before { content: "\f5f1"; } +.bi-type-h2::before { content: "\f5f2"; } +.bi-type-h3::before { content: "\f5f3"; } +.bi-type-italic::before { content: "\f5f4"; } +.bi-type-strikethrough::before { content: "\f5f5"; } +.bi-type-underline::before { content: "\f5f6"; } +.bi-type::before { content: "\f5f7"; } +.bi-ui-checks-grid::before { content: "\f5f8"; } +.bi-ui-checks::before { content: "\f5f9"; } +.bi-ui-radios-grid::before { content: "\f5fa"; } +.bi-ui-radios::before { content: "\f5fb"; } +.bi-umbrella-fill::before { content: "\f5fc"; } +.bi-umbrella::before { content: "\f5fd"; } +.bi-union::before { content: "\f5fe"; } +.bi-unlock-fill::before { content: "\f5ff"; } +.bi-unlock::before { content: "\f600"; } +.bi-upc-scan::before { content: "\f601"; } +.bi-upc::before { content: "\f602"; } +.bi-upload::before { content: "\f603"; } +.bi-vector-pen::before { content: "\f604"; } +.bi-view-list::before { content: "\f605"; } +.bi-view-stacked::before { content: "\f606"; } +.bi-vinyl-fill::before { content: "\f607"; } +.bi-vinyl::before { content: "\f608"; } +.bi-voicemail::before { content: "\f609"; } +.bi-volume-down-fill::before { content: "\f60a"; } +.bi-volume-down::before { content: "\f60b"; } +.bi-volume-mute-fill::before { content: "\f60c"; } +.bi-volume-mute::before { content: "\f60d"; } +.bi-volume-off-fill::before { content: "\f60e"; } +.bi-volume-off::before { content: "\f60f"; } +.bi-volume-up-fill::before { content: "\f610"; } +.bi-volume-up::before { content: "\f611"; } +.bi-vr::before { content: "\f612"; } +.bi-wallet-fill::before { content: "\f613"; } +.bi-wallet::before { content: "\f614"; } +.bi-wallet2::before { content: "\f615"; } +.bi-watch::before { content: "\f616"; } +.bi-water::before { content: "\f617"; } +.bi-whatsapp::before { content: "\f618"; } +.bi-wifi-1::before { content: "\f619"; } +.bi-wifi-2::before { content: "\f61a"; } +.bi-wifi-off::before { content: "\f61b"; } +.bi-wifi::before { content: "\f61c"; } +.bi-wind::before { content: "\f61d"; } +.bi-window-dock::before { content: "\f61e"; } +.bi-window-sidebar::before { content: "\f61f"; } +.bi-window::before { content: "\f620"; } +.bi-wrench::before { content: "\f621"; } +.bi-x-circle-fill::before { content: "\f622"; } +.bi-x-circle::before { content: "\f623"; } +.bi-x-diamond-fill::before { content: "\f624"; } +.bi-x-diamond::before { content: "\f625"; } +.bi-x-octagon-fill::before { content: "\f626"; } +.bi-x-octagon::before { content: "\f627"; } +.bi-x-square-fill::before { content: "\f628"; } +.bi-x-square::before { content: "\f629"; } +.bi-x::before { content: "\f62a"; } +.bi-youtube::before { content: "\f62b"; } +.bi-zoom-in::before { content: "\f62c"; } +.bi-zoom-out::before { content: "\f62d"; } +.bi-bank::before { content: "\f62e"; } +.bi-bank2::before { content: "\f62f"; } +.bi-bell-slash-fill::before { content: "\f630"; } +.bi-bell-slash::before { content: "\f631"; } +.bi-cash-coin::before { content: "\f632"; } +.bi-check-lg::before { content: "\f633"; } +.bi-coin::before { content: "\f634"; } +.bi-currency-bitcoin::before { content: "\f635"; } +.bi-currency-dollar::before { content: "\f636"; } +.bi-currency-euro::before { content: "\f637"; } +.bi-currency-exchange::before { content: "\f638"; } +.bi-currency-pound::before { content: "\f639"; } +.bi-currency-yen::before { content: "\f63a"; } +.bi-dash-lg::before { content: "\f63b"; } +.bi-exclamation-lg::before { content: "\f63c"; } +.bi-file-earmark-pdf-fill::before { content: "\f63d"; } +.bi-file-earmark-pdf::before { content: "\f63e"; } +.bi-file-pdf-fill::before { content: "\f63f"; } +.bi-file-pdf::before { content: "\f640"; } +.bi-gender-ambiguous::before { content: "\f641"; } +.bi-gender-female::before { content: "\f642"; } +.bi-gender-male::before { content: "\f643"; } +.bi-gender-trans::before { content: "\f644"; } +.bi-headset-vr::before { content: "\f645"; } +.bi-info-lg::before { content: "\f646"; } +.bi-mastodon::before { content: "\f647"; } +.bi-messenger::before { content: "\f648"; } +.bi-piggy-bank-fill::before { content: "\f649"; } +.bi-piggy-bank::before { content: "\f64a"; } +.bi-pin-map-fill::before { content: "\f64b"; } +.bi-pin-map::before { content: "\f64c"; } +.bi-plus-lg::before { content: "\f64d"; } +.bi-question-lg::before { content: "\f64e"; } +.bi-recycle::before { content: "\f64f"; } +.bi-reddit::before { content: "\f650"; } +.bi-safe-fill::before { content: "\f651"; } +.bi-safe2-fill::before { content: "\f652"; } +.bi-safe2::before { content: "\f653"; } +.bi-sd-card-fill::before { content: "\f654"; } +.bi-sd-card::before { content: "\f655"; } +.bi-skype::before { content: "\f656"; } +.bi-slash-lg::before { content: "\f657"; } +.bi-translate::before { content: "\f658"; } +.bi-x-lg::before { content: "\f659"; } +.bi-safe::before { content: "\f65a"; } +.bi-apple::before { content: "\f65b"; } +.bi-microsoft::before { content: "\f65d"; } +.bi-windows::before { content: "\f65e"; } +.bi-behance::before { content: "\f65c"; } +.bi-dribbble::before { content: "\f65f"; } +.bi-line::before { content: "\f660"; } +.bi-medium::before { content: "\f661"; } +.bi-paypal::before { content: "\f662"; } +.bi-pinterest::before { content: "\f663"; } +.bi-signal::before { content: "\f664"; } +.bi-snapchat::before { content: "\f665"; } +.bi-spotify::before { content: "\f666"; } +.bi-stack-overflow::before { content: "\f667"; } +.bi-strava::before { content: "\f668"; } +.bi-wordpress::before { content: "\f669"; } +.bi-vimeo::before { content: "\f66a"; } +.bi-activity::before { content: "\f66b"; } +.bi-easel2-fill::before { content: "\f66c"; } +.bi-easel2::before { content: "\f66d"; } +.bi-easel3-fill::before { content: "\f66e"; } +.bi-easel3::before { content: "\f66f"; } +.bi-fan::before { content: "\f670"; } +.bi-fingerprint::before { content: "\f671"; } +.bi-graph-down-arrow::before { content: "\f672"; } +.bi-graph-up-arrow::before { content: "\f673"; } +.bi-hypnotize::before { content: "\f674"; } +.bi-magic::before { content: "\f675"; } +.bi-person-rolodex::before { content: "\f676"; } +.bi-person-video::before { content: "\f677"; } +.bi-person-video2::before { content: "\f678"; } +.bi-person-video3::before { content: "\f679"; } +.bi-person-workspace::before { content: "\f67a"; } +.bi-radioactive::before { content: "\f67b"; } +.bi-webcam-fill::before { content: "\f67c"; } +.bi-webcam::before { content: "\f67d"; } +.bi-yin-yang::before { content: "\f67e"; } +.bi-bandaid-fill::before { content: "\f680"; } +.bi-bandaid::before { content: "\f681"; } +.bi-bluetooth::before { content: "\f682"; } +.bi-body-text::before { content: "\f683"; } +.bi-boombox::before { content: "\f684"; } +.bi-boxes::before { content: "\f685"; } +.bi-dpad-fill::before { content: "\f686"; } +.bi-dpad::before { content: "\f687"; } +.bi-ear-fill::before { content: "\f688"; } +.bi-ear::before { content: "\f689"; } +.bi-envelope-check-fill::before { content: "\f68b"; } +.bi-envelope-check::before { content: "\f68c"; } +.bi-envelope-dash-fill::before { content: "\f68e"; } +.bi-envelope-dash::before { content: "\f68f"; } +.bi-envelope-exclamation-fill::before { content: "\f691"; } +.bi-envelope-exclamation::before { content: "\f692"; } +.bi-envelope-plus-fill::before { content: "\f693"; } +.bi-envelope-plus::before { content: "\f694"; } +.bi-envelope-slash-fill::before { content: "\f696"; } +.bi-envelope-slash::before { content: "\f697"; } +.bi-envelope-x-fill::before { content: "\f699"; } +.bi-envelope-x::before { content: "\f69a"; } +.bi-explicit-fill::before { content: "\f69b"; } +.bi-explicit::before { content: "\f69c"; } +.bi-git::before { content: "\f69d"; } +.bi-infinity::before { content: "\f69e"; } +.bi-list-columns-reverse::before { content: "\f69f"; } +.bi-list-columns::before { content: "\f6a0"; } +.bi-meta::before { content: "\f6a1"; } +.bi-nintendo-switch::before { content: "\f6a4"; } +.bi-pc-display-horizontal::before { content: "\f6a5"; } +.bi-pc-display::before { content: "\f6a6"; } +.bi-pc-horizontal::before { content: "\f6a7"; } +.bi-pc::before { content: "\f6a8"; } +.bi-playstation::before { content: "\f6a9"; } +.bi-plus-slash-minus::before { content: "\f6aa"; } +.bi-projector-fill::before { content: "\f6ab"; } +.bi-projector::before { content: "\f6ac"; } +.bi-qr-code-scan::before { content: "\f6ad"; } +.bi-qr-code::before { content: "\f6ae"; } +.bi-quora::before { content: "\f6af"; } +.bi-quote::before { content: "\f6b0"; } +.bi-robot::before { content: "\f6b1"; } +.bi-send-check-fill::before { content: "\f6b2"; } +.bi-send-check::before { content: "\f6b3"; } +.bi-send-dash-fill::before { content: "\f6b4"; } +.bi-send-dash::before { content: "\f6b5"; } +.bi-send-exclamation-fill::before { content: "\f6b7"; } +.bi-send-exclamation::before { content: "\f6b8"; } +.bi-send-fill::before { content: "\f6b9"; } +.bi-send-plus-fill::before { content: "\f6ba"; } +.bi-send-plus::before { content: "\f6bb"; } +.bi-send-slash-fill::before { content: "\f6bc"; } +.bi-send-slash::before { content: "\f6bd"; } +.bi-send-x-fill::before { content: "\f6be"; } +.bi-send-x::before { content: "\f6bf"; } +.bi-send::before { content: "\f6c0"; } +.bi-steam::before { content: "\f6c1"; } +.bi-terminal-dash::before { content: "\f6c3"; } +.bi-terminal-plus::before { content: "\f6c4"; } +.bi-terminal-split::before { content: "\f6c5"; } +.bi-ticket-detailed-fill::before { content: "\f6c6"; } +.bi-ticket-detailed::before { content: "\f6c7"; } +.bi-ticket-fill::before { content: "\f6c8"; } +.bi-ticket-perforated-fill::before { content: "\f6c9"; } +.bi-ticket-perforated::before { content: "\f6ca"; } +.bi-ticket::before { content: "\f6cb"; } +.bi-tiktok::before { content: "\f6cc"; } +.bi-window-dash::before { content: "\f6cd"; } +.bi-window-desktop::before { content: "\f6ce"; } +.bi-window-fullscreen::before { content: "\f6cf"; } +.bi-window-plus::before { content: "\f6d0"; } +.bi-window-split::before { content: "\f6d1"; } +.bi-window-stack::before { content: "\f6d2"; } +.bi-window-x::before { content: "\f6d3"; } +.bi-xbox::before { content: "\f6d4"; } +.bi-ethernet::before { content: "\f6d5"; } +.bi-hdmi-fill::before { content: "\f6d6"; } +.bi-hdmi::before { content: "\f6d7"; } +.bi-usb-c-fill::before { content: "\f6d8"; } +.bi-usb-c::before { content: "\f6d9"; } +.bi-usb-fill::before { content: "\f6da"; } +.bi-usb-plug-fill::before { content: "\f6db"; } +.bi-usb-plug::before { content: "\f6dc"; } +.bi-usb-symbol::before { content: "\f6dd"; } +.bi-usb::before { content: "\f6de"; } +.bi-boombox-fill::before { content: "\f6df"; } +.bi-displayport::before { content: "\f6e1"; } +.bi-gpu-card::before { content: "\f6e2"; } +.bi-memory::before { content: "\f6e3"; } +.bi-modem-fill::before { content: "\f6e4"; } +.bi-modem::before { content: "\f6e5"; } +.bi-motherboard-fill::before { content: "\f6e6"; } +.bi-motherboard::before { content: "\f6e7"; } +.bi-optical-audio-fill::before { content: "\f6e8"; } +.bi-optical-audio::before { content: "\f6e9"; } +.bi-pci-card::before { content: "\f6ea"; } +.bi-router-fill::before { content: "\f6eb"; } +.bi-router::before { content: "\f6ec"; } +.bi-thunderbolt-fill::before { content: "\f6ef"; } +.bi-thunderbolt::before { content: "\f6f0"; } +.bi-usb-drive-fill::before { content: "\f6f1"; } +.bi-usb-drive::before { content: "\f6f2"; } +.bi-usb-micro-fill::before { content: "\f6f3"; } +.bi-usb-micro::before { content: "\f6f4"; } +.bi-usb-mini-fill::before { content: "\f6f5"; } +.bi-usb-mini::before { content: "\f6f6"; } +.bi-cloud-haze2::before { content: "\f6f7"; } +.bi-device-hdd-fill::before { content: "\f6f8"; } +.bi-device-hdd::before { content: "\f6f9"; } +.bi-device-ssd-fill::before { content: "\f6fa"; } +.bi-device-ssd::before { content: "\f6fb"; } +.bi-displayport-fill::before { content: "\f6fc"; } +.bi-mortarboard-fill::before { content: "\f6fd"; } +.bi-mortarboard::before { content: "\f6fe"; } +.bi-terminal-x::before { content: "\f6ff"; } +.bi-arrow-through-heart-fill::before { content: "\f700"; } +.bi-arrow-through-heart::before { content: "\f701"; } +.bi-badge-sd-fill::before { content: "\f702"; } +.bi-badge-sd::before { content: "\f703"; } +.bi-bag-heart-fill::before { content: "\f704"; } +.bi-bag-heart::before { content: "\f705"; } +.bi-balloon-fill::before { content: "\f706"; } +.bi-balloon-heart-fill::before { content: "\f707"; } +.bi-balloon-heart::before { content: "\f708"; } +.bi-balloon::before { content: "\f709"; } +.bi-box2-fill::before { content: "\f70a"; } +.bi-box2-heart-fill::before { content: "\f70b"; } +.bi-box2-heart::before { content: "\f70c"; } +.bi-box2::before { content: "\f70d"; } +.bi-braces-asterisk::before { content: "\f70e"; } +.bi-calendar-heart-fill::before { content: "\f70f"; } +.bi-calendar-heart::before { content: "\f710"; } +.bi-calendar2-heart-fill::before { content: "\f711"; } +.bi-calendar2-heart::before { content: "\f712"; } +.bi-chat-heart-fill::before { content: "\f713"; } +.bi-chat-heart::before { content: "\f714"; } +.bi-chat-left-heart-fill::before { content: "\f715"; } +.bi-chat-left-heart::before { content: "\f716"; } +.bi-chat-right-heart-fill::before { content: "\f717"; } +.bi-chat-right-heart::before { content: "\f718"; } +.bi-chat-square-heart-fill::before { content: "\f719"; } +.bi-chat-square-heart::before { content: "\f71a"; } +.bi-clipboard-check-fill::before { content: "\f71b"; } +.bi-clipboard-data-fill::before { content: "\f71c"; } +.bi-clipboard-fill::before { content: "\f71d"; } +.bi-clipboard-heart-fill::before { content: "\f71e"; } +.bi-clipboard-heart::before { content: "\f71f"; } +.bi-clipboard-minus-fill::before { content: "\f720"; } +.bi-clipboard-plus-fill::before { content: "\f721"; } +.bi-clipboard-pulse::before { content: "\f722"; } +.bi-clipboard-x-fill::before { content: "\f723"; } +.bi-clipboard2-check-fill::before { content: "\f724"; } +.bi-clipboard2-check::before { content: "\f725"; } +.bi-clipboard2-data-fill::before { content: "\f726"; } +.bi-clipboard2-data::before { content: "\f727"; } +.bi-clipboard2-fill::before { content: "\f728"; } +.bi-clipboard2-heart-fill::before { content: "\f729"; } +.bi-clipboard2-heart::before { content: "\f72a"; } +.bi-clipboard2-minus-fill::before { content: "\f72b"; } +.bi-clipboard2-minus::before { content: "\f72c"; } +.bi-clipboard2-plus-fill::before { content: "\f72d"; } +.bi-clipboard2-plus::before { content: "\f72e"; } +.bi-clipboard2-pulse-fill::before { content: "\f72f"; } +.bi-clipboard2-pulse::before { content: "\f730"; } +.bi-clipboard2-x-fill::before { content: "\f731"; } +.bi-clipboard2-x::before { content: "\f732"; } +.bi-clipboard2::before { content: "\f733"; } +.bi-emoji-kiss-fill::before { content: "\f734"; } +.bi-emoji-kiss::before { content: "\f735"; } +.bi-envelope-heart-fill::before { content: "\f736"; } +.bi-envelope-heart::before { content: "\f737"; } +.bi-envelope-open-heart-fill::before { content: "\f738"; } +.bi-envelope-open-heart::before { content: "\f739"; } +.bi-envelope-paper-fill::before { content: "\f73a"; } +.bi-envelope-paper-heart-fill::before { content: "\f73b"; } +.bi-envelope-paper-heart::before { content: "\f73c"; } +.bi-envelope-paper::before { content: "\f73d"; } +.bi-filetype-aac::before { content: "\f73e"; } +.bi-filetype-ai::before { content: "\f73f"; } +.bi-filetype-bmp::before { content: "\f740"; } +.bi-filetype-cs::before { content: "\f741"; } +.bi-filetype-css::before { content: "\f742"; } +.bi-filetype-csv::before { content: "\f743"; } +.bi-filetype-doc::before { content: "\f744"; } +.bi-filetype-docx::before { content: "\f745"; } +.bi-filetype-exe::before { content: "\f746"; } +.bi-filetype-gif::before { content: "\f747"; } +.bi-filetype-heic::before { content: "\f748"; } +.bi-filetype-html::before { content: "\f749"; } +.bi-filetype-java::before { content: "\f74a"; } +.bi-filetype-jpg::before { content: "\f74b"; } +.bi-filetype-js::before { content: "\f74c"; } +.bi-filetype-jsx::before { content: "\f74d"; } +.bi-filetype-key::before { content: "\f74e"; } +.bi-filetype-m4p::before { content: "\f74f"; } +.bi-filetype-md::before { content: "\f750"; } +.bi-filetype-mdx::before { content: "\f751"; } +.bi-filetype-mov::before { content: "\f752"; } +.bi-filetype-mp3::before { content: "\f753"; } +.bi-filetype-mp4::before { content: "\f754"; } +.bi-filetype-otf::before { content: "\f755"; } +.bi-filetype-pdf::before { content: "\f756"; } +.bi-filetype-php::before { content: "\f757"; } +.bi-filetype-png::before { content: "\f758"; } +.bi-filetype-ppt::before { content: "\f75a"; } +.bi-filetype-psd::before { content: "\f75b"; } +.bi-filetype-py::before { content: "\f75c"; } +.bi-filetype-raw::before { content: "\f75d"; } +.bi-filetype-rb::before { content: "\f75e"; } +.bi-filetype-sass::before { content: "\f75f"; } +.bi-filetype-scss::before { content: "\f760"; } +.bi-filetype-sh::before { content: "\f761"; } +.bi-filetype-svg::before { content: "\f762"; } +.bi-filetype-tiff::before { content: "\f763"; } +.bi-filetype-tsx::before { content: "\f764"; } +.bi-filetype-ttf::before { content: "\f765"; } +.bi-filetype-txt::before { content: "\f766"; } +.bi-filetype-wav::before { content: "\f767"; } +.bi-filetype-woff::before { content: "\f768"; } +.bi-filetype-xls::before { content: "\f76a"; } +.bi-filetype-xml::before { content: "\f76b"; } +.bi-filetype-yml::before { content: "\f76c"; } +.bi-heart-arrow::before { content: "\f76d"; } +.bi-heart-pulse-fill::before { content: "\f76e"; } +.bi-heart-pulse::before { content: "\f76f"; } +.bi-heartbreak-fill::before { content: "\f770"; } +.bi-heartbreak::before { content: "\f771"; } +.bi-hearts::before { content: "\f772"; } +.bi-hospital-fill::before { content: "\f773"; } +.bi-hospital::before { content: "\f774"; } +.bi-house-heart-fill::before { content: "\f775"; } +.bi-house-heart::before { content: "\f776"; } +.bi-incognito::before { content: "\f777"; } +.bi-magnet-fill::before { content: "\f778"; } +.bi-magnet::before { content: "\f779"; } +.bi-person-heart::before { content: "\f77a"; } +.bi-person-hearts::before { content: "\f77b"; } +.bi-phone-flip::before { content: "\f77c"; } +.bi-plugin::before { content: "\f77d"; } +.bi-postage-fill::before { content: "\f77e"; } +.bi-postage-heart-fill::before { content: "\f77f"; } +.bi-postage-heart::before { content: "\f780"; } +.bi-postage::before { content: "\f781"; } +.bi-postcard-fill::before { content: "\f782"; } +.bi-postcard-heart-fill::before { content: "\f783"; } +.bi-postcard-heart::before { content: "\f784"; } +.bi-postcard::before { content: "\f785"; } +.bi-search-heart-fill::before { content: "\f786"; } +.bi-search-heart::before { content: "\f787"; } +.bi-sliders2-vertical::before { content: "\f788"; } +.bi-sliders2::before { content: "\f789"; } +.bi-trash3-fill::before { content: "\f78a"; } +.bi-trash3::before { content: "\f78b"; } +.bi-valentine::before { content: "\f78c"; } +.bi-valentine2::before { content: "\f78d"; } +.bi-wrench-adjustable-circle-fill::before { content: "\f78e"; } +.bi-wrench-adjustable-circle::before { content: "\f78f"; } +.bi-wrench-adjustable::before { content: "\f790"; } +.bi-filetype-json::before { content: "\f791"; } +.bi-filetype-pptx::before { content: "\f792"; } +.bi-filetype-xlsx::before { content: "\f793"; } +.bi-1-circle-fill::before { content: "\f796"; } +.bi-1-circle::before { content: "\f797"; } +.bi-1-square-fill::before { content: "\f798"; } +.bi-1-square::before { content: "\f799"; } +.bi-2-circle-fill::before { content: "\f79c"; } +.bi-2-circle::before { content: "\f79d"; } +.bi-2-square-fill::before { content: "\f79e"; } +.bi-2-square::before { content: "\f79f"; } +.bi-3-circle-fill::before { content: "\f7a2"; } +.bi-3-circle::before { content: "\f7a3"; } +.bi-3-square-fill::before { content: "\f7a4"; } +.bi-3-square::before { content: "\f7a5"; } +.bi-4-circle-fill::before { content: "\f7a8"; } +.bi-4-circle::before { content: "\f7a9"; } +.bi-4-square-fill::before { content: "\f7aa"; } +.bi-4-square::before { content: "\f7ab"; } +.bi-5-circle-fill::before { content: "\f7ae"; } +.bi-5-circle::before { content: "\f7af"; } +.bi-5-square-fill::before { content: "\f7b0"; } +.bi-5-square::before { content: "\f7b1"; } +.bi-6-circle-fill::before { content: "\f7b4"; } +.bi-6-circle::before { content: "\f7b5"; } +.bi-6-square-fill::before { content: "\f7b6"; } +.bi-6-square::before { content: "\f7b7"; } +.bi-7-circle-fill::before { content: "\f7ba"; } +.bi-7-circle::before { content: "\f7bb"; } +.bi-7-square-fill::before { content: "\f7bc"; } +.bi-7-square::before { content: "\f7bd"; } +.bi-8-circle-fill::before { content: "\f7c0"; } +.bi-8-circle::before { content: "\f7c1"; } +.bi-8-square-fill::before { content: "\f7c2"; } +.bi-8-square::before { content: "\f7c3"; } +.bi-9-circle-fill::before { content: "\f7c6"; } +.bi-9-circle::before { content: "\f7c7"; } +.bi-9-square-fill::before { content: "\f7c8"; } +.bi-9-square::before { content: "\f7c9"; } +.bi-airplane-engines-fill::before { content: "\f7ca"; } +.bi-airplane-engines::before { content: "\f7cb"; } +.bi-airplane-fill::before { content: "\f7cc"; } +.bi-airplane::before { content: "\f7cd"; } +.bi-alexa::before { content: "\f7ce"; } +.bi-alipay::before { content: "\f7cf"; } +.bi-android::before { content: "\f7d0"; } +.bi-android2::before { content: "\f7d1"; } +.bi-box-fill::before { content: "\f7d2"; } +.bi-box-seam-fill::before { content: "\f7d3"; } +.bi-browser-chrome::before { content: "\f7d4"; } +.bi-browser-edge::before { content: "\f7d5"; } +.bi-browser-firefox::before { content: "\f7d6"; } +.bi-browser-safari::before { content: "\f7d7"; } +.bi-c-circle-fill::before { content: "\f7da"; } +.bi-c-circle::before { content: "\f7db"; } +.bi-c-square-fill::before { content: "\f7dc"; } +.bi-c-square::before { content: "\f7dd"; } +.bi-capsule-pill::before { content: "\f7de"; } +.bi-capsule::before { content: "\f7df"; } +.bi-car-front-fill::before { content: "\f7e0"; } +.bi-car-front::before { content: "\f7e1"; } +.bi-cassette-fill::before { content: "\f7e2"; } +.bi-cassette::before { content: "\f7e3"; } +.bi-cc-circle-fill::before { content: "\f7e6"; } +.bi-cc-circle::before { content: "\f7e7"; } +.bi-cc-square-fill::before { content: "\f7e8"; } +.bi-cc-square::before { content: "\f7e9"; } +.bi-cup-hot-fill::before { content: "\f7ea"; } +.bi-cup-hot::before { content: "\f7eb"; } +.bi-currency-rupee::before { content: "\f7ec"; } +.bi-dropbox::before { content: "\f7ed"; } +.bi-escape::before { content: "\f7ee"; } +.bi-fast-forward-btn-fill::before { content: "\f7ef"; } +.bi-fast-forward-btn::before { content: "\f7f0"; } +.bi-fast-forward-circle-fill::before { content: "\f7f1"; } +.bi-fast-forward-circle::before { content: "\f7f2"; } +.bi-fast-forward-fill::before { content: "\f7f3"; } +.bi-fast-forward::before { content: "\f7f4"; } +.bi-filetype-sql::before { content: "\f7f5"; } +.bi-fire::before { content: "\f7f6"; } +.bi-google-play::before { content: "\f7f7"; } +.bi-h-circle-fill::before { content: "\f7fa"; } +.bi-h-circle::before { content: "\f7fb"; } +.bi-h-square-fill::before { content: "\f7fc"; } +.bi-h-square::before { content: "\f7fd"; } +.bi-indent::before { content: "\f7fe"; } +.bi-lungs-fill::before { content: "\f7ff"; } +.bi-lungs::before { content: "\f800"; } +.bi-microsoft-teams::before { content: "\f801"; } +.bi-p-circle-fill::before { content: "\f804"; } +.bi-p-circle::before { content: "\f805"; } +.bi-p-square-fill::before { content: "\f806"; } +.bi-p-square::before { content: "\f807"; } +.bi-pass-fill::before { content: "\f808"; } +.bi-pass::before { content: "\f809"; } +.bi-prescription::before { content: "\f80a"; } +.bi-prescription2::before { content: "\f80b"; } +.bi-r-circle-fill::before { content: "\f80e"; } +.bi-r-circle::before { content: "\f80f"; } +.bi-r-square-fill::before { content: "\f810"; } +.bi-r-square::before { content: "\f811"; } +.bi-repeat-1::before { content: "\f812"; } +.bi-repeat::before { content: "\f813"; } +.bi-rewind-btn-fill::before { content: "\f814"; } +.bi-rewind-btn::before { content: "\f815"; } +.bi-rewind-circle-fill::before { content: "\f816"; } +.bi-rewind-circle::before { content: "\f817"; } +.bi-rewind-fill::before { content: "\f818"; } +.bi-rewind::before { content: "\f819"; } +.bi-train-freight-front-fill::before { content: "\f81a"; } +.bi-train-freight-front::before { content: "\f81b"; } +.bi-train-front-fill::before { content: "\f81c"; } +.bi-train-front::before { content: "\f81d"; } +.bi-train-lightrail-front-fill::before { content: "\f81e"; } +.bi-train-lightrail-front::before { content: "\f81f"; } +.bi-truck-front-fill::before { content: "\f820"; } +.bi-truck-front::before { content: "\f821"; } +.bi-ubuntu::before { content: "\f822"; } +.bi-unindent::before { content: "\f823"; } +.bi-unity::before { content: "\f824"; } +.bi-universal-access-circle::before { content: "\f825"; } +.bi-universal-access::before { content: "\f826"; } +.bi-virus::before { content: "\f827"; } +.bi-virus2::before { content: "\f828"; } +.bi-wechat::before { content: "\f829"; } +.bi-yelp::before { content: "\f82a"; } +.bi-sign-stop-fill::before { content: "\f82b"; } +.bi-sign-stop-lights-fill::before { content: "\f82c"; } +.bi-sign-stop-lights::before { content: "\f82d"; } +.bi-sign-stop::before { content: "\f82e"; } +.bi-sign-turn-left-fill::before { content: "\f82f"; } +.bi-sign-turn-left::before { content: "\f830"; } +.bi-sign-turn-right-fill::before { content: "\f831"; } +.bi-sign-turn-right::before { content: "\f832"; } +.bi-sign-turn-slight-left-fill::before { content: "\f833"; } +.bi-sign-turn-slight-left::before { content: "\f834"; } +.bi-sign-turn-slight-right-fill::before { content: "\f835"; } +.bi-sign-turn-slight-right::before { content: "\f836"; } +.bi-sign-yield-fill::before { content: "\f837"; } +.bi-sign-yield::before { content: "\f838"; } +.bi-ev-station-fill::before { content: "\f839"; } +.bi-ev-station::before { content: "\f83a"; } +.bi-fuel-pump-diesel-fill::before { content: "\f83b"; } +.bi-fuel-pump-diesel::before { content: "\f83c"; } +.bi-fuel-pump-fill::before { content: "\f83d"; } +.bi-fuel-pump::before { content: "\f83e"; } +.bi-0-circle-fill::before { content: "\f83f"; } +.bi-0-circle::before { content: "\f840"; } +.bi-0-square-fill::before { content: "\f841"; } +.bi-0-square::before { content: "\f842"; } +.bi-rocket-fill::before { content: "\f843"; } +.bi-rocket-takeoff-fill::before { content: "\f844"; } +.bi-rocket-takeoff::before { content: "\f845"; } +.bi-rocket::before { content: "\f846"; } +.bi-stripe::before { content: "\f847"; } +.bi-subscript::before { content: "\f848"; } +.bi-superscript::before { content: "\f849"; } +.bi-trello::before { content: "\f84a"; } +.bi-envelope-at-fill::before { content: "\f84b"; } +.bi-envelope-at::before { content: "\f84c"; } +.bi-regex::before { content: "\f84d"; } +.bi-text-wrap::before { content: "\f84e"; } +.bi-sign-dead-end-fill::before { content: "\f84f"; } +.bi-sign-dead-end::before { content: "\f850"; } +.bi-sign-do-not-enter-fill::before { content: "\f851"; } +.bi-sign-do-not-enter::before { content: "\f852"; } +.bi-sign-intersection-fill::before { content: "\f853"; } +.bi-sign-intersection-side-fill::before { content: "\f854"; } +.bi-sign-intersection-side::before { content: "\f855"; } +.bi-sign-intersection-t-fill::before { content: "\f856"; } +.bi-sign-intersection-t::before { content: "\f857"; } +.bi-sign-intersection-y-fill::before { content: "\f858"; } +.bi-sign-intersection-y::before { content: "\f859"; } +.bi-sign-intersection::before { content: "\f85a"; } +.bi-sign-merge-left-fill::before { content: "\f85b"; } +.bi-sign-merge-left::before { content: "\f85c"; } +.bi-sign-merge-right-fill::before { content: "\f85d"; } +.bi-sign-merge-right::before { content: "\f85e"; } +.bi-sign-no-left-turn-fill::before { content: "\f85f"; } +.bi-sign-no-left-turn::before { content: "\f860"; } +.bi-sign-no-parking-fill::before { content: "\f861"; } +.bi-sign-no-parking::before { content: "\f862"; } +.bi-sign-no-right-turn-fill::before { content: "\f863"; } +.bi-sign-no-right-turn::before { content: "\f864"; } +.bi-sign-railroad-fill::before { content: "\f865"; } +.bi-sign-railroad::before { content: "\f866"; } +.bi-building-add::before { content: "\f867"; } +.bi-building-check::before { content: "\f868"; } +.bi-building-dash::before { content: "\f869"; } +.bi-building-down::before { content: "\f86a"; } +.bi-building-exclamation::before { content: "\f86b"; } +.bi-building-fill-add::before { content: "\f86c"; } +.bi-building-fill-check::before { content: "\f86d"; } +.bi-building-fill-dash::before { content: "\f86e"; } +.bi-building-fill-down::before { content: "\f86f"; } +.bi-building-fill-exclamation::before { content: "\f870"; } +.bi-building-fill-gear::before { content: "\f871"; } +.bi-building-fill-lock::before { content: "\f872"; } +.bi-building-fill-slash::before { content: "\f873"; } +.bi-building-fill-up::before { content: "\f874"; } +.bi-building-fill-x::before { content: "\f875"; } +.bi-building-fill::before { content: "\f876"; } +.bi-building-gear::before { content: "\f877"; } +.bi-building-lock::before { content: "\f878"; } +.bi-building-slash::before { content: "\f879"; } +.bi-building-up::before { content: "\f87a"; } +.bi-building-x::before { content: "\f87b"; } +.bi-buildings-fill::before { content: "\f87c"; } +.bi-buildings::before { content: "\f87d"; } +.bi-bus-front-fill::before { content: "\f87e"; } +.bi-bus-front::before { content: "\f87f"; } +.bi-ev-front-fill::before { content: "\f880"; } +.bi-ev-front::before { content: "\f881"; } +.bi-globe-americas::before { content: "\f882"; } +.bi-globe-asia-australia::before { content: "\f883"; } +.bi-globe-central-south-asia::before { content: "\f884"; } +.bi-globe-europe-africa::before { content: "\f885"; } +.bi-house-add-fill::before { content: "\f886"; } +.bi-house-add::before { content: "\f887"; } +.bi-house-check-fill::before { content: "\f888"; } +.bi-house-check::before { content: "\f889"; } +.bi-house-dash-fill::before { content: "\f88a"; } +.bi-house-dash::before { content: "\f88b"; } +.bi-house-down-fill::before { content: "\f88c"; } +.bi-house-down::before { content: "\f88d"; } +.bi-house-exclamation-fill::before { content: "\f88e"; } +.bi-house-exclamation::before { content: "\f88f"; } +.bi-house-gear-fill::before { content: "\f890"; } +.bi-house-gear::before { content: "\f891"; } +.bi-house-lock-fill::before { content: "\f892"; } +.bi-house-lock::before { content: "\f893"; } +.bi-house-slash-fill::before { content: "\f894"; } +.bi-house-slash::before { content: "\f895"; } +.bi-house-up-fill::before { content: "\f896"; } +.bi-house-up::before { content: "\f897"; } +.bi-house-x-fill::before { content: "\f898"; } +.bi-house-x::before { content: "\f899"; } +.bi-person-add::before { content: "\f89a"; } +.bi-person-down::before { content: "\f89b"; } +.bi-person-exclamation::before { content: "\f89c"; } +.bi-person-fill-add::before { content: "\f89d"; } +.bi-person-fill-check::before { content: "\f89e"; } +.bi-person-fill-dash::before { content: "\f89f"; } +.bi-person-fill-down::before { content: "\f8a0"; } +.bi-person-fill-exclamation::before { content: "\f8a1"; } +.bi-person-fill-gear::before { content: "\f8a2"; } +.bi-person-fill-lock::before { content: "\f8a3"; } +.bi-person-fill-slash::before { content: "\f8a4"; } +.bi-person-fill-up::before { content: "\f8a5"; } +.bi-person-fill-x::before { content: "\f8a6"; } +.bi-person-gear::before { content: "\f8a7"; } +.bi-person-lock::before { content: "\f8a8"; } +.bi-person-slash::before { content: "\f8a9"; } +.bi-person-up::before { content: "\f8aa"; } +.bi-scooter::before { content: "\f8ab"; } +.bi-taxi-front-fill::before { content: "\f8ac"; } +.bi-taxi-front::before { content: "\f8ad"; } +.bi-amd::before { content: "\f8ae"; } +.bi-database-add::before { content: "\f8af"; } +.bi-database-check::before { content: "\f8b0"; } +.bi-database-dash::before { content: "\f8b1"; } +.bi-database-down::before { content: "\f8b2"; } +.bi-database-exclamation::before { content: "\f8b3"; } +.bi-database-fill-add::before { content: "\f8b4"; } +.bi-database-fill-check::before { content: "\f8b5"; } +.bi-database-fill-dash::before { content: "\f8b6"; } +.bi-database-fill-down::before { content: "\f8b7"; } +.bi-database-fill-exclamation::before { content: "\f8b8"; } +.bi-database-fill-gear::before { content: "\f8b9"; } +.bi-database-fill-lock::before { content: "\f8ba"; } +.bi-database-fill-slash::before { content: "\f8bb"; } +.bi-database-fill-up::before { content: "\f8bc"; } +.bi-database-fill-x::before { content: "\f8bd"; } +.bi-database-fill::before { content: "\f8be"; } +.bi-database-gear::before { content: "\f8bf"; } +.bi-database-lock::before { content: "\f8c0"; } +.bi-database-slash::before { content: "\f8c1"; } +.bi-database-up::before { content: "\f8c2"; } +.bi-database-x::before { content: "\f8c3"; } +.bi-database::before { content: "\f8c4"; } +.bi-houses-fill::before { content: "\f8c5"; } +.bi-houses::before { content: "\f8c6"; } +.bi-nvidia::before { content: "\f8c7"; } +.bi-person-vcard-fill::before { content: "\f8c8"; } +.bi-person-vcard::before { content: "\f8c9"; } +.bi-sina-weibo::before { content: "\f8ca"; } +.bi-tencent-qq::before { content: "\f8cb"; } +.bi-wikipedia::before { content: "\f8cc"; } +.bi-alphabet-uppercase::before { content: "\f2a5"; } +.bi-alphabet::before { content: "\f68a"; } +.bi-amazon::before { content: "\f68d"; } +.bi-arrows-collapse-vertical::before { content: "\f690"; } +.bi-arrows-expand-vertical::before { content: "\f695"; } +.bi-arrows-vertical::before { content: "\f698"; } +.bi-arrows::before { content: "\f6a2"; } +.bi-ban-fill::before { content: "\f6a3"; } +.bi-ban::before { content: "\f6b6"; } +.bi-bing::before { content: "\f6c2"; } +.bi-cake::before { content: "\f6e0"; } +.bi-cake2::before { content: "\f6ed"; } +.bi-cookie::before { content: "\f6ee"; } +.bi-copy::before { content: "\f759"; } +.bi-crosshair::before { content: "\f769"; } +.bi-crosshair2::before { content: "\f794"; } +.bi-emoji-astonished-fill::before { content: "\f795"; } +.bi-emoji-astonished::before { content: "\f79a"; } +.bi-emoji-grimace-fill::before { content: "\f79b"; } +.bi-emoji-grimace::before { content: "\f7a0"; } +.bi-emoji-grin-fill::before { content: "\f7a1"; } +.bi-emoji-grin::before { content: "\f7a6"; } +.bi-emoji-surprise-fill::before { content: "\f7a7"; } +.bi-emoji-surprise::before { content: "\f7ac"; } +.bi-emoji-tear-fill::before { content: "\f7ad"; } +.bi-emoji-tear::before { content: "\f7b2"; } +.bi-envelope-arrow-down-fill::before { content: "\f7b3"; } +.bi-envelope-arrow-down::before { content: "\f7b8"; } +.bi-envelope-arrow-up-fill::before { content: "\f7b9"; } +.bi-envelope-arrow-up::before { content: "\f7be"; } +.bi-feather::before { content: "\f7bf"; } +.bi-feather2::before { content: "\f7c4"; } +.bi-floppy-fill::before { content: "\f7c5"; } +.bi-floppy::before { content: "\f7d8"; } +.bi-floppy2-fill::before { content: "\f7d9"; } +.bi-floppy2::before { content: "\f7e4"; } +.bi-gitlab::before { content: "\f7e5"; } +.bi-highlighter::before { content: "\f7f8"; } +.bi-marker-tip::before { content: "\f802"; } +.bi-nvme-fill::before { content: "\f803"; } +.bi-nvme::before { content: "\f80c"; } +.bi-opencollective::before { content: "\f80d"; } +.bi-pci-card-network::before { content: "\f8cd"; } +.bi-pci-card-sound::before { content: "\f8ce"; } +.bi-radar::before { content: "\f8cf"; } +.bi-send-arrow-down-fill::before { content: "\f8d0"; } +.bi-send-arrow-down::before { content: "\f8d1"; } +.bi-send-arrow-up-fill::before { content: "\f8d2"; } +.bi-send-arrow-up::before { content: "\f8d3"; } +.bi-sim-slash-fill::before { content: "\f8d4"; } +.bi-sim-slash::before { content: "\f8d5"; } +.bi-sourceforge::before { content: "\f8d6"; } +.bi-substack::before { content: "\f8d7"; } +.bi-threads-fill::before { content: "\f8d8"; } +.bi-threads::before { content: "\f8d9"; } +.bi-transparency::before { content: "\f8da"; } +.bi-twitter-x::before { content: "\f8db"; } +.bi-type-h4::before { content: "\f8dc"; } +.bi-type-h5::before { content: "\f8dd"; } +.bi-type-h6::before { content: "\f8de"; } +.bi-backpack-fill::before { content: "\f8df"; } +.bi-backpack::before { content: "\f8e0"; } +.bi-backpack2-fill::before { content: "\f8e1"; } +.bi-backpack2::before { content: "\f8e2"; } +.bi-backpack3-fill::before { content: "\f8e3"; } +.bi-backpack3::before { content: "\f8e4"; } +.bi-backpack4-fill::before { content: "\f8e5"; } +.bi-backpack4::before { content: "\f8e6"; } +.bi-brilliance::before { content: "\f8e7"; } +.bi-cake-fill::before { content: "\f8e8"; } +.bi-cake2-fill::before { content: "\f8e9"; } +.bi-duffle-fill::before { content: "\f8ea"; } +.bi-duffle::before { content: "\f8eb"; } +.bi-exposure::before { content: "\f8ec"; } +.bi-gender-neuter::before { content: "\f8ed"; } +.bi-highlights::before { content: "\f8ee"; } +.bi-luggage-fill::before { content: "\f8ef"; } +.bi-luggage::before { content: "\f8f0"; } +.bi-mailbox-flag::before { content: "\f8f1"; } +.bi-mailbox2-flag::before { content: "\f8f2"; } +.bi-noise-reduction::before { content: "\f8f3"; } +.bi-passport-fill::before { content: "\f8f4"; } +.bi-passport::before { content: "\f8f5"; } +.bi-person-arms-up::before { content: "\f8f6"; } +.bi-person-raised-hand::before { content: "\f8f7"; } +.bi-person-standing-dress::before { content: "\f8f8"; } +.bi-person-standing::before { content: "\f8f9"; } +.bi-person-walking::before { content: "\f8fa"; } +.bi-person-wheelchair::before { content: "\f8fb"; } +.bi-shadows::before { content: "\f8fc"; } +.bi-suitcase-fill::before { content: "\f8fd"; } +.bi-suitcase-lg-fill::before { content: "\f8fe"; } +.bi-suitcase-lg::before { content: "\f8ff"; } +.bi-suitcase::before { content: "\f900"; } +.bi-suitcase2-fill::before { content: "\f901"; } +.bi-suitcase2::before { content: "\f902"; } +.bi-vignette::before { content: "\f903"; } diff --git a/site_libs/bootstrap/bootstrap-icons.woff b/site_libs/bootstrap/bootstrap-icons.woff new file mode 100644 index 00000000..dbeeb055 Binary files /dev/null and b/site_libs/bootstrap/bootstrap-icons.woff differ diff --git a/site_libs/bootstrap/bootstrap.min.css b/site_libs/bootstrap/bootstrap.min.css new file mode 100644 index 00000000..cf8f44a8 --- /dev/null +++ b/site_libs/bootstrap/bootstrap.min.css @@ -0,0 +1,12 @@ +/*! + * Bootstrap v5.3.1 (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */@import"https://fonts.googleapis.com/css?family=Roboto:400,500,700&display=swap";@import"https://fonts.googleapis.com/css?family=Roboto+Mono|JetBrains+Mono&display=swap";:root,[data-bs-theme=light]{--bs-blue: #0d6efd;--bs-indigo: #6610f2;--bs-purple: #6f42c1;--bs-pink: #d63384;--bs-red: #dc3545;--bs-orange: #fd7e14;--bs-yellow: #ffc107;--bs-green: #198754;--bs-teal: #20c997;--bs-cyan: #0dcaf0;--bs-black: #000;--bs-white: #ffffff;--bs-gray: #6c757d;--bs-gray-dark: #343a40;--bs-gray-100: #f8f9fa;--bs-gray-200: #e9ecef;--bs-gray-300: #dee2e6;--bs-gray-400: #ced4da;--bs-gray-500: #adb5bd;--bs-gray-600: #6c757d;--bs-gray-700: #495057;--bs-gray-800: #343a40;--bs-gray-900: #212529;--bs-default: #dee2e6;--bs-primary: #0d6efd;--bs-secondary: #6c757d;--bs-success: #198754;--bs-info: #0dcaf0;--bs-warning: #ffc107;--bs-danger: #dc3545;--bs-light: #f8f9fa;--bs-dark: #212529;--bs-default-rgb: 222, 226, 230;--bs-primary-rgb: 13, 110, 253;--bs-secondary-rgb: 108, 117, 125;--bs-success-rgb: 25, 135, 84;--bs-info-rgb: 13, 202, 240;--bs-warning-rgb: 255, 193, 7;--bs-danger-rgb: 220, 53, 69;--bs-light-rgb: 248, 249, 250;--bs-dark-rgb: 33, 37, 41;--bs-primary-text-emphasis: #052c65;--bs-secondary-text-emphasis: #2b2f32;--bs-success-text-emphasis: #0a3622;--bs-info-text-emphasis: #055160;--bs-warning-text-emphasis: #664d03;--bs-danger-text-emphasis: #58151c;--bs-light-text-emphasis: #495057;--bs-dark-text-emphasis: #495057;--bs-primary-bg-subtle: #cfe2ff;--bs-secondary-bg-subtle: #e2e3e5;--bs-success-bg-subtle: #d1e7dd;--bs-info-bg-subtle: #cff4fc;--bs-warning-bg-subtle: #fff3cd;--bs-danger-bg-subtle: #f8d7da;--bs-light-bg-subtle: #fcfcfd;--bs-dark-bg-subtle: #ced4da;--bs-primary-border-subtle: #9ec5fe;--bs-secondary-border-subtle: #c4c8cb;--bs-success-border-subtle: #a3cfbb;--bs-info-border-subtle: #9eeaf9;--bs-warning-border-subtle: #ffe69c;--bs-danger-border-subtle: #f1aeb5;--bs-light-border-subtle: #e9ecef;--bs-dark-border-subtle: #adb5bd;--bs-white-rgb: 255, 255, 255;--bs-black-rgb: 0, 0, 0;--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));--bs-root-font-size: 16px;--bs-body-font-family: Roboto;--bs-body-font-size:1rem;--bs-body-font-weight: 400;--bs-body-line-height: 1.5;--bs-body-color: #212529;--bs-body-color-rgb: 33, 37, 41;--bs-body-bg: #ffffff;--bs-body-bg-rgb: 255, 255, 255;--bs-emphasis-color: #000;--bs-emphasis-color-rgb: 0, 0, 0;--bs-secondary-color: rgba(33, 37, 41, 0.75);--bs-secondary-color-rgb: 33, 37, 41;--bs-secondary-bg: #e9ecef;--bs-secondary-bg-rgb: 233, 236, 239;--bs-tertiary-color: rgba(33, 37, 41, 0.5);--bs-tertiary-color-rgb: 33, 37, 41;--bs-tertiary-bg: #f8f9fa;--bs-tertiary-bg-rgb: 248, 249, 250;--bs-heading-color: inherit;--bs-link-color: rgb(3, 99, 142);--bs-link-color-rgb: 3, 99, 142;--bs-link-decoration: underline;--bs-link-hover-color: #024f72;--bs-link-hover-color-rgb: 2, 79, 114;--bs-code-color: #7d12ba;--bs-highlight-bg: #fff3cd;--bs-border-width: 1px;--bs-border-style: solid;--bs-border-color: #dee2e6;--bs-border-color-translucent: rgba(0, 0, 0, 0.175);--bs-border-radius: 0.25rem;--bs-border-radius-sm: 0.2em;--bs-border-radius-lg: 0.5rem;--bs-border-radius-xl: 1rem;--bs-border-radius-xxl: 2rem;--bs-border-radius-2xl: var(--bs-border-radius-xxl);--bs-border-radius-pill: 50rem;--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);--bs-focus-ring-width: 0.25rem;--bs-focus-ring-opacity: 0.25;--bs-focus-ring-color: rgba(13, 110, 253, 0.25);--bs-form-valid-color: #198754;--bs-form-valid-border-color: #198754;--bs-form-invalid-color: #dc3545;--bs-form-invalid-border-color: #dc3545}[data-bs-theme=dark]{color-scheme:dark;--bs-body-color: #dee2e6;--bs-body-color-rgb: 222, 226, 230;--bs-body-bg: #212529;--bs-body-bg-rgb: 33, 37, 41;--bs-emphasis-color: #ffffff;--bs-emphasis-color-rgb: 255, 255, 255;--bs-secondary-color: rgba(222, 226, 230, 0.75);--bs-secondary-color-rgb: 222, 226, 230;--bs-secondary-bg: #343a40;--bs-secondary-bg-rgb: 52, 58, 64;--bs-tertiary-color: rgba(222, 226, 230, 0.5);--bs-tertiary-color-rgb: 222, 226, 230;--bs-tertiary-bg: #2b3035;--bs-tertiary-bg-rgb: 43, 48, 53;--bs-primary-text-emphasis: #6ea8fe;--bs-secondary-text-emphasis: #a7acb1;--bs-success-text-emphasis: #75b798;--bs-info-text-emphasis: #6edff6;--bs-warning-text-emphasis: #ffda6a;--bs-danger-text-emphasis: #ea868f;--bs-light-text-emphasis: #f8f9fa;--bs-dark-text-emphasis: #dee2e6;--bs-primary-bg-subtle: #031633;--bs-secondary-bg-subtle: #161719;--bs-success-bg-subtle: #051b11;--bs-info-bg-subtle: #032830;--bs-warning-bg-subtle: #332701;--bs-danger-bg-subtle: #2c0b0e;--bs-light-bg-subtle: #343a40;--bs-dark-bg-subtle: #1a1d20;--bs-primary-border-subtle: #084298;--bs-secondary-border-subtle: #41464b;--bs-success-border-subtle: #0f5132;--bs-info-border-subtle: #087990;--bs-warning-border-subtle: #997404;--bs-danger-border-subtle: #842029;--bs-light-border-subtle: #495057;--bs-dark-border-subtle: #343a40;--bs-heading-color: inherit;--bs-link-color: #6ea8fe;--bs-link-hover-color: #8bb9fe;--bs-link-color-rgb: 110, 168, 254;--bs-link-hover-color-rgb: 139, 185, 254;--bs-code-color: white;--bs-border-color: #495057;--bs-border-color-translucent: rgba(255, 255, 255, 0.15);--bs-form-valid-color: #75b798;--bs-form-valid-border-color: #75b798;--bs-form-invalid-color: #ea868f;--bs-form-invalid-border-color: #ea868f}*,*::before,*::after{box-sizing:border-box}:root{font-size:var(--bs-root-font-size)}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}hr{margin:1rem 0;color:inherit;border:0;border-top:1px solid;opacity:.25}h6,.h6,h5,.h5,h4,.h4,h3,.h3,h2,.h2,h1,.h1{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2;color:var(--bs-heading-color)}h1,.h1{font-size:calc(1.325rem + 0.9vw)}@media(min-width: 1200px){h1,.h1{font-size:2rem}}h2,.h2{font-size:calc(1.29rem + 0.48vw)}@media(min-width: 1200px){h2,.h2{font-size:1.65rem}}h3,.h3{font-size:calc(1.27rem + 0.24vw)}@media(min-width: 1200px){h3,.h3{font-size:1.45rem}}h4,.h4{font-size:1.25rem}h5,.h5{font-size:1.1rem}h6,.h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[title]{text-decoration:underline dotted;-webkit-text-decoration:underline dotted;-moz-text-decoration:underline dotted;-ms-text-decoration:underline dotted;-o-text-decoration:underline dotted;cursor:help;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem;padding:.625rem 1.25rem;border-left:.25rem solid #e9ecef}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}b,strong{font-weight:bolder}small,.small{font-size:0.875em}mark,.mark{padding:.1875em;background-color:var(--bs-highlight-bg)}sub,sup{position:relative;font-size:0.75em;line-height:0;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}a{color:rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));text-decoration:underline;-webkit-text-decoration:underline;-moz-text-decoration:underline;-ms-text-decoration:underline;-o-text-decoration:underline}a:hover{--bs-link-color-rgb: var(--bs-link-hover-color-rgb)}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}pre,code,kbd,samp{font-family:"JetBrains Mono";font-size:1em}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:0.875em;color:#000;background-color:#f8f9fa;padding:.5rem;border:1px solid var(--bs-border-color, #dee2e6);border-radius:.25rem}pre code{background-color:rgba(0,0,0,0);font-size:inherit;color:inherit;word-break:normal}code{font-size:0.875em;color:var(--bs-code-color);background-color:#f8f9fa;border-radius:.25rem;padding:.125rem .25rem;word-wrap:break-word}a>code{color:inherit}kbd{padding:.4rem .4rem;font-size:0.875em;color:#fff;background-color:#212529;border-radius:.2em}kbd kbd{padding:0;font-size:1em}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:rgba(33,37,41,.75);text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}thead,tbody,tfoot,tr,td,th{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator{display:none !important}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button:not(:disabled),[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + 0.3vw);line-height:inherit}@media(min-width: 1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-text,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none !important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:calc(1.625rem + 4.5vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-1{font-size:5rem}}.display-2{font-size:calc(1.575rem + 3.9vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-2{font-size:4.5rem}}.display-3{font-size:calc(1.525rem + 3.3vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-3{font-size:4rem}}.display-4{font-size:calc(1.475rem + 2.7vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-4{font-size:3.5rem}}.display-5{font-size:calc(1.425rem + 2.1vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-5{font-size:3rem}}.display-6{font-size:calc(1.375rem + 1.5vw);font-weight:300;line-height:1.2}@media(min-width: 1200px){.display-6{font-size:2.5rem}}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:0.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:0.875em;color:#6c757d}.blockquote-footer::before{content:"— "}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:0.875em;color:rgba(33,37,41,.75)}.container,.container-fluid,.container-xxl,.container-xl,.container-lg,.container-md,.container-sm{--bs-gutter-x: 1.5rem;--bs-gutter-y: 0;width:100%;padding-right:calc(var(--bs-gutter-x)*.5);padding-left:calc(var(--bs-gutter-x)*.5);margin-right:auto;margin-left:auto}@media(min-width: 576px){.container-sm,.container{max-width:540px}}@media(min-width: 768px){.container-md,.container-sm,.container{max-width:720px}}@media(min-width: 992px){.container-lg,.container-md,.container-sm,.container{max-width:960px}}@media(min-width: 1200px){.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1140px}}@media(min-width: 1400px){.container-xxl,.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1320px}}:root{--bs-breakpoint-xs: 0;--bs-breakpoint-sm: 576px;--bs-breakpoint-md: 768px;--bs-breakpoint-lg: 992px;--bs-breakpoint-xl: 1200px;--bs-breakpoint-xxl: 1400px}.grid{display:grid;grid-template-rows:repeat(var(--bs-rows, 1), 1fr);grid-template-columns:repeat(var(--bs-columns, 12), 1fr);gap:var(--bs-gap, 1.5rem)}.grid .g-col-1{grid-column:auto/span 1}.grid .g-col-2{grid-column:auto/span 2}.grid .g-col-3{grid-column:auto/span 3}.grid .g-col-4{grid-column:auto/span 4}.grid .g-col-5{grid-column:auto/span 5}.grid .g-col-6{grid-column:auto/span 6}.grid .g-col-7{grid-column:auto/span 7}.grid .g-col-8{grid-column:auto/span 8}.grid .g-col-9{grid-column:auto/span 9}.grid .g-col-10{grid-column:auto/span 10}.grid .g-col-11{grid-column:auto/span 11}.grid .g-col-12{grid-column:auto/span 12}.grid .g-start-1{grid-column-start:1}.grid .g-start-2{grid-column-start:2}.grid .g-start-3{grid-column-start:3}.grid .g-start-4{grid-column-start:4}.grid .g-start-5{grid-column-start:5}.grid .g-start-6{grid-column-start:6}.grid .g-start-7{grid-column-start:7}.grid .g-start-8{grid-column-start:8}.grid .g-start-9{grid-column-start:9}.grid .g-start-10{grid-column-start:10}.grid .g-start-11{grid-column-start:11}@media(min-width: 576px){.grid .g-col-sm-1{grid-column:auto/span 1}.grid .g-col-sm-2{grid-column:auto/span 2}.grid .g-col-sm-3{grid-column:auto/span 3}.grid .g-col-sm-4{grid-column:auto/span 4}.grid .g-col-sm-5{grid-column:auto/span 5}.grid .g-col-sm-6{grid-column:auto/span 6}.grid .g-col-sm-7{grid-column:auto/span 7}.grid .g-col-sm-8{grid-column:auto/span 8}.grid .g-col-sm-9{grid-column:auto/span 9}.grid .g-col-sm-10{grid-column:auto/span 10}.grid .g-col-sm-11{grid-column:auto/span 11}.grid .g-col-sm-12{grid-column:auto/span 12}.grid .g-start-sm-1{grid-column-start:1}.grid .g-start-sm-2{grid-column-start:2}.grid .g-start-sm-3{grid-column-start:3}.grid .g-start-sm-4{grid-column-start:4}.grid .g-start-sm-5{grid-column-start:5}.grid .g-start-sm-6{grid-column-start:6}.grid .g-start-sm-7{grid-column-start:7}.grid .g-start-sm-8{grid-column-start:8}.grid .g-start-sm-9{grid-column-start:9}.grid .g-start-sm-10{grid-column-start:10}.grid .g-start-sm-11{grid-column-start:11}}@media(min-width: 768px){.grid .g-col-md-1{grid-column:auto/span 1}.grid .g-col-md-2{grid-column:auto/span 2}.grid .g-col-md-3{grid-column:auto/span 3}.grid .g-col-md-4{grid-column:auto/span 4}.grid .g-col-md-5{grid-column:auto/span 5}.grid .g-col-md-6{grid-column:auto/span 6}.grid .g-col-md-7{grid-column:auto/span 7}.grid .g-col-md-8{grid-column:auto/span 8}.grid .g-col-md-9{grid-column:auto/span 9}.grid .g-col-md-10{grid-column:auto/span 10}.grid .g-col-md-11{grid-column:auto/span 11}.grid .g-col-md-12{grid-column:auto/span 12}.grid .g-start-md-1{grid-column-start:1}.grid .g-start-md-2{grid-column-start:2}.grid .g-start-md-3{grid-column-start:3}.grid .g-start-md-4{grid-column-start:4}.grid .g-start-md-5{grid-column-start:5}.grid .g-start-md-6{grid-column-start:6}.grid .g-start-md-7{grid-column-start:7}.grid .g-start-md-8{grid-column-start:8}.grid .g-start-md-9{grid-column-start:9}.grid .g-start-md-10{grid-column-start:10}.grid .g-start-md-11{grid-column-start:11}}@media(min-width: 992px){.grid .g-col-lg-1{grid-column:auto/span 1}.grid .g-col-lg-2{grid-column:auto/span 2}.grid .g-col-lg-3{grid-column:auto/span 3}.grid .g-col-lg-4{grid-column:auto/span 4}.grid .g-col-lg-5{grid-column:auto/span 5}.grid .g-col-lg-6{grid-column:auto/span 6}.grid .g-col-lg-7{grid-column:auto/span 7}.grid .g-col-lg-8{grid-column:auto/span 8}.grid .g-col-lg-9{grid-column:auto/span 9}.grid .g-col-lg-10{grid-column:auto/span 10}.grid .g-col-lg-11{grid-column:auto/span 11}.grid .g-col-lg-12{grid-column:auto/span 12}.grid .g-start-lg-1{grid-column-start:1}.grid .g-start-lg-2{grid-column-start:2}.grid .g-start-lg-3{grid-column-start:3}.grid .g-start-lg-4{grid-column-start:4}.grid .g-start-lg-5{grid-column-start:5}.grid .g-start-lg-6{grid-column-start:6}.grid .g-start-lg-7{grid-column-start:7}.grid .g-start-lg-8{grid-column-start:8}.grid .g-start-lg-9{grid-column-start:9}.grid .g-start-lg-10{grid-column-start:10}.grid .g-start-lg-11{grid-column-start:11}}@media(min-width: 1200px){.grid .g-col-xl-1{grid-column:auto/span 1}.grid .g-col-xl-2{grid-column:auto/span 2}.grid .g-col-xl-3{grid-column:auto/span 3}.grid .g-col-xl-4{grid-column:auto/span 4}.grid .g-col-xl-5{grid-column:auto/span 5}.grid .g-col-xl-6{grid-column:auto/span 6}.grid .g-col-xl-7{grid-column:auto/span 7}.grid .g-col-xl-8{grid-column:auto/span 8}.grid .g-col-xl-9{grid-column:auto/span 9}.grid .g-col-xl-10{grid-column:auto/span 10}.grid .g-col-xl-11{grid-column:auto/span 11}.grid .g-col-xl-12{grid-column:auto/span 12}.grid .g-start-xl-1{grid-column-start:1}.grid .g-start-xl-2{grid-column-start:2}.grid .g-start-xl-3{grid-column-start:3}.grid .g-start-xl-4{grid-column-start:4}.grid .g-start-xl-5{grid-column-start:5}.grid .g-start-xl-6{grid-column-start:6}.grid .g-start-xl-7{grid-column-start:7}.grid .g-start-xl-8{grid-column-start:8}.grid .g-start-xl-9{grid-column-start:9}.grid .g-start-xl-10{grid-column-start:10}.grid .g-start-xl-11{grid-column-start:11}}@media(min-width: 1400px){.grid .g-col-xxl-1{grid-column:auto/span 1}.grid .g-col-xxl-2{grid-column:auto/span 2}.grid .g-col-xxl-3{grid-column:auto/span 3}.grid .g-col-xxl-4{grid-column:auto/span 4}.grid .g-col-xxl-5{grid-column:auto/span 5}.grid .g-col-xxl-6{grid-column:auto/span 6}.grid .g-col-xxl-7{grid-column:auto/span 7}.grid .g-col-xxl-8{grid-column:auto/span 8}.grid .g-col-xxl-9{grid-column:auto/span 9}.grid .g-col-xxl-10{grid-column:auto/span 10}.grid .g-col-xxl-11{grid-column:auto/span 11}.grid .g-col-xxl-12{grid-column:auto/span 12}.grid .g-start-xxl-1{grid-column-start:1}.grid .g-start-xxl-2{grid-column-start:2}.grid .g-start-xxl-3{grid-column-start:3}.grid .g-start-xxl-4{grid-column-start:4}.grid .g-start-xxl-5{grid-column-start:5}.grid .g-start-xxl-6{grid-column-start:6}.grid .g-start-xxl-7{grid-column-start:7}.grid .g-start-xxl-8{grid-column-start:8}.grid .g-start-xxl-9{grid-column-start:9}.grid .g-start-xxl-10{grid-column-start:10}.grid .g-start-xxl-11{grid-column-start:11}}.table{--bs-table-color-type: initial;--bs-table-bg-type: initial;--bs-table-color-state: initial;--bs-table-bg-state: initial;--bs-table-color: #212529;--bs-table-bg: #ffffff;--bs-table-border-color: #dee2e6;--bs-table-accent-bg: transparent;--bs-table-striped-color: #212529;--bs-table-striped-bg: rgba(0, 0, 0, 0.05);--bs-table-active-color: #212529;--bs-table-active-bg: rgba(0, 0, 0, 0.1);--bs-table-hover-color: #212529;--bs-table-hover-bg: rgba(0, 0, 0, 0.075);width:100%;margin-bottom:1rem;vertical-align:top;border-color:var(--bs-table-border-color)}.table>:not(caption)>*>*{padding:.5rem .5rem;color:var(--bs-table-color-state, var(--bs-table-color-type, var(--bs-table-color)));background-color:var(--bs-table-bg);border-bottom-width:1px;box-shadow:inset 0 0 0 9999px var(--bs-table-bg-state, var(--bs-table-bg-type, var(--bs-table-accent-bg)))}.table>tbody{vertical-align:inherit}.table>thead{vertical-align:bottom}.table-group-divider{border-top:calc(1px*2) solid #9ba5ae}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem .25rem}.table-bordered>:not(caption)>*{border-width:1px 0}.table-bordered>:not(caption)>*>*{border-width:0 1px}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-borderless>:not(:first-child){border-top-width:0}.table-striped>tbody>tr:nth-of-type(odd)>*{--bs-table-color-type: var(--bs-table-striped-color);--bs-table-bg-type: var(--bs-table-striped-bg)}.table-striped-columns>:not(caption)>tr>:nth-child(even){--bs-table-color-type: var(--bs-table-striped-color);--bs-table-bg-type: var(--bs-table-striped-bg)}.table-active{--bs-table-color-state: var(--bs-table-active-color);--bs-table-bg-state: var(--bs-table-active-bg)}.table-hover>tbody>tr:hover>*{--bs-table-color-state: var(--bs-table-hover-color);--bs-table-bg-state: var(--bs-table-hover-bg)}.table-primary{--bs-table-color: #000;--bs-table-bg: #cfe2ff;--bs-table-border-color: #bacbe6;--bs-table-striped-bg: #c5d7f2;--bs-table-striped-color: #000;--bs-table-active-bg: #bacbe6;--bs-table-active-color: #000;--bs-table-hover-bg: #bfd1ec;--bs-table-hover-color: #000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-secondary{--bs-table-color: #000;--bs-table-bg: #e2e3e5;--bs-table-border-color: #cbccce;--bs-table-striped-bg: #d7d8da;--bs-table-striped-color: #000;--bs-table-active-bg: #cbccce;--bs-table-active-color: #000;--bs-table-hover-bg: #d1d2d4;--bs-table-hover-color: #000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-success{--bs-table-color: #000;--bs-table-bg: #d1e7dd;--bs-table-border-color: #bcd0c7;--bs-table-striped-bg: #c7dbd2;--bs-table-striped-color: #000;--bs-table-active-bg: #bcd0c7;--bs-table-active-color: #000;--bs-table-hover-bg: #c1d6cc;--bs-table-hover-color: #000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-info{--bs-table-color: #000;--bs-table-bg: #cff4fc;--bs-table-border-color: #badce3;--bs-table-striped-bg: #c5e8ef;--bs-table-striped-color: #000;--bs-table-active-bg: #badce3;--bs-table-active-color: #000;--bs-table-hover-bg: #bfe2e9;--bs-table-hover-color: #000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-warning{--bs-table-color: #000;--bs-table-bg: #fff3cd;--bs-table-border-color: #e6dbb9;--bs-table-striped-bg: #f2e7c3;--bs-table-striped-color: #000;--bs-table-active-bg: #e6dbb9;--bs-table-active-color: #000;--bs-table-hover-bg: #ece1be;--bs-table-hover-color: #000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-danger{--bs-table-color: #000;--bs-table-bg: #f8d7da;--bs-table-border-color: #dfc2c4;--bs-table-striped-bg: #eccccf;--bs-table-striped-color: #000;--bs-table-active-bg: #dfc2c4;--bs-table-active-color: #000;--bs-table-hover-bg: #e5c7ca;--bs-table-hover-color: #000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-light{--bs-table-color: #000;--bs-table-bg: #f8f9fa;--bs-table-border-color: #dfe0e1;--bs-table-striped-bg: #ecedee;--bs-table-striped-color: #000;--bs-table-active-bg: #dfe0e1;--bs-table-active-color: #000;--bs-table-hover-bg: #e5e6e7;--bs-table-hover-color: #000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-dark{--bs-table-color: #ffffff;--bs-table-bg: #212529;--bs-table-border-color: #373b3e;--bs-table-striped-bg: #2c3034;--bs-table-striped-color: #ffffff;--bs-table-active-bg: #373b3e;--bs-table-active-color: #ffffff;--bs-table-hover-bg: #323539;--bs-table-hover-color: #ffffff;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media(max-width: 575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width: 767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width: 991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width: 1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width: 1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label,.shiny-input-container .control-label{margin-bottom:.5rem}.col-form-label{padding-top:calc(0.375rem + 1px);padding-bottom:calc(0.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(0.5rem + 1px);padding-bottom:calc(0.5rem + 1px);font-size:1.25rem}.col-form-label-sm{padding-top:calc(0.25rem + 1px);padding-bottom:calc(0.25rem + 1px);font-size:0.875rem}.form-text{margin-top:.25rem;font-size:0.875em;color:rgba(33,37,41,.75)}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:#fff;background-clip:padding-box;border:1px solid #dee2e6;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:#212529;background-color:#fff;border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-control::-webkit-date-and-time-value{min-width:85px;height:1.5em;margin:0}.form-control::-webkit-datetime-edit{display:block;padding:0}.form-control::placeholder{color:rgba(33,37,41,.75);opacity:1}.form-control:disabled{background-color:#e9ecef;opacity:1}.form-control::file-selector-button{padding:.375rem .75rem;margin:-0.375rem -0.75rem;margin-inline-end:.75rem;color:#212529;background-color:#f8f9fa;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:#e9ecef}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:#212529;background-color:rgba(0,0,0,0);border:solid rgba(0,0,0,0);border-width:1px 0}.form-control-plaintext:focus{outline:0}.form-control-plaintext.form-control-sm,.form-control-plaintext.form-control-lg{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.5em + 0.5rem + calc(1px * 2));padding:.25rem .5rem;font-size:0.875rem;border-radius:.2em}.form-control-sm::file-selector-button{padding:.25rem .5rem;margin:-0.25rem -0.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.5em + 1rem + calc(1px * 2));padding:.5rem 1rem;font-size:1.25rem;border-radius:.5rem}.form-control-lg::file-selector-button{padding:.5rem 1rem;margin:-0.5rem -1rem;margin-inline-end:1rem}textarea.form-control{min-height:calc(1.5em + 0.75rem + calc(1px * 2))}textarea.form-control-sm{min-height:calc(1.5em + 0.5rem + calc(1px * 2))}textarea.form-control-lg{min-height:calc(1.5em + 1rem + calc(1px * 2))}.form-control-color{width:3rem;height:calc(1.5em + 0.75rem + calc(1px * 2));padding:.375rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{border:0 !important;border-radius:.25rem}.form-control-color::-webkit-color-swatch{border:0 !important;border-radius:.25rem}.form-control-color.form-control-sm{height:calc(1.5em + 0.5rem + calc(1px * 2))}.form-control-color.form-control-lg{height:calc(1.5em + 1rem + calc(1px * 2))}.form-select{--bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:#fff;background-image:var(--bs-form-select-bg-img),var(--bs-form-select-bg-icon, none);background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:1px solid #dee2e6;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-select{transition:none}}.form-select:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled{background-color:#e9ecef}.form-select:-moz-focusring{color:rgba(0,0,0,0);text-shadow:0 0 0 #212529}.form-select-sm{padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:0.875rem;border-radius:.2em}.form-select-lg{padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem;border-radius:.5rem}[data-bs-theme=dark] .form-select{--bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e")}.form-check,.shiny-input-container .checkbox,.shiny-input-container .radio{display:block;min-height:1.5rem;padding-left:0;margin-bottom:.125rem}.form-check .form-check-input,.form-check .shiny-input-container .checkbox input,.form-check .shiny-input-container .radio input,.shiny-input-container .checkbox .form-check-input,.shiny-input-container .checkbox .shiny-input-container .checkbox input,.shiny-input-container .checkbox .shiny-input-container .radio input,.shiny-input-container .radio .form-check-input,.shiny-input-container .radio .shiny-input-container .checkbox input,.shiny-input-container .radio .shiny-input-container .radio input{float:left;margin-left:0}.form-check-reverse{padding-right:0;padding-left:0;text-align:right}.form-check-reverse .form-check-input{float:right;margin-right:0;margin-left:0}.form-check-input,.shiny-input-container .checkbox input,.shiny-input-container .checkbox-inline input,.shiny-input-container .radio input,.shiny-input-container .radio-inline input{--bs-form-check-bg: #ffffff;width:1em;height:1em;margin-top:.25em;vertical-align:top;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:var(--bs-form-check-bg);background-image:var(--bs-form-check-bg-image);background-repeat:no-repeat;background-position:center;background-size:contain;border:1px solid #dee2e6;print-color-adjust:exact}.form-check-input[type=checkbox],.shiny-input-container .checkbox input[type=checkbox],.shiny-input-container .checkbox-inline input[type=checkbox],.shiny-input-container .radio input[type=checkbox],.shiny-input-container .radio-inline input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio],.shiny-input-container .checkbox input[type=radio],.shiny-input-container .checkbox-inline input[type=radio],.shiny-input-container .radio input[type=radio],.shiny-input-container .radio-inline input[type=radio]{border-radius:50%}.form-check-input:active,.shiny-input-container .checkbox input:active,.shiny-input-container .checkbox-inline input:active,.shiny-input-container .radio input:active,.shiny-input-container .radio-inline input:active{filter:brightness(90%)}.form-check-input:focus,.shiny-input-container .checkbox input:focus,.shiny-input-container .checkbox-inline input:focus,.shiny-input-container .radio input:focus,.shiny-input-container .radio-inline input:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-check-input:checked,.shiny-input-container .checkbox input:checked,.shiny-input-container .checkbox-inline input:checked,.shiny-input-container .radio input:checked,.shiny-input-container .radio-inline input:checked{background-color:#0d6efd;border-color:#0d6efd}.form-check-input:checked[type=checkbox],.shiny-input-container .checkbox input:checked[type=checkbox],.shiny-input-container .checkbox-inline input:checked[type=checkbox],.shiny-input-container .radio input:checked[type=checkbox],.shiny-input-container .radio-inline input:checked[type=checkbox]{--bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio],.shiny-input-container .checkbox input:checked[type=radio],.shiny-input-container .checkbox-inline input:checked[type=radio],.shiny-input-container .radio input:checked[type=radio],.shiny-input-container .radio-inline input:checked[type=radio]{--bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23ffffff'/%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate,.shiny-input-container .checkbox input[type=checkbox]:indeterminate,.shiny-input-container .checkbox-inline input[type=checkbox]:indeterminate,.shiny-input-container .radio input[type=checkbox]:indeterminate,.shiny-input-container .radio-inline input[type=checkbox]:indeterminate{background-color:#0d6efd;border-color:#0d6efd;--bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled,.shiny-input-container .checkbox input:disabled,.shiny-input-container .checkbox-inline input:disabled,.shiny-input-container .radio input:disabled,.shiny-input-container .radio-inline input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input[disabled]~.form-check-label,.form-check-input[disabled]~span,.form-check-input:disabled~.form-check-label,.form-check-input:disabled~span,.shiny-input-container .checkbox input[disabled]~.form-check-label,.shiny-input-container .checkbox input[disabled]~span,.shiny-input-container .checkbox input:disabled~.form-check-label,.shiny-input-container .checkbox input:disabled~span,.shiny-input-container .checkbox-inline input[disabled]~.form-check-label,.shiny-input-container .checkbox-inline input[disabled]~span,.shiny-input-container .checkbox-inline input:disabled~.form-check-label,.shiny-input-container .checkbox-inline input:disabled~span,.shiny-input-container .radio input[disabled]~.form-check-label,.shiny-input-container .radio input[disabled]~span,.shiny-input-container .radio input:disabled~.form-check-label,.shiny-input-container .radio input:disabled~span,.shiny-input-container .radio-inline input[disabled]~.form-check-label,.shiny-input-container .radio-inline input[disabled]~span,.shiny-input-container .radio-inline input:disabled~.form-check-label,.shiny-input-container .radio-inline input:disabled~span{cursor:default;opacity:.5}.form-check-label,.shiny-input-container .checkbox label,.shiny-input-container .checkbox-inline label,.shiny-input-container .radio label,.shiny-input-container .radio-inline label{cursor:pointer}.form-switch{padding-left:2.5em}.form-switch .form-check-input{--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");width:2em;margin-left:-2.5em;background-image:var(--bs-form-switch-bg);background-position:left center;border-radius:2em;transition:background-position .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-switch .form-check-input{transition:none}}.form-switch .form-check-input:focus{--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23ffffff'/%3e%3c/svg%3e")}.form-switch.form-check-reverse{padding-right:2.5em;padding-left:0}.form-switch.form-check-reverse .form-check-input{margin-right:-2.5em;margin-left:0}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.btn-check[disabled]+.btn,.btn-check:disabled+.btn{pointer-events:none;filter:none;opacity:.65}[data-bs-theme=dark] .form-switch .form-check-input:not(:checked):not(:focus){--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%28255, 255, 255, 0.25%29'/%3e%3c/svg%3e")}.form-range{width:100%;height:1.5rem;padding:0;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:rgba(0,0,0,0)}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-0.25rem;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:#0d6efd;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-range::-webkit-slider-thumb{transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#b6d4fe}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:rgba(0,0,0,0);cursor:pointer;background-color:#f8f9fa;border-color:rgba(0,0,0,0);border-radius:1rem}.form-range::-moz-range-thumb{width:1rem;height:1rem;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:#0d6efd;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-range::-moz-range-thumb{transition:none}}.form-range::-moz-range-thumb:active{background-color:#b6d4fe}.form-range::-moz-range-track{width:100%;height:.5rem;color:rgba(0,0,0,0);cursor:pointer;background-color:#f8f9fa;border-color:rgba(0,0,0,0);border-radius:1rem}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:rgba(33,37,41,.75)}.form-range:disabled::-moz-range-thumb{background-color:rgba(33,37,41,.75)}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-control-plaintext,.form-floating>.form-select{height:calc(3.5rem + calc(1px * 2));min-height:calc(3.5rem + calc(1px * 2));line-height:1.25}.form-floating>label{position:absolute;top:0;left:0;z-index:2;height:100%;padding:1rem .75rem;overflow:hidden;text-align:start;text-overflow:ellipsis;white-space:nowrap;pointer-events:none;border:1px solid rgba(0,0,0,0);transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media(prefers-reduced-motion: reduce){.form-floating>label{transition:none}}.form-floating>.form-control,.form-floating>.form-control-plaintext{padding:1rem .75rem}.form-floating>.form-control::placeholder,.form-floating>.form-control-plaintext::placeholder{color:rgba(0,0,0,0)}.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown),.form-floating>.form-control-plaintext:focus,.form-floating>.form-control-plaintext:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:-webkit-autofill,.form-floating>.form-control-plaintext:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-control-plaintext~label,.form-floating>.form-select~label{color:rgba(var(--bs-body-color-rgb), 0.65);transform:scale(0.85) translateY(-0.5rem) translateX(0.15rem)}.form-floating>.form-control:focus~label::after,.form-floating>.form-control:not(:placeholder-shown)~label::after,.form-floating>.form-control-plaintext~label::after,.form-floating>.form-select~label::after{position:absolute;inset:1rem .375rem;z-index:-1;height:1.5em;content:"";background-color:#fff;border-radius:.25rem}.form-floating>.form-control:-webkit-autofill~label{color:rgba(var(--bs-body-color-rgb), 0.65);transform:scale(0.85) translateY(-0.5rem) translateX(0.15rem)}.form-floating>.form-control-plaintext~label{border-width:1px 0}.form-floating>:disabled~label,.form-floating>.form-control:disabled~label{color:#6c757d}.form-floating>:disabled~label::after,.form-floating>.form-control:disabled~label::after{background-color:#e9ecef}.input-group{position:relative;display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:stretch;-webkit-align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-select,.input-group>.form-floating{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-select:focus,.input-group>.form-floating:focus-within{z-index:5}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:5}.input-group-text{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:center;white-space:nowrap;background-color:#f8f9fa;border:1px solid #dee2e6;border-radius:.25rem}.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text,.input-group-lg>.btn{padding:.5rem 1rem;font-size:1.25rem;border-radius:.5rem}.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text,.input-group-sm>.btn{padding:.25rem .5rem;font-size:0.875rem;border-radius:.2em}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:3rem}.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating),.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3),.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-control,.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-select{border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating),.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4),.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-control,.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-select{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:calc(1px*-1);border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.form-floating:not(:first-child)>.form-control,.input-group>.form-floating:not(:first-child)>.form-select{border-top-left-radius:0;border-bottom-left-radius:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:0.875em;color:#198754}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:0.875rem;color:#fff;background-color:#198754;border-radius:.25rem}.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip,.is-valid~.valid-feedback,.is-valid~.valid-tooltip{display:block}.was-validated .form-control:valid,.form-control.is-valid{border-color:#198754;padding-right:calc(1.5em + 0.75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(0.375em + 0.1875rem) center;background-size:calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-control:valid:focus,.form-control.is-valid:focus{border-color:#198754;box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + 0.75rem);background-position:top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem)}.was-validated .form-select:valid,.form-select.is-valid{border-color:#198754}.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"],.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"]{--bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");padding-right:4.125rem;background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-select:valid:focus,.form-select.is-valid:focus{border-color:#198754;box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.was-validated .form-control-color:valid,.form-control-color.is-valid{width:calc(3rem + calc(1.5em + 0.75rem))}.was-validated .form-check-input:valid,.form-check-input.is-valid{border-color:#198754}.was-validated .form-check-input:valid:checked,.form-check-input.is-valid:checked{background-color:#198754}.was-validated .form-check-input:valid:focus,.form-check-input.is-valid:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.was-validated .form-check-input:valid~.form-check-label,.form-check-input.is-valid~.form-check-label{color:#198754}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.was-validated .input-group>.form-control:not(:focus):valid,.input-group>.form-control:not(:focus).is-valid,.was-validated .input-group>.form-select:not(:focus):valid,.input-group>.form-select:not(:focus).is-valid,.was-validated .input-group>.form-floating:not(:focus-within):valid,.input-group>.form-floating:not(:focus-within).is-valid{z-index:3}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:0.875em;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:0.875rem;color:#fff;background-color:#dc3545;border-radius:.25rem}.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip,.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip{display:block}.was-validated .form-control:invalid,.form-control.is-invalid{border-color:#dc3545;padding-right:calc(1.5em + 0.75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(0.375em + 0.1875rem) center;background-size:calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-control:invalid:focus,.form-control.is-invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + 0.75rem);background-position:top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem)}.was-validated .form-select:invalid,.form-select.is-invalid{border-color:#dc3545}.was-validated .form-select:invalid:not([multiple]):not([size]),.was-validated .form-select:invalid:not([multiple])[size="1"],.form-select.is-invalid:not([multiple]):not([size]),.form-select.is-invalid:not([multiple])[size="1"]{--bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");padding-right:4.125rem;background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-select:invalid:focus,.form-select.is-invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.was-validated .form-control-color:invalid,.form-control-color.is-invalid{width:calc(3rem + calc(1.5em + 0.75rem))}.was-validated .form-check-input:invalid,.form-check-input.is-invalid{border-color:#dc3545}.was-validated .form-check-input:invalid:checked,.form-check-input.is-invalid:checked{background-color:#dc3545}.was-validated .form-check-input:invalid:focus,.form-check-input.is-invalid:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.was-validated .form-check-input:invalid~.form-check-label,.form-check-input.is-invalid~.form-check-label{color:#dc3545}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.was-validated .input-group>.form-control:not(:focus):invalid,.input-group>.form-control:not(:focus).is-invalid,.was-validated .input-group>.form-select:not(:focus):invalid,.input-group>.form-select:not(:focus).is-invalid,.was-validated .input-group>.form-floating:not(:focus-within):invalid,.input-group>.form-floating:not(:focus-within).is-invalid{z-index:4}.btn{--bs-btn-padding-x: 0.75rem;--bs-btn-padding-y: 0.375rem;--bs-btn-font-family: ;--bs-btn-font-size:1rem;--bs-btn-font-weight: 400;--bs-btn-line-height: 1.5;--bs-btn-color: #212529;--bs-btn-bg: transparent;--bs-btn-border-width: 1px;--bs-btn-border-color: transparent;--bs-btn-border-radius: 0.25rem;--bs-btn-hover-border-color: transparent;--bs-btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);--bs-btn-disabled-opacity: 0.65;--bs-btn-focus-box-shadow: 0 0 0 0.25rem rgba(var(--bs-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);color:var(--bs-btn-color);text-align:center;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;vertical-align:middle;cursor:pointer;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.btn{transition:none}}.btn:hover{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color)}.btn-check+.btn:hover{color:var(--bs-btn-color);background-color:var(--bs-btn-bg);border-color:var(--bs-btn-border-color)}.btn:focus-visible{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:focus-visible+.btn{border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:checked+.btn,:not(.btn-check)+.btn:active,.btn:first-child:active,.btn.active,.btn.show{color:var(--bs-btn-active-color);background-color:var(--bs-btn-active-bg);border-color:var(--bs-btn-active-border-color)}.btn-check:checked+.btn:focus-visible,:not(.btn-check)+.btn:active:focus-visible,.btn:first-child:active:focus-visible,.btn.active:focus-visible,.btn.show:focus-visible{box-shadow:var(--bs-btn-focus-box-shadow)}.btn:disabled,.btn.disabled,fieldset:disabled .btn{color:var(--bs-btn-disabled-color);pointer-events:none;background-color:var(--bs-btn-disabled-bg);border-color:var(--bs-btn-disabled-border-color);opacity:var(--bs-btn-disabled-opacity)}.btn-default{--bs-btn-color: #000;--bs-btn-bg: #dee2e6;--bs-btn-border-color: #dee2e6;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #e3e6ea;--bs-btn-hover-border-color: #e1e5e9;--bs-btn-focus-shadow-rgb: 189, 192, 196;--bs-btn-active-color: #000;--bs-btn-active-bg: #e5e8eb;--bs-btn-active-border-color: #e1e5e9;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #dee2e6;--bs-btn-disabled-border-color: #dee2e6}.btn-primary{--bs-btn-color: #ffffff;--bs-btn-bg: #0d6efd;--bs-btn-border-color: #0d6efd;--bs-btn-hover-color: #ffffff;--bs-btn-hover-bg: #0b5ed7;--bs-btn-hover-border-color: #0a58ca;--bs-btn-focus-shadow-rgb: 49, 132, 253;--bs-btn-active-color: #ffffff;--bs-btn-active-bg: #0a58ca;--bs-btn-active-border-color: #0a53be;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #ffffff;--bs-btn-disabled-bg: #0d6efd;--bs-btn-disabled-border-color: #0d6efd}.btn-secondary{--bs-btn-color: #ffffff;--bs-btn-bg: #6c757d;--bs-btn-border-color: #6c757d;--bs-btn-hover-color: #ffffff;--bs-btn-hover-bg: #5c636a;--bs-btn-hover-border-color: #565e64;--bs-btn-focus-shadow-rgb: 130, 138, 145;--bs-btn-active-color: #ffffff;--bs-btn-active-bg: #565e64;--bs-btn-active-border-color: #51585e;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #ffffff;--bs-btn-disabled-bg: #6c757d;--bs-btn-disabled-border-color: #6c757d}.btn-success{--bs-btn-color: #ffffff;--bs-btn-bg: #198754;--bs-btn-border-color: #198754;--bs-btn-hover-color: #ffffff;--bs-btn-hover-bg: #157347;--bs-btn-hover-border-color: #146c43;--bs-btn-focus-shadow-rgb: 60, 153, 110;--bs-btn-active-color: #ffffff;--bs-btn-active-bg: #146c43;--bs-btn-active-border-color: #13653f;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #ffffff;--bs-btn-disabled-bg: #198754;--bs-btn-disabled-border-color: #198754}.btn-info{--bs-btn-color: #000;--bs-btn-bg: #0dcaf0;--bs-btn-border-color: #0dcaf0;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #31d2f2;--bs-btn-hover-border-color: #25cff2;--bs-btn-focus-shadow-rgb: 11, 172, 204;--bs-btn-active-color: #000;--bs-btn-active-bg: #3dd5f3;--bs-btn-active-border-color: #25cff2;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #0dcaf0;--bs-btn-disabled-border-color: #0dcaf0}.btn-warning{--bs-btn-color: #000;--bs-btn-bg: #ffc107;--bs-btn-border-color: #ffc107;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #ffca2c;--bs-btn-hover-border-color: #ffc720;--bs-btn-focus-shadow-rgb: 217, 164, 6;--bs-btn-active-color: #000;--bs-btn-active-bg: #ffcd39;--bs-btn-active-border-color: #ffc720;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #ffc107;--bs-btn-disabled-border-color: #ffc107}.btn-danger{--bs-btn-color: #ffffff;--bs-btn-bg: #dc3545;--bs-btn-border-color: #dc3545;--bs-btn-hover-color: #ffffff;--bs-btn-hover-bg: #bb2d3b;--bs-btn-hover-border-color: #b02a37;--bs-btn-focus-shadow-rgb: 225, 83, 97;--bs-btn-active-color: #ffffff;--bs-btn-active-bg: #b02a37;--bs-btn-active-border-color: #a52834;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #ffffff;--bs-btn-disabled-bg: #dc3545;--bs-btn-disabled-border-color: #dc3545}.btn-light{--bs-btn-color: #000;--bs-btn-bg: #f8f9fa;--bs-btn-border-color: #f8f9fa;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #d3d4d5;--bs-btn-hover-border-color: #c6c7c8;--bs-btn-focus-shadow-rgb: 211, 212, 213;--bs-btn-active-color: #000;--bs-btn-active-bg: #c6c7c8;--bs-btn-active-border-color: #babbbc;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #f8f9fa;--bs-btn-disabled-border-color: #f8f9fa}.btn-dark{--bs-btn-color: #ffffff;--bs-btn-bg: #212529;--bs-btn-border-color: #212529;--bs-btn-hover-color: #ffffff;--bs-btn-hover-bg: #424649;--bs-btn-hover-border-color: #373b3e;--bs-btn-focus-shadow-rgb: 66, 70, 73;--bs-btn-active-color: #ffffff;--bs-btn-active-bg: #4d5154;--bs-btn-active-border-color: #373b3e;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #ffffff;--bs-btn-disabled-bg: #212529;--bs-btn-disabled-border-color: #212529}.btn-outline-default{--bs-btn-color: #dee2e6;--bs-btn-border-color: #dee2e6;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #dee2e6;--bs-btn-hover-border-color: #dee2e6;--bs-btn-focus-shadow-rgb: 222, 226, 230;--bs-btn-active-color: #000;--bs-btn-active-bg: #dee2e6;--bs-btn-active-border-color: #dee2e6;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #dee2e6;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #dee2e6;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-primary{--bs-btn-color: #0d6efd;--bs-btn-border-color: #0d6efd;--bs-btn-hover-color: #ffffff;--bs-btn-hover-bg: #0d6efd;--bs-btn-hover-border-color: #0d6efd;--bs-btn-focus-shadow-rgb: 13, 110, 253;--bs-btn-active-color: #ffffff;--bs-btn-active-bg: #0d6efd;--bs-btn-active-border-color: #0d6efd;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #0d6efd;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #0d6efd;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-secondary{--bs-btn-color: #6c757d;--bs-btn-border-color: #6c757d;--bs-btn-hover-color: #ffffff;--bs-btn-hover-bg: #6c757d;--bs-btn-hover-border-color: #6c757d;--bs-btn-focus-shadow-rgb: 108, 117, 125;--bs-btn-active-color: #ffffff;--bs-btn-active-bg: #6c757d;--bs-btn-active-border-color: #6c757d;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #6c757d;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #6c757d;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-success{--bs-btn-color: #198754;--bs-btn-border-color: #198754;--bs-btn-hover-color: #ffffff;--bs-btn-hover-bg: #198754;--bs-btn-hover-border-color: #198754;--bs-btn-focus-shadow-rgb: 25, 135, 84;--bs-btn-active-color: #ffffff;--bs-btn-active-bg: #198754;--bs-btn-active-border-color: #198754;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #198754;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #198754;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-info{--bs-btn-color: #0dcaf0;--bs-btn-border-color: #0dcaf0;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #0dcaf0;--bs-btn-hover-border-color: #0dcaf0;--bs-btn-focus-shadow-rgb: 13, 202, 240;--bs-btn-active-color: #000;--bs-btn-active-bg: #0dcaf0;--bs-btn-active-border-color: #0dcaf0;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #0dcaf0;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #0dcaf0;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-warning{--bs-btn-color: #ffc107;--bs-btn-border-color: #ffc107;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #ffc107;--bs-btn-hover-border-color: #ffc107;--bs-btn-focus-shadow-rgb: 255, 193, 7;--bs-btn-active-color: #000;--bs-btn-active-bg: #ffc107;--bs-btn-active-border-color: #ffc107;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #ffc107;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #ffc107;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-danger{--bs-btn-color: #dc3545;--bs-btn-border-color: #dc3545;--bs-btn-hover-color: #ffffff;--bs-btn-hover-bg: #dc3545;--bs-btn-hover-border-color: #dc3545;--bs-btn-focus-shadow-rgb: 220, 53, 69;--bs-btn-active-color: #ffffff;--bs-btn-active-bg: #dc3545;--bs-btn-active-border-color: #dc3545;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #dc3545;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #dc3545;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-light{--bs-btn-color: #f8f9fa;--bs-btn-border-color: #f8f9fa;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #f8f9fa;--bs-btn-hover-border-color: #f8f9fa;--bs-btn-focus-shadow-rgb: 248, 249, 250;--bs-btn-active-color: #000;--bs-btn-active-bg: #f8f9fa;--bs-btn-active-border-color: #f8f9fa;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #f8f9fa;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #f8f9fa;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-dark{--bs-btn-color: #212529;--bs-btn-border-color: #212529;--bs-btn-hover-color: #ffffff;--bs-btn-hover-bg: #212529;--bs-btn-hover-border-color: #212529;--bs-btn-focus-shadow-rgb: 33, 37, 41;--bs-btn-active-color: #ffffff;--bs-btn-active-bg: #212529;--bs-btn-active-border-color: #212529;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #212529;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #212529;--bs-btn-bg: transparent;--bs-gradient: none}.btn-link{--bs-btn-font-weight: 400;--bs-btn-color: rgb(3, 99, 142);--bs-btn-bg: transparent;--bs-btn-border-color: transparent;--bs-btn-hover-color: #024f72;--bs-btn-hover-border-color: transparent;--bs-btn-active-color: #024f72;--bs-btn-active-border-color: transparent;--bs-btn-disabled-color: #6c757d;--bs-btn-disabled-border-color: transparent;--bs-btn-box-shadow: 0 0 0 #000;--bs-btn-focus-shadow-rgb: 41, 122, 159;text-decoration:underline;-webkit-text-decoration:underline;-moz-text-decoration:underline;-ms-text-decoration:underline;-o-text-decoration:underline}.btn-link:focus-visible{color:var(--bs-btn-color)}.btn-link:hover{color:var(--bs-btn-hover-color)}.btn-lg,.btn-group-lg>.btn{--bs-btn-padding-y: 0.5rem;--bs-btn-padding-x: 1rem;--bs-btn-font-size:1.25rem;--bs-btn-border-radius: 0.5rem}.btn-sm,.btn-group-sm>.btn{--bs-btn-padding-y: 0.25rem;--bs-btn-padding-x: 0.5rem;--bs-btn-font-size:0.875rem;--bs-btn-border-radius: 0.2em}.fade{transition:opacity .15s linear}@media(prefers-reduced-motion: reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .2s ease}@media(prefers-reduced-motion: reduce){.collapsing{transition:none}}.collapsing.collapse-horizontal{width:0;height:auto;transition:width .35s ease}@media(prefers-reduced-motion: reduce){.collapsing.collapse-horizontal{transition:none}}.dropup,.dropend,.dropdown,.dropstart,.dropup-center,.dropdown-center{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid rgba(0,0,0,0);border-bottom:0;border-left:.3em solid rgba(0,0,0,0)}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{--bs-dropdown-zindex: 1000;--bs-dropdown-min-width: 10rem;--bs-dropdown-padding-x: 0;--bs-dropdown-padding-y: 0.5rem;--bs-dropdown-spacer: 0.125rem;--bs-dropdown-font-size:1rem;--bs-dropdown-color: #212529;--bs-dropdown-bg: #ffffff;--bs-dropdown-border-color: rgba(0, 0, 0, 0.175);--bs-dropdown-border-radius: 0.25rem;--bs-dropdown-border-width: 1px;--bs-dropdown-inner-border-radius: calc(0.25rem - 1px);--bs-dropdown-divider-bg: rgba(0, 0, 0, 0.175);--bs-dropdown-divider-margin-y: 0.5rem;--bs-dropdown-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-dropdown-link-color: #212529;--bs-dropdown-link-hover-color: #212529;--bs-dropdown-link-hover-bg: #f8f9fa;--bs-dropdown-link-active-color: #ffffff;--bs-dropdown-link-active-bg: #0d6efd;--bs-dropdown-link-disabled-color: rgba(33, 37, 41, 0.5);--bs-dropdown-item-padding-x: 1rem;--bs-dropdown-item-padding-y: 0.25rem;--bs-dropdown-header-color: #6c757d;--bs-dropdown-header-padding-x: 1rem;--bs-dropdown-header-padding-y: 0.5rem;position:absolute;z-index:var(--bs-dropdown-zindex);display:none;min-width:var(--bs-dropdown-min-width);padding:var(--bs-dropdown-padding-y) var(--bs-dropdown-padding-x);margin:0;font-size:var(--bs-dropdown-font-size);color:var(--bs-dropdown-color);text-align:left;list-style:none;background-color:var(--bs-dropdown-bg);background-clip:padding-box;border:var(--bs-dropdown-border-width) solid var(--bs-dropdown-border-color);border-radius:var(--bs-dropdown-border-radius)}.dropdown-menu[data-bs-popper]{top:100%;left:0;margin-top:var(--bs-dropdown-spacer)}.dropdown-menu-start{--bs-position: start}.dropdown-menu-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-end{--bs-position: end}.dropdown-menu-end[data-bs-popper]{right:0;left:auto}@media(min-width: 576px){.dropdown-menu-sm-start{--bs-position: start}.dropdown-menu-sm-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-sm-end{--bs-position: end}.dropdown-menu-sm-end[data-bs-popper]{right:0;left:auto}}@media(min-width: 768px){.dropdown-menu-md-start{--bs-position: start}.dropdown-menu-md-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-md-end{--bs-position: end}.dropdown-menu-md-end[data-bs-popper]{right:0;left:auto}}@media(min-width: 992px){.dropdown-menu-lg-start{--bs-position: start}.dropdown-menu-lg-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-lg-end{--bs-position: end}.dropdown-menu-lg-end[data-bs-popper]{right:0;left:auto}}@media(min-width: 1200px){.dropdown-menu-xl-start{--bs-position: start}.dropdown-menu-xl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xl-end{--bs-position: end}.dropdown-menu-xl-end[data-bs-popper]{right:0;left:auto}}@media(min-width: 1400px){.dropdown-menu-xxl-start{--bs-position: start}.dropdown-menu-xxl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xxl-end{--bs-position: end}.dropdown-menu-xxl-end[data-bs-popper]{right:0;left:auto}}.dropup .dropdown-menu[data-bs-popper]{top:auto;bottom:100%;margin-top:0;margin-bottom:var(--bs-dropdown-spacer)}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid rgba(0,0,0,0);border-bottom:.3em solid;border-left:.3em solid rgba(0,0,0,0)}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-menu[data-bs-popper]{top:0;right:auto;left:100%;margin-top:0;margin-left:var(--bs-dropdown-spacer)}.dropend .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid rgba(0,0,0,0);border-right:0;border-bottom:.3em solid rgba(0,0,0,0);border-left:.3em solid}.dropend .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-toggle::after{vertical-align:0}.dropstart .dropdown-menu[data-bs-popper]{top:0;right:100%;left:auto;margin-top:0;margin-right:var(--bs-dropdown-spacer)}.dropstart .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropstart .dropdown-toggle::after{display:none}.dropstart .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid rgba(0,0,0,0);border-right:.3em solid;border-bottom:.3em solid rgba(0,0,0,0)}.dropstart .dropdown-toggle:empty::after{margin-left:0}.dropstart .dropdown-toggle::before{vertical-align:0}.dropdown-divider{height:0;margin:var(--bs-dropdown-divider-margin-y) 0;overflow:hidden;border-top:1px solid var(--bs-dropdown-divider-bg);opacity:1}.dropdown-item{display:block;width:100%;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);clear:both;font-weight:400;color:var(--bs-dropdown-link-color);text-align:inherit;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;white-space:nowrap;background-color:rgba(0,0,0,0);border:0;border-radius:var(--bs-dropdown-item-border-radius, 0)}.dropdown-item:hover,.dropdown-item:focus{color:var(--bs-dropdown-link-hover-color);background-color:var(--bs-dropdown-link-hover-bg)}.dropdown-item.active,.dropdown-item:active{color:var(--bs-dropdown-link-active-color);text-decoration:none;background-color:var(--bs-dropdown-link-active-bg)}.dropdown-item.disabled,.dropdown-item:disabled{color:var(--bs-dropdown-link-disabled-color);pointer-events:none;background-color:rgba(0,0,0,0)}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:var(--bs-dropdown-header-padding-y) var(--bs-dropdown-header-padding-x);margin-bottom:0;font-size:0.875rem;color:var(--bs-dropdown-header-color);white-space:nowrap}.dropdown-item-text{display:block;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);color:var(--bs-dropdown-link-color)}.dropdown-menu-dark{--bs-dropdown-color: #dee2e6;--bs-dropdown-bg: #343a40;--bs-dropdown-border-color: rgba(0, 0, 0, 0.175);--bs-dropdown-box-shadow: ;--bs-dropdown-link-color: #dee2e6;--bs-dropdown-link-hover-color: #ffffff;--bs-dropdown-divider-bg: rgba(0, 0, 0, 0.175);--bs-dropdown-link-hover-bg: rgba(255, 255, 255, 0.15);--bs-dropdown-link-active-color: #ffffff;--bs-dropdown-link-active-bg: #0d6efd;--bs-dropdown-link-disabled-color: #adb5bd;--bs-dropdown-header-color: #adb5bd}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto}.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn:hover,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn.active{z-index:1}.btn-toolbar{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;justify-content:flex-start;-webkit-justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group{border-radius:.25rem}.btn-group>:not(.btn-check:first-child)+.btn,.btn-group>.btn-group:not(:first-child){margin-left:calc(1px*-1)}.btn-group>.btn:not(:last-child):not(.dropdown-toggle),.btn-group>.btn.dropdown-toggle-split:first-child,.btn-group>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:nth-child(n+3),.btn-group>:not(.btn-check)+.btn,.btn-group>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after,.dropend .dropdown-toggle-split::after{margin-left:0}.dropstart .dropdown-toggle-split::before{margin-right:0}.btn-sm+.dropdown-toggle-split,.btn-group-sm>.btn+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-lg+.dropdown-toggle-split,.btn-group-lg>.btn+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;-webkit-flex-direction:column;align-items:flex-start;-webkit-align-items:flex-start;justify-content:center;-webkit-justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child){margin-top:calc(1px*-1)}.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle),.btn-group-vertical>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn~.btn,.btn-group-vertical>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-top-right-radius:0}.nav{--bs-nav-link-padding-x: 1rem;--bs-nav-link-padding-y: 0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color: rgb(3, 99, 142);--bs-nav-link-hover-color: #024f72;--bs-nav-link-disabled-color: rgba(33, 37, 41, 0.75);display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x);font-size:var(--bs-nav-link-font-size);font-weight:var(--bs-nav-link-font-weight);color:var(--bs-nav-link-color);text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;background:none;border:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media(prefers-reduced-motion: reduce){.nav-link{transition:none}}.nav-link:hover,.nav-link:focus{color:var(--bs-nav-link-hover-color)}.nav-link:focus-visible{outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.nav-link.disabled,.nav-link:disabled{color:var(--bs-nav-link-disabled-color);pointer-events:none;cursor:default}.nav-tabs{--bs-nav-tabs-border-width: 1px;--bs-nav-tabs-border-color: #dee2e6;--bs-nav-tabs-border-radius: 0.25rem;--bs-nav-tabs-link-hover-border-color: #e9ecef #e9ecef #dee2e6;--bs-nav-tabs-link-active-color: #000;--bs-nav-tabs-link-active-bg: #ffffff;--bs-nav-tabs-link-active-border-color: #dee2e6 #dee2e6 #ffffff;border-bottom:var(--bs-nav-tabs-border-width) solid var(--bs-nav-tabs-border-color)}.nav-tabs .nav-link{margin-bottom:calc(-1*var(--bs-nav-tabs-border-width));border:var(--bs-nav-tabs-border-width) solid rgba(0,0,0,0);border-top-left-radius:var(--bs-nav-tabs-border-radius);border-top-right-radius:var(--bs-nav-tabs-border-radius)}.nav-tabs .nav-link:hover,.nav-tabs .nav-link:focus{isolation:isolate;border-color:var(--bs-nav-tabs-link-hover-border-color)}.nav-tabs .nav-link.active,.nav-tabs .nav-item.show .nav-link{color:var(--bs-nav-tabs-link-active-color);background-color:var(--bs-nav-tabs-link-active-bg);border-color:var(--bs-nav-tabs-link-active-border-color)}.nav-tabs .dropdown-menu{margin-top:calc(-1*var(--bs-nav-tabs-border-width));border-top-left-radius:0;border-top-right-radius:0}.nav-pills{--bs-nav-pills-border-radius: 0.25rem;--bs-nav-pills-link-active-color: #ffffff;--bs-nav-pills-link-active-bg: #0d6efd}.nav-pills .nav-link{border-radius:var(--bs-nav-pills-border-radius)}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:var(--bs-nav-pills-link-active-color);background-color:var(--bs-nav-pills-link-active-bg)}.nav-underline{--bs-nav-underline-gap: 1rem;--bs-nav-underline-border-width: 0.125rem;--bs-nav-underline-link-active-color: #000;gap:var(--bs-nav-underline-gap)}.nav-underline .nav-link{padding-right:0;padding-left:0;border-bottom:var(--bs-nav-underline-border-width) solid rgba(0,0,0,0)}.nav-underline .nav-link:hover,.nav-underline .nav-link:focus{border-bottom-color:currentcolor}.nav-underline .nav-link.active,.nav-underline .show>.nav-link{font-weight:700;color:var(--bs-nav-underline-link-active-color);border-bottom-color:currentcolor}.nav-fill>.nav-link,.nav-fill .nav-item{flex:1 1 auto;-webkit-flex:1 1 auto;text-align:center}.nav-justified>.nav-link,.nav-justified .nav-item{flex-basis:0;-webkit-flex-basis:0;flex-grow:1;-webkit-flex-grow:1;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{--bs-navbar-padding-x: 0;--bs-navbar-padding-y: 0.5rem;--bs-navbar-color: #595959;--bs-navbar-hover-color: rgba(3, 95, 136, 0.8);--bs-navbar-disabled-color: rgba(89, 89, 89, 0.75);--bs-navbar-active-color: #035f88;--bs-navbar-brand-padding-y: 0.3125rem;--bs-navbar-brand-margin-end: 1rem;--bs-navbar-brand-font-size: 1.25rem;--bs-navbar-brand-color: #595959;--bs-navbar-brand-hover-color: #035f88;--bs-navbar-nav-link-padding-x: 0.5rem;--bs-navbar-toggler-padding-y: 0.25;--bs-navbar-toggler-padding-x: 0;--bs-navbar-toggler-font-size: 1.25rem;--bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='%23595959' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");--bs-navbar-toggler-border-color: rgba(89, 89, 89, 0);--bs-navbar-toggler-border-radius: 0.25rem;--bs-navbar-toggler-focus-width: 0.25rem;--bs-navbar-toggler-transition: box-shadow 0.15s ease-in-out;position:relative;display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between;padding:var(--bs-navbar-padding-y) var(--bs-navbar-padding-x)}.navbar>.container,.navbar>.container-fluid,.navbar>.container-sm,.navbar>.container-md,.navbar>.container-lg,.navbar>.container-xl,.navbar>.container-xxl{display:flex;display:-webkit-flex;flex-wrap:inherit;-webkit-flex-wrap:inherit;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between}.navbar-brand{padding-top:var(--bs-navbar-brand-padding-y);padding-bottom:var(--bs-navbar-brand-padding-y);margin-right:var(--bs-navbar-brand-margin-end);font-size:var(--bs-navbar-brand-font-size);color:var(--bs-navbar-brand-color);text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;white-space:nowrap}.navbar-brand:hover,.navbar-brand:focus{color:var(--bs-navbar-brand-hover-color)}.navbar-nav{--bs-nav-link-padding-x: 0;--bs-nav-link-padding-y: 0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color: var(--bs-navbar-color);--bs-nav-link-hover-color: var(--bs-navbar-hover-color);--bs-nav-link-disabled-color: var(--bs-navbar-disabled-color);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link.active,.navbar-nav .nav-link.show{color:var(--bs-navbar-active-color)}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem;color:var(--bs-navbar-color)}.navbar-text a,.navbar-text a:hover,.navbar-text a:focus{color:var(--bs-navbar-active-color)}.navbar-collapse{flex-basis:100%;-webkit-flex-basis:100%;flex-grow:1;-webkit-flex-grow:1;align-items:center;-webkit-align-items:center}.navbar-toggler{padding:var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x);font-size:var(--bs-navbar-toggler-font-size);line-height:1;color:var(--bs-navbar-color);background-color:rgba(0,0,0,0);border:var(--bs-border-width) solid var(--bs-navbar-toggler-border-color);border-radius:var(--bs-navbar-toggler-border-radius);transition:var(--bs-navbar-toggler-transition)}@media(prefers-reduced-motion: reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 var(--bs-navbar-toggler-focus-width)}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-image:var(--bs-navbar-toggler-icon-bg);background-repeat:no-repeat;background-position:center;background-size:100%}.navbar-nav-scroll{max-height:var(--bs-scroll-height, 75vh);overflow-y:auto}@media(min-width: 576px){.navbar-expand-sm{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}.navbar-expand-sm .offcanvas{position:static;z-index:auto;flex-grow:1;-webkit-flex-grow:1;width:auto !important;height:auto !important;visibility:visible !important;background-color:rgba(0,0,0,0) !important;border:0 !important;transform:none !important;transition:none}.navbar-expand-sm .offcanvas .offcanvas-header{display:none}.navbar-expand-sm .offcanvas .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}@media(min-width: 768px){.navbar-expand-md{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}.navbar-expand-md .offcanvas{position:static;z-index:auto;flex-grow:1;-webkit-flex-grow:1;width:auto !important;height:auto !important;visibility:visible !important;background-color:rgba(0,0,0,0) !important;border:0 !important;transform:none !important;transition:none}.navbar-expand-md .offcanvas .offcanvas-header{display:none}.navbar-expand-md .offcanvas .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}@media(min-width: 992px){.navbar-expand-lg{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}.navbar-expand-lg .offcanvas{position:static;z-index:auto;flex-grow:1;-webkit-flex-grow:1;width:auto !important;height:auto !important;visibility:visible !important;background-color:rgba(0,0,0,0) !important;border:0 !important;transform:none !important;transition:none}.navbar-expand-lg .offcanvas .offcanvas-header{display:none}.navbar-expand-lg .offcanvas .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}@media(min-width: 1200px){.navbar-expand-xl{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}.navbar-expand-xl .offcanvas{position:static;z-index:auto;flex-grow:1;-webkit-flex-grow:1;width:auto !important;height:auto !important;visibility:visible !important;background-color:rgba(0,0,0,0) !important;border:0 !important;transform:none !important;transition:none}.navbar-expand-xl .offcanvas .offcanvas-header{display:none}.navbar-expand-xl .offcanvas .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}@media(min-width: 1400px){.navbar-expand-xxl{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}.navbar-expand-xxl .offcanvas{position:static;z-index:auto;flex-grow:1;-webkit-flex-grow:1;width:auto !important;height:auto !important;visibility:visible !important;background-color:rgba(0,0,0,0) !important;border:0 !important;transform:none !important;transition:none}.navbar-expand-xxl .offcanvas .offcanvas-header{display:none}.navbar-expand-xxl .offcanvas .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}.navbar-expand{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-expand .offcanvas{position:static;z-index:auto;flex-grow:1;-webkit-flex-grow:1;width:auto !important;height:auto !important;visibility:visible !important;background-color:rgba(0,0,0,0) !important;border:0 !important;transform:none !important;transition:none}.navbar-expand .offcanvas .offcanvas-header{display:none}.navbar-expand .offcanvas .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}.navbar-dark,.navbar[data-bs-theme=dark]{--bs-navbar-color: #595959;--bs-navbar-hover-color: rgba(3, 95, 136, 0.8);--bs-navbar-disabled-color: rgba(89, 89, 89, 0.75);--bs-navbar-active-color: #035f88;--bs-navbar-brand-color: #595959;--bs-navbar-brand-hover-color: #035f88;--bs-navbar-toggler-border-color: rgba(89, 89, 89, 0);--bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='%23595959' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}[data-bs-theme=dark] .navbar-toggler-icon{--bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='%23595959' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.card{--bs-card-spacer-y: 1rem;--bs-card-spacer-x: 1rem;--bs-card-title-spacer-y: 0.5rem;--bs-card-title-color: ;--bs-card-subtitle-color: ;--bs-card-border-width: 1px;--bs-card-border-color: rgba(0, 0, 0, 0.175);--bs-card-border-radius: 0.25rem;--bs-card-box-shadow: ;--bs-card-inner-border-radius: calc(0.25rem - 1px);--bs-card-cap-padding-y: 0.5rem;--bs-card-cap-padding-x: 1rem;--bs-card-cap-bg: rgba(52, 58, 64, 0.25);--bs-card-cap-color: ;--bs-card-height: ;--bs-card-color: ;--bs-card-bg: #ffffff;--bs-card-img-overlay-padding: 1rem;--bs-card-group-margin: 0.75rem;position:relative;display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;min-width:0;height:var(--bs-card-height);color:var(--bs-body-color);word-wrap:break-word;background-color:var(--bs-card-bg);background-clip:border-box;border:var(--bs-card-border-width) solid var(--bs-card-border-color);border-radius:var(--bs-card-border-radius)}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;-webkit-flex:1 1 auto;padding:var(--bs-card-spacer-y) var(--bs-card-spacer-x);color:var(--bs-card-color)}.card-title{margin-bottom:var(--bs-card-title-spacer-y);color:var(--bs-card-title-color)}.card-subtitle{margin-top:calc(-0.5*var(--bs-card-title-spacer-y));margin-bottom:0;color:var(--bs-card-subtitle-color)}.card-text:last-child{margin-bottom:0}.card-link+.card-link{margin-left:var(--bs-card-spacer-x)}.card-header{padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x);margin-bottom:0;color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-bottom:var(--bs-card-border-width) solid var(--bs-card-border-color)}.card-header:first-child{border-radius:var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius) 0 0}.card-footer{padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x);color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-top:var(--bs-card-border-width) solid var(--bs-card-border-color)}.card-footer:last-child{border-radius:0 0 var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius)}.card-header-tabs{margin-right:calc(-0.5*var(--bs-card-cap-padding-x));margin-bottom:calc(-1*var(--bs-card-cap-padding-y));margin-left:calc(-0.5*var(--bs-card-cap-padding-x));border-bottom:0}.card-header-tabs .nav-link.active{background-color:var(--bs-card-bg);border-bottom-color:var(--bs-card-bg)}.card-header-pills{margin-right:calc(-0.5*var(--bs-card-cap-padding-x));margin-left:calc(-0.5*var(--bs-card-cap-padding-x))}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:var(--bs-card-img-overlay-padding);border-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-top,.card-img-bottom{width:100%}.card-img,.card-img-top{border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-bottom{border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card-group>.card{margin-bottom:var(--bs-card-group-margin)}@media(min-width: 576px){.card-group{display:flex;display:-webkit-flex;flex-flow:row wrap;-webkit-flex-flow:row wrap}.card-group>.card{flex:1 0 0%;-webkit-flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-img-top,.card-group>.card:not(:last-child) .card-header{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-img-bottom,.card-group>.card:not(:last-child) .card-footer{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-img-top,.card-group>.card:not(:first-child) .card-header{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-img-bottom,.card-group>.card:not(:first-child) .card-footer{border-bottom-left-radius:0}}.accordion{--bs-accordion-color: #212529;--bs-accordion-bg: #ffffff;--bs-accordion-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, border-radius 0.15s ease;--bs-accordion-border-color: #dee2e6;--bs-accordion-border-width: 1px;--bs-accordion-border-radius: 0.25rem;--bs-accordion-inner-border-radius: calc(0.25rem - 1px);--bs-accordion-btn-padding-x: 1.25rem;--bs-accordion-btn-padding-y: 1rem;--bs-accordion-btn-color: #212529;--bs-accordion-btn-bg: #ffffff;--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");--bs-accordion-btn-icon-width: 1.25rem;--bs-accordion-btn-icon-transform: rotate(-180deg);--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23052c65'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");--bs-accordion-btn-focus-border-color: #86b7fe;--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);--bs-accordion-body-padding-x: 1.25rem;--bs-accordion-body-padding-y: 1rem;--bs-accordion-active-color: #052c65;--bs-accordion-active-bg: #cfe2ff}.accordion-button{position:relative;display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;width:100%;padding:var(--bs-accordion-btn-padding-y) var(--bs-accordion-btn-padding-x);font-size:1rem;color:var(--bs-accordion-btn-color);text-align:left;background-color:var(--bs-accordion-btn-bg);border:0;border-radius:0;overflow-anchor:none;transition:var(--bs-accordion-transition)}@media(prefers-reduced-motion: reduce){.accordion-button{transition:none}}.accordion-button:not(.collapsed){color:var(--bs-accordion-active-color);background-color:var(--bs-accordion-active-bg);box-shadow:inset 0 calc(-1*var(--bs-accordion-border-width)) 0 var(--bs-accordion-border-color)}.accordion-button:not(.collapsed)::after{background-image:var(--bs-accordion-btn-active-icon);transform:var(--bs-accordion-btn-icon-transform)}.accordion-button::after{flex-shrink:0;-webkit-flex-shrink:0;width:var(--bs-accordion-btn-icon-width);height:var(--bs-accordion-btn-icon-width);margin-left:auto;content:"";background-image:var(--bs-accordion-btn-icon);background-repeat:no-repeat;background-size:var(--bs-accordion-btn-icon-width);transition:var(--bs-accordion-btn-icon-transition)}@media(prefers-reduced-motion: reduce){.accordion-button::after{transition:none}}.accordion-button:hover{z-index:2}.accordion-button:focus{z-index:3;border-color:var(--bs-accordion-btn-focus-border-color);outline:0;box-shadow:var(--bs-accordion-btn-focus-box-shadow)}.accordion-header{margin-bottom:0}.accordion-item{color:var(--bs-accordion-color);background-color:var(--bs-accordion-bg);border:var(--bs-accordion-border-width) solid var(--bs-accordion-border-color)}.accordion-item:first-of-type{border-top-left-radius:var(--bs-accordion-border-radius);border-top-right-radius:var(--bs-accordion-border-radius)}.accordion-item:first-of-type .accordion-button{border-top-left-radius:var(--bs-accordion-inner-border-radius);border-top-right-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:not(:first-of-type){border-top:0}.accordion-item:last-of-type{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-item:last-of-type .accordion-button.collapsed{border-bottom-right-radius:var(--bs-accordion-inner-border-radius);border-bottom-left-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:last-of-type .accordion-collapse{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-body{padding:var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x)}.accordion-flush .accordion-collapse{border-width:0}.accordion-flush .accordion-item{border-right:0;border-left:0;border-radius:0}.accordion-flush .accordion-item:first-child{border-top:0}.accordion-flush .accordion-item:last-child{border-bottom:0}.accordion-flush .accordion-item .accordion-button,.accordion-flush .accordion-item .accordion-button.collapsed{border-radius:0}[data-bs-theme=dark] .accordion-button::after{--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236ea8fe'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236ea8fe'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")}.breadcrumb{--bs-breadcrumb-padding-x: 0;--bs-breadcrumb-padding-y: 0;--bs-breadcrumb-margin-bottom: 1rem;--bs-breadcrumb-bg: ;--bs-breadcrumb-border-radius: ;--bs-breadcrumb-divider-color: rgba(33, 37, 41, 0.75);--bs-breadcrumb-item-padding-x: 0.5rem;--bs-breadcrumb-item-active-color: rgba(33, 37, 41, 0.75);display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;padding:var(--bs-breadcrumb-padding-y) var(--bs-breadcrumb-padding-x);margin-bottom:var(--bs-breadcrumb-margin-bottom);font-size:var(--bs-breadcrumb-font-size);list-style:none;background-color:var(--bs-breadcrumb-bg);border-radius:var(--bs-breadcrumb-border-radius)}.breadcrumb-item+.breadcrumb-item{padding-left:var(--bs-breadcrumb-item-padding-x)}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:var(--bs-breadcrumb-item-padding-x);color:var(--bs-breadcrumb-divider-color);content:var(--bs-breadcrumb-divider, ">") /* rtl: var(--bs-breadcrumb-divider, ">") */}.breadcrumb-item.active{color:var(--bs-breadcrumb-item-active-color)}.pagination{--bs-pagination-padding-x: 0.75rem;--bs-pagination-padding-y: 0.375rem;--bs-pagination-font-size:1rem;--bs-pagination-color: rgb(3, 99, 142);--bs-pagination-bg: #ffffff;--bs-pagination-border-width: 1px;--bs-pagination-border-color: #dee2e6;--bs-pagination-border-radius: 0.25rem;--bs-pagination-hover-color: #024f72;--bs-pagination-hover-bg: #f8f9fa;--bs-pagination-hover-border-color: #dee2e6;--bs-pagination-focus-color: #024f72;--bs-pagination-focus-bg: #e9ecef;--bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);--bs-pagination-active-color: #ffffff;--bs-pagination-active-bg: #0d6efd;--bs-pagination-active-border-color: #0d6efd;--bs-pagination-disabled-color: rgba(33, 37, 41, 0.75);--bs-pagination-disabled-bg: #e9ecef;--bs-pagination-disabled-border-color: #dee2e6;display:flex;display:-webkit-flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;padding:var(--bs-pagination-padding-y) var(--bs-pagination-padding-x);font-size:var(--bs-pagination-font-size);color:var(--bs-pagination-color);text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;background-color:var(--bs-pagination-bg);border:var(--bs-pagination-border-width) solid var(--bs-pagination-border-color);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:var(--bs-pagination-hover-color);background-color:var(--bs-pagination-hover-bg);border-color:var(--bs-pagination-hover-border-color)}.page-link:focus{z-index:3;color:var(--bs-pagination-focus-color);background-color:var(--bs-pagination-focus-bg);outline:0;box-shadow:var(--bs-pagination-focus-box-shadow)}.page-link.active,.active>.page-link{z-index:3;color:var(--bs-pagination-active-color);background-color:var(--bs-pagination-active-bg);border-color:var(--bs-pagination-active-border-color)}.page-link.disabled,.disabled>.page-link{color:var(--bs-pagination-disabled-color);pointer-events:none;background-color:var(--bs-pagination-disabled-bg);border-color:var(--bs-pagination-disabled-border-color)}.page-item:not(:first-child) .page-link{margin-left:calc(1px*-1)}.page-item:first-child .page-link{border-top-left-radius:var(--bs-pagination-border-radius);border-bottom-left-radius:var(--bs-pagination-border-radius)}.page-item:last-child .page-link{border-top-right-radius:var(--bs-pagination-border-radius);border-bottom-right-radius:var(--bs-pagination-border-radius)}.pagination-lg{--bs-pagination-padding-x: 1.5rem;--bs-pagination-padding-y: 0.75rem;--bs-pagination-font-size:1.25rem;--bs-pagination-border-radius: 0.5rem}.pagination-sm{--bs-pagination-padding-x: 0.5rem;--bs-pagination-padding-y: 0.25rem;--bs-pagination-font-size:0.875rem;--bs-pagination-border-radius: 0.2em}.badge{--bs-badge-padding-x: 0.65em;--bs-badge-padding-y: 0.35em;--bs-badge-font-size:0.75em;--bs-badge-font-weight: 700;--bs-badge-color: #ffffff;--bs-badge-border-radius: 0.25rem;display:inline-block;padding:var(--bs-badge-padding-y) var(--bs-badge-padding-x);font-size:var(--bs-badge-font-size);font-weight:var(--bs-badge-font-weight);line-height:1;color:var(--bs-badge-color);text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:var(--bs-badge-border-radius)}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.alert{--bs-alert-bg: transparent;--bs-alert-padding-x: 1rem;--bs-alert-padding-y: 1rem;--bs-alert-margin-bottom: 1rem;--bs-alert-color: inherit;--bs-alert-border-color: transparent;--bs-alert-border: 1px solid var(--bs-alert-border-color);--bs-alert-border-radius: 0.25rem;--bs-alert-link-color: inherit;position:relative;padding:var(--bs-alert-padding-y) var(--bs-alert-padding-x);margin-bottom:var(--bs-alert-margin-bottom);color:var(--bs-alert-color);background-color:var(--bs-alert-bg);border:var(--bs-alert-border);border-radius:var(--bs-alert-border-radius)}.alert-heading{color:inherit}.alert-link{font-weight:700;color:var(--bs-alert-link-color)}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{position:absolute;top:0;right:0;z-index:2;padding:1.25rem 1rem}.alert-default{--bs-alert-color: var(--bs-default-text-emphasis);--bs-alert-bg: var(--bs-default-bg-subtle);--bs-alert-border-color: var(--bs-default-border-subtle);--bs-alert-link-color: var(--bs-default-text-emphasis)}.alert-primary{--bs-alert-color: var(--bs-primary-text-emphasis);--bs-alert-bg: var(--bs-primary-bg-subtle);--bs-alert-border-color: var(--bs-primary-border-subtle);--bs-alert-link-color: var(--bs-primary-text-emphasis)}.alert-secondary{--bs-alert-color: var(--bs-secondary-text-emphasis);--bs-alert-bg: var(--bs-secondary-bg-subtle);--bs-alert-border-color: var(--bs-secondary-border-subtle);--bs-alert-link-color: var(--bs-secondary-text-emphasis)}.alert-success{--bs-alert-color: var(--bs-success-text-emphasis);--bs-alert-bg: var(--bs-success-bg-subtle);--bs-alert-border-color: var(--bs-success-border-subtle);--bs-alert-link-color: var(--bs-success-text-emphasis)}.alert-info{--bs-alert-color: var(--bs-info-text-emphasis);--bs-alert-bg: var(--bs-info-bg-subtle);--bs-alert-border-color: var(--bs-info-border-subtle);--bs-alert-link-color: var(--bs-info-text-emphasis)}.alert-warning{--bs-alert-color: var(--bs-warning-text-emphasis);--bs-alert-bg: var(--bs-warning-bg-subtle);--bs-alert-border-color: var(--bs-warning-border-subtle);--bs-alert-link-color: var(--bs-warning-text-emphasis)}.alert-danger{--bs-alert-color: var(--bs-danger-text-emphasis);--bs-alert-bg: var(--bs-danger-bg-subtle);--bs-alert-border-color: var(--bs-danger-border-subtle);--bs-alert-link-color: var(--bs-danger-text-emphasis)}.alert-light{--bs-alert-color: var(--bs-light-text-emphasis);--bs-alert-bg: var(--bs-light-bg-subtle);--bs-alert-border-color: var(--bs-light-border-subtle);--bs-alert-link-color: var(--bs-light-text-emphasis)}.alert-dark{--bs-alert-color: var(--bs-dark-text-emphasis);--bs-alert-bg: var(--bs-dark-bg-subtle);--bs-alert-border-color: var(--bs-dark-border-subtle);--bs-alert-link-color: var(--bs-dark-text-emphasis)}@keyframes progress-bar-stripes{0%{background-position-x:1rem}}.progress,.progress-stacked{--bs-progress-height: 1rem;--bs-progress-font-size:0.75rem;--bs-progress-bg: #e9ecef;--bs-progress-border-radius: 0.25rem;--bs-progress-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075);--bs-progress-bar-color: #ffffff;--bs-progress-bar-bg: #0d6efd;--bs-progress-bar-transition: width 0.6s ease;display:flex;display:-webkit-flex;height:var(--bs-progress-height);overflow:hidden;font-size:var(--bs-progress-font-size);background-color:var(--bs-progress-bg);border-radius:var(--bs-progress-border-radius)}.progress-bar{display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;justify-content:center;-webkit-justify-content:center;overflow:hidden;color:var(--bs-progress-bar-color);text-align:center;white-space:nowrap;background-color:var(--bs-progress-bar-bg);transition:var(--bs-progress-bar-transition)}@media(prefers-reduced-motion: reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-size:var(--bs-progress-height) var(--bs-progress-height)}.progress-stacked>.progress{overflow:visible}.progress-stacked>.progress>.progress-bar{width:100%}.progress-bar-animated{animation:1s linear infinite progress-bar-stripes}@media(prefers-reduced-motion: reduce){.progress-bar-animated{animation:none}}.list-group{--bs-list-group-color: #212529;--bs-list-group-bg: #ffffff;--bs-list-group-border-color: #dee2e6;--bs-list-group-border-width: 1px;--bs-list-group-border-radius: 0.25rem;--bs-list-group-item-padding-x: 1rem;--bs-list-group-item-padding-y: 0.5rem;--bs-list-group-action-color: rgba(33, 37, 41, 0.75);--bs-list-group-action-hover-color: #000;--bs-list-group-action-hover-bg: #f8f9fa;--bs-list-group-action-active-color: #212529;--bs-list-group-action-active-bg: #e9ecef;--bs-list-group-disabled-color: rgba(33, 37, 41, 0.75);--bs-list-group-disabled-bg: #ffffff;--bs-list-group-active-color: #ffffff;--bs-list-group-active-bg: #0d6efd;--bs-list-group-active-border-color: #0d6efd;display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;padding-left:0;margin-bottom:0;border-radius:var(--bs-list-group-border-radius)}.list-group-numbered{list-style-type:none;counter-reset:section}.list-group-numbered>.list-group-item::before{content:counters(section, ".") ". ";counter-increment:section}.list-group-item-action{width:100%;color:var(--bs-list-group-action-color);text-align:inherit}.list-group-item-action:hover,.list-group-item-action:focus{z-index:1;color:var(--bs-list-group-action-hover-color);text-decoration:none;background-color:var(--bs-list-group-action-hover-bg)}.list-group-item-action:active{color:var(--bs-list-group-action-active-color);background-color:var(--bs-list-group-action-active-bg)}.list-group-item{position:relative;display:block;padding:var(--bs-list-group-item-padding-y) var(--bs-list-group-item-padding-x);color:var(--bs-list-group-color);text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;background-color:var(--bs-list-group-bg);border:var(--bs-list-group-border-width) solid var(--bs-list-group-border-color)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:var(--bs-list-group-disabled-color);pointer-events:none;background-color:var(--bs-list-group-disabled-bg)}.list-group-item.active{z-index:2;color:var(--bs-list-group-active-color);background-color:var(--bs-list-group-active-bg);border-color:var(--bs-list-group-active-border-color)}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:calc(-1*var(--bs-list-group-border-width));border-top-width:var(--bs-list-group-border-width)}.list-group-horizontal{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:calc(-1*var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}@media(min-width: 576px){.list-group-horizontal-sm{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:calc(-1*var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media(min-width: 768px){.list-group-horizontal-md{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:calc(-1*var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media(min-width: 992px){.list-group-horizontal-lg{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:calc(-1*var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media(min-width: 1200px){.list-group-horizontal-xl{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:calc(-1*var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media(min-width: 1400px){.list-group-horizontal-xxl{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-xxl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xxl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:calc(-1*var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 var(--bs-list-group-border-width)}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-default{--bs-list-group-color: var(--bs-default-text-emphasis);--bs-list-group-bg: var(--bs-default-bg-subtle);--bs-list-group-border-color: var(--bs-default-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-default-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-default-border-subtle);--bs-list-group-active-color: var(--bs-default-bg-subtle);--bs-list-group-active-bg: var(--bs-default-text-emphasis);--bs-list-group-active-border-color: var(--bs-default-text-emphasis)}.list-group-item-primary{--bs-list-group-color: var(--bs-primary-text-emphasis);--bs-list-group-bg: var(--bs-primary-bg-subtle);--bs-list-group-border-color: var(--bs-primary-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-primary-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-primary-border-subtle);--bs-list-group-active-color: var(--bs-primary-bg-subtle);--bs-list-group-active-bg: var(--bs-primary-text-emphasis);--bs-list-group-active-border-color: var(--bs-primary-text-emphasis)}.list-group-item-secondary{--bs-list-group-color: var(--bs-secondary-text-emphasis);--bs-list-group-bg: var(--bs-secondary-bg-subtle);--bs-list-group-border-color: var(--bs-secondary-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-secondary-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-secondary-border-subtle);--bs-list-group-active-color: var(--bs-secondary-bg-subtle);--bs-list-group-active-bg: var(--bs-secondary-text-emphasis);--bs-list-group-active-border-color: var(--bs-secondary-text-emphasis)}.list-group-item-success{--bs-list-group-color: var(--bs-success-text-emphasis);--bs-list-group-bg: var(--bs-success-bg-subtle);--bs-list-group-border-color: var(--bs-success-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-success-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-success-border-subtle);--bs-list-group-active-color: var(--bs-success-bg-subtle);--bs-list-group-active-bg: var(--bs-success-text-emphasis);--bs-list-group-active-border-color: var(--bs-success-text-emphasis)}.list-group-item-info{--bs-list-group-color: var(--bs-info-text-emphasis);--bs-list-group-bg: var(--bs-info-bg-subtle);--bs-list-group-border-color: var(--bs-info-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-info-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-info-border-subtle);--bs-list-group-active-color: var(--bs-info-bg-subtle);--bs-list-group-active-bg: var(--bs-info-text-emphasis);--bs-list-group-active-border-color: var(--bs-info-text-emphasis)}.list-group-item-warning{--bs-list-group-color: var(--bs-warning-text-emphasis);--bs-list-group-bg: var(--bs-warning-bg-subtle);--bs-list-group-border-color: var(--bs-warning-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-warning-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-warning-border-subtle);--bs-list-group-active-color: var(--bs-warning-bg-subtle);--bs-list-group-active-bg: var(--bs-warning-text-emphasis);--bs-list-group-active-border-color: var(--bs-warning-text-emphasis)}.list-group-item-danger{--bs-list-group-color: var(--bs-danger-text-emphasis);--bs-list-group-bg: var(--bs-danger-bg-subtle);--bs-list-group-border-color: var(--bs-danger-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-danger-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-danger-border-subtle);--bs-list-group-active-color: var(--bs-danger-bg-subtle);--bs-list-group-active-bg: var(--bs-danger-text-emphasis);--bs-list-group-active-border-color: var(--bs-danger-text-emphasis)}.list-group-item-light{--bs-list-group-color: var(--bs-light-text-emphasis);--bs-list-group-bg: var(--bs-light-bg-subtle);--bs-list-group-border-color: var(--bs-light-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-light-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-light-border-subtle);--bs-list-group-active-color: var(--bs-light-bg-subtle);--bs-list-group-active-bg: var(--bs-light-text-emphasis);--bs-list-group-active-border-color: var(--bs-light-text-emphasis)}.list-group-item-dark{--bs-list-group-color: var(--bs-dark-text-emphasis);--bs-list-group-bg: var(--bs-dark-bg-subtle);--bs-list-group-border-color: var(--bs-dark-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-dark-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-dark-border-subtle);--bs-list-group-active-color: var(--bs-dark-bg-subtle);--bs-list-group-active-bg: var(--bs-dark-text-emphasis);--bs-list-group-active-border-color: var(--bs-dark-text-emphasis)}.btn-close{--bs-btn-close-color: #000;--bs-btn-close-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3e%3c/svg%3e");--bs-btn-close-opacity: 0.5;--bs-btn-close-hover-opacity: 0.75;--bs-btn-close-focus-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);--bs-btn-close-focus-opacity: 1;--bs-btn-close-disabled-opacity: 0.25;--bs-btn-close-white-filter: invert(1) grayscale(100%) brightness(200%);box-sizing:content-box;width:1em;height:1em;padding:.25em .25em;color:var(--bs-btn-close-color);background:rgba(0,0,0,0) var(--bs-btn-close-bg) center/1em auto no-repeat;border:0;border-radius:.25rem;opacity:var(--bs-btn-close-opacity)}.btn-close:hover{color:var(--bs-btn-close-color);text-decoration:none;opacity:var(--bs-btn-close-hover-opacity)}.btn-close:focus{outline:0;box-shadow:var(--bs-btn-close-focus-shadow);opacity:var(--bs-btn-close-focus-opacity)}.btn-close:disabled,.btn-close.disabled{pointer-events:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;opacity:var(--bs-btn-close-disabled-opacity)}.btn-close-white{filter:var(--bs-btn-close-white-filter)}[data-bs-theme=dark] .btn-close{filter:var(--bs-btn-close-white-filter)}.toast{--bs-toast-zindex: 1090;--bs-toast-padding-x: 0.75rem;--bs-toast-padding-y: 0.5rem;--bs-toast-spacing: 1.5rem;--bs-toast-max-width: 350px;--bs-toast-font-size:0.875rem;--bs-toast-color: ;--bs-toast-bg: rgba(255, 255, 255, 0.85);--bs-toast-border-width: 1px;--bs-toast-border-color: rgba(0, 0, 0, 0.175);--bs-toast-border-radius: 0.25rem;--bs-toast-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-toast-header-color: rgba(33, 37, 41, 0.75);--bs-toast-header-bg: rgba(255, 255, 255, 0.85);--bs-toast-header-border-color: rgba(0, 0, 0, 0.175);width:var(--bs-toast-max-width);max-width:100%;font-size:var(--bs-toast-font-size);color:var(--bs-toast-color);pointer-events:auto;background-color:var(--bs-toast-bg);background-clip:padding-box;border:var(--bs-toast-border-width) solid var(--bs-toast-border-color);box-shadow:var(--bs-toast-box-shadow);border-radius:var(--bs-toast-border-radius)}.toast.showing{opacity:0}.toast:not(.show){display:none}.toast-container{--bs-toast-zindex: 1090;position:absolute;z-index:var(--bs-toast-zindex);width:max-content;width:-webkit-max-content;width:-moz-max-content;width:-ms-max-content;width:-o-max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:var(--bs-toast-spacing)}.toast-header{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;padding:var(--bs-toast-padding-y) var(--bs-toast-padding-x);color:var(--bs-toast-header-color);background-color:var(--bs-toast-header-bg);background-clip:padding-box;border-bottom:var(--bs-toast-border-width) solid var(--bs-toast-header-border-color);border-top-left-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width));border-top-right-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width))}.toast-header .btn-close{margin-right:calc(-0.5*var(--bs-toast-padding-x));margin-left:var(--bs-toast-padding-x)}.toast-body{padding:var(--bs-toast-padding-x);word-wrap:break-word}.modal{--bs-modal-zindex: 1055;--bs-modal-width: 500px;--bs-modal-padding: 1rem;--bs-modal-margin: 0.5rem;--bs-modal-color: ;--bs-modal-bg: #ffffff;--bs-modal-border-color: rgba(0, 0, 0, 0.175);--bs-modal-border-width: 1px;--bs-modal-border-radius: 0.5rem;--bs-modal-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);--bs-modal-inner-border-radius: calc(0.5rem - 1px);--bs-modal-header-padding-x: 1rem;--bs-modal-header-padding-y: 1rem;--bs-modal-header-padding: 1rem 1rem;--bs-modal-header-border-color: #dee2e6;--bs-modal-header-border-width: 1px;--bs-modal-title-line-height: 1.5;--bs-modal-footer-gap: 0.5rem;--bs-modal-footer-bg: ;--bs-modal-footer-border-color: #dee2e6;--bs-modal-footer-border-width: 1px;position:fixed;top:0;left:0;z-index:var(--bs-modal-zindex);display:none;width:100%;height:100%;overflow-x:hidden;overflow-y:auto;outline:0}.modal-dialog{position:relative;width:auto;margin:var(--bs-modal-margin);pointer-events:none}.modal.fade .modal-dialog{transition:transform .3s ease-out;transform:translate(0, -50px)}@media(prefers-reduced-motion: reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - var(--bs-modal-margin)*2)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;min-height:calc(100% - var(--bs-modal-margin)*2)}.modal-content{position:relative;display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;width:100%;color:var(--bs-modal-color);pointer-events:auto;background-color:var(--bs-modal-bg);background-clip:padding-box;border:var(--bs-modal-border-width) solid var(--bs-modal-border-color);border-radius:var(--bs-modal-border-radius);outline:0}.modal-backdrop{--bs-backdrop-zindex: 1050;--bs-backdrop-bg: #000;--bs-backdrop-opacity: 0.5;position:fixed;top:0;left:0;z-index:var(--bs-backdrop-zindex);width:100vw;height:100vh;background-color:var(--bs-backdrop-bg)}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:var(--bs-backdrop-opacity)}.modal-header{display:flex;display:-webkit-flex;flex-shrink:0;-webkit-flex-shrink:0;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between;padding:var(--bs-modal-header-padding);border-bottom:var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);border-top-left-radius:var(--bs-modal-inner-border-radius);border-top-right-radius:var(--bs-modal-inner-border-radius)}.modal-header .btn-close{padding:calc(var(--bs-modal-header-padding-y)*.5) calc(var(--bs-modal-header-padding-x)*.5);margin:calc(-0.5*var(--bs-modal-header-padding-y)) calc(-0.5*var(--bs-modal-header-padding-x)) calc(-0.5*var(--bs-modal-header-padding-y)) auto}.modal-title{margin-bottom:0;line-height:var(--bs-modal-title-line-height)}.modal-body{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto;padding:var(--bs-modal-padding)}.modal-footer{display:flex;display:-webkit-flex;flex-shrink:0;-webkit-flex-shrink:0;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:center;-webkit-align-items:center;justify-content:flex-end;-webkit-justify-content:flex-end;padding:calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap)*.5);background-color:var(--bs-modal-footer-bg);border-top:var(--bs-modal-footer-border-width) solid var(--bs-modal-footer-border-color);border-bottom-right-radius:var(--bs-modal-inner-border-radius);border-bottom-left-radius:var(--bs-modal-inner-border-radius)}.modal-footer>*{margin:calc(var(--bs-modal-footer-gap)*.5)}@media(min-width: 576px){.modal{--bs-modal-margin: 1.75rem;--bs-modal-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15)}.modal-dialog{max-width:var(--bs-modal-width);margin-right:auto;margin-left:auto}.modal-sm{--bs-modal-width: 300px}}@media(min-width: 992px){.modal-lg,.modal-xl{--bs-modal-width: 800px}}@media(min-width: 1200px){.modal-xl{--bs-modal-width: 1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-header,.modal-fullscreen .modal-footer{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}@media(max-width: 575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-header,.modal-fullscreen-sm-down .modal-footer{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}}@media(max-width: 767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-header,.modal-fullscreen-md-down .modal-footer{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}}@media(max-width: 991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-header,.modal-fullscreen-lg-down .modal-footer{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}}@media(max-width: 1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-header,.modal-fullscreen-xl-down .modal-footer{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}}@media(max-width: 1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-header,.modal-fullscreen-xxl-down .modal-footer{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}}.tooltip{--bs-tooltip-zindex: 1080;--bs-tooltip-max-width: 200px;--bs-tooltip-padding-x: 0.5rem;--bs-tooltip-padding-y: 0.25rem;--bs-tooltip-margin: ;--bs-tooltip-font-size:0.875rem;--bs-tooltip-color: #ffffff;--bs-tooltip-bg: #000;--bs-tooltip-border-radius: 0.25rem;--bs-tooltip-opacity: 0.9;--bs-tooltip-arrow-width: 0.8rem;--bs-tooltip-arrow-height: 0.4rem;z-index:var(--bs-tooltip-zindex);display:block;margin:var(--bs-tooltip-margin);font-family:Roboto;font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-tooltip-font-size);word-wrap:break-word;opacity:0}.tooltip.show{opacity:var(--bs-tooltip-opacity)}.tooltip .tooltip-arrow{display:block;width:var(--bs-tooltip-arrow-width);height:var(--bs-tooltip-arrow-height)}.tooltip .tooltip-arrow::before{position:absolute;content:"";border-color:rgba(0,0,0,0);border-style:solid}.bs-tooltip-top .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow{bottom:calc(-1*var(--bs-tooltip-arrow-height))}.bs-tooltip-top .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before{top:-1px;border-width:var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width)*.5) 0;border-top-color:var(--bs-tooltip-bg)}.bs-tooltip-end .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow{left:calc(-1*var(--bs-tooltip-arrow-height));width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-end .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before{right:-1px;border-width:calc(var(--bs-tooltip-arrow-width)*.5) var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width)*.5) 0;border-right-color:var(--bs-tooltip-bg)}.bs-tooltip-bottom .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow{top:calc(-1*var(--bs-tooltip-arrow-height))}.bs-tooltip-bottom .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before{bottom:-1px;border-width:0 calc(var(--bs-tooltip-arrow-width)*.5) var(--bs-tooltip-arrow-height);border-bottom-color:var(--bs-tooltip-bg)}.bs-tooltip-start .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow{right:calc(-1*var(--bs-tooltip-arrow-height));width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-start .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before{left:-1px;border-width:calc(var(--bs-tooltip-arrow-width)*.5) 0 calc(var(--bs-tooltip-arrow-width)*.5) var(--bs-tooltip-arrow-height);border-left-color:var(--bs-tooltip-bg)}.tooltip-inner{max-width:var(--bs-tooltip-max-width);padding:var(--bs-tooltip-padding-y) var(--bs-tooltip-padding-x);color:var(--bs-tooltip-color);text-align:center;background-color:var(--bs-tooltip-bg);border-radius:var(--bs-tooltip-border-radius)}.popover{--bs-popover-zindex: 1070;--bs-popover-max-width: 276px;--bs-popover-font-size:0.875rem;--bs-popover-bg: #ffffff;--bs-popover-border-width: 1px;--bs-popover-border-color: rgba(0, 0, 0, 0.175);--bs-popover-border-radius: 0.5rem;--bs-popover-inner-border-radius: calc(0.5rem - 1px);--bs-popover-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-popover-header-padding-x: 1rem;--bs-popover-header-padding-y: 0.5rem;--bs-popover-header-font-size:1rem;--bs-popover-header-color: inherit;--bs-popover-header-bg: #e9ecef;--bs-popover-body-padding-x: 1rem;--bs-popover-body-padding-y: 1rem;--bs-popover-body-color: #212529;--bs-popover-arrow-width: 1rem;--bs-popover-arrow-height: 0.5rem;--bs-popover-arrow-border: var(--bs-popover-border-color);z-index:var(--bs-popover-zindex);display:block;max-width:var(--bs-popover-max-width);font-family:Roboto;font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-popover-font-size);word-wrap:break-word;background-color:var(--bs-popover-bg);background-clip:padding-box;border:var(--bs-popover-border-width) solid var(--bs-popover-border-color);border-radius:var(--bs-popover-border-radius)}.popover .popover-arrow{display:block;width:var(--bs-popover-arrow-width);height:var(--bs-popover-arrow-height)}.popover .popover-arrow::before,.popover .popover-arrow::after{position:absolute;display:block;content:"";border-color:rgba(0,0,0,0);border-style:solid;border-width:0}.bs-popover-top>.popover-arrow,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow{bottom:calc(-1*(var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-top>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before,.bs-popover-top>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after{border-width:var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width)*.5) 0}.bs-popover-top>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before{bottom:0;border-top-color:var(--bs-popover-arrow-border)}.bs-popover-top>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after{bottom:var(--bs-popover-border-width);border-top-color:var(--bs-popover-bg)}.bs-popover-end>.popover-arrow,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow{left:calc(-1*(var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-end>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before,.bs-popover-end>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after{border-width:calc(var(--bs-popover-arrow-width)*.5) var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width)*.5) 0}.bs-popover-end>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before{left:0;border-right-color:var(--bs-popover-arrow-border)}.bs-popover-end>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after{left:var(--bs-popover-border-width);border-right-color:var(--bs-popover-bg)}.bs-popover-bottom>.popover-arrow,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow{top:calc(-1*(var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-bottom>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before,.bs-popover-bottom>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after{border-width:0 calc(var(--bs-popover-arrow-width)*.5) var(--bs-popover-arrow-height)}.bs-popover-bottom>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before{top:0;border-bottom-color:var(--bs-popover-arrow-border)}.bs-popover-bottom>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after{top:var(--bs-popover-border-width);border-bottom-color:var(--bs-popover-bg)}.bs-popover-bottom .popover-header::before,.bs-popover-auto[data-popper-placement^=bottom] .popover-header::before{position:absolute;top:0;left:50%;display:block;width:var(--bs-popover-arrow-width);margin-left:calc(-0.5*var(--bs-popover-arrow-width));content:"";border-bottom:var(--bs-popover-border-width) solid var(--bs-popover-header-bg)}.bs-popover-start>.popover-arrow,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow{right:calc(-1*(var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-start>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before,.bs-popover-start>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after{border-width:calc(var(--bs-popover-arrow-width)*.5) 0 calc(var(--bs-popover-arrow-width)*.5) var(--bs-popover-arrow-height)}.bs-popover-start>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before{right:0;border-left-color:var(--bs-popover-arrow-border)}.bs-popover-start>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after{right:var(--bs-popover-border-width);border-left-color:var(--bs-popover-bg)}.popover-header{padding:var(--bs-popover-header-padding-y) var(--bs-popover-header-padding-x);margin-bottom:0;font-size:var(--bs-popover-header-font-size);color:var(--bs-popover-header-color);background-color:var(--bs-popover-header-bg);border-bottom:var(--bs-popover-border-width) solid var(--bs-popover-border-color);border-top-left-radius:var(--bs-popover-inner-border-radius);border-top-right-radius:var(--bs-popover-inner-border-radius)}.popover-header:empty{display:none}.popover-body{padding:var(--bs-popover-body-padding-y) var(--bs-popover-body-padding-x);color:var(--bs-popover-body-color)}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y;-webkit-touch-action:pan-y;-moz-touch-action:pan-y;-ms-touch-action:pan-y;-o-touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;backface-visibility:hidden;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;-o-backface-visibility:hidden;transition:transform .6s ease-in-out}@media(prefers-reduced-motion: reduce){.carousel-item{transition:none}}.carousel-item.active,.carousel-item-next,.carousel-item-prev{display:block}.carousel-item-next:not(.carousel-item-start),.active.carousel-item-end{transform:translateX(100%)}.carousel-item-prev:not(.carousel-item-end),.active.carousel-item-start{transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item.active,.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end{z-index:1;opacity:1}.carousel-fade .active.carousel-item-start,.carousel-fade .active.carousel-item-end{z-index:0;opacity:0;transition:opacity 0s .6s}@media(prefers-reduced-motion: reduce){.carousel-fade .active.carousel-item-start,.carousel-fade .active.carousel-item-end{transition:none}}.carousel-control-prev,.carousel-control-next{position:absolute;top:0;bottom:0;z-index:1;display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;justify-content:center;-webkit-justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:none;border:0;opacity:.5;transition:opacity .15s ease}@media(prefers-reduced-motion: reduce){.carousel-control-prev,.carousel-control-next{transition:none}}.carousel-control-prev:hover,.carousel-control-prev:focus,.carousel-control-next:hover,.carousel-control-next:focus{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-prev-icon,.carousel-control-next-icon{display:inline-block;width:2rem;height:2rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ffffff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ffffff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;display:-webkit-flex;justify-content:center;-webkit-justify-content:center;padding:0;margin-right:15%;margin-bottom:1rem;margin-left:15%}.carousel-indicators [data-bs-target]{box-sizing:content-box;flex:0 1 auto;-webkit-flex:0 1 auto;width:30px;height:3px;padding:0;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border:0;border-top:10px solid rgba(0,0,0,0);border-bottom:10px solid rgba(0,0,0,0);opacity:.5;transition:opacity .6s ease}@media(prefers-reduced-motion: reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:#fff;text-align:center}.carousel-dark .carousel-control-prev-icon,.carousel-dark .carousel-control-next-icon{filter:invert(1) grayscale(100)}.carousel-dark .carousel-indicators [data-bs-target]{background-color:#000}.carousel-dark .carousel-caption{color:#000}[data-bs-theme=dark] .carousel .carousel-control-prev-icon,[data-bs-theme=dark] .carousel .carousel-control-next-icon,[data-bs-theme=dark].carousel .carousel-control-prev-icon,[data-bs-theme=dark].carousel .carousel-control-next-icon{filter:invert(1) grayscale(100)}[data-bs-theme=dark] .carousel .carousel-indicators [data-bs-target],[data-bs-theme=dark].carousel .carousel-indicators [data-bs-target]{background-color:#000}[data-bs-theme=dark] .carousel .carousel-caption,[data-bs-theme=dark].carousel .carousel-caption{color:#000}.spinner-grow,.spinner-border{display:inline-block;width:var(--bs-spinner-width);height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);border-radius:50%;animation:var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name)}@keyframes spinner-border{to{transform:rotate(360deg) /* rtl:ignore */}}.spinner-border{--bs-spinner-width: 2rem;--bs-spinner-height: 2rem;--bs-spinner-vertical-align: -0.125em;--bs-spinner-border-width: 0.25em;--bs-spinner-animation-speed: 0.75s;--bs-spinner-animation-name: spinner-border;border:var(--bs-spinner-border-width) solid currentcolor;border-right-color:rgba(0,0,0,0)}.spinner-border-sm{--bs-spinner-width: 1rem;--bs-spinner-height: 1rem;--bs-spinner-border-width: 0.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{--bs-spinner-width: 2rem;--bs-spinner-height: 2rem;--bs-spinner-vertical-align: -0.125em;--bs-spinner-animation-speed: 0.75s;--bs-spinner-animation-name: spinner-grow;background-color:currentcolor;opacity:0}.spinner-grow-sm{--bs-spinner-width: 1rem;--bs-spinner-height: 1rem}@media(prefers-reduced-motion: reduce){.spinner-border,.spinner-grow{--bs-spinner-animation-speed: 1.5s}}.offcanvas,.offcanvas-xxl,.offcanvas-xl,.offcanvas-lg,.offcanvas-md,.offcanvas-sm{--bs-offcanvas-zindex: 1045;--bs-offcanvas-width: 400px;--bs-offcanvas-height: 30vh;--bs-offcanvas-padding-x: 1rem;--bs-offcanvas-padding-y: 1rem;--bs-offcanvas-color: #212529;--bs-offcanvas-bg: #ffffff;--bs-offcanvas-border-width: 1px;--bs-offcanvas-border-color: rgba(0, 0, 0, 0.175);--bs-offcanvas-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);--bs-offcanvas-transition: transform 0.3s ease-in-out;--bs-offcanvas-title-line-height: 1.5}@media(max-width: 575.98px){.offcanvas-sm{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media(max-width: 575.98px)and (prefers-reduced-motion: reduce){.offcanvas-sm{transition:none}}@media(max-width: 575.98px){.offcanvas-sm.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-sm.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-sm.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-sm.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-sm.showing,.offcanvas-sm.show:not(.hiding){transform:none}.offcanvas-sm.showing,.offcanvas-sm.hiding,.offcanvas-sm.show{visibility:visible}}@media(min-width: 576px){.offcanvas-sm{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:rgba(0,0,0,0) !important}.offcanvas-sm .offcanvas-header{display:none}.offcanvas-sm .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible;background-color:rgba(0,0,0,0) !important}}@media(max-width: 767.98px){.offcanvas-md{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media(max-width: 767.98px)and (prefers-reduced-motion: reduce){.offcanvas-md{transition:none}}@media(max-width: 767.98px){.offcanvas-md.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-md.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-md.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-md.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-md.showing,.offcanvas-md.show:not(.hiding){transform:none}.offcanvas-md.showing,.offcanvas-md.hiding,.offcanvas-md.show{visibility:visible}}@media(min-width: 768px){.offcanvas-md{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:rgba(0,0,0,0) !important}.offcanvas-md .offcanvas-header{display:none}.offcanvas-md .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible;background-color:rgba(0,0,0,0) !important}}@media(max-width: 991.98px){.offcanvas-lg{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media(max-width: 991.98px)and (prefers-reduced-motion: reduce){.offcanvas-lg{transition:none}}@media(max-width: 991.98px){.offcanvas-lg.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-lg.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-lg.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-lg.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-lg.showing,.offcanvas-lg.show:not(.hiding){transform:none}.offcanvas-lg.showing,.offcanvas-lg.hiding,.offcanvas-lg.show{visibility:visible}}@media(min-width: 992px){.offcanvas-lg{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:rgba(0,0,0,0) !important}.offcanvas-lg .offcanvas-header{display:none}.offcanvas-lg .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible;background-color:rgba(0,0,0,0) !important}}@media(max-width: 1199.98px){.offcanvas-xl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media(max-width: 1199.98px)and (prefers-reduced-motion: reduce){.offcanvas-xl{transition:none}}@media(max-width: 1199.98px){.offcanvas-xl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-xl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-xl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xl.showing,.offcanvas-xl.show:not(.hiding){transform:none}.offcanvas-xl.showing,.offcanvas-xl.hiding,.offcanvas-xl.show{visibility:visible}}@media(min-width: 1200px){.offcanvas-xl{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:rgba(0,0,0,0) !important}.offcanvas-xl .offcanvas-header{display:none}.offcanvas-xl .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible;background-color:rgba(0,0,0,0) !important}}@media(max-width: 1399.98px){.offcanvas-xxl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media(max-width: 1399.98px)and (prefers-reduced-motion: reduce){.offcanvas-xxl{transition:none}}@media(max-width: 1399.98px){.offcanvas-xxl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-xxl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-xxl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xxl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xxl.showing,.offcanvas-xxl.show:not(.hiding){transform:none}.offcanvas-xxl.showing,.offcanvas-xxl.hiding,.offcanvas-xxl.show{visibility:visible}}@media(min-width: 1400px){.offcanvas-xxl{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:rgba(0,0,0,0) !important}.offcanvas-xxl .offcanvas-header{display:none}.offcanvas-xxl .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible;background-color:rgba(0,0,0,0) !important}}.offcanvas{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}@media(prefers-reduced-motion: reduce){.offcanvas{transition:none}}.offcanvas.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas.showing,.offcanvas.show:not(.hiding){transform:none}.offcanvas.showing,.offcanvas.hiding,.offcanvas.show{visibility:visible}.offcanvas-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.offcanvas-backdrop.fade{opacity:0}.offcanvas-backdrop.show{opacity:.5}.offcanvas-header{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between;padding:var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x)}.offcanvas-header .btn-close{padding:calc(var(--bs-offcanvas-padding-y)*.5) calc(var(--bs-offcanvas-padding-x)*.5);margin-top:calc(-0.5*var(--bs-offcanvas-padding-y));margin-right:calc(-0.5*var(--bs-offcanvas-padding-x));margin-bottom:calc(-0.5*var(--bs-offcanvas-padding-y))}.offcanvas-title{margin-bottom:0;line-height:var(--bs-offcanvas-title-line-height)}.offcanvas-body{flex-grow:1;-webkit-flex-grow:1;padding:var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);overflow-y:auto}.placeholder{display:inline-block;min-height:1em;vertical-align:middle;cursor:wait;background-color:currentcolor;opacity:.5}.placeholder.btn::before{display:inline-block;content:""}.placeholder-xs{min-height:.6em}.placeholder-sm{min-height:.8em}.placeholder-lg{min-height:1.2em}.placeholder-glow .placeholder{animation:placeholder-glow 2s ease-in-out infinite}@keyframes placeholder-glow{50%{opacity:.2}}.placeholder-wave{mask-image:linear-gradient(130deg, #000 55%, rgba(0, 0, 0, 0.8) 75%, #000 95%);-webkit-mask-image:linear-gradient(130deg, #000 55%, rgba(0, 0, 0, 0.8) 75%, #000 95%);mask-size:200% 100%;-webkit-mask-size:200% 100%;animation:placeholder-wave 2s linear infinite}@keyframes placeholder-wave{100%{mask-position:-200% 0%;-webkit-mask-position:-200% 0%}}.clearfix::after{display:block;clear:both;content:""}.text-bg-default{color:#000 !important;background-color:RGBA(var(--bs-default-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-primary{color:#fff !important;background-color:RGBA(var(--bs-primary-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-secondary{color:#fff !important;background-color:RGBA(var(--bs-secondary-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-success{color:#fff !important;background-color:RGBA(var(--bs-success-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-info{color:#000 !important;background-color:RGBA(var(--bs-info-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-warning{color:#000 !important;background-color:RGBA(var(--bs-warning-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-danger{color:#fff !important;background-color:RGBA(var(--bs-danger-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-light{color:#000 !important;background-color:RGBA(var(--bs-light-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-dark{color:#fff !important;background-color:RGBA(var(--bs-dark-rgb), var(--bs-bg-opacity, 1)) !important}.link-default{color:RGBA(var(--bs-default-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-default-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-default:hover,.link-default:focus{color:RGBA(229, 232, 235, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(229, 232, 235, var(--bs-link-underline-opacity, 1)) !important}.link-primary{color:RGBA(var(--bs-primary-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-primary-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-primary:hover,.link-primary:focus{color:RGBA(10, 88, 202, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(10, 88, 202, var(--bs-link-underline-opacity, 1)) !important}.link-secondary{color:RGBA(var(--bs-secondary-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-secondary-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-secondary:hover,.link-secondary:focus{color:RGBA(86, 94, 100, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(86, 94, 100, var(--bs-link-underline-opacity, 1)) !important}.link-success{color:RGBA(var(--bs-success-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-success-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-success:hover,.link-success:focus{color:RGBA(20, 108, 67, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(20, 108, 67, var(--bs-link-underline-opacity, 1)) !important}.link-info{color:RGBA(var(--bs-info-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-info-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-info:hover,.link-info:focus{color:RGBA(61, 213, 243, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(61, 213, 243, var(--bs-link-underline-opacity, 1)) !important}.link-warning{color:RGBA(var(--bs-warning-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-warning-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-warning:hover,.link-warning:focus{color:RGBA(255, 205, 57, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(255, 205, 57, var(--bs-link-underline-opacity, 1)) !important}.link-danger{color:RGBA(var(--bs-danger-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-danger-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-danger:hover,.link-danger:focus{color:RGBA(176, 42, 55, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(176, 42, 55, var(--bs-link-underline-opacity, 1)) !important}.link-light{color:RGBA(var(--bs-light-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-light-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-light:hover,.link-light:focus{color:RGBA(249, 250, 251, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(249, 250, 251, var(--bs-link-underline-opacity, 1)) !important}.link-dark{color:RGBA(var(--bs-dark-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-dark-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-dark:hover,.link-dark:focus{color:RGBA(26, 30, 33, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(26, 30, 33, var(--bs-link-underline-opacity, 1)) !important}.link-body-emphasis{color:RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-body-emphasis:hover,.link-body-emphasis:focus{color:RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-opacity, 0.75)) !important;text-decoration-color:RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-underline-opacity, 0.75)) !important}.focus-ring:focus{outline:0;box-shadow:var(--bs-focus-ring-x, 0) var(--bs-focus-ring-y, 0) var(--bs-focus-ring-blur, 0) var(--bs-focus-ring-width) var(--bs-focus-ring-color)}.icon-link{display:inline-flex;gap:.375rem;align-items:center;-webkit-align-items:center;text-decoration-color:rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 0.5));text-underline-offset:.25em;backface-visibility:hidden;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;-o-backface-visibility:hidden}.icon-link>.bi{flex-shrink:0;-webkit-flex-shrink:0;width:1em;height:1em;fill:currentcolor;transition:.2s ease-in-out transform}@media(prefers-reduced-motion: reduce){.icon-link>.bi{transition:none}}.icon-link-hover:hover>.bi,.icon-link-hover:focus-visible>.bi{transform:var(--bs-icon-link-transform, translate3d(0.25em, 0, 0))}.ratio{position:relative;width:100%}.ratio::before{display:block;padding-top:var(--bs-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--bs-aspect-ratio: 100%}.ratio-4x3{--bs-aspect-ratio: 75%}.ratio-16x9{--bs-aspect-ratio: 56.25%}.ratio-21x9{--bs-aspect-ratio: 42.8571428571%}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:sticky;top:0;z-index:1020}.sticky-bottom{position:sticky;bottom:0;z-index:1020}@media(min-width: 576px){.sticky-sm-top{position:sticky;top:0;z-index:1020}.sticky-sm-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width: 768px){.sticky-md-top{position:sticky;top:0;z-index:1020}.sticky-md-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width: 992px){.sticky-lg-top{position:sticky;top:0;z-index:1020}.sticky-lg-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width: 1200px){.sticky-xl-top{position:sticky;top:0;z-index:1020}.sticky-xl-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width: 1400px){.sticky-xxl-top{position:sticky;top:0;z-index:1020}.sticky-xxl-bottom{position:sticky;bottom:0;z-index:1020}}.hstack{display:flex;display:-webkit-flex;flex-direction:row;-webkit-flex-direction:row;align-items:center;-webkit-align-items:center;align-self:stretch;-webkit-align-self:stretch}.vstack{display:flex;display:-webkit-flex;flex:1 1 auto;-webkit-flex:1 1 auto;flex-direction:column;-webkit-flex-direction:column;align-self:stretch;-webkit-align-self:stretch}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){width:1px !important;height:1px !important;padding:0 !important;margin:-1px !important;overflow:hidden !important;clip:rect(0, 0, 0, 0) !important;white-space:nowrap !important;border:0 !important}.visually-hidden:not(caption),.visually-hidden-focusable:not(:focus):not(:focus-within):not(caption){position:absolute !important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vr{display:inline-block;align-self:stretch;-webkit-align-self:stretch;width:1px;min-height:1em;background-color:currentcolor;opacity:.25}.align-baseline{vertical-align:baseline !important}.align-top{vertical-align:top !important}.align-middle{vertical-align:middle !important}.align-bottom{vertical-align:bottom !important}.align-text-bottom{vertical-align:text-bottom !important}.align-text-top{vertical-align:text-top !important}.float-start{float:left !important}.float-end{float:right !important}.float-none{float:none !important}.object-fit-contain{object-fit:contain !important}.object-fit-cover{object-fit:cover !important}.object-fit-fill{object-fit:fill !important}.object-fit-scale{object-fit:scale-down !important}.object-fit-none{object-fit:none !important}.opacity-0{opacity:0 !important}.opacity-25{opacity:.25 !important}.opacity-50{opacity:.5 !important}.opacity-75{opacity:.75 !important}.opacity-100{opacity:1 !important}.overflow-auto{overflow:auto !important}.overflow-hidden{overflow:hidden !important}.overflow-visible{overflow:visible !important}.overflow-scroll{overflow:scroll !important}.overflow-x-auto{overflow-x:auto !important}.overflow-x-hidden{overflow-x:hidden !important}.overflow-x-visible{overflow-x:visible !important}.overflow-x-scroll{overflow-x:scroll !important}.overflow-y-auto{overflow-y:auto !important}.overflow-y-hidden{overflow-y:hidden !important}.overflow-y-visible{overflow-y:visible !important}.overflow-y-scroll{overflow-y:scroll !important}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-block{display:block !important}.d-grid{display:grid !important}.d-inline-grid{display:inline-grid !important}.d-table{display:table !important}.d-table-row{display:table-row !important}.d-table-cell{display:table-cell !important}.d-flex{display:flex !important}.d-inline-flex{display:inline-flex !important}.d-none{display:none !important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15) !important}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075) !important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175) !important}.shadow-none{box-shadow:none !important}.focus-ring-default{--bs-focus-ring-color: rgba(var(--bs-default-rgb), var(--bs-focus-ring-opacity))}.focus-ring-primary{--bs-focus-ring-color: rgba(var(--bs-primary-rgb), var(--bs-focus-ring-opacity))}.focus-ring-secondary{--bs-focus-ring-color: rgba(var(--bs-secondary-rgb), var(--bs-focus-ring-opacity))}.focus-ring-success{--bs-focus-ring-color: rgba(var(--bs-success-rgb), var(--bs-focus-ring-opacity))}.focus-ring-info{--bs-focus-ring-color: rgba(var(--bs-info-rgb), var(--bs-focus-ring-opacity))}.focus-ring-warning{--bs-focus-ring-color: rgba(var(--bs-warning-rgb), var(--bs-focus-ring-opacity))}.focus-ring-danger{--bs-focus-ring-color: rgba(var(--bs-danger-rgb), var(--bs-focus-ring-opacity))}.focus-ring-light{--bs-focus-ring-color: rgba(var(--bs-light-rgb), var(--bs-focus-ring-opacity))}.focus-ring-dark{--bs-focus-ring-color: rgba(var(--bs-dark-rgb), var(--bs-focus-ring-opacity))}.position-static{position:static !important}.position-relative{position:relative !important}.position-absolute{position:absolute !important}.position-fixed{position:fixed !important}.position-sticky{position:sticky !important}.top-0{top:0 !important}.top-50{top:50% !important}.top-100{top:100% !important}.bottom-0{bottom:0 !important}.bottom-50{bottom:50% !important}.bottom-100{bottom:100% !important}.start-0{left:0 !important}.start-50{left:50% !important}.start-100{left:100% !important}.end-0{right:0 !important}.end-50{right:50% !important}.end-100{right:100% !important}.translate-middle{transform:translate(-50%, -50%) !important}.translate-middle-x{transform:translateX(-50%) !important}.translate-middle-y{transform:translateY(-50%) !important}.border{border:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important}.border-0{border:0 !important}.border-top{border-top:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important}.border-top-0{border-top:0 !important}.border-end{border-right:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important}.border-end-0{border-right:0 !important}.border-bottom{border-bottom:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important}.border-bottom-0{border-bottom:0 !important}.border-start{border-left:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important}.border-start-0{border-left:0 !important}.border-default{--bs-border-opacity: 1;border-color:rgba(var(--bs-default-rgb), var(--bs-border-opacity)) !important}.border-primary{--bs-border-opacity: 1;border-color:rgba(var(--bs-primary-rgb), var(--bs-border-opacity)) !important}.border-secondary{--bs-border-opacity: 1;border-color:rgba(var(--bs-secondary-rgb), var(--bs-border-opacity)) !important}.border-success{--bs-border-opacity: 1;border-color:rgba(var(--bs-success-rgb), var(--bs-border-opacity)) !important}.border-info{--bs-border-opacity: 1;border-color:rgba(var(--bs-info-rgb), var(--bs-border-opacity)) !important}.border-warning{--bs-border-opacity: 1;border-color:rgba(var(--bs-warning-rgb), var(--bs-border-opacity)) !important}.border-danger{--bs-border-opacity: 1;border-color:rgba(var(--bs-danger-rgb), var(--bs-border-opacity)) !important}.border-light{--bs-border-opacity: 1;border-color:rgba(var(--bs-light-rgb), var(--bs-border-opacity)) !important}.border-dark{--bs-border-opacity: 1;border-color:rgba(var(--bs-dark-rgb), var(--bs-border-opacity)) !important}.border-black{--bs-border-opacity: 1;border-color:rgba(var(--bs-black-rgb), var(--bs-border-opacity)) !important}.border-white{--bs-border-opacity: 1;border-color:rgba(var(--bs-white-rgb), var(--bs-border-opacity)) !important}.border-primary-subtle{border-color:var(--bs-primary-border-subtle) !important}.border-secondary-subtle{border-color:var(--bs-secondary-border-subtle) !important}.border-success-subtle{border-color:var(--bs-success-border-subtle) !important}.border-info-subtle{border-color:var(--bs-info-border-subtle) !important}.border-warning-subtle{border-color:var(--bs-warning-border-subtle) !important}.border-danger-subtle{border-color:var(--bs-danger-border-subtle) !important}.border-light-subtle{border-color:var(--bs-light-border-subtle) !important}.border-dark-subtle{border-color:var(--bs-dark-border-subtle) !important}.border-1{border-width:1px !important}.border-2{border-width:2px !important}.border-3{border-width:3px !important}.border-4{border-width:4px !important}.border-5{border-width:5px !important}.border-opacity-10{--bs-border-opacity: 0.1}.border-opacity-25{--bs-border-opacity: 0.25}.border-opacity-50{--bs-border-opacity: 0.5}.border-opacity-75{--bs-border-opacity: 0.75}.border-opacity-100{--bs-border-opacity: 1}.w-25{width:25% !important}.w-50{width:50% !important}.w-75{width:75% !important}.w-100{width:100% !important}.w-auto{width:auto !important}.mw-100{max-width:100% !important}.vw-100{width:100vw !important}.min-vw-100{min-width:100vw !important}.h-25{height:25% !important}.h-50{height:50% !important}.h-75{height:75% !important}.h-100{height:100% !important}.h-auto{height:auto !important}.mh-100{max-height:100% !important}.vh-100{height:100vh !important}.min-vh-100{min-height:100vh !important}.flex-fill{flex:1 1 auto !important}.flex-row{flex-direction:row !important}.flex-column{flex-direction:column !important}.flex-row-reverse{flex-direction:row-reverse !important}.flex-column-reverse{flex-direction:column-reverse !important}.flex-grow-0{flex-grow:0 !important}.flex-grow-1{flex-grow:1 !important}.flex-shrink-0{flex-shrink:0 !important}.flex-shrink-1{flex-shrink:1 !important}.flex-wrap{flex-wrap:wrap !important}.flex-nowrap{flex-wrap:nowrap !important}.flex-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-start{justify-content:flex-start !important}.justify-content-end{justify-content:flex-end !important}.justify-content-center{justify-content:center !important}.justify-content-between{justify-content:space-between !important}.justify-content-around{justify-content:space-around !important}.justify-content-evenly{justify-content:space-evenly !important}.align-items-start{align-items:flex-start !important}.align-items-end{align-items:flex-end !important}.align-items-center{align-items:center !important}.align-items-baseline{align-items:baseline !important}.align-items-stretch{align-items:stretch !important}.align-content-start{align-content:flex-start !important}.align-content-end{align-content:flex-end !important}.align-content-center{align-content:center !important}.align-content-between{align-content:space-between !important}.align-content-around{align-content:space-around !important}.align-content-stretch{align-content:stretch !important}.align-self-auto{align-self:auto !important}.align-self-start{align-self:flex-start !important}.align-self-end{align-self:flex-end !important}.align-self-center{align-self:center !important}.align-self-baseline{align-self:baseline !important}.align-self-stretch{align-self:stretch !important}.order-first{order:-1 !important}.order-0{order:0 !important}.order-1{order:1 !important}.order-2{order:2 !important}.order-3{order:3 !important}.order-4{order:4 !important}.order-5{order:5 !important}.order-last{order:6 !important}.m-0{margin:0 !important}.m-1{margin:.25rem !important}.m-2{margin:.5rem !important}.m-3{margin:1rem !important}.m-4{margin:1.5rem !important}.m-5{margin:3rem !important}.m-auto{margin:auto !important}.mx-0{margin-right:0 !important;margin-left:0 !important}.mx-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-3{margin-right:1rem !important;margin-left:1rem !important}.mx-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-5{margin-right:3rem !important;margin-left:3rem !important}.mx-auto{margin-right:auto !important;margin-left:auto !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-0{margin-top:0 !important}.mt-1{margin-top:.25rem !important}.mt-2{margin-top:.5rem !important}.mt-3{margin-top:1rem !important}.mt-4{margin-top:1.5rem !important}.mt-5{margin-top:3rem !important}.mt-auto{margin-top:auto !important}.me-0{margin-right:0 !important}.me-1{margin-right:.25rem !important}.me-2{margin-right:.5rem !important}.me-3{margin-right:1rem !important}.me-4{margin-right:1.5rem !important}.me-5{margin-right:3rem !important}.me-auto{margin-right:auto !important}.mb-0{margin-bottom:0 !important}.mb-1{margin-bottom:.25rem !important}.mb-2{margin-bottom:.5rem !important}.mb-3{margin-bottom:1rem !important}.mb-4{margin-bottom:1.5rem !important}.mb-5{margin-bottom:3rem !important}.mb-auto{margin-bottom:auto !important}.ms-0{margin-left:0 !important}.ms-1{margin-left:.25rem !important}.ms-2{margin-left:.5rem !important}.ms-3{margin-left:1rem !important}.ms-4{margin-left:1.5rem !important}.ms-5{margin-left:3rem !important}.ms-auto{margin-left:auto !important}.p-0{padding:0 !important}.p-1{padding:.25rem !important}.p-2{padding:.5rem !important}.p-3{padding:1rem !important}.p-4{padding:1.5rem !important}.p-5{padding:3rem !important}.px-0{padding-right:0 !important;padding-left:0 !important}.px-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-3{padding-right:1rem !important;padding-left:1rem !important}.px-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-5{padding-right:3rem !important;padding-left:3rem !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-0{padding-top:0 !important}.pt-1{padding-top:.25rem !important}.pt-2{padding-top:.5rem !important}.pt-3{padding-top:1rem !important}.pt-4{padding-top:1.5rem !important}.pt-5{padding-top:3rem !important}.pe-0{padding-right:0 !important}.pe-1{padding-right:.25rem !important}.pe-2{padding-right:.5rem !important}.pe-3{padding-right:1rem !important}.pe-4{padding-right:1.5rem !important}.pe-5{padding-right:3rem !important}.pb-0{padding-bottom:0 !important}.pb-1{padding-bottom:.25rem !important}.pb-2{padding-bottom:.5rem !important}.pb-3{padding-bottom:1rem !important}.pb-4{padding-bottom:1.5rem !important}.pb-5{padding-bottom:3rem !important}.ps-0{padding-left:0 !important}.ps-1{padding-left:.25rem !important}.ps-2{padding-left:.5rem !important}.ps-3{padding-left:1rem !important}.ps-4{padding-left:1.5rem !important}.ps-5{padding-left:3rem !important}.gap-0{gap:0 !important}.gap-1{gap:.25rem !important}.gap-2{gap:.5rem !important}.gap-3{gap:1rem !important}.gap-4{gap:1.5rem !important}.gap-5{gap:3rem !important}.row-gap-0{row-gap:0 !important}.row-gap-1{row-gap:.25rem !important}.row-gap-2{row-gap:.5rem !important}.row-gap-3{row-gap:1rem !important}.row-gap-4{row-gap:1.5rem !important}.row-gap-5{row-gap:3rem !important}.column-gap-0{column-gap:0 !important}.column-gap-1{column-gap:.25rem !important}.column-gap-2{column-gap:.5rem !important}.column-gap-3{column-gap:1rem !important}.column-gap-4{column-gap:1.5rem !important}.column-gap-5{column-gap:3rem !important}.font-monospace{font-family:var(--bs-font-monospace) !important}.fs-1{font-size:calc(1.325rem + 0.9vw) !important}.fs-2{font-size:calc(1.29rem + 0.48vw) !important}.fs-3{font-size:calc(1.27rem + 0.24vw) !important}.fs-4{font-size:1.25rem !important}.fs-5{font-size:1.1rem !important}.fs-6{font-size:1rem !important}.fst-italic{font-style:italic !important}.fst-normal{font-style:normal !important}.fw-lighter{font-weight:lighter !important}.fw-light{font-weight:300 !important}.fw-normal{font-weight:400 !important}.fw-medium{font-weight:500 !important}.fw-semibold{font-weight:600 !important}.fw-bold{font-weight:700 !important}.fw-bolder{font-weight:bolder !important}.lh-1{line-height:1 !important}.lh-sm{line-height:1.25 !important}.lh-base{line-height:1.5 !important}.lh-lg{line-height:2 !important}.text-start{text-align:left !important}.text-end{text-align:right !important}.text-center{text-align:center !important}.text-decoration-none{text-decoration:none !important}.text-decoration-underline{text-decoration:underline !important}.text-decoration-line-through{text-decoration:line-through !important}.text-lowercase{text-transform:lowercase !important}.text-uppercase{text-transform:uppercase !important}.text-capitalize{text-transform:capitalize !important}.text-wrap{white-space:normal !important}.text-nowrap{white-space:nowrap !important}.text-break{word-wrap:break-word !important;word-break:break-word !important}.text-default{--bs-text-opacity: 1;color:rgba(var(--bs-default-rgb), var(--bs-text-opacity)) !important}.text-primary{--bs-text-opacity: 1;color:rgba(var(--bs-primary-rgb), var(--bs-text-opacity)) !important}.text-secondary{--bs-text-opacity: 1;color:rgba(var(--bs-secondary-rgb), var(--bs-text-opacity)) !important}.text-success{--bs-text-opacity: 1;color:rgba(var(--bs-success-rgb), var(--bs-text-opacity)) !important}.text-info{--bs-text-opacity: 1;color:rgba(var(--bs-info-rgb), var(--bs-text-opacity)) !important}.text-warning{--bs-text-opacity: 1;color:rgba(var(--bs-warning-rgb), var(--bs-text-opacity)) !important}.text-danger{--bs-text-opacity: 1;color:rgba(var(--bs-danger-rgb), var(--bs-text-opacity)) !important}.text-light{--bs-text-opacity: 1;color:rgba(var(--bs-light-rgb), var(--bs-text-opacity)) !important}.text-dark{--bs-text-opacity: 1;color:rgba(var(--bs-dark-rgb), var(--bs-text-opacity)) !important}.text-black{--bs-text-opacity: 1;color:rgba(var(--bs-black-rgb), var(--bs-text-opacity)) !important}.text-white{--bs-text-opacity: 1;color:rgba(var(--bs-white-rgb), var(--bs-text-opacity)) !important}.text-body{--bs-text-opacity: 1;color:rgba(var(--bs-body-color-rgb), var(--bs-text-opacity)) !important}.text-muted{--bs-text-opacity: 1;color:var(--bs-secondary-color) !important}.text-black-50{--bs-text-opacity: 1;color:rgba(0,0,0,.5) !important}.text-white-50{--bs-text-opacity: 1;color:rgba(255,255,255,.5) !important}.text-body-secondary{--bs-text-opacity: 1;color:var(--bs-secondary-color) !important}.text-body-tertiary{--bs-text-opacity: 1;color:var(--bs-tertiary-color) !important}.text-body-emphasis{--bs-text-opacity: 1;color:var(--bs-emphasis-color) !important}.text-reset{--bs-text-opacity: 1;color:inherit !important}.text-opacity-25{--bs-text-opacity: 0.25}.text-opacity-50{--bs-text-opacity: 0.5}.text-opacity-75{--bs-text-opacity: 0.75}.text-opacity-100{--bs-text-opacity: 1}.text-primary-emphasis{color:var(--bs-primary-text-emphasis) !important}.text-secondary-emphasis{color:var(--bs-secondary-text-emphasis) !important}.text-success-emphasis{color:var(--bs-success-text-emphasis) !important}.text-info-emphasis{color:var(--bs-info-text-emphasis) !important}.text-warning-emphasis{color:var(--bs-warning-text-emphasis) !important}.text-danger-emphasis{color:var(--bs-danger-text-emphasis) !important}.text-light-emphasis{color:var(--bs-light-text-emphasis) !important}.text-dark-emphasis{color:var(--bs-dark-text-emphasis) !important}.link-opacity-10{--bs-link-opacity: 0.1}.link-opacity-10-hover:hover{--bs-link-opacity: 0.1}.link-opacity-25{--bs-link-opacity: 0.25}.link-opacity-25-hover:hover{--bs-link-opacity: 0.25}.link-opacity-50{--bs-link-opacity: 0.5}.link-opacity-50-hover:hover{--bs-link-opacity: 0.5}.link-opacity-75{--bs-link-opacity: 0.75}.link-opacity-75-hover:hover{--bs-link-opacity: 0.75}.link-opacity-100{--bs-link-opacity: 1}.link-opacity-100-hover:hover{--bs-link-opacity: 1}.link-offset-1{text-underline-offset:.125em !important}.link-offset-1-hover:hover{text-underline-offset:.125em !important}.link-offset-2{text-underline-offset:.25em !important}.link-offset-2-hover:hover{text-underline-offset:.25em !important}.link-offset-3{text-underline-offset:.375em !important}.link-offset-3-hover:hover{text-underline-offset:.375em !important}.link-underline-default{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-default-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-primary{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-primary-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-secondary{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-secondary-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-success{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-success-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-info{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-info-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-warning{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-warning-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-danger{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-danger-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-light{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-light-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-dark{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-dark-rgb), var(--bs-link-underline-opacity)) !important}.link-underline{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-link-color-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-underline-opacity-0{--bs-link-underline-opacity: 0}.link-underline-opacity-0-hover:hover{--bs-link-underline-opacity: 0}.link-underline-opacity-10{--bs-link-underline-opacity: 0.1}.link-underline-opacity-10-hover:hover{--bs-link-underline-opacity: 0.1}.link-underline-opacity-25{--bs-link-underline-opacity: 0.25}.link-underline-opacity-25-hover:hover{--bs-link-underline-opacity: 0.25}.link-underline-opacity-50{--bs-link-underline-opacity: 0.5}.link-underline-opacity-50-hover:hover{--bs-link-underline-opacity: 0.5}.link-underline-opacity-75{--bs-link-underline-opacity: 0.75}.link-underline-opacity-75-hover:hover{--bs-link-underline-opacity: 0.75}.link-underline-opacity-100{--bs-link-underline-opacity: 1}.link-underline-opacity-100-hover:hover{--bs-link-underline-opacity: 1}.bg-default{--bs-bg-opacity: 1;background-color:rgba(var(--bs-default-rgb), var(--bs-bg-opacity)) !important}.bg-primary{--bs-bg-opacity: 1;background-color:rgba(var(--bs-primary-rgb), var(--bs-bg-opacity)) !important}.bg-secondary{--bs-bg-opacity: 1;background-color:rgba(var(--bs-secondary-rgb), var(--bs-bg-opacity)) !important}.bg-success{--bs-bg-opacity: 1;background-color:rgba(var(--bs-success-rgb), var(--bs-bg-opacity)) !important}.bg-info{--bs-bg-opacity: 1;background-color:rgba(var(--bs-info-rgb), var(--bs-bg-opacity)) !important}.bg-warning{--bs-bg-opacity: 1;background-color:rgba(var(--bs-warning-rgb), var(--bs-bg-opacity)) !important}.bg-danger{--bs-bg-opacity: 1;background-color:rgba(var(--bs-danger-rgb), var(--bs-bg-opacity)) !important}.bg-light{--bs-bg-opacity: 1;background-color:rgba(var(--bs-light-rgb), var(--bs-bg-opacity)) !important}.bg-dark{--bs-bg-opacity: 1;background-color:rgba(var(--bs-dark-rgb), var(--bs-bg-opacity)) !important}.bg-black{--bs-bg-opacity: 1;background-color:rgba(var(--bs-black-rgb), var(--bs-bg-opacity)) !important}.bg-white{--bs-bg-opacity: 1;background-color:rgba(var(--bs-white-rgb), var(--bs-bg-opacity)) !important}.bg-body{--bs-bg-opacity: 1;background-color:rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important}.bg-transparent{--bs-bg-opacity: 1;background-color:rgba(0,0,0,0) !important}.bg-body-secondary{--bs-bg-opacity: 1;background-color:rgba(var(--bs-secondary-bg-rgb), var(--bs-bg-opacity)) !important}.bg-body-tertiary{--bs-bg-opacity: 1;background-color:rgba(var(--bs-tertiary-bg-rgb), var(--bs-bg-opacity)) !important}.bg-opacity-10{--bs-bg-opacity: 0.1}.bg-opacity-25{--bs-bg-opacity: 0.25}.bg-opacity-50{--bs-bg-opacity: 0.5}.bg-opacity-75{--bs-bg-opacity: 0.75}.bg-opacity-100{--bs-bg-opacity: 1}.bg-primary-subtle{background-color:var(--bs-primary-bg-subtle) !important}.bg-secondary-subtle{background-color:var(--bs-secondary-bg-subtle) !important}.bg-success-subtle{background-color:var(--bs-success-bg-subtle) !important}.bg-info-subtle{background-color:var(--bs-info-bg-subtle) !important}.bg-warning-subtle{background-color:var(--bs-warning-bg-subtle) !important}.bg-danger-subtle{background-color:var(--bs-danger-bg-subtle) !important}.bg-light-subtle{background-color:var(--bs-light-bg-subtle) !important}.bg-dark-subtle{background-color:var(--bs-dark-bg-subtle) !important}.bg-gradient{background-image:var(--bs-gradient) !important}.user-select-all{user-select:all !important}.user-select-auto{user-select:auto !important}.user-select-none{user-select:none !important}.pe-none{pointer-events:none !important}.pe-auto{pointer-events:auto !important}.rounded{border-radius:var(--bs-border-radius) !important}.rounded-0{border-radius:0 !important}.rounded-1{border-radius:var(--bs-border-radius-sm) !important}.rounded-2{border-radius:var(--bs-border-radius) !important}.rounded-3{border-radius:var(--bs-border-radius-lg) !important}.rounded-4{border-radius:var(--bs-border-radius-xl) !important}.rounded-5{border-radius:var(--bs-border-radius-xxl) !important}.rounded-circle{border-radius:50% !important}.rounded-pill{border-radius:var(--bs-border-radius-pill) !important}.rounded-top{border-top-left-radius:var(--bs-border-radius) !important;border-top-right-radius:var(--bs-border-radius) !important}.rounded-top-0{border-top-left-radius:0 !important;border-top-right-radius:0 !important}.rounded-top-1{border-top-left-radius:var(--bs-border-radius-sm) !important;border-top-right-radius:var(--bs-border-radius-sm) !important}.rounded-top-2{border-top-left-radius:var(--bs-border-radius) !important;border-top-right-radius:var(--bs-border-radius) !important}.rounded-top-3{border-top-left-radius:var(--bs-border-radius-lg) !important;border-top-right-radius:var(--bs-border-radius-lg) !important}.rounded-top-4{border-top-left-radius:var(--bs-border-radius-xl) !important;border-top-right-radius:var(--bs-border-radius-xl) !important}.rounded-top-5{border-top-left-radius:var(--bs-border-radius-xxl) !important;border-top-right-radius:var(--bs-border-radius-xxl) !important}.rounded-top-circle{border-top-left-radius:50% !important;border-top-right-radius:50% !important}.rounded-top-pill{border-top-left-radius:var(--bs-border-radius-pill) !important;border-top-right-radius:var(--bs-border-radius-pill) !important}.rounded-end{border-top-right-radius:var(--bs-border-radius) !important;border-bottom-right-radius:var(--bs-border-radius) !important}.rounded-end-0{border-top-right-radius:0 !important;border-bottom-right-radius:0 !important}.rounded-end-1{border-top-right-radius:var(--bs-border-radius-sm) !important;border-bottom-right-radius:var(--bs-border-radius-sm) !important}.rounded-end-2{border-top-right-radius:var(--bs-border-radius) !important;border-bottom-right-radius:var(--bs-border-radius) !important}.rounded-end-3{border-top-right-radius:var(--bs-border-radius-lg) !important;border-bottom-right-radius:var(--bs-border-radius-lg) !important}.rounded-end-4{border-top-right-radius:var(--bs-border-radius-xl) !important;border-bottom-right-radius:var(--bs-border-radius-xl) !important}.rounded-end-5{border-top-right-radius:var(--bs-border-radius-xxl) !important;border-bottom-right-radius:var(--bs-border-radius-xxl) !important}.rounded-end-circle{border-top-right-radius:50% !important;border-bottom-right-radius:50% !important}.rounded-end-pill{border-top-right-radius:var(--bs-border-radius-pill) !important;border-bottom-right-radius:var(--bs-border-radius-pill) !important}.rounded-bottom{border-bottom-right-radius:var(--bs-border-radius) !important;border-bottom-left-radius:var(--bs-border-radius) !important}.rounded-bottom-0{border-bottom-right-radius:0 !important;border-bottom-left-radius:0 !important}.rounded-bottom-1{border-bottom-right-radius:var(--bs-border-radius-sm) !important;border-bottom-left-radius:var(--bs-border-radius-sm) !important}.rounded-bottom-2{border-bottom-right-radius:var(--bs-border-radius) !important;border-bottom-left-radius:var(--bs-border-radius) !important}.rounded-bottom-3{border-bottom-right-radius:var(--bs-border-radius-lg) !important;border-bottom-left-radius:var(--bs-border-radius-lg) !important}.rounded-bottom-4{border-bottom-right-radius:var(--bs-border-radius-xl) !important;border-bottom-left-radius:var(--bs-border-radius-xl) !important}.rounded-bottom-5{border-bottom-right-radius:var(--bs-border-radius-xxl) !important;border-bottom-left-radius:var(--bs-border-radius-xxl) !important}.rounded-bottom-circle{border-bottom-right-radius:50% !important;border-bottom-left-radius:50% !important}.rounded-bottom-pill{border-bottom-right-radius:var(--bs-border-radius-pill) !important;border-bottom-left-radius:var(--bs-border-radius-pill) !important}.rounded-start{border-bottom-left-radius:var(--bs-border-radius) !important;border-top-left-radius:var(--bs-border-radius) !important}.rounded-start-0{border-bottom-left-radius:0 !important;border-top-left-radius:0 !important}.rounded-start-1{border-bottom-left-radius:var(--bs-border-radius-sm) !important;border-top-left-radius:var(--bs-border-radius-sm) !important}.rounded-start-2{border-bottom-left-radius:var(--bs-border-radius) !important;border-top-left-radius:var(--bs-border-radius) !important}.rounded-start-3{border-bottom-left-radius:var(--bs-border-radius-lg) !important;border-top-left-radius:var(--bs-border-radius-lg) !important}.rounded-start-4{border-bottom-left-radius:var(--bs-border-radius-xl) !important;border-top-left-radius:var(--bs-border-radius-xl) !important}.rounded-start-5{border-bottom-left-radius:var(--bs-border-radius-xxl) !important;border-top-left-radius:var(--bs-border-radius-xxl) !important}.rounded-start-circle{border-bottom-left-radius:50% !important;border-top-left-radius:50% !important}.rounded-start-pill{border-bottom-left-radius:var(--bs-border-radius-pill) !important;border-top-left-radius:var(--bs-border-radius-pill) !important}.visible{visibility:visible !important}.invisible{visibility:hidden !important}.z-n1{z-index:-1 !important}.z-0{z-index:0 !important}.z-1{z-index:1 !important}.z-2{z-index:2 !important}.z-3{z-index:3 !important}@media(min-width: 576px){.float-sm-start{float:left !important}.float-sm-end{float:right !important}.float-sm-none{float:none !important}.object-fit-sm-contain{object-fit:contain !important}.object-fit-sm-cover{object-fit:cover !important}.object-fit-sm-fill{object-fit:fill !important}.object-fit-sm-scale{object-fit:scale-down !important}.object-fit-sm-none{object-fit:none !important}.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-block{display:block !important}.d-sm-grid{display:grid !important}.d-sm-inline-grid{display:inline-grid !important}.d-sm-table{display:table !important}.d-sm-table-row{display:table-row !important}.d-sm-table-cell{display:table-cell !important}.d-sm-flex{display:flex !important}.d-sm-inline-flex{display:inline-flex !important}.d-sm-none{display:none !important}.flex-sm-fill{flex:1 1 auto !important}.flex-sm-row{flex-direction:row !important}.flex-sm-column{flex-direction:column !important}.flex-sm-row-reverse{flex-direction:row-reverse !important}.flex-sm-column-reverse{flex-direction:column-reverse !important}.flex-sm-grow-0{flex-grow:0 !important}.flex-sm-grow-1{flex-grow:1 !important}.flex-sm-shrink-0{flex-shrink:0 !important}.flex-sm-shrink-1{flex-shrink:1 !important}.flex-sm-wrap{flex-wrap:wrap !important}.flex-sm-nowrap{flex-wrap:nowrap !important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-sm-start{justify-content:flex-start !important}.justify-content-sm-end{justify-content:flex-end !important}.justify-content-sm-center{justify-content:center !important}.justify-content-sm-between{justify-content:space-between !important}.justify-content-sm-around{justify-content:space-around !important}.justify-content-sm-evenly{justify-content:space-evenly !important}.align-items-sm-start{align-items:flex-start !important}.align-items-sm-end{align-items:flex-end !important}.align-items-sm-center{align-items:center !important}.align-items-sm-baseline{align-items:baseline !important}.align-items-sm-stretch{align-items:stretch !important}.align-content-sm-start{align-content:flex-start !important}.align-content-sm-end{align-content:flex-end !important}.align-content-sm-center{align-content:center !important}.align-content-sm-between{align-content:space-between !important}.align-content-sm-around{align-content:space-around !important}.align-content-sm-stretch{align-content:stretch !important}.align-self-sm-auto{align-self:auto !important}.align-self-sm-start{align-self:flex-start !important}.align-self-sm-end{align-self:flex-end !important}.align-self-sm-center{align-self:center !important}.align-self-sm-baseline{align-self:baseline !important}.align-self-sm-stretch{align-self:stretch !important}.order-sm-first{order:-1 !important}.order-sm-0{order:0 !important}.order-sm-1{order:1 !important}.order-sm-2{order:2 !important}.order-sm-3{order:3 !important}.order-sm-4{order:4 !important}.order-sm-5{order:5 !important}.order-sm-last{order:6 !important}.m-sm-0{margin:0 !important}.m-sm-1{margin:.25rem !important}.m-sm-2{margin:.5rem !important}.m-sm-3{margin:1rem !important}.m-sm-4{margin:1.5rem !important}.m-sm-5{margin:3rem !important}.m-sm-auto{margin:auto !important}.mx-sm-0{margin-right:0 !important;margin-left:0 !important}.mx-sm-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-sm-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-sm-3{margin-right:1rem !important;margin-left:1rem !important}.mx-sm-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-sm-5{margin-right:3rem !important;margin-left:3rem !important}.mx-sm-auto{margin-right:auto !important;margin-left:auto !important}.my-sm-0{margin-top:0 !important;margin-bottom:0 !important}.my-sm-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-sm-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-sm-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-sm-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-sm-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-sm-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-sm-0{margin-top:0 !important}.mt-sm-1{margin-top:.25rem !important}.mt-sm-2{margin-top:.5rem !important}.mt-sm-3{margin-top:1rem !important}.mt-sm-4{margin-top:1.5rem !important}.mt-sm-5{margin-top:3rem !important}.mt-sm-auto{margin-top:auto !important}.me-sm-0{margin-right:0 !important}.me-sm-1{margin-right:.25rem !important}.me-sm-2{margin-right:.5rem !important}.me-sm-3{margin-right:1rem !important}.me-sm-4{margin-right:1.5rem !important}.me-sm-5{margin-right:3rem !important}.me-sm-auto{margin-right:auto !important}.mb-sm-0{margin-bottom:0 !important}.mb-sm-1{margin-bottom:.25rem !important}.mb-sm-2{margin-bottom:.5rem !important}.mb-sm-3{margin-bottom:1rem !important}.mb-sm-4{margin-bottom:1.5rem !important}.mb-sm-5{margin-bottom:3rem !important}.mb-sm-auto{margin-bottom:auto !important}.ms-sm-0{margin-left:0 !important}.ms-sm-1{margin-left:.25rem !important}.ms-sm-2{margin-left:.5rem !important}.ms-sm-3{margin-left:1rem !important}.ms-sm-4{margin-left:1.5rem !important}.ms-sm-5{margin-left:3rem !important}.ms-sm-auto{margin-left:auto !important}.p-sm-0{padding:0 !important}.p-sm-1{padding:.25rem !important}.p-sm-2{padding:.5rem !important}.p-sm-3{padding:1rem !important}.p-sm-4{padding:1.5rem !important}.p-sm-5{padding:3rem !important}.px-sm-0{padding-right:0 !important;padding-left:0 !important}.px-sm-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-sm-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-sm-3{padding-right:1rem !important;padding-left:1rem !important}.px-sm-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-sm-5{padding-right:3rem !important;padding-left:3rem !important}.py-sm-0{padding-top:0 !important;padding-bottom:0 !important}.py-sm-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-sm-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-sm-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-sm-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-sm-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-sm-0{padding-top:0 !important}.pt-sm-1{padding-top:.25rem !important}.pt-sm-2{padding-top:.5rem !important}.pt-sm-3{padding-top:1rem !important}.pt-sm-4{padding-top:1.5rem !important}.pt-sm-5{padding-top:3rem !important}.pe-sm-0{padding-right:0 !important}.pe-sm-1{padding-right:.25rem !important}.pe-sm-2{padding-right:.5rem !important}.pe-sm-3{padding-right:1rem !important}.pe-sm-4{padding-right:1.5rem !important}.pe-sm-5{padding-right:3rem !important}.pb-sm-0{padding-bottom:0 !important}.pb-sm-1{padding-bottom:.25rem !important}.pb-sm-2{padding-bottom:.5rem !important}.pb-sm-3{padding-bottom:1rem !important}.pb-sm-4{padding-bottom:1.5rem !important}.pb-sm-5{padding-bottom:3rem !important}.ps-sm-0{padding-left:0 !important}.ps-sm-1{padding-left:.25rem !important}.ps-sm-2{padding-left:.5rem !important}.ps-sm-3{padding-left:1rem !important}.ps-sm-4{padding-left:1.5rem !important}.ps-sm-5{padding-left:3rem !important}.gap-sm-0{gap:0 !important}.gap-sm-1{gap:.25rem !important}.gap-sm-2{gap:.5rem !important}.gap-sm-3{gap:1rem !important}.gap-sm-4{gap:1.5rem !important}.gap-sm-5{gap:3rem !important}.row-gap-sm-0{row-gap:0 !important}.row-gap-sm-1{row-gap:.25rem !important}.row-gap-sm-2{row-gap:.5rem !important}.row-gap-sm-3{row-gap:1rem !important}.row-gap-sm-4{row-gap:1.5rem !important}.row-gap-sm-5{row-gap:3rem !important}.column-gap-sm-0{column-gap:0 !important}.column-gap-sm-1{column-gap:.25rem !important}.column-gap-sm-2{column-gap:.5rem !important}.column-gap-sm-3{column-gap:1rem !important}.column-gap-sm-4{column-gap:1.5rem !important}.column-gap-sm-5{column-gap:3rem !important}.text-sm-start{text-align:left !important}.text-sm-end{text-align:right !important}.text-sm-center{text-align:center !important}}@media(min-width: 768px){.float-md-start{float:left !important}.float-md-end{float:right !important}.float-md-none{float:none !important}.object-fit-md-contain{object-fit:contain !important}.object-fit-md-cover{object-fit:cover !important}.object-fit-md-fill{object-fit:fill !important}.object-fit-md-scale{object-fit:scale-down !important}.object-fit-md-none{object-fit:none !important}.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-block{display:block !important}.d-md-grid{display:grid !important}.d-md-inline-grid{display:inline-grid !important}.d-md-table{display:table !important}.d-md-table-row{display:table-row !important}.d-md-table-cell{display:table-cell !important}.d-md-flex{display:flex !important}.d-md-inline-flex{display:inline-flex !important}.d-md-none{display:none !important}.flex-md-fill{flex:1 1 auto !important}.flex-md-row{flex-direction:row !important}.flex-md-column{flex-direction:column !important}.flex-md-row-reverse{flex-direction:row-reverse !important}.flex-md-column-reverse{flex-direction:column-reverse !important}.flex-md-grow-0{flex-grow:0 !important}.flex-md-grow-1{flex-grow:1 !important}.flex-md-shrink-0{flex-shrink:0 !important}.flex-md-shrink-1{flex-shrink:1 !important}.flex-md-wrap{flex-wrap:wrap !important}.flex-md-nowrap{flex-wrap:nowrap !important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-md-start{justify-content:flex-start !important}.justify-content-md-end{justify-content:flex-end !important}.justify-content-md-center{justify-content:center !important}.justify-content-md-between{justify-content:space-between !important}.justify-content-md-around{justify-content:space-around !important}.justify-content-md-evenly{justify-content:space-evenly !important}.align-items-md-start{align-items:flex-start !important}.align-items-md-end{align-items:flex-end !important}.align-items-md-center{align-items:center !important}.align-items-md-baseline{align-items:baseline !important}.align-items-md-stretch{align-items:stretch !important}.align-content-md-start{align-content:flex-start !important}.align-content-md-end{align-content:flex-end !important}.align-content-md-center{align-content:center !important}.align-content-md-between{align-content:space-between !important}.align-content-md-around{align-content:space-around !important}.align-content-md-stretch{align-content:stretch !important}.align-self-md-auto{align-self:auto !important}.align-self-md-start{align-self:flex-start !important}.align-self-md-end{align-self:flex-end !important}.align-self-md-center{align-self:center !important}.align-self-md-baseline{align-self:baseline !important}.align-self-md-stretch{align-self:stretch !important}.order-md-first{order:-1 !important}.order-md-0{order:0 !important}.order-md-1{order:1 !important}.order-md-2{order:2 !important}.order-md-3{order:3 !important}.order-md-4{order:4 !important}.order-md-5{order:5 !important}.order-md-last{order:6 !important}.m-md-0{margin:0 !important}.m-md-1{margin:.25rem !important}.m-md-2{margin:.5rem !important}.m-md-3{margin:1rem !important}.m-md-4{margin:1.5rem !important}.m-md-5{margin:3rem !important}.m-md-auto{margin:auto !important}.mx-md-0{margin-right:0 !important;margin-left:0 !important}.mx-md-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-md-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-md-3{margin-right:1rem !important;margin-left:1rem !important}.mx-md-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-md-5{margin-right:3rem !important;margin-left:3rem !important}.mx-md-auto{margin-right:auto !important;margin-left:auto !important}.my-md-0{margin-top:0 !important;margin-bottom:0 !important}.my-md-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-md-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-md-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-md-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-md-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-md-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-md-0{margin-top:0 !important}.mt-md-1{margin-top:.25rem !important}.mt-md-2{margin-top:.5rem !important}.mt-md-3{margin-top:1rem !important}.mt-md-4{margin-top:1.5rem !important}.mt-md-5{margin-top:3rem !important}.mt-md-auto{margin-top:auto !important}.me-md-0{margin-right:0 !important}.me-md-1{margin-right:.25rem !important}.me-md-2{margin-right:.5rem !important}.me-md-3{margin-right:1rem !important}.me-md-4{margin-right:1.5rem !important}.me-md-5{margin-right:3rem !important}.me-md-auto{margin-right:auto !important}.mb-md-0{margin-bottom:0 !important}.mb-md-1{margin-bottom:.25rem !important}.mb-md-2{margin-bottom:.5rem !important}.mb-md-3{margin-bottom:1rem !important}.mb-md-4{margin-bottom:1.5rem !important}.mb-md-5{margin-bottom:3rem !important}.mb-md-auto{margin-bottom:auto !important}.ms-md-0{margin-left:0 !important}.ms-md-1{margin-left:.25rem !important}.ms-md-2{margin-left:.5rem !important}.ms-md-3{margin-left:1rem !important}.ms-md-4{margin-left:1.5rem !important}.ms-md-5{margin-left:3rem !important}.ms-md-auto{margin-left:auto !important}.p-md-0{padding:0 !important}.p-md-1{padding:.25rem !important}.p-md-2{padding:.5rem !important}.p-md-3{padding:1rem !important}.p-md-4{padding:1.5rem !important}.p-md-5{padding:3rem !important}.px-md-0{padding-right:0 !important;padding-left:0 !important}.px-md-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-md-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-md-3{padding-right:1rem !important;padding-left:1rem !important}.px-md-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-md-5{padding-right:3rem !important;padding-left:3rem !important}.py-md-0{padding-top:0 !important;padding-bottom:0 !important}.py-md-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-md-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-md-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-md-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-md-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-md-0{padding-top:0 !important}.pt-md-1{padding-top:.25rem !important}.pt-md-2{padding-top:.5rem !important}.pt-md-3{padding-top:1rem !important}.pt-md-4{padding-top:1.5rem !important}.pt-md-5{padding-top:3rem !important}.pe-md-0{padding-right:0 !important}.pe-md-1{padding-right:.25rem !important}.pe-md-2{padding-right:.5rem !important}.pe-md-3{padding-right:1rem !important}.pe-md-4{padding-right:1.5rem !important}.pe-md-5{padding-right:3rem !important}.pb-md-0{padding-bottom:0 !important}.pb-md-1{padding-bottom:.25rem !important}.pb-md-2{padding-bottom:.5rem !important}.pb-md-3{padding-bottom:1rem !important}.pb-md-4{padding-bottom:1.5rem !important}.pb-md-5{padding-bottom:3rem !important}.ps-md-0{padding-left:0 !important}.ps-md-1{padding-left:.25rem !important}.ps-md-2{padding-left:.5rem !important}.ps-md-3{padding-left:1rem !important}.ps-md-4{padding-left:1.5rem !important}.ps-md-5{padding-left:3rem !important}.gap-md-0{gap:0 !important}.gap-md-1{gap:.25rem !important}.gap-md-2{gap:.5rem !important}.gap-md-3{gap:1rem !important}.gap-md-4{gap:1.5rem !important}.gap-md-5{gap:3rem !important}.row-gap-md-0{row-gap:0 !important}.row-gap-md-1{row-gap:.25rem !important}.row-gap-md-2{row-gap:.5rem !important}.row-gap-md-3{row-gap:1rem !important}.row-gap-md-4{row-gap:1.5rem !important}.row-gap-md-5{row-gap:3rem !important}.column-gap-md-0{column-gap:0 !important}.column-gap-md-1{column-gap:.25rem !important}.column-gap-md-2{column-gap:.5rem !important}.column-gap-md-3{column-gap:1rem !important}.column-gap-md-4{column-gap:1.5rem !important}.column-gap-md-5{column-gap:3rem !important}.text-md-start{text-align:left !important}.text-md-end{text-align:right !important}.text-md-center{text-align:center !important}}@media(min-width: 992px){.float-lg-start{float:left !important}.float-lg-end{float:right !important}.float-lg-none{float:none !important}.object-fit-lg-contain{object-fit:contain !important}.object-fit-lg-cover{object-fit:cover !important}.object-fit-lg-fill{object-fit:fill !important}.object-fit-lg-scale{object-fit:scale-down !important}.object-fit-lg-none{object-fit:none !important}.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-block{display:block !important}.d-lg-grid{display:grid !important}.d-lg-inline-grid{display:inline-grid !important}.d-lg-table{display:table !important}.d-lg-table-row{display:table-row !important}.d-lg-table-cell{display:table-cell !important}.d-lg-flex{display:flex !important}.d-lg-inline-flex{display:inline-flex !important}.d-lg-none{display:none !important}.flex-lg-fill{flex:1 1 auto !important}.flex-lg-row{flex-direction:row !important}.flex-lg-column{flex-direction:column !important}.flex-lg-row-reverse{flex-direction:row-reverse !important}.flex-lg-column-reverse{flex-direction:column-reverse !important}.flex-lg-grow-0{flex-grow:0 !important}.flex-lg-grow-1{flex-grow:1 !important}.flex-lg-shrink-0{flex-shrink:0 !important}.flex-lg-shrink-1{flex-shrink:1 !important}.flex-lg-wrap{flex-wrap:wrap !important}.flex-lg-nowrap{flex-wrap:nowrap !important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-lg-start{justify-content:flex-start !important}.justify-content-lg-end{justify-content:flex-end !important}.justify-content-lg-center{justify-content:center !important}.justify-content-lg-between{justify-content:space-between !important}.justify-content-lg-around{justify-content:space-around !important}.justify-content-lg-evenly{justify-content:space-evenly !important}.align-items-lg-start{align-items:flex-start !important}.align-items-lg-end{align-items:flex-end !important}.align-items-lg-center{align-items:center !important}.align-items-lg-baseline{align-items:baseline !important}.align-items-lg-stretch{align-items:stretch !important}.align-content-lg-start{align-content:flex-start !important}.align-content-lg-end{align-content:flex-end !important}.align-content-lg-center{align-content:center !important}.align-content-lg-between{align-content:space-between !important}.align-content-lg-around{align-content:space-around !important}.align-content-lg-stretch{align-content:stretch !important}.align-self-lg-auto{align-self:auto !important}.align-self-lg-start{align-self:flex-start !important}.align-self-lg-end{align-self:flex-end !important}.align-self-lg-center{align-self:center !important}.align-self-lg-baseline{align-self:baseline !important}.align-self-lg-stretch{align-self:stretch !important}.order-lg-first{order:-1 !important}.order-lg-0{order:0 !important}.order-lg-1{order:1 !important}.order-lg-2{order:2 !important}.order-lg-3{order:3 !important}.order-lg-4{order:4 !important}.order-lg-5{order:5 !important}.order-lg-last{order:6 !important}.m-lg-0{margin:0 !important}.m-lg-1{margin:.25rem !important}.m-lg-2{margin:.5rem !important}.m-lg-3{margin:1rem !important}.m-lg-4{margin:1.5rem !important}.m-lg-5{margin:3rem !important}.m-lg-auto{margin:auto !important}.mx-lg-0{margin-right:0 !important;margin-left:0 !important}.mx-lg-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-lg-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-lg-3{margin-right:1rem !important;margin-left:1rem !important}.mx-lg-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-lg-5{margin-right:3rem !important;margin-left:3rem !important}.mx-lg-auto{margin-right:auto !important;margin-left:auto !important}.my-lg-0{margin-top:0 !important;margin-bottom:0 !important}.my-lg-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-lg-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-lg-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-lg-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-lg-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-lg-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-lg-0{margin-top:0 !important}.mt-lg-1{margin-top:.25rem !important}.mt-lg-2{margin-top:.5rem !important}.mt-lg-3{margin-top:1rem !important}.mt-lg-4{margin-top:1.5rem !important}.mt-lg-5{margin-top:3rem !important}.mt-lg-auto{margin-top:auto !important}.me-lg-0{margin-right:0 !important}.me-lg-1{margin-right:.25rem !important}.me-lg-2{margin-right:.5rem !important}.me-lg-3{margin-right:1rem !important}.me-lg-4{margin-right:1.5rem !important}.me-lg-5{margin-right:3rem !important}.me-lg-auto{margin-right:auto !important}.mb-lg-0{margin-bottom:0 !important}.mb-lg-1{margin-bottom:.25rem !important}.mb-lg-2{margin-bottom:.5rem !important}.mb-lg-3{margin-bottom:1rem !important}.mb-lg-4{margin-bottom:1.5rem !important}.mb-lg-5{margin-bottom:3rem !important}.mb-lg-auto{margin-bottom:auto !important}.ms-lg-0{margin-left:0 !important}.ms-lg-1{margin-left:.25rem !important}.ms-lg-2{margin-left:.5rem !important}.ms-lg-3{margin-left:1rem !important}.ms-lg-4{margin-left:1.5rem !important}.ms-lg-5{margin-left:3rem !important}.ms-lg-auto{margin-left:auto !important}.p-lg-0{padding:0 !important}.p-lg-1{padding:.25rem !important}.p-lg-2{padding:.5rem !important}.p-lg-3{padding:1rem !important}.p-lg-4{padding:1.5rem !important}.p-lg-5{padding:3rem !important}.px-lg-0{padding-right:0 !important;padding-left:0 !important}.px-lg-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-lg-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-lg-3{padding-right:1rem !important;padding-left:1rem !important}.px-lg-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-lg-5{padding-right:3rem !important;padding-left:3rem !important}.py-lg-0{padding-top:0 !important;padding-bottom:0 !important}.py-lg-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-lg-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-lg-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-lg-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-lg-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-lg-0{padding-top:0 !important}.pt-lg-1{padding-top:.25rem !important}.pt-lg-2{padding-top:.5rem !important}.pt-lg-3{padding-top:1rem !important}.pt-lg-4{padding-top:1.5rem !important}.pt-lg-5{padding-top:3rem !important}.pe-lg-0{padding-right:0 !important}.pe-lg-1{padding-right:.25rem !important}.pe-lg-2{padding-right:.5rem !important}.pe-lg-3{padding-right:1rem !important}.pe-lg-4{padding-right:1.5rem !important}.pe-lg-5{padding-right:3rem !important}.pb-lg-0{padding-bottom:0 !important}.pb-lg-1{padding-bottom:.25rem !important}.pb-lg-2{padding-bottom:.5rem !important}.pb-lg-3{padding-bottom:1rem !important}.pb-lg-4{padding-bottom:1.5rem !important}.pb-lg-5{padding-bottom:3rem !important}.ps-lg-0{padding-left:0 !important}.ps-lg-1{padding-left:.25rem !important}.ps-lg-2{padding-left:.5rem !important}.ps-lg-3{padding-left:1rem !important}.ps-lg-4{padding-left:1.5rem !important}.ps-lg-5{padding-left:3rem !important}.gap-lg-0{gap:0 !important}.gap-lg-1{gap:.25rem !important}.gap-lg-2{gap:.5rem !important}.gap-lg-3{gap:1rem !important}.gap-lg-4{gap:1.5rem !important}.gap-lg-5{gap:3rem !important}.row-gap-lg-0{row-gap:0 !important}.row-gap-lg-1{row-gap:.25rem !important}.row-gap-lg-2{row-gap:.5rem !important}.row-gap-lg-3{row-gap:1rem !important}.row-gap-lg-4{row-gap:1.5rem !important}.row-gap-lg-5{row-gap:3rem !important}.column-gap-lg-0{column-gap:0 !important}.column-gap-lg-1{column-gap:.25rem !important}.column-gap-lg-2{column-gap:.5rem !important}.column-gap-lg-3{column-gap:1rem !important}.column-gap-lg-4{column-gap:1.5rem !important}.column-gap-lg-5{column-gap:3rem !important}.text-lg-start{text-align:left !important}.text-lg-end{text-align:right !important}.text-lg-center{text-align:center !important}}@media(min-width: 1200px){.float-xl-start{float:left !important}.float-xl-end{float:right !important}.float-xl-none{float:none !important}.object-fit-xl-contain{object-fit:contain !important}.object-fit-xl-cover{object-fit:cover !important}.object-fit-xl-fill{object-fit:fill !important}.object-fit-xl-scale{object-fit:scale-down !important}.object-fit-xl-none{object-fit:none !important}.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-block{display:block !important}.d-xl-grid{display:grid !important}.d-xl-inline-grid{display:inline-grid !important}.d-xl-table{display:table !important}.d-xl-table-row{display:table-row !important}.d-xl-table-cell{display:table-cell !important}.d-xl-flex{display:flex !important}.d-xl-inline-flex{display:inline-flex !important}.d-xl-none{display:none !important}.flex-xl-fill{flex:1 1 auto !important}.flex-xl-row{flex-direction:row !important}.flex-xl-column{flex-direction:column !important}.flex-xl-row-reverse{flex-direction:row-reverse !important}.flex-xl-column-reverse{flex-direction:column-reverse !important}.flex-xl-grow-0{flex-grow:0 !important}.flex-xl-grow-1{flex-grow:1 !important}.flex-xl-shrink-0{flex-shrink:0 !important}.flex-xl-shrink-1{flex-shrink:1 !important}.flex-xl-wrap{flex-wrap:wrap !important}.flex-xl-nowrap{flex-wrap:nowrap !important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-xl-start{justify-content:flex-start !important}.justify-content-xl-end{justify-content:flex-end !important}.justify-content-xl-center{justify-content:center !important}.justify-content-xl-between{justify-content:space-between !important}.justify-content-xl-around{justify-content:space-around !important}.justify-content-xl-evenly{justify-content:space-evenly !important}.align-items-xl-start{align-items:flex-start !important}.align-items-xl-end{align-items:flex-end !important}.align-items-xl-center{align-items:center !important}.align-items-xl-baseline{align-items:baseline !important}.align-items-xl-stretch{align-items:stretch !important}.align-content-xl-start{align-content:flex-start !important}.align-content-xl-end{align-content:flex-end !important}.align-content-xl-center{align-content:center !important}.align-content-xl-between{align-content:space-between !important}.align-content-xl-around{align-content:space-around !important}.align-content-xl-stretch{align-content:stretch !important}.align-self-xl-auto{align-self:auto !important}.align-self-xl-start{align-self:flex-start !important}.align-self-xl-end{align-self:flex-end !important}.align-self-xl-center{align-self:center !important}.align-self-xl-baseline{align-self:baseline !important}.align-self-xl-stretch{align-self:stretch !important}.order-xl-first{order:-1 !important}.order-xl-0{order:0 !important}.order-xl-1{order:1 !important}.order-xl-2{order:2 !important}.order-xl-3{order:3 !important}.order-xl-4{order:4 !important}.order-xl-5{order:5 !important}.order-xl-last{order:6 !important}.m-xl-0{margin:0 !important}.m-xl-1{margin:.25rem !important}.m-xl-2{margin:.5rem !important}.m-xl-3{margin:1rem !important}.m-xl-4{margin:1.5rem !important}.m-xl-5{margin:3rem !important}.m-xl-auto{margin:auto !important}.mx-xl-0{margin-right:0 !important;margin-left:0 !important}.mx-xl-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-xl-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-xl-3{margin-right:1rem !important;margin-left:1rem !important}.mx-xl-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-xl-5{margin-right:3rem !important;margin-left:3rem !important}.mx-xl-auto{margin-right:auto !important;margin-left:auto !important}.my-xl-0{margin-top:0 !important;margin-bottom:0 !important}.my-xl-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-xl-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-xl-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-xl-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-xl-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-xl-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-xl-0{margin-top:0 !important}.mt-xl-1{margin-top:.25rem !important}.mt-xl-2{margin-top:.5rem !important}.mt-xl-3{margin-top:1rem !important}.mt-xl-4{margin-top:1.5rem !important}.mt-xl-5{margin-top:3rem !important}.mt-xl-auto{margin-top:auto !important}.me-xl-0{margin-right:0 !important}.me-xl-1{margin-right:.25rem !important}.me-xl-2{margin-right:.5rem !important}.me-xl-3{margin-right:1rem !important}.me-xl-4{margin-right:1.5rem !important}.me-xl-5{margin-right:3rem !important}.me-xl-auto{margin-right:auto !important}.mb-xl-0{margin-bottom:0 !important}.mb-xl-1{margin-bottom:.25rem !important}.mb-xl-2{margin-bottom:.5rem !important}.mb-xl-3{margin-bottom:1rem !important}.mb-xl-4{margin-bottom:1.5rem !important}.mb-xl-5{margin-bottom:3rem !important}.mb-xl-auto{margin-bottom:auto !important}.ms-xl-0{margin-left:0 !important}.ms-xl-1{margin-left:.25rem !important}.ms-xl-2{margin-left:.5rem !important}.ms-xl-3{margin-left:1rem !important}.ms-xl-4{margin-left:1.5rem !important}.ms-xl-5{margin-left:3rem !important}.ms-xl-auto{margin-left:auto !important}.p-xl-0{padding:0 !important}.p-xl-1{padding:.25rem !important}.p-xl-2{padding:.5rem !important}.p-xl-3{padding:1rem !important}.p-xl-4{padding:1.5rem !important}.p-xl-5{padding:3rem !important}.px-xl-0{padding-right:0 !important;padding-left:0 !important}.px-xl-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-xl-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-xl-3{padding-right:1rem !important;padding-left:1rem !important}.px-xl-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-xl-5{padding-right:3rem !important;padding-left:3rem !important}.py-xl-0{padding-top:0 !important;padding-bottom:0 !important}.py-xl-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-xl-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-xl-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-xl-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-xl-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-xl-0{padding-top:0 !important}.pt-xl-1{padding-top:.25rem !important}.pt-xl-2{padding-top:.5rem !important}.pt-xl-3{padding-top:1rem !important}.pt-xl-4{padding-top:1.5rem !important}.pt-xl-5{padding-top:3rem !important}.pe-xl-0{padding-right:0 !important}.pe-xl-1{padding-right:.25rem !important}.pe-xl-2{padding-right:.5rem !important}.pe-xl-3{padding-right:1rem !important}.pe-xl-4{padding-right:1.5rem !important}.pe-xl-5{padding-right:3rem !important}.pb-xl-0{padding-bottom:0 !important}.pb-xl-1{padding-bottom:.25rem !important}.pb-xl-2{padding-bottom:.5rem !important}.pb-xl-3{padding-bottom:1rem !important}.pb-xl-4{padding-bottom:1.5rem !important}.pb-xl-5{padding-bottom:3rem !important}.ps-xl-0{padding-left:0 !important}.ps-xl-1{padding-left:.25rem !important}.ps-xl-2{padding-left:.5rem !important}.ps-xl-3{padding-left:1rem !important}.ps-xl-4{padding-left:1.5rem !important}.ps-xl-5{padding-left:3rem !important}.gap-xl-0{gap:0 !important}.gap-xl-1{gap:.25rem !important}.gap-xl-2{gap:.5rem !important}.gap-xl-3{gap:1rem !important}.gap-xl-4{gap:1.5rem !important}.gap-xl-5{gap:3rem !important}.row-gap-xl-0{row-gap:0 !important}.row-gap-xl-1{row-gap:.25rem !important}.row-gap-xl-2{row-gap:.5rem !important}.row-gap-xl-3{row-gap:1rem !important}.row-gap-xl-4{row-gap:1.5rem !important}.row-gap-xl-5{row-gap:3rem !important}.column-gap-xl-0{column-gap:0 !important}.column-gap-xl-1{column-gap:.25rem !important}.column-gap-xl-2{column-gap:.5rem !important}.column-gap-xl-3{column-gap:1rem !important}.column-gap-xl-4{column-gap:1.5rem !important}.column-gap-xl-5{column-gap:3rem !important}.text-xl-start{text-align:left !important}.text-xl-end{text-align:right !important}.text-xl-center{text-align:center !important}}@media(min-width: 1400px){.float-xxl-start{float:left !important}.float-xxl-end{float:right !important}.float-xxl-none{float:none !important}.object-fit-xxl-contain{object-fit:contain !important}.object-fit-xxl-cover{object-fit:cover !important}.object-fit-xxl-fill{object-fit:fill !important}.object-fit-xxl-scale{object-fit:scale-down !important}.object-fit-xxl-none{object-fit:none !important}.d-xxl-inline{display:inline !important}.d-xxl-inline-block{display:inline-block !important}.d-xxl-block{display:block !important}.d-xxl-grid{display:grid !important}.d-xxl-inline-grid{display:inline-grid !important}.d-xxl-table{display:table !important}.d-xxl-table-row{display:table-row !important}.d-xxl-table-cell{display:table-cell !important}.d-xxl-flex{display:flex !important}.d-xxl-inline-flex{display:inline-flex !important}.d-xxl-none{display:none !important}.flex-xxl-fill{flex:1 1 auto !important}.flex-xxl-row{flex-direction:row !important}.flex-xxl-column{flex-direction:column !important}.flex-xxl-row-reverse{flex-direction:row-reverse !important}.flex-xxl-column-reverse{flex-direction:column-reverse !important}.flex-xxl-grow-0{flex-grow:0 !important}.flex-xxl-grow-1{flex-grow:1 !important}.flex-xxl-shrink-0{flex-shrink:0 !important}.flex-xxl-shrink-1{flex-shrink:1 !important}.flex-xxl-wrap{flex-wrap:wrap !important}.flex-xxl-nowrap{flex-wrap:nowrap !important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-xxl-start{justify-content:flex-start !important}.justify-content-xxl-end{justify-content:flex-end !important}.justify-content-xxl-center{justify-content:center !important}.justify-content-xxl-between{justify-content:space-between !important}.justify-content-xxl-around{justify-content:space-around !important}.justify-content-xxl-evenly{justify-content:space-evenly !important}.align-items-xxl-start{align-items:flex-start !important}.align-items-xxl-end{align-items:flex-end !important}.align-items-xxl-center{align-items:center !important}.align-items-xxl-baseline{align-items:baseline !important}.align-items-xxl-stretch{align-items:stretch !important}.align-content-xxl-start{align-content:flex-start !important}.align-content-xxl-end{align-content:flex-end !important}.align-content-xxl-center{align-content:center !important}.align-content-xxl-between{align-content:space-between !important}.align-content-xxl-around{align-content:space-around !important}.align-content-xxl-stretch{align-content:stretch !important}.align-self-xxl-auto{align-self:auto !important}.align-self-xxl-start{align-self:flex-start !important}.align-self-xxl-end{align-self:flex-end !important}.align-self-xxl-center{align-self:center !important}.align-self-xxl-baseline{align-self:baseline !important}.align-self-xxl-stretch{align-self:stretch !important}.order-xxl-first{order:-1 !important}.order-xxl-0{order:0 !important}.order-xxl-1{order:1 !important}.order-xxl-2{order:2 !important}.order-xxl-3{order:3 !important}.order-xxl-4{order:4 !important}.order-xxl-5{order:5 !important}.order-xxl-last{order:6 !important}.m-xxl-0{margin:0 !important}.m-xxl-1{margin:.25rem !important}.m-xxl-2{margin:.5rem !important}.m-xxl-3{margin:1rem !important}.m-xxl-4{margin:1.5rem !important}.m-xxl-5{margin:3rem !important}.m-xxl-auto{margin:auto !important}.mx-xxl-0{margin-right:0 !important;margin-left:0 !important}.mx-xxl-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-xxl-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-xxl-3{margin-right:1rem !important;margin-left:1rem !important}.mx-xxl-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-xxl-5{margin-right:3rem !important;margin-left:3rem !important}.mx-xxl-auto{margin-right:auto !important;margin-left:auto !important}.my-xxl-0{margin-top:0 !important;margin-bottom:0 !important}.my-xxl-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-xxl-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-xxl-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-xxl-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-xxl-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-xxl-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-xxl-0{margin-top:0 !important}.mt-xxl-1{margin-top:.25rem !important}.mt-xxl-2{margin-top:.5rem !important}.mt-xxl-3{margin-top:1rem !important}.mt-xxl-4{margin-top:1.5rem !important}.mt-xxl-5{margin-top:3rem !important}.mt-xxl-auto{margin-top:auto !important}.me-xxl-0{margin-right:0 !important}.me-xxl-1{margin-right:.25rem !important}.me-xxl-2{margin-right:.5rem !important}.me-xxl-3{margin-right:1rem !important}.me-xxl-4{margin-right:1.5rem !important}.me-xxl-5{margin-right:3rem !important}.me-xxl-auto{margin-right:auto !important}.mb-xxl-0{margin-bottom:0 !important}.mb-xxl-1{margin-bottom:.25rem !important}.mb-xxl-2{margin-bottom:.5rem !important}.mb-xxl-3{margin-bottom:1rem !important}.mb-xxl-4{margin-bottom:1.5rem !important}.mb-xxl-5{margin-bottom:3rem !important}.mb-xxl-auto{margin-bottom:auto !important}.ms-xxl-0{margin-left:0 !important}.ms-xxl-1{margin-left:.25rem !important}.ms-xxl-2{margin-left:.5rem !important}.ms-xxl-3{margin-left:1rem !important}.ms-xxl-4{margin-left:1.5rem !important}.ms-xxl-5{margin-left:3rem !important}.ms-xxl-auto{margin-left:auto !important}.p-xxl-0{padding:0 !important}.p-xxl-1{padding:.25rem !important}.p-xxl-2{padding:.5rem !important}.p-xxl-3{padding:1rem !important}.p-xxl-4{padding:1.5rem !important}.p-xxl-5{padding:3rem !important}.px-xxl-0{padding-right:0 !important;padding-left:0 !important}.px-xxl-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-xxl-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-xxl-3{padding-right:1rem !important;padding-left:1rem !important}.px-xxl-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-xxl-5{padding-right:3rem !important;padding-left:3rem !important}.py-xxl-0{padding-top:0 !important;padding-bottom:0 !important}.py-xxl-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-xxl-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-xxl-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-xxl-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-xxl-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-xxl-0{padding-top:0 !important}.pt-xxl-1{padding-top:.25rem !important}.pt-xxl-2{padding-top:.5rem !important}.pt-xxl-3{padding-top:1rem !important}.pt-xxl-4{padding-top:1.5rem !important}.pt-xxl-5{padding-top:3rem !important}.pe-xxl-0{padding-right:0 !important}.pe-xxl-1{padding-right:.25rem !important}.pe-xxl-2{padding-right:.5rem !important}.pe-xxl-3{padding-right:1rem !important}.pe-xxl-4{padding-right:1.5rem !important}.pe-xxl-5{padding-right:3rem !important}.pb-xxl-0{padding-bottom:0 !important}.pb-xxl-1{padding-bottom:.25rem !important}.pb-xxl-2{padding-bottom:.5rem !important}.pb-xxl-3{padding-bottom:1rem !important}.pb-xxl-4{padding-bottom:1.5rem !important}.pb-xxl-5{padding-bottom:3rem !important}.ps-xxl-0{padding-left:0 !important}.ps-xxl-1{padding-left:.25rem !important}.ps-xxl-2{padding-left:.5rem !important}.ps-xxl-3{padding-left:1rem !important}.ps-xxl-4{padding-left:1.5rem !important}.ps-xxl-5{padding-left:3rem !important}.gap-xxl-0{gap:0 !important}.gap-xxl-1{gap:.25rem !important}.gap-xxl-2{gap:.5rem !important}.gap-xxl-3{gap:1rem !important}.gap-xxl-4{gap:1.5rem !important}.gap-xxl-5{gap:3rem !important}.row-gap-xxl-0{row-gap:0 !important}.row-gap-xxl-1{row-gap:.25rem !important}.row-gap-xxl-2{row-gap:.5rem !important}.row-gap-xxl-3{row-gap:1rem !important}.row-gap-xxl-4{row-gap:1.5rem !important}.row-gap-xxl-5{row-gap:3rem !important}.column-gap-xxl-0{column-gap:0 !important}.column-gap-xxl-1{column-gap:.25rem !important}.column-gap-xxl-2{column-gap:.5rem !important}.column-gap-xxl-3{column-gap:1rem !important}.column-gap-xxl-4{column-gap:1.5rem !important}.column-gap-xxl-5{column-gap:3rem !important}.text-xxl-start{text-align:left !important}.text-xxl-end{text-align:right !important}.text-xxl-center{text-align:center !important}}.bg-default{color:#000}.bg-primary{color:#fff}.bg-secondary{color:#fff}.bg-success{color:#fff}.bg-info{color:#000}.bg-warning{color:#000}.bg-danger{color:#fff}.bg-light{color:#000}.bg-dark{color:#fff}@media(min-width: 1200px){.fs-1{font-size:2rem !important}.fs-2{font-size:1.65rem !important}.fs-3{font-size:1.45rem !important}}@media print{.d-print-inline{display:inline !important}.d-print-inline-block{display:inline-block !important}.d-print-block{display:block !important}.d-print-grid{display:grid !important}.d-print-inline-grid{display:inline-grid !important}.d-print-table{display:table !important}.d-print-table-row{display:table-row !important}.d-print-table-cell{display:table-cell !important}.d-print-flex{display:flex !important}.d-print-inline-flex{display:inline-flex !important}.d-print-none{display:none !important}}.bg-blue{--bslib-color-bg: #0d6efd;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-blue{--bslib-color-fg: #0d6efd;color:var(--bslib-color-fg)}.bg-indigo{--bslib-color-bg: #6610f2;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-indigo{--bslib-color-fg: #6610f2;color:var(--bslib-color-fg)}.bg-purple{--bslib-color-bg: #6f42c1;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-purple{--bslib-color-fg: #6f42c1;color:var(--bslib-color-fg)}.bg-pink{--bslib-color-bg: #d63384;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-pink{--bslib-color-fg: #d63384;color:var(--bslib-color-fg)}.bg-red{--bslib-color-bg: #dc3545;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-red{--bslib-color-fg: #dc3545;color:var(--bslib-color-fg)}.bg-orange{--bslib-color-bg: #fd7e14;--bslib-color-fg: #000;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-orange{--bslib-color-fg: #fd7e14;color:var(--bslib-color-fg)}.bg-yellow{--bslib-color-bg: #ffc107;--bslib-color-fg: #000;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-yellow{--bslib-color-fg: #ffc107;color:var(--bslib-color-fg)}.bg-green{--bslib-color-bg: #198754;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-green{--bslib-color-fg: #198754;color:var(--bslib-color-fg)}.bg-teal{--bslib-color-bg: #20c997;--bslib-color-fg: #000;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-teal{--bslib-color-fg: #20c997;color:var(--bslib-color-fg)}.bg-cyan{--bslib-color-bg: #0dcaf0;--bslib-color-fg: #000;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-cyan{--bslib-color-fg: #0dcaf0;color:var(--bslib-color-fg)}.text-default{--bslib-color-fg: #dee2e6}.bg-default{--bslib-color-bg: #dee2e6;--bslib-color-fg: #000}.text-primary{--bslib-color-fg: #0d6efd}.bg-primary{--bslib-color-bg: #0d6efd;--bslib-color-fg: #ffffff}.text-secondary{--bslib-color-fg: #6c757d}.bg-secondary{--bslib-color-bg: #6c757d;--bslib-color-fg: #ffffff}.text-success{--bslib-color-fg: #198754}.bg-success{--bslib-color-bg: #198754;--bslib-color-fg: #ffffff}.text-info{--bslib-color-fg: #0dcaf0}.bg-info{--bslib-color-bg: #0dcaf0;--bslib-color-fg: #000}.text-warning{--bslib-color-fg: #ffc107}.bg-warning{--bslib-color-bg: #ffc107;--bslib-color-fg: #000}.text-danger{--bslib-color-fg: #dc3545}.bg-danger{--bslib-color-bg: #dc3545;--bslib-color-fg: #ffffff}.text-light{--bslib-color-fg: #f8f9fa}.bg-light{--bslib-color-bg: #f8f9fa;--bslib-color-fg: #000}.text-dark{--bslib-color-fg: #212529}.bg-dark{--bslib-color-bg: #212529;--bslib-color-fg: #ffffff}.bg-gradient-blue-indigo{--bslib-color-fg: #ffffff;--bslib-color-bg: #3148f9;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #3148f9;color:#fff}.bg-gradient-blue-purple{--bslib-color-fg: #ffffff;--bslib-color-bg: #345ce5;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #345ce5;color:#fff}.bg-gradient-blue-pink{--bslib-color-fg: #ffffff;--bslib-color-bg: #5d56cd;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) #5d56cd;color:#fff}.bg-gradient-blue-red{--bslib-color-fg: #ffffff;--bslib-color-bg: #6057b3;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) #6057b3;color:#fff}.bg-gradient-blue-orange{--bslib-color-fg: #ffffff;--bslib-color-bg: #6d74a0;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #6d74a0;color:#fff}.bg-gradient-blue-yellow{--bslib-color-fg: #000;--bslib-color-bg: #6e8f9b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) #6e8f9b;color:#000}.bg-gradient-blue-green{--bslib-color-fg: #ffffff;--bslib-color-bg: #1278b9;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) #1278b9;color:#fff}.bg-gradient-blue-teal{--bslib-color-fg: #000;--bslib-color-bg: #1592d4;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #1592d4;color:#000}.bg-gradient-blue-cyan{--bslib-color-fg: #000;--bslib-color-bg: #0d93f8;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) #0d93f8;color:#000}.bg-gradient-indigo-blue{--bslib-color-fg: #ffffff;--bslib-color-bg: #4236f6;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) #4236f6;color:#fff}.bg-gradient-indigo-purple{--bslib-color-fg: #ffffff;--bslib-color-bg: #6a24de;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #6a24de;color:#fff}.bg-gradient-indigo-pink{--bslib-color-fg: #ffffff;--bslib-color-bg: #931ec6;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) #931ec6;color:#fff}.bg-gradient-indigo-red{--bslib-color-fg: #ffffff;--bslib-color-bg: #951fad;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) #951fad;color:#fff}.bg-gradient-indigo-orange{--bslib-color-fg: #ffffff;--bslib-color-bg: #a23c99;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #a23c99;color:#fff}.bg-gradient-indigo-yellow{--bslib-color-fg: #ffffff;--bslib-color-bg: #a35794;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) #a35794;color:#fff}.bg-gradient-indigo-green{--bslib-color-fg: #ffffff;--bslib-color-bg: #4740b3;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) #4740b3;color:#fff}.bg-gradient-indigo-teal{--bslib-color-fg: #ffffff;--bslib-color-bg: #4a5ace;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #4a5ace;color:#fff}.bg-gradient-indigo-cyan{--bslib-color-fg: #ffffff;--bslib-color-bg: #425af1;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) #425af1;color:#fff}.bg-gradient-purple-blue{--bslib-color-fg: #ffffff;--bslib-color-bg: #4854d9;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) #4854d9;color:#fff}.bg-gradient-purple-indigo{--bslib-color-fg: #ffffff;--bslib-color-bg: #6b2ed5;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #6b2ed5;color:#fff}.bg-gradient-purple-pink{--bslib-color-fg: #ffffff;--bslib-color-bg: #983ca9;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) #983ca9;color:#fff}.bg-gradient-purple-red{--bslib-color-fg: #ffffff;--bslib-color-bg: #9b3d8f;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) #9b3d8f;color:#fff}.bg-gradient-purple-orange{--bslib-color-fg: #ffffff;--bslib-color-bg: #a85a7c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #a85a7c;color:#fff}.bg-gradient-purple-yellow{--bslib-color-fg: #000;--bslib-color-bg: #a97577;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) #a97577;color:#000}.bg-gradient-purple-green{--bslib-color-fg: #ffffff;--bslib-color-bg: #4d5e95;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) #4d5e95;color:#fff}.bg-gradient-purple-teal{--bslib-color-fg: #ffffff;--bslib-color-bg: #4f78b0;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #4f78b0;color:#fff}.bg-gradient-purple-cyan{--bslib-color-fg: #000;--bslib-color-bg: #4878d4;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) #4878d4;color:#000}.bg-gradient-pink-blue{--bslib-color-fg: #ffffff;--bslib-color-bg: #864bb4;background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) #864bb4;color:#fff}.bg-gradient-pink-indigo{--bslib-color-fg: #ffffff;--bslib-color-bg: #a925b0;background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #a925b0;color:#fff}.bg-gradient-pink-purple{--bslib-color-fg: #ffffff;--bslib-color-bg: #ad399c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #ad399c;color:#fff}.bg-gradient-pink-red{--bslib-color-fg: #ffffff;--bslib-color-bg: #d8346b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) #d8346b;color:#fff}.bg-gradient-pink-orange{--bslib-color-fg: #000;--bslib-color-bg: #e65157;background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #e65157;color:#000}.bg-gradient-pink-yellow{--bslib-color-fg: #000;--bslib-color-bg: #e66c52;background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) #e66c52;color:#000}.bg-gradient-pink-green{--bslib-color-fg: #ffffff;--bslib-color-bg: #8a5571;background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) #8a5571;color:#fff}.bg-gradient-pink-teal{--bslib-color-fg: #000;--bslib-color-bg: #8d6f8c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #8d6f8c;color:#000}.bg-gradient-pink-cyan{--bslib-color-fg: #000;--bslib-color-bg: #866faf;background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) #866faf;color:#000}.bg-gradient-red-blue{--bslib-color-fg: #ffffff;--bslib-color-bg: #894c8f;background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) #894c8f;color:#fff}.bg-gradient-red-indigo{--bslib-color-fg: #ffffff;--bslib-color-bg: #ad268a;background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #ad268a;color:#fff}.bg-gradient-red-purple{--bslib-color-fg: #ffffff;--bslib-color-bg: #b03a77;background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #b03a77;color:#fff}.bg-gradient-red-pink{--bslib-color-fg: #ffffff;--bslib-color-bg: #da345e;background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) #da345e;color:#fff}.bg-gradient-red-orange{--bslib-color-fg: #000;--bslib-color-bg: #e95231;background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #e95231;color:#000}.bg-gradient-red-yellow{--bslib-color-fg: #000;--bslib-color-bg: #ea6d2c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) #ea6d2c;color:#000}.bg-gradient-red-green{--bslib-color-fg: #ffffff;--bslib-color-bg: #8e564b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) #8e564b;color:#fff}.bg-gradient-red-teal{--bslib-color-fg: #000;--bslib-color-bg: #917066;background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #917066;color:#000}.bg-gradient-red-cyan{--bslib-color-fg: #000;--bslib-color-bg: #897189;background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) #897189;color:#000}.bg-gradient-orange-blue{--bslib-color-fg: #000;--bslib-color-bg: #9d7871;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) #9d7871;color:#000}.bg-gradient-orange-indigo{--bslib-color-fg: #000;--bslib-color-bg: #c1526d;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #c1526d;color:#000}.bg-gradient-orange-purple{--bslib-color-fg: #000;--bslib-color-bg: #c46659;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #c46659;color:#000}.bg-gradient-orange-pink{--bslib-color-fg: #000;--bslib-color-bg: #ed6041;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) #ed6041;color:#000}.bg-gradient-orange-red{--bslib-color-fg: #000;--bslib-color-bg: #f06128;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) #f06128;color:#000}.bg-gradient-orange-yellow{--bslib-color-fg: #000;--bslib-color-bg: #fe990f;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) #fe990f;color:#000}.bg-gradient-orange-green{--bslib-color-fg: #000;--bslib-color-bg: #a2822e;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) #a2822e;color:#000}.bg-gradient-orange-teal{--bslib-color-fg: #000;--bslib-color-bg: #a59c48;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #a59c48;color:#000}.bg-gradient-orange-cyan{--bslib-color-fg: #000;--bslib-color-bg: #9d9c6c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) #9d9c6c;color:#000}.bg-gradient-yellow-blue{--bslib-color-fg: #000;--bslib-color-bg: #9ea069;background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) #9ea069;color:#000}.bg-gradient-yellow-indigo{--bslib-color-fg: #000;--bslib-color-bg: #c27a65;background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #c27a65;color:#000}.bg-gradient-yellow-purple{--bslib-color-fg: #000;--bslib-color-bg: #c58e51;background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #c58e51;color:#000}.bg-gradient-yellow-pink{--bslib-color-fg: #000;--bslib-color-bg: #ef8839;background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) #ef8839;color:#000}.bg-gradient-yellow-red{--bslib-color-fg: #000;--bslib-color-bg: #f18920;background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) #f18920;color:#000}.bg-gradient-yellow-orange{--bslib-color-fg: #000;--bslib-color-bg: #fea60c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #fea60c;color:#000}.bg-gradient-yellow-green{--bslib-color-fg: #000;--bslib-color-bg: #a3aa26;background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) #a3aa26;color:#000}.bg-gradient-yellow-teal{--bslib-color-fg: #000;--bslib-color-bg: #a6c441;background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #a6c441;color:#000}.bg-gradient-yellow-cyan{--bslib-color-fg: #000;--bslib-color-bg: #9ec564;background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) #9ec564;color:#000}.bg-gradient-green-blue{--bslib-color-fg: #ffffff;--bslib-color-bg: #147d98;background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) #147d98;color:#fff}.bg-gradient-green-indigo{--bslib-color-fg: #ffffff;--bslib-color-bg: #385793;background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #385793;color:#fff}.bg-gradient-green-purple{--bslib-color-fg: #ffffff;--bslib-color-bg: #3b6b80;background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #3b6b80;color:#fff}.bg-gradient-green-pink{--bslib-color-fg: #ffffff;--bslib-color-bg: #656567;background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) #656567;color:#fff}.bg-gradient-green-red{--bslib-color-fg: #ffffff;--bslib-color-bg: #67664e;background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) #67664e;color:#fff}.bg-gradient-green-orange{--bslib-color-fg: #000;--bslib-color-bg: #74833a;background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #74833a;color:#000}.bg-gradient-green-yellow{--bslib-color-fg: #000;--bslib-color-bg: #759e35;background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) #759e35;color:#000}.bg-gradient-green-teal{--bslib-color-fg: #000;--bslib-color-bg: #1ca16f;background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #1ca16f;color:#000}.bg-gradient-green-cyan{--bslib-color-fg: #000;--bslib-color-bg: #14a292;background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) #14a292;color:#000}.bg-gradient-teal-blue{--bslib-color-fg: #000;--bslib-color-bg: #18a5c0;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) #18a5c0;color:#000}.bg-gradient-teal-indigo{--bslib-color-fg: #000;--bslib-color-bg: #3c7fbb;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #3c7fbb;color:#000}.bg-gradient-teal-purple{--bslib-color-fg: #000;--bslib-color-bg: #4093a8;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #4093a8;color:#000}.bg-gradient-teal-pink{--bslib-color-fg: #000;--bslib-color-bg: #698d8f;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) #698d8f;color:#000}.bg-gradient-teal-red{--bslib-color-fg: #000;--bslib-color-bg: #6b8e76;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) #6b8e76;color:#000}.bg-gradient-teal-orange{--bslib-color-fg: #000;--bslib-color-bg: #78ab63;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #78ab63;color:#000}.bg-gradient-teal-yellow{--bslib-color-fg: #000;--bslib-color-bg: #79c65d;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) #79c65d;color:#000}.bg-gradient-teal-green{--bslib-color-fg: #000;--bslib-color-bg: #1daf7c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) #1daf7c;color:#000}.bg-gradient-teal-cyan{--bslib-color-fg: #000;--bslib-color-bg: #18c9bb;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) #18c9bb;color:#000}.bg-gradient-cyan-blue{--bslib-color-fg: #000;--bslib-color-bg: #0da5f5;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) #0da5f5;color:#000}.bg-gradient-cyan-indigo{--bslib-color-fg: #000;--bslib-color-bg: #3180f1;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #3180f1;color:#000}.bg-gradient-cyan-purple{--bslib-color-fg: #000;--bslib-color-bg: #3494dd;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #3494dd;color:#000}.bg-gradient-cyan-pink{--bslib-color-fg: #000;--bslib-color-bg: #5d8ec5;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) #5d8ec5;color:#000}.bg-gradient-cyan-red{--bslib-color-fg: #000;--bslib-color-bg: #608eac;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) #608eac;color:#000}.bg-gradient-cyan-orange{--bslib-color-fg: #000;--bslib-color-bg: #6dac98;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #6dac98;color:#000}.bg-gradient-cyan-yellow{--bslib-color-fg: #000;--bslib-color-bg: #6ec693;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) #6ec693;color:#000}.bg-gradient-cyan-green{--bslib-color-fg: #000;--bslib-color-bg: #12afb2;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) #12afb2;color:#000}.bg-gradient-cyan-teal{--bslib-color-fg: #000;--bslib-color-bg: #15cacc;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #15cacc;color:#000}:root{--bslib-spacer: 1rem;--bslib-mb-spacer: var(--bslib-spacer, 1rem)}.bslib-mb-spacing{margin-bottom:var(--bslib-mb-spacer)}.bslib-gap-spacing{gap:var(--bslib-mb-spacer)}.bslib-gap-spacing>.bslib-mb-spacing,.bslib-gap-spacing>.form-group,.bslib-gap-spacing>p,.bslib-gap-spacing>pre{margin-bottom:0}.html-fill-container>.html-fill-item.bslib-mb-spacing{margin-bottom:0}.tab-content>.tab-pane.html-fill-container{display:none}.tab-content>.active.html-fill-container{display:flex}.tab-content.html-fill-container{padding:0}:root{--bslib-spacer: 1rem;--bslib-mb-spacer: var(--bslib-spacer, 1rem)}.bslib-mb-spacing{margin-bottom:var(--bslib-mb-spacer)}.bslib-gap-spacing{gap:var(--bslib-mb-spacer)}.bslib-gap-spacing>.bslib-mb-spacing,.bslib-gap-spacing>.form-group,.bslib-gap-spacing>p,.bslib-gap-spacing>pre{margin-bottom:0}.html-fill-container>.html-fill-item.bslib-mb-spacing{margin-bottom:0}.tab-content>.tab-pane.html-fill-container{display:none}.tab-content>.active.html-fill-container{display:flex}.tab-content.html-fill-container{padding:0}.bg-blue{--bslib-color-bg: #0d6efd;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-blue{--bslib-color-fg: #0d6efd;color:var(--bslib-color-fg)}.bg-indigo{--bslib-color-bg: #6610f2;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-indigo{--bslib-color-fg: #6610f2;color:var(--bslib-color-fg)}.bg-purple{--bslib-color-bg: #6f42c1;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-purple{--bslib-color-fg: #6f42c1;color:var(--bslib-color-fg)}.bg-pink{--bslib-color-bg: #d63384;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-pink{--bslib-color-fg: #d63384;color:var(--bslib-color-fg)}.bg-red{--bslib-color-bg: #dc3545;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-red{--bslib-color-fg: #dc3545;color:var(--bslib-color-fg)}.bg-orange{--bslib-color-bg: #fd7e14;--bslib-color-fg: #000;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-orange{--bslib-color-fg: #fd7e14;color:var(--bslib-color-fg)}.bg-yellow{--bslib-color-bg: #ffc107;--bslib-color-fg: #000;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-yellow{--bslib-color-fg: #ffc107;color:var(--bslib-color-fg)}.bg-green{--bslib-color-bg: #198754;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-green{--bslib-color-fg: #198754;color:var(--bslib-color-fg)}.bg-teal{--bslib-color-bg: #20c997;--bslib-color-fg: #000;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-teal{--bslib-color-fg: #20c997;color:var(--bslib-color-fg)}.bg-cyan{--bslib-color-bg: #0dcaf0;--bslib-color-fg: #000;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-cyan{--bslib-color-fg: #0dcaf0;color:var(--bslib-color-fg)}.text-default{--bslib-color-fg: #dee2e6}.bg-default{--bslib-color-bg: #dee2e6;--bslib-color-fg: #000}.text-primary{--bslib-color-fg: #0d6efd}.bg-primary{--bslib-color-bg: #0d6efd;--bslib-color-fg: #ffffff}.text-secondary{--bslib-color-fg: #6c757d}.bg-secondary{--bslib-color-bg: #6c757d;--bslib-color-fg: #ffffff}.text-success{--bslib-color-fg: #198754}.bg-success{--bslib-color-bg: #198754;--bslib-color-fg: #ffffff}.text-info{--bslib-color-fg: #0dcaf0}.bg-info{--bslib-color-bg: #0dcaf0;--bslib-color-fg: #000}.text-warning{--bslib-color-fg: #ffc107}.bg-warning{--bslib-color-bg: #ffc107;--bslib-color-fg: #000}.text-danger{--bslib-color-fg: #dc3545}.bg-danger{--bslib-color-bg: #dc3545;--bslib-color-fg: #ffffff}.text-light{--bslib-color-fg: #f8f9fa}.bg-light{--bslib-color-bg: #f8f9fa;--bslib-color-fg: #000}.text-dark{--bslib-color-fg: #212529}.bg-dark{--bslib-color-bg: #212529;--bslib-color-fg: #ffffff}.bg-gradient-blue-indigo{--bslib-color-fg: #ffffff;--bslib-color-bg: #3148f9;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #3148f9;color:#fff}.bg-gradient-blue-purple{--bslib-color-fg: #ffffff;--bslib-color-bg: #345ce5;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #345ce5;color:#fff}.bg-gradient-blue-pink{--bslib-color-fg: #ffffff;--bslib-color-bg: #5d56cd;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) #5d56cd;color:#fff}.bg-gradient-blue-red{--bslib-color-fg: #ffffff;--bslib-color-bg: #6057b3;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) #6057b3;color:#fff}.bg-gradient-blue-orange{--bslib-color-fg: #ffffff;--bslib-color-bg: #6d74a0;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #6d74a0;color:#fff}.bg-gradient-blue-yellow{--bslib-color-fg: #000;--bslib-color-bg: #6e8f9b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) #6e8f9b;color:#000}.bg-gradient-blue-green{--bslib-color-fg: #ffffff;--bslib-color-bg: #1278b9;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) #1278b9;color:#fff}.bg-gradient-blue-teal{--bslib-color-fg: #000;--bslib-color-bg: #1592d4;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #1592d4;color:#000}.bg-gradient-blue-cyan{--bslib-color-fg: #000;--bslib-color-bg: #0d93f8;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) #0d93f8;color:#000}.bg-gradient-indigo-blue{--bslib-color-fg: #ffffff;--bslib-color-bg: #4236f6;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) #4236f6;color:#fff}.bg-gradient-indigo-purple{--bslib-color-fg: #ffffff;--bslib-color-bg: #6a24de;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #6a24de;color:#fff}.bg-gradient-indigo-pink{--bslib-color-fg: #ffffff;--bslib-color-bg: #931ec6;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) #931ec6;color:#fff}.bg-gradient-indigo-red{--bslib-color-fg: #ffffff;--bslib-color-bg: #951fad;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) #951fad;color:#fff}.bg-gradient-indigo-orange{--bslib-color-fg: #ffffff;--bslib-color-bg: #a23c99;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #a23c99;color:#fff}.bg-gradient-indigo-yellow{--bslib-color-fg: #ffffff;--bslib-color-bg: #a35794;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) #a35794;color:#fff}.bg-gradient-indigo-green{--bslib-color-fg: #ffffff;--bslib-color-bg: #4740b3;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) #4740b3;color:#fff}.bg-gradient-indigo-teal{--bslib-color-fg: #ffffff;--bslib-color-bg: #4a5ace;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #4a5ace;color:#fff}.bg-gradient-indigo-cyan{--bslib-color-fg: #ffffff;--bslib-color-bg: #425af1;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) #425af1;color:#fff}.bg-gradient-purple-blue{--bslib-color-fg: #ffffff;--bslib-color-bg: #4854d9;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) #4854d9;color:#fff}.bg-gradient-purple-indigo{--bslib-color-fg: #ffffff;--bslib-color-bg: #6b2ed5;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #6b2ed5;color:#fff}.bg-gradient-purple-pink{--bslib-color-fg: #ffffff;--bslib-color-bg: #983ca9;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) #983ca9;color:#fff}.bg-gradient-purple-red{--bslib-color-fg: #ffffff;--bslib-color-bg: #9b3d8f;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) #9b3d8f;color:#fff}.bg-gradient-purple-orange{--bslib-color-fg: #ffffff;--bslib-color-bg: #a85a7c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #a85a7c;color:#fff}.bg-gradient-purple-yellow{--bslib-color-fg: #000;--bslib-color-bg: #a97577;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) #a97577;color:#000}.bg-gradient-purple-green{--bslib-color-fg: #ffffff;--bslib-color-bg: #4d5e95;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) #4d5e95;color:#fff}.bg-gradient-purple-teal{--bslib-color-fg: #ffffff;--bslib-color-bg: #4f78b0;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #4f78b0;color:#fff}.bg-gradient-purple-cyan{--bslib-color-fg: #000;--bslib-color-bg: #4878d4;background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) #4878d4;color:#000}.bg-gradient-pink-blue{--bslib-color-fg: #ffffff;--bslib-color-bg: #864bb4;background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) #864bb4;color:#fff}.bg-gradient-pink-indigo{--bslib-color-fg: #ffffff;--bslib-color-bg: #a925b0;background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #a925b0;color:#fff}.bg-gradient-pink-purple{--bslib-color-fg: #ffffff;--bslib-color-bg: #ad399c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #ad399c;color:#fff}.bg-gradient-pink-red{--bslib-color-fg: #ffffff;--bslib-color-bg: #d8346b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) #d8346b;color:#fff}.bg-gradient-pink-orange{--bslib-color-fg: #000;--bslib-color-bg: #e65157;background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #e65157;color:#000}.bg-gradient-pink-yellow{--bslib-color-fg: #000;--bslib-color-bg: #e66c52;background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) #e66c52;color:#000}.bg-gradient-pink-green{--bslib-color-fg: #ffffff;--bslib-color-bg: #8a5571;background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) #8a5571;color:#fff}.bg-gradient-pink-teal{--bslib-color-fg: #000;--bslib-color-bg: #8d6f8c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #8d6f8c;color:#000}.bg-gradient-pink-cyan{--bslib-color-fg: #000;--bslib-color-bg: #866faf;background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) #866faf;color:#000}.bg-gradient-red-blue{--bslib-color-fg: #ffffff;--bslib-color-bg: #894c8f;background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) #894c8f;color:#fff}.bg-gradient-red-indigo{--bslib-color-fg: #ffffff;--bslib-color-bg: #ad268a;background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #ad268a;color:#fff}.bg-gradient-red-purple{--bslib-color-fg: #ffffff;--bslib-color-bg: #b03a77;background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #b03a77;color:#fff}.bg-gradient-red-pink{--bslib-color-fg: #ffffff;--bslib-color-bg: #da345e;background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) #da345e;color:#fff}.bg-gradient-red-orange{--bslib-color-fg: #000;--bslib-color-bg: #e95231;background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #e95231;color:#000}.bg-gradient-red-yellow{--bslib-color-fg: #000;--bslib-color-bg: #ea6d2c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) #ea6d2c;color:#000}.bg-gradient-red-green{--bslib-color-fg: #ffffff;--bslib-color-bg: #8e564b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) #8e564b;color:#fff}.bg-gradient-red-teal{--bslib-color-fg: #000;--bslib-color-bg: #917066;background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #917066;color:#000}.bg-gradient-red-cyan{--bslib-color-fg: #000;--bslib-color-bg: #897189;background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) #897189;color:#000}.bg-gradient-orange-blue{--bslib-color-fg: #000;--bslib-color-bg: #9d7871;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) #9d7871;color:#000}.bg-gradient-orange-indigo{--bslib-color-fg: #000;--bslib-color-bg: #c1526d;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #c1526d;color:#000}.bg-gradient-orange-purple{--bslib-color-fg: #000;--bslib-color-bg: #c46659;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #c46659;color:#000}.bg-gradient-orange-pink{--bslib-color-fg: #000;--bslib-color-bg: #ed6041;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) #ed6041;color:#000}.bg-gradient-orange-red{--bslib-color-fg: #000;--bslib-color-bg: #f06128;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) #f06128;color:#000}.bg-gradient-orange-yellow{--bslib-color-fg: #000;--bslib-color-bg: #fe990f;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) #fe990f;color:#000}.bg-gradient-orange-green{--bslib-color-fg: #000;--bslib-color-bg: #a2822e;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) #a2822e;color:#000}.bg-gradient-orange-teal{--bslib-color-fg: #000;--bslib-color-bg: #a59c48;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #a59c48;color:#000}.bg-gradient-orange-cyan{--bslib-color-fg: #000;--bslib-color-bg: #9d9c6c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) #9d9c6c;color:#000}.bg-gradient-yellow-blue{--bslib-color-fg: #000;--bslib-color-bg: #9ea069;background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) #9ea069;color:#000}.bg-gradient-yellow-indigo{--bslib-color-fg: #000;--bslib-color-bg: #c27a65;background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #c27a65;color:#000}.bg-gradient-yellow-purple{--bslib-color-fg: #000;--bslib-color-bg: #c58e51;background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #c58e51;color:#000}.bg-gradient-yellow-pink{--bslib-color-fg: #000;--bslib-color-bg: #ef8839;background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) #ef8839;color:#000}.bg-gradient-yellow-red{--bslib-color-fg: #000;--bslib-color-bg: #f18920;background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) #f18920;color:#000}.bg-gradient-yellow-orange{--bslib-color-fg: #000;--bslib-color-bg: #fea60c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #fea60c;color:#000}.bg-gradient-yellow-green{--bslib-color-fg: #000;--bslib-color-bg: #a3aa26;background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) #a3aa26;color:#000}.bg-gradient-yellow-teal{--bslib-color-fg: #000;--bslib-color-bg: #a6c441;background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #a6c441;color:#000}.bg-gradient-yellow-cyan{--bslib-color-fg: #000;--bslib-color-bg: #9ec564;background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) #9ec564;color:#000}.bg-gradient-green-blue{--bslib-color-fg: #ffffff;--bslib-color-bg: #147d98;background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) #147d98;color:#fff}.bg-gradient-green-indigo{--bslib-color-fg: #ffffff;--bslib-color-bg: #385793;background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #385793;color:#fff}.bg-gradient-green-purple{--bslib-color-fg: #ffffff;--bslib-color-bg: #3b6b80;background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #3b6b80;color:#fff}.bg-gradient-green-pink{--bslib-color-fg: #ffffff;--bslib-color-bg: #656567;background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) #656567;color:#fff}.bg-gradient-green-red{--bslib-color-fg: #ffffff;--bslib-color-bg: #67664e;background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) #67664e;color:#fff}.bg-gradient-green-orange{--bslib-color-fg: #000;--bslib-color-bg: #74833a;background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #74833a;color:#000}.bg-gradient-green-yellow{--bslib-color-fg: #000;--bslib-color-bg: #759e35;background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) #759e35;color:#000}.bg-gradient-green-teal{--bslib-color-fg: #000;--bslib-color-bg: #1ca16f;background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #1ca16f;color:#000}.bg-gradient-green-cyan{--bslib-color-fg: #000;--bslib-color-bg: #14a292;background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) #14a292;color:#000}.bg-gradient-teal-blue{--bslib-color-fg: #000;--bslib-color-bg: #18a5c0;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) #18a5c0;color:#000}.bg-gradient-teal-indigo{--bslib-color-fg: #000;--bslib-color-bg: #3c7fbb;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #3c7fbb;color:#000}.bg-gradient-teal-purple{--bslib-color-fg: #000;--bslib-color-bg: #4093a8;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #4093a8;color:#000}.bg-gradient-teal-pink{--bslib-color-fg: #000;--bslib-color-bg: #698d8f;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) #698d8f;color:#000}.bg-gradient-teal-red{--bslib-color-fg: #000;--bslib-color-bg: #6b8e76;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) #6b8e76;color:#000}.bg-gradient-teal-orange{--bslib-color-fg: #000;--bslib-color-bg: #78ab63;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #78ab63;color:#000}.bg-gradient-teal-yellow{--bslib-color-fg: #000;--bslib-color-bg: #79c65d;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) #79c65d;color:#000}.bg-gradient-teal-green{--bslib-color-fg: #000;--bslib-color-bg: #1daf7c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) #1daf7c;color:#000}.bg-gradient-teal-cyan{--bslib-color-fg: #000;--bslib-color-bg: #18c9bb;background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) #18c9bb;color:#000}.bg-gradient-cyan-blue{--bslib-color-fg: #000;--bslib-color-bg: #0da5f5;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) #0da5f5;color:#000}.bg-gradient-cyan-indigo{--bslib-color-fg: #000;--bslib-color-bg: #3180f1;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) #3180f1;color:#000}.bg-gradient-cyan-purple{--bslib-color-fg: #000;--bslib-color-bg: #3494dd;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) #3494dd;color:#000}.bg-gradient-cyan-pink{--bslib-color-fg: #000;--bslib-color-bg: #5d8ec5;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) #5d8ec5;color:#000}.bg-gradient-cyan-red{--bslib-color-fg: #000;--bslib-color-bg: #608eac;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) #608eac;color:#000}.bg-gradient-cyan-orange{--bslib-color-fg: #000;--bslib-color-bg: #6dac98;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) #6dac98;color:#000}.bg-gradient-cyan-yellow{--bslib-color-fg: #000;--bslib-color-bg: #6ec693;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) #6ec693;color:#000}.bg-gradient-cyan-green{--bslib-color-fg: #000;--bslib-color-bg: #12afb2;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) #12afb2;color:#000}.bg-gradient-cyan-teal{--bslib-color-fg: #000;--bslib-color-bg: #15cacc;background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) #15cacc;color:#000}@media(min-width: 576px){.nav:not(.nav-hidden){display:flex !important;display:-webkit-flex !important}.nav:not(.nav-hidden):not(.nav-stacked):not(.flex-column){float:none !important}.nav:not(.nav-hidden):not(.nav-stacked):not(.flex-column)>.bslib-nav-spacer{margin-left:auto !important}.nav:not(.nav-hidden):not(.nav-stacked):not(.flex-column)>.form-inline{margin-top:auto;margin-bottom:auto}.nav:not(.nav-hidden).nav-stacked{flex-direction:column;-webkit-flex-direction:column;height:100%}.nav:not(.nav-hidden).nav-stacked>.bslib-nav-spacer{margin-top:auto !important}}.bslib-grid{display:grid !important;gap:var(--bslib-spacer, 1rem);height:var(--bslib-grid-height)}.bslib-grid.grid{grid-template-columns:repeat(var(--bs-columns, 12), minmax(0, 1fr));grid-template-rows:unset;grid-auto-rows:var(--bslib-grid--row-heights);--bslib-grid--row-heights--xs: unset;--bslib-grid--row-heights--sm: unset;--bslib-grid--row-heights--md: unset;--bslib-grid--row-heights--lg: unset;--bslib-grid--row-heights--xl: unset;--bslib-grid--row-heights--xxl: unset}.bslib-grid.grid.bslib-grid--row-heights--xs{--bslib-grid--row-heights: var(--bslib-grid--row-heights--xs)}@media(min-width: 576px){.bslib-grid.grid.bslib-grid--row-heights--sm{--bslib-grid--row-heights: var(--bslib-grid--row-heights--sm)}}@media(min-width: 768px){.bslib-grid.grid.bslib-grid--row-heights--md{--bslib-grid--row-heights: var(--bslib-grid--row-heights--md)}}@media(min-width: 992px){.bslib-grid.grid.bslib-grid--row-heights--lg{--bslib-grid--row-heights: var(--bslib-grid--row-heights--lg)}}@media(min-width: 1200px){.bslib-grid.grid.bslib-grid--row-heights--xl{--bslib-grid--row-heights: var(--bslib-grid--row-heights--xl)}}@media(min-width: 1400px){.bslib-grid.grid.bslib-grid--row-heights--xxl{--bslib-grid--row-heights: var(--bslib-grid--row-heights--xxl)}}.bslib-grid>*>.shiny-input-container{width:100%}.bslib-grid-item{grid-column:auto/span 1}@media(max-width: 767.98px){.bslib-grid-item{grid-column:1/-1}}@media(max-width: 575.98px){.bslib-grid{grid-template-columns:1fr !important;height:var(--bslib-grid-height-mobile)}.bslib-grid.grid{height:unset !important;grid-auto-rows:var(--bslib-grid--row-heights--xs, auto)}}.bslib-card{overflow:auto}.bslib-card .card-body+.card-body{padding-top:0}.bslib-card .card-body{overflow:auto}.bslib-card .card-body p{margin-top:0}.bslib-card .card-body p:last-child{margin-bottom:0}.bslib-card .card-body{max-height:var(--bslib-card-body-max-height, none)}.bslib-card[data-full-screen=true]>.card-body{max-height:var(--bslib-card-body-max-height-full-screen, none)}.bslib-card .card-header .form-group{margin-bottom:0}.bslib-card .card-header .selectize-control{margin-bottom:0}.bslib-card .card-header .selectize-control .item{margin-right:1.15rem}.bslib-card .card-footer{margin-top:auto}.bslib-card .bslib-navs-card-title{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center}.bslib-card .bslib-navs-card-title .nav{margin-left:auto}.bslib-card .bslib-sidebar-layout:not([data-bslib-sidebar-border=true]){border:none}.bslib-card .bslib-sidebar-layout:not([data-bslib-sidebar-border-radius=true]){border-top-left-radius:0;border-top-right-radius:0}[data-full-screen=true]{position:fixed;inset:3.5rem 1rem 1rem;height:auto !important;max-height:none !important;width:auto !important;z-index:1070}.bslib-full-screen-enter{display:none;position:absolute;bottom:var(--bslib-full-screen-enter-bottom, 0.2rem);right:var(--bslib-full-screen-enter-right, 0);top:var(--bslib-full-screen-enter-top);left:var(--bslib-full-screen-enter-left);color:var(--bslib-color-fg, var(--bs-card-color));background-color:var(--bslib-color-bg, var(--bs-card-bg, var(--bs-body-bg)));border:var(--bs-card-border-width) solid var(--bslib-color-fg, var(--bs-card-border-color));box-shadow:0 2px 4px rgba(0,0,0,.15);margin:.2rem .4rem;padding:.55rem !important;font-size:.8rem;cursor:pointer;opacity:.7;z-index:1070}.bslib-full-screen-enter:hover{opacity:1}.card[data-full-screen=false]:hover>*>.bslib-full-screen-enter{display:block}.bslib-has-full-screen .card:hover>*>.bslib-full-screen-enter{display:none}@media(max-width: 575.98px){.bslib-full-screen-enter{display:none !important}}.bslib-full-screen-exit{position:relative;top:1.35rem;font-size:.9rem;cursor:pointer;text-decoration:none;display:flex;float:right;margin-right:2.15rem;align-items:center;color:rgba(var(--bs-body-bg-rgb), 0.8)}.bslib-full-screen-exit:hover{color:rgba(var(--bs-body-bg-rgb), 1)}.bslib-full-screen-exit svg{margin-left:.5rem;font-size:1.5rem}#bslib-full-screen-overlay{position:fixed;inset:0;background-color:rgba(var(--bs-body-color-rgb), 0.6);backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);z-index:1069;animation:bslib-full-screen-overlay-enter 400ms cubic-bezier(0.6, 0.02, 0.65, 1) forwards}@keyframes bslib-full-screen-overlay-enter{0%{opacity:0}100%{opacity:1}}html{height:100%}.bslib-page-fill{width:100%;height:100%;margin:0;padding:var(--bslib-spacer, 1rem);gap:var(--bslib-spacer, 1rem)}@media(max-width: 575.98px){.bslib-page-fill{height:var(--bslib-page-fill-mobile-height, auto)}}.bslib-sidebar-layout{--bslib-sidebar-transition-duration: 500ms;--bslib-sidebar-transition-easing-x: cubic-bezier(0.8, 0.78, 0.22, 1.07);--bslib-sidebar-border: var(--bs-card-border-width, 1px) solid var(--bs-card-border-color, rgba(0, 0, 0, 0.175));--bslib-sidebar-border-radius: var(--bs-border-radius);--bslib-sidebar-vert-border: var(--bs-card-border-width, 1px) solid var(--bs-card-border-color, rgba(0, 0, 0, 0.175));--bslib-sidebar-bg: rgba(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.05);--bslib-sidebar-fg: var(--bs-emphasis-color, black);--bslib-sidebar-main-fg: var(--bs-card-color, var(--bs-body-color));--bslib-sidebar-main-bg: var(--bs-card-bg, var(--bs-body-bg));--bslib-sidebar-toggle-bg: rgba(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.1);--bslib-sidebar-padding: calc(var(--bslib-spacer) * 1.5);--bslib-sidebar-icon-size: var(--bslib-spacer, 1rem);--bslib-sidebar-icon-button-size: calc(var(--bslib-sidebar-icon-size, 1rem) * 2);--bslib-sidebar-padding-icon: calc(var(--bslib-sidebar-icon-button-size, 2rem) * 1.5);--bslib-collapse-toggle-border-radius: var(--bs-border-radius, 0.25rem);--bslib-collapse-toggle-transform: 0deg;--bslib-sidebar-toggle-transition-easing: cubic-bezier(1, 0, 0, 1);--bslib-collapse-toggle-right-transform: 180deg;--bslib-sidebar-column-main: minmax(0, 1fr);display:grid !important;grid-template-columns:min(100% - var(--bslib-sidebar-icon-size),var(--bslib-sidebar-width, 250px)) var(--bslib-sidebar-column-main);position:relative;transition:grid-template-columns ease-in-out var(--bslib-sidebar-transition-duration);border:var(--bslib-sidebar-border);border-radius:var(--bslib-sidebar-border-radius)}@media(prefers-reduced-motion: reduce){.bslib-sidebar-layout{transition:none}}.bslib-sidebar-layout[data-bslib-sidebar-border=false]{border:none}.bslib-sidebar-layout[data-bslib-sidebar-border-radius=false]{border-radius:initial}.bslib-sidebar-layout>.main,.bslib-sidebar-layout>.sidebar{grid-row:1/2;border-radius:inherit;overflow:auto}.bslib-sidebar-layout>.main{grid-column:2/3;border-top-left-radius:0;border-bottom-left-radius:0;padding:var(--bslib-sidebar-padding);transition:padding var(--bslib-sidebar-transition-easing-x) var(--bslib-sidebar-transition-duration);color:var(--bslib-sidebar-main-fg);background-color:var(--bslib-sidebar-main-bg)}.bslib-sidebar-layout>.sidebar{grid-column:1/2;width:100%;height:100%;border-right:var(--bslib-sidebar-vert-border);border-top-right-radius:0;border-bottom-right-radius:0;color:var(--bslib-sidebar-fg);background-color:var(--bslib-sidebar-bg);backdrop-filter:blur(5px)}.bslib-sidebar-layout>.sidebar>.sidebar-content{display:flex;flex-direction:column;gap:var(--bslib-spacer, 1rem);padding:var(--bslib-sidebar-padding);padding-top:var(--bslib-sidebar-padding-icon)}.bslib-sidebar-layout>.sidebar>.sidebar-content>:last-child:not(.sidebar-title){margin-bottom:0}.bslib-sidebar-layout>.sidebar>.sidebar-content>.accordion{margin-left:calc(-1*var(--bslib-sidebar-padding));margin-right:calc(-1*var(--bslib-sidebar-padding))}.bslib-sidebar-layout>.sidebar>.sidebar-content>.accordion:last-child{margin-bottom:calc(-1*var(--bslib-sidebar-padding))}.bslib-sidebar-layout>.sidebar>.sidebar-content>.accordion:not(:last-child){margin-bottom:1rem}.bslib-sidebar-layout>.sidebar>.sidebar-content>.accordion .accordion-body{display:flex;flex-direction:column}.bslib-sidebar-layout>.sidebar>.sidebar-content>.accordion:not(:first-child) .accordion-item:first-child{border-top:var(--bs-accordion-border-width) solid var(--bs-accordion-border-color)}.bslib-sidebar-layout>.sidebar>.sidebar-content>.accordion:not(:last-child) .accordion-item:last-child{border-bottom:var(--bs-accordion-border-width) solid var(--bs-accordion-border-color)}.bslib-sidebar-layout>.sidebar>.sidebar-content.has-accordion>.sidebar-title{border-bottom:none;padding-bottom:0}.bslib-sidebar-layout>.sidebar .shiny-input-container{width:100%}.bslib-sidebar-layout[data-bslib-sidebar-open=always]>.sidebar>.sidebar-content{padding-top:var(--bslib-sidebar-padding)}.bslib-sidebar-layout>.collapse-toggle{grid-row:1/2;grid-column:1/2;display:inline-flex;align-items:center;position:absolute;right:calc(var(--bslib-sidebar-icon-size));top:calc(var(--bslib-sidebar-icon-size, 1rem)/2);border:none;border-radius:var(--bslib-collapse-toggle-border-radius);height:var(--bslib-sidebar-icon-button-size, 2rem);width:var(--bslib-sidebar-icon-button-size, 2rem);display:flex;align-items:center;justify-content:center;padding:0;color:var(--bslib-sidebar-fg);background-color:unset;transition:color var(--bslib-sidebar-transition-easing-x) var(--bslib-sidebar-transition-duration),top var(--bslib-sidebar-transition-easing-x) var(--bslib-sidebar-transition-duration),right var(--bslib-sidebar-transition-easing-x) var(--bslib-sidebar-transition-duration),left var(--bslib-sidebar-transition-easing-x) var(--bslib-sidebar-transition-duration)}.bslib-sidebar-layout>.collapse-toggle:hover{background-color:var(--bslib-sidebar-toggle-bg)}.bslib-sidebar-layout>.collapse-toggle>.collapse-icon{opacity:.8;width:var(--bslib-sidebar-icon-size);height:var(--bslib-sidebar-icon-size);transform:rotateY(var(--bslib-collapse-toggle-transform));transition:transform var(--bslib-sidebar-toggle-transition-easing) var(--bslib-sidebar-transition-duration)}.bslib-sidebar-layout>.collapse-toggle:hover>.collapse-icon{opacity:1}.bslib-sidebar-layout .sidebar-title{font-size:1.25rem;line-height:1.25;margin-top:0;margin-bottom:1rem;padding-bottom:1rem;border-bottom:var(--bslib-sidebar-border)}.bslib-sidebar-layout.sidebar-right{grid-template-columns:var(--bslib-sidebar-column-main) min(100% - var(--bslib-sidebar-icon-size),var(--bslib-sidebar-width, 250px))}.bslib-sidebar-layout.sidebar-right>.main{grid-column:1/2;border-top-right-radius:0;border-bottom-right-radius:0;border-top-left-radius:inherit;border-bottom-left-radius:inherit}.bslib-sidebar-layout.sidebar-right>.sidebar{grid-column:2/3;border-right:none;border-left:var(--bslib-sidebar-vert-border);border-top-left-radius:0;border-bottom-left-radius:0}.bslib-sidebar-layout.sidebar-right>.collapse-toggle{grid-column:2/3;left:var(--bslib-sidebar-icon-size);right:unset;border:var(--bslib-collapse-toggle-border)}.bslib-sidebar-layout.sidebar-right>.collapse-toggle>.collapse-icon{transform:rotateY(var(--bslib-collapse-toggle-right-transform))}.bslib-sidebar-layout.sidebar-collapsed{--bslib-collapse-toggle-transform: 180deg;--bslib-collapse-toggle-right-transform: 0deg;--bslib-sidebar-vert-border: none;grid-template-columns:0 minmax(0, 1fr)}.bslib-sidebar-layout.sidebar-collapsed.sidebar-right{grid-template-columns:minmax(0, 1fr) 0}.bslib-sidebar-layout.sidebar-collapsed:not(.transitioning)>.sidebar>*{display:none}.bslib-sidebar-layout.sidebar-collapsed>.main{border-radius:inherit}.bslib-sidebar-layout.sidebar-collapsed:not(.sidebar-right)>.main{padding-left:var(--bslib-sidebar-padding-icon)}.bslib-sidebar-layout.sidebar-collapsed.sidebar-right>.main{padding-right:var(--bslib-sidebar-padding-icon)}.bslib-sidebar-layout.sidebar-collapsed>.collapse-toggle{color:var(--bslib-sidebar-main-fg);top:calc(var(--bslib-sidebar-overlap-counter, 0)*(var(--bslib-sidebar-icon-size) + var(--bslib-sidebar-padding)) + var(--bslib-sidebar-icon-size, 1rem)/2);right:calc(-2.5*var(--bslib-sidebar-icon-size) - var(--bs-card-border-width, 1px))}.bslib-sidebar-layout.sidebar-collapsed.sidebar-right>.collapse-toggle{left:calc(-2.5*var(--bslib-sidebar-icon-size) - var(--bs-card-border-width, 1px));right:unset}@media(min-width: 576px){.bslib-sidebar-layout.transitioning>.sidebar>.sidebar-content{display:none}}@media(max-width: 575.98px){.bslib-sidebar-layout[data-bslib-sidebar-open=desktop]{--bslib-sidebar-js-init-collapsed: true}.bslib-sidebar-layout>.sidebar,.bslib-sidebar-layout.sidebar-right>.sidebar{border:none}.bslib-sidebar-layout>.main,.bslib-sidebar-layout.sidebar-right>.main{grid-column:1/3}.bslib-sidebar-layout[data-bslib-sidebar-open=always]{display:block !important}.bslib-sidebar-layout[data-bslib-sidebar-open=always]>.sidebar{max-height:var(--bslib-sidebar-max-height-mobile);overflow-y:auto;border-top:var(--bslib-sidebar-vert-border)}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]){grid-template-columns:100% 0}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]):not(.sidebar-collapsed)>.sidebar{z-index:1}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]):not(.sidebar-collapsed)>.collapse-toggle{z-index:1}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]).sidebar-right{grid-template-columns:0 100%}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]).sidebar-collapsed{grid-template-columns:0 100%}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]).sidebar-collapsed.sidebar-right{grid-template-columns:100% 0}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]):not(.sidebar-right)>.main{padding-left:var(--bslib-sidebar-padding-icon)}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]).sidebar-right>.main{padding-right:var(--bslib-sidebar-padding-icon)}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always])>.main{opacity:0;transition:opacity var(--bslib-sidebar-transition-easing-x) var(--bslib-sidebar-transition-duration)}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]).sidebar-collapsed>.main{opacity:1}}:root{--bslib-value-box-shadow: none;--bslib-value-box-border-width-auto-yes: var(--bslib-value-box-border-width-baseline);--bslib-value-box-border-width-auto-no: 0;--bslib-value-box-border-width-baseline: 1px}.bslib-value-box{border-width:var(--bslib-value-box-border-width-auto-no, var(--bslib-value-box-border-width-baseline));container-name:bslib-value-box;container-type:inline-size}.bslib-value-box.card{box-shadow:var(--bslib-value-box-shadow)}.bslib-value-box.border-auto{border-width:var(--bslib-value-box-border-width-auto-yes, var(--bslib-value-box-border-width-baseline))}.bslib-value-box.default{--bslib-value-box-bg-default: var(--bs-card-bg, #ffffff);--bslib-value-box-border-color-default: var(--bs-card-border-color, rgba(0, 0, 0, 0.175));color:var(--bslib-value-box-color);background-color:var(--bslib-value-box-bg, var(--bslib-value-box-bg-default));border-color:var(--bslib-value-box-border-color, var(--bslib-value-box-border-color-default))}.bslib-value-box .value-box-grid{display:grid;grid-template-areas:"left right";align-items:center;overflow:hidden}.bslib-value-box .value-box-showcase{height:100%;max-height:var(---bslib-value-box-showcase-max-h, 100%)}.bslib-value-box .value-box-showcase,.bslib-value-box .value-box-showcase>.html-fill-item{width:100%}.bslib-value-box[data-full-screen=true] .value-box-showcase{max-height:var(---bslib-value-box-showcase-max-h-fs, 100%)}@media screen and (min-width: 575.98px){@container bslib-value-box (max-width: 300px){.bslib-value-box:not(.showcase-bottom) .value-box-grid{grid-template-columns:1fr !important;grid-template-rows:auto auto;grid-template-areas:"top" "bottom"}.bslib-value-box:not(.showcase-bottom) .value-box-grid .value-box-showcase{grid-area:top !important}.bslib-value-box:not(.showcase-bottom) .value-box-grid .value-box-area{grid-area:bottom !important;justify-content:end}}}.bslib-value-box .value-box-area{justify-content:center;padding:1.5rem 1rem;font-size:.9rem;font-weight:500}.bslib-value-box .value-box-area *{margin-bottom:0;margin-top:0}.bslib-value-box .value-box-title{font-size:1rem;margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}.bslib-value-box .value-box-title:empty::after{content:" "}.bslib-value-box .value-box-value{font-size:calc(1.29rem + 0.48vw);margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}@media(min-width: 1200px){.bslib-value-box .value-box-value{font-size:1.65rem}}.bslib-value-box .value-box-value:empty::after{content:" "}.bslib-value-box .value-box-showcase{align-items:center;justify-content:center;margin-top:auto;margin-bottom:auto;padding:1rem}.bslib-value-box .value-box-showcase .bi,.bslib-value-box .value-box-showcase .fa,.bslib-value-box .value-box-showcase .fab,.bslib-value-box .value-box-showcase .fas,.bslib-value-box .value-box-showcase .far{opacity:.85;min-width:50px;max-width:125%}.bslib-value-box .value-box-showcase .bi,.bslib-value-box .value-box-showcase .fa,.bslib-value-box .value-box-showcase .fab,.bslib-value-box .value-box-showcase .fas,.bslib-value-box .value-box-showcase .far{font-size:4rem}.bslib-value-box.showcase-top-right .value-box-grid{grid-template-columns:1fr var(---bslib-value-box-showcase-w, 50%)}.bslib-value-box.showcase-top-right .value-box-grid .value-box-showcase{grid-area:right;margin-left:auto;align-self:start;align-items:end;padding-left:0;padding-bottom:0}.bslib-value-box.showcase-top-right .value-box-grid .value-box-area{grid-area:left;align-self:end}.bslib-value-box.showcase-top-right[data-full-screen=true] .value-box-grid{grid-template-columns:auto var(---bslib-value-box-showcase-w-fs, 1fr)}.bslib-value-box.showcase-top-right[data-full-screen=true] .value-box-grid>div{align-self:center}.bslib-value-box.showcase-top-right:not([data-full-screen=true]) .value-box-showcase{margin-top:0}@container bslib-value-box (max-width: 300px){.bslib-value-box.showcase-top-right:not([data-full-screen=true]) .value-box-grid .value-box-showcase{padding-left:1rem}}.bslib-value-box.showcase-left-center .value-box-grid{grid-template-columns:var(---bslib-value-box-showcase-w, 30%) auto}.bslib-value-box.showcase-left-center[data-full-screen=true] .value-box-grid{grid-template-columns:var(---bslib-value-box-showcase-w-fs, 1fr) auto}.bslib-value-box.showcase-left-center:not([data-fill-screen=true]) .value-box-grid .value-box-showcase{grid-area:left}.bslib-value-box.showcase-left-center:not([data-fill-screen=true]) .value-box-grid .value-box-area{grid-area:right}.bslib-value-box.showcase-bottom .value-box-grid{grid-template-columns:1fr;grid-template-rows:1fr var(---bslib-value-box-showcase-h, auto);grid-template-areas:"top" "bottom";overflow:hidden}.bslib-value-box.showcase-bottom .value-box-grid .value-box-showcase{grid-area:bottom;padding:0;margin:0}.bslib-value-box.showcase-bottom .value-box-grid .value-box-area{grid-area:top}.bslib-value-box.showcase-bottom[data-full-screen=true] .value-box-grid{grid-template-rows:1fr var(---bslib-value-box-showcase-h-fs, 2fr)}.bslib-value-box.showcase-bottom[data-full-screen=true] .value-box-grid .value-box-showcase{padding:1rem}[data-bs-theme=dark] .bslib-value-box{--bslib-value-box-shadow: 0 0.5rem 1rem rgb(0 0 0 / 50%)}.navbar+.container-fluid:has(>.tab-content>.tab-pane.active.html-fill-container),.navbar+.container-sm:has(>.tab-content>.tab-pane.active.html-fill-container),.navbar+.container-md:has(>.tab-content>.tab-pane.active.html-fill-container),.navbar+.container-lg:has(>.tab-content>.tab-pane.active.html-fill-container),.navbar+.container-xl:has(>.tab-content>.tab-pane.active.html-fill-container),.navbar+.container-xxl:has(>.tab-content>.tab-pane.active.html-fill-container){padding-left:0;padding-right:0}.navbar+.container-fluid>.tab-content>.tab-pane.active.html-fill-container,.navbar+.container-sm>.tab-content>.tab-pane.active.html-fill-container,.navbar+.container-md>.tab-content>.tab-pane.active.html-fill-container,.navbar+.container-lg>.tab-content>.tab-pane.active.html-fill-container,.navbar+.container-xl>.tab-content>.tab-pane.active.html-fill-container,.navbar+.container-xxl>.tab-content>.tab-pane.active.html-fill-container{padding:var(--bslib-spacer, 1rem);gap:var(--bslib-spacer, 1rem)}.navbar+.container-fluid>.tab-content>.tab-pane.active.html-fill-container:has(>.bslib-sidebar-layout:only-child),.navbar+.container-sm>.tab-content>.tab-pane.active.html-fill-container:has(>.bslib-sidebar-layout:only-child),.navbar+.container-md>.tab-content>.tab-pane.active.html-fill-container:has(>.bslib-sidebar-layout:only-child),.navbar+.container-lg>.tab-content>.tab-pane.active.html-fill-container:has(>.bslib-sidebar-layout:only-child),.navbar+.container-xl>.tab-content>.tab-pane.active.html-fill-container:has(>.bslib-sidebar-layout:only-child),.navbar+.container-xxl>.tab-content>.tab-pane.active.html-fill-container:has(>.bslib-sidebar-layout:only-child){padding:0}.navbar+.container-fluid>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border=true]),.navbar+.container-sm>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border=true]),.navbar+.container-md>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border=true]),.navbar+.container-lg>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border=true]),.navbar+.container-xl>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border=true]),.navbar+.container-xxl>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border=true]){border-left:none;border-right:none;border-bottom:none}.navbar+.container-fluid>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border-radius=true]),.navbar+.container-sm>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border-radius=true]),.navbar+.container-md>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border-radius=true]),.navbar+.container-lg>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border-radius=true]),.navbar+.container-xl>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border-radius=true]),.navbar+.container-xxl>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border-radius=true]){border-radius:0}.navbar+div>.bslib-sidebar-layout{border-top:var(--bslib-sidebar-border)}.accordion .accordion-header{font-size:calc(1.29rem + 0.48vw);margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2;color:var(--bs-heading-color);margin-bottom:0}@media(min-width: 1200px){.accordion .accordion-header{font-size:1.65rem}}.accordion .accordion-icon:not(:empty){margin-right:.75rem;display:flex}.accordion .accordion-button:not(.collapsed){box-shadow:none}.accordion .accordion-button:not(.collapsed):focus{box-shadow:var(--bs-accordion-btn-focus-box-shadow)}:root{--bslib-page-sidebar-title-bg: #fff;--bslib-page-sidebar-title-color: #000}.bslib-page-title{background-color:var(--bslib-page-sidebar-title-bg);color:var(--bslib-page-sidebar-title-color);font-size:1.25rem;font-weight:300;padding:var(--bslib-spacer, 1rem);padding-left:1.5rem;margin-bottom:0;border-bottom:1px solid #dee2e6}.html-fill-container{display:flex;flex-direction:column;min-height:0;min-width:0}.html-fill-container>.html-fill-item{flex:1 1 auto;min-height:0;min-width:0}.html-fill-container>:not(.html-fill-item){flex:0 0 auto}.quarto-container{min-height:calc(100vh - 132px)}body.hypothesis-enabled #quarto-header{margin-right:16px}footer.footer .nav-footer,#quarto-header>nav{padding-left:1em;padding-right:1em}footer.footer div.nav-footer p:first-child{margin-top:0}footer.footer div.nav-footer p:last-child{margin-bottom:0}#quarto-content>*{padding-top:14px}#quarto-content>#quarto-sidebar-glass{padding-top:0px}@media(max-width: 991.98px){#quarto-content>*{padding-top:0}#quarto-content .subtitle{padding-top:14px}#quarto-content section:first-of-type h2:first-of-type,#quarto-content section:first-of-type .h2:first-of-type{margin-top:1rem}}.headroom-target,header.headroom{will-change:transform;transition:position 200ms linear;transition:all 200ms linear}header.headroom--pinned{transform:translateY(0%)}header.headroom--unpinned{transform:translateY(-100%)}.navbar-container{width:100%}.navbar-brand{overflow:hidden;text-overflow:ellipsis}.navbar-brand-container{max-width:calc(100% - 115px);min-width:0;display:flex;align-items:center}@media(min-width: 992px){.navbar-brand-container{margin-right:1em}}.navbar-brand.navbar-brand-logo{margin-right:4px;display:inline-flex}.navbar-toggler{flex-basis:content;flex-shrink:0}.navbar .navbar-brand-container{order:2}.navbar .navbar-toggler{order:1}.navbar .navbar-container>.navbar-nav{order:20}.navbar .navbar-container>.navbar-brand-container{margin-left:0 !important;margin-right:0 !important}.navbar .navbar-collapse{order:20}.navbar #quarto-search{order:4;margin-left:auto}.navbar .navbar-toggler{margin-right:.5em}.navbar-collapse .quarto-navbar-tools{margin-left:.5em}.navbar-logo{max-height:24px;width:auto;padding-right:4px}nav .nav-item:not(.compact){padding-top:1px}nav .nav-link i,nav .dropdown-item i{padding-right:1px}.navbar-expand-lg .navbar-nav .nav-link{padding-left:.6rem;padding-right:.6rem}nav .nav-item.compact .nav-link{padding-left:.5rem;padding-right:.5rem;font-size:1.1rem}.navbar .quarto-navbar-tools{order:3}.navbar .quarto-navbar-tools div.dropdown{display:inline-block}.navbar .quarto-navbar-tools .quarto-navigation-tool{color:#595959}.navbar .quarto-navbar-tools .quarto-navigation-tool:hover{color:#035f88}.navbar-nav .dropdown-menu{min-width:220px;font-size:.9rem}.navbar .navbar-nav .nav-link.dropdown-toggle::after{opacity:.75;vertical-align:.175em}.navbar ul.dropdown-menu{padding-top:0;padding-bottom:0}.navbar .dropdown-header{text-transform:uppercase;font-size:.8rem;padding:0 .5rem}.navbar .dropdown-item{padding:.4rem .5rem}.navbar .dropdown-item>i.bi{margin-left:.1rem;margin-right:.25em}.sidebar #quarto-search{margin-top:-1px}.sidebar #quarto-search svg.aa-SubmitIcon{width:16px;height:16px}.sidebar-navigation a{color:inherit}.sidebar-title{margin-top:.25rem;padding-bottom:.5rem;font-size:1.3rem;line-height:1.6rem;visibility:visible}.sidebar-title>a{font-size:inherit;text-decoration:none}.sidebar-title .sidebar-tools-main{margin-top:-6px}@media(max-width: 991.98px){#quarto-sidebar div.sidebar-header{padding-top:.2em}}.sidebar-header-stacked .sidebar-title{margin-top:.6rem}.sidebar-logo{max-width:90%;padding-bottom:.5rem}.sidebar-logo-link{text-decoration:none}.sidebar-navigation li a{text-decoration:none}.sidebar-navigation .quarto-navigation-tool{opacity:.7;font-size:.875rem}#quarto-sidebar>nav>.sidebar-tools-main{margin-left:14px}.sidebar-tools-main{display:inline-flex;margin-left:0px;order:2}.sidebar-tools-main:not(.tools-wide){vertical-align:middle}.sidebar-navigation .quarto-navigation-tool.dropdown-toggle::after{display:none}.sidebar.sidebar-navigation>*{padding-top:1em}.sidebar-item{margin-bottom:.2em;line-height:1rem;margin-top:.4rem}.sidebar-section{padding-left:.5em;padding-bottom:.2em}.sidebar-item .sidebar-item-container{display:flex;justify-content:space-between;cursor:pointer}.sidebar-item-toggle:hover{cursor:pointer}.sidebar-item .sidebar-item-toggle .bi{font-size:.7rem;text-align:center}.sidebar-item .sidebar-item-toggle .bi-chevron-right::before{transition:transform 200ms ease}.sidebar-item .sidebar-item-toggle[aria-expanded=false] .bi-chevron-right::before{transform:none}.sidebar-item .sidebar-item-toggle[aria-expanded=true] .bi-chevron-right::before{transform:rotate(90deg)}.sidebar-item-text{width:100%}.sidebar-navigation .sidebar-divider{margin-left:0;margin-right:0;margin-top:.5rem;margin-bottom:.5rem}@media(max-width: 991.98px){.quarto-secondary-nav{display:block}.quarto-secondary-nav button.quarto-search-button{padding-right:0em;padding-left:2em}.quarto-secondary-nav button.quarto-btn-toggle{margin-left:-0.75rem;margin-right:.15rem}.quarto-secondary-nav nav.quarto-title-breadcrumbs{display:none}.quarto-secondary-nav nav.quarto-page-breadcrumbs{display:flex;align-items:center;padding-right:1em;margin-left:-0.25em}.quarto-secondary-nav nav.quarto-page-breadcrumbs a{text-decoration:none}.quarto-secondary-nav nav.quarto-page-breadcrumbs ol.breadcrumb{margin-bottom:0}}@media(min-width: 992px){.quarto-secondary-nav{display:none}}.quarto-title-breadcrumbs .breadcrumb{margin-bottom:.5em;font-size:.9rem}.quarto-title-breadcrumbs .breadcrumb li:last-of-type a{color:#6c757d}.quarto-secondary-nav .quarto-btn-toggle{color:#595959}.quarto-secondary-nav[aria-expanded=false] .quarto-btn-toggle .bi-chevron-right::before{transform:none}.quarto-secondary-nav[aria-expanded=true] .quarto-btn-toggle .bi-chevron-right::before{transform:rotate(90deg)}.quarto-secondary-nav .quarto-btn-toggle .bi-chevron-right::before{transition:transform 200ms ease}.quarto-secondary-nav{cursor:pointer}.no-decor{text-decoration:none}.quarto-secondary-nav-title{margin-top:.3em;color:#595959;padding-top:4px}.quarto-secondary-nav nav.quarto-page-breadcrumbs{color:#595959}.quarto-secondary-nav nav.quarto-page-breadcrumbs a{color:#595959}.quarto-secondary-nav nav.quarto-page-breadcrumbs a:hover{color:rgba(3,95,136,.8)}.quarto-secondary-nav nav.quarto-page-breadcrumbs .breadcrumb-item::before{color:#8c8c8c}.breadcrumb-item{line-height:1.2rem}div.sidebar-item-container{color:#595959}div.sidebar-item-container:hover,div.sidebar-item-container:focus{color:rgba(3,95,136,.8)}div.sidebar-item-container.disabled{color:rgba(89,89,89,.75)}div.sidebar-item-container .active,div.sidebar-item-container .show>.nav-link,div.sidebar-item-container .sidebar-link>code{color:#035f88}div.sidebar.sidebar-navigation.rollup.quarto-sidebar-toggle-contents,nav.sidebar.sidebar-navigation:not(.rollup){background-color:#fff}@media(max-width: 991.98px){.sidebar-navigation .sidebar-item a,.nav-page .nav-page-text,.sidebar-navigation{font-size:1rem}.sidebar-navigation ul.sidebar-section.depth1 .sidebar-section-item{font-size:1.1rem}.sidebar-logo{display:none}.sidebar.sidebar-navigation{position:static;border-bottom:1px solid #dee2e6}.sidebar.sidebar-navigation.collapsing{position:fixed;z-index:1000}.sidebar.sidebar-navigation.show{position:fixed;z-index:1000}.sidebar.sidebar-navigation{min-height:100%}nav.quarto-secondary-nav{background-color:#fff;border-bottom:1px solid #dee2e6}.quarto-banner nav.quarto-secondary-nav{background-color:#fff;color:#595959;border-top:1px solid #dee2e6}.sidebar .sidebar-footer{visibility:visible;padding-top:1rem;position:inherit}.sidebar-tools-collapse{display:block}}#quarto-sidebar{transition:width .15s ease-in}#quarto-sidebar>*{padding-right:1em}@media(max-width: 991.98px){#quarto-sidebar .sidebar-menu-container{white-space:nowrap;min-width:225px}#quarto-sidebar.show{transition:width .15s ease-out}}@media(min-width: 992px){#quarto-sidebar{display:flex;flex-direction:column}.nav-page .nav-page-text,.sidebar-navigation .sidebar-section .sidebar-item{font-size:.875rem}.sidebar-navigation .sidebar-item{font-size:.925rem}.sidebar.sidebar-navigation{display:block;position:sticky}.sidebar-search{width:100%}.sidebar .sidebar-footer{visibility:visible}}@media(min-width: 992px){#quarto-sidebar-glass{display:none}}@media(max-width: 991.98px){#quarto-sidebar-glass{position:fixed;top:0;bottom:0;left:0;right:0;background-color:rgba(255,255,255,0);transition:background-color .15s ease-in;z-index:-1}#quarto-sidebar-glass.collapsing{z-index:1000}#quarto-sidebar-glass.show{transition:background-color .15s ease-out;background-color:rgba(102,102,102,.4);z-index:1000}}.sidebar .sidebar-footer{padding:.5rem 1rem;align-self:flex-end;color:#6c757d;width:100%}.quarto-page-breadcrumbs .breadcrumb-item+.breadcrumb-item,.quarto-page-breadcrumbs .breadcrumb-item{padding-right:.33em;padding-left:0}.quarto-page-breadcrumbs .breadcrumb-item::before{padding-right:.33em}.quarto-sidebar-footer{font-size:.875em}.sidebar-section .bi-chevron-right{vertical-align:middle}.sidebar-section .bi-chevron-right::before{font-size:.9em}.notransition{-webkit-transition:none !important;-moz-transition:none !important;-o-transition:none !important;transition:none !important}.btn:focus:not(:focus-visible){box-shadow:none}.page-navigation{display:flex;justify-content:space-between}.nav-page{padding-bottom:.75em}.nav-page .bi{font-size:1.8rem;vertical-align:middle}.nav-page .nav-page-text{padding-left:.25em;padding-right:.25em}.nav-page a{color:#6c757d;text-decoration:none;display:flex;align-items:center}.nav-page a:hover{color:#024f72}.nav-footer .toc-actions{padding-bottom:.5em;padding-top:.5em}.nav-footer .toc-actions a,.nav-footer .toc-actions a:hover{text-decoration:none}.nav-footer .toc-actions ul{display:flex;list-style:none}.nav-footer .toc-actions ul :first-child{margin-left:auto}.nav-footer .toc-actions ul :last-child{margin-right:auto}.nav-footer .toc-actions ul li{padding-right:1.5em}.nav-footer .toc-actions ul li i.bi{padding-right:.4em}.nav-footer .toc-actions ul li:last-of-type{padding-right:0}.nav-footer{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:space-between;align-items:baseline;text-align:center;padding-top:.5rem;padding-bottom:.5rem;background-color:#fff}body.nav-fixed{padding-top:64px}.nav-footer-contents{color:#6c757d;margin-top:.25rem}.nav-footer{min-height:3.5em;color:#757575}.nav-footer a{color:#757575}.nav-footer .nav-footer-left{font-size:.825em}.nav-footer .nav-footer-center{font-size:.825em}.nav-footer .nav-footer-right{font-size:.825em}.nav-footer-left .footer-items,.nav-footer-center .footer-items,.nav-footer-right .footer-items{display:inline-flex;padding-top:.3em;padding-bottom:.3em;margin-bottom:0em}.nav-footer-left .footer-items .nav-link,.nav-footer-center .footer-items .nav-link,.nav-footer-right .footer-items .nav-link{padding-left:.6em;padding-right:.6em}@media(min-width: 768px){.nav-footer-left{flex:1 1 0px;text-align:left}}@media(max-width: 575.98px){.nav-footer-left{margin-bottom:1em;flex:100%}}@media(min-width: 768px){.nav-footer-right{flex:1 1 0px;text-align:right}}@media(max-width: 575.98px){.nav-footer-right{margin-bottom:1em;flex:100%}}.nav-footer-center{text-align:center;min-height:3em}@media(min-width: 768px){.nav-footer-center{flex:1 1 0px}}.nav-footer-center .footer-items{justify-content:center}@media(max-width: 767.98px){.nav-footer-center{margin-bottom:1em;flex:100%}}@media(max-width: 767.98px){.nav-footer-center{margin-top:3em;order:10}}.navbar .quarto-reader-toggle.reader .quarto-reader-toggle-btn{background-color:#595959;border-radius:3px}@media(max-width: 991.98px){.quarto-reader-toggle{display:none}}.quarto-reader-toggle.reader.quarto-navigation-tool .quarto-reader-toggle-btn{background-color:#595959;border-radius:3px}.quarto-reader-toggle .quarto-reader-toggle-btn{display:inline-flex;padding-left:.2em;padding-right:.2em;margin-left:-0.2em;margin-right:-0.2em;text-align:center}.navbar .quarto-reader-toggle:not(.reader) .bi::before{background-image:url('data:image/svg+xml,')}.navbar .quarto-reader-toggle.reader .bi::before{background-image:url('data:image/svg+xml,')}.sidebar-navigation .quarto-reader-toggle:not(.reader) .bi::before{background-image:url('data:image/svg+xml,')}.sidebar-navigation .quarto-reader-toggle.reader .bi::before{background-image:url('data:image/svg+xml,')}#quarto-back-to-top{display:none;position:fixed;bottom:50px;background-color:#fff;border-radius:.25rem;box-shadow:0 .2rem .5rem #6c757d,0 0 .05rem #6c757d;color:#6c757d;text-decoration:none;font-size:.9em;text-align:center;left:50%;padding:.4rem .8rem;transform:translate(-50%, 0)}#quarto-announcement{padding:.5em;display:flex;justify-content:space-between;margin-bottom:0;font-size:.9em}#quarto-announcement .quarto-announcement-content{margin-right:auto}#quarto-announcement .quarto-announcement-content p{margin-bottom:0}#quarto-announcement .quarto-announcement-icon{margin-right:.5em;font-size:1.2em;margin-top:-0.15em}#quarto-announcement .quarto-announcement-action{cursor:pointer}.aa-DetachedSearchButtonQuery{display:none}.aa-DetachedOverlay ul.aa-List,#quarto-search-results ul.aa-List{list-style:none;padding-left:0}.aa-DetachedOverlay .aa-Panel,#quarto-search-results .aa-Panel{background-color:#fff;position:absolute;z-index:2000}#quarto-search-results .aa-Panel{max-width:400px}#quarto-search input{font-size:.925rem}@media(min-width: 992px){.navbar #quarto-search{margin-left:.25rem;order:999}}.navbar.navbar-expand-sm #quarto-search,.navbar.navbar-expand-md #quarto-search{order:999}@media(min-width: 992px){.navbar .quarto-navbar-tools{order:900}}@media(min-width: 992px){.navbar .quarto-navbar-tools.tools-end{margin-left:auto !important}}@media(max-width: 991.98px){#quarto-sidebar .sidebar-search{display:none}}#quarto-sidebar .sidebar-search .aa-Autocomplete{width:100%}.navbar .aa-Autocomplete .aa-Form{width:180px}.navbar #quarto-search.type-overlay .aa-Autocomplete{width:40px}.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form{background-color:inherit;border:none}.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form:focus-within{box-shadow:none;outline:none}.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form .aa-InputWrapper{display:none}.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form .aa-InputWrapper:focus-within{display:inherit}.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form .aa-Label svg,.navbar #quarto-search.type-overlay .aa-Autocomplete .aa-Form .aa-LoadingIndicator svg{width:26px;height:26px;color:#595959;opacity:1}.navbar #quarto-search.type-overlay .aa-Autocomplete svg.aa-SubmitIcon{width:26px;height:26px;color:#595959;opacity:1}.aa-Autocomplete .aa-Form,.aa-DetachedFormContainer .aa-Form{align-items:center;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;color:#212529;display:flex;line-height:1em;margin:0;position:relative;width:100%}.aa-Autocomplete .aa-Form:focus-within,.aa-DetachedFormContainer .aa-Form:focus-within{box-shadow:rgba(13,110,253,.6) 0 0 0 1px;outline:currentColor none medium}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix{align-items:center;display:flex;flex-shrink:0;order:1}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-Label,.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-Label,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator{cursor:initial;flex-shrink:0;padding:0;text-align:left}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-Label svg,.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator svg,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-Label svg,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator svg{color:#212529;opacity:.5}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-SubmitButton,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-SubmitButton{appearance:none;background:none;border:0;margin:0}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator{align-items:center;display:flex;justify-content:center}.aa-Autocomplete .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator[hidden],.aa-DetachedFormContainer .aa-Form .aa-InputWrapperPrefix .aa-LoadingIndicator[hidden]{display:none}.aa-Autocomplete .aa-Form .aa-InputWrapper,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper{order:3;position:relative;width:100%}.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input{appearance:none;background:none;border:0;color:#212529;font:inherit;height:calc(1.5em + .1rem + 2px);padding:0;width:100%}.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input::placeholder,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input::placeholder{color:#212529;opacity:.8}.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input:focus,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input:focus{border-color:none;box-shadow:none;outline:none}.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-decoration,.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-cancel-button,.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-results-button,.aa-Autocomplete .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-results-decoration,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-decoration,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-cancel-button,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-results-button,.aa-DetachedFormContainer .aa-Form .aa-InputWrapper .aa-Input::-webkit-search-results-decoration{display:none}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix{align-items:center;display:flex;order:4}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-ClearButton,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-ClearButton{align-items:center;background:none;border:0;color:#212529;opacity:.8;cursor:pointer;display:flex;margin:0;width:calc(1.5em + .1rem + 2px)}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-ClearButton:hover,.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-ClearButton:focus,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-ClearButton:hover,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-ClearButton:focus{color:#212529;opacity:.8}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-ClearButton[hidden],.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-ClearButton[hidden]{display:none}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-ClearButton svg,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-ClearButton svg{width:calc(1.5em + 0.75rem + calc(1px * 2))}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-CopyButton,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-CopyButton{border:none;align-items:center;background:none;color:#212529;opacity:.4;font-size:.7rem;cursor:pointer;display:none;margin:0;width:calc(1em + .1rem + 2px)}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-CopyButton:hover,.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-CopyButton:focus,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-CopyButton:hover,.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-CopyButton:focus{color:#212529;opacity:.8}.aa-Autocomplete .aa-Form .aa-InputWrapperSuffix .aa-CopyButton[hidden],.aa-DetachedFormContainer .aa-Form .aa-InputWrapperSuffix .aa-CopyButton[hidden]{display:none}.aa-PanelLayout:empty{display:none}.quarto-search-no-results.no-query{display:none}.aa-Source:has(.no-query){display:none}#quarto-search-results .aa-Panel{border:solid #dee2e6 1px}#quarto-search-results .aa-SourceNoResults{width:398px}.aa-DetachedOverlay .aa-Panel,#quarto-search-results .aa-Panel{max-height:65vh;overflow-y:auto;font-size:.925rem}.aa-DetachedOverlay .aa-SourceNoResults,#quarto-search-results .aa-SourceNoResults{height:60px;display:flex;justify-content:center;align-items:center}.aa-DetachedOverlay .search-error,#quarto-search-results .search-error{padding-top:10px;padding-left:20px;padding-right:20px;cursor:default}.aa-DetachedOverlay .search-error .search-error-title,#quarto-search-results .search-error .search-error-title{font-size:1.1rem;margin-bottom:.5rem}.aa-DetachedOverlay .search-error .search-error-title .search-error-icon,#quarto-search-results .search-error .search-error-title .search-error-icon{margin-right:8px}.aa-DetachedOverlay .search-error .search-error-text,#quarto-search-results .search-error .search-error-text{font-weight:300}.aa-DetachedOverlay .search-result-text,#quarto-search-results .search-result-text{font-weight:300;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;line-height:1.2rem;max-height:2.4rem}.aa-DetachedOverlay .aa-SourceHeader .search-result-header,#quarto-search-results .aa-SourceHeader .search-result-header{font-size:.875rem;background-color:#f2f2f2;padding-left:14px;padding-bottom:4px;padding-top:4px}.aa-DetachedOverlay .aa-SourceHeader .search-result-header-no-results,#quarto-search-results .aa-SourceHeader .search-result-header-no-results{display:none}.aa-DetachedOverlay .aa-SourceFooter .algolia-search-logo,#quarto-search-results .aa-SourceFooter .algolia-search-logo{width:110px;opacity:.85;margin:8px;float:right}.aa-DetachedOverlay .search-result-section,#quarto-search-results .search-result-section{font-size:.925em}.aa-DetachedOverlay a.search-result-link,#quarto-search-results a.search-result-link{color:inherit;text-decoration:none}.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item,#quarto-search-results li.aa-Item[aria-selected=true] .search-item{background-color:#0d6efd}.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item.search-result-more,.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item .search-result-section,.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item .search-result-text,.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item .search-result-title-container,.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item .search-result-text-container,#quarto-search-results li.aa-Item[aria-selected=true] .search-item.search-result-more,#quarto-search-results li.aa-Item[aria-selected=true] .search-item .search-result-section,#quarto-search-results li.aa-Item[aria-selected=true] .search-item .search-result-text,#quarto-search-results li.aa-Item[aria-selected=true] .search-item .search-result-title-container,#quarto-search-results li.aa-Item[aria-selected=true] .search-item .search-result-text-container{color:#fff;background-color:#0d6efd}.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item mark.search-match,.aa-DetachedOverlay li.aa-Item[aria-selected=true] .search-item .search-match.mark,#quarto-search-results li.aa-Item[aria-selected=true] .search-item mark.search-match,#quarto-search-results li.aa-Item[aria-selected=true] .search-item .search-match.mark{color:#fff;background-color:#3586fd}.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item,#quarto-search-results li.aa-Item[aria-selected=false] .search-item{background-color:#fff}.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item.search-result-more,.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item .search-result-section,.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item .search-result-text,.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item .search-result-title-container,.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item .search-result-text-container,#quarto-search-results li.aa-Item[aria-selected=false] .search-item.search-result-more,#quarto-search-results li.aa-Item[aria-selected=false] .search-item .search-result-section,#quarto-search-results li.aa-Item[aria-selected=false] .search-item .search-result-text,#quarto-search-results li.aa-Item[aria-selected=false] .search-item .search-result-title-container,#quarto-search-results li.aa-Item[aria-selected=false] .search-item .search-result-text-container{color:#212529}.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item mark.search-match,.aa-DetachedOverlay li.aa-Item[aria-selected=false] .search-item .search-match.mark,#quarto-search-results li.aa-Item[aria-selected=false] .search-item mark.search-match,#quarto-search-results li.aa-Item[aria-selected=false] .search-item .search-match.mark{color:inherit;background-color:#e1edff}.aa-DetachedOverlay .aa-Item .search-result-doc:not(.document-selectable) .search-result-title-container,#quarto-search-results .aa-Item .search-result-doc:not(.document-selectable) .search-result-title-container{background-color:#fff;color:#212529}.aa-DetachedOverlay .aa-Item .search-result-doc:not(.document-selectable) .search-result-text-container,#quarto-search-results .aa-Item .search-result-doc:not(.document-selectable) .search-result-text-container{padding-top:0px}.aa-DetachedOverlay li.aa-Item .search-result-doc.document-selectable .search-result-text-container,#quarto-search-results li.aa-Item .search-result-doc.document-selectable .search-result-text-container{margin-top:-4px}.aa-DetachedOverlay .aa-Item,#quarto-search-results .aa-Item{cursor:pointer}.aa-DetachedOverlay .aa-Item .search-item,#quarto-search-results .aa-Item .search-item{border-left:none;border-right:none;border-top:none;background-color:#fff;border-color:#dee2e6;color:#212529}.aa-DetachedOverlay .aa-Item .search-item p,#quarto-search-results .aa-Item .search-item p{margin-top:0;margin-bottom:0}.aa-DetachedOverlay .aa-Item .search-item i.bi,#quarto-search-results .aa-Item .search-item i.bi{padding-left:8px;padding-right:8px;font-size:1.3em}.aa-DetachedOverlay .aa-Item .search-item .search-result-title,#quarto-search-results .aa-Item .search-item .search-result-title{margin-top:.3em;margin-bottom:0em}.aa-DetachedOverlay .aa-Item .search-item .search-result-crumbs,#quarto-search-results .aa-Item .search-item .search-result-crumbs{white-space:nowrap;text-overflow:ellipsis;font-size:.8em;font-weight:300;margin-right:1em}.aa-DetachedOverlay .aa-Item .search-item .search-result-crumbs:not(.search-result-crumbs-wrap),#quarto-search-results .aa-Item .search-item .search-result-crumbs:not(.search-result-crumbs-wrap){max-width:30%;margin-left:auto;margin-top:.5em;margin-bottom:.1rem}.aa-DetachedOverlay .aa-Item .search-item .search-result-crumbs.search-result-crumbs-wrap,#quarto-search-results .aa-Item .search-item .search-result-crumbs.search-result-crumbs-wrap{flex-basis:100%;margin-top:0em;margin-bottom:.2em;margin-left:37px}.aa-DetachedOverlay .aa-Item .search-result-title-container,#quarto-search-results .aa-Item .search-result-title-container{font-size:1em;display:flex;flex-wrap:wrap;padding:6px 4px 6px 4px}.aa-DetachedOverlay .aa-Item .search-result-text-container,#quarto-search-results .aa-Item .search-result-text-container{padding-bottom:8px;padding-right:8px;margin-left:42px}.aa-DetachedOverlay .aa-Item .search-result-doc-section,.aa-DetachedOverlay .aa-Item .search-result-more,#quarto-search-results .aa-Item .search-result-doc-section,#quarto-search-results .aa-Item .search-result-more{padding-top:8px;padding-bottom:8px;padding-left:44px}.aa-DetachedOverlay .aa-Item .search-result-more,#quarto-search-results .aa-Item .search-result-more{font-size:.8em;font-weight:400}.aa-DetachedOverlay .aa-Item .search-result-doc,#quarto-search-results .aa-Item .search-result-doc{border-top:1px solid #dee2e6}.aa-DetachedSearchButton{background:none;border:none}.aa-DetachedSearchButton .aa-DetachedSearchButtonPlaceholder{display:none}.navbar .aa-DetachedSearchButton .aa-DetachedSearchButtonIcon{color:#595959}.sidebar-tools-collapse #quarto-search,.sidebar-tools-main #quarto-search{display:inline}.sidebar-tools-collapse #quarto-search .aa-Autocomplete,.sidebar-tools-main #quarto-search .aa-Autocomplete{display:inline}.sidebar-tools-collapse #quarto-search .aa-DetachedSearchButton,.sidebar-tools-main #quarto-search .aa-DetachedSearchButton{padding-left:4px;padding-right:4px}.sidebar-tools-collapse #quarto-search .aa-DetachedSearchButton .aa-DetachedSearchButtonIcon,.sidebar-tools-main #quarto-search .aa-DetachedSearchButton .aa-DetachedSearchButtonIcon{color:#595959}.sidebar-tools-collapse #quarto-search .aa-DetachedSearchButton .aa-DetachedSearchButtonIcon .aa-SubmitIcon,.sidebar-tools-main #quarto-search .aa-DetachedSearchButton .aa-DetachedSearchButtonIcon .aa-SubmitIcon{margin-top:-3px}.aa-DetachedContainer{background:rgba(255,255,255,.65);width:90%;bottom:0;box-shadow:rgba(222,226,230,.6) 0 0 0 1px;outline:currentColor none medium;display:flex;flex-direction:column;left:0;margin:0;overflow:hidden;padding:0;position:fixed;right:0;top:0;z-index:1101}.aa-DetachedContainer::after{height:32px}.aa-DetachedContainer .aa-SourceHeader{margin:var(--aa-spacing-half) 0 var(--aa-spacing-half) 2px}.aa-DetachedContainer .aa-Panel{background-color:#fff;border-radius:0;box-shadow:none;flex-grow:1;margin:0;padding:0;position:relative}.aa-DetachedContainer .aa-PanelLayout{bottom:0;box-shadow:none;left:0;margin:0;max-height:none;overflow-y:auto;position:absolute;right:0;top:0;width:100%}.aa-DetachedFormContainer{background-color:#fff;border-bottom:1px solid #dee2e6;display:flex;flex-direction:row;justify-content:space-between;margin:0;padding:.5em}.aa-DetachedCancelButton{background:none;font-size:.8em;border:0;border-radius:3px;color:#212529;cursor:pointer;margin:0 0 0 .5em;padding:0 .5em}.aa-DetachedCancelButton:hover,.aa-DetachedCancelButton:focus{box-shadow:rgba(13,110,253,.6) 0 0 0 1px;outline:currentColor none medium}.aa-DetachedContainer--modal{bottom:inherit;height:auto;margin:0 auto;position:absolute;top:100px;border-radius:6px;max-width:850px}@media(max-width: 575.98px){.aa-DetachedContainer--modal{width:100%;top:0px;border-radius:0px;border:none}}.aa-DetachedContainer--modal .aa-PanelLayout{max-height:var(--aa-detached-modal-max-height);padding-bottom:var(--aa-spacing-half);position:static}.aa-Detached{height:100vh;overflow:hidden}.aa-DetachedOverlay{background-color:rgba(33,37,41,.4);position:fixed;left:0;right:0;top:0;margin:0;padding:0;height:100vh;z-index:1100}.quarto-dashboard.nav-fixed.dashboard-sidebar #quarto-content.quarto-dashboard-content{padding:0em}.quarto-dashboard #quarto-content.quarto-dashboard-content{padding:1em}.quarto-dashboard #quarto-content.quarto-dashboard-content>*{padding-top:0}@media(min-width: 576px){.quarto-dashboard{height:100%}}.quarto-dashboard .card.valuebox.bslib-card.bg-primary{background-color:#0d6efd !important}.quarto-dashboard .card.valuebox.bslib-card.bg-secondary{background-color:#6c757d !important}.quarto-dashboard .card.valuebox.bslib-card.bg-success{background-color:#198754 !important}.quarto-dashboard .card.valuebox.bslib-card.bg-info{background-color:#0dcaf0 !important}.quarto-dashboard .card.valuebox.bslib-card.bg-warning{background-color:#ffc107 !important}.quarto-dashboard .card.valuebox.bslib-card.bg-danger{background-color:#dc3545 !important}.quarto-dashboard .card.valuebox.bslib-card.bg-light{background-color:#f8f9fa !important}.quarto-dashboard .card.valuebox.bslib-card.bg-dark{background-color:#212529 !important}.quarto-dashboard.dashboard-fill{display:flex;flex-direction:column}.quarto-dashboard #quarto-appendix{display:none}.quarto-dashboard #quarto-header #quarto-dashboard-header{border-top:solid 1px #e6e6e6;border-bottom:solid 1px #e6e6e6}.quarto-dashboard #quarto-header #quarto-dashboard-header>nav{padding-left:1em;padding-right:1em}.quarto-dashboard #quarto-header #quarto-dashboard-header>nav .navbar-brand-container{padding-left:0}.quarto-dashboard #quarto-header #quarto-dashboard-header .navbar-toggler{margin-right:0}.quarto-dashboard #quarto-header #quarto-dashboard-header .navbar-toggler-icon{height:1em;width:1em;background-image:url('data:image/svg+xml,')}.quarto-dashboard #quarto-header #quarto-dashboard-header .navbar-brand-container{padding-right:1em}.quarto-dashboard #quarto-header #quarto-dashboard-header .navbar-title{font-size:1.1em}.quarto-dashboard #quarto-header #quarto-dashboard-header .navbar-nav{font-size:.9em}.quarto-dashboard #quarto-dashboard-header .navbar{padding:0}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-container{padding-left:1em}.quarto-dashboard #quarto-dashboard-header .navbar.slim .navbar-brand-container .nav-link,.quarto-dashboard #quarto-dashboard-header .navbar.slim .navbar-nav .nav-link{padding:.7em}.quarto-dashboard #quarto-dashboard-header .navbar .quarto-color-scheme-toggle{order:9}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-toggler{margin-left:.5em;order:10}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-nav .nav-link{padding:.5em;height:100%;display:flex;align-items:center}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-nav .active{background-color:#ebebeb}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-brand-container{padding:.5em .5em .5em 0;display:flex;flex-direction:row;margin-right:2em;align-items:center}@media(max-width: 767.98px){.quarto-dashboard #quarto-dashboard-header .navbar .navbar-brand-container{margin-right:auto}}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-collapse{align-self:stretch}@media(min-width: 768px){.quarto-dashboard #quarto-dashboard-header .navbar .navbar-collapse{order:8}}@media(max-width: 767.98px){.quarto-dashboard #quarto-dashboard-header .navbar .navbar-collapse{order:1000;padding-bottom:.5em}}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-collapse .navbar-nav{align-self:stretch}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-title{font-size:1.25em;line-height:1.1em;display:flex;flex-direction:row;flex-wrap:wrap;align-items:baseline}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-title .navbar-title-text{margin-right:.4em}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-title a{text-decoration:none;color:inherit}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-subtitle,.quarto-dashboard #quarto-dashboard-header .navbar .navbar-author{font-size:.9rem;margin-right:.5em}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-author{margin-left:auto}.quarto-dashboard #quarto-dashboard-header .navbar .navbar-logo{max-height:48px;min-height:30px;object-fit:cover;margin-right:1em}.quarto-dashboard #quarto-dashboard-header .navbar .quarto-dashboard-links{order:9;padding-right:1em}.quarto-dashboard #quarto-dashboard-header .navbar .quarto-dashboard-link-text{margin-left:.25em}.quarto-dashboard #quarto-dashboard-header .navbar .quarto-dashboard-link{padding-right:0em;padding-left:.7em;text-decoration:none;color:#595959}.quarto-dashboard .page-layout-custom .tab-content{padding:0;border:none}.quarto-dashboard-img-contain{height:100%;width:100%;object-fit:contain}@media(max-width: 575.98px){.quarto-dashboard .bslib-grid{grid-template-rows:minmax(1em, max-content) !important}.quarto-dashboard .sidebar-content{height:inherit}.quarto-dashboard .page-layout-custom{min-height:100vh}}.quarto-dashboard.dashboard-toolbar>.page-layout-custom,.quarto-dashboard.dashboard-sidebar>.page-layout-custom{padding:0}.quarto-dashboard .quarto-dashboard-content.quarto-dashboard-pages{padding:0}.quarto-dashboard .callout{margin-bottom:0;margin-top:0}.quarto-dashboard .html-fill-container figure{overflow:hidden}.quarto-dashboard bslib-tooltip .rounded-pill{border:solid #6c757d 1px}.quarto-dashboard bslib-tooltip .rounded-pill .svg{fill:#212529}.quarto-dashboard .tabset .dashboard-card-no-title .nav-tabs{margin-left:0;margin-right:auto}.quarto-dashboard .tabset .tab-content{border:none}.quarto-dashboard .tabset .card-header .nav-link[role=tab]{margin-top:-6px;padding-top:6px;padding-bottom:6px}.quarto-dashboard .card.valuebox,.quarto-dashboard .card.bslib-value-box{min-height:3rem}.quarto-dashboard .card.valuebox .card-body,.quarto-dashboard .card.bslib-value-box .card-body{padding:0}.quarto-dashboard .bslib-value-box .value-box-value{font-size:clamp(.1em,15cqw,5em)}.quarto-dashboard .bslib-value-box .value-box-showcase .bi{font-size:clamp(.1em,max(18cqw,5.2cqh),5em);text-align:center;height:1em}.quarto-dashboard .bslib-value-box .value-box-showcase .bi::before{vertical-align:1em}.quarto-dashboard .bslib-value-box .value-box-area{margin-top:auto;margin-bottom:auto}.quarto-dashboard .card figure.quarto-float{display:flex;flex-direction:column;align-items:center}.quarto-dashboard .dashboard-scrolling{padding:1em}.quarto-dashboard .full-height{height:100%}.quarto-dashboard .showcase-bottom .value-box-grid{display:grid;grid-template-columns:1fr;grid-template-rows:1fr auto;grid-template-areas:"top" "bottom"}.quarto-dashboard .showcase-bottom .value-box-grid .value-box-showcase{grid-area:bottom;padding:0;margin:0}.quarto-dashboard .showcase-bottom .value-box-grid .value-box-showcase i.bi{font-size:4rem}.quarto-dashboard .showcase-bottom .value-box-grid .value-box-area{grid-area:top}.quarto-dashboard .tab-content{margin-bottom:0}.quarto-dashboard .bslib-card .bslib-navs-card-title{justify-content:stretch;align-items:end}.quarto-dashboard .card-header{display:flex;flex-wrap:wrap;justify-content:space-between}.quarto-dashboard .card-header .card-title{display:flex;flex-direction:column;justify-content:center;margin-bottom:0}.quarto-dashboard .tabset .card-toolbar{margin-bottom:1em}.quarto-dashboard .bslib-grid>.bslib-sidebar-layout{border:none;gap:var(--bslib-spacer, 1rem)}.quarto-dashboard .bslib-grid>.bslib-sidebar-layout>.main{padding:0}.quarto-dashboard .bslib-grid>.bslib-sidebar-layout>.sidebar{border-radius:.25rem;border:1px solid rgba(0,0,0,.175)}.quarto-dashboard .bslib-grid>.bslib-sidebar-layout>.collapse-toggle{display:none}@media(max-width: 767.98px){.quarto-dashboard .bslib-grid>.bslib-sidebar-layout{grid-template-columns:1fr;grid-template-rows:max-content 1fr}.quarto-dashboard .bslib-grid>.bslib-sidebar-layout>.main{grid-column:1;grid-row:2}.quarto-dashboard .bslib-grid>.bslib-sidebar-layout .sidebar{grid-column:1;grid-row:1}}.quarto-dashboard .sidebar-right .sidebar{padding-left:2.5em}.quarto-dashboard .sidebar-right .collapse-toggle{left:2px}.quarto-dashboard .quarto-dashboard .sidebar-right button.collapse-toggle:not(.transitioning){left:unset}.quarto-dashboard aside.sidebar{padding-left:1em;padding-right:1em;background-color:rgba(52,58,64,.25);color:#212529}.quarto-dashboard .bslib-sidebar-layout>div.main{padding:.7em}.quarto-dashboard .bslib-sidebar-layout button.collapse-toggle{margin-top:.3em}.quarto-dashboard .bslib-sidebar-layout .collapse-toggle{top:0}.quarto-dashboard .bslib-sidebar-layout.sidebar-collapsed:not(.transitioning):not(.sidebar-right) .collapse-toggle{left:2px}.quarto-dashboard .sidebar>section>.h3:first-of-type{margin-top:0em}.quarto-dashboard .sidebar .h3,.quarto-dashboard .sidebar .h4,.quarto-dashboard .sidebar .h5,.quarto-dashboard .sidebar .h6{margin-top:.5em}.quarto-dashboard .sidebar form{flex-direction:column;align-items:start;margin-bottom:1em}.quarto-dashboard .sidebar form div[class*=oi-][class$=-input]{flex-direction:column}.quarto-dashboard .sidebar form[class*=oi-][class$=-toggle]{flex-direction:row-reverse;align-items:center;justify-content:start}.quarto-dashboard .sidebar form input[type=range]{margin-top:.5em;margin-right:.8em;margin-left:1em}.quarto-dashboard .sidebar label{width:fit-content}.quarto-dashboard .sidebar .card-body{margin-bottom:2em}.quarto-dashboard .sidebar .shiny-input-container{margin-bottom:1em}.quarto-dashboard .sidebar .shiny-options-group{margin-top:0}.quarto-dashboard .sidebar .control-label{margin-bottom:.3em}.quarto-dashboard .card .card-body .quarto-layout-row{align-items:stretch}.quarto-dashboard .toolbar{font-size:.9em;display:flex;flex-direction:row;border-top:solid 1px #c7c9cd;padding:1em;flex-wrap:wrap;background-color:rgba(52,58,64,.25)}.quarto-dashboard .toolbar .cell-output-display{display:flex}.quarto-dashboard .toolbar .shiny-input-container{padding-bottom:.5em;margin-bottom:.5em;width:inherit}.quarto-dashboard .toolbar .shiny-input-container>.checkbox:first-child{margin-top:6px}.quarto-dashboard .toolbar>*:last-child{margin-right:0}.quarto-dashboard .toolbar>*>*{margin-right:1em;align-items:baseline}.quarto-dashboard .toolbar>*>*>a{text-decoration:none;margin-top:auto;margin-bottom:auto}.quarto-dashboard .toolbar .shiny-input-container{padding-bottom:0;margin-bottom:0}.quarto-dashboard .toolbar .shiny-input-container>*{flex-shrink:0;flex-grow:0}.quarto-dashboard .toolbar .form-group.shiny-input-container:not([role=group])>label{margin-bottom:0}.quarto-dashboard .toolbar .shiny-input-container.no-baseline{align-items:start;padding-top:6px}.quarto-dashboard .toolbar .shiny-input-container{display:flex;align-items:baseline}.quarto-dashboard .toolbar .shiny-input-container label{padding-right:.4em}.quarto-dashboard .toolbar .shiny-input-container .bslib-input-switch{margin-top:6px}.quarto-dashboard .toolbar input[type=text]{line-height:1;width:inherit}.quarto-dashboard .toolbar .input-daterange{width:inherit}.quarto-dashboard .toolbar .input-daterange input[type=text]{height:2.4em;width:10em}.quarto-dashboard .toolbar .input-daterange .input-group-addon{height:auto;padding:0;margin-left:-5px !important;margin-right:-5px}.quarto-dashboard .toolbar .input-daterange .input-group-addon .input-group-text{padding-top:0;padding-bottom:0;height:100%}.quarto-dashboard .toolbar span.irs.irs--shiny{width:10em}.quarto-dashboard .toolbar span.irs.irs--shiny .irs-line{top:9px}.quarto-dashboard .toolbar span.irs.irs--shiny .irs-min,.quarto-dashboard .toolbar span.irs.irs--shiny .irs-max,.quarto-dashboard .toolbar span.irs.irs--shiny .irs-from,.quarto-dashboard .toolbar span.irs.irs--shiny .irs-to,.quarto-dashboard .toolbar span.irs.irs--shiny .irs-single{top:20px}.quarto-dashboard .toolbar span.irs.irs--shiny .irs-bar{top:8px}.quarto-dashboard .toolbar span.irs.irs--shiny .irs-handle{top:0px}.quarto-dashboard .toolbar .shiny-input-checkboxgroup>label{margin-top:6px}.quarto-dashboard .toolbar .shiny-input-checkboxgroup>.shiny-options-group{margin-top:0;align-items:baseline}.quarto-dashboard .toolbar .shiny-input-radiogroup>label{margin-top:6px}.quarto-dashboard .toolbar .shiny-input-radiogroup>.shiny-options-group{align-items:baseline;margin-top:0}.quarto-dashboard .toolbar .shiny-input-radiogroup>.shiny-options-group>.radio{margin-right:.3em}.quarto-dashboard .toolbar .form-select{padding-top:.2em;padding-bottom:.2em}.quarto-dashboard .toolbar .shiny-input-select{min-width:6em}.quarto-dashboard .toolbar div.checkbox{margin-bottom:0px}.quarto-dashboard .toolbar>.checkbox:first-child{margin-top:6px}.quarto-dashboard .toolbar form{width:fit-content}.quarto-dashboard .toolbar form label{padding-top:.2em;padding-bottom:.2em;width:fit-content}.quarto-dashboard .toolbar form input[type=date]{width:fit-content}.quarto-dashboard .toolbar form input[type=color]{width:3em}.quarto-dashboard .toolbar form button{padding:.4em}.quarto-dashboard .toolbar form select{width:fit-content}.quarto-dashboard .toolbar>*{font-size:.9em;flex-grow:0}.quarto-dashboard .toolbar .shiny-input-container label{margin-bottom:1px}.quarto-dashboard .toolbar-bottom{margin-top:1em;margin-bottom:0 !important;order:2}.quarto-dashboard .quarto-dashboard-content>.dashboard-toolbar-container>.toolbar-content>.tab-content>.tab-pane>*:not(.bslib-sidebar-layout){padding:1em}.quarto-dashboard .quarto-dashboard-content>.dashboard-toolbar-container>.toolbar-content>*:not(.tab-content){padding:1em}.quarto-dashboard .quarto-dashboard-content>.tab-content>.dashboard-page>.dashboard-toolbar-container>.toolbar-content,.quarto-dashboard .quarto-dashboard-content>.tab-content>.dashboard-page:not(.dashboard-sidebar-container)>*:not(.dashboard-toolbar-container){padding:1em}.quarto-dashboard .toolbar-content{padding:0}.quarto-dashboard .quarto-dashboard-content.quarto-dashboard-pages .tab-pane>.dashboard-toolbar-container .toolbar{border-radius:0;margin-bottom:0}.quarto-dashboard .dashboard-toolbar-container.toolbar-toplevel .toolbar{border-bottom:1px solid rgba(0,0,0,.175)}.quarto-dashboard .dashboard-toolbar-container.toolbar-toplevel .toolbar-bottom{margin-top:0}.quarto-dashboard .dashboard-toolbar-container:not(.toolbar-toplevel) .toolbar{margin-bottom:1em;border-top:none;border-radius:.25rem;border:1px solid rgba(0,0,0,.175)}.quarto-dashboard .vega-embed.has-actions details{width:1.7em;height:2em;position:absolute !important;top:0;right:0}.quarto-dashboard .dashboard-toolbar-container{padding:0}.quarto-dashboard .card .card-header p:last-child,.quarto-dashboard .card .card-footer p:last-child{margin-bottom:0}.quarto-dashboard .card .card-body>.h4:first-child{margin-top:0}.quarto-dashboard .card .card-body{z-index:4}@media(max-width: 767.98px){.quarto-dashboard .card .card-body .itables div.dataTables_wrapper div.dataTables_length,.quarto-dashboard .card .card-body .itables div.dataTables_wrapper div.dataTables_info,.quarto-dashboard .card .card-body .itables div.dataTables_wrapper div.dataTables_paginate{text-align:initial}.quarto-dashboard .card .card-body .itables div.dataTables_wrapper div.dataTables_filter{text-align:right}.quarto-dashboard .card .card-body .itables div.dataTables_wrapper div.dataTables_paginate ul.pagination{justify-content:initial}}.quarto-dashboard .card .card-body .itables .dataTables_wrapper{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;padding-top:0}.quarto-dashboard .card .card-body .itables .dataTables_wrapper table{flex-shrink:0}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dt-buttons{margin-bottom:.5em;margin-left:auto;width:fit-content;float:right}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dt-buttons.btn-group{background:#fff;border:none}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dt-buttons .btn-secondary{background-color:#fff;background-image:none;border:solid #dee2e6 1px;padding:.2em .7em}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dt-buttons .btn span{font-size:.8em;color:#212529}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dataTables_info{margin-left:.5em;margin-bottom:.5em;padding-top:0}@media(min-width: 768px){.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dataTables_info{font-size:.875em}}@media(max-width: 767.98px){.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dataTables_info{font-size:.8em}}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dataTables_filter{margin-bottom:.5em;font-size:.875em}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dataTables_filter input[type=search]{padding:1px 5px 1px 5px;font-size:.875em}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dataTables_length{flex-basis:1 1 50%;margin-bottom:.5em;font-size:.875em}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dataTables_length select{padding:.4em 3em .4em .5em;font-size:.875em;margin-left:.2em;margin-right:.2em}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dataTables_paginate{flex-shrink:0}@media(min-width: 768px){.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dataTables_paginate{margin-left:auto}}.quarto-dashboard .card .card-body .itables .dataTables_wrapper .dataTables_paginate ul.pagination .paginate_button .page-link{font-size:.8em}.quarto-dashboard .card .card-footer{font-size:.9em}.quarto-dashboard .card .card-toolbar{display:flex;flex-grow:1;flex-direction:row;width:100%;flex-wrap:wrap}.quarto-dashboard .card .card-toolbar>*{font-size:.8em;flex-grow:0}.quarto-dashboard .card .card-toolbar>.card-title{font-size:1em;flex-grow:1;align-self:flex-start;margin-top:.1em}.quarto-dashboard .card .card-toolbar .cell-output-display{display:flex}.quarto-dashboard .card .card-toolbar .shiny-input-container{padding-bottom:.5em;margin-bottom:.5em;width:inherit}.quarto-dashboard .card .card-toolbar .shiny-input-container>.checkbox:first-child{margin-top:6px}.quarto-dashboard .card .card-toolbar>*:last-child{margin-right:0}.quarto-dashboard .card .card-toolbar>*>*{margin-right:1em;align-items:baseline}.quarto-dashboard .card .card-toolbar>*>*>a{text-decoration:none;margin-top:auto;margin-bottom:auto}.quarto-dashboard .card .card-toolbar form{width:fit-content}.quarto-dashboard .card .card-toolbar form label{padding-top:.2em;padding-bottom:.2em;width:fit-content}.quarto-dashboard .card .card-toolbar form input[type=date]{width:fit-content}.quarto-dashboard .card .card-toolbar form input[type=color]{width:3em}.quarto-dashboard .card .card-toolbar form button{padding:.4em}.quarto-dashboard .card .card-toolbar form select{width:fit-content}.quarto-dashboard .card .card-toolbar .cell-output-display{display:flex}.quarto-dashboard .card .card-toolbar .shiny-input-container{padding-bottom:.5em;margin-bottom:.5em;width:inherit}.quarto-dashboard .card .card-toolbar .shiny-input-container>.checkbox:first-child{margin-top:6px}.quarto-dashboard .card .card-toolbar>*:last-child{margin-right:0}.quarto-dashboard .card .card-toolbar>*>*{margin-right:1em;align-items:baseline}.quarto-dashboard .card .card-toolbar>*>*>a{text-decoration:none;margin-top:auto;margin-bottom:auto}.quarto-dashboard .card .card-toolbar .shiny-input-container{padding-bottom:0;margin-bottom:0}.quarto-dashboard .card .card-toolbar .shiny-input-container>*{flex-shrink:0;flex-grow:0}.quarto-dashboard .card .card-toolbar .form-group.shiny-input-container:not([role=group])>label{margin-bottom:0}.quarto-dashboard .card .card-toolbar .shiny-input-container.no-baseline{align-items:start;padding-top:6px}.quarto-dashboard .card .card-toolbar .shiny-input-container{display:flex;align-items:baseline}.quarto-dashboard .card .card-toolbar .shiny-input-container label{padding-right:.4em}.quarto-dashboard .card .card-toolbar .shiny-input-container .bslib-input-switch{margin-top:6px}.quarto-dashboard .card .card-toolbar input[type=text]{line-height:1;width:inherit}.quarto-dashboard .card .card-toolbar .input-daterange{width:inherit}.quarto-dashboard .card .card-toolbar .input-daterange input[type=text]{height:2.4em;width:10em}.quarto-dashboard .card .card-toolbar .input-daterange .input-group-addon{height:auto;padding:0;margin-left:-5px !important;margin-right:-5px}.quarto-dashboard .card .card-toolbar .input-daterange .input-group-addon .input-group-text{padding-top:0;padding-bottom:0;height:100%}.quarto-dashboard .card .card-toolbar span.irs.irs--shiny{width:10em}.quarto-dashboard .card .card-toolbar span.irs.irs--shiny .irs-line{top:9px}.quarto-dashboard .card .card-toolbar span.irs.irs--shiny .irs-min,.quarto-dashboard .card .card-toolbar span.irs.irs--shiny .irs-max,.quarto-dashboard .card .card-toolbar span.irs.irs--shiny .irs-from,.quarto-dashboard .card .card-toolbar span.irs.irs--shiny .irs-to,.quarto-dashboard .card .card-toolbar span.irs.irs--shiny .irs-single{top:20px}.quarto-dashboard .card .card-toolbar span.irs.irs--shiny .irs-bar{top:8px}.quarto-dashboard .card .card-toolbar span.irs.irs--shiny .irs-handle{top:0px}.quarto-dashboard .card .card-toolbar .shiny-input-checkboxgroup>label{margin-top:6px}.quarto-dashboard .card .card-toolbar .shiny-input-checkboxgroup>.shiny-options-group{margin-top:0;align-items:baseline}.quarto-dashboard .card .card-toolbar .shiny-input-radiogroup>label{margin-top:6px}.quarto-dashboard .card .card-toolbar .shiny-input-radiogroup>.shiny-options-group{align-items:baseline;margin-top:0}.quarto-dashboard .card .card-toolbar .shiny-input-radiogroup>.shiny-options-group>.radio{margin-right:.3em}.quarto-dashboard .card .card-toolbar .form-select{padding-top:.2em;padding-bottom:.2em}.quarto-dashboard .card .card-toolbar .shiny-input-select{min-width:6em}.quarto-dashboard .card .card-toolbar div.checkbox{margin-bottom:0px}.quarto-dashboard .card .card-toolbar>.checkbox:first-child{margin-top:6px}.quarto-dashboard .card-body>table>thead{border-top:none}.quarto-dashboard .card-body>.table>:not(caption)>*>*{background-color:#fff}.tableFloatingHeaderOriginal{background-color:#fff;position:sticky !important;top:0 !important}.dashboard-data-table{margin-top:-1px}div.value-box-area span.observablehq--number{font-size:calc(clamp(.1em,15cqw,5em)*1.25);line-height:1.2;color:inherit;font-family:var(--bs-body-font-family)}.quarto-listing{padding-bottom:1em}.listing-pagination{padding-top:.5em}ul.pagination{float:right;padding-left:8px;padding-top:.5em}ul.pagination li{padding-right:.75em}ul.pagination li.disabled a,ul.pagination li.active a{color:#fff;text-decoration:none}ul.pagination li:last-of-type{padding-right:0}.listing-actions-group{display:flex}.quarto-listing-filter{margin-bottom:1em;width:200px;margin-left:auto}.quarto-listing-sort{margin-bottom:1em;margin-right:auto;width:auto}.quarto-listing-sort .input-group-text{font-size:.8em}.input-group-text{border-right:none}.quarto-listing-sort select.form-select{font-size:.8em}.listing-no-matching{text-align:center;padding-top:2em;padding-bottom:3em;font-size:1em}#quarto-margin-sidebar .quarto-listing-category{padding-top:0;font-size:1rem}#quarto-margin-sidebar .quarto-listing-category-title{cursor:pointer;font-weight:600;font-size:1rem}.quarto-listing-category .category{cursor:pointer}.quarto-listing-category .category.active{font-weight:600}.quarto-listing-category.category-cloud{display:flex;flex-wrap:wrap;align-items:baseline}.quarto-listing-category.category-cloud .category{padding-right:5px}.quarto-listing-category.category-cloud .category-cloud-1{font-size:.75em}.quarto-listing-category.category-cloud .category-cloud-2{font-size:.95em}.quarto-listing-category.category-cloud .category-cloud-3{font-size:1.15em}.quarto-listing-category.category-cloud .category-cloud-4{font-size:1.35em}.quarto-listing-category.category-cloud .category-cloud-5{font-size:1.55em}.quarto-listing-category.category-cloud .category-cloud-6{font-size:1.75em}.quarto-listing-category.category-cloud .category-cloud-7{font-size:1.95em}.quarto-listing-category.category-cloud .category-cloud-8{font-size:2.15em}.quarto-listing-category.category-cloud .category-cloud-9{font-size:2.35em}.quarto-listing-category.category-cloud .category-cloud-10{font-size:2.55em}.quarto-listing-cols-1{grid-template-columns:repeat(1, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-1{grid-template-columns:repeat(1, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-1{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-2{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-2{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-2{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-3{grid-template-columns:repeat(3, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-3{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-3{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-4{grid-template-columns:repeat(4, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-4{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-4{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-5{grid-template-columns:repeat(5, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-5{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-5{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-6{grid-template-columns:repeat(6, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-6{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-6{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-7{grid-template-columns:repeat(7, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-7{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-7{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-8{grid-template-columns:repeat(8, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-8{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-8{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-9{grid-template-columns:repeat(9, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-9{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-9{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-10{grid-template-columns:repeat(10, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-10{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-10{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-11{grid-template-columns:repeat(11, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-11{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-11{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-cols-12{grid-template-columns:repeat(12, minmax(0, 1fr));gap:1.5em}@media(max-width: 767.98px){.quarto-listing-cols-12{grid-template-columns:repeat(2, minmax(0, 1fr));gap:1.5em}}@media(max-width: 575.98px){.quarto-listing-cols-12{grid-template-columns:minmax(0, 1fr);gap:1.5em}}.quarto-listing-grid{gap:1.5em}.quarto-grid-item.borderless{border:none}.quarto-grid-item.borderless .listing-categories .listing-category:last-of-type,.quarto-grid-item.borderless .listing-categories .listing-category:first-of-type{padding-left:0}.quarto-grid-item.borderless .listing-categories .listing-category{border:0}.quarto-grid-link{text-decoration:none;color:inherit}.quarto-grid-link:hover{text-decoration:none;color:inherit}.quarto-grid-item h5.title,.quarto-grid-item .title.h5{margin-top:0;margin-bottom:0}.quarto-grid-item .card-footer{display:flex;justify-content:space-between;font-size:.8em}.quarto-grid-item .card-footer p{margin-bottom:0}.quarto-grid-item p.card-img-top{margin-bottom:0}.quarto-grid-item p.card-img-top>img{object-fit:cover}.quarto-grid-item .card-other-values{margin-top:.5em;font-size:.8em}.quarto-grid-item .card-other-values tr{margin-bottom:.5em}.quarto-grid-item .card-other-values tr>td:first-of-type{font-weight:600;padding-right:1em;padding-left:1em;vertical-align:top}.quarto-grid-item div.post-contents{display:flex;flex-direction:column;text-decoration:none;height:100%}.quarto-grid-item .listing-item-img-placeholder{background-color:rgba(52,58,64,.25);flex-shrink:0}.quarto-grid-item .card-attribution{padding-top:1em;display:flex;gap:1em;text-transform:uppercase;color:#6c757d;font-weight:500;flex-grow:10;align-items:flex-end}.quarto-grid-item .description{padding-bottom:1em}.quarto-grid-item .card-attribution .date{align-self:flex-end}.quarto-grid-item .card-attribution.justify{justify-content:space-between}.quarto-grid-item .card-attribution.start{justify-content:flex-start}.quarto-grid-item .card-attribution.end{justify-content:flex-end}.quarto-grid-item .card-title{margin-bottom:.1em}.quarto-grid-item .card-subtitle{padding-top:.25em}.quarto-grid-item .card-text{font-size:.9em}.quarto-grid-item .listing-reading-time{padding-bottom:.25em}.quarto-grid-item .card-text-small{font-size:.8em}.quarto-grid-item .card-subtitle.subtitle{font-size:.9em;font-weight:600;padding-bottom:.5em}.quarto-grid-item .listing-categories{display:flex;flex-wrap:wrap;padding-bottom:5px}.quarto-grid-item .listing-categories .listing-category{color:#6c757d;border:solid 1px #dee2e6;border-radius:.25rem;text-transform:uppercase;font-size:.65em;padding-left:.5em;padding-right:.5em;padding-top:.15em;padding-bottom:.15em;cursor:pointer;margin-right:4px;margin-bottom:4px}.quarto-grid-item.card-right{text-align:right}.quarto-grid-item.card-right .listing-categories{justify-content:flex-end}.quarto-grid-item.card-left{text-align:left}.quarto-grid-item.card-center{text-align:center}.quarto-grid-item.card-center .listing-description{text-align:justify}.quarto-grid-item.card-center .listing-categories{justify-content:center}table.quarto-listing-table td.image{padding:0px}table.quarto-listing-table td.image img{width:100%;max-width:50px;object-fit:contain}table.quarto-listing-table a{text-decoration:none;word-break:keep-all}table.quarto-listing-table th a{color:inherit}table.quarto-listing-table th a.asc:after{margin-bottom:-2px;margin-left:5px;display:inline-block;height:1rem;width:1rem;background-repeat:no-repeat;background-size:1rem 1rem;background-image:url('data:image/svg+xml,');content:""}table.quarto-listing-table th a.desc:after{margin-bottom:-2px;margin-left:5px;display:inline-block;height:1rem;width:1rem;background-repeat:no-repeat;background-size:1rem 1rem;background-image:url('data:image/svg+xml,');content:""}table.quarto-listing-table.table-hover td{cursor:pointer}.quarto-post.image-left{flex-direction:row}.quarto-post.image-right{flex-direction:row-reverse}@media(max-width: 767.98px){.quarto-post.image-right,.quarto-post.image-left{gap:0em;flex-direction:column}.quarto-post .metadata{padding-bottom:1em;order:2}.quarto-post .body{order:1}.quarto-post .thumbnail{order:3}}.list.quarto-listing-default div:last-of-type{border-bottom:none}@media(min-width: 992px){.quarto-listing-container-default{margin-right:2em}}div.quarto-post{display:flex;gap:2em;margin-bottom:1.5em;border-bottom:1px solid #dee2e6}@media(max-width: 767.98px){div.quarto-post{padding-bottom:1em}}div.quarto-post .metadata{flex-basis:20%;flex-grow:0;margin-top:.2em;flex-shrink:10}div.quarto-post .thumbnail{flex-basis:30%;flex-grow:0;flex-shrink:0}div.quarto-post .thumbnail img{margin-top:.4em;width:100%;object-fit:cover}div.quarto-post .body{flex-basis:45%;flex-grow:1;flex-shrink:0}div.quarto-post .body h3.listing-title,div.quarto-post .body .listing-title.h3{margin-top:0px;margin-bottom:0px;border-bottom:none}div.quarto-post .body .listing-subtitle{font-size:.875em;margin-bottom:.5em;margin-top:.2em}div.quarto-post .body .description{font-size:.9em}div.quarto-post .body pre code{white-space:pre-wrap}div.quarto-post a{color:#212529;text-decoration:none}div.quarto-post .metadata{display:flex;flex-direction:column;font-size:.8em;font-family:Roboto;flex-basis:33%}div.quarto-post .listing-categories{display:flex;flex-wrap:wrap;padding-bottom:5px}div.quarto-post .listing-categories .listing-category{color:#6c757d;border:solid 1px #dee2e6;border-radius:.25rem;text-transform:uppercase;font-size:.65em;padding-left:.5em;padding-right:.5em;padding-top:.15em;padding-bottom:.15em;cursor:pointer;margin-right:4px;margin-bottom:4px}div.quarto-post .listing-description{margin-bottom:.5em}div.quarto-about-jolla{display:flex !important;flex-direction:column;align-items:center;margin-top:10%;padding-bottom:1em}div.quarto-about-jolla .about-image{object-fit:cover;margin-left:auto;margin-right:auto;margin-bottom:1.5em}div.quarto-about-jolla img.round{border-radius:50%}div.quarto-about-jolla img.rounded{border-radius:10px}div.quarto-about-jolla .quarto-title h1.title,div.quarto-about-jolla .quarto-title .title.h1{text-align:center}div.quarto-about-jolla .quarto-title .description{text-align:center}div.quarto-about-jolla h2,div.quarto-about-jolla .h2{border-bottom:none}div.quarto-about-jolla .about-sep{width:60%}div.quarto-about-jolla main{text-align:center}div.quarto-about-jolla .about-links{display:flex}@media(min-width: 992px){div.quarto-about-jolla .about-links{flex-direction:row;column-gap:.8em;row-gap:15px;flex-wrap:wrap}}@media(max-width: 991.98px){div.quarto-about-jolla .about-links{flex-direction:column;row-gap:1em;width:100%;padding-bottom:1.5em}}div.quarto-about-jolla .about-link{color:#4e5862;text-decoration:none;border:solid 1px}@media(min-width: 992px){div.quarto-about-jolla .about-link{font-size:.8em;padding:.25em .5em;border-radius:4px}}@media(max-width: 991.98px){div.quarto-about-jolla .about-link{font-size:1.1em;padding:.5em .5em;text-align:center;border-radius:6px}}div.quarto-about-jolla .about-link:hover{color:#03638e}div.quarto-about-jolla .about-link i.bi{margin-right:.15em}div.quarto-about-solana{display:flex !important;flex-direction:column;padding-top:3em !important;padding-bottom:1em}div.quarto-about-solana .about-entity{display:flex !important;align-items:start;justify-content:space-between}@media(min-width: 992px){div.quarto-about-solana .about-entity{flex-direction:row}}@media(max-width: 991.98px){div.quarto-about-solana .about-entity{flex-direction:column-reverse;align-items:center;text-align:center}}div.quarto-about-solana .about-entity .entity-contents{display:flex;flex-direction:column}@media(max-width: 767.98px){div.quarto-about-solana .about-entity .entity-contents{width:100%}}div.quarto-about-solana .about-entity .about-image{object-fit:cover}@media(max-width: 991.98px){div.quarto-about-solana .about-entity .about-image{margin-bottom:1.5em}}div.quarto-about-solana .about-entity img.round{border-radius:50%}div.quarto-about-solana .about-entity img.rounded{border-radius:10px}div.quarto-about-solana .about-entity .about-links{display:flex;justify-content:left;padding-bottom:1.2em}@media(min-width: 992px){div.quarto-about-solana .about-entity .about-links{flex-direction:row;column-gap:.8em;row-gap:15px;flex-wrap:wrap}}@media(max-width: 991.98px){div.quarto-about-solana .about-entity .about-links{flex-direction:column;row-gap:1em;width:100%;padding-bottom:1.5em}}div.quarto-about-solana .about-entity .about-link{color:#4e5862;text-decoration:none;border:solid 1px}@media(min-width: 992px){div.quarto-about-solana .about-entity .about-link{font-size:.8em;padding:.25em .5em;border-radius:4px}}@media(max-width: 991.98px){div.quarto-about-solana .about-entity .about-link{font-size:1.1em;padding:.5em .5em;text-align:center;border-radius:6px}}div.quarto-about-solana .about-entity .about-link:hover{color:#03638e}div.quarto-about-solana .about-entity .about-link i.bi{margin-right:.15em}div.quarto-about-solana .about-contents{padding-right:1.5em;flex-basis:0;flex-grow:1}div.quarto-about-solana .about-contents main.content{margin-top:0}div.quarto-about-solana .about-contents h2,div.quarto-about-solana .about-contents .h2{border-bottom:none}div.quarto-about-trestles{display:flex !important;flex-direction:row;padding-top:3em !important;padding-bottom:1em}@media(max-width: 991.98px){div.quarto-about-trestles{flex-direction:column;padding-top:0em !important}}div.quarto-about-trestles .about-entity{display:flex !important;flex-direction:column;align-items:center;text-align:center;padding-right:1em}@media(min-width: 992px){div.quarto-about-trestles .about-entity{flex:0 0 42%}}div.quarto-about-trestles .about-entity .about-image{object-fit:cover;margin-bottom:1.5em}div.quarto-about-trestles .about-entity img.round{border-radius:50%}div.quarto-about-trestles .about-entity img.rounded{border-radius:10px}div.quarto-about-trestles .about-entity .about-links{display:flex;justify-content:center}@media(min-width: 992px){div.quarto-about-trestles .about-entity .about-links{flex-direction:row;column-gap:.8em;row-gap:15px;flex-wrap:wrap}}@media(max-width: 991.98px){div.quarto-about-trestles .about-entity .about-links{flex-direction:column;row-gap:1em;width:100%;padding-bottom:1.5em}}div.quarto-about-trestles .about-entity .about-link{color:#4e5862;text-decoration:none;border:solid 1px}@media(min-width: 992px){div.quarto-about-trestles .about-entity .about-link{font-size:.8em;padding:.25em .5em;border-radius:4px}}@media(max-width: 991.98px){div.quarto-about-trestles .about-entity .about-link{font-size:1.1em;padding:.5em .5em;text-align:center;border-radius:6px}}div.quarto-about-trestles .about-entity .about-link:hover{color:#03638e}div.quarto-about-trestles .about-entity .about-link i.bi{margin-right:.15em}div.quarto-about-trestles .about-contents{flex-basis:0;flex-grow:1}div.quarto-about-trestles .about-contents h2,div.quarto-about-trestles .about-contents .h2{border-bottom:none}@media(min-width: 992px){div.quarto-about-trestles .about-contents{border-left:solid 1px #dee2e6;padding-left:1.5em}}div.quarto-about-trestles .about-contents main.content{margin-top:0}div.quarto-about-marquee{padding-bottom:1em}div.quarto-about-marquee .about-contents{display:flex;flex-direction:column}div.quarto-about-marquee .about-image{max-height:550px;margin-bottom:1.5em;object-fit:cover}div.quarto-about-marquee img.round{border-radius:50%}div.quarto-about-marquee img.rounded{border-radius:10px}div.quarto-about-marquee h2,div.quarto-about-marquee .h2{border-bottom:none}div.quarto-about-marquee .about-links{display:flex;justify-content:center;padding-top:1.5em}@media(min-width: 992px){div.quarto-about-marquee .about-links{flex-direction:row;column-gap:.8em;row-gap:15px;flex-wrap:wrap}}@media(max-width: 991.98px){div.quarto-about-marquee .about-links{flex-direction:column;row-gap:1em;width:100%;padding-bottom:1.5em}}div.quarto-about-marquee .about-link{color:#4e5862;text-decoration:none;border:solid 1px}@media(min-width: 992px){div.quarto-about-marquee .about-link{font-size:.8em;padding:.25em .5em;border-radius:4px}}@media(max-width: 991.98px){div.quarto-about-marquee .about-link{font-size:1.1em;padding:.5em .5em;text-align:center;border-radius:6px}}div.quarto-about-marquee .about-link:hover{color:#03638e}div.quarto-about-marquee .about-link i.bi{margin-right:.15em}@media(min-width: 992px){div.quarto-about-marquee .about-link{border:none}}div.quarto-about-broadside{display:flex;flex-direction:column;padding-bottom:1em}div.quarto-about-broadside .about-main{display:flex !important;padding-top:0 !important}@media(min-width: 992px){div.quarto-about-broadside .about-main{flex-direction:row;align-items:flex-start}}@media(max-width: 991.98px){div.quarto-about-broadside .about-main{flex-direction:column}}@media(max-width: 991.98px){div.quarto-about-broadside .about-main .about-entity{flex-shrink:0;width:100%;height:450px;margin-bottom:1.5em;background-size:cover;background-repeat:no-repeat}}@media(min-width: 992px){div.quarto-about-broadside .about-main .about-entity{flex:0 10 50%;margin-right:1.5em;width:100%;height:100%;background-size:100%;background-repeat:no-repeat}}div.quarto-about-broadside .about-main .about-contents{padding-top:14px;flex:0 0 50%}div.quarto-about-broadside h2,div.quarto-about-broadside .h2{border-bottom:none}div.quarto-about-broadside .about-sep{margin-top:1.5em;width:60%;align-self:center}div.quarto-about-broadside .about-links{display:flex;justify-content:center;column-gap:20px;padding-top:1.5em}@media(min-width: 992px){div.quarto-about-broadside .about-links{flex-direction:row;column-gap:.8em;row-gap:15px;flex-wrap:wrap}}@media(max-width: 991.98px){div.quarto-about-broadside .about-links{flex-direction:column;row-gap:1em;width:100%;padding-bottom:1.5em}}div.quarto-about-broadside .about-link{color:#4e5862;text-decoration:none;border:solid 1px}@media(min-width: 992px){div.quarto-about-broadside .about-link{font-size:.8em;padding:.25em .5em;border-radius:4px}}@media(max-width: 991.98px){div.quarto-about-broadside .about-link{font-size:1.1em;padding:.5em .5em;text-align:center;border-radius:6px}}div.quarto-about-broadside .about-link:hover{color:#03638e}div.quarto-about-broadside .about-link i.bi{margin-right:.15em}@media(min-width: 992px){div.quarto-about-broadside .about-link{border:none}}.tippy-box[data-theme~=quarto]{background-color:#fff;border:solid 1px #dee2e6;border-radius:.25rem;color:#212529;font-size:.875rem}.tippy-box[data-theme~=quarto]>.tippy-backdrop{background-color:#fff}.tippy-box[data-theme~=quarto]>.tippy-arrow:after,.tippy-box[data-theme~=quarto]>.tippy-svg-arrow:after{content:"";position:absolute;z-index:-1}.tippy-box[data-theme~=quarto]>.tippy-arrow:after{border-color:rgba(0,0,0,0);border-style:solid}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-6px}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-6px}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-6px}.tippy-box[data-placement^=left]>.tippy-arrow:before{right:-6px}.tippy-box[data-theme~=quarto][data-placement^=top]>.tippy-arrow:before{border-top-color:#fff}.tippy-box[data-theme~=quarto][data-placement^=top]>.tippy-arrow:after{border-top-color:#dee2e6;border-width:7px 7px 0;top:17px;left:1px}.tippy-box[data-theme~=quarto][data-placement^=top]>.tippy-svg-arrow>svg{top:16px}.tippy-box[data-theme~=quarto][data-placement^=top]>.tippy-svg-arrow:after{top:17px}.tippy-box[data-theme~=quarto][data-placement^=bottom]>.tippy-arrow:before{border-bottom-color:#fff;bottom:16px}.tippy-box[data-theme~=quarto][data-placement^=bottom]>.tippy-arrow:after{border-bottom-color:#dee2e6;border-width:0 7px 7px;bottom:17px;left:1px}.tippy-box[data-theme~=quarto][data-placement^=bottom]>.tippy-svg-arrow>svg{bottom:15px}.tippy-box[data-theme~=quarto][data-placement^=bottom]>.tippy-svg-arrow:after{bottom:17px}.tippy-box[data-theme~=quarto][data-placement^=left]>.tippy-arrow:before{border-left-color:#fff}.tippy-box[data-theme~=quarto][data-placement^=left]>.tippy-arrow:after{border-left-color:#dee2e6;border-width:7px 0 7px 7px;left:17px;top:1px}.tippy-box[data-theme~=quarto][data-placement^=left]>.tippy-svg-arrow>svg{left:11px}.tippy-box[data-theme~=quarto][data-placement^=left]>.tippy-svg-arrow:after{left:12px}.tippy-box[data-theme~=quarto][data-placement^=right]>.tippy-arrow:before{border-right-color:#fff;right:16px}.tippy-box[data-theme~=quarto][data-placement^=right]>.tippy-arrow:after{border-width:7px 7px 7px 0;right:17px;top:1px;border-right-color:#dee2e6}.tippy-box[data-theme~=quarto][data-placement^=right]>.tippy-svg-arrow>svg{right:11px}.tippy-box[data-theme~=quarto][data-placement^=right]>.tippy-svg-arrow:after{right:12px}.tippy-box[data-theme~=quarto]>.tippy-svg-arrow{fill:#212529}.tippy-box[data-theme~=quarto]>.tippy-svg-arrow:after{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMCA2czEuNzk2LS4wMTMgNC42Ny0zLjYxNUM1Ljg1MS45IDYuOTMuMDA2IDggMGMxLjA3LS4wMDYgMi4xNDguODg3IDMuMzQzIDIuMzg1QzE0LjIzMyA2LjAwNSAxNiA2IDE2IDZIMHoiIGZpbGw9InJnYmEoMCwgOCwgMTYsIDAuMikiLz48L3N2Zz4=);background-size:16px 6px;width:16px;height:6px}.top-right{position:absolute;top:1em;right:1em}.visually-hidden{border:0;clip:rect(0 0 0 0);height:auto;margin:0;overflow:hidden;padding:0;position:absolute;width:1px;white-space:nowrap}.hidden{display:none !important}.zindex-bottom{z-index:-1 !important}figure.figure{display:block}.quarto-layout-panel{margin-bottom:1em}.quarto-layout-panel>figure{width:100%}.quarto-layout-panel>figure>figcaption,.quarto-layout-panel>.panel-caption{margin-top:10pt}.quarto-layout-panel>.table-caption{margin-top:0px}.table-caption p{margin-bottom:.5em}.quarto-layout-row{display:flex;flex-direction:row;align-items:flex-start}.quarto-layout-valign-top{align-items:flex-start}.quarto-layout-valign-bottom{align-items:flex-end}.quarto-layout-valign-center{align-items:center}.quarto-layout-cell{position:relative;margin-right:20px}.quarto-layout-cell:last-child{margin-right:0}.quarto-layout-cell figure,.quarto-layout-cell>p{margin:.2em}.quarto-layout-cell img{max-width:100%}.quarto-layout-cell .html-widget{width:100% !important}.quarto-layout-cell div figure p{margin:0}.quarto-layout-cell figure{display:block;margin-inline-start:0;margin-inline-end:0}.quarto-layout-cell table{display:inline-table}.quarto-layout-cell-subref figcaption,figure .quarto-layout-row figure figcaption{text-align:center;font-style:italic}.quarto-figure{position:relative;margin-bottom:1em}.quarto-figure>figure{width:100%;margin-bottom:0}.quarto-figure-left>figure>p,.quarto-figure-left>figure>div{text-align:left}.quarto-figure-center>figure>p,.quarto-figure-center>figure>div{text-align:center}.quarto-figure-right>figure>p,.quarto-figure-right>figure>div{text-align:right}.quarto-figure>figure>div.cell-annotation,.quarto-figure>figure>div code{text-align:left}figure>p:empty{display:none}figure>p:first-child{margin-top:0;margin-bottom:0}figure>figcaption.quarto-float-caption-bottom{margin-bottom:.5em}figure>figcaption.quarto-float-caption-top{margin-top:.5em}div[id^=tbl-]{position:relative}.quarto-figure>.anchorjs-link{position:absolute;top:.6em;right:.5em}div[id^=tbl-]>.anchorjs-link{position:absolute;top:.7em;right:.3em}.quarto-figure:hover>.anchorjs-link,div[id^=tbl-]:hover>.anchorjs-link,h2:hover>.anchorjs-link,.h2:hover>.anchorjs-link,h3:hover>.anchorjs-link,.h3:hover>.anchorjs-link,h4:hover>.anchorjs-link,.h4:hover>.anchorjs-link,h5:hover>.anchorjs-link,.h5:hover>.anchorjs-link,h6:hover>.anchorjs-link,.h6:hover>.anchorjs-link,.reveal-anchorjs-link>.anchorjs-link{opacity:1}#title-block-header{margin-block-end:1rem;position:relative;margin-top:-1px}#title-block-header .abstract{margin-block-start:1rem}#title-block-header .abstract .abstract-title{font-weight:600}#title-block-header a{text-decoration:none}#title-block-header .author,#title-block-header .date,#title-block-header .doi{margin-block-end:.2rem}#title-block-header .quarto-title-block>div{display:flex}#title-block-header .quarto-title-block>div>h1,#title-block-header .quarto-title-block>div>.h1{flex-grow:1}#title-block-header .quarto-title-block>div>button{flex-shrink:0;height:2.25rem;margin-top:0}@media(min-width: 992px){#title-block-header .quarto-title-block>div>button{margin-top:5px}}tr.header>th>p:last-of-type{margin-bottom:0px}table,table.table{margin-top:.5rem;margin-bottom:.5rem}caption,.table-caption{padding-top:.5rem;padding-bottom:.5rem;text-align:center}figure.quarto-float-tbl figcaption.quarto-float-caption-top{margin-top:.5rem;margin-bottom:.25rem;text-align:center}figure.quarto-float-tbl figcaption.quarto-float-caption-bottom{padding-top:.25rem;margin-bottom:.5rem;text-align:center}.utterances{max-width:none;margin-left:-8px}iframe{margin-bottom:1em}details{margin-bottom:1em}details[show]{margin-bottom:0}details>summary{color:#6c757d}details>summary>p:only-child{display:inline}pre.sourceCode,code.sourceCode{position:relative}dd code:not(.sourceCode),p code:not(.sourceCode){white-space:pre-wrap}code{white-space:pre}@media print{code{white-space:pre-wrap}}pre>code{display:block}pre>code.sourceCode{white-space:pre}pre>code.sourceCode>span>a:first-child::before{text-decoration:none}pre.code-overflow-wrap>code.sourceCode{white-space:pre-wrap}pre.code-overflow-scroll>code.sourceCode{white-space:pre}code a:any-link{color:inherit;text-decoration:none}code a:hover{color:inherit;text-decoration:underline}ul.task-list{padding-left:1em}[data-tippy-root]{display:inline-block}.tippy-content .footnote-back{display:none}.footnote-back{margin-left:.2em}.tippy-content{overflow-x:auto}.quarto-embedded-source-code{display:none}.quarto-unresolved-ref{font-weight:600}.quarto-cover-image{max-width:35%;float:right;margin-left:30px}.cell-output-display .widget-subarea{margin-bottom:1em}.cell-output-display:not(.no-overflow-x),.knitsql-table:not(.no-overflow-x){overflow-x:auto}.panel-input{margin-bottom:1em}.panel-input>div,.panel-input>div>div{display:inline-block;vertical-align:top;padding-right:12px}.panel-input>p:last-child{margin-bottom:0}.layout-sidebar{margin-bottom:1em}.layout-sidebar .tab-content{border:none}.tab-content>.page-columns.active{display:grid}div.sourceCode>iframe{width:100%;height:300px;margin-bottom:-0.5em}a{text-underline-offset:3px}div.ansi-escaped-output{font-family:monospace;display:block}/*! +* +* ansi colors from IPython notebook's +* +* we also add `bright-[color]-` synonyms for the `-[color]-intense` classes since +* that seems to be what ansi_up emits +* +*/.ansi-black-fg{color:#3e424d}.ansi-black-bg{background-color:#3e424d}.ansi-black-intense-black,.ansi-bright-black-fg{color:#282c36}.ansi-black-intense-black,.ansi-bright-black-bg{background-color:#282c36}.ansi-red-fg{color:#e75c58}.ansi-red-bg{background-color:#e75c58}.ansi-red-intense-red,.ansi-bright-red-fg{color:#b22b31}.ansi-red-intense-red,.ansi-bright-red-bg{background-color:#b22b31}.ansi-green-fg{color:#00a250}.ansi-green-bg{background-color:#00a250}.ansi-green-intense-green,.ansi-bright-green-fg{color:#007427}.ansi-green-intense-green,.ansi-bright-green-bg{background-color:#007427}.ansi-yellow-fg{color:#ddb62b}.ansi-yellow-bg{background-color:#ddb62b}.ansi-yellow-intense-yellow,.ansi-bright-yellow-fg{color:#b27d12}.ansi-yellow-intense-yellow,.ansi-bright-yellow-bg{background-color:#b27d12}.ansi-blue-fg{color:#208ffb}.ansi-blue-bg{background-color:#208ffb}.ansi-blue-intense-blue,.ansi-bright-blue-fg{color:#0065ca}.ansi-blue-intense-blue,.ansi-bright-blue-bg{background-color:#0065ca}.ansi-magenta-fg{color:#d160c4}.ansi-magenta-bg{background-color:#d160c4}.ansi-magenta-intense-magenta,.ansi-bright-magenta-fg{color:#a03196}.ansi-magenta-intense-magenta,.ansi-bright-magenta-bg{background-color:#a03196}.ansi-cyan-fg{color:#60c6c8}.ansi-cyan-bg{background-color:#60c6c8}.ansi-cyan-intense-cyan,.ansi-bright-cyan-fg{color:#258f8f}.ansi-cyan-intense-cyan,.ansi-bright-cyan-bg{background-color:#258f8f}.ansi-white-fg{color:#c5c1b4}.ansi-white-bg{background-color:#c5c1b4}.ansi-white-intense-white,.ansi-bright-white-fg{color:#a1a6b2}.ansi-white-intense-white,.ansi-bright-white-bg{background-color:#a1a6b2}.ansi-default-inverse-fg{color:#fff}.ansi-default-inverse-bg{background-color:#000}.ansi-bold{font-weight:bold}.ansi-underline{text-decoration:underline}:root{--quarto-body-bg: #ffffff;--quarto-body-color: #212529;--quarto-text-muted: #6c757d;--quarto-border-color: #dee2e6;--quarto-border-width: 1px;--quarto-border-radius: 0.25rem}table.gt_table{color:var(--quarto-body-color);font-size:1em;width:100%;background-color:rgba(0,0,0,0);border-top-width:inherit;border-bottom-width:inherit;border-color:var(--quarto-border-color)}table.gt_table th.gt_column_spanner_outer{color:var(--quarto-body-color);background-color:rgba(0,0,0,0);border-top-width:inherit;border-bottom-width:inherit;border-color:var(--quarto-border-color)}table.gt_table th.gt_col_heading{color:var(--quarto-body-color);font-weight:bold;background-color:rgba(0,0,0,0)}table.gt_table thead.gt_col_headings{border-bottom:1px solid currentColor;border-top-width:inherit;border-top-color:var(--quarto-border-color)}table.gt_table thead.gt_col_headings:not(:first-child){border-top-width:1px;border-top-color:var(--quarto-border-color)}table.gt_table td.gt_row{border-bottom-width:1px;border-bottom-color:var(--quarto-border-color);border-top-width:0px}table.gt_table tbody.gt_table_body{border-top-width:1px;border-bottom-width:1px;border-bottom-color:var(--quarto-border-color);border-top-color:currentColor}div.columns{display:initial;gap:initial}div.column{display:inline-block;overflow-x:initial;vertical-align:top;width:50%}.code-annotation-tip-content{word-wrap:break-word}.code-annotation-container-hidden{display:none !important}dl.code-annotation-container-grid{display:grid;grid-template-columns:min-content auto}dl.code-annotation-container-grid dt{grid-column:1}dl.code-annotation-container-grid dd{grid-column:2}pre.sourceCode.code-annotation-code{padding-right:0}code.sourceCode .code-annotation-anchor{z-index:100;position:relative;float:right;background-color:rgba(0,0,0,0)}input[type=checkbox]{margin-right:.5ch}:root{--mermaid-bg-color: rgb(255, 255, 255);--mermaid-edge-color: #6c757d;--mermaid-node-fg-color: rgba(0, 0, 0, 0.175);--mermaid-fg-color: #212529;--mermaid-fg-color--lighter: rgba(0, 0, 0, 0.175);--mermaid-fg-color--lightest: rgb(241, 241, 241);--mermaid-font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, Noto Sans, Liberation Sans, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;--mermaid-label-bg-color: #ffffff;--mermaid-label-fg-color: #0d6efd;--mermaid-node-bg-color: #80aabb;--mermaid-node-fg-color: rgba(0, 0, 0, 0.175)}@media print{:root{font-size:11pt}#quarto-sidebar,#TOC,.nav-page{display:none}.page-columns .content{grid-column-start:page-start}.fixed-top{position:relative}.panel-caption,.figure-caption,figcaption{color:#666}}.code-copy-button{position:absolute;top:0;right:0;border:0;margin-top:5px;margin-right:5px;background-color:rgba(0,0,0,0);z-index:3}.code-copy-button:focus{outline:none}.code-copy-button-tooltip{font-size:.75em}pre.sourceCode:hover>.code-copy-button>.bi::before{display:inline-block;height:1rem;width:1rem;content:"";vertical-align:-0.125em;background-image:url('data:image/svg+xml,');background-repeat:no-repeat;background-size:1rem 1rem}pre.sourceCode:hover>.code-copy-button-checked>.bi::before{background-image:url('data:image/svg+xml,')}pre.sourceCode:hover>.code-copy-button:hover>.bi::before{background-image:url('data:image/svg+xml,')}pre.sourceCode:hover>.code-copy-button-checked:hover>.bi::before{background-image:url('data:image/svg+xml,')}main ol ol,main ul ul,main ol ul,main ul ol{margin-bottom:1em}ul>li:not(:has(>p))>ul,ol>li:not(:has(>p))>ul,ul>li:not(:has(>p))>ol,ol>li:not(:has(>p))>ol{margin-bottom:0}ul>li:not(:has(>p))>ul>li:has(>p),ol>li:not(:has(>p))>ul>li:has(>p),ul>li:not(:has(>p))>ol>li:has(>p),ol>li:not(:has(>p))>ol>li:has(>p){margin-top:1rem}body{margin:0}main.page-columns>header>h1.title,main.page-columns>header>.title.h1{margin-bottom:0}@media(min-width: 992px){body .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset] 35px [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(500px, calc(850px - 3em)) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] 35px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.fullcontent:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset] 35px [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(500px, calc(850px - 3em)) [body-content-end] 1.5em [body-end] 35px [body-end-outset] 35px [page-end-inset page-end] 5fr [screen-end-inset] 1.5em}body.slimcontent:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset] 35px [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(500px, calc(850px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 35px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.listing:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(50px, 100px) [page-start-inset] 50px [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(500px, calc(850px - 3em)) [body-content-end] 3em [body-end] 50px [body-end-outset] minmax(0px, 250px) [page-end-inset] minmax(50px, 100px) [page-end] 1fr [screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 35px [page-start-inset] minmax(0px, 175px) [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(450px, calc(800px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 35px [page-start-inset] minmax(0px, 175px) [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(450px, calc(800px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] minmax(25px, 50px) [page-start-inset] minmax(50px, 150px) [body-start-outset] minmax(25px, 50px) [body-start] 1.5em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end] minmax(25px, 50px) [body-end-outset] minmax(50px, 150px) [page-end-inset] minmax(25px, 50px) [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(50px, 100px) [page-start-inset] 50px [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(500px, calc(1000px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(50px, 100px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(50px, 100px) [page-start-inset] 50px [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(500px, calc(1000px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 50px [page-start-inset] minmax(50px, 150px) [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.slimcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(50px, 100px) [page-start-inset] 50px [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(450px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.listing .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(50px, 100px) [page-start-inset] 50px [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(500px, calc(1000px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.slimcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 50px [page-start-inset] minmax(50px, 150px) [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(450px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(50px, 150px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.listing .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] minmax(25px, 50px) [page-start-inset] minmax(50px, 150px) [body-start-outset] minmax(25px, 50px) [body-start] 1.5em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end] minmax(25px, 50px) [body-end-outset] minmax(50px, 150px) [page-end-inset] minmax(25px, 50px) [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}}@media(max-width: 991.98px){body .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset] 5fr [body-start] 1.5em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] 35px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.fullcontent:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset] 5fr [body-start] 1.5em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.slimcontent:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset] 5fr [body-start] 1.5em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] 35px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.listing:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset] 5fr [body-start] 1.5em [body-content-start] minmax(500px, calc(1250px - 3em)) [body-content-end body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 35px [page-start-inset] minmax(0px, 145px) [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(450px, calc(800px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 35px [page-start-inset] minmax(0px, 145px) [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(450px, calc(800px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset body-start-outset body-start] 1.5em [body-content-start] minmax(500px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(75px, 150px) [page-end-inset] 25px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(500px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(25px, 50px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(500px, calc(1000px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset body-start-outset body-start] 1em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 4fr [screen-end-inset] 1.5em [screen-end]}body.docked.slimcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(500px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(25px, 50px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.listing .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(500px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(25px, 50px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.slimcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset body-start-outset body-start] 1em [body-content-start] minmax(500px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] 35px [page-end] 4fr [screen-end-inset] 1.5em [screen-end]}body.floating.listing .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset body-start-outset body-start] 1em [body-content-start] minmax(500px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(75px, 150px) [page-end-inset] 25px [page-end] 4fr [screen-end-inset] 1.5em [screen-end]}}@media(max-width: 767.98px){body .page-columns,body.fullcontent:not(.floating):not(.docked) .page-columns,body.slimcontent:not(.floating):not(.docked) .page-columns,body.docked .page-columns,body.docked.slimcontent .page-columns,body.docked.fullcontent .page-columns,body.floating .page-columns,body.floating.slimcontent .page-columns,body.floating.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(0px, 1fr) [body-content-end body-end body-end-outset page-end-inset page-end screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(0px, 1fr) [body-content-end body-end body-end-outset page-end-inset page-end screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(0px, 1fr) [body-content-end body-end body-end-outset page-end-inset page-end screen-end-inset] 1.5em [screen-end]}nav[role=doc-toc]{display:none}}body,.page-row-navigation{grid-template-rows:[page-top] max-content [contents-top] max-content [contents-bottom] max-content [page-bottom]}.page-rows-contents{grid-template-rows:[content-top] minmax(max-content, 1fr) [content-bottom] minmax(60px, max-content) [page-bottom]}.page-full{grid-column:screen-start/screen-end !important}.page-columns>*{grid-column:body-content-start/body-content-end}.page-columns.column-page>*{grid-column:page-start/page-end}.page-columns.column-page-left .page-columns.page-full>*,.page-columns.column-page-left>*{grid-column:page-start/body-content-end}.page-columns.column-page-right .page-columns.page-full>*,.page-columns.column-page-right>*{grid-column:body-content-start/page-end}.page-rows{grid-auto-rows:auto}.header{grid-column:screen-start/screen-end;grid-row:page-top/contents-top}#quarto-content{padding:0;grid-column:screen-start/screen-end;grid-row:contents-top/contents-bottom}body.floating .sidebar.sidebar-navigation{grid-column:page-start/body-start;grid-row:content-top/page-bottom}body.docked .sidebar.sidebar-navigation{grid-column:screen-start/body-start;grid-row:content-top/page-bottom}.sidebar.toc-left{grid-column:page-start/body-start;grid-row:content-top/page-bottom}.sidebar.margin-sidebar{grid-column:body-end/page-end;grid-row:content-top/page-bottom}.page-columns .content{grid-column:body-content-start/body-content-end;grid-row:content-top/content-bottom;align-content:flex-start}.page-columns .page-navigation{grid-column:body-content-start/body-content-end;grid-row:content-bottom/page-bottom}.page-columns .footer{grid-column:screen-start/screen-end;grid-row:contents-bottom/page-bottom}.page-columns .column-body{grid-column:body-content-start/body-content-end}.page-columns .column-body-fullbleed{grid-column:body-start/body-end}.page-columns .column-body-outset{grid-column:body-start-outset/body-end-outset;z-index:998;opacity:.999}.page-columns .column-body-outset table{background:#fff}.page-columns .column-body-outset-left{grid-column:body-start-outset/body-content-end;z-index:998;opacity:.999}.page-columns .column-body-outset-left table{background:#fff}.page-columns .column-body-outset-right{grid-column:body-content-start/body-end-outset;z-index:998;opacity:.999}.page-columns .column-body-outset-right table{background:#fff}.page-columns .column-page{grid-column:page-start/page-end;z-index:998;opacity:.999}.page-columns .column-page table{background:#fff}.page-columns .column-page-inset{grid-column:page-start-inset/page-end-inset;z-index:998;opacity:.999}.page-columns .column-page-inset table{background:#fff}.page-columns .column-page-inset-left{grid-column:page-start-inset/body-content-end;z-index:998;opacity:.999}.page-columns .column-page-inset-left table{background:#fff}.page-columns .column-page-inset-right{grid-column:body-content-start/page-end-inset;z-index:998;opacity:.999}.page-columns .column-page-inset-right figcaption table{background:#fff}.page-columns .column-page-left{grid-column:page-start/body-content-end;z-index:998;opacity:.999}.page-columns .column-page-left table{background:#fff}.page-columns .column-page-right{grid-column:body-content-start/page-end;z-index:998;opacity:.999}.page-columns .column-page-right figcaption table{background:#fff}#quarto-content.page-columns #quarto-margin-sidebar,#quarto-content.page-columns #quarto-sidebar{z-index:1}@media(max-width: 991.98px){#quarto-content.page-columns #quarto-margin-sidebar.collapse,#quarto-content.page-columns #quarto-sidebar.collapse,#quarto-content.page-columns #quarto-margin-sidebar.collapsing,#quarto-content.page-columns #quarto-sidebar.collapsing{z-index:1055}}#quarto-content.page-columns main.column-page,#quarto-content.page-columns main.column-page-right,#quarto-content.page-columns main.column-page-left{z-index:0}.page-columns .column-screen-inset{grid-column:screen-start-inset/screen-end-inset;z-index:998;opacity:.999}.page-columns .column-screen-inset table{background:#fff}.page-columns .column-screen-inset-left{grid-column:screen-start-inset/body-content-end;z-index:998;opacity:.999}.page-columns .column-screen-inset-left table{background:#fff}.page-columns .column-screen-inset-right{grid-column:body-content-start/screen-end-inset;z-index:998;opacity:.999}.page-columns .column-screen-inset-right table{background:#fff}.page-columns .column-screen{grid-column:screen-start/screen-end;z-index:998;opacity:.999}.page-columns .column-screen table{background:#fff}.page-columns .column-screen-left{grid-column:screen-start/body-content-end;z-index:998;opacity:.999}.page-columns .column-screen-left table{background:#fff}.page-columns .column-screen-right{grid-column:body-content-start/screen-end;z-index:998;opacity:.999}.page-columns .column-screen-right table{background:#fff}.page-columns .column-screen-inset-shaded{grid-column:screen-start/screen-end;padding:1em;background:#f8f9fa;z-index:998;opacity:.999;margin-bottom:1em}.zindex-content{z-index:998;opacity:.999}.zindex-modal{z-index:1055;opacity:.999}.zindex-over-content{z-index:999;opacity:.999}img.img-fluid.column-screen,img.img-fluid.column-screen-inset-shaded,img.img-fluid.column-screen-inset,img.img-fluid.column-screen-inset-left,img.img-fluid.column-screen-inset-right,img.img-fluid.column-screen-left,img.img-fluid.column-screen-right{width:100%}@media(min-width: 992px){.margin-caption,div.aside,aside:not(.footnotes):not(.sidebar),.column-margin{grid-column:body-end/page-end !important;z-index:998}.column-sidebar{grid-column:page-start/body-start !important;z-index:998}.column-leftmargin{grid-column:screen-start-inset/body-start !important;z-index:998}.no-row-height{height:1em;overflow:visible}}@media(max-width: 991.98px){.margin-caption,div.aside,aside:not(.footnotes):not(.sidebar),.column-margin{grid-column:body-end/page-end !important;z-index:998}.no-row-height{height:1em;overflow:visible}.page-columns.page-full{overflow:visible}.page-columns.toc-left .margin-caption,.page-columns.toc-left div.aside,.page-columns.toc-left aside:not(.footnotes):not(.sidebar),.page-columns.toc-left .column-margin{grid-column:body-content-start/body-content-end !important;z-index:998;opacity:.999}.page-columns.toc-left .no-row-height{height:initial;overflow:initial}}@media(max-width: 767.98px){.margin-caption,div.aside,aside:not(.footnotes):not(.sidebar),.column-margin{grid-column:body-content-start/body-content-end !important;z-index:998;opacity:.999}.no-row-height{height:initial;overflow:initial}#quarto-margin-sidebar{display:none}#quarto-sidebar-toc-left{display:none}.hidden-sm{display:none}}.panel-grid{display:grid;grid-template-rows:repeat(1, 1fr);grid-template-columns:repeat(24, 1fr);gap:1em}.panel-grid .g-col-1{grid-column:auto/span 1}.panel-grid .g-col-2{grid-column:auto/span 2}.panel-grid .g-col-3{grid-column:auto/span 3}.panel-grid .g-col-4{grid-column:auto/span 4}.panel-grid .g-col-5{grid-column:auto/span 5}.panel-grid .g-col-6{grid-column:auto/span 6}.panel-grid .g-col-7{grid-column:auto/span 7}.panel-grid .g-col-8{grid-column:auto/span 8}.panel-grid .g-col-9{grid-column:auto/span 9}.panel-grid .g-col-10{grid-column:auto/span 10}.panel-grid .g-col-11{grid-column:auto/span 11}.panel-grid .g-col-12{grid-column:auto/span 12}.panel-grid .g-col-13{grid-column:auto/span 13}.panel-grid .g-col-14{grid-column:auto/span 14}.panel-grid .g-col-15{grid-column:auto/span 15}.panel-grid .g-col-16{grid-column:auto/span 16}.panel-grid .g-col-17{grid-column:auto/span 17}.panel-grid .g-col-18{grid-column:auto/span 18}.panel-grid .g-col-19{grid-column:auto/span 19}.panel-grid .g-col-20{grid-column:auto/span 20}.panel-grid .g-col-21{grid-column:auto/span 21}.panel-grid .g-col-22{grid-column:auto/span 22}.panel-grid .g-col-23{grid-column:auto/span 23}.panel-grid .g-col-24{grid-column:auto/span 24}.panel-grid .g-start-1{grid-column-start:1}.panel-grid .g-start-2{grid-column-start:2}.panel-grid .g-start-3{grid-column-start:3}.panel-grid .g-start-4{grid-column-start:4}.panel-grid .g-start-5{grid-column-start:5}.panel-grid .g-start-6{grid-column-start:6}.panel-grid .g-start-7{grid-column-start:7}.panel-grid .g-start-8{grid-column-start:8}.panel-grid .g-start-9{grid-column-start:9}.panel-grid .g-start-10{grid-column-start:10}.panel-grid .g-start-11{grid-column-start:11}.panel-grid .g-start-12{grid-column-start:12}.panel-grid .g-start-13{grid-column-start:13}.panel-grid .g-start-14{grid-column-start:14}.panel-grid .g-start-15{grid-column-start:15}.panel-grid .g-start-16{grid-column-start:16}.panel-grid .g-start-17{grid-column-start:17}.panel-grid .g-start-18{grid-column-start:18}.panel-grid .g-start-19{grid-column-start:19}.panel-grid .g-start-20{grid-column-start:20}.panel-grid .g-start-21{grid-column-start:21}.panel-grid .g-start-22{grid-column-start:22}.panel-grid .g-start-23{grid-column-start:23}@media(min-width: 576px){.panel-grid .g-col-sm-1{grid-column:auto/span 1}.panel-grid .g-col-sm-2{grid-column:auto/span 2}.panel-grid .g-col-sm-3{grid-column:auto/span 3}.panel-grid .g-col-sm-4{grid-column:auto/span 4}.panel-grid .g-col-sm-5{grid-column:auto/span 5}.panel-grid .g-col-sm-6{grid-column:auto/span 6}.panel-grid .g-col-sm-7{grid-column:auto/span 7}.panel-grid .g-col-sm-8{grid-column:auto/span 8}.panel-grid .g-col-sm-9{grid-column:auto/span 9}.panel-grid .g-col-sm-10{grid-column:auto/span 10}.panel-grid .g-col-sm-11{grid-column:auto/span 11}.panel-grid .g-col-sm-12{grid-column:auto/span 12}.panel-grid .g-col-sm-13{grid-column:auto/span 13}.panel-grid .g-col-sm-14{grid-column:auto/span 14}.panel-grid .g-col-sm-15{grid-column:auto/span 15}.panel-grid .g-col-sm-16{grid-column:auto/span 16}.panel-grid .g-col-sm-17{grid-column:auto/span 17}.panel-grid .g-col-sm-18{grid-column:auto/span 18}.panel-grid .g-col-sm-19{grid-column:auto/span 19}.panel-grid .g-col-sm-20{grid-column:auto/span 20}.panel-grid .g-col-sm-21{grid-column:auto/span 21}.panel-grid .g-col-sm-22{grid-column:auto/span 22}.panel-grid .g-col-sm-23{grid-column:auto/span 23}.panel-grid .g-col-sm-24{grid-column:auto/span 24}.panel-grid .g-start-sm-1{grid-column-start:1}.panel-grid .g-start-sm-2{grid-column-start:2}.panel-grid .g-start-sm-3{grid-column-start:3}.panel-grid .g-start-sm-4{grid-column-start:4}.panel-grid .g-start-sm-5{grid-column-start:5}.panel-grid .g-start-sm-6{grid-column-start:6}.panel-grid .g-start-sm-7{grid-column-start:7}.panel-grid .g-start-sm-8{grid-column-start:8}.panel-grid .g-start-sm-9{grid-column-start:9}.panel-grid .g-start-sm-10{grid-column-start:10}.panel-grid .g-start-sm-11{grid-column-start:11}.panel-grid .g-start-sm-12{grid-column-start:12}.panel-grid .g-start-sm-13{grid-column-start:13}.panel-grid .g-start-sm-14{grid-column-start:14}.panel-grid .g-start-sm-15{grid-column-start:15}.panel-grid .g-start-sm-16{grid-column-start:16}.panel-grid .g-start-sm-17{grid-column-start:17}.panel-grid .g-start-sm-18{grid-column-start:18}.panel-grid .g-start-sm-19{grid-column-start:19}.panel-grid .g-start-sm-20{grid-column-start:20}.panel-grid .g-start-sm-21{grid-column-start:21}.panel-grid .g-start-sm-22{grid-column-start:22}.panel-grid .g-start-sm-23{grid-column-start:23}}@media(min-width: 768px){.panel-grid .g-col-md-1{grid-column:auto/span 1}.panel-grid .g-col-md-2{grid-column:auto/span 2}.panel-grid .g-col-md-3{grid-column:auto/span 3}.panel-grid .g-col-md-4{grid-column:auto/span 4}.panel-grid .g-col-md-5{grid-column:auto/span 5}.panel-grid .g-col-md-6{grid-column:auto/span 6}.panel-grid .g-col-md-7{grid-column:auto/span 7}.panel-grid .g-col-md-8{grid-column:auto/span 8}.panel-grid .g-col-md-9{grid-column:auto/span 9}.panel-grid .g-col-md-10{grid-column:auto/span 10}.panel-grid .g-col-md-11{grid-column:auto/span 11}.panel-grid .g-col-md-12{grid-column:auto/span 12}.panel-grid .g-col-md-13{grid-column:auto/span 13}.panel-grid .g-col-md-14{grid-column:auto/span 14}.panel-grid .g-col-md-15{grid-column:auto/span 15}.panel-grid .g-col-md-16{grid-column:auto/span 16}.panel-grid .g-col-md-17{grid-column:auto/span 17}.panel-grid .g-col-md-18{grid-column:auto/span 18}.panel-grid .g-col-md-19{grid-column:auto/span 19}.panel-grid .g-col-md-20{grid-column:auto/span 20}.panel-grid .g-col-md-21{grid-column:auto/span 21}.panel-grid .g-col-md-22{grid-column:auto/span 22}.panel-grid .g-col-md-23{grid-column:auto/span 23}.panel-grid .g-col-md-24{grid-column:auto/span 24}.panel-grid .g-start-md-1{grid-column-start:1}.panel-grid .g-start-md-2{grid-column-start:2}.panel-grid .g-start-md-3{grid-column-start:3}.panel-grid .g-start-md-4{grid-column-start:4}.panel-grid .g-start-md-5{grid-column-start:5}.panel-grid .g-start-md-6{grid-column-start:6}.panel-grid .g-start-md-7{grid-column-start:7}.panel-grid .g-start-md-8{grid-column-start:8}.panel-grid .g-start-md-9{grid-column-start:9}.panel-grid .g-start-md-10{grid-column-start:10}.panel-grid .g-start-md-11{grid-column-start:11}.panel-grid .g-start-md-12{grid-column-start:12}.panel-grid .g-start-md-13{grid-column-start:13}.panel-grid .g-start-md-14{grid-column-start:14}.panel-grid .g-start-md-15{grid-column-start:15}.panel-grid .g-start-md-16{grid-column-start:16}.panel-grid .g-start-md-17{grid-column-start:17}.panel-grid .g-start-md-18{grid-column-start:18}.panel-grid .g-start-md-19{grid-column-start:19}.panel-grid .g-start-md-20{grid-column-start:20}.panel-grid .g-start-md-21{grid-column-start:21}.panel-grid .g-start-md-22{grid-column-start:22}.panel-grid .g-start-md-23{grid-column-start:23}}@media(min-width: 992px){.panel-grid .g-col-lg-1{grid-column:auto/span 1}.panel-grid .g-col-lg-2{grid-column:auto/span 2}.panel-grid .g-col-lg-3{grid-column:auto/span 3}.panel-grid .g-col-lg-4{grid-column:auto/span 4}.panel-grid .g-col-lg-5{grid-column:auto/span 5}.panel-grid .g-col-lg-6{grid-column:auto/span 6}.panel-grid .g-col-lg-7{grid-column:auto/span 7}.panel-grid .g-col-lg-8{grid-column:auto/span 8}.panel-grid .g-col-lg-9{grid-column:auto/span 9}.panel-grid .g-col-lg-10{grid-column:auto/span 10}.panel-grid .g-col-lg-11{grid-column:auto/span 11}.panel-grid .g-col-lg-12{grid-column:auto/span 12}.panel-grid .g-col-lg-13{grid-column:auto/span 13}.panel-grid .g-col-lg-14{grid-column:auto/span 14}.panel-grid .g-col-lg-15{grid-column:auto/span 15}.panel-grid .g-col-lg-16{grid-column:auto/span 16}.panel-grid .g-col-lg-17{grid-column:auto/span 17}.panel-grid .g-col-lg-18{grid-column:auto/span 18}.panel-grid .g-col-lg-19{grid-column:auto/span 19}.panel-grid .g-col-lg-20{grid-column:auto/span 20}.panel-grid .g-col-lg-21{grid-column:auto/span 21}.panel-grid .g-col-lg-22{grid-column:auto/span 22}.panel-grid .g-col-lg-23{grid-column:auto/span 23}.panel-grid .g-col-lg-24{grid-column:auto/span 24}.panel-grid .g-start-lg-1{grid-column-start:1}.panel-grid .g-start-lg-2{grid-column-start:2}.panel-grid .g-start-lg-3{grid-column-start:3}.panel-grid .g-start-lg-4{grid-column-start:4}.panel-grid .g-start-lg-5{grid-column-start:5}.panel-grid .g-start-lg-6{grid-column-start:6}.panel-grid .g-start-lg-7{grid-column-start:7}.panel-grid .g-start-lg-8{grid-column-start:8}.panel-grid .g-start-lg-9{grid-column-start:9}.panel-grid .g-start-lg-10{grid-column-start:10}.panel-grid .g-start-lg-11{grid-column-start:11}.panel-grid .g-start-lg-12{grid-column-start:12}.panel-grid .g-start-lg-13{grid-column-start:13}.panel-grid .g-start-lg-14{grid-column-start:14}.panel-grid .g-start-lg-15{grid-column-start:15}.panel-grid .g-start-lg-16{grid-column-start:16}.panel-grid .g-start-lg-17{grid-column-start:17}.panel-grid .g-start-lg-18{grid-column-start:18}.panel-grid .g-start-lg-19{grid-column-start:19}.panel-grid .g-start-lg-20{grid-column-start:20}.panel-grid .g-start-lg-21{grid-column-start:21}.panel-grid .g-start-lg-22{grid-column-start:22}.panel-grid .g-start-lg-23{grid-column-start:23}}@media(min-width: 1200px){.panel-grid .g-col-xl-1{grid-column:auto/span 1}.panel-grid .g-col-xl-2{grid-column:auto/span 2}.panel-grid .g-col-xl-3{grid-column:auto/span 3}.panel-grid .g-col-xl-4{grid-column:auto/span 4}.panel-grid .g-col-xl-5{grid-column:auto/span 5}.panel-grid .g-col-xl-6{grid-column:auto/span 6}.panel-grid .g-col-xl-7{grid-column:auto/span 7}.panel-grid .g-col-xl-8{grid-column:auto/span 8}.panel-grid .g-col-xl-9{grid-column:auto/span 9}.panel-grid .g-col-xl-10{grid-column:auto/span 10}.panel-grid .g-col-xl-11{grid-column:auto/span 11}.panel-grid .g-col-xl-12{grid-column:auto/span 12}.panel-grid .g-col-xl-13{grid-column:auto/span 13}.panel-grid .g-col-xl-14{grid-column:auto/span 14}.panel-grid .g-col-xl-15{grid-column:auto/span 15}.panel-grid .g-col-xl-16{grid-column:auto/span 16}.panel-grid .g-col-xl-17{grid-column:auto/span 17}.panel-grid .g-col-xl-18{grid-column:auto/span 18}.panel-grid .g-col-xl-19{grid-column:auto/span 19}.panel-grid .g-col-xl-20{grid-column:auto/span 20}.panel-grid .g-col-xl-21{grid-column:auto/span 21}.panel-grid .g-col-xl-22{grid-column:auto/span 22}.panel-grid .g-col-xl-23{grid-column:auto/span 23}.panel-grid .g-col-xl-24{grid-column:auto/span 24}.panel-grid .g-start-xl-1{grid-column-start:1}.panel-grid .g-start-xl-2{grid-column-start:2}.panel-grid .g-start-xl-3{grid-column-start:3}.panel-grid .g-start-xl-4{grid-column-start:4}.panel-grid .g-start-xl-5{grid-column-start:5}.panel-grid .g-start-xl-6{grid-column-start:6}.panel-grid .g-start-xl-7{grid-column-start:7}.panel-grid .g-start-xl-8{grid-column-start:8}.panel-grid .g-start-xl-9{grid-column-start:9}.panel-grid .g-start-xl-10{grid-column-start:10}.panel-grid .g-start-xl-11{grid-column-start:11}.panel-grid .g-start-xl-12{grid-column-start:12}.panel-grid .g-start-xl-13{grid-column-start:13}.panel-grid .g-start-xl-14{grid-column-start:14}.panel-grid .g-start-xl-15{grid-column-start:15}.panel-grid .g-start-xl-16{grid-column-start:16}.panel-grid .g-start-xl-17{grid-column-start:17}.panel-grid .g-start-xl-18{grid-column-start:18}.panel-grid .g-start-xl-19{grid-column-start:19}.panel-grid .g-start-xl-20{grid-column-start:20}.panel-grid .g-start-xl-21{grid-column-start:21}.panel-grid .g-start-xl-22{grid-column-start:22}.panel-grid .g-start-xl-23{grid-column-start:23}}@media(min-width: 1400px){.panel-grid .g-col-xxl-1{grid-column:auto/span 1}.panel-grid .g-col-xxl-2{grid-column:auto/span 2}.panel-grid .g-col-xxl-3{grid-column:auto/span 3}.panel-grid .g-col-xxl-4{grid-column:auto/span 4}.panel-grid .g-col-xxl-5{grid-column:auto/span 5}.panel-grid .g-col-xxl-6{grid-column:auto/span 6}.panel-grid .g-col-xxl-7{grid-column:auto/span 7}.panel-grid .g-col-xxl-8{grid-column:auto/span 8}.panel-grid .g-col-xxl-9{grid-column:auto/span 9}.panel-grid .g-col-xxl-10{grid-column:auto/span 10}.panel-grid .g-col-xxl-11{grid-column:auto/span 11}.panel-grid .g-col-xxl-12{grid-column:auto/span 12}.panel-grid .g-col-xxl-13{grid-column:auto/span 13}.panel-grid .g-col-xxl-14{grid-column:auto/span 14}.panel-grid .g-col-xxl-15{grid-column:auto/span 15}.panel-grid .g-col-xxl-16{grid-column:auto/span 16}.panel-grid .g-col-xxl-17{grid-column:auto/span 17}.panel-grid .g-col-xxl-18{grid-column:auto/span 18}.panel-grid .g-col-xxl-19{grid-column:auto/span 19}.panel-grid .g-col-xxl-20{grid-column:auto/span 20}.panel-grid .g-col-xxl-21{grid-column:auto/span 21}.panel-grid .g-col-xxl-22{grid-column:auto/span 22}.panel-grid .g-col-xxl-23{grid-column:auto/span 23}.panel-grid .g-col-xxl-24{grid-column:auto/span 24}.panel-grid .g-start-xxl-1{grid-column-start:1}.panel-grid .g-start-xxl-2{grid-column-start:2}.panel-grid .g-start-xxl-3{grid-column-start:3}.panel-grid .g-start-xxl-4{grid-column-start:4}.panel-grid .g-start-xxl-5{grid-column-start:5}.panel-grid .g-start-xxl-6{grid-column-start:6}.panel-grid .g-start-xxl-7{grid-column-start:7}.panel-grid .g-start-xxl-8{grid-column-start:8}.panel-grid .g-start-xxl-9{grid-column-start:9}.panel-grid .g-start-xxl-10{grid-column-start:10}.panel-grid .g-start-xxl-11{grid-column-start:11}.panel-grid .g-start-xxl-12{grid-column-start:12}.panel-grid .g-start-xxl-13{grid-column-start:13}.panel-grid .g-start-xxl-14{grid-column-start:14}.panel-grid .g-start-xxl-15{grid-column-start:15}.panel-grid .g-start-xxl-16{grid-column-start:16}.panel-grid .g-start-xxl-17{grid-column-start:17}.panel-grid .g-start-xxl-18{grid-column-start:18}.panel-grid .g-start-xxl-19{grid-column-start:19}.panel-grid .g-start-xxl-20{grid-column-start:20}.panel-grid .g-start-xxl-21{grid-column-start:21}.panel-grid .g-start-xxl-22{grid-column-start:22}.panel-grid .g-start-xxl-23{grid-column-start:23}}main{margin-top:1em;margin-bottom:1em}h1,.h1,h2,.h2{color:inherit;margin-top:2rem;margin-bottom:1rem;font-weight:600}h1.title,.title.h1{margin-top:0}main.content>section:first-of-type>h2:first-child,main.content>section:first-of-type>.h2:first-child{margin-top:0}h2,.h2{border-bottom:1px solid #dee2e6;padding-bottom:.5rem}h3,.h3{font-weight:600}h3,.h3,h4,.h4{opacity:.9;margin-top:1.5rem}h5,.h5,h6,.h6{opacity:.9}.header-section-number{color:#5a6570}.nav-link.active .header-section-number{color:inherit}mark,.mark{padding:0em}.panel-caption,.figure-caption,.subfigure-caption,.table-caption,figcaption,caption{font-size:.9rem;color:#5a6570}.quarto-layout-cell[data-ref-parent] caption{color:#5a6570}.column-margin figcaption,.margin-caption,div.aside,aside,.column-margin{color:#5a6570;font-size:.825rem}.panel-caption.margin-caption{text-align:inherit}.column-margin.column-container p{margin-bottom:0}.column-margin.column-container>*:not(.collapse):first-child{padding-bottom:.5em;display:block}.column-margin.column-container>*:not(.collapse):not(:first-child){padding-top:.5em;padding-bottom:.5em;display:block}.column-margin.column-container>*.collapse:not(.show){display:none}@media(min-width: 768px){.column-margin.column-container .callout-margin-content:first-child{margin-top:4.5em}.column-margin.column-container .callout-margin-content-simple:first-child{margin-top:3.5em}}.margin-caption>*{padding-top:.5em;padding-bottom:.5em}@media(max-width: 767.98px){.quarto-layout-row{flex-direction:column}}.nav-tabs .nav-item{margin-top:1px;cursor:pointer}.tab-content{margin-top:0px;border-left:#dee2e6 1px solid;border-right:#dee2e6 1px solid;border-bottom:#dee2e6 1px solid;margin-left:0;padding:1em;margin-bottom:1em}@media(max-width: 767.98px){.layout-sidebar{margin-left:0;margin-right:0}}.panel-sidebar,.panel-sidebar .form-control,.panel-input,.panel-input .form-control,.selectize-dropdown{font-size:.9rem}.panel-sidebar .form-control,.panel-input .form-control{padding-top:.1rem}.tab-pane div.sourceCode{margin-top:0px}.tab-pane>p{padding-top:0}.tab-pane>p:nth-child(1){padding-top:0}.tab-pane>p:last-child{margin-bottom:0}.tab-pane>pre:last-child{margin-bottom:0}.tab-content>.tab-pane:not(.active){display:none !important}div.sourceCode{background-color:rgba(233,236,239,.65);border:1px solid rgba(233,236,239,.65);border-radius:.25rem}pre.sourceCode{background-color:rgba(0,0,0,0)}pre.sourceCode{border:none;font-size:.875em;overflow:visible !important;padding:.4em}.callout pre.sourceCode{padding-left:0}div.sourceCode{overflow-y:hidden}.callout div.sourceCode{margin-left:initial}.blockquote{font-size:inherit;padding-left:1rem;padding-right:1.5rem;color:#5a6570}.blockquote h1:first-child,.blockquote .h1:first-child,.blockquote h2:first-child,.blockquote .h2:first-child,.blockquote h3:first-child,.blockquote .h3:first-child,.blockquote h4:first-child,.blockquote .h4:first-child,.blockquote h5:first-child,.blockquote .h5:first-child{margin-top:0}pre{background-color:initial;padding:initial;border:initial}p code:not(.sourceCode),li code:not(.sourceCode),kbd,pre:not(.sourceCode),samp{background-color:#f6f6f6;padding:.2em}p pre code:not(.sourceCode),li pre code:not(.sourceCode),pre code:not(.sourceCode){background-color:initial}p code:not(.sourceCode),li code:not(.sourceCode),td code:not(.sourceCode){background-color:#f6f6f6;padding:.2em}nav p code:not(.sourceCode),nav li code:not(.sourceCode),nav td code:not(.sourceCode){background-color:rgba(0,0,0,0);padding:0}td code:not(.sourceCode){white-space:pre-wrap}#quarto-embedded-source-code-modal>.modal-dialog{max-width:1000px;padding-left:1.75rem;padding-right:1.75rem}#quarto-embedded-source-code-modal>.modal-dialog>.modal-content>.modal-body{padding:0}#quarto-embedded-source-code-modal>.modal-dialog>.modal-content>.modal-body div.sourceCode{margin:0;padding:.2rem .2rem;border-radius:0px;border:none}#quarto-embedded-source-code-modal>.modal-dialog>.modal-content>.modal-header{padding:.7rem}.code-tools-button{font-size:1rem;padding:.15rem .15rem;margin-left:5px;color:#6c757d;background-color:rgba(0,0,0,0);transition:initial;cursor:pointer}.code-tools-button>.bi::before{display:inline-block;height:1rem;width:1rem;content:"";vertical-align:-0.125em;background-image:url('data:image/svg+xml,');background-repeat:no-repeat;background-size:1rem 1rem}.code-tools-button:hover>.bi::before{background-image:url('data:image/svg+xml,')}#quarto-embedded-source-code-modal .code-copy-button>.bi::before{background-image:url('data:image/svg+xml,')}#quarto-embedded-source-code-modal .code-copy-button-checked>.bi::before{background-image:url('data:image/svg+xml,')}.sidebar{will-change:top;transition:top 200ms linear;position:sticky;overflow-y:auto;padding-top:1.2em;max-height:100vh}.sidebar.toc-left,.sidebar.margin-sidebar{top:0px;padding-top:1em}.sidebar.quarto-banner-title-block-sidebar>*{padding-top:1.65em}figure .quarto-notebook-link{margin-top:.5em}.quarto-notebook-link{font-size:.75em;color:#6c757d;margin-bottom:1em;text-decoration:none;display:block}.quarto-notebook-link:hover{text-decoration:underline;color:#03638e}.quarto-notebook-link::before{display:inline-block;height:.75rem;width:.75rem;margin-bottom:0em;margin-right:.25em;content:"";vertical-align:-0.125em;background-image:url('data:image/svg+xml,');background-repeat:no-repeat;background-size:.75rem .75rem}.toc-actions i.bi,.quarto-code-links i.bi,.quarto-other-links i.bi,.quarto-alternate-notebooks i.bi,.quarto-alternate-formats i.bi{margin-right:.4em;font-size:.8rem}.quarto-other-links-text-target .quarto-code-links i.bi,.quarto-other-links-text-target .quarto-other-links i.bi{margin-right:.2em}.quarto-other-formats-text-target .quarto-alternate-formats i.bi{margin-right:.1em}.toc-actions i.bi.empty,.quarto-code-links i.bi.empty,.quarto-other-links i.bi.empty,.quarto-alternate-notebooks i.bi.empty,.quarto-alternate-formats i.bi.empty{padding-left:1em}.quarto-notebook h2,.quarto-notebook .h2{border-bottom:none}.quarto-notebook .cell-container{display:flex}.quarto-notebook .cell-container .cell{flex-grow:4}.quarto-notebook .cell-container .cell-decorator{padding-top:1.5em;padding-right:1em;text-align:right}.quarto-notebook .cell-container.code-fold .cell-decorator{padding-top:3em}.quarto-notebook .cell-code code{white-space:pre-wrap}.quarto-notebook .cell .cell-output-stderr pre code,.quarto-notebook .cell .cell-output-stdout pre code{white-space:pre-wrap;overflow-wrap:anywhere}.toc-actions,.quarto-alternate-formats,.quarto-other-links,.quarto-code-links,.quarto-alternate-notebooks{padding-left:0em}.sidebar .toc-actions a,.sidebar .quarto-alternate-formats a,.sidebar .quarto-other-links a,.sidebar .quarto-code-links a,.sidebar .quarto-alternate-notebooks a,.sidebar nav[role=doc-toc] a{text-decoration:none}.sidebar .toc-actions a:hover,.sidebar .quarto-other-links a:hover,.sidebar .quarto-code-links a:hover,.sidebar .quarto-alternate-formats a:hover,.sidebar .quarto-alternate-notebooks a:hover{color:#03638e}.sidebar .toc-actions h2,.sidebar .toc-actions .h2,.sidebar .quarto-code-links h2,.sidebar .quarto-code-links .h2,.sidebar .quarto-other-links h2,.sidebar .quarto-other-links .h2,.sidebar .quarto-alternate-notebooks h2,.sidebar .quarto-alternate-notebooks .h2,.sidebar .quarto-alternate-formats h2,.sidebar .quarto-alternate-formats .h2,.sidebar nav[role=doc-toc]>h2,.sidebar nav[role=doc-toc]>.h2{font-weight:500;margin-bottom:.2rem;margin-top:.3rem;font-family:inherit;border-bottom:0;padding-bottom:0;padding-top:0px}.sidebar .toc-actions>h2,.sidebar .toc-actions>.h2,.sidebar .quarto-code-links>h2,.sidebar .quarto-code-links>.h2,.sidebar .quarto-other-links>h2,.sidebar .quarto-other-links>.h2,.sidebar .quarto-alternate-notebooks>h2,.sidebar .quarto-alternate-notebooks>.h2,.sidebar .quarto-alternate-formats>h2,.sidebar .quarto-alternate-formats>.h2{font-size:.8rem}.sidebar nav[role=doc-toc]>h2,.sidebar nav[role=doc-toc]>.h2{font-size:.875rem}.sidebar nav[role=doc-toc]>ul a{border-left:1px solid #e9ecef;padding-left:.6rem}.sidebar .toc-actions h2>ul a,.sidebar .toc-actions .h2>ul a,.sidebar .quarto-code-links h2>ul a,.sidebar .quarto-code-links .h2>ul a,.sidebar .quarto-other-links h2>ul a,.sidebar .quarto-other-links .h2>ul a,.sidebar .quarto-alternate-notebooks h2>ul a,.sidebar .quarto-alternate-notebooks .h2>ul a,.sidebar .quarto-alternate-formats h2>ul a,.sidebar .quarto-alternate-formats .h2>ul a{border-left:none;padding-left:.6rem}.sidebar .toc-actions ul a:empty,.sidebar .quarto-code-links ul a:empty,.sidebar .quarto-other-links ul a:empty,.sidebar .quarto-alternate-notebooks ul a:empty,.sidebar .quarto-alternate-formats ul a:empty,.sidebar nav[role=doc-toc]>ul a:empty{display:none}.sidebar .toc-actions ul,.sidebar .quarto-code-links ul,.sidebar .quarto-other-links ul,.sidebar .quarto-alternate-notebooks ul,.sidebar .quarto-alternate-formats ul{padding-left:0;list-style:none}.sidebar nav[role=doc-toc] ul{list-style:none;padding-left:0;list-style:none}.sidebar nav[role=doc-toc]>ul{margin-left:.45em}.quarto-margin-sidebar nav[role=doc-toc]{padding-left:.5em}.sidebar .toc-actions>ul,.sidebar .quarto-code-links>ul,.sidebar .quarto-other-links>ul,.sidebar .quarto-alternate-notebooks>ul,.sidebar .quarto-alternate-formats>ul{font-size:.8rem}.sidebar nav[role=doc-toc]>ul{font-size:.875rem}.sidebar .toc-actions ul li a,.sidebar .quarto-code-links ul li a,.sidebar .quarto-other-links ul li a,.sidebar .quarto-alternate-notebooks ul li a,.sidebar .quarto-alternate-formats ul li a,.sidebar nav[role=doc-toc]>ul li a{line-height:1.1rem;padding-bottom:.2rem;padding-top:.2rem;color:inherit}.sidebar nav[role=doc-toc] ul>li>ul>li>a{padding-left:1.2em}.sidebar nav[role=doc-toc] ul>li>ul>li>ul>li>a{padding-left:2.4em}.sidebar nav[role=doc-toc] ul>li>ul>li>ul>li>ul>li>a{padding-left:3.6em}.sidebar nav[role=doc-toc] ul>li>ul>li>ul>li>ul>li>ul>li>a{padding-left:4.8em}.sidebar nav[role=doc-toc] ul>li>ul>li>ul>li>ul>li>ul>li>ul>li>a{padding-left:6em}.sidebar nav[role=doc-toc] ul>li>a.active,.sidebar nav[role=doc-toc] ul>li>ul>li>a.active{border-left:1px solid #03638e;color:#03638e !important}.sidebar nav[role=doc-toc] ul>li>a:hover,.sidebar nav[role=doc-toc] ul>li>ul>li>a:hover{color:#03638e !important}kbd,.kbd{color:#212529;background-color:#f8f9fa;border:1px solid;border-radius:5px;border-color:#dee2e6}.quarto-appendix-contents div.hanging-indent{margin-left:0em}.quarto-appendix-contents div.hanging-indent div.csl-entry{margin-left:1em;text-indent:-1em}.citation a,.footnote-ref{text-decoration:none}.footnotes ol{padding-left:1em}.tippy-content>*{margin-bottom:.7em}.tippy-content>*:last-child{margin-bottom:0}.callout{margin-top:1.25rem;margin-bottom:1.25rem;border-radius:.25rem;overflow-wrap:break-word}.callout .callout-title-container{overflow-wrap:anywhere}.callout.callout-style-simple{padding:.4em .7em;border-left:5px solid;border-right:1px solid #dee2e6;border-top:1px solid #dee2e6;border-bottom:1px solid #dee2e6}.callout.callout-style-default{border-left:5px solid;border-right:1px solid #dee2e6;border-top:1px solid #dee2e6;border-bottom:1px solid #dee2e6}.callout .callout-body-container{flex-grow:1}.callout.callout-style-simple .callout-body{font-size:.9rem;font-weight:400}.callout.callout-style-default .callout-body{font-size:.9rem;font-weight:400}.callout:not(.no-icon).callout-titled.callout-style-simple .callout-body{padding-left:1.6em}.callout.callout-titled>.callout-header{padding-top:.2em;margin-bottom:-0.2em}.callout.callout-style-simple>div.callout-header{border-bottom:none;font-size:.9rem;font-weight:600;opacity:75%}.callout.callout-style-default>div.callout-header{border-bottom:none;font-weight:600;opacity:85%;font-size:.9rem;padding-left:.5em;padding-right:.5em}.callout.callout-style-default .callout-body{padding-left:.5em;padding-right:.5em}.callout.callout-style-default .callout-body>:first-child{padding-top:.5rem;margin-top:0}.callout>div.callout-header[data-bs-toggle=collapse]{cursor:pointer}.callout.callout-style-default .callout-header[aria-expanded=false],.callout.callout-style-default .callout-header[aria-expanded=true]{padding-top:0px;margin-bottom:0px;align-items:center}.callout.callout-titled .callout-body>:last-child:not(.sourceCode),.callout.callout-titled .callout-body>div>:last-child:not(.sourceCode){padding-bottom:.5rem;margin-bottom:0}.callout:not(.callout-titled) .callout-body>:first-child,.callout:not(.callout-titled) .callout-body>div>:first-child{margin-top:.25rem}.callout:not(.callout-titled) .callout-body>:last-child,.callout:not(.callout-titled) .callout-body>div>:last-child{margin-bottom:.2rem}.callout.callout-style-simple .callout-icon::before,.callout.callout-style-simple .callout-toggle::before{height:1rem;width:1rem;display:inline-block;content:"";background-repeat:no-repeat;background-size:1rem 1rem}.callout.callout-style-default .callout-icon::before,.callout.callout-style-default .callout-toggle::before{height:.9rem;width:.9rem;display:inline-block;content:"";background-repeat:no-repeat;background-size:.9rem .9rem}.callout.callout-style-default .callout-toggle::before{margin-top:5px}.callout .callout-btn-toggle .callout-toggle::before{transition:transform .2s linear}.callout .callout-header[aria-expanded=false] .callout-toggle::before{transform:rotate(-90deg)}.callout .callout-header[aria-expanded=true] .callout-toggle::before{transform:none}.callout.callout-style-simple:not(.no-icon) div.callout-icon-container{padding-top:.2em;padding-right:.55em}.callout.callout-style-default:not(.no-icon) div.callout-icon-container{padding-top:.1em;padding-right:.35em}.callout.callout-style-default:not(.no-icon) div.callout-title-container{margin-top:-1px}.callout.callout-style-default.callout-caution:not(.no-icon) div.callout-icon-container{padding-top:.3em;padding-right:.35em}.callout>.callout-body>.callout-icon-container>.no-icon,.callout>.callout-header>.callout-icon-container>.no-icon{display:none}div.callout.callout{border-left-color:#6c757d}div.callout.callout-style-default>.callout-header{background-color:#6c757d}div.callout-note.callout{border-left-color:#0d6efd}div.callout-note.callout-style-default>.callout-header{background-color:#e7f1ff}div.callout-note:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-note.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-note .callout-toggle::before{background-image:url('data:image/svg+xml,')}div.callout-tip.callout{border-left-color:#198754}div.callout-tip.callout-style-default>.callout-header{background-color:#e8f3ee}div.callout-tip:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-tip.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-tip .callout-toggle::before{background-image:url('data:image/svg+xml,')}div.callout-warning.callout{border-left-color:#ffc107}div.callout-warning.callout-style-default>.callout-header{background-color:#fff9e6}div.callout-warning:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-warning.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-warning .callout-toggle::before{background-image:url('data:image/svg+xml,')}div.callout-caution.callout{border-left-color:#fd7e14}div.callout-caution.callout-style-default>.callout-header{background-color:#fff2e8}div.callout-caution:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-caution.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-caution .callout-toggle::before{background-image:url('data:image/svg+xml,')}div.callout-important.callout{border-left-color:#dc3545}div.callout-important.callout-style-default>.callout-header{background-color:#fcebec}div.callout-important:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-important.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-important .callout-toggle::before{background-image:url('data:image/svg+xml,')}.quarto-toggle-container{display:flex;align-items:center}.quarto-reader-toggle .bi::before,.quarto-color-scheme-toggle .bi::before{display:inline-block;height:1rem;width:1rem;content:"";background-repeat:no-repeat;background-size:1rem 1rem}.sidebar-navigation{padding-left:20px}.navbar{background-color:#fff;color:#595959}.navbar .quarto-color-scheme-toggle:not(.alternate) .bi::before{background-image:url('data:image/svg+xml,')}.navbar .quarto-color-scheme-toggle.alternate .bi::before{background-image:url('data:image/svg+xml,')}.sidebar-navigation .quarto-color-scheme-toggle:not(.alternate) .bi::before{background-image:url('data:image/svg+xml,')}.sidebar-navigation .quarto-color-scheme-toggle.alternate .bi::before{background-image:url('data:image/svg+xml,')}.quarto-sidebar-toggle{border-color:#dee2e6;border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem;border-style:solid;border-width:1px;overflow:hidden;border-top-width:0px;padding-top:0px !important}.quarto-sidebar-toggle-title{cursor:pointer;padding-bottom:2px;margin-left:.25em;text-align:center;font-weight:400;font-size:.775em}#quarto-content .quarto-sidebar-toggle{background:#fafafa}#quarto-content .quarto-sidebar-toggle-title{color:#212529}.quarto-sidebar-toggle-icon{color:#dee2e6;margin-right:.5em;float:right;transition:transform .2s ease}.quarto-sidebar-toggle-icon::before{padding-top:5px}.quarto-sidebar-toggle.expanded .quarto-sidebar-toggle-icon{transform:rotate(-180deg)}.quarto-sidebar-toggle.expanded .quarto-sidebar-toggle-title{border-bottom:solid #dee2e6 1px}.quarto-sidebar-toggle-contents{background-color:#fff;padding-right:10px;padding-left:10px;margin-top:0px !important;transition:max-height .5s ease}.quarto-sidebar-toggle.expanded .quarto-sidebar-toggle-contents{padding-top:1em;padding-bottom:10px}@media(max-width: 767.98px){.sidebar-menu-container{padding-bottom:5em}}.quarto-sidebar-toggle:not(.expanded) .quarto-sidebar-toggle-contents{padding-top:0px !important;padding-bottom:0px}nav[role=doc-toc]{z-index:1020}#quarto-sidebar>*,nav[role=doc-toc]>*{transition:opacity .1s ease,border .1s ease}#quarto-sidebar.slow>*,nav[role=doc-toc].slow>*{transition:opacity .4s ease,border .4s ease}.quarto-color-scheme-toggle:not(.alternate).top-right .bi::before{background-image:url('data:image/svg+xml,')}.quarto-color-scheme-toggle.alternate.top-right .bi::before{background-image:url('data:image/svg+xml,')}#quarto-appendix.default{border-top:1px solid #dee2e6}#quarto-appendix.default{background-color:#fff;padding-top:1.5em;margin-top:2em;z-index:998}#quarto-appendix.default .quarto-appendix-heading{margin-top:0;line-height:1.4em;font-weight:600;opacity:.9;border-bottom:none;margin-bottom:0}#quarto-appendix.default .footnotes ol,#quarto-appendix.default .footnotes ol li>p:last-of-type,#quarto-appendix.default .quarto-appendix-contents>p:last-of-type{margin-bottom:0}#quarto-appendix.default .footnotes ol{margin-left:.5em}#quarto-appendix.default .quarto-appendix-secondary-label{margin-bottom:.4em}#quarto-appendix.default .quarto-appendix-bibtex{font-size:.7em;padding:1em;border:solid 1px #dee2e6;margin-bottom:1em}#quarto-appendix.default .quarto-appendix-bibtex code.sourceCode{white-space:pre-wrap}#quarto-appendix.default .quarto-appendix-citeas{font-size:.9em;padding:1em;border:solid 1px #dee2e6;margin-bottom:1em}#quarto-appendix.default .quarto-appendix-heading{font-size:1em !important}#quarto-appendix.default *[role=doc-endnotes]>ol,#quarto-appendix.default .quarto-appendix-contents>*:not(h2):not(.h2){font-size:.9em}#quarto-appendix.default section{padding-bottom:1.5em}#quarto-appendix.default section *[role=doc-endnotes],#quarto-appendix.default section>*:not(a){opacity:.9;word-wrap:break-word}.btn.btn-quarto,div.cell-output-display .btn-quarto{--bs-btn-color: #fefefe;--bs-btn-bg: #6c757d;--bs-btn-border-color: #6c757d;--bs-btn-hover-color: #fefefe;--bs-btn-hover-bg: #828a91;--bs-btn-hover-border-color: #7b838a;--bs-btn-focus-shadow-rgb: 130, 138, 144;--bs-btn-active-color: #000;--bs-btn-active-bg: #899197;--bs-btn-active-border-color: #7b838a;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #ffffff;--bs-btn-disabled-bg: #6c757d;--bs-btn-disabled-border-color: #6c757d}nav.quarto-secondary-nav.color-navbar{background-color:#fff;color:#595959}nav.quarto-secondary-nav.color-navbar h1,nav.quarto-secondary-nav.color-navbar .h1,nav.quarto-secondary-nav.color-navbar .quarto-btn-toggle{color:#595959}@media(max-width: 991.98px){body.nav-sidebar .quarto-title-banner{margin-bottom:0;padding-bottom:1em}body.nav-sidebar #title-block-header{margin-block-end:0}}p.subtitle{margin-top:.25em;margin-bottom:.5em}code a:any-link{color:inherit;text-decoration-color:#6c757d}/*! light */div.observablehq table thead tr th{background-color:var(--bs-body-bg)}input,button,select,optgroup,textarea{background-color:var(--bs-body-bg)}.code-annotated .code-copy-button{margin-right:1.25em;margin-top:0;padding-bottom:0;padding-top:3px}.code-annotation-gutter-bg{background-color:#fff}.code-annotation-gutter{background-color:rgba(233,236,239,.65)}.code-annotation-gutter,.code-annotation-gutter-bg{height:100%;width:calc(20px + .5em);position:absolute;top:0;right:0}dl.code-annotation-container-grid dt{margin-right:1em;margin-top:.25rem}dl.code-annotation-container-grid dt{font-family:"JetBrains Mono";color:#383f45;border:solid #383f45 1px;border-radius:50%;height:22px;width:22px;line-height:22px;font-size:11px;text-align:center;vertical-align:middle;text-decoration:none}dl.code-annotation-container-grid dt[data-target-cell]{cursor:pointer}dl.code-annotation-container-grid dt[data-target-cell].code-annotation-active{color:#fff;border:solid #aaa 1px;background-color:#aaa}pre.code-annotation-code{padding-top:0;padding-bottom:0}pre.code-annotation-code code{z-index:3}#code-annotation-line-highlight-gutter{width:100%;border-top:solid rgba(170,170,170,.2666666667) 1px;border-bottom:solid rgba(170,170,170,.2666666667) 1px;z-index:2;background-color:rgba(170,170,170,.1333333333)}#code-annotation-line-highlight{margin-left:-4em;width:calc(100% + 4em);border-top:solid rgba(170,170,170,.2666666667) 1px;border-bottom:solid rgba(170,170,170,.2666666667) 1px;z-index:2;background-color:rgba(170,170,170,.1333333333)}code.sourceCode .code-annotation-anchor.code-annotation-active{background-color:var(--quarto-hl-normal-color, #aaaaaa);border:solid var(--quarto-hl-normal-color, #aaaaaa) 1px;color:#e9ecef;font-weight:bolder}code.sourceCode .code-annotation-anchor{font-family:"JetBrains Mono";color:var(--quarto-hl-co-color);border:solid var(--quarto-hl-co-color) 1px;border-radius:50%;height:18px;width:18px;font-size:9px;margin-top:2px}code.sourceCode button.code-annotation-anchor{padding:2px;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none}code.sourceCode a.code-annotation-anchor{line-height:18px;text-align:center;vertical-align:middle;cursor:default;text-decoration:none}@media print{.page-columns .column-screen-inset{grid-column:page-start-inset/page-end-inset;z-index:998;opacity:.999}.page-columns .column-screen-inset table{background:#fff}.page-columns .column-screen-inset-left{grid-column:page-start-inset/body-content-end;z-index:998;opacity:.999}.page-columns .column-screen-inset-left table{background:#fff}.page-columns .column-screen-inset-right{grid-column:body-content-start/page-end-inset;z-index:998;opacity:.999}.page-columns .column-screen-inset-right table{background:#fff}.page-columns .column-screen{grid-column:page-start/page-end;z-index:998;opacity:.999}.page-columns .column-screen table{background:#fff}.page-columns .column-screen-left{grid-column:page-start/body-content-end;z-index:998;opacity:.999}.page-columns .column-screen-left table{background:#fff}.page-columns .column-screen-right{grid-column:body-content-start/page-end;z-index:998;opacity:.999}.page-columns .column-screen-right table{background:#fff}.page-columns .column-screen-inset-shaded{grid-column:page-start-inset/page-end-inset;padding:1em;background:#f8f9fa;z-index:998;opacity:.999;margin-bottom:1em}}.quarto-video{margin-bottom:1em}.table{border-top:1px solid #d3d8dc;border-bottom:1px solid #d3d8dc}.table>thead{border-top-width:0;border-bottom:1px solid #9ba5ae}.table a{word-break:break-word}.table>:not(caption)>*>*{background-color:unset;color:unset}#quarto-document-content .crosstalk-input .checkbox input[type=checkbox],#quarto-document-content .crosstalk-input .checkbox-inline input[type=checkbox]{position:unset;margin-top:unset;margin-left:unset}#quarto-document-content .row{margin-left:unset;margin-right:unset}.quarto-xref{white-space:nowrap}#quarto-draft-alert{margin-top:0px;margin-bottom:0px;padding:.3em;text-align:center;font-size:.9em}#quarto-draft-alert i{margin-right:.3em}a.external:after{content:"";background-image:url('data:image/svg+xml,');background-size:contain;background-repeat:no-repeat;background-position:center center;margin-left:.2em;padding-right:.75em}div.sourceCode code a.external:after{content:none}a.external:after:hover{cursor:pointer}.quarto-ext-icon{display:inline-block;font-size:.75em;padding-left:.3em}.code-with-filename .code-with-filename-file{margin-bottom:0;padding-bottom:2px;padding-top:2px;padding-left:.7em;border:var(--quarto-border-width) solid var(--quarto-border-color);border-radius:var(--quarto-border-radius);border-bottom:0;border-bottom-left-radius:0%;border-bottom-right-radius:0%}.code-with-filename div.sourceCode,.reveal .code-with-filename div.sourceCode{margin-top:0;border-top-left-radius:0%;border-top-right-radius:0%}.code-with-filename .code-with-filename-file pre{margin-bottom:0}.code-with-filename .code-with-filename-file{background-color:rgba(219,219,219,.8)}.quarto-dark .code-with-filename .code-with-filename-file{background-color:#555}.code-with-filename .code-with-filename-file strong{font-weight:400}.quarto-title-banner{margin-bottom:1em;color:#595959;background:#fff}.quarto-title-banner a{color:#595959}.quarto-title-banner h1,.quarto-title-banner .h1,.quarto-title-banner h2,.quarto-title-banner .h2{color:#595959}.quarto-title-banner .code-tools-button{color:#8c8c8c}.quarto-title-banner .code-tools-button:hover{color:#595959}.quarto-title-banner .code-tools-button>.bi::before{background-image:url('data:image/svg+xml,')}.quarto-title-banner .code-tools-button:hover>.bi::before{background-image:url('data:image/svg+xml,')}.quarto-title-banner .quarto-title .title{font-weight:600}.quarto-title-banner .quarto-categories{margin-top:.75em}@media(min-width: 992px){.quarto-title-banner{padding-top:2.5em;padding-bottom:2.5em}}@media(max-width: 991.98px){.quarto-title-banner{padding-top:1em;padding-bottom:1em}}@media(max-width: 767.98px){body.hypothesis-enabled #title-block-header>*{padding-right:20px}}main.quarto-banner-title-block>section:first-child>h2,main.quarto-banner-title-block>section:first-child>.h2,main.quarto-banner-title-block>section:first-child>h3,main.quarto-banner-title-block>section:first-child>.h3,main.quarto-banner-title-block>section:first-child>h4,main.quarto-banner-title-block>section:first-child>.h4{margin-top:0}.quarto-title .quarto-categories{display:flex;flex-wrap:wrap;row-gap:.5em;column-gap:.4em;padding-bottom:.5em;margin-top:.75em}.quarto-title .quarto-categories .quarto-category{padding:.25em .75em;font-size:.65em;text-transform:uppercase;border:solid 1px;border-radius:.25rem;opacity:.6}.quarto-title .quarto-categories .quarto-category a{color:inherit}.quarto-title-meta-container{display:grid;grid-template-columns:1fr auto}.quarto-title-meta-column-end{display:flex;flex-direction:column;padding-left:1em}.quarto-title-meta-column-end a .bi{margin-right:.3em}#title-block-header.quarto-title-block.default .quarto-title-meta{display:grid;grid-template-columns:repeat(2, 1fr);grid-column-gap:1em}#title-block-header.quarto-title-block.default .quarto-title .title{margin-bottom:0}#title-block-header.quarto-title-block.default .quarto-title-author-orcid img{margin-top:-0.2em;height:.8em;width:.8em}#title-block-header.quarto-title-block.default .quarto-title-author-email{opacity:.7}#title-block-header.quarto-title-block.default .quarto-description p:last-of-type{margin-bottom:0}#title-block-header.quarto-title-block.default .quarto-title-meta-contents p,#title-block-header.quarto-title-block.default .quarto-title-authors p,#title-block-header.quarto-title-block.default .quarto-title-affiliations p{margin-bottom:.1em}#title-block-header.quarto-title-block.default .quarto-title-meta-heading{text-transform:uppercase;margin-top:1em;font-size:.8em;opacity:.8;font-weight:400}#title-block-header.quarto-title-block.default .quarto-title-meta-contents{font-size:.9em}#title-block-header.quarto-title-block.default .quarto-title-meta-contents p.affiliation:last-of-type{margin-bottom:.1em}#title-block-header.quarto-title-block.default p.affiliation{margin-bottom:.1em}#title-block-header.quarto-title-block.default .keywords,#title-block-header.quarto-title-block.default .description,#title-block-header.quarto-title-block.default .abstract{margin-top:0}#title-block-header.quarto-title-block.default .keywords>p,#title-block-header.quarto-title-block.default .description>p,#title-block-header.quarto-title-block.default .abstract>p{font-size:.9em}#title-block-header.quarto-title-block.default .keywords>p:last-of-type,#title-block-header.quarto-title-block.default .description>p:last-of-type,#title-block-header.quarto-title-block.default .abstract>p:last-of-type{margin-bottom:0}#title-block-header.quarto-title-block.default .keywords .block-title,#title-block-header.quarto-title-block.default .description .block-title,#title-block-header.quarto-title-block.default .abstract .block-title{margin-top:1em;text-transform:uppercase;font-size:.8em;opacity:.8;font-weight:400}#title-block-header.quarto-title-block.default .quarto-title-meta-author{display:grid;grid-template-columns:minmax(max-content, 1fr) 1fr;grid-column-gap:1em}.quarto-title-tools-only{display:flex;justify-content:right}.grid{display:inline-grid;column-gap:10px;row-gap:10px;margin-bottom:30px}.grid-two{grid-template-columns:repeat(1, 1fr)}@media only screen and (min-width: 768px){.grid-two{grid-template-columns:repeat(2, 1fr)}}.grid-three{grid-template-columns:repeat(2, 1fr)}@media only screen and (min-width: 768px){.grid-three{grid-template-columns:repeat(3, 1fr)}}.grid__item{vertical-align:top;max-width:420px;text-align:left;padding:10px;position:relative}.grid__item:hover{background-color:#f8f9fa}.grid__title{margin-top:0;align-items:center;border-bottom:1px solid rgba(0,0,0,.2);font-size:1.5rem;display:inline-block;width:100%;padding-bottom:.5rem;color:#03638e}.grid__title-icon{color:#000}.grid__link-box{position:absolute;width:100%;height:100%;top:0;left:0;z-index:1}.grid__list{margin-top:10px}.grid__item li:not(:last-child){margin-bottom:0}.grid__title-link{color:#03638e;border-bottom:0px;text-decoration:none}.grid__status{font-size:.75rem;margin-left:10px}.grid__status--stable{color:#b4cfb0}.grid__status--experimental{color:#fbc6a4}.grid__status--planned{color:#ff856a}.grid__item-footer{position:absolute;bottom:0}.grid__icon-footer{color:#000;border-bottom:0px;text-decoration:none;font-size:1.5rem;margin-left:10px}.grid__icon-footer:hover{color:#03638e}.grid__link-footer{border-bottom:0px;text-decoration:none}.grid__text--footer{margin-bottom:2em}.grid__item-footer{position:absolute;bottom:0}.feature-grid{display:inline-grid;grid-template-columns:repeat(2, 1fr)}@media only screen and (min-width: 768px){.feature-grid{grid-template-columns:repeat(3, 1fr)}}.feature-grid__item{text-align:center;padding:30px}.feature-grid__icon{padding-bottom:15px}.feature-grid__link{border-bottom:0px;text-decoration:none}.feature-grid__i{font-size:3rem;color:#000}.feature-grid__i:hover{color:#03638e}.team-grid{display:inline-grid;grid-template-columns:repeat(1, 1fr);column-gap:10px;row-gap:10px;margin-bottom:30px;width:100%}@media only screen and (min-width: 768px){.team-grid{grid-template-columns:repeat(2, 1fr)}}.team-grid__item{border-top:#03638e solid 5px;box-shadow:2px 2px rgba(0,0,0,.0666666667);border-radius:0px 0px 10px 0px;vertical-align:top;max-width:420px;text-align:left;position:relative}.team-grid__item:hover{background-color:rgba(0,0,0,.2)}.team-grid__image-container{position:relative}.team-grid__image-container::after{content:"";display:block;padding-bottom:100%}.team-grid__image{position:absolute;width:100%;height:100%;object-fit:cover}.team-grid__text{padding:10px}.team-grid__name{margin-top:0;display:flex;align-items:center}.team-grid__link{border-bottom:0px;text-decoration:none}.gallery{display:inline-grid;grid-template-columns:100px auto;margin-bottom:3rem}.gallery__icon-column{text-align:center}.gallery__icon{font-size:3rem}.gallery__link{padding-top:1em;padding-left:1em;padding-bottom:3em;font-size:large}.rt-th{border-bottom:1px solid rgba(0,0,0,.2) !important}.object-table__list{display:inline-block;padding:0;margin:0}.object-table__list-item{list-style-type:none}footer.footer .nav-footer,#quarto-header nav{border-bottom:1px solid rgba(0,0,0,.2) !important}.aa-Autocomplete .aa-Form,.aa-DetachedFormContainer .aa-Form{border-radius:6px !important}p code:not(.sourceCode),li code:not(.sourceCode),kbd,pre:not(.sourceCode),samp{background-color:#f6f6f6 !important;padding:.25em;border-radius:6px !important}div.sourceCode{background-color:#f6f6f6 !important;border-radius:6px}.grid .g-col-md-5{border-radius:6px !important}div.csl-entry{clear:both;margin-bottom:10px}.bi-twitter{color:#1da1f2 !important}.bi-arrow-up-circle{padding-left:2px}.bi-heart-fill{color:darkred}i.status-stable{color:#b4cfb0}i.status-experimental{color:#fbc6a4}i.status-planned{color:#ff856a !important}.navbar-collapse .quarto-color-scheme-toggle{margin-top:-6px}.listing-date{width:100px}.page-item.active .page-link{background-color:#184fa9;border-color:#184fa9}.banner__image{width:100%;margin-top:10px}.banner__caption{font-size:.9rem}.quarto-title-banner{padding-bottom:0 !important} diff --git a/site_libs/bootstrap/bootstrap.min.js b/site_libs/bootstrap/bootstrap.min.js new file mode 100644 index 00000000..e8f21f70 --- /dev/null +++ b/site_libs/bootstrap/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v5.3.1 (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap=e()}(this,(function(){"use strict";const t=new Map,e={set(e,i,n){t.has(e)||t.set(e,new Map);const s=t.get(e);s.has(i)||0===s.size?s.set(i,n):console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(s.keys())[0]}.`)},get:(e,i)=>t.has(e)&&t.get(e).get(i)||null,remove(e,i){if(!t.has(e))return;const n=t.get(e);n.delete(i),0===n.size&&t.delete(e)}},i="transitionend",n=t=>(t&&window.CSS&&window.CSS.escape&&(t=t.replace(/#([^\s"#']+)/g,((t,e)=>`#${CSS.escape(e)}`))),t),s=t=>{t.dispatchEvent(new Event(i))},o=t=>!(!t||"object"!=typeof t)&&(void 0!==t.jquery&&(t=t[0]),void 0!==t.nodeType),r=t=>o(t)?t.jquery?t[0]:t:"string"==typeof t&&t.length>0?document.querySelector(n(t)):null,a=t=>{if(!o(t)||0===t.getClientRects().length)return!1;const e="visible"===getComputedStyle(t).getPropertyValue("visibility"),i=t.closest("details:not([open])");if(!i)return e;if(i!==t){const e=t.closest("summary");if(e&&e.parentNode!==i)return!1;if(null===e)return!1}return e},l=t=>!t||t.nodeType!==Node.ELEMENT_NODE||!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")),c=t=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){const e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?c(t.parentNode):null},h=()=>{},d=t=>{t.offsetHeight},u=()=>window.jQuery&&!document.body.hasAttribute("data-bs-no-jquery")?window.jQuery:null,f=[],p=()=>"rtl"===document.documentElement.dir,m=t=>{var e;e=()=>{const e=u();if(e){const i=t.NAME,n=e.fn[i];e.fn[i]=t.jQueryInterface,e.fn[i].Constructor=t,e.fn[i].noConflict=()=>(e.fn[i]=n,t.jQueryInterface)}},"loading"===document.readyState?(f.length||document.addEventListener("DOMContentLoaded",(()=>{for(const t of f)t()})),f.push(e)):e()},g=(t,e=[],i=t)=>"function"==typeof t?t(...e):i,_=(t,e,n=!0)=>{if(!n)return void g(t);const o=(t=>{if(!t)return 0;let{transitionDuration:e,transitionDelay:i}=window.getComputedStyle(t);const n=Number.parseFloat(e),s=Number.parseFloat(i);return n||s?(e=e.split(",")[0],i=i.split(",")[0],1e3*(Number.parseFloat(e)+Number.parseFloat(i))):0})(e)+5;let r=!1;const a=({target:n})=>{n===e&&(r=!0,e.removeEventListener(i,a),g(t))};e.addEventListener(i,a),setTimeout((()=>{r||s(e)}),o)},b=(t,e,i,n)=>{const s=t.length;let o=t.indexOf(e);return-1===o?!i&&n?t[s-1]:t[0]:(o+=i?1:-1,n&&(o=(o+s)%s),t[Math.max(0,Math.min(o,s-1))])},v=/[^.]*(?=\..*)\.|.*/,y=/\..*/,w=/::\d+$/,A={};let E=1;const T={mouseenter:"mouseover",mouseleave:"mouseout"},C=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function O(t,e){return e&&`${e}::${E++}`||t.uidEvent||E++}function x(t){const e=O(t);return t.uidEvent=e,A[e]=A[e]||{},A[e]}function k(t,e,i=null){return Object.values(t).find((t=>t.callable===e&&t.delegationSelector===i))}function L(t,e,i){const n="string"==typeof e,s=n?i:e||i;let o=I(t);return C.has(o)||(o=t),[n,s,o]}function S(t,e,i,n,s){if("string"!=typeof e||!t)return;let[o,r,a]=L(e,i,n);if(e in T){const t=t=>function(e){if(!e.relatedTarget||e.relatedTarget!==e.delegateTarget&&!e.delegateTarget.contains(e.relatedTarget))return t.call(this,e)};r=t(r)}const l=x(t),c=l[a]||(l[a]={}),h=k(c,r,o?i:null);if(h)return void(h.oneOff=h.oneOff&&s);const d=O(r,e.replace(v,"")),u=o?function(t,e,i){return function n(s){const o=t.querySelectorAll(e);for(let{target:r}=s;r&&r!==this;r=r.parentNode)for(const a of o)if(a===r)return P(s,{delegateTarget:r}),n.oneOff&&N.off(t,s.type,e,i),i.apply(r,[s])}}(t,i,r):function(t,e){return function i(n){return P(n,{delegateTarget:t}),i.oneOff&&N.off(t,n.type,e),e.apply(t,[n])}}(t,r);u.delegationSelector=o?i:null,u.callable=r,u.oneOff=s,u.uidEvent=d,c[d]=u,t.addEventListener(a,u,o)}function D(t,e,i,n,s){const o=k(e[i],n,s);o&&(t.removeEventListener(i,o,Boolean(s)),delete e[i][o.uidEvent])}function $(t,e,i,n){const s=e[i]||{};for(const[o,r]of Object.entries(s))o.includes(n)&&D(t,e,i,r.callable,r.delegationSelector)}function I(t){return t=t.replace(y,""),T[t]||t}const N={on(t,e,i,n){S(t,e,i,n,!1)},one(t,e,i,n){S(t,e,i,n,!0)},off(t,e,i,n){if("string"!=typeof e||!t)return;const[s,o,r]=L(e,i,n),a=r!==e,l=x(t),c=l[r]||{},h=e.startsWith(".");if(void 0===o){if(h)for(const i of Object.keys(l))$(t,l,i,e.slice(1));for(const[i,n]of Object.entries(c)){const s=i.replace(w,"");a&&!e.includes(s)||D(t,l,r,n.callable,n.delegationSelector)}}else{if(!Object.keys(c).length)return;D(t,l,r,o,s?i:null)}},trigger(t,e,i){if("string"!=typeof e||!t)return null;const n=u();let s=null,o=!0,r=!0,a=!1;e!==I(e)&&n&&(s=n.Event(e,i),n(t).trigger(s),o=!s.isPropagationStopped(),r=!s.isImmediatePropagationStopped(),a=s.isDefaultPrevented());const l=P(new Event(e,{bubbles:o,cancelable:!0}),i);return a&&l.preventDefault(),r&&t.dispatchEvent(l),l.defaultPrevented&&s&&s.preventDefault(),l}};function P(t,e={}){for(const[i,n]of Object.entries(e))try{t[i]=n}catch(e){Object.defineProperty(t,i,{configurable:!0,get:()=>n})}return t}function M(t){if("true"===t)return!0;if("false"===t)return!1;if(t===Number(t).toString())return Number(t);if(""===t||"null"===t)return null;if("string"!=typeof t)return t;try{return JSON.parse(decodeURIComponent(t))}catch(e){return t}}function j(t){return t.replace(/[A-Z]/g,(t=>`-${t.toLowerCase()}`))}const F={setDataAttribute(t,e,i){t.setAttribute(`data-bs-${j(e)}`,i)},removeDataAttribute(t,e){t.removeAttribute(`data-bs-${j(e)}`)},getDataAttributes(t){if(!t)return{};const e={},i=Object.keys(t.dataset).filter((t=>t.startsWith("bs")&&!t.startsWith("bsConfig")));for(const n of i){let i=n.replace(/^bs/,"");i=i.charAt(0).toLowerCase()+i.slice(1,i.length),e[i]=M(t.dataset[n])}return e},getDataAttribute:(t,e)=>M(t.getAttribute(`data-bs-${j(e)}`))};class H{static get Default(){return{}}static get DefaultType(){return{}}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}_getConfig(t){return t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t}_mergeConfigObj(t,e){const i=o(e)?F.getDataAttribute(e,"config"):{};return{...this.constructor.Default,..."object"==typeof i?i:{},...o(e)?F.getDataAttributes(e):{},..."object"==typeof t?t:{}}}_typeCheckConfig(t,e=this.constructor.DefaultType){for(const[n,s]of Object.entries(e)){const e=t[n],r=o(e)?"element":null==(i=e)?`${i}`:Object.prototype.toString.call(i).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(s).test(r))throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${n}" provided type "${r}" but expected type "${s}".`)}var i}}class W extends H{constructor(t,i){super(),(t=r(t))&&(this._element=t,this._config=this._getConfig(i),e.set(this._element,this.constructor.DATA_KEY,this))}dispose(){e.remove(this._element,this.constructor.DATA_KEY),N.off(this._element,this.constructor.EVENT_KEY);for(const t of Object.getOwnPropertyNames(this))this[t]=null}_queueCallback(t,e,i=!0){_(t,e,i)}_getConfig(t){return t=this._mergeConfigObj(t,this._element),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}static getInstance(t){return e.get(r(t),this.DATA_KEY)}static getOrCreateInstance(t,e={}){return this.getInstance(t)||new this(t,"object"==typeof e?e:null)}static get VERSION(){return"5.3.1"}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}static eventName(t){return`${t}${this.EVENT_KEY}`}}const B=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let i=t.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i=`#${i.split("#")[1]}`),e=i&&"#"!==i?i.trim():null}return n(e)},z={find:(t,e=document.documentElement)=>[].concat(...Element.prototype.querySelectorAll.call(e,t)),findOne:(t,e=document.documentElement)=>Element.prototype.querySelector.call(e,t),children:(t,e)=>[].concat(...t.children).filter((t=>t.matches(e))),parents(t,e){const i=[];let n=t.parentNode.closest(e);for(;n;)i.push(n),n=n.parentNode.closest(e);return i},prev(t,e){let i=t.previousElementSibling;for(;i;){if(i.matches(e))return[i];i=i.previousElementSibling}return[]},next(t,e){let i=t.nextElementSibling;for(;i;){if(i.matches(e))return[i];i=i.nextElementSibling}return[]},focusableChildren(t){const e=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map((t=>`${t}:not([tabindex^="-"])`)).join(",");return this.find(e,t).filter((t=>!l(t)&&a(t)))},getSelectorFromElement(t){const e=B(t);return e&&z.findOne(e)?e:null},getElementFromSelector(t){const e=B(t);return e?z.findOne(e):null},getMultipleElementsFromSelector(t){const e=B(t);return e?z.find(e):[]}},R=(t,e="hide")=>{const i=`click.dismiss${t.EVENT_KEY}`,n=t.NAME;N.on(document,i,`[data-bs-dismiss="${n}"]`,(function(i){if(["A","AREA"].includes(this.tagName)&&i.preventDefault(),l(this))return;const s=z.getElementFromSelector(this)||this.closest(`.${n}`);t.getOrCreateInstance(s)[e]()}))},q=".bs.alert",V=`close${q}`,K=`closed${q}`;class Q extends W{static get NAME(){return"alert"}close(){if(N.trigger(this._element,V).defaultPrevented)return;this._element.classList.remove("show");const t=this._element.classList.contains("fade");this._queueCallback((()=>this._destroyElement()),this._element,t)}_destroyElement(){this._element.remove(),N.trigger(this._element,K),this.dispose()}static jQueryInterface(t){return this.each((function(){const e=Q.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}R(Q,"close"),m(Q);const X='[data-bs-toggle="button"]';class Y extends W{static get NAME(){return"button"}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle("active"))}static jQueryInterface(t){return this.each((function(){const e=Y.getOrCreateInstance(this);"toggle"===t&&e[t]()}))}}N.on(document,"click.bs.button.data-api",X,(t=>{t.preventDefault();const e=t.target.closest(X);Y.getOrCreateInstance(e).toggle()})),m(Y);const U=".bs.swipe",G=`touchstart${U}`,J=`touchmove${U}`,Z=`touchend${U}`,tt=`pointerdown${U}`,et=`pointerup${U}`,it={endCallback:null,leftCallback:null,rightCallback:null},nt={endCallback:"(function|null)",leftCallback:"(function|null)",rightCallback:"(function|null)"};class st extends H{constructor(t,e){super(),this._element=t,t&&st.isSupported()&&(this._config=this._getConfig(e),this._deltaX=0,this._supportPointerEvents=Boolean(window.PointerEvent),this._initEvents())}static get Default(){return it}static get DefaultType(){return nt}static get NAME(){return"swipe"}dispose(){N.off(this._element,U)}_start(t){this._supportPointerEvents?this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX):this._deltaX=t.touches[0].clientX}_end(t){this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX-this._deltaX),this._handleSwipe(),g(this._config.endCallback)}_move(t){this._deltaX=t.touches&&t.touches.length>1?0:t.touches[0].clientX-this._deltaX}_handleSwipe(){const t=Math.abs(this._deltaX);if(t<=40)return;const e=t/this._deltaX;this._deltaX=0,e&&g(e>0?this._config.rightCallback:this._config.leftCallback)}_initEvents(){this._supportPointerEvents?(N.on(this._element,tt,(t=>this._start(t))),N.on(this._element,et,(t=>this._end(t))),this._element.classList.add("pointer-event")):(N.on(this._element,G,(t=>this._start(t))),N.on(this._element,J,(t=>this._move(t))),N.on(this._element,Z,(t=>this._end(t))))}_eventIsPointerPenTouch(t){return this._supportPointerEvents&&("pen"===t.pointerType||"touch"===t.pointerType)}static isSupported(){return"ontouchstart"in document.documentElement||navigator.maxTouchPoints>0}}const ot=".bs.carousel",rt=".data-api",at="next",lt="prev",ct="left",ht="right",dt=`slide${ot}`,ut=`slid${ot}`,ft=`keydown${ot}`,pt=`mouseenter${ot}`,mt=`mouseleave${ot}`,gt=`dragstart${ot}`,_t=`load${ot}${rt}`,bt=`click${ot}${rt}`,vt="carousel",yt="active",wt=".active",At=".carousel-item",Et=wt+At,Tt={ArrowLeft:ht,ArrowRight:ct},Ct={interval:5e3,keyboard:!0,pause:"hover",ride:!1,touch:!0,wrap:!0},Ot={interval:"(number|boolean)",keyboard:"boolean",pause:"(string|boolean)",ride:"(boolean|string)",touch:"boolean",wrap:"boolean"};class xt extends W{constructor(t,e){super(t,e),this._interval=null,this._activeElement=null,this._isSliding=!1,this.touchTimeout=null,this._swipeHelper=null,this._indicatorsElement=z.findOne(".carousel-indicators",this._element),this._addEventListeners(),this._config.ride===vt&&this.cycle()}static get Default(){return Ct}static get DefaultType(){return Ot}static get NAME(){return"carousel"}next(){this._slide(at)}nextWhenVisible(){!document.hidden&&a(this._element)&&this.next()}prev(){this._slide(lt)}pause(){this._isSliding&&s(this._element),this._clearInterval()}cycle(){this._clearInterval(),this._updateInterval(),this._interval=setInterval((()=>this.nextWhenVisible()),this._config.interval)}_maybeEnableCycle(){this._config.ride&&(this._isSliding?N.one(this._element,ut,(()=>this.cycle())):this.cycle())}to(t){const e=this._getItems();if(t>e.length-1||t<0)return;if(this._isSliding)return void N.one(this._element,ut,(()=>this.to(t)));const i=this._getItemIndex(this._getActive());if(i===t)return;const n=t>i?at:lt;this._slide(n,e[t])}dispose(){this._swipeHelper&&this._swipeHelper.dispose(),super.dispose()}_configAfterMerge(t){return t.defaultInterval=t.interval,t}_addEventListeners(){this._config.keyboard&&N.on(this._element,ft,(t=>this._keydown(t))),"hover"===this._config.pause&&(N.on(this._element,pt,(()=>this.pause())),N.on(this._element,mt,(()=>this._maybeEnableCycle()))),this._config.touch&&st.isSupported()&&this._addTouchEventListeners()}_addTouchEventListeners(){for(const t of z.find(".carousel-item img",this._element))N.on(t,gt,(t=>t.preventDefault()));const t={leftCallback:()=>this._slide(this._directionToOrder(ct)),rightCallback:()=>this._slide(this._directionToOrder(ht)),endCallback:()=>{"hover"===this._config.pause&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout((()=>this._maybeEnableCycle()),500+this._config.interval))}};this._swipeHelper=new st(this._element,t)}_keydown(t){if(/input|textarea/i.test(t.target.tagName))return;const e=Tt[t.key];e&&(t.preventDefault(),this._slide(this._directionToOrder(e)))}_getItemIndex(t){return this._getItems().indexOf(t)}_setActiveIndicatorElement(t){if(!this._indicatorsElement)return;const e=z.findOne(wt,this._indicatorsElement);e.classList.remove(yt),e.removeAttribute("aria-current");const i=z.findOne(`[data-bs-slide-to="${t}"]`,this._indicatorsElement);i&&(i.classList.add(yt),i.setAttribute("aria-current","true"))}_updateInterval(){const t=this._activeElement||this._getActive();if(!t)return;const e=Number.parseInt(t.getAttribute("data-bs-interval"),10);this._config.interval=e||this._config.defaultInterval}_slide(t,e=null){if(this._isSliding)return;const i=this._getActive(),n=t===at,s=e||b(this._getItems(),i,n,this._config.wrap);if(s===i)return;const o=this._getItemIndex(s),r=e=>N.trigger(this._element,e,{relatedTarget:s,direction:this._orderToDirection(t),from:this._getItemIndex(i),to:o});if(r(dt).defaultPrevented)return;if(!i||!s)return;const a=Boolean(this._interval);this.pause(),this._isSliding=!0,this._setActiveIndicatorElement(o),this._activeElement=s;const l=n?"carousel-item-start":"carousel-item-end",c=n?"carousel-item-next":"carousel-item-prev";s.classList.add(c),d(s),i.classList.add(l),s.classList.add(l),this._queueCallback((()=>{s.classList.remove(l,c),s.classList.add(yt),i.classList.remove(yt,c,l),this._isSliding=!1,r(ut)}),i,this._isAnimated()),a&&this.cycle()}_isAnimated(){return this._element.classList.contains("slide")}_getActive(){return z.findOne(Et,this._element)}_getItems(){return z.find(At,this._element)}_clearInterval(){this._interval&&(clearInterval(this._interval),this._interval=null)}_directionToOrder(t){return p()?t===ct?lt:at:t===ct?at:lt}_orderToDirection(t){return p()?t===lt?ct:ht:t===lt?ht:ct}static jQueryInterface(t){return this.each((function(){const e=xt.getOrCreateInstance(this,t);if("number"!=typeof t){if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}else e.to(t)}))}}N.on(document,bt,"[data-bs-slide], [data-bs-slide-to]",(function(t){const e=z.getElementFromSelector(this);if(!e||!e.classList.contains(vt))return;t.preventDefault();const i=xt.getOrCreateInstance(e),n=this.getAttribute("data-bs-slide-to");return n?(i.to(n),void i._maybeEnableCycle()):"next"===F.getDataAttribute(this,"slide")?(i.next(),void i._maybeEnableCycle()):(i.prev(),void i._maybeEnableCycle())})),N.on(window,_t,(()=>{const t=z.find('[data-bs-ride="carousel"]');for(const e of t)xt.getOrCreateInstance(e)})),m(xt);const kt=".bs.collapse",Lt=`show${kt}`,St=`shown${kt}`,Dt=`hide${kt}`,$t=`hidden${kt}`,It=`click${kt}.data-api`,Nt="show",Pt="collapse",Mt="collapsing",jt=`:scope .${Pt} .${Pt}`,Ft='[data-bs-toggle="collapse"]',Ht={parent:null,toggle:!0},Wt={parent:"(null|element)",toggle:"boolean"};class Bt extends W{constructor(t,e){super(t,e),this._isTransitioning=!1,this._triggerArray=[];const i=z.find(Ft);for(const t of i){const e=z.getSelectorFromElement(t),i=z.find(e).filter((t=>t===this._element));null!==e&&i.length&&this._triggerArray.push(t)}this._initializeChildren(),this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown()),this._config.toggle&&this.toggle()}static get Default(){return Ht}static get DefaultType(){return Wt}static get NAME(){return"collapse"}toggle(){this._isShown()?this.hide():this.show()}show(){if(this._isTransitioning||this._isShown())return;let t=[];if(this._config.parent&&(t=this._getFirstLevelChildren(".collapse.show, .collapse.collapsing").filter((t=>t!==this._element)).map((t=>Bt.getOrCreateInstance(t,{toggle:!1})))),t.length&&t[0]._isTransitioning)return;if(N.trigger(this._element,Lt).defaultPrevented)return;for(const e of t)e.hide();const e=this._getDimension();this._element.classList.remove(Pt),this._element.classList.add(Mt),this._element.style[e]=0,this._addAriaAndCollapsedClass(this._triggerArray,!0),this._isTransitioning=!0;const i=`scroll${e[0].toUpperCase()+e.slice(1)}`;this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(Mt),this._element.classList.add(Pt,Nt),this._element.style[e]="",N.trigger(this._element,St)}),this._element,!0),this._element.style[e]=`${this._element[i]}px`}hide(){if(this._isTransitioning||!this._isShown())return;if(N.trigger(this._element,Dt).defaultPrevented)return;const t=this._getDimension();this._element.style[t]=`${this._element.getBoundingClientRect()[t]}px`,d(this._element),this._element.classList.add(Mt),this._element.classList.remove(Pt,Nt);for(const t of this._triggerArray){const e=z.getElementFromSelector(t);e&&!this._isShown(e)&&this._addAriaAndCollapsedClass([t],!1)}this._isTransitioning=!0,this._element.style[t]="",this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(Mt),this._element.classList.add(Pt),N.trigger(this._element,$t)}),this._element,!0)}_isShown(t=this._element){return t.classList.contains(Nt)}_configAfterMerge(t){return t.toggle=Boolean(t.toggle),t.parent=r(t.parent),t}_getDimension(){return this._element.classList.contains("collapse-horizontal")?"width":"height"}_initializeChildren(){if(!this._config.parent)return;const t=this._getFirstLevelChildren(Ft);for(const e of t){const t=z.getElementFromSelector(e);t&&this._addAriaAndCollapsedClass([e],this._isShown(t))}}_getFirstLevelChildren(t){const e=z.find(jt,this._config.parent);return z.find(t,this._config.parent).filter((t=>!e.includes(t)))}_addAriaAndCollapsedClass(t,e){if(t.length)for(const i of t)i.classList.toggle("collapsed",!e),i.setAttribute("aria-expanded",e)}static jQueryInterface(t){const e={};return"string"==typeof t&&/show|hide/.test(t)&&(e.toggle=!1),this.each((function(){const i=Bt.getOrCreateInstance(this,e);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t]()}}))}}N.on(document,It,Ft,(function(t){("A"===t.target.tagName||t.delegateTarget&&"A"===t.delegateTarget.tagName)&&t.preventDefault();for(const t of z.getMultipleElementsFromSelector(this))Bt.getOrCreateInstance(t,{toggle:!1}).toggle()})),m(Bt);var zt="top",Rt="bottom",qt="right",Vt="left",Kt="auto",Qt=[zt,Rt,qt,Vt],Xt="start",Yt="end",Ut="clippingParents",Gt="viewport",Jt="popper",Zt="reference",te=Qt.reduce((function(t,e){return t.concat([e+"-"+Xt,e+"-"+Yt])}),[]),ee=[].concat(Qt,[Kt]).reduce((function(t,e){return t.concat([e,e+"-"+Xt,e+"-"+Yt])}),[]),ie="beforeRead",ne="read",se="afterRead",oe="beforeMain",re="main",ae="afterMain",le="beforeWrite",ce="write",he="afterWrite",de=[ie,ne,se,oe,re,ae,le,ce,he];function ue(t){return t?(t.nodeName||"").toLowerCase():null}function fe(t){if(null==t)return window;if("[object Window]"!==t.toString()){var e=t.ownerDocument;return e&&e.defaultView||window}return t}function pe(t){return t instanceof fe(t).Element||t instanceof Element}function me(t){return t instanceof fe(t).HTMLElement||t instanceof HTMLElement}function ge(t){return"undefined"!=typeof ShadowRoot&&(t instanceof fe(t).ShadowRoot||t instanceof ShadowRoot)}const _e={name:"applyStyles",enabled:!0,phase:"write",fn:function(t){var e=t.state;Object.keys(e.elements).forEach((function(t){var i=e.styles[t]||{},n=e.attributes[t]||{},s=e.elements[t];me(s)&&ue(s)&&(Object.assign(s.style,i),Object.keys(n).forEach((function(t){var e=n[t];!1===e?s.removeAttribute(t):s.setAttribute(t,!0===e?"":e)})))}))},effect:function(t){var e=t.state,i={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(e.elements.popper.style,i.popper),e.styles=i,e.elements.arrow&&Object.assign(e.elements.arrow.style,i.arrow),function(){Object.keys(e.elements).forEach((function(t){var n=e.elements[t],s=e.attributes[t]||{},o=Object.keys(e.styles.hasOwnProperty(t)?e.styles[t]:i[t]).reduce((function(t,e){return t[e]="",t}),{});me(n)&&ue(n)&&(Object.assign(n.style,o),Object.keys(s).forEach((function(t){n.removeAttribute(t)})))}))}},requires:["computeStyles"]};function be(t){return t.split("-")[0]}var ve=Math.max,ye=Math.min,we=Math.round;function Ae(){var t=navigator.userAgentData;return null!=t&&t.brands&&Array.isArray(t.brands)?t.brands.map((function(t){return t.brand+"/"+t.version})).join(" "):navigator.userAgent}function Ee(){return!/^((?!chrome|android).)*safari/i.test(Ae())}function Te(t,e,i){void 0===e&&(e=!1),void 0===i&&(i=!1);var n=t.getBoundingClientRect(),s=1,o=1;e&&me(t)&&(s=t.offsetWidth>0&&we(n.width)/t.offsetWidth||1,o=t.offsetHeight>0&&we(n.height)/t.offsetHeight||1);var r=(pe(t)?fe(t):window).visualViewport,a=!Ee()&&i,l=(n.left+(a&&r?r.offsetLeft:0))/s,c=(n.top+(a&&r?r.offsetTop:0))/o,h=n.width/s,d=n.height/o;return{width:h,height:d,top:c,right:l+h,bottom:c+d,left:l,x:l,y:c}}function Ce(t){var e=Te(t),i=t.offsetWidth,n=t.offsetHeight;return Math.abs(e.width-i)<=1&&(i=e.width),Math.abs(e.height-n)<=1&&(n=e.height),{x:t.offsetLeft,y:t.offsetTop,width:i,height:n}}function Oe(t,e){var i=e.getRootNode&&e.getRootNode();if(t.contains(e))return!0;if(i&&ge(i)){var n=e;do{if(n&&t.isSameNode(n))return!0;n=n.parentNode||n.host}while(n)}return!1}function xe(t){return fe(t).getComputedStyle(t)}function ke(t){return["table","td","th"].indexOf(ue(t))>=0}function Le(t){return((pe(t)?t.ownerDocument:t.document)||window.document).documentElement}function Se(t){return"html"===ue(t)?t:t.assignedSlot||t.parentNode||(ge(t)?t.host:null)||Le(t)}function De(t){return me(t)&&"fixed"!==xe(t).position?t.offsetParent:null}function $e(t){for(var e=fe(t),i=De(t);i&&ke(i)&&"static"===xe(i).position;)i=De(i);return i&&("html"===ue(i)||"body"===ue(i)&&"static"===xe(i).position)?e:i||function(t){var e=/firefox/i.test(Ae());if(/Trident/i.test(Ae())&&me(t)&&"fixed"===xe(t).position)return null;var i=Se(t);for(ge(i)&&(i=i.host);me(i)&&["html","body"].indexOf(ue(i))<0;){var n=xe(i);if("none"!==n.transform||"none"!==n.perspective||"paint"===n.contain||-1!==["transform","perspective"].indexOf(n.willChange)||e&&"filter"===n.willChange||e&&n.filter&&"none"!==n.filter)return i;i=i.parentNode}return null}(t)||e}function Ie(t){return["top","bottom"].indexOf(t)>=0?"x":"y"}function Ne(t,e,i){return ve(t,ye(e,i))}function Pe(t){return Object.assign({},{top:0,right:0,bottom:0,left:0},t)}function Me(t,e){return e.reduce((function(e,i){return e[i]=t,e}),{})}const je={name:"arrow",enabled:!0,phase:"main",fn:function(t){var e,i=t.state,n=t.name,s=t.options,o=i.elements.arrow,r=i.modifiersData.popperOffsets,a=be(i.placement),l=Ie(a),c=[Vt,qt].indexOf(a)>=0?"height":"width";if(o&&r){var h=function(t,e){return Pe("number"!=typeof(t="function"==typeof t?t(Object.assign({},e.rects,{placement:e.placement})):t)?t:Me(t,Qt))}(s.padding,i),d=Ce(o),u="y"===l?zt:Vt,f="y"===l?Rt:qt,p=i.rects.reference[c]+i.rects.reference[l]-r[l]-i.rects.popper[c],m=r[l]-i.rects.reference[l],g=$e(o),_=g?"y"===l?g.clientHeight||0:g.clientWidth||0:0,b=p/2-m/2,v=h[u],y=_-d[c]-h[f],w=_/2-d[c]/2+b,A=Ne(v,w,y),E=l;i.modifiersData[n]=((e={})[E]=A,e.centerOffset=A-w,e)}},effect:function(t){var e=t.state,i=t.options.element,n=void 0===i?"[data-popper-arrow]":i;null!=n&&("string"!=typeof n||(n=e.elements.popper.querySelector(n)))&&Oe(e.elements.popper,n)&&(e.elements.arrow=n)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function Fe(t){return t.split("-")[1]}var He={top:"auto",right:"auto",bottom:"auto",left:"auto"};function We(t){var e,i=t.popper,n=t.popperRect,s=t.placement,o=t.variation,r=t.offsets,a=t.position,l=t.gpuAcceleration,c=t.adaptive,h=t.roundOffsets,d=t.isFixed,u=r.x,f=void 0===u?0:u,p=r.y,m=void 0===p?0:p,g="function"==typeof h?h({x:f,y:m}):{x:f,y:m};f=g.x,m=g.y;var _=r.hasOwnProperty("x"),b=r.hasOwnProperty("y"),v=Vt,y=zt,w=window;if(c){var A=$e(i),E="clientHeight",T="clientWidth";A===fe(i)&&"static"!==xe(A=Le(i)).position&&"absolute"===a&&(E="scrollHeight",T="scrollWidth"),(s===zt||(s===Vt||s===qt)&&o===Yt)&&(y=Rt,m-=(d&&A===w&&w.visualViewport?w.visualViewport.height:A[E])-n.height,m*=l?1:-1),s!==Vt&&(s!==zt&&s!==Rt||o!==Yt)||(v=qt,f-=(d&&A===w&&w.visualViewport?w.visualViewport.width:A[T])-n.width,f*=l?1:-1)}var C,O=Object.assign({position:a},c&&He),x=!0===h?function(t,e){var i=t.x,n=t.y,s=e.devicePixelRatio||1;return{x:we(i*s)/s||0,y:we(n*s)/s||0}}({x:f,y:m},fe(i)):{x:f,y:m};return f=x.x,m=x.y,l?Object.assign({},O,((C={})[y]=b?"0":"",C[v]=_?"0":"",C.transform=(w.devicePixelRatio||1)<=1?"translate("+f+"px, "+m+"px)":"translate3d("+f+"px, "+m+"px, 0)",C)):Object.assign({},O,((e={})[y]=b?m+"px":"",e[v]=_?f+"px":"",e.transform="",e))}const Be={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(t){var e=t.state,i=t.options,n=i.gpuAcceleration,s=void 0===n||n,o=i.adaptive,r=void 0===o||o,a=i.roundOffsets,l=void 0===a||a,c={placement:be(e.placement),variation:Fe(e.placement),popper:e.elements.popper,popperRect:e.rects.popper,gpuAcceleration:s,isFixed:"fixed"===e.options.strategy};null!=e.modifiersData.popperOffsets&&(e.styles.popper=Object.assign({},e.styles.popper,We(Object.assign({},c,{offsets:e.modifiersData.popperOffsets,position:e.options.strategy,adaptive:r,roundOffsets:l})))),null!=e.modifiersData.arrow&&(e.styles.arrow=Object.assign({},e.styles.arrow,We(Object.assign({},c,{offsets:e.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-placement":e.placement})},data:{}};var ze={passive:!0};const Re={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(t){var e=t.state,i=t.instance,n=t.options,s=n.scroll,o=void 0===s||s,r=n.resize,a=void 0===r||r,l=fe(e.elements.popper),c=[].concat(e.scrollParents.reference,e.scrollParents.popper);return o&&c.forEach((function(t){t.addEventListener("scroll",i.update,ze)})),a&&l.addEventListener("resize",i.update,ze),function(){o&&c.forEach((function(t){t.removeEventListener("scroll",i.update,ze)})),a&&l.removeEventListener("resize",i.update,ze)}},data:{}};var qe={left:"right",right:"left",bottom:"top",top:"bottom"};function Ve(t){return t.replace(/left|right|bottom|top/g,(function(t){return qe[t]}))}var Ke={start:"end",end:"start"};function Qe(t){return t.replace(/start|end/g,(function(t){return Ke[t]}))}function Xe(t){var e=fe(t);return{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function Ye(t){return Te(Le(t)).left+Xe(t).scrollLeft}function Ue(t){var e=xe(t),i=e.overflow,n=e.overflowX,s=e.overflowY;return/auto|scroll|overlay|hidden/.test(i+s+n)}function Ge(t){return["html","body","#document"].indexOf(ue(t))>=0?t.ownerDocument.body:me(t)&&Ue(t)?t:Ge(Se(t))}function Je(t,e){var i;void 0===e&&(e=[]);var n=Ge(t),s=n===(null==(i=t.ownerDocument)?void 0:i.body),o=fe(n),r=s?[o].concat(o.visualViewport||[],Ue(n)?n:[]):n,a=e.concat(r);return s?a:a.concat(Je(Se(r)))}function Ze(t){return Object.assign({},t,{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height})}function ti(t,e,i){return e===Gt?Ze(function(t,e){var i=fe(t),n=Le(t),s=i.visualViewport,o=n.clientWidth,r=n.clientHeight,a=0,l=0;if(s){o=s.width,r=s.height;var c=Ee();(c||!c&&"fixed"===e)&&(a=s.offsetLeft,l=s.offsetTop)}return{width:o,height:r,x:a+Ye(t),y:l}}(t,i)):pe(e)?function(t,e){var i=Te(t,!1,"fixed"===e);return i.top=i.top+t.clientTop,i.left=i.left+t.clientLeft,i.bottom=i.top+t.clientHeight,i.right=i.left+t.clientWidth,i.width=t.clientWidth,i.height=t.clientHeight,i.x=i.left,i.y=i.top,i}(e,i):Ze(function(t){var e,i=Le(t),n=Xe(t),s=null==(e=t.ownerDocument)?void 0:e.body,o=ve(i.scrollWidth,i.clientWidth,s?s.scrollWidth:0,s?s.clientWidth:0),r=ve(i.scrollHeight,i.clientHeight,s?s.scrollHeight:0,s?s.clientHeight:0),a=-n.scrollLeft+Ye(t),l=-n.scrollTop;return"rtl"===xe(s||i).direction&&(a+=ve(i.clientWidth,s?s.clientWidth:0)-o),{width:o,height:r,x:a,y:l}}(Le(t)))}function ei(t){var e,i=t.reference,n=t.element,s=t.placement,o=s?be(s):null,r=s?Fe(s):null,a=i.x+i.width/2-n.width/2,l=i.y+i.height/2-n.height/2;switch(o){case zt:e={x:a,y:i.y-n.height};break;case Rt:e={x:a,y:i.y+i.height};break;case qt:e={x:i.x+i.width,y:l};break;case Vt:e={x:i.x-n.width,y:l};break;default:e={x:i.x,y:i.y}}var c=o?Ie(o):null;if(null!=c){var h="y"===c?"height":"width";switch(r){case Xt:e[c]=e[c]-(i[h]/2-n[h]/2);break;case Yt:e[c]=e[c]+(i[h]/2-n[h]/2)}}return e}function ii(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=void 0===n?t.placement:n,o=i.strategy,r=void 0===o?t.strategy:o,a=i.boundary,l=void 0===a?Ut:a,c=i.rootBoundary,h=void 0===c?Gt:c,d=i.elementContext,u=void 0===d?Jt:d,f=i.altBoundary,p=void 0!==f&&f,m=i.padding,g=void 0===m?0:m,_=Pe("number"!=typeof g?g:Me(g,Qt)),b=u===Jt?Zt:Jt,v=t.rects.popper,y=t.elements[p?b:u],w=function(t,e,i,n){var s="clippingParents"===e?function(t){var e=Je(Se(t)),i=["absolute","fixed"].indexOf(xe(t).position)>=0&&me(t)?$e(t):t;return pe(i)?e.filter((function(t){return pe(t)&&Oe(t,i)&&"body"!==ue(t)})):[]}(t):[].concat(e),o=[].concat(s,[i]),r=o[0],a=o.reduce((function(e,i){var s=ti(t,i,n);return e.top=ve(s.top,e.top),e.right=ye(s.right,e.right),e.bottom=ye(s.bottom,e.bottom),e.left=ve(s.left,e.left),e}),ti(t,r,n));return a.width=a.right-a.left,a.height=a.bottom-a.top,a.x=a.left,a.y=a.top,a}(pe(y)?y:y.contextElement||Le(t.elements.popper),l,h,r),A=Te(t.elements.reference),E=ei({reference:A,element:v,strategy:"absolute",placement:s}),T=Ze(Object.assign({},v,E)),C=u===Jt?T:A,O={top:w.top-C.top+_.top,bottom:C.bottom-w.bottom+_.bottom,left:w.left-C.left+_.left,right:C.right-w.right+_.right},x=t.modifiersData.offset;if(u===Jt&&x){var k=x[s];Object.keys(O).forEach((function(t){var e=[qt,Rt].indexOf(t)>=0?1:-1,i=[zt,Rt].indexOf(t)>=0?"y":"x";O[t]+=k[i]*e}))}return O}function ni(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=i.boundary,o=i.rootBoundary,r=i.padding,a=i.flipVariations,l=i.allowedAutoPlacements,c=void 0===l?ee:l,h=Fe(n),d=h?a?te:te.filter((function(t){return Fe(t)===h})):Qt,u=d.filter((function(t){return c.indexOf(t)>=0}));0===u.length&&(u=d);var f=u.reduce((function(e,i){return e[i]=ii(t,{placement:i,boundary:s,rootBoundary:o,padding:r})[be(i)],e}),{});return Object.keys(f).sort((function(t,e){return f[t]-f[e]}))}const si={name:"flip",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name;if(!e.modifiersData[n]._skip){for(var s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0===r||r,l=i.fallbackPlacements,c=i.padding,h=i.boundary,d=i.rootBoundary,u=i.altBoundary,f=i.flipVariations,p=void 0===f||f,m=i.allowedAutoPlacements,g=e.options.placement,_=be(g),b=l||(_!==g&&p?function(t){if(be(t)===Kt)return[];var e=Ve(t);return[Qe(t),e,Qe(e)]}(g):[Ve(g)]),v=[g].concat(b).reduce((function(t,i){return t.concat(be(i)===Kt?ni(e,{placement:i,boundary:h,rootBoundary:d,padding:c,flipVariations:p,allowedAutoPlacements:m}):i)}),[]),y=e.rects.reference,w=e.rects.popper,A=new Map,E=!0,T=v[0],C=0;C=0,S=L?"width":"height",D=ii(e,{placement:O,boundary:h,rootBoundary:d,altBoundary:u,padding:c}),$=L?k?qt:Vt:k?Rt:zt;y[S]>w[S]&&($=Ve($));var I=Ve($),N=[];if(o&&N.push(D[x]<=0),a&&N.push(D[$]<=0,D[I]<=0),N.every((function(t){return t}))){T=O,E=!1;break}A.set(O,N)}if(E)for(var P=function(t){var e=v.find((function(e){var i=A.get(e);if(i)return i.slice(0,t).every((function(t){return t}))}));if(e)return T=e,"break"},M=p?3:1;M>0&&"break"!==P(M);M--);e.placement!==T&&(e.modifiersData[n]._skip=!0,e.placement=T,e.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function oi(t,e,i){return void 0===i&&(i={x:0,y:0}),{top:t.top-e.height-i.y,right:t.right-e.width+i.x,bottom:t.bottom-e.height+i.y,left:t.left-e.width-i.x}}function ri(t){return[zt,qt,Rt,Vt].some((function(e){return t[e]>=0}))}const ai={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(t){var e=t.state,i=t.name,n=e.rects.reference,s=e.rects.popper,o=e.modifiersData.preventOverflow,r=ii(e,{elementContext:"reference"}),a=ii(e,{altBoundary:!0}),l=oi(r,n),c=oi(a,s,o),h=ri(l),d=ri(c);e.modifiersData[i]={referenceClippingOffsets:l,popperEscapeOffsets:c,isReferenceHidden:h,hasPopperEscaped:d},e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-reference-hidden":h,"data-popper-escaped":d})}},li={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.offset,o=void 0===s?[0,0]:s,r=ee.reduce((function(t,i){return t[i]=function(t,e,i){var n=be(t),s=[Vt,zt].indexOf(n)>=0?-1:1,o="function"==typeof i?i(Object.assign({},e,{placement:t})):i,r=o[0],a=o[1];return r=r||0,a=(a||0)*s,[Vt,qt].indexOf(n)>=0?{x:a,y:r}:{x:r,y:a}}(i,e.rects,o),t}),{}),a=r[e.placement],l=a.x,c=a.y;null!=e.modifiersData.popperOffsets&&(e.modifiersData.popperOffsets.x+=l,e.modifiersData.popperOffsets.y+=c),e.modifiersData[n]=r}},ci={name:"popperOffsets",enabled:!0,phase:"read",fn:function(t){var e=t.state,i=t.name;e.modifiersData[i]=ei({reference:e.rects.reference,element:e.rects.popper,strategy:"absolute",placement:e.placement})},data:{}},hi={name:"preventOverflow",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0!==r&&r,l=i.boundary,c=i.rootBoundary,h=i.altBoundary,d=i.padding,u=i.tether,f=void 0===u||u,p=i.tetherOffset,m=void 0===p?0:p,g=ii(e,{boundary:l,rootBoundary:c,padding:d,altBoundary:h}),_=be(e.placement),b=Fe(e.placement),v=!b,y=Ie(_),w="x"===y?"y":"x",A=e.modifiersData.popperOffsets,E=e.rects.reference,T=e.rects.popper,C="function"==typeof m?m(Object.assign({},e.rects,{placement:e.placement})):m,O="number"==typeof C?{mainAxis:C,altAxis:C}:Object.assign({mainAxis:0,altAxis:0},C),x=e.modifiersData.offset?e.modifiersData.offset[e.placement]:null,k={x:0,y:0};if(A){if(o){var L,S="y"===y?zt:Vt,D="y"===y?Rt:qt,$="y"===y?"height":"width",I=A[y],N=I+g[S],P=I-g[D],M=f?-T[$]/2:0,j=b===Xt?E[$]:T[$],F=b===Xt?-T[$]:-E[$],H=e.elements.arrow,W=f&&H?Ce(H):{width:0,height:0},B=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},z=B[S],R=B[D],q=Ne(0,E[$],W[$]),V=v?E[$]/2-M-q-z-O.mainAxis:j-q-z-O.mainAxis,K=v?-E[$]/2+M+q+R+O.mainAxis:F+q+R+O.mainAxis,Q=e.elements.arrow&&$e(e.elements.arrow),X=Q?"y"===y?Q.clientTop||0:Q.clientLeft||0:0,Y=null!=(L=null==x?void 0:x[y])?L:0,U=I+K-Y,G=Ne(f?ye(N,I+V-Y-X):N,I,f?ve(P,U):P);A[y]=G,k[y]=G-I}if(a){var J,Z="x"===y?zt:Vt,tt="x"===y?Rt:qt,et=A[w],it="y"===w?"height":"width",nt=et+g[Z],st=et-g[tt],ot=-1!==[zt,Vt].indexOf(_),rt=null!=(J=null==x?void 0:x[w])?J:0,at=ot?nt:et-E[it]-T[it]-rt+O.altAxis,lt=ot?et+E[it]+T[it]-rt-O.altAxis:st,ct=f&&ot?function(t,e,i){var n=Ne(t,e,i);return n>i?i:n}(at,et,lt):Ne(f?at:nt,et,f?lt:st);A[w]=ct,k[w]=ct-et}e.modifiersData[n]=k}},requiresIfExists:["offset"]};function di(t,e,i){void 0===i&&(i=!1);var n,s,o=me(e),r=me(e)&&function(t){var e=t.getBoundingClientRect(),i=we(e.width)/t.offsetWidth||1,n=we(e.height)/t.offsetHeight||1;return 1!==i||1!==n}(e),a=Le(e),l=Te(t,r,i),c={scrollLeft:0,scrollTop:0},h={x:0,y:0};return(o||!o&&!i)&&(("body"!==ue(e)||Ue(a))&&(c=(n=e)!==fe(n)&&me(n)?{scrollLeft:(s=n).scrollLeft,scrollTop:s.scrollTop}:Xe(n)),me(e)?((h=Te(e,!0)).x+=e.clientLeft,h.y+=e.clientTop):a&&(h.x=Ye(a))),{x:l.left+c.scrollLeft-h.x,y:l.top+c.scrollTop-h.y,width:l.width,height:l.height}}function ui(t){var e=new Map,i=new Set,n=[];function s(t){i.add(t.name),[].concat(t.requires||[],t.requiresIfExists||[]).forEach((function(t){if(!i.has(t)){var n=e.get(t);n&&s(n)}})),n.push(t)}return t.forEach((function(t){e.set(t.name,t)})),t.forEach((function(t){i.has(t.name)||s(t)})),n}var fi={placement:"bottom",modifiers:[],strategy:"absolute"};function pi(){for(var t=arguments.length,e=new Array(t),i=0;iNumber.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_getPopperConfig(){const t={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return(this._inNavbar||"static"===this._config.display)&&(F.setDataAttribute(this._menu,"popper","static"),t.modifiers=[{name:"applyStyles",enabled:!1}]),{...t,...g(this._config.popperConfig,[t])}}_selectMenuItem({key:t,target:e}){const i=z.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",this._menu).filter((t=>a(t)));i.length&&b(i,e,t===Ti,!i.includes(e)).focus()}static jQueryInterface(t){return this.each((function(){const e=qi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}static clearMenus(t){if(2===t.button||"keyup"===t.type&&"Tab"!==t.key)return;const e=z.find(Ni);for(const i of e){const e=qi.getInstance(i);if(!e||!1===e._config.autoClose)continue;const n=t.composedPath(),s=n.includes(e._menu);if(n.includes(e._element)||"inside"===e._config.autoClose&&!s||"outside"===e._config.autoClose&&s)continue;if(e._menu.contains(t.target)&&("keyup"===t.type&&"Tab"===t.key||/input|select|option|textarea|form/i.test(t.target.tagName)))continue;const o={relatedTarget:e._element};"click"===t.type&&(o.clickEvent=t),e._completeHide(o)}}static dataApiKeydownHandler(t){const e=/input|textarea/i.test(t.target.tagName),i="Escape"===t.key,n=[Ei,Ti].includes(t.key);if(!n&&!i)return;if(e&&!i)return;t.preventDefault();const s=this.matches(Ii)?this:z.prev(this,Ii)[0]||z.next(this,Ii)[0]||z.findOne(Ii,t.delegateTarget.parentNode),o=qi.getOrCreateInstance(s);if(n)return t.stopPropagation(),o.show(),void o._selectMenuItem(t);o._isShown()&&(t.stopPropagation(),o.hide(),s.focus())}}N.on(document,Si,Ii,qi.dataApiKeydownHandler),N.on(document,Si,Pi,qi.dataApiKeydownHandler),N.on(document,Li,qi.clearMenus),N.on(document,Di,qi.clearMenus),N.on(document,Li,Ii,(function(t){t.preventDefault(),qi.getOrCreateInstance(this).toggle()})),m(qi);const Vi="backdrop",Ki="show",Qi=`mousedown.bs.${Vi}`,Xi={className:"modal-backdrop",clickCallback:null,isAnimated:!1,isVisible:!0,rootElement:"body"},Yi={className:"string",clickCallback:"(function|null)",isAnimated:"boolean",isVisible:"boolean",rootElement:"(element|string)"};class Ui extends H{constructor(t){super(),this._config=this._getConfig(t),this._isAppended=!1,this._element=null}static get Default(){return Xi}static get DefaultType(){return Yi}static get NAME(){return Vi}show(t){if(!this._config.isVisible)return void g(t);this._append();const e=this._getElement();this._config.isAnimated&&d(e),e.classList.add(Ki),this._emulateAnimation((()=>{g(t)}))}hide(t){this._config.isVisible?(this._getElement().classList.remove(Ki),this._emulateAnimation((()=>{this.dispose(),g(t)}))):g(t)}dispose(){this._isAppended&&(N.off(this._element,Qi),this._element.remove(),this._isAppended=!1)}_getElement(){if(!this._element){const t=document.createElement("div");t.className=this._config.className,this._config.isAnimated&&t.classList.add("fade"),this._element=t}return this._element}_configAfterMerge(t){return t.rootElement=r(t.rootElement),t}_append(){if(this._isAppended)return;const t=this._getElement();this._config.rootElement.append(t),N.on(t,Qi,(()=>{g(this._config.clickCallback)})),this._isAppended=!0}_emulateAnimation(t){_(t,this._getElement(),this._config.isAnimated)}}const Gi=".bs.focustrap",Ji=`focusin${Gi}`,Zi=`keydown.tab${Gi}`,tn="backward",en={autofocus:!0,trapElement:null},nn={autofocus:"boolean",trapElement:"element"};class sn extends H{constructor(t){super(),this._config=this._getConfig(t),this._isActive=!1,this._lastTabNavDirection=null}static get Default(){return en}static get DefaultType(){return nn}static get NAME(){return"focustrap"}activate(){this._isActive||(this._config.autofocus&&this._config.trapElement.focus(),N.off(document,Gi),N.on(document,Ji,(t=>this._handleFocusin(t))),N.on(document,Zi,(t=>this._handleKeydown(t))),this._isActive=!0)}deactivate(){this._isActive&&(this._isActive=!1,N.off(document,Gi))}_handleFocusin(t){const{trapElement:e}=this._config;if(t.target===document||t.target===e||e.contains(t.target))return;const i=z.focusableChildren(e);0===i.length?e.focus():this._lastTabNavDirection===tn?i[i.length-1].focus():i[0].focus()}_handleKeydown(t){"Tab"===t.key&&(this._lastTabNavDirection=t.shiftKey?tn:"forward")}}const on=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",rn=".sticky-top",an="padding-right",ln="margin-right";class cn{constructor(){this._element=document.body}getWidth(){const t=document.documentElement.clientWidth;return Math.abs(window.innerWidth-t)}hide(){const t=this.getWidth();this._disableOverFlow(),this._setElementAttributes(this._element,an,(e=>e+t)),this._setElementAttributes(on,an,(e=>e+t)),this._setElementAttributes(rn,ln,(e=>e-t))}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,an),this._resetElementAttributes(on,an),this._resetElementAttributes(rn,ln)}isOverflowing(){return this.getWidth()>0}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(t,e,i){const n=this.getWidth();this._applyManipulationCallback(t,(t=>{if(t!==this._element&&window.innerWidth>t.clientWidth+n)return;this._saveInitialAttribute(t,e);const s=window.getComputedStyle(t).getPropertyValue(e);t.style.setProperty(e,`${i(Number.parseFloat(s))}px`)}))}_saveInitialAttribute(t,e){const i=t.style.getPropertyValue(e);i&&F.setDataAttribute(t,e,i)}_resetElementAttributes(t,e){this._applyManipulationCallback(t,(t=>{const i=F.getDataAttribute(t,e);null!==i?(F.removeDataAttribute(t,e),t.style.setProperty(e,i)):t.style.removeProperty(e)}))}_applyManipulationCallback(t,e){if(o(t))e(t);else for(const i of z.find(t,this._element))e(i)}}const hn=".bs.modal",dn=`hide${hn}`,un=`hidePrevented${hn}`,fn=`hidden${hn}`,pn=`show${hn}`,mn=`shown${hn}`,gn=`resize${hn}`,_n=`click.dismiss${hn}`,bn=`mousedown.dismiss${hn}`,vn=`keydown.dismiss${hn}`,yn=`click${hn}.data-api`,wn="modal-open",An="show",En="modal-static",Tn={backdrop:!0,focus:!0,keyboard:!0},Cn={backdrop:"(boolean|string)",focus:"boolean",keyboard:"boolean"};class On extends W{constructor(t,e){super(t,e),this._dialog=z.findOne(".modal-dialog",this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._isTransitioning=!1,this._scrollBar=new cn,this._addEventListeners()}static get Default(){return Tn}static get DefaultType(){return Cn}static get NAME(){return"modal"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||this._isTransitioning||N.trigger(this._element,pn,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._isTransitioning=!0,this._scrollBar.hide(),document.body.classList.add(wn),this._adjustDialog(),this._backdrop.show((()=>this._showElement(t))))}hide(){this._isShown&&!this._isTransitioning&&(N.trigger(this._element,dn).defaultPrevented||(this._isShown=!1,this._isTransitioning=!0,this._focustrap.deactivate(),this._element.classList.remove(An),this._queueCallback((()=>this._hideModal()),this._element,this._isAnimated())))}dispose(){N.off(window,hn),N.off(this._dialog,hn),this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new Ui({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new sn({trapElement:this._element})}_showElement(t){document.body.contains(this._element)||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0;const e=z.findOne(".modal-body",this._dialog);e&&(e.scrollTop=0),d(this._element),this._element.classList.add(An),this._queueCallback((()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,N.trigger(this._element,mn,{relatedTarget:t})}),this._dialog,this._isAnimated())}_addEventListeners(){N.on(this._element,vn,(t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():this._triggerBackdropTransition())})),N.on(window,gn,(()=>{this._isShown&&!this._isTransitioning&&this._adjustDialog()})),N.on(this._element,bn,(t=>{N.one(this._element,_n,(e=>{this._element===t.target&&this._element===e.target&&("static"!==this._config.backdrop?this._config.backdrop&&this.hide():this._triggerBackdropTransition())}))}))}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide((()=>{document.body.classList.remove(wn),this._resetAdjustments(),this._scrollBar.reset(),N.trigger(this._element,fn)}))}_isAnimated(){return this._element.classList.contains("fade")}_triggerBackdropTransition(){if(N.trigger(this._element,un).defaultPrevented)return;const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._element.style.overflowY;"hidden"===e||this._element.classList.contains(En)||(t||(this._element.style.overflowY="hidden"),this._element.classList.add(En),this._queueCallback((()=>{this._element.classList.remove(En),this._queueCallback((()=>{this._element.style.overflowY=e}),this._dialog)}),this._dialog),this._element.focus())}_adjustDialog(){const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._scrollBar.getWidth(),i=e>0;if(i&&!t){const t=p()?"paddingLeft":"paddingRight";this._element.style[t]=`${e}px`}if(!i&&t){const t=p()?"paddingRight":"paddingLeft";this._element.style[t]=`${e}px`}}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(t,e){return this.each((function(){const i=On.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t](e)}}))}}N.on(document,yn,'[data-bs-toggle="modal"]',(function(t){const e=z.getElementFromSelector(this);["A","AREA"].includes(this.tagName)&&t.preventDefault(),N.one(e,pn,(t=>{t.defaultPrevented||N.one(e,fn,(()=>{a(this)&&this.focus()}))}));const i=z.findOne(".modal.show");i&&On.getInstance(i).hide(),On.getOrCreateInstance(e).toggle(this)})),R(On),m(On);const xn=".bs.offcanvas",kn=".data-api",Ln=`load${xn}${kn}`,Sn="show",Dn="showing",$n="hiding",In=".offcanvas.show",Nn=`show${xn}`,Pn=`shown${xn}`,Mn=`hide${xn}`,jn=`hidePrevented${xn}`,Fn=`hidden${xn}`,Hn=`resize${xn}`,Wn=`click${xn}${kn}`,Bn=`keydown.dismiss${xn}`,zn={backdrop:!0,keyboard:!0,scroll:!1},Rn={backdrop:"(boolean|string)",keyboard:"boolean",scroll:"boolean"};class qn extends W{constructor(t,e){super(t,e),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._addEventListeners()}static get Default(){return zn}static get DefaultType(){return Rn}static get NAME(){return"offcanvas"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||N.trigger(this._element,Nn,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._backdrop.show(),this._config.scroll||(new cn).hide(),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add(Dn),this._queueCallback((()=>{this._config.scroll&&!this._config.backdrop||this._focustrap.activate(),this._element.classList.add(Sn),this._element.classList.remove(Dn),N.trigger(this._element,Pn,{relatedTarget:t})}),this._element,!0))}hide(){this._isShown&&(N.trigger(this._element,Mn).defaultPrevented||(this._focustrap.deactivate(),this._element.blur(),this._isShown=!1,this._element.classList.add($n),this._backdrop.hide(),this._queueCallback((()=>{this._element.classList.remove(Sn,$n),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._config.scroll||(new cn).reset(),N.trigger(this._element,Fn)}),this._element,!0)))}dispose(){this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}_initializeBackDrop(){const t=Boolean(this._config.backdrop);return new Ui({className:"offcanvas-backdrop",isVisible:t,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:t?()=>{"static"!==this._config.backdrop?this.hide():N.trigger(this._element,jn)}:null})}_initializeFocusTrap(){return new sn({trapElement:this._element})}_addEventListeners(){N.on(this._element,Bn,(t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():N.trigger(this._element,jn))}))}static jQueryInterface(t){return this.each((function(){const e=qn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}N.on(document,Wn,'[data-bs-toggle="offcanvas"]',(function(t){const e=z.getElementFromSelector(this);if(["A","AREA"].includes(this.tagName)&&t.preventDefault(),l(this))return;N.one(e,Fn,(()=>{a(this)&&this.focus()}));const i=z.findOne(In);i&&i!==e&&qn.getInstance(i).hide(),qn.getOrCreateInstance(e).toggle(this)})),N.on(window,Ln,(()=>{for(const t of z.find(In))qn.getOrCreateInstance(t).show()})),N.on(window,Hn,(()=>{for(const t of z.find("[aria-modal][class*=show][class*=offcanvas-]"))"fixed"!==getComputedStyle(t).position&&qn.getOrCreateInstance(t).hide()})),R(qn),m(qn);const Vn={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},Kn=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),Qn=/^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i,Xn=(t,e)=>{const i=t.nodeName.toLowerCase();return e.includes(i)?!Kn.has(i)||Boolean(Qn.test(t.nodeValue)):e.filter((t=>t instanceof RegExp)).some((t=>t.test(i)))},Yn={allowList:Vn,content:{},extraClass:"",html:!1,sanitize:!0,sanitizeFn:null,template:"
"},Un={allowList:"object",content:"object",extraClass:"(string|function)",html:"boolean",sanitize:"boolean",sanitizeFn:"(null|function)",template:"string"},Gn={entry:"(string|element|function|null)",selector:"(string|element)"};class Jn extends H{constructor(t){super(),this._config=this._getConfig(t)}static get Default(){return Yn}static get DefaultType(){return Un}static get NAME(){return"TemplateFactory"}getContent(){return Object.values(this._config.content).map((t=>this._resolvePossibleFunction(t))).filter(Boolean)}hasContent(){return this.getContent().length>0}changeContent(t){return this._checkContent(t),this._config.content={...this._config.content,...t},this}toHtml(){const t=document.createElement("div");t.innerHTML=this._maybeSanitize(this._config.template);for(const[e,i]of Object.entries(this._config.content))this._setContent(t,i,e);const e=t.children[0],i=this._resolvePossibleFunction(this._config.extraClass);return i&&e.classList.add(...i.split(" ")),e}_typeCheckConfig(t){super._typeCheckConfig(t),this._checkContent(t.content)}_checkContent(t){for(const[e,i]of Object.entries(t))super._typeCheckConfig({selector:e,entry:i},Gn)}_setContent(t,e,i){const n=z.findOne(i,t);n&&((e=this._resolvePossibleFunction(e))?o(e)?this._putElementInTemplate(r(e),n):this._config.html?n.innerHTML=this._maybeSanitize(e):n.textContent=e:n.remove())}_maybeSanitize(t){return this._config.sanitize?function(t,e,i){if(!t.length)return t;if(i&&"function"==typeof i)return i(t);const n=(new window.DOMParser).parseFromString(t,"text/html"),s=[].concat(...n.body.querySelectorAll("*"));for(const t of s){const i=t.nodeName.toLowerCase();if(!Object.keys(e).includes(i)){t.remove();continue}const n=[].concat(...t.attributes),s=[].concat(e["*"]||[],e[i]||[]);for(const e of n)Xn(e,s)||t.removeAttribute(e.nodeName)}return n.body.innerHTML}(t,this._config.allowList,this._config.sanitizeFn):t}_resolvePossibleFunction(t){return g(t,[this])}_putElementInTemplate(t,e){if(this._config.html)return e.innerHTML="",void e.append(t);e.textContent=t.textContent}}const Zn=new Set(["sanitize","allowList","sanitizeFn"]),ts="fade",es="show",is=".modal",ns="hide.bs.modal",ss="hover",os="focus",rs={AUTO:"auto",TOP:"top",RIGHT:p()?"left":"right",BOTTOM:"bottom",LEFT:p()?"right":"left"},as={allowList:Vn,animation:!0,boundary:"clippingParents",container:!1,customClass:"",delay:0,fallbackPlacements:["top","right","bottom","left"],html:!1,offset:[0,6],placement:"top",popperConfig:null,sanitize:!0,sanitizeFn:null,selector:!1,template:'',title:"",trigger:"hover focus"},ls={allowList:"object",animation:"boolean",boundary:"(string|element)",container:"(string|element|boolean)",customClass:"(string|function)",delay:"(number|object)",fallbackPlacements:"array",html:"boolean",offset:"(array|string|function)",placement:"(string|function)",popperConfig:"(null|object|function)",sanitize:"boolean",sanitizeFn:"(null|function)",selector:"(string|boolean)",template:"string",title:"(string|element|function)",trigger:"string"};class cs extends W{constructor(t,e){if(void 0===vi)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");super(t,e),this._isEnabled=!0,this._timeout=0,this._isHovered=null,this._activeTrigger={},this._popper=null,this._templateFactory=null,this._newContent=null,this.tip=null,this._setListeners(),this._config.selector||this._fixTitle()}static get Default(){return as}static get DefaultType(){return ls}static get NAME(){return"tooltip"}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(){this._isEnabled&&(this._activeTrigger.click=!this._activeTrigger.click,this._isShown()?this._leave():this._enter())}dispose(){clearTimeout(this._timeout),N.off(this._element.closest(is),ns,this._hideModalHandler),this._element.getAttribute("data-bs-original-title")&&this._element.setAttribute("title",this._element.getAttribute("data-bs-original-title")),this._disposePopper(),super.dispose()}show(){if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(!this._isWithContent()||!this._isEnabled)return;const t=N.trigger(this._element,this.constructor.eventName("show")),e=(c(this._element)||this._element.ownerDocument.documentElement).contains(this._element);if(t.defaultPrevented||!e)return;this._disposePopper();const i=this._getTipElement();this._element.setAttribute("aria-describedby",i.getAttribute("id"));const{container:n}=this._config;if(this._element.ownerDocument.documentElement.contains(this.tip)||(n.append(i),N.trigger(this._element,this.constructor.eventName("inserted"))),this._popper=this._createPopper(i),i.classList.add(es),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))N.on(t,"mouseover",h);this._queueCallback((()=>{N.trigger(this._element,this.constructor.eventName("shown")),!1===this._isHovered&&this._leave(),this._isHovered=!1}),this.tip,this._isAnimated())}hide(){if(this._isShown()&&!N.trigger(this._element,this.constructor.eventName("hide")).defaultPrevented){if(this._getTipElement().classList.remove(es),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))N.off(t,"mouseover",h);this._activeTrigger.click=!1,this._activeTrigger[os]=!1,this._activeTrigger[ss]=!1,this._isHovered=null,this._queueCallback((()=>{this._isWithActiveTrigger()||(this._isHovered||this._disposePopper(),this._element.removeAttribute("aria-describedby"),N.trigger(this._element,this.constructor.eventName("hidden")))}),this.tip,this._isAnimated())}}update(){this._popper&&this._popper.update()}_isWithContent(){return Boolean(this._getTitle())}_getTipElement(){return this.tip||(this.tip=this._createTipElement(this._newContent||this._getContentForTemplate())),this.tip}_createTipElement(t){const e=this._getTemplateFactory(t).toHtml();if(!e)return null;e.classList.remove(ts,es),e.classList.add(`bs-${this.constructor.NAME}-auto`);const i=(t=>{do{t+=Math.floor(1e6*Math.random())}while(document.getElementById(t));return t})(this.constructor.NAME).toString();return e.setAttribute("id",i),this._isAnimated()&&e.classList.add(ts),e}setContent(t){this._newContent=t,this._isShown()&&(this._disposePopper(),this.show())}_getTemplateFactory(t){return this._templateFactory?this._templateFactory.changeContent(t):this._templateFactory=new Jn({...this._config,content:t,extraClass:this._resolvePossibleFunction(this._config.customClass)}),this._templateFactory}_getContentForTemplate(){return{".tooltip-inner":this._getTitle()}}_getTitle(){return this._resolvePossibleFunction(this._config.title)||this._element.getAttribute("data-bs-original-title")}_initializeOnDelegatedTarget(t){return this.constructor.getOrCreateInstance(t.delegateTarget,this._getDelegateConfig())}_isAnimated(){return this._config.animation||this.tip&&this.tip.classList.contains(ts)}_isShown(){return this.tip&&this.tip.classList.contains(es)}_createPopper(t){const e=g(this._config.placement,[this,t,this._element]),i=rs[e.toUpperCase()];return bi(this._element,t,this._getPopperConfig(i))}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map((t=>Number.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_resolvePossibleFunction(t){return g(t,[this._element])}_getPopperConfig(t){const e={placement:t,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"preSetPlacement",enabled:!0,phase:"beforeMain",fn:t=>{this._getTipElement().setAttribute("data-popper-placement",t.state.placement)}}]};return{...e,...g(this._config.popperConfig,[e])}}_setListeners(){const t=this._config.trigger.split(" ");for(const e of t)if("click"===e)N.on(this._element,this.constructor.eventName("click"),this._config.selector,(t=>{this._initializeOnDelegatedTarget(t).toggle()}));else if("manual"!==e){const t=e===ss?this.constructor.eventName("mouseenter"):this.constructor.eventName("focusin"),i=e===ss?this.constructor.eventName("mouseleave"):this.constructor.eventName("focusout");N.on(this._element,t,this._config.selector,(t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusin"===t.type?os:ss]=!0,e._enter()})),N.on(this._element,i,this._config.selector,(t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusout"===t.type?os:ss]=e._element.contains(t.relatedTarget),e._leave()}))}this._hideModalHandler=()=>{this._element&&this.hide()},N.on(this._element.closest(is),ns,this._hideModalHandler)}_fixTitle(){const t=this._element.getAttribute("title");t&&(this._element.getAttribute("aria-label")||this._element.textContent.trim()||this._element.setAttribute("aria-label",t),this._element.setAttribute("data-bs-original-title",t),this._element.removeAttribute("title"))}_enter(){this._isShown()||this._isHovered?this._isHovered=!0:(this._isHovered=!0,this._setTimeout((()=>{this._isHovered&&this.show()}),this._config.delay.show))}_leave(){this._isWithActiveTrigger()||(this._isHovered=!1,this._setTimeout((()=>{this._isHovered||this.hide()}),this._config.delay.hide))}_setTimeout(t,e){clearTimeout(this._timeout),this._timeout=setTimeout(t,e)}_isWithActiveTrigger(){return Object.values(this._activeTrigger).includes(!0)}_getConfig(t){const e=F.getDataAttributes(this._element);for(const t of Object.keys(e))Zn.has(t)&&delete e[t];return t={...e,..."object"==typeof t&&t?t:{}},t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t.container=!1===t.container?document.body:r(t.container),"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),t}_getDelegateConfig(){const t={};for(const[e,i]of Object.entries(this._config))this.constructor.Default[e]!==i&&(t[e]=i);return t.selector=!1,t.trigger="manual",t}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null),this.tip&&(this.tip.remove(),this.tip=null)}static jQueryInterface(t){return this.each((function(){const e=cs.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}m(cs);const hs={...cs.Default,content:"",offset:[0,8],placement:"right",template:'',trigger:"click"},ds={...cs.DefaultType,content:"(null|string|element|function)"};class us extends cs{static get Default(){return hs}static get DefaultType(){return ds}static get NAME(){return"popover"}_isWithContent(){return this._getTitle()||this._getContent()}_getContentForTemplate(){return{".popover-header":this._getTitle(),".popover-body":this._getContent()}}_getContent(){return this._resolvePossibleFunction(this._config.content)}static jQueryInterface(t){return this.each((function(){const e=us.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}m(us);const fs=".bs.scrollspy",ps=`activate${fs}`,ms=`click${fs}`,gs=`load${fs}.data-api`,_s="active",bs="[href]",vs=".nav-link",ys=`${vs}, .nav-item > ${vs}, .list-group-item`,ws={offset:null,rootMargin:"0px 0px -25%",smoothScroll:!1,target:null,threshold:[.1,.5,1]},As={offset:"(number|null)",rootMargin:"string",smoothScroll:"boolean",target:"element",threshold:"array"};class Es extends W{constructor(t,e){super(t,e),this._targetLinks=new Map,this._observableSections=new Map,this._rootElement="visible"===getComputedStyle(this._element).overflowY?null:this._element,this._activeTarget=null,this._observer=null,this._previousScrollData={visibleEntryTop:0,parentScrollTop:0},this.refresh()}static get Default(){return ws}static get DefaultType(){return As}static get NAME(){return"scrollspy"}refresh(){this._initializeTargetsAndObservables(),this._maybeEnableSmoothScroll(),this._observer?this._observer.disconnect():this._observer=this._getNewObserver();for(const t of this._observableSections.values())this._observer.observe(t)}dispose(){this._observer.disconnect(),super.dispose()}_configAfterMerge(t){return t.target=r(t.target)||document.body,t.rootMargin=t.offset?`${t.offset}px 0px -30%`:t.rootMargin,"string"==typeof t.threshold&&(t.threshold=t.threshold.split(",").map((t=>Number.parseFloat(t)))),t}_maybeEnableSmoothScroll(){this._config.smoothScroll&&(N.off(this._config.target,ms),N.on(this._config.target,ms,bs,(t=>{const e=this._observableSections.get(t.target.hash);if(e){t.preventDefault();const i=this._rootElement||window,n=e.offsetTop-this._element.offsetTop;if(i.scrollTo)return void i.scrollTo({top:n,behavior:"smooth"});i.scrollTop=n}})))}_getNewObserver(){const t={root:this._rootElement,threshold:this._config.threshold,rootMargin:this._config.rootMargin};return new IntersectionObserver((t=>this._observerCallback(t)),t)}_observerCallback(t){const e=t=>this._targetLinks.get(`#${t.target.id}`),i=t=>{this._previousScrollData.visibleEntryTop=t.target.offsetTop,this._process(e(t))},n=(this._rootElement||document.documentElement).scrollTop,s=n>=this._previousScrollData.parentScrollTop;this._previousScrollData.parentScrollTop=n;for(const o of t){if(!o.isIntersecting){this._activeTarget=null,this._clearActiveClass(e(o));continue}const t=o.target.offsetTop>=this._previousScrollData.visibleEntryTop;if(s&&t){if(i(o),!n)return}else s||t||i(o)}}_initializeTargetsAndObservables(){this._targetLinks=new Map,this._observableSections=new Map;const t=z.find(bs,this._config.target);for(const e of t){if(!e.hash||l(e))continue;const t=z.findOne(decodeURI(e.hash),this._element);a(t)&&(this._targetLinks.set(decodeURI(e.hash),e),this._observableSections.set(e.hash,t))}}_process(t){this._activeTarget!==t&&(this._clearActiveClass(this._config.target),this._activeTarget=t,t.classList.add(_s),this._activateParents(t),N.trigger(this._element,ps,{relatedTarget:t}))}_activateParents(t){if(t.classList.contains("dropdown-item"))z.findOne(".dropdown-toggle",t.closest(".dropdown")).classList.add(_s);else for(const e of z.parents(t,".nav, .list-group"))for(const t of z.prev(e,ys))t.classList.add(_s)}_clearActiveClass(t){t.classList.remove(_s);const e=z.find(`${bs}.${_s}`,t);for(const t of e)t.classList.remove(_s)}static jQueryInterface(t){return this.each((function(){const e=Es.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}))}}N.on(window,gs,(()=>{for(const t of z.find('[data-bs-spy="scroll"]'))Es.getOrCreateInstance(t)})),m(Es);const Ts=".bs.tab",Cs=`hide${Ts}`,Os=`hidden${Ts}`,xs=`show${Ts}`,ks=`shown${Ts}`,Ls=`click${Ts}`,Ss=`keydown${Ts}`,Ds=`load${Ts}`,$s="ArrowLeft",Is="ArrowRight",Ns="ArrowUp",Ps="ArrowDown",Ms="Home",js="End",Fs="active",Hs="fade",Ws="show",Bs=":not(.dropdown-toggle)",zs='[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',Rs=`.nav-link${Bs}, .list-group-item${Bs}, [role="tab"]${Bs}, ${zs}`,qs=`.${Fs}[data-bs-toggle="tab"], .${Fs}[data-bs-toggle="pill"], .${Fs}[data-bs-toggle="list"]`;class Vs extends W{constructor(t){super(t),this._parent=this._element.closest('.list-group, .nav, [role="tablist"]'),this._parent&&(this._setInitialAttributes(this._parent,this._getChildren()),N.on(this._element,Ss,(t=>this._keydown(t))))}static get NAME(){return"tab"}show(){const t=this._element;if(this._elemIsActive(t))return;const e=this._getActiveElem(),i=e?N.trigger(e,Cs,{relatedTarget:t}):null;N.trigger(t,xs,{relatedTarget:e}).defaultPrevented||i&&i.defaultPrevented||(this._deactivate(e,t),this._activate(t,e))}_activate(t,e){t&&(t.classList.add(Fs),this._activate(z.getElementFromSelector(t)),this._queueCallback((()=>{"tab"===t.getAttribute("role")?(t.removeAttribute("tabindex"),t.setAttribute("aria-selected",!0),this._toggleDropDown(t,!0),N.trigger(t,ks,{relatedTarget:e})):t.classList.add(Ws)}),t,t.classList.contains(Hs)))}_deactivate(t,e){t&&(t.classList.remove(Fs),t.blur(),this._deactivate(z.getElementFromSelector(t)),this._queueCallback((()=>{"tab"===t.getAttribute("role")?(t.setAttribute("aria-selected",!1),t.setAttribute("tabindex","-1"),this._toggleDropDown(t,!1),N.trigger(t,Os,{relatedTarget:e})):t.classList.remove(Ws)}),t,t.classList.contains(Hs)))}_keydown(t){if(![$s,Is,Ns,Ps,Ms,js].includes(t.key))return;t.stopPropagation(),t.preventDefault();const e=this._getChildren().filter((t=>!l(t)));let i;if([Ms,js].includes(t.key))i=e[t.key===Ms?0:e.length-1];else{const n=[Is,Ps].includes(t.key);i=b(e,t.target,n,!0)}i&&(i.focus({preventScroll:!0}),Vs.getOrCreateInstance(i).show())}_getChildren(){return z.find(Rs,this._parent)}_getActiveElem(){return this._getChildren().find((t=>this._elemIsActive(t)))||null}_setInitialAttributes(t,e){this._setAttributeIfNotExists(t,"role","tablist");for(const t of e)this._setInitialAttributesOnChild(t)}_setInitialAttributesOnChild(t){t=this._getInnerElement(t);const e=this._elemIsActive(t),i=this._getOuterElement(t);t.setAttribute("aria-selected",e),i!==t&&this._setAttributeIfNotExists(i,"role","presentation"),e||t.setAttribute("tabindex","-1"),this._setAttributeIfNotExists(t,"role","tab"),this._setInitialAttributesOnTargetPanel(t)}_setInitialAttributesOnTargetPanel(t){const e=z.getElementFromSelector(t);e&&(this._setAttributeIfNotExists(e,"role","tabpanel"),t.id&&this._setAttributeIfNotExists(e,"aria-labelledby",`${t.id}`))}_toggleDropDown(t,e){const i=this._getOuterElement(t);if(!i.classList.contains("dropdown"))return;const n=(t,n)=>{const s=z.findOne(t,i);s&&s.classList.toggle(n,e)};n(".dropdown-toggle",Fs),n(".dropdown-menu",Ws),i.setAttribute("aria-expanded",e)}_setAttributeIfNotExists(t,e,i){t.hasAttribute(e)||t.setAttribute(e,i)}_elemIsActive(t){return t.classList.contains(Fs)}_getInnerElement(t){return t.matches(Rs)?t:z.findOne(Rs,t)}_getOuterElement(t){return t.closest(".nav-item, .list-group-item")||t}static jQueryInterface(t){return this.each((function(){const e=Vs.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}))}}N.on(document,Ls,zs,(function(t){["A","AREA"].includes(this.tagName)&&t.preventDefault(),l(this)||Vs.getOrCreateInstance(this).show()})),N.on(window,Ds,(()=>{for(const t of z.find(qs))Vs.getOrCreateInstance(t)})),m(Vs);const Ks=".bs.toast",Qs=`mouseover${Ks}`,Xs=`mouseout${Ks}`,Ys=`focusin${Ks}`,Us=`focusout${Ks}`,Gs=`hide${Ks}`,Js=`hidden${Ks}`,Zs=`show${Ks}`,to=`shown${Ks}`,eo="hide",io="show",no="showing",so={animation:"boolean",autohide:"boolean",delay:"number"},oo={animation:!0,autohide:!0,delay:5e3};class ro extends W{constructor(t,e){super(t,e),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get Default(){return oo}static get DefaultType(){return so}static get NAME(){return"toast"}show(){N.trigger(this._element,Zs).defaultPrevented||(this._clearTimeout(),this._config.animation&&this._element.classList.add("fade"),this._element.classList.remove(eo),d(this._element),this._element.classList.add(io,no),this._queueCallback((()=>{this._element.classList.remove(no),N.trigger(this._element,to),this._maybeScheduleHide()}),this._element,this._config.animation))}hide(){this.isShown()&&(N.trigger(this._element,Gs).defaultPrevented||(this._element.classList.add(no),this._queueCallback((()=>{this._element.classList.add(eo),this._element.classList.remove(no,io),N.trigger(this._element,Js)}),this._element,this._config.animation)))}dispose(){this._clearTimeout(),this.isShown()&&this._element.classList.remove(io),super.dispose()}isShown(){return this._element.classList.contains(io)}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout((()=>{this.hide()}),this._config.delay)))}_onInteraction(t,e){switch(t.type){case"mouseover":case"mouseout":this._hasMouseInteraction=e;break;case"focusin":case"focusout":this._hasKeyboardInteraction=e}if(e)return void this._clearTimeout();const i=t.relatedTarget;this._element===i||this._element.contains(i)||this._maybeScheduleHide()}_setListeners(){N.on(this._element,Qs,(t=>this._onInteraction(t,!0))),N.on(this._element,Xs,(t=>this._onInteraction(t,!1))),N.on(this._element,Ys,(t=>this._onInteraction(t,!0))),N.on(this._element,Us,(t=>this._onInteraction(t,!1)))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(t){return this.each((function(){const e=ro.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}return R(ro),m(ro),{Alert:Q,Button:Y,Carousel:xt,Collapse:Bt,Dropdown:qi,Modal:On,Offcanvas:qn,Popover:us,ScrollSpy:Es,Tab:Vs,Toast:ro,Tooltip:cs}})); +//# sourceMappingURL=bootstrap.bundle.min.js.map \ No newline at end of file diff --git a/site_libs/clipboard/clipboard.min.js b/site_libs/clipboard/clipboard.min.js new file mode 100644 index 00000000..1103f811 --- /dev/null +++ b/site_libs/clipboard/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return b}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),r=n.n(e);function c(t){try{return document.execCommand(t)}catch(t){return}}var a=function(t){t=r()(t);return c("cut"),t};function o(t,e){var n,o,t=(n=t,o="rtl"===document.documentElement.getAttribute("dir"),(t=document.createElement("textarea")).style.fontSize="12pt",t.style.border="0",t.style.padding="0",t.style.margin="0",t.style.position="absolute",t.style[o?"right":"left"]="-9999px",o=window.pageYOffset||document.documentElement.scrollTop,t.style.top="".concat(o,"px"),t.setAttribute("readonly",""),t.value=n,t);return e.container.appendChild(t),e=r()(t),c("copy"),t.remove(),e}var f=function(t){var e=1=8.9.0" + } +} diff --git a/site_libs/core-js-2.5.3/shim.min.js b/site_libs/core-js-2.5.3/shim.min.js new file mode 100644 index 00000000..dcc9a160 --- /dev/null +++ b/site_libs/core-js-2.5.3/shim.min.js @@ -0,0 +1,10 @@ +/** + * core-js 2.6.11 + * https://github.com/zloirock/core-js + * License: http://rock.mit-license.org + * © 2019 Denis Pushkarev + */ +!function(e,i,Jt){"use strict";!function(r){var e={};function __webpack_require__(t){if(e[t])return e[t].exports;var n=e[t]={i:t,l:!1,exports:{}};return r[t].call(n.exports,n,n.exports,__webpack_require__),n.l=!0,n.exports}__webpack_require__.m=r,__webpack_require__.c=e,__webpack_require__.d=function(t,n,r){__webpack_require__.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:r})},__webpack_require__.n=function(t){var n=t&&t.__esModule?function getDefault(){return t["default"]}:function getModuleExports(){return t};return __webpack_require__.d(n,"a",n),n},__webpack_require__.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},__webpack_require__.p="",__webpack_require__(__webpack_require__.s=129)}([function(t,n,r){var v=r(2),g=r(26),y=r(11),d=r(12),b=r(18),S="prototype",_=function(t,n,r){var e,i,o,u,c=t&_.F,a=t&_.G,f=t&_.P,s=t&_.B,l=a?v:t&_.S?v[n]||(v[n]={}):(v[n]||{})[S],h=a?g:g[n]||(g[n]={}),p=h[S]||(h[S]={});for(e in a&&(r=n),r)o=((i=!c&&l&&l[e]!==Jt)?l:r)[e],u=s&&i?b(o,v):f&&"function"==typeof o?b(Function.call,o):o,l&&d(l,e,o,t&_.U),h[e]!=o&&y(h,e,u),f&&p[e]!=o&&(p[e]=o)};v.core=g,_.F=1,_.G=2,_.S=4,_.P=8,_.B=16,_.W=32,_.U=64,_.R=128,t.exports=_},function(t,n,r){var e=r(4);t.exports=function(t){if(!e(t))throw TypeError(t+" is not an object!");return t}},function(t,n){var r=t.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof i&&(i=r)},function(t,n){t.exports=function(t){try{return!!t()}catch(n){return!0}}},function(t,n){t.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},function(t,n,r){var e=r(47)("wks"),i=r(33),o=r(2).Symbol,u="function"==typeof o;(t.exports=function(t){return e[t]||(e[t]=u&&o[t]||(u?o:i)("Symbol."+t))}).store=e},function(t,n,r){var e=r(20),i=Math.min;t.exports=function(t){return 0"+i+""};t.exports=function(n,t){var r={};r[n]=t(o),e(e.P+e.F*i(function(){var t=""[n]('"');return t!==t.toLowerCase()||3document.F=Object<\/script>"),t.close(),s=t.F;r--;)delete s[f][u[r]];return s()};t.exports=Object.create||function create(t,n){var r;return null!==t?(a[f]=i(t),r=new a,a[f]=null,r[c]=t):r=s(),n===Jt?r:o(r,n)}},function(t,n,r){var e=r(95),i=r(69).concat("length","prototype");n.f=Object.getOwnPropertyNames||function getOwnPropertyNames(t){return e(t,i)}},function(t,n,r){var e=r(2),i=r(8),o=r(7),u=r(5)("species");t.exports=function(t){var n=e[t];o&&n&&!n[u]&&i.f(n,u,{configurable:!0,get:function(){return this}})}},function(t,n){t.exports=function(t,n,r,e){if(!(t instanceof n)||e!==Jt&&e in t)throw TypeError(r+": incorrect invocation!");return t}},function(t,n,r){var h=r(18),p=r(108),v=r(81),g=r(1),y=r(6),d=r(83),b={},S={};(n=t.exports=function(t,n,r,e,i){var o,u,c,a,f=i?function(){return t}:d(t),s=h(r,e,n?2:1),l=0;if("function"!=typeof f)throw TypeError(t+" is not iterable!");if(v(f)){for(o=y(t.length);l")}),d=function(){var t=/(?:)/,n=t.exec;t.exec=function(){return n.apply(this,arguments)};var r="ab".split(t);return 2===r.length&&"a"===r[0]&&"b"===r[1]}();t.exports=function(r,t,n){var e=p(r),o=!l(function(){var t={};return t[e]=function(){return 7},7!=""[r](t)}),i=o?!l(function(){var t=!1,n=/a/;return n.exec=function(){return t=!0,null},"split"===r&&(n.constructor={},n.constructor[g]=function(){return n}),n[e](""),!t}):Jt;if(!o||!i||"replace"===r&&!y||"split"===r&&!d){var u=/./[e],c=n(h,e,""[r],function maybeCallNative(t,n,r,e,i){return n.exec===v?o&&!i?{done:!0,value:u.call(n,r,e)}:{done:!0,value:t.call(r,n,e)}:{done:!1}}),a=c[1];f(String.prototype,r,c[0]),s(RegExp.prototype,e,2==t?function(t,n){return a.call(t,this,n)}:function(t){return a.call(t,this)})}}},function(t,n,r){var e=r(2).navigator;t.exports=e&&e.userAgent||""},function(t,n,r){var d=r(2),b=r(0),S=r(12),_=r(41),x=r(30),m=r(40),w=r(39),E=r(4),O=r(3),M=r(57),I=r(43),P=r(72);t.exports=function(e,t,n,r,i,o){var u=d[e],c=u,a=i?"set":"add",f=c&&c.prototype,s={},l=function(t){var r=f[t];S(f,t,"delete"==t?function(t){return!(o&&!E(t))&&r.call(this,0===t?0:t)}:"has"==t?function has(t){return!(o&&!E(t))&&r.call(this,0===t?0:t)}:"get"==t?function get(t){return o&&!E(t)?Jt:r.call(this,0===t?0:t)}:"add"==t?function add(t){return r.call(this,0===t?0:t),this}:function set(t,n){return r.call(this,0===t?0:t,n),this})};if("function"==typeof c&&(o||f.forEach&&!O(function(){(new c).entries().next()}))){var h=new c,p=h[a](o?{}:-0,1)!=h,v=O(function(){h.has(1)}),g=M(function(t){new c(t)}),y=!o&&O(function(){for(var t=new c,n=5;n--;)t[a](n,n);return!t.has(-0)});g||(((c=t(function(t,n){w(t,c,e);var r=P(new u,t,c);return n!=Jt&&m(n,i,r[a],r),r})).prototype=f).constructor=c),(v||y)&&(l("delete"),l("has"),i&&l("get")),(y||p)&&l(a),o&&f.clear&&delete f.clear}else c=r.getConstructor(t,e,i,a),_(c.prototype,n),x.NEED=!0;return I(c,e),b(b.G+b.W+b.F*((s[e]=c)!=u),s),o||r.setStrong(c,e,i),c}},function(t,n,r){for(var e,i=r(2),o=r(11),u=r(33),c=u("typed_array"),a=u("view"),f=!(!i.ArrayBuffer||!i.DataView),s=f,l=0,h="Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array".split(",");l<9;)(e=i[h[l++]])?(o(e.prototype,c,!0),o(e.prototype,a,!0)):s=!1;t.exports={ABV:f,CONSTR:s,TYPED:c,VIEW:a}},function(t,n,r){t.exports=r(29)||!r(3)(function(){var t=Math.random();__defineSetter__.call(null,t,function(){}),delete r(2)[t]})},function(t,n,r){var e=r(0);t.exports=function(t){e(e.S,t,{of:function of(){for(var t=arguments.length,n=new Array(t);t--;)n[t]=arguments[t];return new this(n)}})}},function(t,n,r){var e=r(0),u=r(10),c=r(18),a=r(40);t.exports=function(t){e(e.S,t,{from:function from(t){var n,r,e,i,o=arguments[1];return u(this),(n=o!==Jt)&&u(o),t==Jt?new this:(r=[],n?(e=0,i=c(o,arguments[2],2),a(t,!1,function(t){r.push(i(t,e++))})):a(t,!1,r.push,r),new this(r))}})}},function(t,n,r){var e=r(4),i=r(2).document,o=e(i)&&e(i.createElement);t.exports=function(t){return o?i.createElement(t):{}}},function(t,n,r){var e=r(2),i=r(26),o=r(29),u=r(94),c=r(8).f;t.exports=function(t){var n=i.Symbol||(i.Symbol=o?{}:e.Symbol||{});"_"==t.charAt(0)||t in n||c(n,t,{value:u.f(t)})}},function(t,n,r){var e=r(47)("keys"),i=r(33);t.exports=function(t){return e[t]||(e[t]=i(t))}},function(t,n){t.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(t,n,r){var e=r(2).document;t.exports=e&&e.documentElement},function(t,n,i){var r=i(4),e=i(1),o=function(t,n){if(e(t),!r(n)&&null!==n)throw TypeError(n+": can't set as prototype!")};t.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(t,r,e){try{(e=i(18)(Function.call,i(16).f(Object.prototype,"__proto__").set,2))(t,[]),r=!(t instanceof Array)}catch(n){r=!0}return function setPrototypeOf(t,n){return o(t,n),r?t.__proto__=n:e(t,n),t}}({},!1):Jt),check:o}},function(t,n,r){var o=r(4),u=r(71).set;t.exports=function(t,n,r){var e,i=n.constructor;return i!==r&&"function"==typeof i&&(e=i.prototype)!==r.prototype&&o(e)&&u&&u(t,e),t}},function(t,n){t.exports="\t\n\x0B\f\r   ᠎              \u2028\u2029\ufeff"},function(t,n,r){var i=r(20),o=r(23);t.exports=function repeat(t){var n=String(o(this)),r="",e=i(t);if(e<0||e==Infinity)throw RangeError("Count can't be negative");for(;0>>=1)&&(n+=n))1&e&&(r+=n);return r}},function(t,n){t.exports=Math.sign||function sign(t){return 0==(t=+t)||t!=t?t:t<0?-1:1}},function(t,n){var r=Math.expm1;t.exports=!r||22025.465794806718>1,s=23===n?F(2,-24)-F(2,-77):0,l=0,h=t<0||0===t&&1/t<0?1:0;for((t=P(t))!=t||t===M?(i=t!=t?1:0,e=a):(e=A(k(t)/N),t*(o=F(2,-e))<1&&(e--,o*=2),2<=(t+=1<=e+f?s/o:s*F(2,1-f))*o&&(e++,o/=2),a<=e+f?(i=0,e=a):1<=e+f?(i=(t*o-1)*F(2,n),e+=f):(i=t*F(2,f-1)*F(2,n),e=0));8<=n;u[l++]=255&i,i/=256,n-=8);for(e=e<>1,c=i-7,a=r-1,f=t[a--],s=127&f;for(f>>=7;0>=-c,c+=n;0>8&255]}function packI32(t){return[255&t,t>>8&255,t>>16&255,t>>24&255]}function packF64(t){return packIEEE754(t,52,8)}function packF32(t){return packIEEE754(t,23,4)}function addGetter(t,n,r){g(t[_],n,{get:function(){return this[r]}})}function get(t,n,r,e){var i=p(+r);if(t[L]>24)},setUint8:function setUint8(t,n){B.call(this,t,n<<24>>24)}},!0)}else m=function ArrayBuffer(t){s(this,m,b);var n=p(t);this._b=y.call(new Array(n),0),this[L]=n},w=function DataView(t,n,r){s(this,w,S),s(t,m,S);var e=t[L],i=l(n);if(i<0||e>24},getUint8:function getUint8(t){return get(this,1,t)[0]},getInt16:function getInt16(t){var n=get(this,2,t,arguments[1]);return(n[1]<<8|n[0])<<16>>16},getUint16:function getUint16(t){var n=get(this,2,t,arguments[1]);return n[1]<<8|n[0]},getInt32:function getInt32(t){return unpackI32(get(this,4,t,arguments[1]))},getUint32:function getUint32(t){return unpackI32(get(this,4,t,arguments[1]))>>>0},getFloat32:function getFloat32(t){return unpackIEEE754(get(this,4,t,arguments[1]),23,4)},getFloat64:function getFloat64(t){return unpackIEEE754(get(this,8,t,arguments[1]),52,8)},setInt8:function setInt8(t,n){set(this,1,t,packI8,n)},setUint8:function setUint8(t,n){set(this,1,t,packI8,n)},setInt16:function setInt16(t,n){set(this,2,t,packI16,n,arguments[2])},setUint16:function setUint16(t,n){set(this,2,t,packI16,n,arguments[2])},setInt32:function setInt32(t,n){set(this,4,t,packI32,n,arguments[2])},setUint32:function setUint32(t,n){set(this,4,t,packI32,n,arguments[2])},setFloat32:function setFloat32(t,n){set(this,4,t,packF32,n,arguments[2])}, +setFloat64:function setFloat64(t,n){set(this,8,t,packF64,n,arguments[2])}});d(m,b),d(w,S),c(w[_],u.VIEW,!0),n[b]=m,n[S]=w},function(t,n,r){t.exports=!r(7)&&!r(3)(function(){return 7!=Object.defineProperty(r(66)("div"),"a",{get:function(){return 7}}).a})},function(t,n,r){n.f=r(5)},function(t,n,r){var u=r(14),c=r(15),a=r(52)(!1),f=r(68)("IE_PROTO");t.exports=function(t,n){var r,e=c(t),i=0,o=[];for(r in e)r!=f&&u(e,r)&&o.push(r);for(;i>>0||(u.test(r)?16:10))}:e},function(t,n){t.exports=Math.log1p||function log1p(t){return-1e-8<(t=+t)&&t<1e-8?t-t*t/2:Math.log(1+t)}},function(t,n,r){var o=r(75),e=Math.pow,u=e(2,-52),c=e(2,-23),a=e(2,127)*(2-c),f=e(2,-126);t.exports=Math.fround||function fround(t){var n,r,e=Math.abs(t),i=o(t);return e>>=0)?31-Math.floor(Math.log(t+.5)*Math.LOG2E):32}})},function(t,n,r){var e=r(0),i=Math.exp;e(e.S,"Math",{cosh:function cosh(t){return(i(t=+t)+i(-t))/2}})},function(t,n,r){var e=r(0),i=r(76);e(e.S+e.F*(i!=Math.expm1),"Math",{expm1:i})},function(t,n,r){var e=r(0);e(e.S,"Math",{fround:r(107)})},function(t,n,r){var e=r(0),a=Math.abs;e(e.S,"Math",{hypot:function hypot(t,n){for(var r,e,i=0,o=0,u=arguments.length,c=0;o>>16)*u+o*(r&i>>>16)<<16>>>0)}})},function(t,n,r){var e=r(0);e(e.S,"Math",{log10:function log10(t){return Math.log(t)*Math.LOG10E}})},function(t,n,r){var e=r(0);e(e.S,"Math",{log1p:r(106)})},function(t,n,r){var e=r(0);e(e.S,"Math",{log2:function log2(t){return Math.log(t)/Math.LN2}})},function(t,n,r){var e=r(0);e(e.S,"Math",{sign:r(75)})},function(t,n,r){var e=r(0),i=r(76),o=Math.exp;e(e.S+e.F*r(3)(function(){return-2e-17!=!Math.sinh(-2e-17)}),"Math",{sinh:function sinh(t){return Math.abs(t=+t)<1?(i(t)-i(-t))/2:(o(t-1)-o(-t-1))*(Math.E/2)}})},function(t,n,r){var e=r(0),i=r(76),o=Math.exp;e(e.S,"Math",{tanh:function tanh(t){var n=i(t=+t),r=i(-t);return n==Infinity?1:r==Infinity?-1:(n-r)/(o(t)+o(-t))}})},function(t,n,r){var e=r(0);e(e.S,"Math",{trunc:function trunc(t){return(0>10),n%1024+56320))}return r.join("")}})},function(t,n,r){var e=r(0),u=r(15),c=r(6);e(e.S,"String",{raw:function raw(t){for(var n=u(t.raw),r=c(n.length),e=arguments.length,i=[],o=0;o]*>)/g,v=/\$([$&`']|\d\d?)/g;r(59)("replace",2,function(i,o,x,m){return[function replace(t,n){var r=i(this),e=t==Jt?Jt:t[o];return e!==Jt?e.call(t,r,n):x.call(String(r),t,n)},function(t,n){var r=m(x,t,this,n);if(r.done)return r.value;var e=w(t),i=String(this),o="function"==typeof n;o||(n=String(n));var u=e.global;if(u){var c=e.unicode;e.lastIndex=0}for(var a=[];;){var f=I(e,i);if( +null===f)break;if(a.push(f),!u)break;""===String(f[0])&&(e.lastIndex=M(i,E(e.lastIndex),c))}for(var s,l="",h=0,p=0;p>>0,f=new RegExp(t.source,(t.ignoreCase?"i":"")+(t.multiline?"m":"")+(t.unicode?"u":"")+(t.sticky?"y":"")+"g");(e=l.call(f,r))&&!(c<(i=f[v])&&(u.push(r.slice(c,e.index)),1>>0;if(0===a)return[];if(0===i.length)return null===m(c,i)?[i]:[];for(var f=0,s=0,l=[];s>>0,o=r>>>0;return(n>>>0)+(e>>>0)+((i&o|(i|o)&~(i+o>>>0))>>>31)|0}})},function(t,n,r){var e=r(0);e(e.S,"Math",{isubh:function isubh(t,n,r,e){var i=t>>>0,o=r>>>0;return(n>>>0)-(e>>>0)-((~i&o|~(i^o)&i-o>>>0)>>>31)|0}})},function(t,n,r){var e=r(0);e(e.S,"Math",{imulh:function imulh(t,n){var r=+t,e=+n,i=65535&r,o=65535&e,u=r>>16,c=e>>16,a=(u*o>>>0)+(i*o>>>16);return u*c+(a>>16)+((i*c>>>0)+(65535&a)>>16)}})},function(t,n,r){var e=r(0);e(e.S,"Math",{RAD_PER_DEG:180/Math.PI})},function(t,n,r){var e=r(0),i=Math.PI/180;e(e.S,"Math",{radians:function radians(t){return t*i}})},function(t,n,r){var e=r(0);e(e.S,"Math",{scale:r(128)})},function(t,n,r){var e=r(0);e(e.S,"Math",{umulh:function umulh(t,n){var r=+t,e=+n,i=65535&r,o=65535&e,u=r>>>16,c=e>>>16,a=(u*o>>>0)+(i*o>>>16);return u*c+(a>>>16)+((i*c>>>0)+(65535&a)>>>16)}})},function(t,n,r){var e=r(0);e(e.S,"Math",{signbit:function signbit(t){return(t=+t)!=t?t:0==t?1/t==Infinity:0.container-fluid.crosstalk-bscols{margin-left:auto;margin-right:auto}.crosstalk-input-checkboxgroup .crosstalk-options-group .crosstalk-options-column{display:inline-block;padding-right:12px;vertical-align:top}@media only screen and (max-width: 480px){.crosstalk-input-checkboxgroup .crosstalk-options-group .crosstalk-options-column{display:block;padding-right:inherit}}.crosstalk-input{margin-bottom:15px}.crosstalk-input .control-label{margin-bottom:0;vertical-align:middle}.crosstalk-input input[type="checkbox"]{margin:4px 0 0;margin-top:1px;line-height:normal}.crosstalk-input .checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.crosstalk-input .checkbox>label{padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.crosstalk-input .checkbox input[type="checkbox"],.crosstalk-input .checkbox-inline input[type="checkbox"]{position:absolute;margin-top:2px;margin-left:-20px}.crosstalk-input .checkbox+.checkbox{margin-top:-5px}.crosstalk-input .checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.crosstalk-input .checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px} diff --git a/site_libs/crosstalk-1.2.0/js/crosstalk.js.map b/site_libs/crosstalk-1.2.0/js/crosstalk.js.map new file mode 100644 index 00000000..cff94f08 --- /dev/null +++ b/site_libs/crosstalk-1.2.0/js/crosstalk.js.map @@ -0,0 +1,37 @@ +{ + "version": 3, + "sources": [ + "node_modules/browser-pack/_prelude.js", + "javascript/src/events.js", + "javascript/src/filter.js", + "javascript/src/filterset.js", + "javascript/src/group.js", + "javascript/src/index.js", + "javascript/src/input.js", + "javascript/src/input_checkboxgroup.js", + "javascript/src/input_selectize.js", + "javascript/src/input_slider.js", + "javascript/src/selection.js", + "javascript/src/util.js", + "javascript/src/var.js" + ], + "names": [], + "mappings": "AAAA;;;;;;;;;;;ICAqB,M;AACnB,oBAAc;AAAA;;AACZ,SAAK,MAAL,GAAc,EAAd;AACA,SAAK,IAAL,GAAY,CAAZ;AACD;;;;uBAEE,S,EAAW,Q,EAAU;AACtB,UAAI,OAAO,KAAK,MAAL,CAAY,SAAZ,CAAX;AACA,UAAI,CAAC,IAAL,EAAW;AACT,eAAO,KAAK,MAAL,CAAY,SAAZ,IAAyB,EAAhC;AACD;AACD,UAAI,MAAM,QAAS,KAAK,IAAL,EAAnB;AACA,WAAK,GAAL,IAAY,QAAZ;AACA,aAAO,GAAP;AACD;;AAED;;;;wBACI,S,EAAW,Q,EAAU;AACvB,UAAI,OAAO,KAAK,MAAL,CAAY,SAAZ,CAAX;AACA,UAAI,OAAO,QAAP,KAAqB,UAAzB,EAAqC;AACnC,aAAK,IAAI,GAAT,IAAgB,IAAhB,EAAsB;AACpB,cAAI,KAAK,cAAL,CAAoB,GAApB,CAAJ,EAA8B;AAC5B,gBAAI,KAAK,GAAL,MAAc,QAAlB,EAA4B;AAC1B,qBAAO,KAAK,GAAL,CAAP;AACA,qBAAO,GAAP;AACD;AACF;AACF;AACD,eAAO,KAAP;AACD,OAVD,MAUO,IAAI,OAAO,QAAP,KAAqB,QAAzB,EAAmC;AACxC,YAAI,QAAQ,KAAK,QAAL,CAAZ,EAA4B;AAC1B,iBAAO,KAAK,QAAL,CAAP;AACA,iBAAO,QAAP;AACD;AACD,eAAO,KAAP;AACD,OANM,MAMA;AACL,cAAM,IAAI,KAAJ,CAAU,8BAAV,CAAN;AACD;AACF;;;4BAEO,S,EAAW,G,EAAK,O,EAAS;AAC/B,UAAI,OAAO,KAAK,MAAL,CAAY,SAAZ,CAAX;AACA,WAAK,IAAI,GAAT,IAAgB,IAAhB,EAAsB;AACpB,YAAI,KAAK,cAAL,CAAoB,GAApB,CAAJ,EAA8B;AAC5B,eAAK,GAAL,EAAU,IAAV,CAAe,OAAf,EAAwB,GAAxB;AACD;AACF;AACF;;;;;;kBA/CkB,M;;;;;;;;;;;;ACArB;;;;AACA;;;;AACA;;;;AACA;;IAAY,I;;;;;;;;AAEZ,SAAS,YAAT,CAAsB,KAAtB,EAA6B;AAC3B,MAAI,QAAQ,MAAM,GAAN,CAAU,WAAV,CAAZ;AACA,MAAI,SAAS,MAAM,GAAN,EAAb;AACA,MAAI,CAAC,MAAL,EAAa;AACX,aAAS,yBAAT;AACA,UAAM,GAAN,CAAU,MAAV;AACD;AACD,SAAO,MAAP;AACD;;AAED,IAAI,KAAK,CAAT;AACA,SAAS,MAAT,GAAkB;AAChB,SAAO,IAAP;AACD;;AAED;;;;;;;;;;;;;;;;;;;;;;;;;IAwBa,Y,WAAA,Y;AACX,wBAAY,KAAZ,EAAmB,SAAnB,EAA8B;AAAA;;AAC5B,SAAK,WAAL,GAAmB,sBAAnB;AACA,SAAK,QAAL,GAAgB,IAAI,KAAK,mBAAT,CAA6B,KAAK,WAAlC,CAAhB;;AAEA;AACA,SAAK,MAAL,GAAc,IAAd;AACA;AACA,SAAK,UAAL,GAAkB,IAAlB;AACA;AACA,SAAK,UAAL,GAAkB,IAAlB;AACA;AACA,SAAK,eAAL,GAAuB,IAAvB;;AAEA,SAAK,UAAL,GAAkB,KAAK,MAAL,CAAY,EAAE,QAAQ,IAAV,EAAZ,EAA8B,SAA9B,CAAlB;;AAEA,SAAK,GAAL,GAAW,WAAW,QAAtB;;AAEA,SAAK,QAAL,CAAc,KAAd;AACD;;AAED;;;;;;;;;;;;;;6BAUS,K,EAAO;AAAA;;AACd;AACA,UAAI,KAAK,MAAL,KAAgB,KAApB,EACE;AACF;AACA,UAAI,CAAC,KAAK,MAAN,IAAgB,CAAC,KAArB,EACE;;AAEF,UAAI,KAAK,UAAT,EAAqB;AACnB,aAAK,UAAL,CAAgB,GAAhB,CAAoB,QAApB,EAA8B,KAAK,eAAnC;AACA,aAAK,KAAL;AACA,aAAK,eAAL,GAAuB,IAAvB;AACA,aAAK,UAAL,GAAkB,IAAlB;AACA,aAAK,UAAL,GAAkB,IAAlB;AACD;;AAED,WAAK,MAAL,GAAc,KAAd;;AAEA,UAAI,KAAJ,EAAW;AACT,gBAAQ,qBAAI,KAAJ,CAAR;AACA,aAAK,UAAL,GAAkB,aAAa,KAAb,CAAlB;AACA,aAAK,UAAL,GAAkB,qBAAI,KAAJ,EAAW,GAAX,CAAe,QAAf,CAAlB;AACA,YAAI,MAAM,KAAK,UAAL,CAAgB,EAAhB,CAAmB,QAAnB,EAA6B,UAAC,CAAD,EAAO;AAC5C,gBAAK,WAAL,CAAiB,OAAjB,CAAyB,QAAzB,EAAmC,CAAnC;AACD,SAFS,CAAV;AAGA,aAAK,eAAL,GAAuB,GAAvB;AACD;AACF;;AAED;;;;;;;;oCAKgB,S,EAAW;AACzB,aAAO,KAAK,MAAL,CAAY,EAAZ,EACL,KAAK,UAAL,GAAkB,KAAK,UAAvB,GAAoC,IAD/B,EAEL,YAAY,SAAZ,GAAwB,IAFnB,CAAP;AAGD;;AAED;;;;;;;4BAIQ;AACN,WAAK,QAAL,CAAc,kBAAd;AACA,WAAK,KAAL;AACA,WAAK,QAAL,CAAc,IAAd;AACD;;AAED;;;;;;;;;;;;0BASM,S,EAAW;AACf,UAAI,CAAC,KAAK,UAAV,EACE;AACF,WAAK,UAAL,CAAgB,KAAhB,CAAsB,KAAK,GAA3B;AACA,WAAK,SAAL,CAAe,SAAf;AACD;;AAED;;;;;;;;;;;;;;;;;;;;wBAiBI,I,EAAM,S,EAAW;AACnB,UAAI,CAAC,KAAK,UAAV,EACE;AACF,WAAK,UAAL,CAAgB,MAAhB,CAAuB,KAAK,GAA5B,EAAiC,IAAjC;AACA,WAAK,SAAL,CAAe,SAAf;AACD;;AAED;;;;;;;;;;AASA;;;;;;;;;;uBAUG,S,EAAW,Q,EAAU;AACtB,aAAO,KAAK,QAAL,CAAc,EAAd,CAAiB,SAAjB,EAA4B,QAA5B,CAAP;AACD;;AAED;;;;;;;;;;;wBAQI,S,EAAW,Q,EAAU;AACvB,aAAO,KAAK,QAAL,CAAc,GAAd,CAAkB,SAAlB,EAA6B,QAA7B,CAAP;AACD;;;8BAES,S,EAAW;AACnB,UAAI,CAAC,KAAK,UAAV,EACE;AACF,WAAK,UAAL,CAAgB,GAAhB,CAAoB,KAAK,UAAL,CAAgB,KAApC,EAA2C,KAAK,eAAL,CAAqB,SAArB,CAA3C;AACD;;AAED;;;;;;;;;;;wBApCmB;AACjB,aAAO,KAAK,UAAL,GAAkB,KAAK,UAAL,CAAgB,KAAlC,GAA0C,IAAjD;AACD;;;;;;AA6CH;;;;;;;;;;;;;;;;;;;ACzNA;;;;AAEA,SAAS,iBAAT,CAA2B,CAA3B,EAA8B,CAA9B,EAAiC;AAC/B,MAAI,MAAM,CAAV,EAAa;AACX,WAAO,CAAP;AACD,GAFD,MAEO,IAAI,IAAI,CAAR,EAAW;AAChB,WAAO,CAAC,CAAR;AACD,GAFM,MAEA,IAAI,IAAI,CAAR,EAAW;AAChB,WAAO,CAAP;AACD;AACF;;AAED;;;;IAGqB,S;AACnB,uBAAc;AAAA;;AACZ,SAAK,KAAL;AACD;;;;4BAEO;AACN;AACA,WAAK,QAAL,GAAgB,EAAhB;AACA;AACA,WAAK,KAAL,GAAa,EAAb;AACA,WAAK,MAAL,GAAc,IAAd;AACA,WAAK,cAAL,GAAsB,CAAtB;AACD;;;2BAMM,Q,EAAU,I,EAAM;AACrB,UAAI,SAAS,IAAb,EAAmB;AACjB,eAAO,KAAK,KAAL,CAAW,CAAX,CAAP,CADiB,CACK;AACtB,aAAK,IAAL,CAAU,iBAAV;AACD;;AAJoB,6BAME,2BAAgB,KAAK,QAAL,CAAc,QAAd,CAAhB,EAAyC,IAAzC,CANF;AAAA,UAMhB,KANgB,oBAMhB,KANgB;AAAA,UAMT,OANS,oBAMT,OANS;;AAOrB,WAAK,QAAL,CAAc,QAAd,IAA0B,IAA1B;;AAEA,WAAK,IAAI,IAAI,CAAb,EAAgB,IAAI,MAAM,MAA1B,EAAkC,GAAlC,EAAuC;AACrC,aAAK,KAAL,CAAW,MAAM,CAAN,CAAX,IAAuB,CAAC,KAAK,KAAL,CAAW,MAAM,CAAN,CAAX,KAAwB,CAAzB,IAA8B,CAArD;AACD;AACD,WAAK,IAAI,KAAI,CAAb,EAAgB,KAAI,QAAQ,MAA5B,EAAoC,IAApC,EAAyC;AACvC,aAAK,KAAL,CAAW,QAAQ,EAAR,CAAX;AACD;;AAED,WAAK,YAAL,CAAkB,IAAlB;AACD;;AAED;;;;;;;;mCAKmC;AAAA,UAAtB,IAAsB,uEAAf,KAAK,QAAU;;AACjC,UAAI,cAAc,OAAO,IAAP,CAAY,KAAK,QAAjB,EAA2B,MAA7C;AACA,UAAI,gBAAgB,CAApB,EAAuB;AACrB,aAAK,MAAL,GAAc,IAAd;AACD,OAFD,MAEO;AACL,aAAK,MAAL,GAAc,EAAd;AACA,aAAK,IAAI,IAAI,CAAb,EAAgB,IAAI,KAAK,MAAzB,EAAiC,GAAjC,EAAsC;AACpC,cAAI,QAAQ,KAAK,KAAL,CAAW,KAAK,CAAL,CAAX,CAAZ;AACA,cAAI,UAAU,WAAd,EAA2B;AACzB,iBAAK,MAAL,CAAY,IAAZ,CAAiB,KAAK,CAAL,CAAjB;AACD;AACF;AACF;AACF;;;0BAEK,Q,EAAU;AACd,UAAI,OAAO,KAAK,QAAL,CAAc,QAAd,CAAP,KAAoC,WAAxC,EAAqD;AACnD;AACD;;AAED,UAAI,OAAO,KAAK,QAAL,CAAc,QAAd,CAAX;AACA,UAAI,CAAC,IAAL,EAAW;AACT,eAAO,EAAP;AACD;;AAED,WAAK,IAAI,IAAI,CAAb,EAAgB,IAAI,KAAK,MAAzB,EAAiC,GAAjC,EAAsC;AACpC,aAAK,KAAL,CAAW,KAAK,CAAL,CAAX;AACD;AACD,aAAO,KAAK,QAAL,CAAc,QAAd,CAAP;;AAEA,WAAK,YAAL;AACD;;;wBA3DW;AACV,aAAO,KAAK,MAAZ;AACD;;;wBA2Dc;AACb,UAAI,UAAU,OAAO,IAAP,CAAY,KAAK,KAAjB,CAAd;AACA,cAAQ,IAAR,CAAa,iBAAb;AACA,aAAO,OAAP;AACD;;;;;;kBA/EkB,S;;;;;;;;;;;;;;kBCRG,K;;AAPxB;;;;;;;;AAEA;AACA;AACA,OAAO,kBAAP,GAA4B,OAAO,kBAAP,IAA6B,EAAzD;AACA,IAAI,SAAS,OAAO,kBAApB;;AAEe,SAAS,KAAT,CAAe,SAAf,EAA0B;AACvC,MAAI,aAAa,OAAO,SAAP,KAAsB,QAAvC,EAAiD;AAC/C,QAAI,CAAC,OAAO,cAAP,CAAsB,SAAtB,CAAL,EAAuC;AACrC,aAAO,SAAP,IAAoB,IAAI,KAAJ,CAAU,SAAV,CAApB;AACD;AACD,WAAO,OAAO,SAAP,CAAP;AACD,GALD,MAKO,IAAI,QAAO,SAAP,yCAAO,SAAP,OAAsB,QAAtB,IAAkC,UAAU,KAA5C,IAAqD,UAAU,GAAnE,EAAwE;AAC7E;AACA,WAAO,SAAP;AACD,GAHM,MAGA,IAAI,MAAM,OAAN,CAAc,SAAd,KACP,UAAU,MAAV,IAAoB,CADb,IAEP,OAAO,UAAU,CAAV,CAAP,KAAyB,QAFtB,EAEgC;AACrC,WAAO,MAAM,UAAU,CAAV,CAAN,CAAP;AACD,GAJM,MAIA;AACL,UAAM,IAAI,KAAJ,CAAU,4BAAV,CAAN;AACD;AACF;;IAEK,K;AACJ,iBAAY,IAAZ,EAAkB;AAAA;;AAChB,SAAK,IAAL,GAAY,IAAZ;AACA,SAAK,KAAL,GAAa,EAAb;AACD;;;;yBAEG,I,EAAM;AACR,UAAI,CAAC,IAAD,IAAS,OAAO,IAAP,KAAiB,QAA9B,EAAwC;AACtC,cAAM,IAAI,KAAJ,CAAU,kBAAV,CAAN;AACD;;AAED,UAAI,CAAC,KAAK,KAAL,CAAW,cAAX,CAA0B,IAA1B,CAAL,EACE,KAAK,KAAL,CAAW,IAAX,IAAmB,kBAAQ,IAAR,EAAc,IAAd,CAAnB;AACF,aAAO,KAAK,KAAL,CAAW,IAAX,CAAP;AACD;;;wBAEG,I,EAAM;AACR,UAAI,CAAC,IAAD,IAAS,OAAO,IAAP,KAAiB,QAA9B,EAAwC;AACtC,cAAM,IAAI,KAAJ,CAAU,kBAAV,CAAN;AACD;;AAED,aAAO,KAAK,KAAL,CAAW,cAAX,CAA0B,IAA1B,CAAP;AACD;;;;;;;;;;;;;;;;AC/CH;;;;AACA;;AACA;;AACA;;AACA;;AACA;;AACA;;;;AAEA,IAAM,eAAe,qBAAM,SAAN,CAArB;;AAEA,SAAS,IAAT,CAAc,IAAd,EAAoB;AAClB,SAAO,aAAa,GAAb,CAAiB,IAAjB,CAAP;AACD;;AAED,SAAS,GAAT,CAAa,IAAb,EAAmB;AACjB,SAAO,aAAa,GAAb,CAAiB,IAAjB,CAAP;AACD;;AAED,IAAI,OAAO,KAAX,EAAkB;AAChB,SAAO,KAAP,CAAa,uBAAb,CAAqC,qBAArC,EAA4D,UAAS,OAAT,EAAkB;AAC5E,QAAI,OAAO,QAAQ,KAAf,KAA0B,QAA9B,EAAwC;AACtC,2BAAM,QAAQ,KAAd,EAAqB,GAArB,CAAyB,QAAQ,IAAjC,EAAuC,GAAvC,CAA2C,QAAQ,KAAnD;AACD,KAFD,MAEO;AACL,WAAK,QAAQ,IAAb,EAAmB,GAAnB,CAAuB,QAAQ,KAA/B;AACD;AACF,GAND;AAOD;;AAED,IAAM,YAAY;AAChB,wBADgB;AAEhB,OAAK,IAFW;AAGhB,OAAK,GAHW;AAIhB,6CAJgB;AAKhB,oCALgB;AAMhB;AANgB,CAAlB;;AASA;;;kBAGe,S;;AACf,OAAO,SAAP,GAAmB,SAAnB;;;;;;;;;;;QCrCgB,Q,GAAA,Q;QAWA,I,GAAA,I;AAfhB,IAAI,IAAI,OAAO,MAAf;;AAEA,IAAI,WAAW,EAAf;;AAEO,SAAS,QAAT,CAAkB,GAAlB,EAAuB;AAC5B,WAAS,IAAI,SAAb,IAA0B,GAA1B;AACA,MAAI,OAAO,QAAP,IAAmB,OAAO,QAAP,CAAgB,UAAhB,KAA+B,UAAtD,EAAkE;AAChE,MAAE,YAAM;AACN;AACD,KAFD;AAGD,GAJD,MAIO,IAAI,OAAO,QAAX,EAAqB;AAC1B,eAAW,IAAX,EAAiB,GAAjB;AACD;AACF;;AAEM,SAAS,IAAT,GAAgB;AACrB,SAAO,IAAP,CAAY,QAAZ,EAAsB,OAAtB,CAA8B,UAAS,SAAT,EAAoB;AAChD,QAAI,UAAU,SAAS,SAAT,CAAd;AACA,MAAE,MAAM,QAAQ,SAAhB,EAA2B,GAA3B,CAA+B,wBAA/B,EAAyD,IAAzD,CAA8D,UAAS,CAAT,EAAY,EAAZ,EAAgB;AAC5E,mBAAa,OAAb,EAAsB,EAAtB;AACD,KAFD;AAGD,GALD;AAMD;;AAED;AACA,SAAS,OAAT,CAAiB,GAAjB,EAAsB;AACpB,SAAO,IAAI,OAAJ,CAAY,uCAAZ,EAAqD,MAArD,CAAP;AACD;;AAED,SAAS,MAAT,CAAgB,EAAhB,EAAoB;AAClB,MAAI,MAAM,EAAE,EAAF,CAAV;AACA,SAAO,IAAP,CAAY,QAAZ,EAAsB,OAAtB,CAA8B,UAAS,SAAT,EAAoB;AAChD,QAAI,IAAI,QAAJ,CAAa,SAAb,KAA2B,CAAC,IAAI,QAAJ,CAAa,uBAAb,CAAhC,EAAuE;AACrE,UAAI,UAAU,SAAS,SAAT,CAAd;AACA,mBAAa,OAAb,EAAsB,EAAtB;AACD;AACF,GALD;AAMD;;AAED,SAAS,YAAT,CAAsB,OAAtB,EAA+B,EAA/B,EAAmC;AACjC,MAAI,SAAS,EAAE,EAAF,EAAM,IAAN,CAAW,+CAA+C,QAAQ,GAAG,EAAX,CAA/C,GAAgE,IAA3E,CAAb;AACA,MAAI,OAAO,KAAK,KAAL,CAAW,OAAO,CAAP,EAAU,SAArB,CAAX;;AAEA,MAAI,WAAW,QAAQ,OAAR,CAAgB,EAAhB,EAAoB,IAApB,CAAf;AACA,IAAE,EAAF,EAAM,IAAN,CAAW,oBAAX,EAAiC,QAAjC;AACA,IAAE,EAAF,EAAM,QAAN,CAAe,uBAAf;AACD;;AAED,IAAI,OAAO,KAAX,EAAkB;AAChB,MAAI,eAAe,IAAI,OAAO,KAAP,CAAa,YAAjB,EAAnB;AACA,MAAI,KAAI,OAAO,MAAf;AACA,KAAE,MAAF,CAAS,YAAT,EAAuB;AACrB,UAAM,cAAS,KAAT,EAAgB;AACpB,aAAO,GAAE,KAAF,EAAS,IAAT,CAAc,kBAAd,CAAP;AACD,KAHoB;AAIrB,gBAAY,oBAAS,EAAT,EAAa;AACvB,UAAI,CAAC,GAAE,EAAF,EAAM,QAAN,CAAe,uBAAf,CAAL,EAA8C;AAC5C,eAAO,EAAP;AACD;AACF,KARoB;AASrB,WAAO,eAAS,EAAT,EAAa;AAClB,aAAO,GAAG,EAAV;AACD,KAXoB;AAYrB,cAAU,kBAAS,EAAT,EAAa,CAEtB,CAdoB;AAerB,cAAU,kBAAS,EAAT,EAAa,KAAb,EAAoB,CAE7B,CAjBoB;AAkBrB,oBAAgB,wBAAS,EAAT,EAAa,IAAb,EAAmB,CAElC,CApBoB;AAqBrB,eAAW,mBAAS,EAAT,EAAa,QAAb,EAAuB;AAChC,SAAE,EAAF,EAAM,IAAN,CAAW,oBAAX,EAAiC,MAAjC;AACD,KAvBoB;AAwBrB,iBAAa,qBAAS,EAAT,EAAa;AACxB,SAAE,EAAF,EAAM,IAAN,CAAW,oBAAX,EAAiC,OAAjC;AACD;AA1BoB,GAAvB;AA4BA,SAAO,KAAP,CAAa,aAAb,CAA2B,QAA3B,CAAoC,YAApC,EAAkD,wBAAlD;AACD;;;;;;;;AChFD;;IAAY,K;;AACZ;;;;AAEA,IAAI,IAAI,OAAO,MAAf;;AAEA,MAAM,QAAN,CAAe;AACb,aAAW,+BADE;;AAGb,WAAS,iBAAS,EAAT,EAAa,IAAb,EAAmB;AAC1B;;;;AAIA,QAAI,WAAW,yBAAiB,KAAK,KAAtB,CAAf;;AAEA,QAAI,sBAAJ;AACA,QAAI,MAAM,EAAE,EAAF,CAAV;AACA,QAAI,EAAJ,CAAO,QAAP,EAAiB,wBAAjB,EAA2C,YAAW;AACpD,UAAI,UAAU,IAAI,IAAJ,CAAS,gCAAT,CAAd;AACA,UAAI,QAAQ,MAAR,KAAmB,CAAvB,EAA0B;AACxB,wBAAgB,IAAhB;AACA,iBAAS,KAAT;AACD,OAHD,MAGO;AACL,YAAI,OAAO,EAAX;AACA,gBAAQ,IAAR,CAAa,YAAW;AACtB,eAAK,GAAL,CAAS,KAAK,KAAd,EAAqB,OAArB,CAA6B,UAAS,GAAT,EAAc;AACzC,iBAAK,GAAL,IAAY,IAAZ;AACD,WAFD;AAGD,SAJD;AAKA,YAAI,WAAW,OAAO,IAAP,CAAY,IAAZ,CAAf;AACA,iBAAS,IAAT;AACA,wBAAgB,QAAhB;AACA,iBAAS,GAAT,CAAa,QAAb;AACD;AACF,KAjBD;;AAmBA,WAAO;AACL,eAAS,mBAAW;AAClB,iBAAS,KAAT;AACD,OAHI;AAIL,cAAQ,kBAAW;AACjB,YAAI,aAAJ,EACE,SAAS,GAAT,CAAa,aAAb;AACH;AAPI,KAAP;AASD;AAxCY,CAAf;;;;;;;;ACLA;;IAAY,K;;AACZ;;IAAY,I;;AACZ;;;;AAEA,IAAI,IAAI,OAAO,MAAf;;AAEA,MAAM,QAAN,CAAe;AACb,aAAW,wBADE;;AAGb,WAAS,iBAAS,EAAT,EAAa,IAAb,EAAmB;AAC1B;;;;;;AAMA,QAAI,QAAQ,CAAC,EAAC,OAAO,EAAR,EAAY,OAAO,OAAnB,EAAD,CAAZ;AACA,QAAI,QAAQ,KAAK,aAAL,CAAmB,KAAK,KAAxB,CAAZ;AACA,QAAI,OAAO;AACT,eAAS,MAAM,MAAN,CAAa,KAAb,CADA;AAET,kBAAY,OAFH;AAGT,kBAAY,OAHH;AAIT,mBAAa;AAJJ,KAAX;;AAOA,QAAI,SAAS,EAAE,EAAF,EAAM,IAAN,CAAW,QAAX,EAAqB,CAArB,CAAb;;AAEA,QAAI,YAAY,EAAE,MAAF,EAAU,SAAV,CAAoB,IAApB,EAA0B,CAA1B,EAA6B,SAA7C;;AAEA,QAAI,WAAW,yBAAiB,KAAK,KAAtB,CAAf;;AAEA,QAAI,sBAAJ;AACA,cAAU,EAAV,CAAa,QAAb,EAAuB,YAAW;AAChC,UAAI,UAAU,KAAV,CAAgB,MAAhB,KAA2B,CAA/B,EAAkC;AAChC,wBAAgB,IAAhB;AACA,iBAAS,KAAT;AACD,OAHD,MAGO;AACL,YAAI,OAAO,EAAX;AACA,kBAAU,KAAV,CAAgB,OAAhB,CAAwB,UAAS,KAAT,EAAgB;AACtC,eAAK,GAAL,CAAS,KAAT,EAAgB,OAAhB,CAAwB,UAAS,GAAT,EAAc;AACpC,iBAAK,GAAL,IAAY,IAAZ;AACD,WAFD;AAGD,SAJD;AAKA,YAAI,WAAW,OAAO,IAAP,CAAY,IAAZ,CAAf;AACA,iBAAS,IAAT;AACA,wBAAgB,QAAhB;AACA,iBAAS,GAAT,CAAa,QAAb;AACD;AACF,KAhBD;;AAkBA,WAAO;AACL,eAAS,mBAAW;AAClB,iBAAS,KAAT;AACD,OAHI;AAIL,cAAQ,kBAAW;AACjB,YAAI,aAAJ,EACE,SAAS,GAAT,CAAa,aAAb;AACH;AAPI,KAAP;AASD;AArDY,CAAf;;;;;;;;;;ACNA;;IAAY,K;;AACZ;;;;AAEA,IAAI,IAAI,OAAO,MAAf;AACA,IAAI,WAAW,OAAO,QAAtB;;AAEA,MAAM,QAAN,CAAe;AACb,aAAW,wBADE;;AAGb,WAAS,iBAAS,EAAT,EAAa,IAAb,EAAmB;AAC1B;;;;AAIA,QAAI,WAAW,yBAAiB,KAAK,KAAtB,CAAf;;AAEA,QAAI,OAAO,EAAX;AACA,QAAI,MAAM,EAAE,EAAF,EAAM,IAAN,CAAW,OAAX,CAAV;AACA,QAAI,WAAW,IAAI,IAAJ,CAAS,WAAT,CAAf;AACA,QAAI,aAAa,IAAI,IAAJ,CAAS,aAAT,CAAjB;AACA,QAAI,QAAQ,IAAI,IAAJ,CAAS,OAAT,CAAZ;AACA,QAAI,sBAAJ;;AAEA;AACA,QAAI,aAAa,MAAjB,EAAyB;AACvB,sBAAgB,SAAS,GAAT,EAAhB;AACA,WAAK,QAAL,GAAgB,UAAS,GAAT,EAAc;AAC5B,eAAO,cAAc,UAAd,EAA0B,IAAI,IAAJ,CAAS,GAAT,CAA1B,CAAP;AACD,OAFD;AAID,KAND,MAMO,IAAI,aAAa,UAAjB,EAA6B;AAClC,UAAI,WAAW,IAAI,IAAJ,CAAS,UAAT,CAAf;AACA,UAAI,QAAJ,EACE,gBAAgB,SAAS,QAAT,CAAkB,QAAlB,CAAhB,CADF,KAGE,gBAAgB,QAAhB;;AAEF,WAAK,QAAL,GAAgB,UAAS,GAAT,EAAc;AAC5B,eAAO,cAAc,UAAd,EAA0B,IAAI,IAAJ,CAAS,GAAT,CAA1B,CAAP;AACD,OAFD;AAGD,KAVM,MAUA,IAAI,aAAa,QAAjB,EAA2B;AAChC,UAAI,OAAO,KAAP,KAAiB,WAArB,EACE,KAAK,QAAL,GAAgB,UAAS,GAAT,EAAc;AAC5B,YAAI,SAAS,KAAK,GAAL,CAAS,EAAT,EAAa,KAAb,CAAb;AACA,eAAO,KAAK,KAAL,CAAW,MAAM,MAAjB,IAA2B,MAAlC;AACD,OAHD;AAIH;;AAED,QAAI,cAAJ,CAAmB,IAAnB;;AAEA,aAAS,QAAT,GAAoB;AAClB,UAAI,SAAS,IAAI,IAAJ,CAAS,gBAAT,EAA2B,MAAxC;;AAEA;AACA,UAAI,gBAAJ;AACA,UAAI,WAAW,IAAI,IAAJ,CAAS,WAAT,CAAf;AACA,UAAI,aAAa,MAAjB,EAAyB;AACvB,kBAAU,iBAAS,GAAT,EAAc;AACtB,iBAAO,cAAc,IAAI,IAAJ,CAAS,CAAC,GAAV,CAAd,CAAP;AACD,SAFD;AAGD,OAJD,MAIO,IAAI,aAAa,UAAjB,EAA6B;AAClC,kBAAU,iBAAS,GAAT,EAAc;AACtB;AACA,iBAAO,CAAC,GAAD,GAAO,IAAd;AACD,SAHD;AAID,OALM,MAKA;AACL,kBAAU,iBAAS,GAAT,EAAc;AAAE,iBAAO,CAAC,GAAR;AAAc,SAAxC;AACD;;AAED,UAAI,IAAI,IAAJ,CAAS,gBAAT,EAA2B,OAA3B,CAAmC,IAAnC,KAA4C,QAAhD,EAA0D;AACxD,eAAO,CAAC,QAAQ,OAAO,IAAf,CAAD,EAAuB,QAAQ,OAAO,EAAf,CAAvB,CAAP;AACD,OAFD,MAEO;AACL,eAAO,QAAQ,OAAO,IAAf,CAAP;AACD;AACF;;AAED,QAAI,gBAAgB,IAApB;;AAEA,QAAI,EAAJ,CAAO,6BAAP,EAAsC,UAAS,KAAT,EAAgB;AACpD,UAAI,CAAC,IAAI,IAAJ,CAAS,UAAT,CAAD,IAAyB,CAAC,IAAI,IAAJ,CAAS,WAAT,CAA9B,EAAqD;AAAA,wBAClC,UADkC;AAAA;AAAA,YAC9C,IAD8C;AAAA,YACxC,EADwC;;AAEnD,YAAI,OAAO,EAAX;AACA,aAAK,IAAI,IAAI,CAAb,EAAgB,IAAI,KAAK,MAAL,CAAY,MAAhC,EAAwC,GAAxC,EAA6C;AAC3C,cAAI,MAAM,KAAK,MAAL,CAAY,CAAZ,CAAV;AACA,cAAI,OAAO,IAAP,IAAe,OAAO,EAA1B,EAA8B;AAC5B,iBAAK,IAAL,CAAU,KAAK,IAAL,CAAU,CAAV,CAAV;AACD;AACF;AACD,aAAK,IAAL;AACA,iBAAS,GAAT,CAAa,IAAb;AACA,wBAAgB,IAAhB;AACD;AACF,KAdD;;AAiBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,WAAO;AACL,eAAS,mBAAW;AAClB,iBAAS,KAAT;AACD,OAHI;AAIL,cAAQ,kBAAW;AACjB,YAAI,aAAJ,EACE,SAAS,GAAT,CAAa,aAAb;AACH;AAPI,KAAP;AASD;AApHY,CAAf;;AAwHA;AACA,SAAS,QAAT,CAAkB,CAAlB,EAAqB,MAArB,EAA6B;AAC3B,MAAI,MAAM,EAAE,QAAF,EAAV;AACA,SAAO,IAAI,MAAJ,GAAa,MAApB;AACE,UAAM,MAAM,GAAZ;AADF,GAEA,OAAO,GAAP;AACD;;AAED;AACA;AACA,SAAS,aAAT,CAAuB,IAAvB,EAA6B;AAC3B,MAAI,gBAAgB,IAApB,EAA0B;AACxB,WAAO,KAAK,cAAL,KAAwB,GAAxB,GACA,SAAS,KAAK,WAAL,KAAmB,CAA5B,EAA+B,CAA/B,CADA,GACoC,GADpC,GAEA,SAAS,KAAK,UAAL,EAAT,EAA4B,CAA5B,CAFP;AAID,GALD,MAKO;AACL,WAAO,IAAP;AACD;AACF;;;;;;;;;;;;;;ACjJD;;;;AACA;;;;AACA;;IAAY,I;;;;;;;;AAEZ;;;;;;;;;;;;;;;;IAgBa,e,WAAA,e;AAEX,6BAA4C;AAAA,QAAhC,KAAgC,uEAAxB,IAAwB;AAAA,QAAlB,SAAkB,uEAAN,IAAM;;AAAA;;AAC1C,SAAK,WAAL,GAAmB,sBAAnB;AACA,SAAK,QAAL,GAAgB,IAAI,KAAK,mBAAT,CAA6B,KAAK,WAAlC,CAAhB;;AAEA;AACA,SAAK,MAAL,GAAc,IAAd;AACA;AACA,SAAK,IAAL,GAAY,IAAZ;AACA;AACA,SAAK,eAAL,GAAuB,IAAvB;;AAEA,SAAK,UAAL,GAAkB,KAAK,MAAL,CAAY,EAAE,QAAQ,IAAV,EAAZ,EAA8B,SAA9B,CAAlB;;AAEA,SAAK,QAAL,CAAc,KAAd;AACD;;AAED;;;;;;;;;;;;;;;;;6BAaS,K,EAAO;AAAA;;AACd;AACA,UAAI,KAAK,MAAL,KAAgB,KAApB,EACE;AACF;AACA,UAAI,CAAC,KAAK,MAAN,IAAgB,CAAC,KAArB,EACE;;AAEF,UAAI,KAAK,IAAT,EAAe;AACb,aAAK,IAAL,CAAU,GAAV,CAAc,QAAd,EAAwB,KAAK,eAA7B;AACA,aAAK,IAAL,GAAY,IAAZ;AACA,aAAK,eAAL,GAAuB,IAAvB;AACD;;AAED,WAAK,MAAL,GAAc,KAAd;;AAEA,UAAI,KAAJ,EAAW;AACT,aAAK,IAAL,GAAY,qBAAI,KAAJ,EAAW,GAAX,CAAe,WAAf,CAAZ;AACA,YAAI,MAAM,KAAK,IAAL,CAAU,EAAV,CAAa,QAAb,EAAuB,UAAC,CAAD,EAAO;AACtC,gBAAK,WAAL,CAAiB,OAAjB,CAAyB,QAAzB,EAAmC,CAAnC;AACD,SAFS,CAAV;AAGA,aAAK,eAAL,GAAuB,GAAvB;AACD;AACF;;AAED;;;;;;;;;;;;;;;AAcA;;;;;oCAKgB,S,EAAW;AACzB;AACA,aAAO,KAAK,MAAL,CAAY,EAAZ,EACL,KAAK,UAAL,GAAkB,KAAK,UAAvB,GAAoC,IAD/B,EAEL,YAAY,SAAZ,GAAwB,IAFnB,CAAP;AAGD;;AAED;;;;;;;;;;;;;;;wBAYI,Y,EAAc,S,EAAW;AAC3B,UAAI,KAAK,IAAT,EACE,KAAK,IAAL,CAAU,GAAV,CAAc,YAAd,EAA4B,KAAK,eAAL,CAAqB,SAArB,CAA5B;AACH;;AAED;;;;;;;;;;;;;0BAUM,S,EAAW;AACf,UAAI,KAAK,IAAT,EACE,KAAK,GAAL,CAAS,KAAK,CAAd,EAAiB,KAAK,eAAL,CAAqB,SAArB,CAAjB;AACH;;AAED;;;;;;;;;;;;;uBAUG,S,EAAW,Q,EAAU;AACtB,aAAO,KAAK,QAAL,CAAc,EAAd,CAAiB,SAAjB,EAA4B,QAA5B,CAAP;AACD;;AAED;;;;;;;;;;;wBAQI,S,EAAW,Q,EAAU;AACvB,aAAO,KAAK,QAAL,CAAc,GAAd,CAAkB,SAAlB,EAA6B,QAA7B,CAAP;AACD;;AAED;;;;;;;;4BAKQ;AACN,WAAK,QAAL,CAAc,kBAAd;AACA,WAAK,QAAL,CAAc,IAAd;AACD;;;wBAlFW;AACV,aAAO,KAAK,IAAL,GAAY,KAAK,IAAL,CAAU,GAAV,EAAZ,GAA8B,IAArC;AACD;;;;;;AAmFH;;;;;;;;;AASA;;;;;;;;;;;;;;;;;;;;;QCpLgB,M,GAAA,M;QAeA,W,GAAA,W;QAQA,e,GAAA,e;QAoCA,a,GAAA,a;;;;AA3DT,SAAS,MAAT,CAAgB,MAAhB,EAAoC;AAAA,oCAAT,OAAS;AAAT,WAAS;AAAA;;AACzC,OAAK,IAAI,IAAI,CAAb,EAAgB,IAAI,QAAQ,MAA5B,EAAoC,GAApC,EAAyC;AACvC,QAAI,MAAM,QAAQ,CAAR,CAAV;AACA,QAAI,OAAO,GAAP,KAAgB,WAAhB,IAA+B,QAAQ,IAA3C,EACE;;AAEF,SAAK,IAAI,GAAT,IAAgB,GAAhB,EAAqB;AACnB,UAAI,IAAI,cAAJ,CAAmB,GAAnB,CAAJ,EAA6B;AAC3B,eAAO,GAAP,IAAc,IAAI,GAAJ,CAAd;AACD;AACF;AACF;AACD,SAAO,MAAP;AACD;;AAEM,SAAS,WAAT,CAAqB,IAArB,EAA2B;AAChC,OAAK,IAAI,IAAI,CAAb,EAAgB,IAAI,KAAK,MAAzB,EAAiC,GAAjC,EAAsC;AACpC,QAAI,KAAK,CAAL,KAAW,KAAK,IAAE,CAAP,CAAf,EAA0B;AACxB,YAAM,IAAI,KAAJ,CAAU,0CAAV,CAAN;AACD;AACF;AACF;;AAEM,SAAS,eAAT,CAAyB,CAAzB,EAA4B,CAA5B,EAA+B;AACpC,MAAI,MAAM,CAAV;AACA,MAAI,MAAM,CAAV;;AAEA,MAAI,CAAC,CAAL,EAAQ,IAAI,EAAJ;AACR,MAAI,CAAC,CAAL,EAAQ,IAAI,EAAJ;;AAER,MAAI,SAAS,EAAb;AACA,MAAI,SAAS,EAAb;;AAEA,cAAY,CAAZ;AACA,cAAY,CAAZ;;AAEA,SAAO,MAAM,EAAE,MAAR,IAAkB,MAAM,EAAE,MAAjC,EAAyC;AACvC,QAAI,EAAE,GAAF,MAAW,EAAE,GAAF,CAAf,EAAuB;AACrB;AACA;AACD,KAHD,MAGO,IAAI,EAAE,GAAF,IAAS,EAAE,GAAF,CAAb,EAAqB;AAC1B,aAAO,IAAP,CAAY,EAAE,KAAF,CAAZ;AACD,KAFM,MAEA;AACL,aAAO,IAAP,CAAY,EAAE,KAAF,CAAZ;AACD;AACF;;AAED,MAAI,MAAM,EAAE,MAAZ,EACE,SAAS,OAAO,MAAP,CAAc,EAAE,KAAF,CAAQ,GAAR,CAAd,CAAT;AACF,MAAI,MAAM,EAAE,MAAZ,EACE,SAAS,OAAO,MAAP,CAAc,EAAE,KAAF,CAAQ,GAAR,CAAd,CAAT;AACF,SAAO;AACL,aAAS,MADJ;AAEL,WAAO;AAFF,GAAP;AAID;;AAED;AACA;AACO,SAAS,aAAT,CAAuB,EAAvB,EAA2B;AAChC,MAAI,QAAQ,EAAZ;AACA,MAAI,eAAJ;AACA,OAAK,IAAI,IAAT,IAAiB,EAAjB,EAAqB;AACnB,QAAI,GAAG,cAAH,CAAkB,IAAlB,CAAJ,EACE,MAAM,IAAN,CAAW,IAAX;AACF,QAAI,QAAO,GAAG,IAAH,CAAP,MAAqB,QAArB,IAAiC,OAAO,GAAG,IAAH,EAAS,MAAhB,KAA4B,WAAjE,EAA8E;AAC5E,YAAM,IAAI,KAAJ,CAAU,2BAAV,CAAN;AACD,KAFD,MAEO,IAAI,OAAO,MAAP,KAAmB,WAAnB,IAAkC,WAAW,GAAG,IAAH,EAAS,MAA1D,EAAkE;AACvE,YAAM,IAAI,KAAJ,CAAU,8CAAV,CAAN;AACD;AACD,aAAS,GAAG,IAAH,EAAS,MAAlB;AACD;AACD,MAAI,UAAU,EAAd;AACA,MAAI,aAAJ;AACA,OAAK,IAAI,MAAM,CAAf,EAAkB,MAAM,MAAxB,EAAgC,KAAhC,EAAuC;AACrC,WAAO,EAAP;AACA,SAAK,IAAI,MAAM,CAAf,EAAkB,MAAM,MAAM,MAA9B,EAAsC,KAAtC,EAA6C;AAC3C,WAAK,MAAM,GAAN,CAAL,IAAmB,GAAG,MAAM,GAAN,CAAH,EAAe,GAAf,CAAnB;AACD;AACD,YAAQ,IAAR,CAAa,IAAb;AACD;AACD,SAAO,OAAP;AACD;;AAED;;;;;;;IAMa,mB,WAAA,mB;AACX,+BAAY,OAAZ,EAAqB;AAAA;;AACnB,SAAK,QAAL,GAAgB,OAAhB;AACA,SAAK,KAAL,GAAa,EAAb;AACD;;;;uBAEE,S,EAAW,Q,EAAU;AACtB,UAAI,MAAM,KAAK,QAAL,CAAc,EAAd,CAAiB,SAAjB,EAA4B,QAA5B,CAAV;AACA,WAAK,KAAL,CAAW,GAAX,IAAkB,SAAlB;AACA,aAAO,GAAP;AACD;;;wBAEG,S,EAAW,Q,EAAU;AACvB,UAAI,MAAM,KAAK,QAAL,CAAc,GAAd,CAAkB,SAAlB,EAA6B,QAA7B,CAAV;AACA,UAAI,GAAJ,EAAS;AACP,eAAO,KAAK,KAAL,CAAW,GAAX,CAAP;AACD;AACD,aAAO,GAAP;AACD;;;yCAEoB;AAAA;;AACnB,UAAI,eAAe,KAAK,KAAxB;AACA,WAAK,KAAL,GAAa,EAAb;AACA,aAAO,IAAP,CAAY,YAAZ,EAA0B,OAA1B,CAAkC,UAAC,GAAD,EAAS;AACzC,cAAK,QAAL,CAAc,GAAd,CAAkB,aAAa,GAAb,CAAlB,EAAqC,GAArC;AACD,OAFD;AAGD;;;;;;;;;;;;;;;;;;ACpHH;;;;;;;;IAEqB,G;AACnB,eAAY,KAAZ,EAAmB,IAAnB,EAAyB,YAAa,KAAtC,EAA6C;AAAA;;AAC3C,SAAK,MAAL,GAAc,KAAd;AACA,SAAK,KAAL,GAAa,IAAb;AACA,SAAK,MAAL,GAAc,KAAd;AACA,SAAK,OAAL,GAAe,sBAAf;AACD;;;;0BAEK;AACJ,aAAO,KAAK,MAAZ;AACD;;;wBAEG,K,EAAO,YAAa,K,EAAO;AAC7B,UAAI,KAAK,MAAL,KAAgB,KAApB,EAA2B;AACzB;AACA;AACD;AACD,UAAI,WAAW,KAAK,MAApB;AACA,WAAK,MAAL,GAAc,KAAd;AACA;AACA,UAAI,MAAM,EAAV;AACA,UAAI,SAAS,QAAO,KAAP,yCAAO,KAAP,OAAkB,QAA/B,EAAyC;AACvC,aAAK,IAAI,CAAT,IAAc,KAAd,EAAqB;AACnB,cAAI,MAAM,cAAN,CAAqB,CAArB,CAAJ,EACE,IAAI,CAAJ,IAAS,MAAM,CAAN,CAAT;AACH;AACF;AACD,UAAI,QAAJ,GAAe,QAAf;AACA,UAAI,KAAJ,GAAY,KAAZ;AACA,WAAK,OAAL,CAAa,OAAb,CAAqB,QAArB,EAA+B,GAA/B,EAAoC,IAApC;;AAEA;AACA;AACA,UAAI,OAAO,KAAP,IAAgB,OAAO,KAAP,CAAa,aAAjC,EAAgD;AAC9C,eAAO,KAAP,CAAa,aAAb,CACE,mBACG,KAAK,MAAL,CAAY,IAAZ,KAAqB,IAArB,GAA4B,KAAK,MAAL,CAAY,IAAZ,GAAmB,GAA/C,GAAqD,EADxD,IAEE,KAAK,KAHT,EAIE,OAAO,KAAP,KAAkB,WAAlB,GAAgC,IAAhC,GAAuC,KAJzC;AAMD;AACF;;;uBAEE,S,EAAW,Q,EAAU;AACtB,aAAO,KAAK,OAAL,CAAa,EAAb,CAAgB,SAAhB,EAA2B,QAA3B,CAAP;AACD;;;wBAEG,S,EAAW,Q,EAAU;AACvB,aAAO,KAAK,OAAL,CAAa,GAAb,CAAiB,SAAjB,EAA4B,QAA5B,CAAP;AACD;;;;;;kBAjDkB,G", + "file": "generated.js", + "sourceRoot": "", + "sourcesContent": [ + "(function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o {\n this._eventRelay.trigger(\"change\", e, this);\n });\n this._varOnChangeSub = sub;\n }\n }\n\n /**\n * Combine the given `extraInfo` (if any) with the handle's default\n * `_extraInfo` (if any).\n * @private\n */\n _mergeExtraInfo(extraInfo) {\n return util.extend({},\n this._extraInfo ? this._extraInfo : null,\n extraInfo ? extraInfo : null);\n }\n\n /**\n * Close the handle. This clears this handle's contribution to the filter set,\n * and unsubscribes all event listeners.\n */\n close() {\n this._emitter.removeAllListeners();\n this.clear();\n this.setGroup(null);\n }\n\n /**\n * Clear this handle's contribution to the filter set.\n *\n * @param {Object} [extraInfo] - Extra properties to be included on the event\n * object that's passed to listeners (in addition to any options that were\n * passed into the `FilterHandle` constructor).\n * \n * @fires FilterHandle#change\n */\n clear(extraInfo) {\n if (!this._filterSet)\n return;\n this._filterSet.clear(this._id);\n this._onChange(extraInfo);\n }\n\n /**\n * Set this handle's contribution to the filter set. This array should consist\n * of the keys of the rows that _should_ be displayed; any keys that are not\n * present in the array will be considered _filtered out_. Note that multiple\n * `FilterHandle` instances in the group may each contribute an array of keys,\n * and only those keys that appear in _all_ of the arrays make it through the\n * filter.\n *\n * @param {string[]} keys - Empty array, or array of keys. To clear the\n * filter, don't pass an empty array; instead, use the\n * {@link FilterHandle#clear} method.\n * @param {Object} [extraInfo] - Extra properties to be included on the event\n * object that's passed to listeners (in addition to any options that were\n * passed into the `FilterHandle` constructor).\n * \n * @fires FilterHandle#change\n */\n set(keys, extraInfo) {\n if (!this._filterSet)\n return;\n this._filterSet.update(this._id, keys);\n this._onChange(extraInfo);\n }\n\n /**\n * @return {string[]|null} - Either: 1) an array of keys that made it through\n * all of the `FilterHandle` instances, or, 2) `null`, which means no filter\n * is being applied (all data should be displayed).\n */\n get filteredKeys() {\n return this._filterSet ? this._filterSet.value : null;\n }\n\n /**\n * Subscribe to events on this `FilterHandle`.\n *\n * @param {string} eventType - Indicates the type of events to listen to.\n * Currently, only `\"change\"` is supported.\n * @param {FilterHandle~listener} listener - The callback function that\n * will be invoked when the event occurs.\n * @return {string} - A token to pass to {@link FilterHandle#off} to cancel\n * this subscription.\n */\n on(eventType, listener) {\n return this._emitter.on(eventType, listener);\n }\n\n /**\n * Cancel event subscriptions created by {@link FilterHandle#on}.\n *\n * @param {string} eventType - The type of event to unsubscribe.\n * @param {string|FilterHandle~listener} listener - Either the callback\n * function previously passed into {@link FilterHandle#on}, or the\n * string that was returned from {@link FilterHandle#on}.\n */\n off(eventType, listener) {\n return this._emitter.off(eventType, listener);\n }\n\n _onChange(extraInfo) {\n if (!this._filterSet)\n return;\n this._filterVar.set(this._filterSet.value, this._mergeExtraInfo(extraInfo));\n }\n\n /**\n * @callback FilterHandle~listener\n * @param {Object} event - An object containing details of the event. For\n * `\"change\"` events, this includes the properties `value` (the new\n * value of the filter set, or `null` if no filter set is active),\n * `oldValue` (the previous value of the filter set), and `sender` (the\n * `FilterHandle` instance that made the change).\n */\n\n}\n\n/**\n * @event FilterHandle#change\n * @type {object}\n * @property {object} value - The new value of the filter set, or `null`\n * if no filter set is active.\n * @property {object} oldValue - The previous value of the filter set.\n * @property {FilterHandle} sender - The `FilterHandle` instance that\n * changed the value.\n */\n", + "import { diffSortedLists } from \"./util\";\n\nfunction naturalComparator(a, b) {\n if (a === b) {\n return 0;\n } else if (a < b) {\n return -1;\n } else if (a > b) {\n return 1;\n }\n}\n\n/**\n * @private\n */\nexport default class FilterSet {\n constructor() {\n this.reset();\n }\n\n reset() {\n // Key: handle ID, Value: array of selected keys, or null\n this._handles = {};\n // Key: key string, Value: count of handles that include it\n this._keys = {};\n this._value = null;\n this._activeHandles = 0;\n }\n\n get value() {\n return this._value;\n }\n\n update(handleId, keys) {\n if (keys !== null) {\n keys = keys.slice(0); // clone before sorting\n keys.sort(naturalComparator);\n }\n\n let {added, removed} = diffSortedLists(this._handles[handleId], keys);\n this._handles[handleId] = keys;\n\n for (let i = 0; i < added.length; i++) {\n this._keys[added[i]] = (this._keys[added[i]] || 0) + 1;\n }\n for (let i = 0; i < removed.length; i++) {\n this._keys[removed[i]]--;\n }\n\n this._updateValue(keys);\n }\n\n /**\n * @param {string[]} keys Sorted array of strings that indicate\n * a superset of possible keys.\n * @private\n */\n _updateValue(keys = this._allKeys) {\n let handleCount = Object.keys(this._handles).length;\n if (handleCount === 0) {\n this._value = null;\n } else {\n this._value = [];\n for (let i = 0; i < keys.length; i++) {\n let count = this._keys[keys[i]];\n if (count === handleCount) {\n this._value.push(keys[i]);\n }\n }\n }\n }\n\n clear(handleId) {\n if (typeof(this._handles[handleId]) === \"undefined\") {\n return;\n }\n\n let keys = this._handles[handleId];\n if (!keys) {\n keys = [];\n }\n\n for (let i = 0; i < keys.length; i++) {\n this._keys[keys[i]]--;\n }\n delete this._handles[handleId];\n\n this._updateValue();\n }\n\n get _allKeys() {\n let allKeys = Object.keys(this._keys);\n allKeys.sort(naturalComparator);\n return allKeys;\n }\n}\n", + "import Var from \"./var\";\n\n// Use a global so that multiple copies of crosstalk.js can be loaded and still\n// have groups behave as singletons across all copies.\nglobal.__crosstalk_groups = global.__crosstalk_groups || {};\nlet groups = global.__crosstalk_groups;\n\nexport default function group(groupName) {\n if (groupName && typeof(groupName) === \"string\") {\n if (!groups.hasOwnProperty(groupName)) {\n groups[groupName] = new Group(groupName);\n }\n return groups[groupName];\n } else if (typeof(groupName) === \"object\" && groupName._vars && groupName.var) {\n // Appears to already be a group object\n return groupName;\n } else if (Array.isArray(groupName) &&\n groupName.length == 1 &&\n typeof(groupName[0]) === \"string\") {\n return group(groupName[0]);\n } else {\n throw new Error(\"Invalid groupName argument\");\n }\n}\n\nclass Group {\n constructor(name) {\n this.name = name;\n this._vars = {};\n }\n\n var(name) {\n if (!name || typeof(name) !== \"string\") {\n throw new Error(\"Invalid var name\");\n }\n\n if (!this._vars.hasOwnProperty(name))\n this._vars[name] = new Var(this, name);\n return this._vars[name];\n }\n\n has(name) {\n if (!name || typeof(name) !== \"string\") {\n throw new Error(\"Invalid var name\");\n }\n\n return this._vars.hasOwnProperty(name);\n }\n}\n", + "import group from \"./group\";\nimport { SelectionHandle } from \"./selection\";\nimport { FilterHandle } from \"./filter\";\nimport { bind } from \"./input\";\nimport \"./input_selectize\";\nimport \"./input_checkboxgroup\";\nimport \"./input_slider\";\n\nconst defaultGroup = group(\"default\");\n\nfunction var_(name) {\n return defaultGroup.var(name);\n}\n\nfunction has(name) {\n return defaultGroup.has(name);\n}\n\nif (global.Shiny) {\n global.Shiny.addCustomMessageHandler(\"update-client-value\", function(message) {\n if (typeof(message.group) === \"string\") {\n group(message.group).var(message.name).set(message.value);\n } else {\n var_(message.name).set(message.value);\n }\n });\n}\n\nconst crosstalk = {\n group: group,\n var: var_,\n has: has,\n SelectionHandle: SelectionHandle,\n FilterHandle: FilterHandle,\n bind: bind\n};\n\n/**\n * @namespace crosstalk\n */\nexport default crosstalk;\nglobal.crosstalk = crosstalk;\n", + "let $ = global.jQuery;\n\nlet bindings = {};\n\nexport function register(reg) {\n bindings[reg.className] = reg;\n if (global.document && global.document.readyState !== \"complete\") {\n $(() => {\n bind();\n });\n } else if (global.document) {\n setTimeout(bind, 100);\n }\n}\n\nexport function bind() {\n Object.keys(bindings).forEach(function(className) {\n let binding = bindings[className];\n $(\".\" + binding.className).not(\".crosstalk-input-bound\").each(function(i, el) {\n bindInstance(binding, el);\n });\n });\n}\n\n// Escape jQuery identifier\nfunction $escape(val) {\n return val.replace(/([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^`{|}~])/g, \"\\\\$1\");\n}\n\nfunction bindEl(el) {\n let $el = $(el);\n Object.keys(bindings).forEach(function(className) {\n if ($el.hasClass(className) && !$el.hasClass(\"crosstalk-input-bound\")) {\n let binding = bindings[className];\n bindInstance(binding, el);\n }\n });\n}\n\nfunction bindInstance(binding, el) {\n let jsonEl = $(el).find(\"script[type='application/json'][data-for='\" + $escape(el.id) + \"']\");\n let data = JSON.parse(jsonEl[0].innerText);\n\n let instance = binding.factory(el, data);\n $(el).data(\"crosstalk-instance\", instance);\n $(el).addClass(\"crosstalk-input-bound\");\n}\n\nif (global.Shiny) {\n let inputBinding = new global.Shiny.InputBinding();\n let $ = global.jQuery;\n $.extend(inputBinding, {\n find: function(scope) {\n return $(scope).find(\".crosstalk-input\");\n },\n initialize: function(el) {\n if (!$(el).hasClass(\"crosstalk-input-bound\")) {\n bindEl(el);\n }\n },\n getId: function(el) {\n return el.id;\n },\n getValue: function(el) {\n\n },\n setValue: function(el, value) {\n\n },\n receiveMessage: function(el, data) {\n\n },\n subscribe: function(el, callback) {\n $(el).data(\"crosstalk-instance\").resume();\n },\n unsubscribe: function(el) {\n $(el).data(\"crosstalk-instance\").suspend();\n }\n });\n global.Shiny.inputBindings.register(inputBinding, \"crosstalk.inputBinding\");\n}\n", + "import * as input from \"./input\";\nimport { FilterHandle } from \"./filter\";\n\nlet $ = global.jQuery;\n\ninput.register({\n className: \"crosstalk-input-checkboxgroup\",\n\n factory: function(el, data) {\n /*\n * map: {\"groupA\": [\"keyA\", \"keyB\", ...], ...}\n * group: \"ct-groupname\"\n */\n let ctHandle = new FilterHandle(data.group);\n\n let lastKnownKeys;\n let $el = $(el);\n $el.on(\"change\", \"input[type='checkbox']\", function() {\n let checked = $el.find(\"input[type='checkbox']:checked\");\n if (checked.length === 0) {\n lastKnownKeys = null;\n ctHandle.clear();\n } else {\n let keys = {};\n checked.each(function() {\n data.map[this.value].forEach(function(key) {\n keys[key] = true;\n });\n });\n let keyArray = Object.keys(keys);\n keyArray.sort();\n lastKnownKeys = keyArray;\n ctHandle.set(keyArray);\n }\n });\n\n return {\n suspend: function() {\n ctHandle.clear();\n },\n resume: function() {\n if (lastKnownKeys)\n ctHandle.set(lastKnownKeys);\n }\n };\n }\n});\n", + "import * as input from \"./input\";\nimport * as util from \"./util\";\nimport { FilterHandle } from \"./filter\";\n\nlet $ = global.jQuery;\n\ninput.register({\n className: \"crosstalk-input-select\",\n\n factory: function(el, data) {\n /*\n * items: {value: [...], label: [...]}\n * map: {\"groupA\": [\"keyA\", \"keyB\", ...], ...}\n * group: \"ct-groupname\"\n */\n\n let first = [{value: \"\", label: \"(All)\"}];\n let items = util.dataframeToD3(data.items);\n let opts = {\n options: first.concat(items),\n valueField: \"value\",\n labelField: \"label\",\n searchField: \"label\"\n };\n\n let select = $(el).find(\"select\")[0];\n\n let selectize = $(select).selectize(opts)[0].selectize;\n\n let ctHandle = new FilterHandle(data.group);\n\n let lastKnownKeys;\n selectize.on(\"change\", function() {\n if (selectize.items.length === 0) {\n lastKnownKeys = null;\n ctHandle.clear();\n } else {\n let keys = {};\n selectize.items.forEach(function(group) {\n data.map[group].forEach(function(key) {\n keys[key] = true;\n });\n });\n let keyArray = Object.keys(keys);\n keyArray.sort();\n lastKnownKeys = keyArray;\n ctHandle.set(keyArray);\n }\n });\n\n return {\n suspend: function() {\n ctHandle.clear();\n },\n resume: function() {\n if (lastKnownKeys)\n ctHandle.set(lastKnownKeys);\n }\n };\n }\n});\n", + "import * as input from \"./input\";\nimport { FilterHandle } from \"./filter\";\n\nlet $ = global.jQuery;\nlet strftime = global.strftime;\n\ninput.register({\n className: \"crosstalk-input-slider\",\n\n factory: function(el, data) {\n /*\n * map: {\"groupA\": [\"keyA\", \"keyB\", ...], ...}\n * group: \"ct-groupname\"\n */\n let ctHandle = new FilterHandle(data.group);\n\n let opts = {};\n let $el = $(el).find(\"input\");\n let dataType = $el.data(\"data-type\");\n let timeFormat = $el.data(\"time-format\");\n let round = $el.data(\"round\");\n let timeFormatter;\n\n // Set up formatting functions\n if (dataType === \"date\") {\n timeFormatter = strftime.utc();\n opts.prettify = function(num) {\n return timeFormatter(timeFormat, new Date(num));\n };\n\n } else if (dataType === \"datetime\") {\n let timezone = $el.data(\"timezone\");\n if (timezone)\n timeFormatter = strftime.timezone(timezone);\n else\n timeFormatter = strftime;\n\n opts.prettify = function(num) {\n return timeFormatter(timeFormat, new Date(num));\n };\n } else if (dataType === \"number\") {\n if (typeof round !== \"undefined\")\n opts.prettify = function(num) {\n let factor = Math.pow(10, round);\n return Math.round(num * factor) / factor;\n };\n }\n\n $el.ionRangeSlider(opts);\n\n function getValue() {\n let result = $el.data(\"ionRangeSlider\").result;\n\n // Function for converting numeric value from slider to appropriate type.\n let convert;\n let dataType = $el.data(\"data-type\");\n if (dataType === \"date\") {\n convert = function(val) {\n return formatDateUTC(new Date(+val));\n };\n } else if (dataType === \"datetime\") {\n convert = function(val) {\n // Convert ms to s\n return +val / 1000;\n };\n } else {\n convert = function(val) { return +val; };\n }\n\n if ($el.data(\"ionRangeSlider\").options.type === \"double\") {\n return [convert(result.from), convert(result.to)];\n } else {\n return convert(result.from);\n }\n }\n\n let lastKnownKeys = null;\n\n $el.on(\"change.crosstalkSliderInput\", function(event) {\n if (!$el.data(\"updating\") && !$el.data(\"animating\")) {\n let [from, to] = getValue();\n let keys = [];\n for (let i = 0; i < data.values.length; i++) {\n let val = data.values[i];\n if (val >= from && val <= to) {\n keys.push(data.keys[i]);\n }\n }\n keys.sort();\n ctHandle.set(keys);\n lastKnownKeys = keys;\n }\n });\n\n\n // let $el = $(el);\n // $el.on(\"change\", \"input[type=\"checkbox\"]\", function() {\n // let checked = $el.find(\"input[type=\"checkbox\"]:checked\");\n // if (checked.length === 0) {\n // ctHandle.clear();\n // } else {\n // let keys = {};\n // checked.each(function() {\n // data.map[this.value].forEach(function(key) {\n // keys[key] = true;\n // });\n // });\n // let keyArray = Object.keys(keys);\n // keyArray.sort();\n // ctHandle.set(keyArray);\n // }\n // });\n\n return {\n suspend: function() {\n ctHandle.clear();\n },\n resume: function() {\n if (lastKnownKeys)\n ctHandle.set(lastKnownKeys);\n }\n };\n }\n});\n\n\n// Convert a number to a string with leading zeros\nfunction padZeros(n, digits) {\n let str = n.toString();\n while (str.length < digits)\n str = \"0\" + str;\n return str;\n}\n\n// Given a Date object, return a string in yyyy-mm-dd format, using the\n// UTC date. This may be a day off from the date in the local time zone.\nfunction formatDateUTC(date) {\n if (date instanceof Date) {\n return date.getUTCFullYear() + \"-\" +\n padZeros(date.getUTCMonth()+1, 2) + \"-\" +\n padZeros(date.getUTCDate(), 2);\n\n } else {\n return null;\n }\n}\n", + "import Events from \"./events\";\nimport grp from \"./group\";\nimport * as util from \"./util\";\n\n/**\n * Use this class to read and write (and listen for changes to) the selection\n * for a Crosstalk group. This is intended to be used for linked brushing.\n *\n * If two (or more) `SelectionHandle` instances in the same webpage share the\n * same group name, they will share the same state. Setting the selection using\n * one `SelectionHandle` instance will result in the `value` property instantly\n * changing across the others, and `\"change\"` event listeners on all instances\n * (including the one that initiated the sending) will fire.\n *\n * @param {string} [group] - The name of the Crosstalk group, or if none,\n * null or undefined (or any other falsy value). This can be changed later\n * via the [SelectionHandle#setGroup](#setGroup) method.\n * @param {Object} [extraInfo] - An object whose properties will be copied to\n * the event object whenever an event is emitted.\n */\nexport class SelectionHandle {\n\n constructor(group = null, extraInfo = null) {\n this._eventRelay = new Events();\n this._emitter = new util.SubscriptionTracker(this._eventRelay);\n\n // Name of the group we're currently tracking, if any. Can change over time.\n this._group = null;\n // The Var we're currently tracking, if any. Can change over time.\n this._var = null;\n // The event handler subscription we currently have on var.on(\"change\").\n this._varOnChangeSub = null;\n\n this._extraInfo = util.extend({ sender: this }, extraInfo);\n\n this.setGroup(group);\n }\n\n /**\n * Changes the Crosstalk group membership of this SelectionHandle. The group\n * being switched away from (if any) will not have its selection value\n * modified as a result of calling `setGroup`, even if this handle was the\n * most recent handle to set the selection of the group.\n *\n * The group being switched to (if any) will also not have its selection value\n * modified as a result of calling `setGroup`. If you want to set the\n * selection value of the new group, call `set` explicitly.\n *\n * @param {string} group - The name of the Crosstalk group, or null (or\n * undefined) to clear the group.\n */\n setGroup(group) {\n // If group is unchanged, do nothing\n if (this._group === group)\n return;\n // Treat null, undefined, and other falsy values the same\n if (!this._group && !group)\n return;\n\n if (this._var) {\n this._var.off(\"change\", this._varOnChangeSub);\n this._var = null;\n this._varOnChangeSub = null;\n }\n\n this._group = group;\n\n if (group) {\n this._var = grp(group).var(\"selection\");\n let sub = this._var.on(\"change\", (e) => {\n this._eventRelay.trigger(\"change\", e, this);\n });\n this._varOnChangeSub = sub;\n }\n }\n\n /**\n * Retrieves the current selection for the group represented by this\n * `SelectionHandle`.\n *\n * - If no selection is active, then this value will be falsy.\n * - If a selection is active, but no data points are selected, then this\n * value will be an empty array.\n * - If a selection is active, and data points are selected, then the keys\n * of the selected data points will be present in the array.\n */\n get value() {\n return this._var ? this._var.get() : null;\n }\n\n /**\n * Combines the given `extraInfo` (if any) with the handle's default\n * `_extraInfo` (if any).\n * @private\n */\n _mergeExtraInfo(extraInfo) {\n // Important incidental effect: shallow clone is returned\n return util.extend({},\n this._extraInfo ? this._extraInfo : null,\n extraInfo ? extraInfo : null);\n }\n\n /**\n * Overwrites the current selection for the group, and raises the `\"change\"`\n * event among all of the group's '`SelectionHandle` instances (including\n * this one).\n *\n * @fires SelectionHandle#change\n * @param {string[]} selectedKeys - Falsy, empty array, or array of keys (see\n * {@link SelectionHandle#value}).\n * @param {Object} [extraInfo] - Extra properties to be included on the event\n * object that's passed to listeners (in addition to any options that were\n * passed into the `SelectionHandle` constructor).\n */\n set(selectedKeys, extraInfo) {\n if (this._var)\n this._var.set(selectedKeys, this._mergeExtraInfo(extraInfo));\n }\n\n /**\n * Overwrites the current selection for the group, and raises the `\"change\"`\n * event among all of the group's '`SelectionHandle` instances (including\n * this one).\n *\n * @fires SelectionHandle#change\n * @param {Object} [extraInfo] - Extra properties to be included on the event\n * object that's passed to listeners (in addition to any that were passed\n * into the `SelectionHandle` constructor).\n */\n clear(extraInfo) {\n if (this._var)\n this.set(void 0, this._mergeExtraInfo(extraInfo));\n }\n\n /**\n * Subscribes to events on this `SelectionHandle`.\n *\n * @param {string} eventType - Indicates the type of events to listen to.\n * Currently, only `\"change\"` is supported.\n * @param {SelectionHandle~listener} listener - The callback function that\n * will be invoked when the event occurs.\n * @return {string} - A token to pass to {@link SelectionHandle#off} to cancel\n * this subscription.\n */\n on(eventType, listener) {\n return this._emitter.on(eventType, listener);\n }\n\n /**\n * Cancels event subscriptions created by {@link SelectionHandle#on}.\n *\n * @param {string} eventType - The type of event to unsubscribe.\n * @param {string|SelectionHandle~listener} listener - Either the callback\n * function previously passed into {@link SelectionHandle#on}, or the\n * string that was returned from {@link SelectionHandle#on}.\n */\n off(eventType, listener) {\n return this._emitter.off(eventType, listener);\n }\n\n /**\n * Shuts down the `SelectionHandle` object.\n *\n * Removes all event listeners that were added through this handle.\n */\n close() {\n this._emitter.removeAllListeners();\n this.setGroup(null);\n }\n}\n\n/**\n * @callback SelectionHandle~listener\n * @param {Object} event - An object containing details of the event. For\n * `\"change\"` events, this includes the properties `value` (the new\n * value of the selection, or `undefined` if no selection is active),\n * `oldValue` (the previous value of the selection), and `sender` (the\n * `SelectionHandle` instance that made the change).\n */\n\n/**\n * @event SelectionHandle#change\n * @type {object}\n * @property {object} value - The new value of the selection, or `undefined`\n * if no selection is active.\n * @property {object} oldValue - The previous value of the selection.\n * @property {SelectionHandle} sender - The `SelectionHandle` instance that\n * changed the value.\n */\n", + "export function extend(target, ...sources) {\n for (let i = 0; i < sources.length; i++) {\n let src = sources[i];\n if (typeof(src) === \"undefined\" || src === null)\n continue;\n\n for (let key in src) {\n if (src.hasOwnProperty(key)) {\n target[key] = src[key];\n }\n }\n }\n return target;\n}\n\nexport function checkSorted(list) {\n for (let i = 1; i < list.length; i++) {\n if (list[i] <= list[i-1]) {\n throw new Error(\"List is not sorted or contains duplicate\");\n }\n }\n}\n\nexport function diffSortedLists(a, b) {\n let i_a = 0;\n let i_b = 0;\n\n if (!a) a = [];\n if (!b) b = [];\n\n let a_only = [];\n let b_only = [];\n\n checkSorted(a);\n checkSorted(b);\n\n while (i_a < a.length && i_b < b.length) {\n if (a[i_a] === b[i_b]) {\n i_a++;\n i_b++;\n } else if (a[i_a] < b[i_b]) {\n a_only.push(a[i_a++]);\n } else {\n b_only.push(b[i_b++]);\n }\n }\n\n if (i_a < a.length)\n a_only = a_only.concat(a.slice(i_a));\n if (i_b < b.length)\n b_only = b_only.concat(b.slice(i_b));\n return {\n removed: a_only,\n added: b_only\n };\n}\n\n// Convert from wide: { colA: [1,2,3], colB: [4,5,6], ... }\n// to long: [ {colA: 1, colB: 4}, {colA: 2, colB: 5}, ... ]\nexport function dataframeToD3(df) {\n let names = [];\n let length;\n for (let name in df) {\n if (df.hasOwnProperty(name))\n names.push(name);\n if (typeof(df[name]) !== \"object\" || typeof(df[name].length) === \"undefined\") {\n throw new Error(\"All fields must be arrays\");\n } else if (typeof(length) !== \"undefined\" && length !== df[name].length) {\n throw new Error(\"All fields must be arrays of the same length\");\n }\n length = df[name].length;\n }\n let results = [];\n let item;\n for (let row = 0; row < length; row++) {\n item = {};\n for (let col = 0; col < names.length; col++) {\n item[names[col]] = df[names[col]][row];\n }\n results.push(item);\n }\n return results;\n}\n\n/**\n * Keeps track of all event listener additions/removals and lets all active\n * listeners be removed with a single operation.\n *\n * @private\n */\nexport class SubscriptionTracker {\n constructor(emitter) {\n this._emitter = emitter;\n this._subs = {};\n }\n\n on(eventType, listener) {\n let sub = this._emitter.on(eventType, listener);\n this._subs[sub] = eventType;\n return sub;\n }\n\n off(eventType, listener) {\n let sub = this._emitter.off(eventType, listener);\n if (sub) {\n delete this._subs[sub];\n }\n return sub;\n }\n\n removeAllListeners() {\n let current_subs = this._subs;\n this._subs = {};\n Object.keys(current_subs).forEach((sub) => {\n this._emitter.off(current_subs[sub], sub);\n });\n }\n}\n", + "import Events from \"./events\";\n\nexport default class Var {\n constructor(group, name, /*optional*/ value) {\n this._group = group;\n this._name = name;\n this._value = value;\n this._events = new Events();\n }\n\n get() {\n return this._value;\n }\n\n set(value, /*optional*/ event) {\n if (this._value === value) {\n // Do nothing; the value hasn't changed\n return;\n }\n let oldValue = this._value;\n this._value = value;\n // Alert JavaScript listeners that the value has changed\n let evt = {};\n if (event && typeof(event) === \"object\") {\n for (let k in event) {\n if (event.hasOwnProperty(k))\n evt[k] = event[k];\n }\n }\n evt.oldValue = oldValue;\n evt.value = value;\n this._events.trigger(\"change\", evt, this);\n\n // TODO: Make this extensible, to let arbitrary back-ends know that\n // something has changed\n if (global.Shiny && global.Shiny.onInputChange) {\n global.Shiny.onInputChange(\n \".clientValue-\" +\n (this._group.name !== null ? this._group.name + \"-\" : \"\") +\n this._name,\n typeof(value) === \"undefined\" ? null : value\n );\n }\n }\n\n on(eventType, listener) {\n return this._events.on(eventType, listener);\n }\n\n off(eventType, listener) {\n return this._events.off(eventType, listener);\n }\n}\n" + ] +} \ No newline at end of file diff --git a/site_libs/crosstalk-1.2.0/js/crosstalk.min.js.map b/site_libs/crosstalk-1.2.0/js/crosstalk.min.js.map new file mode 100644 index 00000000..886ebeef --- /dev/null +++ b/site_libs/crosstalk-1.2.0/js/crosstalk.min.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["node_modules/browser-pack/_prelude.js","javascript/src/events.js","javascript/src/filter.js","javascript/src/filterset.js","javascript/src/group.js","javascript/src/index.js","javascript/src/input.js","javascript/src/input_checkboxgroup.js","javascript/src/input_selectize.js","javascript/src/input_slider.js","javascript/src/selection.js","javascript/src/util.js","javascript/src/var.js"],"names":["e","t","n","r","s","o","u","a","require","i","f","Error","code","l","exports","call","length","1","module","Events","_classCallCheck","this","_types","_seq","eventType","listener","subs","sub","key","hasOwnProperty","arg","thisObj","util","id","FilterHandle","group","extraInfo","_eventRelay","_events2","default","_emitter","SubscriptionTracker","_group","_filterSet","_filterVar","_varOnChangeSub","_extraInfo","extend","sender","_id","setGroup","fsVar","result","_this","off","clear","_group2","var","get","_filterset2","set","on","trigger","removeAllListeners","_onChange","keys","update","value","_mergeExtraInfo","_util","naturalComparator","b","FilterSet","reset","_handles","_keys","_value","_activeHandles","handleId","slice","sort","_diffSortedLists","diffSortedLists","added","removed","_i","_updateValue","arguments","undefined","_allKeys","handleCount","Object","push","allKeys","groupName","groups","Group","_typeof","_vars","Array","isArray","_var2","global","__crosstalk_groups","name","_var3","_selection","_filter","_input","defaultGroup","var_","Shiny","addCustomMessageHandler","message","crosstalk","has","SelectionHandle","bind","register","reg","bindings","className","document","readyState","$","setTimeout","jQuery","forEach","binding","not","each","el","bindInstance","jsonEl","find","replace","data","JSON","parse","innerText","instance","factory","addClass","inputBinding","InputBinding","_$","scope","initialize","$el","hasClass","getId","getValue","setValue","receiveMessage","subscribe","callback","resume","unsubscribe","suspend","inputBindings","input","ctHandle","lastKnownKeys","checked","map","keyArray","items","dataframeToD3","opts","options","label","concat","valueField","labelField","searchField","select","selectize","strftime","padZeros","digits","str","toString","dataType","timeFormat","round","timeFormatter","utc","prettify","num","Date","timezone","factor","Math","pow","convert","val","date","getUTCFullYear","getUTCMonth","getUTCDate","type","from","to","ionRangeSlider","event","_getValue","_getValue2","_slicedToArray","values","_var","selectedKeys","checkSorted","list","target","_len","sources","_key","src","i_a","i_b","a_only","b_only","df","names","results","item","row","col","emitter","_subs","current_subs","_events","Var","_name","oldValue","evt","k","onInputChange"],"mappings":"CAAA,SAAAA,EAAAC,EAAAC,EAAAC,GAAA,SAAAC,EAAAC,EAAAC,GAAA,IAAAJ,EAAAG,GAAA,CAAA,IAAAJ,EAAAI,GAAA,CAAA,IAAAE,EAAA,mBAAAC,SAAAA,QAAA,IAAAF,GAAAC,EAAA,OAAAA,EAAAF,GAAA,GAAA,GAAAI,EAAA,OAAAA,EAAAJ,GAAA,GAAA,IAAAK,EAAA,IAAAC,MAAA,uBAAAN,EAAA,KAAA,MAAAK,EAAAE,KAAA,mBAAAF,EAAA,IAAAG,EAAAX,EAAAG,IAAAS,YAAAb,EAAAI,GAAA,GAAAU,KAAAF,EAAAC,QAAA,SAAAd,GAAA,IAAAE,EAAAD,EAAAI,GAAA,GAAAL,GAAA,OAAAI,EAAAF,GAAAF,IAAAa,EAAAA,EAAAC,QAAAd,EAAAC,EAAAC,EAAAC,GAAA,OAAAD,EAAAG,GAAAS,QAAA,IAAA,IAAAL,EAAA,mBAAAD,SAAAA,QAAAH,EAAA,EAAAA,EAAAF,EAAAa,OAAAX,IAAAD,EAAAD,EAAAE,IAAA,OAAAD,EAAA,EAAAa,GAAA,SAAAT,EAAAU,EAAAJ,8TCAqBK,aACnB,SAAAA,iGAAcC,CAAAC,KAAAF,GACZE,KAAKC,UACLD,KAAKE,KAAO,uCAGXC,EAAWC,GACZ,IAAIC,EAAOL,KAAKC,OAAOE,GAClBE,IACHA,EAAOL,KAAKC,OAAOE,OAErB,IAAIG,EAAM,MAASN,KAAKE,OAExB,OADAG,EAAKC,GAAOF,EACLE,8BAILH,EAAWC,GACb,IAAIC,EAAOL,KAAKC,OAAOE,GACvB,GAAyB,mBAAdC,EAA0B,CACnC,IAAK,IAAIG,KAAOF,EACd,GAAIA,EAAKG,eAAeD,IAClBF,EAAKE,KAASH,EAEhB,cADOC,EAAKE,GACLA,EAIb,OAAO,EACF,GAAyB,iBAAdH,EAChB,SAAIC,IAAQA,EAAKD,aACRC,EAAKD,GACLA,GAIT,MAAM,IAAId,MAAM,gEAIZa,EAAWM,EAAKC,GACtB,IAAIL,EAAOL,KAAKC,OAAOE,GACvB,IAAK,IAAII,KAAOF,EACVA,EAAKG,eAAeD,IACtBF,EAAKE,GAAKb,KAAKgB,EAASD,sBA5CXX,2WCArBX,EAAA,iBACAA,EAAA,oBACAA,EAAA,YACYwB,4JAAZxB,EAAA,8DAYA,IAAIyB,EAAK,IA6BIC,wBACX,SAAAA,EAAYC,EAAOC,gGAAWhB,CAAAC,KAAAa,GAC5Bb,KAAKgB,YAAc,IAAAC,EAAAC,QACnBlB,KAAKmB,SAAW,IAAIR,EAAKS,oBAAoBpB,KAAKgB,aAGlDhB,KAAKqB,OAAS,KAEdrB,KAAKsB,WAAa,KAElBtB,KAAKuB,WAAa,KAElBvB,KAAKwB,gBAAkB,KAEvBxB,KAAKyB,WAAad,EAAKe,QAASC,OAAQ3B,MAAQe,GAEhDf,KAAK4B,IAAM,SA3CNhB,IA6CLZ,KAAK6B,SAASf,8CAaPA,GAAO,IArEZgB,EACAC,EAoEYC,EAAAhC,KAEd,GAAIA,KAAKqB,SAAWP,KAGfd,KAAKqB,QAAWP,KAGjBd,KAAKuB,aACPvB,KAAKuB,WAAWU,IAAI,SAAUjC,KAAKwB,iBACnCxB,KAAKkC,QACLlC,KAAKwB,gBAAkB,KACvBxB,KAAKuB,WAAa,KAClBvB,KAAKsB,WAAa,MAGpBtB,KAAKqB,OAASP,IAEH,CACTA,GAAQ,EAAAqB,EAAAjB,SAAIJ,GACZd,KAAKsB,YAzFLQ,EAyF+BhB,EAzFjBsB,IAAI,cAClBL,EAASD,EAAMO,SAEjBN,EAAS,IAAAO,EAAApB,QACTY,EAAMS,IAAIR,IAELA,GAoFH/B,KAAKuB,YAAa,EAAAY,EAAAjB,SAAIJ,GAAOsB,IAAI,UACjC,IAAI9B,EAAMN,KAAKuB,WAAWiB,GAAG,SAAU,SAAC7D,GACtCqD,EAAKhB,YAAYyB,QAAQ,SAAU9D,EAAnCqD,KAEFhC,KAAKwB,gBAAkBlB,2CASXS,GACd,OAAOJ,EAAKe,UACV1B,KAAKyB,WAAazB,KAAKyB,WAAa,KACpCV,GAAwB,sCAQ1Bf,KAAKmB,SAASuB,qBACd1C,KAAKkC,QACLlC,KAAK6B,SAAS,oCAYVd,GACCf,KAAKsB,aAEVtB,KAAKsB,WAAWY,MAAMlC,KAAK4B,KAC3B5B,KAAK2C,UAAU5B,gCAoBb6B,EAAM7B,GACHf,KAAKsB,aAEVtB,KAAKsB,WAAWuB,OAAO7C,KAAK4B,IAAKgB,GACjC5C,KAAK2C,UAAU5B,+BAsBdZ,EAAWC,GACZ,OAAOJ,KAAKmB,SAASqB,GAAGrC,EAAWC,+BAWjCD,EAAWC,GACb,OAAOJ,KAAKmB,SAASc,IAAI9B,EAAWC,qCAG5BW,GACHf,KAAKsB,YAEVtB,KAAKuB,WAAWgB,IAAIvC,KAAKsB,WAAWwB,MAAO9C,KAAK+C,gBAAgBhC,yCAhChE,OAAOf,KAAKsB,WAAatB,KAAKsB,WAAWwB,MAAQ,iZC3KrDE,EAAA7D,EAAA,UAEA,SAAS8D,EAAkB/D,EAAGgE,GAC5B,OAAIhE,IAAMgE,EACD,EACEhE,EAAIgE,GACL,EACKA,EAAJhE,EACF,OADF,MAQYiE,aACnB,SAAAA,iGAAcpD,CAAAC,KAAAmD,GACZnD,KAAKoD,kDAKLpD,KAAKqD,YAELrD,KAAKsD,SACLtD,KAAKuD,OAAS,KACdvD,KAAKwD,eAAiB,iCAOjBC,EAAUb,GACF,OAATA,IACFA,EAAOA,EAAKc,MAAM,IACbC,KAAKV,GAHS,IAAAW,GAME,EAAAZ,EAAAa,iBAAgB7D,KAAKqD,SAASI,GAAWb,GAA3DkB,EANgBF,EAMhBE,MAAOC,EANSH,EAMTG,QACZ/D,KAAKqD,SAASI,GAAYb,EAE1B,IAAK,IAAIxD,EAAI,EAAGA,EAAI0E,EAAMnE,OAAQP,IAChCY,KAAKsD,MAAMQ,EAAM1E,KAAOY,KAAKsD,MAAMQ,EAAM1E,KAAO,GAAK,EAEvD,IAAK,IAAI4E,EAAI,EAAGA,EAAID,EAAQpE,OAAQqE,IAClChE,KAAKsD,MAAMS,EAAQC,MAGrBhE,KAAKiE,aAAarB,0CAQe,IAAtBA,EAAsB,EAAAsB,UAAAvE,aAAAwE,IAAAD,UAAA,GAAAA,UAAA,GAAflE,KAAKoE,SACnBC,EAAcC,OAAO1B,KAAK5C,KAAKqD,UAAU1D,OAC7C,GAAoB,IAAhB0E,EACFrE,KAAKuD,OAAS,SACT,CACLvD,KAAKuD,UACL,IAAK,IAAInE,EAAI,EAAGA,EAAIwD,EAAKjD,OAAQP,IAAK,CACxBY,KAAKsD,MAAMV,EAAKxD,MACdiF,GACZrE,KAAKuD,OAAOgB,KAAK3B,EAAKxD,oCAMxBqE,GACJ,QAAwC,IAA7BzD,KAAKqD,SAASI,GAAzB,CAIA,IAAIb,EAAO5C,KAAKqD,SAASI,GACpBb,IACHA,MAGF,IAAK,IAAIxD,EAAI,EAAGA,EAAIwD,EAAKjD,OAAQP,IAC/BY,KAAKsD,MAAMV,EAAKxD,aAEXY,KAAKqD,SAASI,GAErBzD,KAAKiE,8CAzDL,OAAOjE,KAAKuD,wCA6DZ,IAAIiB,EAAUF,OAAO1B,KAAK5C,KAAKsD,OAE/B,OADAkB,EAAQb,KAAKV,GACNuB,qBA9EUrB,+jBCRN,SAASrC,EAAM2D,GAC5B,CAAA,GAAIA,GAAmC,iBAAfA,EAItB,OAHKC,EAAOlE,eAAeiE,KACzBC,EAAOD,GAAa,IAAIE,EAAMF,IAEzBC,EAAOD,GACT,GAA0B,iBAAtB,IAAOA,EAAP,YAAAG,EAAOH,KAA2BA,EAAUI,OAASJ,EAAUrC,IAExE,OAAOqC,EACF,GAAIK,MAAMC,QAAQN,IACD,GAApBA,EAAU9E,QACe,iBAAlB8E,EAAU,GACnB,OAAO3D,EAAM2D,EAAU,IAEvB,MAAM,IAAInF,MAAM,gCArBpB,MAAA0F,EAAA7F,EAAA,6CAIA8F,EAAOC,mBAAqBD,EAAOC,uBACnC,IAAIR,EAASO,EAAOC,uBAoBdP,aACJ,SAAAA,EAAYQ,gGAAMpF,CAAAC,KAAA2E,GAChB3E,KAAKmF,KAAOA,EACZnF,KAAK6E,+CAGHM,GACF,IAAKA,GAAyB,iBAAVA,EAClB,MAAM,IAAI7F,MAAM,oBAKlB,OAFKU,KAAK6E,MAAMrE,eAAe2E,KAC7BnF,KAAK6E,MAAMM,GAAQ,IAAAC,EAAAlE,QAAQlB,KAAMmF,IAC5BnF,KAAK6E,MAAMM,+BAGhBA,GACF,IAAKA,GAAyB,iBAAVA,EAClB,MAAM,IAAI7F,MAAM,oBAGlB,OAAOU,KAAK6E,MAAMrE,eAAe2E,2OC9CrC,MAAA9D,EAAAlC,EAAA,+CACAkG,EAAAlG,EAAA,eACAmG,EAAAnG,EAAA,YACAoG,EAAApG,EAAA,WACAA,EAAA,qBACAA,EAAA,yBACAA,EAAA,kBAEA,IAAMqG,GAAe,EAAArD,EAAAjB,SAAM,WAE3B,SAASuE,EAAKN,GACZ,OAAOK,EAAapD,IAAI+C,GAOtBF,EAAOS,OACTT,EAAOS,MAAMC,wBAAwB,sBAAuB,SAASC,GACrC,iBAAnBA,EAAQ9E,OACjB,EAAAqB,EAAAjB,SAAM0E,EAAQ9E,OAAOsB,IAAIwD,EAAQT,MAAM5C,IAAIqD,EAAQ9C,OAEnD2C,EAAKG,EAAQT,MAAM5C,IAAIqD,EAAQ9C,SAKrC,IAAM+C,GACJ/E,MAAAqB,EAAAjB,QACAkB,IAAKqD,EACLK,IAjBF,SAAaX,GACX,OAAOK,EAAaM,IAAIX,IAiBxBY,gBAAAV,EAAAU,gBACAlF,aAAAyE,EAAAzE,aACAmF,KAAAT,EAAAS,gBAMaH,EACfZ,EAAOY,UAAYA,iVCrCHI,SAAT,SAAkBC,GACvBC,EAASD,EAAIE,WAAaF,EACtBjB,EAAOoB,UAA2C,aAA/BpB,EAAOoB,SAASC,WACrCC,EAAE,WACAP,MAEOf,EAAOoB,UAChBG,WAAWR,EAAM,QAILA,KAAAA,EAfhB,IAAIO,EAAItB,EAAOwB,OAEXN,KAaG,SAASH,IACd1B,OAAO1B,KAAKuD,GAAUO,QAAQ,SAASN,GACrC,IAAIO,EAAUR,EAASC,GACvBG,EAAE,IAAMI,EAAQP,WAAWQ,IAAI,0BAA0BC,KAAK,SAASzH,EAAG0H,GACxEC,EAAaJ,EAASG,OAoB5B,SAASC,EAAaJ,EAASG,GAC7B,IAAIE,EAAST,EAAEO,GAAIG,KAAK,6CAAuDH,EAAGlG,GAdvEsG,QAAQ,wCAAyC,QAc4B,MACpFC,EAAOC,KAAKC,MAAML,EAAO,GAAGM,WAE5BC,EAAWZ,EAAQa,QAAQV,EAAIK,GACnCZ,EAAEO,GAAIK,KAAK,qBAAsBI,GACjChB,EAAEO,GAAIW,SAAS,yBAGjB,GAAIxC,EAAOS,MAAO,CAChB,IAAIgC,EAAe,IAAIzC,EAAOS,MAAMiC,aAChCC,EAAI3C,EAAOwB,OACfmB,EAAElG,OAAOgG,GACPT,KAAM,SAASY,GACb,OAAOD,EAAEC,GAAOZ,KAAK,qBAEvBa,WAAY,SAAShB,GA1BzB,IAAgBA,EACViB,EA0BKH,EAAEd,GAAIkB,SAAS,2BA1BpBD,EAAMxB,EADIO,EA4BDA,GA1BbxC,OAAO1B,KAAKuD,GAAUO,QAAQ,SAASN,GACjC2B,EAAIC,SAAS5B,KAAe2B,EAAIC,SAAS,0BAE3CjB,EADcZ,EAASC,GACDU,OA0BxBmB,MAAO,SAASnB,GACd,OAAOA,EAAGlG,IAEZsH,SAAU,SAASpB,KAGnBqB,SAAU,SAASrB,EAAIhE,KAGvBsF,eAAgB,SAAStB,EAAIK,KAG7BkB,UAAW,SAASvB,EAAIwB,GACtBV,EAAEd,GAAIK,KAAK,sBAAsBoB,UAEnCC,YAAa,SAAS1B,GACpBc,EAAEd,GAAIK,KAAK,sBAAsBsB,aAGrCxD,EAAOS,MAAMgD,cAAczC,SAASyB,EAAc,+LC/EpD,IAAYiB,4JAAZxJ,EAAA,YACAmG,EAAAnG,EAAA,YAEA,IAAIoH,EAAItB,EAAOwB,OAEfkC,EAAM1C,UACJG,UAAW,gCAEXoB,QAAS,SAASV,EAAIK,GAKpB,IAAIyB,EAAW,IAAAtD,EAAAzE,aAAiBsG,EAAKrG,OAEjC+H,OAAA,EACAd,EAAMxB,EAAEO,GAoBZ,OAnBAiB,EAAIvF,GAAG,SAAU,yBAA0B,WACzC,IAAIsG,EAAUf,EAAId,KAAK,kCACvB,GAAuB,IAAnB6B,EAAQnJ,OACVkJ,EAAgB,KAChBD,EAAS1G,YACJ,CACL,IAAIU,KACJkG,EAAQjC,KAAK,WACXM,EAAK4B,IAAI/I,KAAK8C,OAAO4D,QAAQ,SAASnG,GACpCqC,EAAKrC,IAAO,MAGhB,IAAIyI,EAAW1E,OAAO1B,KAAKA,GAC3BoG,EAASrF,OACTkF,EAAgBG,EAChBJ,EAASrG,IAAIyG,OAKfP,QAAS,WACPG,EAAS1G,SAEXqG,OAAQ,WACFM,GACFD,EAASrG,IAAIsG,oMC1CvB,IAAYF,IAAZxJ,EAAA,YACYwB,IAAZxB,EAAA,WACAmG,EAAAnG,EAAA,qKAEA,IAAIoH,EAAItB,EAAOwB,OAEfkC,EAAM1C,UACJG,UAAW,yBAEXoB,QAAS,SAASV,EAAIK,GAOpB,IACI8B,EAAQtI,EAAKuI,cAAc/B,EAAK8B,OAChCE,GACFC,UAHYtG,MAAO,GAAIuG,MAAO,UAGfC,OAAOL,GACtBM,WAAY,QACZC,WAAY,QACZC,YAAa,SAGXC,EAASnD,EAAEO,GAAIG,KAAK,UAAU,GAE9B0C,EAAYpD,EAAEmD,GAAQC,UAAUR,GAAM,GAAGQ,UAEzCf,EAAW,IAAAtD,EAAAzE,aAAiBsG,EAAKrG,OAEjC+H,OAAA,EAmBJ,OAlBAc,EAAUnH,GAAG,SAAU,WACrB,GAA+B,IAA3BmH,EAAUV,MAAMtJ,OAClBkJ,EAAgB,KAChBD,EAAS1G,YACJ,CACL,IAAIU,KACJ+G,EAAUV,MAAMvC,QAAQ,SAAS5F,GAC/BqG,EAAK4B,IAAIjI,GAAO4F,QAAQ,SAASnG,GAC/BqC,EAAKrC,IAAO,MAGhB,IAAIyI,EAAW1E,OAAO1B,KAAKA,GAC3BoG,EAASrF,OACTkF,EAAgBG,EAChBJ,EAASrG,IAAIyG,OAKfP,QAAS,WACPG,EAAS1G,SAEXqG,OAAQ,WACFM,GACFD,EAASrG,IAAIsG,kmBCxDXF,4JAAZxJ,EAAA,YACAmG,EAAAnG,EAAA,YAEA,IAAIoH,EAAItB,EAAOwB,OACXmD,EAAW3E,EAAO2E,SA2HtB,SAASC,EAAShL,EAAGiL,GAEnB,IADA,IAAIC,EAAMlL,EAAEmL,WACLD,EAAIpK,OAASmK,GAClBC,EAAM,IAAMA,EACd,OAAOA,EA7HTpB,EAAM1C,UACJG,UAAW,yBAEXoB,QAAS,SAASV,EAAIK,GAKpB,IAAIyB,EAAW,IAAAtD,EAAAzE,aAAiBsG,EAAKrG,OAEjCqI,KACApB,EAAMxB,EAAEO,GAAIG,KAAK,SACjBgD,EAAWlC,EAAIZ,KAAK,aACpB+C,EAAanC,EAAIZ,KAAK,eACtBgD,EAAQpC,EAAIZ,KAAK,SACjBiD,OAAA,EAGJ,GAAiB,SAAbH,EACFG,EAAgBR,EAASS,MACzBlB,EAAKmB,SAAW,SAASC,GACvB,OAAOH,EAAcF,EAAY,IAAIM,KAAKD,UAGvC,GAAiB,aAAbN,EAAyB,CAClC,IAAIQ,EAAW1C,EAAIZ,KAAK,YAEtBiD,EADEK,EACcb,EAASa,SAASA,GAElBb,EAElBT,EAAKmB,SAAW,SAASC,GACvB,OAAOH,EAAcF,EAAY,IAAIM,KAAKD,SAEtB,WAAbN,QACY,IAAVE,IACThB,EAAKmB,SAAW,SAASC,GACvB,IAAIG,EAASC,KAAKC,IAAI,GAAIT,GAC1B,OAAOQ,KAAKR,MAAMI,EAAMG,GAAUA,IAMxC,SAASxC,IACP,IAAInG,EAASgG,EAAIZ,KAAK,kBAAkBpF,OAGpC8I,OAAA,EACAZ,EAAWlC,EAAIZ,KAAK,aAcxB,OAZE0D,EADe,SAAbZ,EACQ,SAASa,GACjB,OA8EaC,EA9EQ,IAAIP,MAAMM,cA+EnBN,KACXO,EAAKC,iBAAmB,IACxBnB,EAASkB,EAAKE,cAAc,EAAG,GAAK,IACpCpB,EAASkB,EAAKG,aAAc,GAG5B,KAPX,IAAuBH,GA5EO,aAAbd,EACC,SAASa,GAEjB,OAAQA,EAAM,KAGN,SAASA,GAAO,OAAQA,GAGY,WAA5C/C,EAAIZ,KAAK,kBAAkBiC,QAAQ+B,MAC7BN,EAAQ9I,EAAOqJ,MAAOP,EAAQ9I,EAAOsJ,KAEtCR,EAAQ9I,EAAOqJ,MAxB1BrD,EAAIuD,eAAenC,GA4BnB,IAAIN,EAAgB,KAqCpB,OAnCAd,EAAIvF,GAAG,8BAA+B,SAAS+I,GAC7C,IAAKxD,EAAIZ,KAAK,cAAgBY,EAAIZ,KAAK,aAAc,CAGnD,IAHmD,IAAAqE,EAClCtD,IADkCuD,EAAAC,EAAAF,EAAA,GAC9CJ,EAD8CK,EAAA,GACxCJ,EADwCI,EAAA,GAE/C7I,KACKxD,EAAI,EAAGA,EAAI+H,EAAKwE,OAAOhM,OAAQP,IAAK,CAC3C,IAAI0L,EAAM3D,EAAKwE,OAAOvM,GACXgM,GAAPN,GAAeA,GAAOO,GACxBzI,EAAK2B,KAAK4C,EAAKvE,KAAKxD,IAGxBwD,EAAKe,OACLiF,EAASrG,IAAIK,GACbiG,EAAgBjG,MAwBlB6F,QAAS,WACPG,EAAS1G,SAEXqG,OAAQ,WACFM,GACFD,EAASrG,IAAIsG,+fCvHvB1J,EAAA,iBACAA,EAAA,YACYwB,4JAAZxB,EAAA,gEAkBa4G,2BAEX,SAAAA,IAA4C,IAAhCjF,EAAgC,EAAAoD,UAAAvE,aAAAwE,IAAAD,UAAA,GAAAA,UAAA,GAAxB,KAAMnD,EAAkB,EAAAmD,UAAAvE,aAAAwE,IAAAD,UAAA,GAAAA,UAAA,GAAN,kGAAMnE,CAAAC,KAAA+F,GAC1C/F,KAAKgB,YAAc,IAAAC,EAAAC,QACnBlB,KAAKmB,SAAW,IAAIR,EAAKS,oBAAoBpB,KAAKgB,aAGlDhB,KAAKqB,OAAS,KAEdrB,KAAK4L,KAAO,KAEZ5L,KAAKwB,gBAAkB,KAEvBxB,KAAKyB,WAAad,EAAKe,QAASC,OAAQ3B,MAAQe,GAEhDf,KAAK6B,SAASf,8CAgBPA,GAAO,IAAAkB,EAAAhC,KAEd,GAAIA,KAAKqB,SAAWP,IAGfd,KAAKqB,QAAWP,KAGjBd,KAAK4L,OACP5L,KAAK4L,KAAK3J,IAAI,SAAUjC,KAAKwB,iBAC7BxB,KAAK4L,KAAO,KACZ5L,KAAKwB,gBAAkB,MAGzBxB,KAAKqB,OAASP,GAEH,CACTd,KAAK4L,MAAO,EAAAzJ,EAAAjB,SAAIJ,GAAOsB,IAAI,aAC3B,IAAI9B,EAAMN,KAAK4L,KAAKpJ,GAAG,SAAU,SAAC7D,GAChCqD,EAAKhB,YAAYyB,QAAQ,SAAU9D,EAAnCqD,KAEFhC,KAAKwB,gBAAkBlB,2CAuBXS,GAEd,OAAOJ,EAAKe,UACV1B,KAAKyB,WAAazB,KAAKyB,WAAa,KACpCV,GAAwB,kCAexB8K,EAAc9K,GACZf,KAAK4L,MACP5L,KAAK4L,KAAKrJ,IAAIsJ,EAAc7L,KAAK+C,gBAAgBhC,kCAa/CA,GACAf,KAAK4L,MACP5L,KAAKuC,SAAI,EAAQvC,KAAK+C,gBAAgBhC,+BAavCZ,EAAWC,GACZ,OAAOJ,KAAKmB,SAASqB,GAAGrC,EAAWC,+BAWjCD,EAAWC,GACb,OAAOJ,KAAKmB,SAASc,IAAI9B,EAAWC,mCASpCJ,KAAKmB,SAASuB,qBACd1C,KAAK6B,SAAS,oCAhFd,OAAO7B,KAAK4L,KAAO5L,KAAK4L,KAAKvJ,MAAQ,8kBCxElC,SAASyJ,EAAYC,GAC1B,IAAK,IAAI3M,EAAI,EAAGA,EAAI2M,EAAKpM,OAAQP,IAC/B,GAAI2M,EAAK3M,IAAM2M,EAAK3M,EAAE,GACpB,MAAM,IAAIE,MAAM,8CAlBNoC,OAAT,SAAgBsK,GAAoB,IAAA,IAAAC,EAAA/H,UAAAvE,OAATuM,EAASpH,MAAA,EAAAmH,EAAAA,EAAA,EAAA,GAAAE,EAAA,EAAAA,EAAAF,EAAAE,IAATD,EAASC,EAAA,GAAAjI,UAAAiI,GACzC,IAAK,IAAI/M,EAAI,EAAGA,EAAI8M,EAAQvM,OAAQP,IAAK,CACvC,IAAIgN,EAAMF,EAAQ9M,GAClB,GAAI,MAAOgN,EAGX,IAAK,IAAI7L,KAAO6L,EACVA,EAAI5L,eAAeD,KACrByL,EAAOzL,GAAO6L,EAAI7L,IAIxB,OAAOyL,KAGOF,YAAAA,IAQAjI,gBAAT,SAAyB3E,EAAGgE,GACjC,IAAImJ,EAAM,EACNC,EAAM,EAELpN,IAAGA,MACHgE,IAAGA,MAER,IAAIqJ,KACAC,KAEJV,EAAY5M,GACZ4M,EAAY5I,GAEZ,KAAOmJ,EAAMnN,EAAES,QAAU2M,EAAMpJ,EAAEvD,QAC3BT,EAAEmN,KAASnJ,EAAEoJ,IACfD,IACAC,KACSpN,EAAEmN,GAAOnJ,EAAEoJ,GACpBC,EAAOhI,KAAKrF,EAAEmN,MAEdG,EAAOjI,KAAKrB,EAAEoJ,MAIdD,EAAMnN,EAAES,SACV4M,EAASA,EAAOjD,OAAOpK,EAAEwE,MAAM2I,KAC7BC,EAAMpJ,EAAEvD,SACV6M,EAASA,EAAOlD,OAAOpG,EAAEQ,MAAM4I,KACjC,OACEvI,QAASwI,EACTzI,MAAO0I,MAMKtD,cAAT,SAAuBuD,GAC5B,IAAIC,KACA/M,OAAA,EACJ,IAAK,IAAIwF,KAAQsH,EAAI,CAGnB,GAFIA,EAAGjM,eAAe2E,IACpBuH,EAAMnI,KAAKY,GACY,WAArBP,EAAO6H,EAAGtH,UAAmD,IAArBsH,EAAGtH,GAAMxF,OACnD,MAAM,IAAIL,MAAM,6BACX,QAAuB,IAAZK,GAA2BA,IAAW8M,EAAGtH,GAAMxF,OAC/D,MAAM,IAAIL,MAAM,gDAElBK,EAAS8M,EAAGtH,GAAMxF,OAIpB,IAFA,IAAIgN,KACAC,OAAA,EACKC,EAAM,EAAGA,EAAMlN,EAAQkN,IAAO,CACrCD,KACA,IAAK,IAAIE,EAAM,EAAGA,EAAMJ,EAAM/M,OAAQmN,IACpCF,EAAKF,EAAMI,IAAQL,EAAGC,EAAMI,IAAMD,GAEpCF,EAAQpI,KAAKqI,GAEf,OAAOD,KASIvL,+BACX,SAAAA,EAAY2L,gGAAShN,CAAAC,KAAAoB,GACnBpB,KAAKmB,SAAW4L,EAChB/M,KAAKgN,8CAGJ7M,EAAWC,GACZ,IAAIE,EAAMN,KAAKmB,SAASqB,GAAGrC,EAAWC,GAEtC,OADAJ,KAAKgN,MAAM1M,GAAOH,EACXG,8BAGLH,EAAWC,GACb,IAAIE,EAAMN,KAAKmB,SAASc,IAAI9B,EAAWC,GAIvC,OAHIE,UACKN,KAAKgN,MAAM1M,GAEbA,+CAGY,IAAA0B,EAAAhC,KACfiN,EAAejN,KAAKgN,MACxBhN,KAAKgN,SACL1I,OAAO1B,KAAKqK,GAAcvG,QAAQ,SAACpG,GACjC0B,EAAKb,SAASc,IAAIgL,EAAa3M,GAAMA,yjBClH3C4M,EAAA/N,EAAA,oDAEqBgO,aACnB,SAAAA,EAAYrM,EAAOqE,EAAmBrC,gGAAO/C,CAAAC,KAAAmN,GAC3CnN,KAAKqB,OAASP,EACdd,KAAKoN,MAAQjI,EACbnF,KAAKuD,OAAST,EACd9C,KAAKkN,QAAU,IAAAjM,EAAAC,gDAIf,OAAOlB,KAAKuD,mCAGVT,EAAoByI,GACtB,GAAIvL,KAAKuD,SAAWT,EAApB,CAIA,IAAIuK,EAAWrN,KAAKuD,OACpBvD,KAAKuD,OAAST,EAEd,IAAIwK,KACJ,GAAI/B,GAA2B,iBAAlB,IAAOA,EAAP,YAAA3G,EAAO2G,IAClB,IAAK,IAAIgC,KAAKhC,EACRA,EAAM/K,eAAe+M,KACvBD,EAAIC,GAAKhC,EAAMgC,IAGrBD,EAAID,SAAWA,EACfC,EAAIxK,MAAQA,EACZ9C,KAAKkN,QAAQzK,QAAQ,SAAU6K,EAAKtN,MAIhCiF,EAAOS,OAAST,EAAOS,MAAM8H,eAC/BvI,EAAOS,MAAM8H,cACX,iBACwB,OAArBxN,KAAKqB,OAAO8D,KAAgBnF,KAAKqB,OAAO8D,KAAO,IAAM,IACtDnF,KAAKoN,WACW,IAAXtK,EAAyB,KAAOA,+BAK1C3C,EAAWC,GACZ,OAAOJ,KAAKkN,QAAQ1K,GAAGrC,EAAWC,+BAGhCD,EAAWC,GACb,OAAOJ,KAAKkN,QAAQjL,IAAI9B,EAAWC,sBAhDlB+M","file":"crosstalk.min.js","sourcesContent":["(function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o {\n this._eventRelay.trigger(\"change\", e, this);\n });\n this._varOnChangeSub = sub;\n }\n }\n\n /**\n * Combine the given `extraInfo` (if any) with the handle's default\n * `_extraInfo` (if any).\n * @private\n */\n _mergeExtraInfo(extraInfo) {\n return util.extend({},\n this._extraInfo ? this._extraInfo : null,\n extraInfo ? extraInfo : null);\n }\n\n /**\n * Close the handle. This clears this handle's contribution to the filter set,\n * and unsubscribes all event listeners.\n */\n close() {\n this._emitter.removeAllListeners();\n this.clear();\n this.setGroup(null);\n }\n\n /**\n * Clear this handle's contribution to the filter set.\n *\n * @param {Object} [extraInfo] - Extra properties to be included on the event\n * object that's passed to listeners (in addition to any options that were\n * passed into the `FilterHandle` constructor).\n * \n * @fires FilterHandle#change\n */\n clear(extraInfo) {\n if (!this._filterSet)\n return;\n this._filterSet.clear(this._id);\n this._onChange(extraInfo);\n }\n\n /**\n * Set this handle's contribution to the filter set. This array should consist\n * of the keys of the rows that _should_ be displayed; any keys that are not\n * present in the array will be considered _filtered out_. Note that multiple\n * `FilterHandle` instances in the group may each contribute an array of keys,\n * and only those keys that appear in _all_ of the arrays make it through the\n * filter.\n *\n * @param {string[]} keys - Empty array, or array of keys. To clear the\n * filter, don't pass an empty array; instead, use the\n * {@link FilterHandle#clear} method.\n * @param {Object} [extraInfo] - Extra properties to be included on the event\n * object that's passed to listeners (in addition to any options that were\n * passed into the `FilterHandle` constructor).\n * \n * @fires FilterHandle#change\n */\n set(keys, extraInfo) {\n if (!this._filterSet)\n return;\n this._filterSet.update(this._id, keys);\n this._onChange(extraInfo);\n }\n\n /**\n * @return {string[]|null} - Either: 1) an array of keys that made it through\n * all of the `FilterHandle` instances, or, 2) `null`, which means no filter\n * is being applied (all data should be displayed).\n */\n get filteredKeys() {\n return this._filterSet ? this._filterSet.value : null;\n }\n\n /**\n * Subscribe to events on this `FilterHandle`.\n *\n * @param {string} eventType - Indicates the type of events to listen to.\n * Currently, only `\"change\"` is supported.\n * @param {FilterHandle~listener} listener - The callback function that\n * will be invoked when the event occurs.\n * @return {string} - A token to pass to {@link FilterHandle#off} to cancel\n * this subscription.\n */\n on(eventType, listener) {\n return this._emitter.on(eventType, listener);\n }\n\n /**\n * Cancel event subscriptions created by {@link FilterHandle#on}.\n *\n * @param {string} eventType - The type of event to unsubscribe.\n * @param {string|FilterHandle~listener} listener - Either the callback\n * function previously passed into {@link FilterHandle#on}, or the\n * string that was returned from {@link FilterHandle#on}.\n */\n off(eventType, listener) {\n return this._emitter.off(eventType, listener);\n }\n\n _onChange(extraInfo) {\n if (!this._filterSet)\n return;\n this._filterVar.set(this._filterSet.value, this._mergeExtraInfo(extraInfo));\n }\n\n /**\n * @callback FilterHandle~listener\n * @param {Object} event - An object containing details of the event. For\n * `\"change\"` events, this includes the properties `value` (the new\n * value of the filter set, or `null` if no filter set is active),\n * `oldValue` (the previous value of the filter set), and `sender` (the\n * `FilterHandle` instance that made the change).\n */\n\n}\n\n/**\n * @event FilterHandle#change\n * @type {object}\n * @property {object} value - The new value of the filter set, or `null`\n * if no filter set is active.\n * @property {object} oldValue - The previous value of the filter set.\n * @property {FilterHandle} sender - The `FilterHandle` instance that\n * changed the value.\n */\n","import { diffSortedLists } from \"./util\";\n\nfunction naturalComparator(a, b) {\n if (a === b) {\n return 0;\n } else if (a < b) {\n return -1;\n } else if (a > b) {\n return 1;\n }\n}\n\n/**\n * @private\n */\nexport default class FilterSet {\n constructor() {\n this.reset();\n }\n\n reset() {\n // Key: handle ID, Value: array of selected keys, or null\n this._handles = {};\n // Key: key string, Value: count of handles that include it\n this._keys = {};\n this._value = null;\n this._activeHandles = 0;\n }\n\n get value() {\n return this._value;\n }\n\n update(handleId, keys) {\n if (keys !== null) {\n keys = keys.slice(0); // clone before sorting\n keys.sort(naturalComparator);\n }\n\n let {added, removed} = diffSortedLists(this._handles[handleId], keys);\n this._handles[handleId] = keys;\n\n for (let i = 0; i < added.length; i++) {\n this._keys[added[i]] = (this._keys[added[i]] || 0) + 1;\n }\n for (let i = 0; i < removed.length; i++) {\n this._keys[removed[i]]--;\n }\n\n this._updateValue(keys);\n }\n\n /**\n * @param {string[]} keys Sorted array of strings that indicate\n * a superset of possible keys.\n * @private\n */\n _updateValue(keys = this._allKeys) {\n let handleCount = Object.keys(this._handles).length;\n if (handleCount === 0) {\n this._value = null;\n } else {\n this._value = [];\n for (let i = 0; i < keys.length; i++) {\n let count = this._keys[keys[i]];\n if (count === handleCount) {\n this._value.push(keys[i]);\n }\n }\n }\n }\n\n clear(handleId) {\n if (typeof(this._handles[handleId]) === \"undefined\") {\n return;\n }\n\n let keys = this._handles[handleId];\n if (!keys) {\n keys = [];\n }\n\n for (let i = 0; i < keys.length; i++) {\n this._keys[keys[i]]--;\n }\n delete this._handles[handleId];\n\n this._updateValue();\n }\n\n get _allKeys() {\n let allKeys = Object.keys(this._keys);\n allKeys.sort(naturalComparator);\n return allKeys;\n }\n}\n","import Var from \"./var\";\n\n// Use a global so that multiple copies of crosstalk.js can be loaded and still\n// have groups behave as singletons across all copies.\nglobal.__crosstalk_groups = global.__crosstalk_groups || {};\nlet groups = global.__crosstalk_groups;\n\nexport default function group(groupName) {\n if (groupName && typeof(groupName) === \"string\") {\n if (!groups.hasOwnProperty(groupName)) {\n groups[groupName] = new Group(groupName);\n }\n return groups[groupName];\n } else if (typeof(groupName) === \"object\" && groupName._vars && groupName.var) {\n // Appears to already be a group object\n return groupName;\n } else if (Array.isArray(groupName) &&\n groupName.length == 1 &&\n typeof(groupName[0]) === \"string\") {\n return group(groupName[0]);\n } else {\n throw new Error(\"Invalid groupName argument\");\n }\n}\n\nclass Group {\n constructor(name) {\n this.name = name;\n this._vars = {};\n }\n\n var(name) {\n if (!name || typeof(name) !== \"string\") {\n throw new Error(\"Invalid var name\");\n }\n\n if (!this._vars.hasOwnProperty(name))\n this._vars[name] = new Var(this, name);\n return this._vars[name];\n }\n\n has(name) {\n if (!name || typeof(name) !== \"string\") {\n throw new Error(\"Invalid var name\");\n }\n\n return this._vars.hasOwnProperty(name);\n }\n}\n","import group from \"./group\";\nimport { SelectionHandle } from \"./selection\";\nimport { FilterHandle } from \"./filter\";\nimport { bind } from \"./input\";\nimport \"./input_selectize\";\nimport \"./input_checkboxgroup\";\nimport \"./input_slider\";\n\nconst defaultGroup = group(\"default\");\n\nfunction var_(name) {\n return defaultGroup.var(name);\n}\n\nfunction has(name) {\n return defaultGroup.has(name);\n}\n\nif (global.Shiny) {\n global.Shiny.addCustomMessageHandler(\"update-client-value\", function(message) {\n if (typeof(message.group) === \"string\") {\n group(message.group).var(message.name).set(message.value);\n } else {\n var_(message.name).set(message.value);\n }\n });\n}\n\nconst crosstalk = {\n group: group,\n var: var_,\n has: has,\n SelectionHandle: SelectionHandle,\n FilterHandle: FilterHandle,\n bind: bind\n};\n\n/**\n * @namespace crosstalk\n */\nexport default crosstalk;\nglobal.crosstalk = crosstalk;\n","let $ = global.jQuery;\n\nlet bindings = {};\n\nexport function register(reg) {\n bindings[reg.className] = reg;\n if (global.document && global.document.readyState !== \"complete\") {\n $(() => {\n bind();\n });\n } else if (global.document) {\n setTimeout(bind, 100);\n }\n}\n\nexport function bind() {\n Object.keys(bindings).forEach(function(className) {\n let binding = bindings[className];\n $(\".\" + binding.className).not(\".crosstalk-input-bound\").each(function(i, el) {\n bindInstance(binding, el);\n });\n });\n}\n\n// Escape jQuery identifier\nfunction $escape(val) {\n return val.replace(/([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^`{|}~])/g, \"\\\\$1\");\n}\n\nfunction bindEl(el) {\n let $el = $(el);\n Object.keys(bindings).forEach(function(className) {\n if ($el.hasClass(className) && !$el.hasClass(\"crosstalk-input-bound\")) {\n let binding = bindings[className];\n bindInstance(binding, el);\n }\n });\n}\n\nfunction bindInstance(binding, el) {\n let jsonEl = $(el).find(\"script[type='application/json'][data-for='\" + $escape(el.id) + \"']\");\n let data = JSON.parse(jsonEl[0].innerText);\n\n let instance = binding.factory(el, data);\n $(el).data(\"crosstalk-instance\", instance);\n $(el).addClass(\"crosstalk-input-bound\");\n}\n\nif (global.Shiny) {\n let inputBinding = new global.Shiny.InputBinding();\n let $ = global.jQuery;\n $.extend(inputBinding, {\n find: function(scope) {\n return $(scope).find(\".crosstalk-input\");\n },\n initialize: function(el) {\n if (!$(el).hasClass(\"crosstalk-input-bound\")) {\n bindEl(el);\n }\n },\n getId: function(el) {\n return el.id;\n },\n getValue: function(el) {\n\n },\n setValue: function(el, value) {\n\n },\n receiveMessage: function(el, data) {\n\n },\n subscribe: function(el, callback) {\n $(el).data(\"crosstalk-instance\").resume();\n },\n unsubscribe: function(el) {\n $(el).data(\"crosstalk-instance\").suspend();\n }\n });\n global.Shiny.inputBindings.register(inputBinding, \"crosstalk.inputBinding\");\n}\n","import * as input from \"./input\";\nimport { FilterHandle } from \"./filter\";\n\nlet $ = global.jQuery;\n\ninput.register({\n className: \"crosstalk-input-checkboxgroup\",\n\n factory: function(el, data) {\n /*\n * map: {\"groupA\": [\"keyA\", \"keyB\", ...], ...}\n * group: \"ct-groupname\"\n */\n let ctHandle = new FilterHandle(data.group);\n\n let lastKnownKeys;\n let $el = $(el);\n $el.on(\"change\", \"input[type='checkbox']\", function() {\n let checked = $el.find(\"input[type='checkbox']:checked\");\n if (checked.length === 0) {\n lastKnownKeys = null;\n ctHandle.clear();\n } else {\n let keys = {};\n checked.each(function() {\n data.map[this.value].forEach(function(key) {\n keys[key] = true;\n });\n });\n let keyArray = Object.keys(keys);\n keyArray.sort();\n lastKnownKeys = keyArray;\n ctHandle.set(keyArray);\n }\n });\n\n return {\n suspend: function() {\n ctHandle.clear();\n },\n resume: function() {\n if (lastKnownKeys)\n ctHandle.set(lastKnownKeys);\n }\n };\n }\n});\n","import * as input from \"./input\";\nimport * as util from \"./util\";\nimport { FilterHandle } from \"./filter\";\n\nlet $ = global.jQuery;\n\ninput.register({\n className: \"crosstalk-input-select\",\n\n factory: function(el, data) {\n /*\n * items: {value: [...], label: [...]}\n * map: {\"groupA\": [\"keyA\", \"keyB\", ...], ...}\n * group: \"ct-groupname\"\n */\n\n let first = [{value: \"\", label: \"(All)\"}];\n let items = util.dataframeToD3(data.items);\n let opts = {\n options: first.concat(items),\n valueField: \"value\",\n labelField: \"label\",\n searchField: \"label\"\n };\n\n let select = $(el).find(\"select\")[0];\n\n let selectize = $(select).selectize(opts)[0].selectize;\n\n let ctHandle = new FilterHandle(data.group);\n\n let lastKnownKeys;\n selectize.on(\"change\", function() {\n if (selectize.items.length === 0) {\n lastKnownKeys = null;\n ctHandle.clear();\n } else {\n let keys = {};\n selectize.items.forEach(function(group) {\n data.map[group].forEach(function(key) {\n keys[key] = true;\n });\n });\n let keyArray = Object.keys(keys);\n keyArray.sort();\n lastKnownKeys = keyArray;\n ctHandle.set(keyArray);\n }\n });\n\n return {\n suspend: function() {\n ctHandle.clear();\n },\n resume: function() {\n if (lastKnownKeys)\n ctHandle.set(lastKnownKeys);\n }\n };\n }\n});\n","import * as input from \"./input\";\nimport { FilterHandle } from \"./filter\";\n\nlet $ = global.jQuery;\nlet strftime = global.strftime;\n\ninput.register({\n className: \"crosstalk-input-slider\",\n\n factory: function(el, data) {\n /*\n * map: {\"groupA\": [\"keyA\", \"keyB\", ...], ...}\n * group: \"ct-groupname\"\n */\n let ctHandle = new FilterHandle(data.group);\n\n let opts = {};\n let $el = $(el).find(\"input\");\n let dataType = $el.data(\"data-type\");\n let timeFormat = $el.data(\"time-format\");\n let round = $el.data(\"round\");\n let timeFormatter;\n\n // Set up formatting functions\n if (dataType === \"date\") {\n timeFormatter = strftime.utc();\n opts.prettify = function(num) {\n return timeFormatter(timeFormat, new Date(num));\n };\n\n } else if (dataType === \"datetime\") {\n let timezone = $el.data(\"timezone\");\n if (timezone)\n timeFormatter = strftime.timezone(timezone);\n else\n timeFormatter = strftime;\n\n opts.prettify = function(num) {\n return timeFormatter(timeFormat, new Date(num));\n };\n } else if (dataType === \"number\") {\n if (typeof round !== \"undefined\")\n opts.prettify = function(num) {\n let factor = Math.pow(10, round);\n return Math.round(num * factor) / factor;\n };\n }\n\n $el.ionRangeSlider(opts);\n\n function getValue() {\n let result = $el.data(\"ionRangeSlider\").result;\n\n // Function for converting numeric value from slider to appropriate type.\n let convert;\n let dataType = $el.data(\"data-type\");\n if (dataType === \"date\") {\n convert = function(val) {\n return formatDateUTC(new Date(+val));\n };\n } else if (dataType === \"datetime\") {\n convert = function(val) {\n // Convert ms to s\n return +val / 1000;\n };\n } else {\n convert = function(val) { return +val; };\n }\n\n if ($el.data(\"ionRangeSlider\").options.type === \"double\") {\n return [convert(result.from), convert(result.to)];\n } else {\n return convert(result.from);\n }\n }\n\n let lastKnownKeys = null;\n\n $el.on(\"change.crosstalkSliderInput\", function(event) {\n if (!$el.data(\"updating\") && !$el.data(\"animating\")) {\n let [from, to] = getValue();\n let keys = [];\n for (let i = 0; i < data.values.length; i++) {\n let val = data.values[i];\n if (val >= from && val <= to) {\n keys.push(data.keys[i]);\n }\n }\n keys.sort();\n ctHandle.set(keys);\n lastKnownKeys = keys;\n }\n });\n\n\n // let $el = $(el);\n // $el.on(\"change\", \"input[type=\"checkbox\"]\", function() {\n // let checked = $el.find(\"input[type=\"checkbox\"]:checked\");\n // if (checked.length === 0) {\n // ctHandle.clear();\n // } else {\n // let keys = {};\n // checked.each(function() {\n // data.map[this.value].forEach(function(key) {\n // keys[key] = true;\n // });\n // });\n // let keyArray = Object.keys(keys);\n // keyArray.sort();\n // ctHandle.set(keyArray);\n // }\n // });\n\n return {\n suspend: function() {\n ctHandle.clear();\n },\n resume: function() {\n if (lastKnownKeys)\n ctHandle.set(lastKnownKeys);\n }\n };\n }\n});\n\n\n// Convert a number to a string with leading zeros\nfunction padZeros(n, digits) {\n let str = n.toString();\n while (str.length < digits)\n str = \"0\" + str;\n return str;\n}\n\n// Given a Date object, return a string in yyyy-mm-dd format, using the\n// UTC date. This may be a day off from the date in the local time zone.\nfunction formatDateUTC(date) {\n if (date instanceof Date) {\n return date.getUTCFullYear() + \"-\" +\n padZeros(date.getUTCMonth()+1, 2) + \"-\" +\n padZeros(date.getUTCDate(), 2);\n\n } else {\n return null;\n }\n}\n","import Events from \"./events\";\nimport grp from \"./group\";\nimport * as util from \"./util\";\n\n/**\n * Use this class to read and write (and listen for changes to) the selection\n * for a Crosstalk group. This is intended to be used for linked brushing.\n *\n * If two (or more) `SelectionHandle` instances in the same webpage share the\n * same group name, they will share the same state. Setting the selection using\n * one `SelectionHandle` instance will result in the `value` property instantly\n * changing across the others, and `\"change\"` event listeners on all instances\n * (including the one that initiated the sending) will fire.\n *\n * @param {string} [group] - The name of the Crosstalk group, or if none,\n * null or undefined (or any other falsy value). This can be changed later\n * via the [SelectionHandle#setGroup](#setGroup) method.\n * @param {Object} [extraInfo] - An object whose properties will be copied to\n * the event object whenever an event is emitted.\n */\nexport class SelectionHandle {\n\n constructor(group = null, extraInfo = null) {\n this._eventRelay = new Events();\n this._emitter = new util.SubscriptionTracker(this._eventRelay);\n\n // Name of the group we're currently tracking, if any. Can change over time.\n this._group = null;\n // The Var we're currently tracking, if any. Can change over time.\n this._var = null;\n // The event handler subscription we currently have on var.on(\"change\").\n this._varOnChangeSub = null;\n\n this._extraInfo = util.extend({ sender: this }, extraInfo);\n\n this.setGroup(group);\n }\n\n /**\n * Changes the Crosstalk group membership of this SelectionHandle. The group\n * being switched away from (if any) will not have its selection value\n * modified as a result of calling `setGroup`, even if this handle was the\n * most recent handle to set the selection of the group.\n *\n * The group being switched to (if any) will also not have its selection value\n * modified as a result of calling `setGroup`. If you want to set the\n * selection value of the new group, call `set` explicitly.\n *\n * @param {string} group - The name of the Crosstalk group, or null (or\n * undefined) to clear the group.\n */\n setGroup(group) {\n // If group is unchanged, do nothing\n if (this._group === group)\n return;\n // Treat null, undefined, and other falsy values the same\n if (!this._group && !group)\n return;\n\n if (this._var) {\n this._var.off(\"change\", this._varOnChangeSub);\n this._var = null;\n this._varOnChangeSub = null;\n }\n\n this._group = group;\n\n if (group) {\n this._var = grp(group).var(\"selection\");\n let sub = this._var.on(\"change\", (e) => {\n this._eventRelay.trigger(\"change\", e, this);\n });\n this._varOnChangeSub = sub;\n }\n }\n\n /**\n * Retrieves the current selection for the group represented by this\n * `SelectionHandle`.\n *\n * - If no selection is active, then this value will be falsy.\n * - If a selection is active, but no data points are selected, then this\n * value will be an empty array.\n * - If a selection is active, and data points are selected, then the keys\n * of the selected data points will be present in the array.\n */\n get value() {\n return this._var ? this._var.get() : null;\n }\n\n /**\n * Combines the given `extraInfo` (if any) with the handle's default\n * `_extraInfo` (if any).\n * @private\n */\n _mergeExtraInfo(extraInfo) {\n // Important incidental effect: shallow clone is returned\n return util.extend({},\n this._extraInfo ? this._extraInfo : null,\n extraInfo ? extraInfo : null);\n }\n\n /**\n * Overwrites the current selection for the group, and raises the `\"change\"`\n * event among all of the group's '`SelectionHandle` instances (including\n * this one).\n *\n * @fires SelectionHandle#change\n * @param {string[]} selectedKeys - Falsy, empty array, or array of keys (see\n * {@link SelectionHandle#value}).\n * @param {Object} [extraInfo] - Extra properties to be included on the event\n * object that's passed to listeners (in addition to any options that were\n * passed into the `SelectionHandle` constructor).\n */\n set(selectedKeys, extraInfo) {\n if (this._var)\n this._var.set(selectedKeys, this._mergeExtraInfo(extraInfo));\n }\n\n /**\n * Overwrites the current selection for the group, and raises the `\"change\"`\n * event among all of the group's '`SelectionHandle` instances (including\n * this one).\n *\n * @fires SelectionHandle#change\n * @param {Object} [extraInfo] - Extra properties to be included on the event\n * object that's passed to listeners (in addition to any that were passed\n * into the `SelectionHandle` constructor).\n */\n clear(extraInfo) {\n if (this._var)\n this.set(void 0, this._mergeExtraInfo(extraInfo));\n }\n\n /**\n * Subscribes to events on this `SelectionHandle`.\n *\n * @param {string} eventType - Indicates the type of events to listen to.\n * Currently, only `\"change\"` is supported.\n * @param {SelectionHandle~listener} listener - The callback function that\n * will be invoked when the event occurs.\n * @return {string} - A token to pass to {@link SelectionHandle#off} to cancel\n * this subscription.\n */\n on(eventType, listener) {\n return this._emitter.on(eventType, listener);\n }\n\n /**\n * Cancels event subscriptions created by {@link SelectionHandle#on}.\n *\n * @param {string} eventType - The type of event to unsubscribe.\n * @param {string|SelectionHandle~listener} listener - Either the callback\n * function previously passed into {@link SelectionHandle#on}, or the\n * string that was returned from {@link SelectionHandle#on}.\n */\n off(eventType, listener) {\n return this._emitter.off(eventType, listener);\n }\n\n /**\n * Shuts down the `SelectionHandle` object.\n *\n * Removes all event listeners that were added through this handle.\n */\n close() {\n this._emitter.removeAllListeners();\n this.setGroup(null);\n }\n}\n\n/**\n * @callback SelectionHandle~listener\n * @param {Object} event - An object containing details of the event. For\n * `\"change\"` events, this includes the properties `value` (the new\n * value of the selection, or `undefined` if no selection is active),\n * `oldValue` (the previous value of the selection), and `sender` (the\n * `SelectionHandle` instance that made the change).\n */\n\n/**\n * @event SelectionHandle#change\n * @type {object}\n * @property {object} value - The new value of the selection, or `undefined`\n * if no selection is active.\n * @property {object} oldValue - The previous value of the selection.\n * @property {SelectionHandle} sender - The `SelectionHandle` instance that\n * changed the value.\n */\n","export function extend(target, ...sources) {\n for (let i = 0; i < sources.length; i++) {\n let src = sources[i];\n if (typeof(src) === \"undefined\" || src === null)\n continue;\n\n for (let key in src) {\n if (src.hasOwnProperty(key)) {\n target[key] = src[key];\n }\n }\n }\n return target;\n}\n\nexport function checkSorted(list) {\n for (let i = 1; i < list.length; i++) {\n if (list[i] <= list[i-1]) {\n throw new Error(\"List is not sorted or contains duplicate\");\n }\n }\n}\n\nexport function diffSortedLists(a, b) {\n let i_a = 0;\n let i_b = 0;\n\n if (!a) a = [];\n if (!b) b = [];\n\n let a_only = [];\n let b_only = [];\n\n checkSorted(a);\n checkSorted(b);\n\n while (i_a < a.length && i_b < b.length) {\n if (a[i_a] === b[i_b]) {\n i_a++;\n i_b++;\n } else if (a[i_a] < b[i_b]) {\n a_only.push(a[i_a++]);\n } else {\n b_only.push(b[i_b++]);\n }\n }\n\n if (i_a < a.length)\n a_only = a_only.concat(a.slice(i_a));\n if (i_b < b.length)\n b_only = b_only.concat(b.slice(i_b));\n return {\n removed: a_only,\n added: b_only\n };\n}\n\n// Convert from wide: { colA: [1,2,3], colB: [4,5,6], ... }\n// to long: [ {colA: 1, colB: 4}, {colA: 2, colB: 5}, ... ]\nexport function dataframeToD3(df) {\n let names = [];\n let length;\n for (let name in df) {\n if (df.hasOwnProperty(name))\n names.push(name);\n if (typeof(df[name]) !== \"object\" || typeof(df[name].length) === \"undefined\") {\n throw new Error(\"All fields must be arrays\");\n } else if (typeof(length) !== \"undefined\" && length !== df[name].length) {\n throw new Error(\"All fields must be arrays of the same length\");\n }\n length = df[name].length;\n }\n let results = [];\n let item;\n for (let row = 0; row < length; row++) {\n item = {};\n for (let col = 0; col < names.length; col++) {\n item[names[col]] = df[names[col]][row];\n }\n results.push(item);\n }\n return results;\n}\n\n/**\n * Keeps track of all event listener additions/removals and lets all active\n * listeners be removed with a single operation.\n *\n * @private\n */\nexport class SubscriptionTracker {\n constructor(emitter) {\n this._emitter = emitter;\n this._subs = {};\n }\n\n on(eventType, listener) {\n let sub = this._emitter.on(eventType, listener);\n this._subs[sub] = eventType;\n return sub;\n }\n\n off(eventType, listener) {\n let sub = this._emitter.off(eventType, listener);\n if (sub) {\n delete this._subs[sub];\n }\n return sub;\n }\n\n removeAllListeners() {\n let current_subs = this._subs;\n this._subs = {};\n Object.keys(current_subs).forEach((sub) => {\n this._emitter.off(current_subs[sub], sub);\n });\n }\n}\n","import Events from \"./events\";\n\nexport default class Var {\n constructor(group, name, /*optional*/ value) {\n this._group = group;\n this._name = name;\n this._value = value;\n this._events = new Events();\n }\n\n get() {\n return this._value;\n }\n\n set(value, /*optional*/ event) {\n if (this._value === value) {\n // Do nothing; the value hasn't changed\n return;\n }\n let oldValue = this._value;\n this._value = value;\n // Alert JavaScript listeners that the value has changed\n let evt = {};\n if (event && typeof(event) === \"object\") {\n for (let k in event) {\n if (event.hasOwnProperty(k))\n evt[k] = event[k];\n }\n }\n evt.oldValue = oldValue;\n evt.value = value;\n this._events.trigger(\"change\", evt, this);\n\n // TODO: Make this extensible, to let arbitrary back-ends know that\n // something has changed\n if (global.Shiny && global.Shiny.onInputChange) {\n global.Shiny.onInputChange(\n \".clientValue-\" +\n (this._group.name !== null ? this._group.name + \"-\" : \"\") +\n this._name,\n typeof(value) === \"undefined\" ? null : value\n );\n }\n }\n\n on(eventType, listener) {\n return this._events.on(eventType, listener);\n }\n\n off(eventType, listener) {\n return this._events.off(eventType, listener);\n }\n}\n"]} \ No newline at end of file diff --git a/site_libs/crosstalk-1.2.0/scss/crosstalk.scss b/site_libs/crosstalk-1.2.0/scss/crosstalk.scss new file mode 100644 index 00000000..35665616 --- /dev/null +++ b/site_libs/crosstalk-1.2.0/scss/crosstalk.scss @@ -0,0 +1,75 @@ +/* Adjust margins outwards, so column contents line up with the edges of the + parent of container-fluid. */ +.container-fluid.crosstalk-bscols { + margin-left: -30px; + margin-right: -30px; + white-space: normal; +} + +/* But don't adjust the margins outwards if we're directly under the body, + i.e. we were the top-level of something at the console. */ +body > .container-fluid.crosstalk-bscols { + margin-left: auto; + margin-right: auto; +} + +.crosstalk-input-checkboxgroup .crosstalk-options-group .crosstalk-options-column { + display: inline-block; + padding-right: 12px; + vertical-align: top; +} + +@media only screen and (max-width:480px) { + .crosstalk-input-checkboxgroup .crosstalk-options-group .crosstalk-options-column { + display: block; + padding-right: inherit; + } +} + +/* Relevant BS3 styles to make filter_checkbox() look reasonable without Bootstrap */ +.crosstalk-input { + margin-bottom: 15px; /* a la .form-group */ + .control-label { + margin-bottom: 0; + vertical-align: middle; + } + input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px; + line-height: normal; + } + .checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; + } + .checkbox > label{ + padding-left: 20px; + margin-bottom: 0; + font-weight: 400; + cursor: pointer; + } + .checkbox input[type="checkbox"], + .checkbox-inline input[type="checkbox"] { + position: absolute; + margin-top: 2px; + margin-left: -20px; + } + .checkbox + .checkbox { + margin-top: -5px; + } + .checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + font-weight: 400; + vertical-align: middle; + cursor: pointer; + } + .checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; + } +} diff --git a/site_libs/datatables-css-0.0.0/datatables-crosstalk.css b/site_libs/datatables-css-0.0.0/datatables-crosstalk.css new file mode 100644 index 00000000..bd1159c8 --- /dev/null +++ b/site_libs/datatables-css-0.0.0/datatables-crosstalk.css @@ -0,0 +1,32 @@ +.dt-crosstalk-fade { + opacity: 0.2; +} + +html body div.DTS div.dataTables_scrollBody { + background: none; +} + + +/* +Fix https://github.com/rstudio/DT/issues/563 +If the `table.display` is set to "block" (e.g., pkgdown), the browser will display +datatable objects strangely. The search panel and the page buttons will still be +in full-width but the table body will be "compact" and shorter. +In therory, having this attributes will affect `dom="t"` +with `display: block` users. But in reality, there should be no one. +We may remove the below lines in the future if the upstream agree to have this there. +See https://github.com/DataTables/DataTablesSrc/issues/160 +*/ + +table.dataTable { + display: table; +} + + +/* +When DTOutput(fill = TRUE), it receives a .html-fill-item class (via htmltools::bindFillRole()), which effectively amounts to `flex: 1 1 auto`. That's mostly fine, but the case where `fillContainer=TRUE`+`height:auto`+`flex-basis:auto` and the container (e.g., a bslib::card()) doesn't have a defined height is a bit problematic since the table wants to fit the parent but the parent wants to fit the table, which results pretty small table height (maybe because there is a minimum height somewhere?). It seems better in this case to impose a 400px height default for the table, which we can do by setting `flex-basis` to 400px (the table is still allowed to grow/shrink when the container has an opinionated height). +*/ + +.html-fill-container > .html-fill-item.datatables { + flex-basis: 400px; +} diff --git a/site_libs/dt-core-bootstrap-1.11.3/css/dataTables.bootstrap.extra.css b/site_libs/dt-core-bootstrap-1.11.3/css/dataTables.bootstrap.extra.css new file mode 100644 index 00000000..2a143668 --- /dev/null +++ b/site_libs/dt-core-bootstrap-1.11.3/css/dataTables.bootstrap.extra.css @@ -0,0 +1,78 @@ +table.dataTable th.dt-left, +table.dataTable td.dt-left { + text-align: left; +} +table.dataTable th.dt-center, +table.dataTable td.dt-center, +table.dataTable td.dataTables_empty { + text-align: center; +} +table.dataTable th.dt-right, +table.dataTable td.dt-right { + text-align: right; +} +table.dataTable th.dt-justify, +table.dataTable td.dt-justify { + text-align: justify; +} +table.dataTable th.dt-nowrap, +table.dataTable td.dt-nowrap { + white-space: nowrap; +} +table.dataTable thead th.dt-head-left, +table.dataTable thead td.dt-head-left, +table.dataTable tfoot th.dt-head-left, +table.dataTable tfoot td.dt-head-left { + text-align: left; +} +table.dataTable thead th.dt-head-center, +table.dataTable thead td.dt-head-center, +table.dataTable tfoot th.dt-head-center, +table.dataTable tfoot td.dt-head-center { + text-align: center; +} +table.dataTable thead th.dt-head-right, +table.dataTable thead td.dt-head-right, +table.dataTable tfoot th.dt-head-right, +table.dataTable tfoot td.dt-head-right { + text-align: right; +} +table.dataTable thead th.dt-head-justify, +table.dataTable thead td.dt-head-justify, +table.dataTable tfoot th.dt-head-justify, +table.dataTable tfoot td.dt-head-justify { + text-align: justify; +} +table.dataTable thead th.dt-head-nowrap, +table.dataTable thead td.dt-head-nowrap, +table.dataTable tfoot th.dt-head-nowrap, +table.dataTable tfoot td.dt-head-nowrap { + white-space: nowrap; +} +table.dataTable tbody th.dt-body-left, +table.dataTable tbody td.dt-body-left { + text-align: left; +} +table.dataTable tbody th.dt-body-center, +table.dataTable tbody td.dt-body-center { + text-align: center; +} +table.dataTable tbody th.dt-body-right, +table.dataTable tbody td.dt-body-right { + text-align: right; +} +table.dataTable tbody th.dt-body-justify, +table.dataTable tbody td.dt-body-justify { + text-align: justify; +} +table.dataTable tbody th.dt-body-nowrap, +table.dataTable tbody td.dt-body-nowrap { + white-space: nowrap; +} +.table.dataTable tbody td.active, .table.dataTable tbody tr.active td { + background-color: #337ab7; + color: white; +} +.dataTables_scrollBody .dataTables_sizing { + visibility: hidden; +} diff --git a/site_libs/dt-core-bootstrap-1.11.3/css/dataTables.bootstrap.min.css b/site_libs/dt-core-bootstrap-1.11.3/css/dataTables.bootstrap.min.css new file mode 100644 index 00000000..b44b4eb6 --- /dev/null +++ b/site_libs/dt-core-bootstrap-1.11.3/css/dataTables.bootstrap.min.css @@ -0,0 +1 @@ +td.dt-control{background:url(data:text/plain;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACjElEQVR4Aa2V30uTURjHnVBUgglCaXVTJJVLMdhQm7+1JEvJiKAggmgSQiKJl0V0E13UVf0HQZmBLcvlpqa55tqV0YoMzIhY6js0yDH11X17vuO8Sq5Zgl/48DznPD/G63nOMSmBkoUNwhYhTUgn9NUeY8z5p0wqOVXYKRwQLMJhhYV7Kpaqck2rNdskbBPMdrv9osfjcQaDwW/RaHSR0OceY8xhrqox/a3ZZmGHkO9wOB7ouj6PBGKMOcxlzcqmdDYKGZmZmSWjo6PvIYosRuDWXGj50IwTb4+hxleN5sAVvJh4jvBCGBRzWSO121UPk3EAaUKuz+d7ycTp+Wnc/nwL1d4qHBVidmjZv/npBkJzGiiv19vFWmGrcVDsvKupqeky/056VMf1j9dQOViBKo9Aa/ixdbnYcrQGWsBc1jQ2NtrZQ/VKShHM8kvdEPVN9qJsoBRl/aUoHyiJ+UpcCxJTtmfCDYoHJT2yYyOlPtcaCoUmGGwdbkVRbxGK+2y0gg2GisUvNmJCy/BVUJqm/eBIxXqpgbUtiBise12HQlc+ClwFSKRCiZH6wXpQs7OzETWn6XENa/trYemywuK0IpGsTotgRU3fcVBzouWG6pOnpqY0BhuGGpDXeUjIW7JKcfuX3tjjP9k4FBkZN4PtY+042JGzzNMcGDJ35C7tmcU++tJmjE63OpSUuLEJ62GcfXUO+59kr8rJnlOY0WfAGtYaY/PHYPv9fhdEY7++4nz/BWS17UPWY0Es2avWp3vOYOTnCCheBtaqHskJr95kZBL3AvdR2XkEex5mYbdQ+qwCd97dRTAcXHn1Moyrt16PA2tN//V8jY+Pf4cS/VWerzU9sDay1gd2Xf4F/AZqlpeB9836LwAAAABJRU5ErkJggg==) no-repeat center center;cursor:pointer}tr.dt-hasChild td.dt-control{background:url(data:text/plain;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACdUlEQVR4Aa2V30tTYRjHVSgsoQKhXPUPlKZMlImiIIg/pggiiDeCBAdqyC4Kf9zVhVdeelX33QnCbtYvxZsxxkoqKxiz1SzdFudMb5xO5/bt+fa+sPCw3IVf+PA+532e5ytn53lfK0qoSrggXBauCbUKxtxjjjVnq1IXXxFuCXeEFqGdMOYec6zRtZX/M6sWrgv1hmHcDwQCLxOJxM9CoZAnjLnHHGt0bbXdVG1cEm4KLp/P9yKXyx2jhJhjDWvZc9qUwUWhzuFwdMVisc8QFQ4PcbCygvT0NJLDw0gNDSH96DEyfj8KmQwo1rJHem8oD2VapX/sxlAo9Aqi/N4e9hYWsDMwgARxD2DH7ZZYren5eZxYFqhgMOhnr3BVeSnn216v98Hf3yqXg/X0CX719YFs9/WquJfPGtkzZ2fBWvZ4PB6DHtqrokaol7/0GqLM2hq2enpsxMmpvf3VVVD8UOJxV42Uet1Wy7J+M5mam8P37u6ySM7MgDJNM8mRUl5qYDtOREz+GB3FZlcXNjs7UUrMk/jYGKhsNnuo57TWZhgTw0hHO0EpRdpV/tvICKgjUdFQv/Lu7q7JZHxqCl9dLqGtSJtL4VJ80Wvc8xD2V9YfRUbmLZPp5WVstLTYaSWt+lmt1tISKH5Q/VFqbGOTl6GNTk7iQ3Oz4FSrU8UfuTqdBJHxceQz+2APe/8Zm+Jgh8PhNxBlt7YQNQysNzVivbEJ7wXGiiZEJiZwEI2C4mFgr/aoKnn0jk0TiWfPsTE4iHcN9xBuaMCn/n5sLy7iKJk8ffTqikfvfC4H9laWdX2lUqltaDEu9/o664LtIOVfsOf4L+APb5yaiwyN8+8AAAAASUVORK5CYII=) no-repeat center center}table.dataTable th.dt-left,table.dataTable td.dt-left{text-align:left}table.dataTable th.dt-center,table.dataTable td.dt-center,table.dataTable td.dataTables_empty{text-align:center}table.dataTable th.dt-right,table.dataTable td.dt-right{text-align:right}table.dataTable th.dt-justify,table.dataTable td.dt-justify{text-align:justify}table.dataTable th.dt-nowrap,table.dataTable td.dt-nowrap{white-space:nowrap}table.dataTable thead th.dt-head-left,table.dataTable thead td.dt-head-left,table.dataTable tfoot th.dt-head-left,table.dataTable tfoot td.dt-head-left{text-align:left}table.dataTable thead th.dt-head-center,table.dataTable thead td.dt-head-center,table.dataTable tfoot th.dt-head-center,table.dataTable tfoot td.dt-head-center{text-align:center}table.dataTable thead th.dt-head-right,table.dataTable thead td.dt-head-right,table.dataTable tfoot th.dt-head-right,table.dataTable tfoot td.dt-head-right{text-align:right}table.dataTable thead th.dt-head-justify,table.dataTable thead td.dt-head-justify,table.dataTable tfoot th.dt-head-justify,table.dataTable tfoot td.dt-head-justify{text-align:justify}table.dataTable thead th.dt-head-nowrap,table.dataTable thead td.dt-head-nowrap,table.dataTable tfoot th.dt-head-nowrap,table.dataTable tfoot td.dt-head-nowrap{white-space:nowrap}table.dataTable tbody th.dt-body-left,table.dataTable tbody td.dt-body-left{text-align:left}table.dataTable tbody th.dt-body-center,table.dataTable tbody td.dt-body-center{text-align:center}table.dataTable tbody th.dt-body-right,table.dataTable tbody td.dt-body-right{text-align:right}table.dataTable tbody th.dt-body-justify,table.dataTable tbody td.dt-body-justify{text-align:justify}table.dataTable tbody th.dt-body-nowrap,table.dataTable tbody td.dt-body-nowrap{white-space:nowrap}table.dataTable{clear:both;margin-top:6px !important;margin-bottom:6px !important;max-width:none !important;border-collapse:separate !important}table.dataTable td,table.dataTable th{-webkit-box-sizing:content-box;box-sizing:content-box}table.dataTable td.dataTables_empty,table.dataTable th.dataTables_empty{text-align:center}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}div.dataTables_wrapper div.dataTables_length label{font-weight:normal;text-align:left;white-space:nowrap}div.dataTables_wrapper div.dataTables_length select{width:75px;display:inline-block}div.dataTables_wrapper div.dataTables_filter{text-align:right}div.dataTables_wrapper div.dataTables_filter label{font-weight:normal;white-space:nowrap;text-align:left}div.dataTables_wrapper div.dataTables_filter input{margin-left:.5em;display:inline-block;width:auto}div.dataTables_wrapper div.dataTables_info{padding-top:8px;white-space:nowrap}div.dataTables_wrapper div.dataTables_paginate{margin:0;white-space:nowrap;text-align:right}div.dataTables_wrapper div.dataTables_paginate ul.pagination{margin:2px 0;white-space:nowrap}div.dataTables_wrapper div.dataTables_processing{position:absolute;top:50%;left:50%;width:200px;margin-left:-100px;margin-top:-26px;text-align:center;padding:1em 0}table.dataTable thead>tr>th.sorting_asc,table.dataTable thead>tr>th.sorting_desc,table.dataTable thead>tr>th.sorting,table.dataTable thead>tr>td.sorting_asc,table.dataTable thead>tr>td.sorting_desc,table.dataTable thead>tr>td.sorting{padding-right:30px}table.dataTable thead>tr>th:active,table.dataTable thead>tr>td:active{outline:none}table.dataTable thead .sorting,table.dataTable thead .sorting_asc,table.dataTable thead .sorting_desc,table.dataTable thead .sorting_asc_disabled,table.dataTable thead .sorting_desc_disabled{cursor:pointer;position:relative}table.dataTable thead .sorting:after,table.dataTable thead .sorting_asc:after,table.dataTable thead .sorting_desc:after,table.dataTable thead .sorting_asc_disabled:after,table.dataTable thead .sorting_desc_disabled:after{position:absolute;bottom:8px;right:8px;display:block;font-family:"Glyphicons Halflings";opacity:.5}table.dataTable thead .sorting:after{opacity:.2;content:""}table.dataTable thead .sorting_asc:after{opacity:.5;content:""}table.dataTable thead .sorting_desc:after{opacity:.5;content:""}table.dataTable thead .sorting_asc_disabled:after,table.dataTable thead .sorting_desc_disabled:after{color:#eee}div.dataTables_scrollHead table.dataTable{margin-bottom:0 !important}div.dataTables_scrollBody>table{border-top:none;margin-top:0 !important;margin-bottom:0 !important}div.dataTables_scrollBody>table>thead .sorting:after,div.dataTables_scrollBody>table>thead .sorting_asc:after,div.dataTables_scrollBody>table>thead .sorting_desc:after{display:none}div.dataTables_scrollBody>table>tbody>tr:first-child>th,div.dataTables_scrollBody>table>tbody>tr:first-child>td{border-top:none}div.dataTables_scrollFoot>.dataTables_scrollFootInner{box-sizing:content-box}div.dataTables_scrollFoot>.dataTables_scrollFootInner>table{margin-top:0 !important;border-top:none}@media screen and (max-width: 767px){div.dataTables_wrapper div.dataTables_length,div.dataTables_wrapper div.dataTables_filter,div.dataTables_wrapper div.dataTables_info,div.dataTables_wrapper div.dataTables_paginate{text-align:center}}table.dataTable.table-condensed>thead>tr>th{padding-right:20px}table.dataTable.table-condensed .sorting:after,table.dataTable.table-condensed .sorting_asc:after,table.dataTable.table-condensed .sorting_desc:after{top:6px;right:6px}table.table-bordered.dataTable{border-right-width:0}table.table-bordered.dataTable th,table.table-bordered.dataTable td{border-left-width:0}table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable td:last-child,table.table-bordered.dataTable td:last-child{border-right-width:1px}table.table-bordered.dataTable tbody th,table.table-bordered.dataTable tbody td{border-bottom-width:0}div.dataTables_scrollHead table.table-bordered{border-bottom-width:0}div.table-responsive>div.dataTables_wrapper>div.row{margin:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^=col-]:first-child{padding-left:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^=col-]:last-child{padding-right:0} diff --git a/site_libs/htmltools-fill-0.5.8.1/fill.css b/site_libs/htmltools-fill-0.5.8.1/fill.css new file mode 100644 index 00000000..841ea9d5 --- /dev/null +++ b/site_libs/htmltools-fill-0.5.8.1/fill.css @@ -0,0 +1,21 @@ +@layer htmltools { + .html-fill-container { + display: flex; + flex-direction: column; + /* Prevent the container from expanding vertically or horizontally beyond its + parent's constraints. */ + min-height: 0; + min-width: 0; + } + .html-fill-container > .html-fill-item { + /* Fill items can grow and shrink freely within + available vertical space in fillable container */ + flex: 1 1 auto; + min-height: 0; + min-width: 0; + } + .html-fill-container > :not(.html-fill-item) { + /* Prevent shrinking or growing of non-fill items */ + flex: 0 0 auto; + } +} diff --git a/site_libs/htmlwidgets-1.6.4/htmlwidgets.js b/site_libs/htmlwidgets-1.6.4/htmlwidgets.js new file mode 100644 index 00000000..1067d029 --- /dev/null +++ b/site_libs/htmlwidgets-1.6.4/htmlwidgets.js @@ -0,0 +1,901 @@ +(function() { + // If window.HTMLWidgets is already defined, then use it; otherwise create a + // new object. This allows preceding code to set options that affect the + // initialization process (though none currently exist). + window.HTMLWidgets = window.HTMLWidgets || {}; + + // See if we're running in a viewer pane. If not, we're in a web browser. + var viewerMode = window.HTMLWidgets.viewerMode = + /\bviewer_pane=1\b/.test(window.location); + + // See if we're running in Shiny mode. If not, it's a static document. + // Note that static widgets can appear in both Shiny and static modes, but + // obviously, Shiny widgets can only appear in Shiny apps/documents. + var shinyMode = window.HTMLWidgets.shinyMode = + typeof(window.Shiny) !== "undefined" && !!window.Shiny.outputBindings; + + // We can't count on jQuery being available, so we implement our own + // version if necessary. + function querySelectorAll(scope, selector) { + if (typeof(jQuery) !== "undefined" && scope instanceof jQuery) { + return scope.find(selector); + } + if (scope.querySelectorAll) { + return scope.querySelectorAll(selector); + } + } + + function asArray(value) { + if (value === null) + return []; + if ($.isArray(value)) + return value; + return [value]; + } + + // Implement jQuery's extend + function extend(target /*, ... */) { + if (arguments.length == 1) { + return target; + } + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + for (var prop in source) { + if (source.hasOwnProperty(prop)) { + target[prop] = source[prop]; + } + } + } + return target; + } + + // IE8 doesn't support Array.forEach. + function forEach(values, callback, thisArg) { + if (values.forEach) { + values.forEach(callback, thisArg); + } else { + for (var i = 0; i < values.length; i++) { + callback.call(thisArg, values[i], i, values); + } + } + } + + // Replaces the specified method with the return value of funcSource. + // + // Note that funcSource should not BE the new method, it should be a function + // that RETURNS the new method. funcSource receives a single argument that is + // the overridden method, it can be called from the new method. The overridden + // method can be called like a regular function, it has the target permanently + // bound to it so "this" will work correctly. + function overrideMethod(target, methodName, funcSource) { + var superFunc = target[methodName] || function() {}; + var superFuncBound = function() { + return superFunc.apply(target, arguments); + }; + target[methodName] = funcSource(superFuncBound); + } + + // Add a method to delegator that, when invoked, calls + // delegatee.methodName. If there is no such method on + // the delegatee, but there was one on delegator before + // delegateMethod was called, then the original version + // is invoked instead. + // For example: + // + // var a = { + // method1: function() { console.log('a1'); } + // method2: function() { console.log('a2'); } + // }; + // var b = { + // method1: function() { console.log('b1'); } + // }; + // delegateMethod(a, b, "method1"); + // delegateMethod(a, b, "method2"); + // a.method1(); + // a.method2(); + // + // The output would be "b1", "a2". + function delegateMethod(delegator, delegatee, methodName) { + var inherited = delegator[methodName]; + delegator[methodName] = function() { + var target = delegatee; + var method = delegatee[methodName]; + + // The method doesn't exist on the delegatee. Instead, + // call the method on the delegator, if it exists. + if (!method) { + target = delegator; + method = inherited; + } + + if (method) { + return method.apply(target, arguments); + } + }; + } + + // Implement a vague facsimilie of jQuery's data method + function elementData(el, name, value) { + if (arguments.length == 2) { + return el["htmlwidget_data_" + name]; + } else if (arguments.length == 3) { + el["htmlwidget_data_" + name] = value; + return el; + } else { + throw new Error("Wrong number of arguments for elementData: " + + arguments.length); + } + } + + // http://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex + function escapeRegExp(str) { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); + } + + function hasClass(el, className) { + var re = new RegExp("\\b" + escapeRegExp(className) + "\\b"); + return re.test(el.className); + } + + // elements - array (or array-like object) of HTML elements + // className - class name to test for + // include - if true, only return elements with given className; + // if false, only return elements *without* given className + function filterByClass(elements, className, include) { + var results = []; + for (var i = 0; i < elements.length; i++) { + if (hasClass(elements[i], className) == include) + results.push(elements[i]); + } + return results; + } + + function on(obj, eventName, func) { + if (obj.addEventListener) { + obj.addEventListener(eventName, func, false); + } else if (obj.attachEvent) { + obj.attachEvent(eventName, func); + } + } + + function off(obj, eventName, func) { + if (obj.removeEventListener) + obj.removeEventListener(eventName, func, false); + else if (obj.detachEvent) { + obj.detachEvent(eventName, func); + } + } + + // Translate array of values to top/right/bottom/left, as usual with + // the "padding" CSS property + // https://developer.mozilla.org/en-US/docs/Web/CSS/padding + function unpackPadding(value) { + if (typeof(value) === "number") + value = [value]; + if (value.length === 1) { + return {top: value[0], right: value[0], bottom: value[0], left: value[0]}; + } + if (value.length === 2) { + return {top: value[0], right: value[1], bottom: value[0], left: value[1]}; + } + if (value.length === 3) { + return {top: value[0], right: value[1], bottom: value[2], left: value[1]}; + } + if (value.length === 4) { + return {top: value[0], right: value[1], bottom: value[2], left: value[3]}; + } + } + + // Convert an unpacked padding object to a CSS value + function paddingToCss(paddingObj) { + return paddingObj.top + "px " + paddingObj.right + "px " + paddingObj.bottom + "px " + paddingObj.left + "px"; + } + + // Makes a number suitable for CSS + function px(x) { + if (typeof(x) === "number") + return x + "px"; + else + return x; + } + + // Retrieves runtime widget sizing information for an element. + // The return value is either null, or an object with fill, padding, + // defaultWidth, defaultHeight fields. + function sizingPolicy(el) { + var sizingEl = document.querySelector("script[data-for='" + el.id + "'][type='application/htmlwidget-sizing']"); + if (!sizingEl) + return null; + var sp = JSON.parse(sizingEl.textContent || sizingEl.text || "{}"); + if (viewerMode) { + return sp.viewer; + } else { + return sp.browser; + } + } + + // @param tasks Array of strings (or falsy value, in which case no-op). + // Each element must be a valid JavaScript expression that yields a + // function. Or, can be an array of objects with "code" and "data" + // properties; in this case, the "code" property should be a string + // of JS that's an expr that yields a function, and "data" should be + // an object that will be added as an additional argument when that + // function is called. + // @param target The object that will be "this" for each function + // execution. + // @param args Array of arguments to be passed to the functions. (The + // same arguments will be passed to all functions.) + function evalAndRun(tasks, target, args) { + if (tasks) { + forEach(tasks, function(task) { + var theseArgs = args; + if (typeof(task) === "object") { + theseArgs = theseArgs.concat([task.data]); + task = task.code; + } + var taskFunc = tryEval(task); + if (typeof(taskFunc) !== "function") { + throw new Error("Task must be a function! Source:\n" + task); + } + taskFunc.apply(target, theseArgs); + }); + } + } + + // Attempt eval() both with and without enclosing in parentheses. + // Note that enclosing coerces a function declaration into + // an expression that eval() can parse + // (otherwise, a SyntaxError is thrown) + function tryEval(code) { + var result = null; + try { + result = eval("(" + code + ")"); + } catch(error) { + if (!(error instanceof SyntaxError)) { + throw error; + } + try { + result = eval(code); + } catch(e) { + if (e instanceof SyntaxError) { + throw error; + } else { + throw e; + } + } + } + return result; + } + + function initSizing(el) { + var sizing = sizingPolicy(el); + if (!sizing) + return; + + var cel = document.getElementById("htmlwidget_container"); + if (!cel) + return; + + if (typeof(sizing.padding) !== "undefined") { + document.body.style.margin = "0"; + document.body.style.padding = paddingToCss(unpackPadding(sizing.padding)); + } + + if (sizing.fill) { + document.body.style.overflow = "hidden"; + document.body.style.width = "100%"; + document.body.style.height = "100%"; + document.documentElement.style.width = "100%"; + document.documentElement.style.height = "100%"; + cel.style.position = "absolute"; + var pad = unpackPadding(sizing.padding); + cel.style.top = pad.top + "px"; + cel.style.right = pad.right + "px"; + cel.style.bottom = pad.bottom + "px"; + cel.style.left = pad.left + "px"; + el.style.width = "100%"; + el.style.height = "100%"; + + return { + getWidth: function() { return cel.getBoundingClientRect().width; }, + getHeight: function() { return cel.getBoundingClientRect().height; } + }; + + } else { + el.style.width = px(sizing.width); + el.style.height = px(sizing.height); + + return { + getWidth: function() { return cel.getBoundingClientRect().width; }, + getHeight: function() { return cel.getBoundingClientRect().height; } + }; + } + } + + // Default implementations for methods + var defaults = { + find: function(scope) { + return querySelectorAll(scope, "." + this.name); + }, + renderError: function(el, err) { + var $el = $(el); + + this.clearError(el); + + // Add all these error classes, as Shiny does + var errClass = "shiny-output-error"; + if (err.type !== null) { + // use the classes of the error condition as CSS class names + errClass = errClass + " " + $.map(asArray(err.type), function(type) { + return errClass + "-" + type; + }).join(" "); + } + errClass = errClass + " htmlwidgets-error"; + + // Is el inline or block? If inline or inline-block, just display:none it + // and add an inline error. + var display = $el.css("display"); + $el.data("restore-display-mode", display); + + if (display === "inline" || display === "inline-block") { + $el.hide(); + if (err.message !== "") { + var errorSpan = $("").addClass(errClass); + errorSpan.text(err.message); + $el.after(errorSpan); + } + } else if (display === "block") { + // If block, add an error just after the el, set visibility:none on the + // el, and position the error to be on top of the el. + // Mark it with a unique ID and CSS class so we can remove it later. + $el.css("visibility", "hidden"); + if (err.message !== "") { + var errorDiv = $("
").addClass(errClass).css("position", "absolute") + .css("top", el.offsetTop) + .css("left", el.offsetLeft) + // setting width can push out the page size, forcing otherwise + // unnecessary scrollbars to appear and making it impossible for + // the element to shrink; so use max-width instead + .css("maxWidth", el.offsetWidth) + .css("height", el.offsetHeight); + errorDiv.text(err.message); + $el.after(errorDiv); + + // Really dumb way to keep the size/position of the error in sync with + // the parent element as the window is resized or whatever. + var intId = setInterval(function() { + if (!errorDiv[0].parentElement) { + clearInterval(intId); + return; + } + errorDiv + .css("top", el.offsetTop) + .css("left", el.offsetLeft) + .css("maxWidth", el.offsetWidth) + .css("height", el.offsetHeight); + }, 500); + } + } + }, + clearError: function(el) { + var $el = $(el); + var display = $el.data("restore-display-mode"); + $el.data("restore-display-mode", null); + + if (display === "inline" || display === "inline-block") { + if (display) + $el.css("display", display); + $(el.nextSibling).filter(".htmlwidgets-error").remove(); + } else if (display === "block"){ + $el.css("visibility", "inherit"); + $(el.nextSibling).filter(".htmlwidgets-error").remove(); + } + }, + sizing: {} + }; + + // Called by widget bindings to register a new type of widget. The definition + // object can contain the following properties: + // - name (required) - A string indicating the binding name, which will be + // used by default as the CSS classname to look for. + // - initialize (optional) - A function(el) that will be called once per + // widget element; if a value is returned, it will be passed as the third + // value to renderValue. + // - renderValue (required) - A function(el, data, initValue) that will be + // called with data. Static contexts will cause this to be called once per + // element; Shiny apps will cause this to be called multiple times per + // element, as the data changes. + window.HTMLWidgets.widget = function(definition) { + if (!definition.name) { + throw new Error("Widget must have a name"); + } + if (!definition.type) { + throw new Error("Widget must have a type"); + } + // Currently we only support output widgets + if (definition.type !== "output") { + throw new Error("Unrecognized widget type '" + definition.type + "'"); + } + // TODO: Verify that .name is a valid CSS classname + + // Support new-style instance-bound definitions. Old-style class-bound + // definitions have one widget "object" per widget per type/class of + // widget; the renderValue and resize methods on such widget objects + // take el and instance arguments, because the widget object can't + // store them. New-style instance-bound definitions have one widget + // object per widget instance; the definition that's passed in doesn't + // provide renderValue or resize methods at all, just the single method + // factory(el, width, height) + // which returns an object that has renderValue(x) and resize(w, h). + // This enables a far more natural programming style for the widget + // author, who can store per-instance state using either OO-style + // instance fields or functional-style closure variables (I guess this + // is in contrast to what can only be called C-style pseudo-OO which is + // what we required before). + if (definition.factory) { + definition = createLegacyDefinitionAdapter(definition); + } + + if (!definition.renderValue) { + throw new Error("Widget must have a renderValue function"); + } + + // For static rendering (non-Shiny), use a simple widget registration + // scheme. We also use this scheme for Shiny apps/documents that also + // contain static widgets. + window.HTMLWidgets.widgets = window.HTMLWidgets.widgets || []; + // Merge defaults into the definition; don't mutate the original definition. + var staticBinding = extend({}, defaults, definition); + overrideMethod(staticBinding, "find", function(superfunc) { + return function(scope) { + var results = superfunc(scope); + // Filter out Shiny outputs, we only want the static kind + return filterByClass(results, "html-widget-output", false); + }; + }); + window.HTMLWidgets.widgets.push(staticBinding); + + if (shinyMode) { + // Shiny is running. Register the definition with an output binding. + // The definition itself will not be the output binding, instead + // we will make an output binding object that delegates to the + // definition. This is because we foolishly used the same method + // name (renderValue) for htmlwidgets definition and Shiny bindings + // but they actually have quite different semantics (the Shiny + // bindings receive data that includes lots of metadata that it + // strips off before calling htmlwidgets renderValue). We can't + // just ignore the difference because in some widgets it's helpful + // to call this.renderValue() from inside of resize(), and if + // we're not delegating, then that call will go to the Shiny + // version instead of the htmlwidgets version. + + // Merge defaults with definition, without mutating either. + var bindingDef = extend({}, defaults, definition); + + // This object will be our actual Shiny binding. + var shinyBinding = new Shiny.OutputBinding(); + + // With a few exceptions, we'll want to simply use the bindingDef's + // version of methods if they are available, otherwise fall back to + // Shiny's defaults. NOTE: If Shiny's output bindings gain additional + // methods in the future, and we want them to be overrideable by + // HTMLWidget binding definitions, then we'll need to add them to this + // list. + delegateMethod(shinyBinding, bindingDef, "getId"); + delegateMethod(shinyBinding, bindingDef, "onValueChange"); + delegateMethod(shinyBinding, bindingDef, "onValueError"); + delegateMethod(shinyBinding, bindingDef, "renderError"); + delegateMethod(shinyBinding, bindingDef, "clearError"); + delegateMethod(shinyBinding, bindingDef, "showProgress"); + + // The find, renderValue, and resize are handled differently, because we + // want to actually decorate the behavior of the bindingDef methods. + + shinyBinding.find = function(scope) { + var results = bindingDef.find(scope); + + // Only return elements that are Shiny outputs, not static ones + var dynamicResults = results.filter(".html-widget-output"); + + // It's possible that whatever caused Shiny to think there might be + // new dynamic outputs, also caused there to be new static outputs. + // Since there might be lots of different htmlwidgets bindings, we + // schedule execution for later--no need to staticRender multiple + // times. + if (results.length !== dynamicResults.length) + scheduleStaticRender(); + + return dynamicResults; + }; + + // Wrap renderValue to handle initialization, which unfortunately isn't + // supported natively by Shiny at the time of this writing. + + shinyBinding.renderValue = function(el, data) { + Shiny.renderDependencies(data.deps); + // Resolve strings marked as javascript literals to objects + if (!(data.evals instanceof Array)) data.evals = [data.evals]; + for (var i = 0; data.evals && i < data.evals.length; i++) { + window.HTMLWidgets.evaluateStringMember(data.x, data.evals[i]); + } + if (!bindingDef.renderOnNullValue) { + if (data.x === null) { + el.style.visibility = "hidden"; + return; + } else { + el.style.visibility = "inherit"; + } + } + if (!elementData(el, "initialized")) { + initSizing(el); + + elementData(el, "initialized", true); + if (bindingDef.initialize) { + var rect = el.getBoundingClientRect(); + var result = bindingDef.initialize(el, rect.width, rect.height); + elementData(el, "init_result", result); + } + } + bindingDef.renderValue(el, data.x, elementData(el, "init_result")); + evalAndRun(data.jsHooks.render, elementData(el, "init_result"), [el, data.x]); + }; + + // Only override resize if bindingDef implements it + if (bindingDef.resize) { + shinyBinding.resize = function(el, width, height) { + // Shiny can call resize before initialize/renderValue have been + // called, which doesn't make sense for widgets. + if (elementData(el, "initialized")) { + bindingDef.resize(el, width, height, elementData(el, "init_result")); + } + }; + } + + Shiny.outputBindings.register(shinyBinding, bindingDef.name); + } + }; + + var scheduleStaticRenderTimerId = null; + function scheduleStaticRender() { + if (!scheduleStaticRenderTimerId) { + scheduleStaticRenderTimerId = setTimeout(function() { + scheduleStaticRenderTimerId = null; + window.HTMLWidgets.staticRender(); + }, 1); + } + } + + // Render static widgets after the document finishes loading + // Statically render all elements that are of this widget's class + window.HTMLWidgets.staticRender = function() { + var bindings = window.HTMLWidgets.widgets || []; + forEach(bindings, function(binding) { + var matches = binding.find(document.documentElement); + forEach(matches, function(el) { + var sizeObj = initSizing(el, binding); + + var getSize = function(el) { + if (sizeObj) { + return {w: sizeObj.getWidth(), h: sizeObj.getHeight()} + } else { + var rect = el.getBoundingClientRect(); + return {w: rect.width, h: rect.height} + } + }; + + if (hasClass(el, "html-widget-static-bound")) + return; + el.className = el.className + " html-widget-static-bound"; + + var initResult; + if (binding.initialize) { + var size = getSize(el); + initResult = binding.initialize(el, size.w, size.h); + elementData(el, "init_result", initResult); + } + + if (binding.resize) { + var lastSize = getSize(el); + var resizeHandler = function(e) { + var size = getSize(el); + if (size.w === 0 && size.h === 0) + return; + if (size.w === lastSize.w && size.h === lastSize.h) + return; + lastSize = size; + binding.resize(el, size.w, size.h, initResult); + }; + + on(window, "resize", resizeHandler); + + // This is needed for cases where we're running in a Shiny + // app, but the widget itself is not a Shiny output, but + // rather a simple static widget. One example of this is + // an rmarkdown document that has runtime:shiny and widget + // that isn't in a render function. Shiny only knows to + // call resize handlers for Shiny outputs, not for static + // widgets, so we do it ourselves. + if (window.jQuery) { + window.jQuery(document).on( + "shown.htmlwidgets shown.bs.tab.htmlwidgets shown.bs.collapse.htmlwidgets", + resizeHandler + ); + window.jQuery(document).on( + "hidden.htmlwidgets hidden.bs.tab.htmlwidgets hidden.bs.collapse.htmlwidgets", + resizeHandler + ); + } + + // This is needed for the specific case of ioslides, which + // flips slides between display:none and display:block. + // Ideally we would not have to have ioslide-specific code + // here, but rather have ioslides raise a generic event, + // but the rmarkdown package just went to CRAN so the + // window to getting that fixed may be long. + if (window.addEventListener) { + // It's OK to limit this to window.addEventListener + // browsers because ioslides itself only supports + // such browsers. + on(document, "slideenter", resizeHandler); + on(document, "slideleave", resizeHandler); + } + } + + var scriptData = document.querySelector("script[data-for='" + el.id + "'][type='application/json']"); + if (scriptData) { + var data = JSON.parse(scriptData.textContent || scriptData.text); + // Resolve strings marked as javascript literals to objects + if (!(data.evals instanceof Array)) data.evals = [data.evals]; + for (var k = 0; data.evals && k < data.evals.length; k++) { + window.HTMLWidgets.evaluateStringMember(data.x, data.evals[k]); + } + binding.renderValue(el, data.x, initResult); + evalAndRun(data.jsHooks.render, initResult, [el, data.x]); + } + }); + }); + + invokePostRenderHandlers(); + } + + + function has_jQuery3() { + if (!window.jQuery) { + return false; + } + var $version = window.jQuery.fn.jquery; + var $major_version = parseInt($version.split(".")[0]); + return $major_version >= 3; + } + + /* + / Shiny 1.4 bumped jQuery from 1.x to 3.x which means jQuery's + / on-ready handler (i.e., $(fn)) is now asyncronous (i.e., it now + / really means $(setTimeout(fn)). + / https://jquery.com/upgrade-guide/3.0/#breaking-change-document-ready-handlers-are-now-asynchronous + / + / Since Shiny uses $() to schedule initShiny, shiny>=1.4 calls initShiny + / one tick later than it did before, which means staticRender() is + / called renderValue() earlier than (advanced) widget authors might be expecting. + / https://github.com/rstudio/shiny/issues/2630 + / + / For a concrete example, leaflet has some methods (e.g., updateBounds) + / which reference Shiny methods registered in initShiny (e.g., setInputValue). + / Since leaflet is privy to this life-cycle, it knows to use setTimeout() to + / delay execution of those methods (until Shiny methods are ready) + / https://github.com/rstudio/leaflet/blob/18ec981/javascript/src/index.js#L266-L268 + / + / Ideally widget authors wouldn't need to use this setTimeout() hack that + / leaflet uses to call Shiny methods on a staticRender(). In the long run, + / the logic initShiny should be broken up so that method registration happens + / right away, but binding happens later. + */ + function maybeStaticRenderLater() { + if (shinyMode && has_jQuery3()) { + window.jQuery(window.HTMLWidgets.staticRender); + } else { + window.HTMLWidgets.staticRender(); + } + } + + if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", function() { + document.removeEventListener("DOMContentLoaded", arguments.callee, false); + maybeStaticRenderLater(); + }, false); + } else if (document.attachEvent) { + document.attachEvent("onreadystatechange", function() { + if (document.readyState === "complete") { + document.detachEvent("onreadystatechange", arguments.callee); + maybeStaticRenderLater(); + } + }); + } + + + window.HTMLWidgets.getAttachmentUrl = function(depname, key) { + // If no key, default to the first item + if (typeof(key) === "undefined") + key = 1; + + var link = document.getElementById(depname + "-" + key + "-attachment"); + if (!link) { + throw new Error("Attachment " + depname + "/" + key + " not found in document"); + } + return link.getAttribute("href"); + }; + + window.HTMLWidgets.dataframeToD3 = function(df) { + var names = []; + var length; + for (var name in df) { + if (df.hasOwnProperty(name)) + names.push(name); + if (typeof(df[name]) !== "object" || typeof(df[name].length) === "undefined") { + throw new Error("All fields must be arrays"); + } else if (typeof(length) !== "undefined" && length !== df[name].length) { + throw new Error("All fields must be arrays of the same length"); + } + length = df[name].length; + } + var results = []; + var item; + for (var row = 0; row < length; row++) { + item = {}; + for (var col = 0; col < names.length; col++) { + item[names[col]] = df[names[col]][row]; + } + results.push(item); + } + return results; + }; + + window.HTMLWidgets.transposeArray2D = function(array) { + if (array.length === 0) return array; + var newArray = array[0].map(function(col, i) { + return array.map(function(row) { + return row[i] + }) + }); + return newArray; + }; + // Split value at splitChar, but allow splitChar to be escaped + // using escapeChar. Any other characters escaped by escapeChar + // will be included as usual (including escapeChar itself). + function splitWithEscape(value, splitChar, escapeChar) { + var results = []; + var escapeMode = false; + var currentResult = ""; + for (var pos = 0; pos < value.length; pos++) { + if (!escapeMode) { + if (value[pos] === splitChar) { + results.push(currentResult); + currentResult = ""; + } else if (value[pos] === escapeChar) { + escapeMode = true; + } else { + currentResult += value[pos]; + } + } else { + currentResult += value[pos]; + escapeMode = false; + } + } + if (currentResult !== "") { + results.push(currentResult); + } + return results; + } + // Function authored by Yihui/JJ Allaire + window.HTMLWidgets.evaluateStringMember = function(o, member) { + var parts = splitWithEscape(member, '.', '\\'); + for (var i = 0, l = parts.length; i < l; i++) { + var part = parts[i]; + // part may be a character or 'numeric' member name + if (o !== null && typeof o === "object" && part in o) { + if (i == (l - 1)) { // if we are at the end of the line then evalulate + if (typeof o[part] === "string") + o[part] = tryEval(o[part]); + } else { // otherwise continue to next embedded object + o = o[part]; + } + } + } + }; + + // Retrieve the HTMLWidget instance (i.e. the return value of an + // HTMLWidget binding's initialize() or factory() function) + // associated with an element, or null if none. + window.HTMLWidgets.getInstance = function(el) { + return elementData(el, "init_result"); + }; + + // Finds the first element in the scope that matches the selector, + // and returns the HTMLWidget instance (i.e. the return value of + // an HTMLWidget binding's initialize() or factory() function) + // associated with that element, if any. If no element matches the + // selector, or the first matching element has no HTMLWidget + // instance associated with it, then null is returned. + // + // The scope argument is optional, and defaults to window.document. + window.HTMLWidgets.find = function(scope, selector) { + if (arguments.length == 1) { + selector = scope; + scope = document; + } + + var el = scope.querySelector(selector); + if (el === null) { + return null; + } else { + return window.HTMLWidgets.getInstance(el); + } + }; + + // Finds all elements in the scope that match the selector, and + // returns the HTMLWidget instances (i.e. the return values of + // an HTMLWidget binding's initialize() or factory() function) + // associated with the elements, in an array. If elements that + // match the selector don't have an associated HTMLWidget + // instance, the returned array will contain nulls. + // + // The scope argument is optional, and defaults to window.document. + window.HTMLWidgets.findAll = function(scope, selector) { + if (arguments.length == 1) { + selector = scope; + scope = document; + } + + var nodes = scope.querySelectorAll(selector); + var results = []; + for (var i = 0; i < nodes.length; i++) { + results.push(window.HTMLWidgets.getInstance(nodes[i])); + } + return results; + }; + + var postRenderHandlers = []; + function invokePostRenderHandlers() { + while (postRenderHandlers.length) { + var handler = postRenderHandlers.shift(); + if (handler) { + handler(); + } + } + } + + // Register the given callback function to be invoked after the + // next time static widgets are rendered. + window.HTMLWidgets.addPostRenderHandler = function(callback) { + postRenderHandlers.push(callback); + }; + + // Takes a new-style instance-bound definition, and returns an + // old-style class-bound definition. This saves us from having + // to rewrite all the logic in this file to accomodate both + // types of definitions. + function createLegacyDefinitionAdapter(defn) { + var result = { + name: defn.name, + type: defn.type, + initialize: function(el, width, height) { + return defn.factory(el, width, height); + }, + renderValue: function(el, x, instance) { + return instance.renderValue(x); + }, + resize: function(el, width, height, instance) { + return instance.resize(width, height); + } + }; + + if (defn.find) + result.find = defn.find; + if (defn.renderError) + result.renderError = defn.renderError; + if (defn.clearError) + result.clearError = defn.clearError; + + return result; + } +})(); diff --git a/site_libs/quarto-diagram/mermaid-init.js b/site_libs/quarto-diagram/mermaid-init.js new file mode 100644 index 00000000..b726354c --- /dev/null +++ b/site_libs/quarto-diagram/mermaid-init.js @@ -0,0 +1,275 @@ +// mermaid-init.js +// Initializes the quarto-mermaid JS runtime +// +// Copyright (C) 2022 Posit Software, PBC + +/** + * String.prototype.replaceAll() polyfill + * https://gomakethings.com/how-to-replace-a-section-of-a-string-with-another-one-with-vanilla-js/ + * @author Chris Ferdinandi + * @license MIT + */ +if (!String.prototype.replaceAll) { + String.prototype.replaceAll = function (str, newStr) { + // If a regex pattern + if ( + Object.prototype.toString.call(str).toLowerCase() === "[object regexp]" + ) { + return this.replace(str, newStr); + } + + // If a string + return this.replace(new RegExp(str, "g"), newStr); + }; +} + +const mermaidOpts = { + startOnLoad: false, +}; +// this CSS is adapted from +// mkdocs-material +// Copyright (c) 2016-2022 Martin Donath + +const defaultCSS = + '.label text {fill: var(--mermaid-fg-color);}.node circle, .node ellipse, .node path, .node polygon, .node rect {fill: var(--mermaid-node-bg-color);stroke: var(--mermaid-node-fg-color);}marker {fill: var(--mermaid-edge-color) !important;}.edgeLabel .label rect {fill: #0000;}.label {color: var(--mermaid-label-fg-color);font-family: var(--mermaid-font-family);}.label foreignObject {line-height: normal;overflow: visible;}.label div .edgeLabel {color: var(--mermaid-label-fg-color);}.edgeLabel, .edgeLabel rect, .label div .edgeLabel {background-color: var(--mermaid-label-bg-color);}.edgeLabel, .edgeLabel rect {fill: var(--mermaid-label-bg-color);color: var(--mermaid-edge-color);}.edgePath .path, .flowchart-link {stroke: var(--mermaid-edge-color);}.edgePath .arrowheadPath {fill: var(--mermaid-edge-color);stroke: none;}.cluster rect {fill: var(--mermaid-fg-color--lightest);stroke: var(--mermaid-fg-color--lighter);}.cluster span {color: var(--mermaid-label-fg-color);font-family: var(--mermaid-font-family);}defs #flowchart-circleEnd, defs #flowchart-circleStart, defs #flowchart-crossEnd, defs #flowchart-crossStart, defs #flowchart-pointEnd, defs #flowchart-pointStart {stroke: none;}g.classGroup line, g.classGroup rect {fill: var(--mermaid-node-bg-color);stroke: var(--mermaid-node-fg-color);}g.classGroup text {fill: var(--mermaid-label-fg-color);font-family: var(--mermaid-font-family);}.classLabel .box {fill: var(--mermaid-label-bg-color);background-color: var(--mermaid-label-bg-color);opacity: 1;}.classLabel .label {fill: var(--mermaid-label-fg-color);font-family: var(--mermaid-font-family);}.node .divider {stroke: var(--mermaid-node-fg-color);}.relation {stroke: var(--mermaid-edge-color);}.cardinality {fill: var(--mermaid-label-fg-color);font-family: var(--mermaid-font-family);}.cardinality text {fill: inherit !important;}defs #classDiagram-compositionEnd, defs #classDiagram-compositionStart, defs #classDiagram-dependencyEnd, defs #classDiagram-dependencyStart, defs #classDiagram-extensionEnd, defs #classDiagram-extensionStart {fill: var(--mermaid-edge-color) !important;stroke: var(--mermaid-edge-color) !important;}defs #classDiagram-aggregationEnd, defs #classDiagram-aggregationStart {fill: var(--mermaid-label-bg-color) !important;stroke: var(--mermaid-edge-color) !important;}g.stateGroup rect {fill: var(--mermaid-node-bg-color);stroke: var(--mermaid-node-fg-color);}g.stateGroup .state-title {fill: var(--mermaid-label-fg-color) !important;font-family: var(--mermaid-font-family);}g.stateGroup .composit {fill: var(--mermaid-label-bg-color);}.nodeLabel {color: var(--mermaid-label-fg-color);font-family: var(--mermaid-font-family);}.node circle.state-end, .node circle.state-start, .start-state {fill: var(--mermaid-edge-color);stroke: none;}.end-state-inner, .end-state-outer {fill: var(--mermaid-edge-color);}.end-state-inner, .node circle.state-end {stroke: var(--mermaid-label-bg-color);}.transition {stroke: var(--mermaid-edge-color);}[id^="state-fork"] rect, [id^="state-join"] rect {fill: var(--mermaid-edge-color) !important;stroke: none !important;}.statediagram-cluster.statediagram-cluster .inner {fill: var(--mermaid-bg-color);}.statediagram-cluster rect {fill: var(--mermaid-node-bg-color);stroke: var(--mermaid-node-fg-color);}.statediagram-state rect.divider {fill: var(--mermaid-fg-color--lightest);stroke: var(--mermaid-fg-color--lighter);}defs #statediagram-barbEnd {stroke: var(--mermaid-edge-color);}.entityBox {fill: var(--mermaid-label-bg-color);stroke: var(--mermaid-node-fg-color);}.entityLabel {fill: var(--mermaid-label-fg-color);font-family: var(--mermaid-font-family);}.relationshipLabelBox {fill: var(--mermaid-label-bg-color);fill-opacity: 1;background-color: var(--mermaid-label-bg-color);opacity: 1;}.relationshipLabel {fill: var(--mermaid-label-fg-color);}.relationshipLine {stroke: var(--mermaid-edge-color);}defs #ONE_OR_MORE_END *, defs #ONE_OR_MORE_START *, defs #ONLY_ONE_END *, defs #ONLY_ONE_START *, defs #ZERO_OR_MORE_END *, defs #ZERO_OR_MORE_START *, defs #ZERO_OR_ONE_END *, defs #ZERO_OR_ONE_START * {stroke: var(--mermaid-edge-color) !important;}.actor, defs #ZERO_OR_MORE_END circle, defs #ZERO_OR_MORE_START circle {fill: var(--mermaid-label-bg-color);}.actor {stroke: var(--mermaid-node-fg-color);}text.actor > tspan {fill: var(--mermaid-label-fg-color);font-family: var(--mermaid-font-family);}line {stroke: var(--mermaid-fg-color--lighter);}.messageLine0, .messageLine1 {stroke: var(--mermaid-edge-color);}.loopText > tspan, .messageText, .noteText > tspan {fill: var(--mermaid-edge-color);stroke: none;font-family: var(--mermaid-font-family) !important;}.noteText > tspan {fill: #000;}#arrowhead path {fill: var(--mermaid-edge-color);stroke: none;}.loopLine {stroke: var(--mermaid-node-fg-color);}.labelBox, .loopLine {fill: var(--mermaid-node-bg-color);}.labelBox {stroke: none;}.labelText, .labelText > span {fill: var(--mermaid-node-fg-color);font-family: var(--mermaid-font-family);}'; + +const mermaidThemeEl = document.querySelector('meta[name="mermaid-theme"]'); +if (mermaidThemeEl) { + mermaidOpts.theme = mermaidThemeEl.content; +} else { + mermaidOpts.themeCSS = defaultCSS; +} + +mermaid.initialize(mermaidOpts); + +const _quartoMermaid = { + // NB: there's effectively a copy of this function + // in `core/svg.ts`. + // if you change something here, you must keep it consistent there as well. + setSvgSize(svg) { + const { widthInPoints, heightInPoints, explicitHeight, explicitWidth } = + this.resolveSize(svg); + + if (explicitWidth && explicitHeight) { + svg.setAttribute("width", widthInPoints); + svg.setAttribute("height", heightInPoints); + svg.style.maxWidth = null; // remove mermaid's default max-width + } else { + if (explicitWidth) { + svg.style.maxWidth = `${widthInPoints}px`; + } + if (explicitHeight) { + svg.style.maxHeight = `${heightInPoints}px`; + } + } + }, + + // NB: there's effectively a copy of this function + // in `core/svg.ts`. + // if you change something here, you must keep it consistent there as well. + makeResponsive(svg) { + const width = svg.getAttribute("width"); + if (width === null) { + throw new Error("Couldn't find SVG width"); + } + const numWidth = Number(width.slice(0, -2)); + + if (numWidth > 650) { + changed = true; + svg.setAttribute("width", "100%"); + svg.removeAttribute("height"); + } + }, + + // NB: there's effectively a copy of this function + // in `core/svg.ts`. + // if you change something here, you must keep it consistent there as well. + fixupAlignment(svg, align) { + let style = svg.getAttribute("style") || ""; + + switch (align) { + case "left": + style = `${style}; display: block; margin: auto auto auto 0`; + break; + case "right": + style = `${style}; display: block; margin: auto 0 auto auto`; + break; + case "center": + style = `${style}; display: block; margin: auto auto auto auto`; + break; + } + svg.setAttribute("style", style); + }, + + resolveOptions(svgEl) { + return svgEl.parentElement.parentElement.parentElement.parentElement + .dataset; + }, + + // NB: there's effectively a copy of this function + // in our mermaid runtime in `core/svg.ts`. + // if you change something here, you must keep it consistent there as well. + resolveSize(svgEl) { + const inInches = (size) => { + if (size.endsWith("in")) { + return Number(size.slice(0, -2)); + } + if (size.endsWith("pt") || size.endsWith("px")) { + // assume 96 dpi for now + return Number(size.slice(0, -2)) / 96; + } + return Number(size); + }; + + // these are figWidth and figHeight on purpose, + // because data attributes are translated to camelCase by the DOM API + const kFigWidth = "figWidth", + kFigHeight = "figHeight"; + const options = this.resolveOptions(svgEl); + let width = svgEl.getAttribute("width"); + let height = svgEl.getAttribute("height"); + const getViewBox = () => { + const vb = svgEl.attributes.getNamedItem("viewBox").value; // do it the roundabout way so that viewBox isn't dropped by deno_dom and text/html + if (!vb) return undefined; + const lst = vb.trim().split(" ").map(Number); + if (lst.length !== 4) return undefined; + if (lst.some(isNaN)) return undefined; + return lst; + }; + if (!width || !height) { + // attempt to resolve figure dimensions via viewBox + const viewBox = getViewBox(); + if (viewBox !== undefined) { + const [_mx, _my, vbWidth, vbHeight] = viewBox; + width = `${vbWidth}px`; + height = `${vbHeight}px`; + } else { + throw new Error( + "Mermaid generated an SVG without a viewbox attribute. Without knowing the diagram dimensions, quarto cannot convert it to a PNG" + ); + } + } + + let svgWidthInInches, svgHeightInInches; + + if ( + (width.slice(0, -2) === "pt" && height.slice(0, -2) === "pt") || + (width.slice(0, -2) === "px" && height.slice(0, -2) === "px") || + (!isNaN(Number(width)) && !isNaN(Number(height))) + ) { + // we assume 96 dpi which is generally what seems to be used. + svgWidthInInches = Number(width.slice(0, -2)) / 96; + svgHeightInInches = Number(height.slice(0, -2)) / 96; + } + const viewBox = getViewBox(); + if (viewBox !== undefined) { + // assume width and height come from viewbox. + const [_mx, _my, vbWidth, vbHeight] = viewBox; + svgWidthInInches = vbWidth / 96; + svgHeightInInches = vbHeight / 96; + } else { + throw new Error( + "Internal Error: Couldn't resolve width and height of SVG" + ); + } + const svgWidthOverHeight = svgWidthInInches / svgHeightInInches; + let widthInInches, heightInInches; + + if (options[kFigWidth] && options[kFigHeight]) { + // both were prescribed, so just go with them + widthInInches = inInches(String(options[kFigWidth])); + heightInInches = inInches(String(options[kFigHeight])); + } else if (options[kFigWidth]) { + // we were only given width, use that and adjust height based on aspect ratio; + widthInInches = inInches(String(options[kFigWidth])); + heightInInches = widthInInches / svgWidthOverHeight; + } else if (options[kFigHeight]) { + // we were only given height, use that and adjust width based on aspect ratio; + heightInInches = inInches(String(options[kFigHeight])); + widthInInches = heightInInches * svgWidthOverHeight; + } else { + // we were not given either, use svg's prescribed height + heightInInches = svgHeightInInches; + widthInInches = svgWidthInInches; + } + + return { + widthInInches, + heightInInches, + widthInPoints: Math.round(widthInInches * 96), + heightInPoints: Math.round(heightInInches * 96), + explicitWidth: options?.[kFigWidth] !== undefined, + explicitHeight: options?.[kFigHeight] !== undefined, + }; + }, + + postProcess(svg) { + const options = this.resolveOptions(svg); + if ( + options.responsive && + options["figWidth"] === undefined && + options["figHeight"] === undefined + ) { + this.makeResponsive(svg); + } else { + this.setSvgSize(svg); + } + if (options["reveal"]) { + this.fixupAlignment(svg, options["figAlign"] || "center"); + } + + // forward align attributes to the correct parent dif + // so that the svg figure is aligned correctly + const div = svg.parentElement.parentElement.parentElement; + const align = div.parentElement.parentElement.dataset.layoutAlign; + if (align) { + div.classList.remove("quarto-figure-left"); + div.classList.remove("quarto-figure-center"); + div.classList.remove("quarto-figure-right"); + div.classList.add(`quarto-figure-${align}`); + } + }, +}; + +// deno-lint-ignore no-window-prefix +window.addEventListener( + "load", + async function () { + let i = 0; + // we need pre because of whitespace preservation + for (const el of Array.from(document.querySelectorAll("pre.mermaid-js"))) { + //   doesn't appear to be treated as whitespace by mermaid + // so we replace it with a space. + const text = el.textContent.replaceAll(" ", " "); + const { svg: output } = await mermaid.mermaidAPI.render( + `mermaid-${++i}`, + text, + el + ); + el.innerHTML = output; + if (el.dataset.label) { + // patch mermaid's emitted style + const svg = el.firstChild; + const style = svg.querySelector("style"); + style.innerHTML = style.innerHTML.replaceAll( + `#${svg.id}`, + `#${el.dataset.label}-mermaid` + ); + svg.id = el.dataset.label + "-mermaid"; + delete el.dataset.label; + } + + const svg = el.querySelector("svg"); + const parent = el.parentElement; + parent.removeChild(el); + parent.appendChild(svg); + svg.classList.add("mermaid-js"); + } + for (const svgEl of Array.from( + document.querySelectorAll("svg.mermaid-js") + )) { + _quartoMermaid.postProcess(svgEl); + } + }, + false +); diff --git a/site_libs/quarto-diagram/mermaid.css b/site_libs/quarto-diagram/mermaid.css new file mode 100644 index 00000000..9f8bb7c7 --- /dev/null +++ b/site_libs/quarto-diagram/mermaid.css @@ -0,0 +1,13 @@ +.mermaidTooltip { + position: absolute; + text-align: center; + max-width: 200px; + padding: 2px; + font-family: "trebuchet ms", verdana, arial; + font-size: 12px; + background: #ffffde; + border: 1px solid #aaaa33; + border-radius: 2px; + pointer-events: none; + z-index: 1000; +} diff --git a/site_libs/quarto-diagram/mermaid.min.js b/site_libs/quarto-diagram/mermaid.min.js new file mode 100644 index 00000000..367f2e01 --- /dev/null +++ b/site_libs/quarto-diagram/mermaid.min.js @@ -0,0 +1,1621 @@ +(function(mN,cA){typeof exports=="object"&&typeof module<"u"?module.exports=cA():typeof define=="function"&&define.amd?define(cA):(mN=typeof globalThis<"u"?globalThis:mN||self,mN.mermaid=cA())})(this,function(){"use strict";function mN(i){for(var a=[],f=1;f=f?a:""+Array(f+1-w.length).join(p)+a},a5t=function(a){var f=-a.utcOffset(),p=Math.abs(f),w=Math.floor(p/60),y=p%60;return(f<=0?"+":"-")+Ffe(w,2,"0")+":"+Ffe(y,2,"0")},o5t=function i(a,f){if(a.date()1)return i(b[0])}else{var E=a.name;NE[E]=a,w=E}return!p&&w&&(kN=w),w||!p&&kN},ru=function(a,f){if(jfe(a))return a.clone();var p=typeof f=="object"?f:{};return p.date=a,p.args=arguments,new cU(p)},f5t=function(a,f){return ru(a,{locale:f.$L,utc:f.$u,x:f.$x,$offset:f.$offset})},tl=h5t;tl.l=oU,tl.i=jfe,tl.w=f5t;var d5t=function(a){var f=a.date,p=a.utc;if(f===null)return new Date(NaN);if(tl.u(f))return new Date;if(f instanceof Date)return new Date(f);if(typeof f=="string"&&!/Z$/i.test(f)){var w=f.match(r5t);if(w){var y=w[2]-1||0,b=(w[7]||"0").substring(0,3);return p?new Date(Date.UTC(w[1],y,w[3]||1,w[4]||0,w[5]||0,w[6]||0,b)):new Date(w[1],y,w[3]||1,w[4]||0,w[5]||0,w[6]||0,b)}}return new Date(f)},cU=function(){function i(f){this.$L=oU(f.locale,null,!0),this.parse(f)}var a=i.prototype;return a.parse=function(p){this.$d=d5t(p),this.$x=p.x||{},this.init()},a.init=function(){var p=this.$d;this.$y=p.getFullYear(),this.$M=p.getMonth(),this.$D=p.getDate(),this.$W=p.getDay(),this.$H=p.getHours(),this.$m=p.getMinutes(),this.$s=p.getSeconds(),this.$ms=p.getMilliseconds()},a.$utils=function(){return tl},a.isValid=function(){return this.$d.toString()!==yLe},a.isSame=function(p,w){var y=ru(p);return this.startOf(w)<=y&&y<=this.endOf(w)},a.isAfter=function(p,w){return ru(p){},debug:(...i)=>{},info:(...i)=>{},warn:(...i)=>{},error:(...i)=>{},fatal:(...i)=>{}},$fe=function(i="fatal"){let a=c5.fatal;typeof i=="string"?(i=i.toLowerCase(),i in c5&&(a=c5[i])):typeof i=="number"&&(a=i),Fe.trace=()=>{},Fe.debug=()=>{},Fe.info=()=>{},Fe.warn=()=>{},Fe.error=()=>{},Fe.fatal=()=>{},a<=c5.fatal&&(Fe.fatal=console.error?console.error.bind(console,Gb("FATAL"),"color: orange"):console.log.bind(console,"\x1B[35m",Gb("FATAL"))),a<=c5.error&&(Fe.error=console.error?console.error.bind(console,Gb("ERROR"),"color: orange"):console.log.bind(console,"\x1B[31m",Gb("ERROR"))),a<=c5.warn&&(Fe.warn=console.warn?console.warn.bind(console,Gb("WARN"),"color: orange"):console.log.bind(console,"\x1B[33m",Gb("WARN"))),a<=c5.info&&(Fe.info=console.info?console.info.bind(console,Gb("INFO"),"color: lightblue"):console.log.bind(console,"\x1B[34m",Gb("INFO"))),a<=c5.debug&&(Fe.debug=console.debug?console.debug.bind(console,Gb("DEBUG"),"color: lightgreen"):console.log.bind(console,"\x1B[32m",Gb("DEBUG"))),a<=c5.trace&&(Fe.trace=console.debug?console.debug.bind(console,Gb("TRACE"),"color: lightgreen"):console.log.bind(console,"\x1B[32m",Gb("TRACE")))},Gb=i=>`%c${ru().format("ss.SSS")} : ${i} : `;var Wk=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function xLe(i){return i&&i.__esModule&&Object.prototype.hasOwnProperty.call(i,"default")?i.default:i}var Hfe={};Object.defineProperty(Hfe,"__esModule",{value:!0});var u5=Hfe.sanitizeUrl=void 0,g5t=/^([^\w]*)(javascript|data|vbscript)/im,p5t=/&#(\w+)(^\w|;)?/g,b5t=/&(newline|tab);/gi,v5t=/[\u0000-\u001F\u007F-\u009F\u2000-\u200D\uFEFF]/gim,w5t=/^.+(:|:)/gim,m5t=[".","/"];function y5t(i){return m5t.indexOf(i[0])>-1}function k5t(i){return i.replace(p5t,function(a,f){return String.fromCharCode(f)})}function x5t(i){var a=k5t(i||"").replace(b5t,"").replace(v5t,"").trim();if(!a)return"about:blank";if(y5t(a))return a;var f=a.match(w5t);if(!f)return a;var p=f[0];return g5t.test(p)?"about:blank":a}u5=Hfe.sanitizeUrl=x5t;function uU(i,a){return i==null||a==null?NaN:ia?1:i>=a?0:NaN}function E5t(i,a){return i==null||a==null?NaN:ai?1:a>=i?0:NaN}function zfe(i){let a,f,p;i.length!==2?(a=uU,f=(E,S)=>uU(i(E),S),p=(E,S)=>i(E)-S):(a=i===uU||i===E5t?i:T5t,f=i,p=i);function w(E,S,N=0,B=E.length){if(N>>1;f(E[R],S)<0?N=R+1:B=R}while(N>>1;f(E[R],S)<=0?N=R+1:B=R}while(NN&&p(E[R-1],S)>-p(E[R],S)?R-1:R}return{left:w,center:b,right:y}}function T5t(){return 0}function _5t(i){return i===null?NaN:+i}const C5t=zfe(uU).right;zfe(_5t).center;const S5t=C5t;class ELe extends Map{constructor(a,f=M5t){if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:f}}),a!=null)for(const[p,w]of a)this.set(p,w)}get(a){return super.get(TLe(this,a))}has(a){return super.has(TLe(this,a))}set(a,f){return super.set(A5t(this,a),f)}delete(a){return super.delete(L5t(this,a))}}function TLe({_intern:i,_key:a},f){const p=a(f);return i.has(p)?i.get(p):f}function A5t({_intern:i,_key:a},f){const p=a(f);return i.has(p)?i.get(p):(i.set(p,f),f)}function L5t({_intern:i,_key:a},f){const p=a(f);return i.has(p)&&(f=i.get(p),i.delete(p)),f}function M5t(i){return i!==null&&typeof i=="object"?i.valueOf():i}var Gfe=Math.sqrt(50),qfe=Math.sqrt(10),Vfe=Math.sqrt(2);function D5t(i,a,f){var p,w=-1,y,b,E;if(a=+a,i=+i,f=+f,i===a&&f>0)return[i];if((p=a0){let S=Math.round(i/E),N=Math.round(a/E);for(S*Ea&&--N,b=new Array(y=N-S+1);++wa&&--N,b=new Array(y=N-S+1);++w=0?(y>=Gfe?10:y>=qfe?5:y>=Vfe?2:1)*Math.pow(10,w):-Math.pow(10,-w)/(y>=Gfe?10:y>=qfe?5:y>=Vfe?2:1)}function Ufe(i,a,f){var p=Math.abs(a-i)/Math.max(0,f),w=Math.pow(10,Math.floor(Math.log(p)/Math.LN10)),y=p/w;return y>=Gfe?w*=10:y>=qfe?w*=5:y>=Vfe&&(w*=2),a=p)&&(f=p);else{let p=-1;for(let w of i)(w=a(w,++p,i))!=null&&(f=w)&&(f=w)}return f}function O5t(i,a){let f;if(a===void 0)for(const p of i)p!=null&&(f>p||f===void 0&&p>=p)&&(f=p);else{let p=-1;for(let w of i)(w=a(w,++p,i))!=null&&(f>w||f===void 0&&w>=w)&&(f=w)}return f}function N5t(i){return i}var lU=1,Wfe=2,Kfe=3,hU=4,CLe=1e-6;function P5t(i){return"translate("+i+",0)"}function B5t(i){return"translate(0,"+i+")"}function R5t(i){return a=>+i(a)}function F5t(i,a){return a=Math.max(0,i.bandwidth()-a*2)/2,i.round()&&(a=Math.round(a)),f=>+i(f)+a}function j5t(){return!this.__axis}function SLe(i,a){var f=[],p=null,w=null,y=6,b=6,E=3,S=typeof window<"u"&&window.devicePixelRatio>1?0:.5,N=i===lU||i===hU?-1:1,B=i===hU||i===Wfe?"x":"y",R=i===lU||i===Kfe?P5t:B5t;function j($){var V=p??(a.ticks?a.ticks.apply(a,f):a.domain()),Q=w??(a.tickFormat?a.tickFormat.apply(a,f):N5t),oe=Math.max(y,0)+E,ce=a.range(),se=+ce[0]+S,ge=+ce[ce.length-1]+S,ye=(a.bandwidth?F5t:R5t)(a.copy(),S),ke=$.selection?$.selection():$,Ae=ke.selectAll(".domain").data([null]),de=ke.selectAll(".tick").data(V,a).order(),ve=de.exit(),te=de.enter().append("g").attr("class","tick"),xe=de.select("line"),De=de.select("text");Ae=Ae.merge(Ae.enter().insert("path",".tick").attr("class","domain").attr("stroke","currentColor")),de=de.merge(te),xe=xe.merge(te.append("line").attr("stroke","currentColor").attr(B+"2",N*y)),De=De.merge(te.append("text").attr("fill","currentColor").attr(B,N*oe).attr("dy",i===lU?"0em":i===Kfe?"0.71em":"0.32em")),$!==ke&&(Ae=Ae.transition($),de=de.transition($),xe=xe.transition($),De=De.transition($),ve=ve.transition($).attr("opacity",CLe).attr("transform",function(he){return isFinite(he=ye(he))?R(he+S):this.getAttribute("transform")}),te.attr("opacity",CLe).attr("transform",function(he){var Ie=this.parentNode.__axis;return R((Ie&&isFinite(Ie=Ie(he))?Ie:ye(he))+S)})),ve.remove(),Ae.attr("d",i===hU||i===Wfe?b?"M"+N*b+","+se+"H"+S+"V"+ge+"H"+N*b:"M"+S+","+se+"V"+ge:b?"M"+se+","+N*b+"V"+S+"H"+ge+"V"+N*b:"M"+se+","+S+"H"+ge),de.attr("opacity",1).attr("transform",function(he){return R(ye(he)+S)}),xe.attr(B+"2",N*y),De.attr(B,N*oe).text(Q),ke.filter(j5t).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",i===Wfe?"start":i===hU?"end":"middle"),ke.each(function(){this.__axis=ye})}return j.scale=function($){return arguments.length?(a=$,j):a},j.ticks=function(){return f=Array.from(arguments),j},j.tickArguments=function($){return arguments.length?(f=$==null?[]:Array.from($),j):f.slice()},j.tickValues=function($){return arguments.length?(p=$==null?null:Array.from($),j):p&&p.slice()},j.tickFormat=function($){return arguments.length?(w=$,j):w},j.tickSize=function($){return arguments.length?(y=b=+$,j):y},j.tickSizeInner=function($){return arguments.length?(y=+$,j):y},j.tickSizeOuter=function($){return arguments.length?(b=+$,j):b},j.tickPadding=function($){return arguments.length?(E=+$,j):E},j.offset=function($){return arguments.length?(S=+$,j):S},j}function $5t(i){return SLe(lU,i)}function H5t(i){return SLe(Kfe,i)}var z5t={value:()=>{}};function ALe(){for(var i=0,a=arguments.length,f={},p;i=0&&(p=f.slice(w+1),f=f.slice(0,w)),f&&!a.hasOwnProperty(f))throw new Error("unknown type: "+f);return{type:f,name:p}})}fU.prototype=ALe.prototype={constructor:fU,on:function(i,a){var f=this._,p=G5t(i+"",f),w,y=-1,b=p.length;if(arguments.length<2){for(;++y0)for(var f=new Array(w),p=0,w,y;p=0&&(a=i.slice(0,f))!=="xmlns"&&(i=i.slice(f+1)),MLe.hasOwnProperty(a)?{space:MLe[a],local:i}:i}function V5t(i){return function(){var a=this.ownerDocument,f=this.namespaceURI;return f===Yfe&&a.documentElement.namespaceURI===Yfe?a.createElement(i):a.createElementNS(f,i)}}function U5t(i){return function(){return this.ownerDocument.createElementNS(i.space,i.local)}}function DLe(i){var a=dU(i);return(a.local?U5t:V5t)(a)}function W5t(){}function Xfe(i){return i==null?W5t:function(){return this.querySelector(i)}}function K5t(i){typeof i!="function"&&(i=Xfe(i));for(var a=this._groups,f=a.length,p=new Array(f),w=0;w=ge&&(ge=se+1);!(ke=oe[ge])&&++ge=0;)(b=p[w])&&(y&&b.compareDocumentPosition(y)^4&&y.parentNode.insertBefore(b,y),y=b);return this}function w6t(i){i||(i=m6t);function a(R,j){return R&&j?i(R.__data__,j.__data__):!R-!j}for(var f=this._groups,p=f.length,w=new Array(p),y=0;ya?1:i>=a?0:NaN}function y6t(){var i=arguments[0];return arguments[0]=this,i.apply(null,arguments),this}function k6t(){return Array.from(this)}function x6t(){for(var i=this._groups,a=0,f=i.length;a1?this.each((a==null?O6t:typeof a=="function"?P6t:N6t)(i,a,f??"")):gA(this.node(),i)}function gA(i,a){return i.style.getPropertyValue(a)||RLe(i).getComputedStyle(i,null).getPropertyValue(a)}function R6t(i){return function(){delete this[i]}}function F6t(i,a){return function(){this[i]=a}}function j6t(i,a){return function(){var f=a.apply(this,arguments);f==null?delete this[i]:this[i]=f}}function $6t(i,a){return arguments.length>1?this.each((a==null?R6t:typeof a=="function"?j6t:F6t)(i,a)):this.node()[i]}function FLe(i){return i.trim().split(/^|\s+/)}function Qfe(i){return i.classList||new jLe(i)}function jLe(i){this._node=i,this._names=FLe(i.getAttribute("class")||"")}jLe.prototype={add:function(i){var a=this._names.indexOf(i);a<0&&(this._names.push(i),this._node.setAttribute("class",this._names.join(" ")))},remove:function(i){var a=this._names.indexOf(i);a>=0&&(this._names.splice(a,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(i){return this._names.indexOf(i)>=0}};function $Le(i,a){for(var f=Qfe(i),p=-1,w=a.length;++p=0&&(f=a.slice(p+1),a=a.slice(0,p)),{type:a,name:f}})}function gkt(i){return function(){var a=this.__on;if(a){for(var f=0,p=-1,w=a.length,y;f>8&15|a>>4&240,a>>4&15|a&240,(a&15)<<4|a&15,1):f===8?vU(a>>24&255,a>>16&255,a>>8&255,(a&255)/255):f===4?vU(a>>12&15|a>>8&240,a>>8&15|a>>4&240,a>>4&15|a&240,((a&15)<<4|a&15)/255):null):(a=Ekt.exec(i))?new v0(a[1],a[2],a[3],1):(a=Tkt.exec(i))?new v0(a[1]*255/100,a[2]*255/100,a[3]*255/100,1):(a=_kt.exec(i))?vU(a[1],a[2],a[3],a[4]):(a=Ckt.exec(i))?vU(a[1]*255/100,a[2]*255/100,a[3]*255/100,a[4]):(a=Skt.exec(i))?XLe(a[1],a[2]/100,a[3]/100,1):(a=Akt.exec(i))?XLe(a[1],a[2]/100,a[3]/100,a[4]):GLe.hasOwnProperty(i)?ULe(GLe[i]):i==="transparent"?new v0(NaN,NaN,NaN,0):null}function ULe(i){return new v0(i>>16&255,i>>8&255,i&255,1)}function vU(i,a,f,p){return p<=0&&(i=a=f=NaN),new v0(i,a,f,p)}function WLe(i){return i instanceof PE||(i=BE(i)),i?(i=i.rgb(),new v0(i.r,i.g,i.b,i.opacity)):new v0}function e1e(i,a,f,p){return arguments.length===1?WLe(i):new v0(i,a,f,p??1)}function v0(i,a,f,p){this.r=+i,this.g=+a,this.b=+f,this.opacity=+p}EN(v0,e1e,pU(PE,{brighter(i){return i=i==null?bU:Math.pow(bU,i),new v0(this.r*i,this.g*i,this.b*i,this.opacity)},darker(i){return i=i==null?TN:Math.pow(TN,i),new v0(this.r*i,this.g*i,this.b*i,this.opacity)},rgb(){return this},clamp(){return new v0(RE(this.r),RE(this.g),RE(this.b),wU(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:KLe,formatHex:KLe,formatHex8:Dkt,formatRgb:YLe,toString:YLe}));function KLe(){return`#${FE(this.r)}${FE(this.g)}${FE(this.b)}`}function Dkt(){return`#${FE(this.r)}${FE(this.g)}${FE(this.b)}${FE((isNaN(this.opacity)?1:this.opacity)*255)}`}function YLe(){const i=wU(this.opacity);return`${i===1?"rgb(":"rgba("}${RE(this.r)}, ${RE(this.g)}, ${RE(this.b)}${i===1?")":`, ${i})`}`}function wU(i){return isNaN(i)?1:Math.max(0,Math.min(1,i))}function RE(i){return Math.max(0,Math.min(255,Math.round(i)||0))}function FE(i){return i=RE(i),(i<16?"0":"")+i.toString(16)}function XLe(i,a,f,p){return p<=0?i=a=f=NaN:f<=0||f>=1?i=a=NaN:a<=0&&(i=NaN),new $w(i,a,f,p)}function QLe(i){if(i instanceof $w)return new $w(i.h,i.s,i.l,i.opacity);if(i instanceof PE||(i=BE(i)),!i)return new $w;if(i instanceof $w)return i;i=i.rgb();var a=i.r/255,f=i.g/255,p=i.b/255,w=Math.min(a,f,p),y=Math.max(a,f,p),b=NaN,E=y-w,S=(y+w)/2;return E?(a===y?b=(f-p)/E+(f0&&S<1?0:b,new $w(b,E,S,i.opacity)}function Ikt(i,a,f,p){return arguments.length===1?QLe(i):new $w(i,a,f,p??1)}function $w(i,a,f,p){this.h=+i,this.s=+a,this.l=+f,this.opacity=+p}EN($w,Ikt,pU(PE,{brighter(i){return i=i==null?bU:Math.pow(bU,i),new $w(this.h,this.s,this.l*i,this.opacity)},darker(i){return i=i==null?TN:Math.pow(TN,i),new $w(this.h,this.s,this.l*i,this.opacity)},rgb(){var i=this.h%360+(this.h<0)*360,a=isNaN(i)||isNaN(this.s)?0:this.s,f=this.l,p=f+(f<.5?f:1-f)*a,w=2*f-p;return new v0(t1e(i>=240?i-240:i+120,w,p),t1e(i,w,p),t1e(i<120?i+240:i-120,w,p),this.opacity)},clamp(){return new $w(ZLe(this.h),mU(this.s),mU(this.l),wU(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const i=wU(this.opacity);return`${i===1?"hsl(":"hsla("}${ZLe(this.h)}, ${mU(this.s)*100}%, ${mU(this.l)*100}%${i===1?")":`, ${i})`}`}}));function ZLe(i){return i=(i||0)%360,i<0?i+360:i}function mU(i){return Math.max(0,Math.min(1,i||0))}function t1e(i,a,f){return(i<60?a+(f-a)*i/60:i<180?f:i<240?a+(f-a)*(240-i)/60:a)*255}const Okt=Math.PI/180,Nkt=180/Math.PI,yU=18,JLe=.96422,eMe=1,tMe=.82521,nMe=4/29,bA=6/29,rMe=3*bA*bA,Pkt=bA*bA*bA;function iMe(i){if(i instanceof Jy)return new Jy(i.l,i.a,i.b,i.opacity);if(i instanceof l5)return sMe(i);i instanceof v0||(i=WLe(i));var a=s1e(i.r),f=s1e(i.g),p=s1e(i.b),w=n1e((.2225045*a+.7168786*f+.0606169*p)/eMe),y,b;return a===f&&f===p?y=b=w:(y=n1e((.4360747*a+.3850649*f+.1430804*p)/JLe),b=n1e((.0139322*a+.0971045*f+.7141733*p)/tMe)),new Jy(116*w-16,500*(y-w),200*(w-b),i.opacity)}function Bkt(i,a,f,p){return arguments.length===1?iMe(i):new Jy(i,a,f,p??1)}function Jy(i,a,f,p){this.l=+i,this.a=+a,this.b=+f,this.opacity=+p}EN(Jy,Bkt,pU(PE,{brighter(i){return new Jy(this.l+yU*(i??1),this.a,this.b,this.opacity)},darker(i){return new Jy(this.l-yU*(i??1),this.a,this.b,this.opacity)},rgb(){var i=(this.l+16)/116,a=isNaN(this.a)?i:i+this.a/500,f=isNaN(this.b)?i:i-this.b/200;return a=JLe*r1e(a),i=eMe*r1e(i),f=tMe*r1e(f),new v0(i1e(3.1338561*a-1.6168667*i-.4906146*f),i1e(-.9787684*a+1.9161415*i+.033454*f),i1e(.0719453*a-.2289914*i+1.4052427*f),this.opacity)}}));function n1e(i){return i>Pkt?Math.pow(i,1/3):i/rMe+nMe}function r1e(i){return i>bA?i*i*i:rMe*(i-nMe)}function i1e(i){return 255*(i<=.0031308?12.92*i:1.055*Math.pow(i,1/2.4)-.055)}function s1e(i){return(i/=255)<=.04045?i/12.92:Math.pow((i+.055)/1.055,2.4)}function Rkt(i){if(i instanceof l5)return new l5(i.h,i.c,i.l,i.opacity);if(i instanceof Jy||(i=iMe(i)),i.a===0&&i.b===0)return new l5(NaN,0()=>i;function aMe(i,a){return function(f){return i+f*a}}function Fkt(i,a,f){return i=Math.pow(i,f),a=Math.pow(a,f)-i,f=1/f,function(p){return Math.pow(i+p*a,f)}}function jkt(i,a){var f=a-i;return f?aMe(i,f>180||f<-180?f-360*Math.round(f/360):f):kU(isNaN(i)?a:i)}function $kt(i){return(i=+i)==1?CN:function(a,f){return f-a?Fkt(a,f,i):kU(isNaN(a)?f:a)}}function CN(i,a){var f=a-i;return f?aMe(i,f):kU(isNaN(i)?a:i)}const xU=function i(a){var f=$kt(a);function p(w,y){var b=f((w=e1e(w)).r,(y=e1e(y)).r),E=f(w.g,y.g),S=f(w.b,y.b),N=CN(w.opacity,y.opacity);return function(B){return w.r=b(B),w.g=E(B),w.b=S(B),w.opacity=N(B),w+""}}return p.gamma=i,p}(1);function Hkt(i,a){a||(a=[]);var f=i?Math.min(a.length,i.length):0,p=a.slice(),w;return function(y){for(w=0;wf&&(y=a.slice(f,y),E[b]?E[b]+=y:E[++b]=y),(p=p[0])===(w=w[0])?E[b]?E[b]+=w:E[++b]=w:(E[++b]=null,S.push({i:b,x:Hw(p,w)})),f=c1e.lastIndex;return f180?B+=360:B-N>180&&(N+=360),j.push({i:R.push(w(R)+"rotate(",null,p)-2,x:Hw(N,B)})):B&&R.push(w(R)+"rotate("+B+p)}function E(N,B,R,j){N!==B?j.push({i:R.push(w(R)+"skewX(",null,p)-2,x:Hw(N,B)}):B&&R.push(w(R)+"skewX("+B+p)}function S(N,B,R,j,$,V){if(N!==R||B!==j){var Q=$.push(w($)+"scale(",null,",",null,")");V.push({i:Q-4,x:Hw(N,R)},{i:Q-2,x:Hw(B,j)})}else(R!==1||j!==1)&&$.push(w($)+"scale("+R+","+j+")")}return function(N,B){var R=[],j=[];return N=i(N),B=i(B),y(N.translateX,N.translateY,B.translateX,B.translateY,R,j),b(N.rotate,B.rotate,R,j),E(N.skewX,B.skewX,R,j),S(N.scaleX,N.scaleY,B.scaleX,B.scaleY,R,j),N=B=null,function($){for(var V=-1,Q=j.length,oe;++V=0&&i._call.call(void 0,a),i=i._next;--vA}function gMe(){jE=(_U=MN.now())+CU,vA=SN=0;try{nxt()}finally{vA=0,ixt(),jE=0}}function rxt(){var i=MN.now(),a=i-_U;a>hMe&&(CU-=a,_U=i)}function ixt(){for(var i,a=TU,f,p=1/0;a;)a._call?(p>a._time&&(p=a._time),i=a,a=a._next):(f=a._next,a._next=null,a=i?i._next=f:TU=f);LN=i,f1e(p)}function f1e(i){if(!vA){SN&&(SN=clearTimeout(SN));var a=i-jE;a>24?(i<1/0&&(SN=setTimeout(gMe,i-MN.now()-CU)),AN&&(AN=clearInterval(AN))):(AN||(_U=MN.now(),AN=setInterval(rxt,hMe)),vA=1,fMe(gMe))}}function pMe(i,a,f){var p=new SU;return a=a==null?0:+a,p.restart(w=>{p.stop(),i(w+a)},a,f),p}var sxt=ALe("start","end","cancel","interrupt"),axt=[],bMe=0,vMe=1,d1e=2,AU=3,wMe=4,g1e=5,LU=6;function MU(i,a,f,p,w,y){var b=i.__transition;if(!b)i.__transition={};else if(f in b)return;oxt(i,f,{name:a,index:p,group:w,on:sxt,tween:axt,time:y.time,delay:y.delay,duration:y.duration,ease:y.ease,timer:null,state:bMe})}function p1e(i,a){var f=zw(i,a);if(f.state>bMe)throw new Error("too late; already scheduled");return f}function e3(i,a){var f=zw(i,a);if(f.state>AU)throw new Error("too late; already running");return f}function zw(i,a){var f=i.__transition;if(!f||!(f=f[a]))throw new Error("transition not found");return f}function oxt(i,a,f){var p=i.__transition,w;p[a]=f,f.timer=dMe(y,0,f.time);function y(N){f.state=vMe,f.timer.restart(b,f.delay,f.time),f.delay<=N&&b(N-f.delay)}function b(N){var B,R,j,$;if(f.state!==vMe)return S();for(B in p)if($=p[B],$.name===f.name){if($.state===AU)return pMe(b);$.state===wMe?($.state=LU,$.timer.stop(),$.on.call("interrupt",i,i.__data__,$.index,$.group),delete p[B]):+Bd1e&&p.state=0&&(a=a.slice(0,f)),!a||a==="start"})}function Fxt(i,a,f){var p,w,y=Rxt(a)?p1e:e3;return function(){var b=y(this,i),E=b.on;E!==p&&(w=(p=E).copy()).on(a,f),b.on=w}}function jxt(i,a){var f=this._id;return arguments.length<2?zw(this.node(),f).on.on(i):this.each(Fxt(f,i,a))}function $xt(i){return function(){var a=this.parentNode;for(var f in this.__transition)if(+f!==i)return;a&&a.removeChild(this)}}function Hxt(){return this.on("end.remove",$xt(this._id))}function zxt(i){var a=this._name,f=this._id;typeof i!="function"&&(i=Xfe(i));for(var p=this._groups,w=p.length,y=new Array(w),b=0;b$E)if(!(Math.abs(B*E-S*N)>$E)||!w)this._+="L"+(this._x1=i)+","+(this._y1=a);else{var j=f-y,$=p-b,V=E*E+S*S,Q=j*j+$*$,oe=Math.sqrt(V),ce=Math.sqrt(R),se=w*Math.tan((v1e-Math.acos((V+R-Q)/(2*oe*ce)))/2),ge=se/ce,ye=se/oe;Math.abs(ge-1)>$E&&(this._+="L"+(i+ge*N)+","+(a+ge*B)),this._+="A"+w+","+w+",0,0,"+ +(B*j>N*$)+","+(this._x1=i+ye*E)+","+(this._y1=a+ye*S)}},arc:function(i,a,f,p,w,y){i=+i,a=+a,f=+f,y=!!y;var b=f*Math.cos(p),E=f*Math.sin(p),S=i+b,N=a+E,B=1^y,R=y?p-w:w-p;if(f<0)throw new Error("negative radius: "+f);this._x1===null?this._+="M"+S+","+N:(Math.abs(this._x1-S)>$E||Math.abs(this._y1-N)>$E)&&(this._+="L"+S+","+N),f&&(R<0&&(R=R%w1e+w1e),R>d8t?this._+="A"+f+","+f+",0,1,"+B+","+(i-b)+","+(a-E)+"A"+f+","+f+",0,1,"+B+","+(this._x1=S)+","+(this._y1=N):R>$E&&(this._+="A"+f+","+f+",0,"+ +(R>=v1e)+","+B+","+(this._x1=i+f*Math.cos(w))+","+(this._y1=a+f*Math.sin(w))))},rect:function(i,a,f,p){this._+="M"+(this._x0=this._x1=+i)+","+(this._y0=this._y1=+a)+"h"+ +f+"v"+ +p+"h"+-f+"Z"},toString:function(){return this._}};function g8t(i){if(!i.ok)throw new Error(i.status+" "+i.statusText);return i.text()}function p8t(i,a){return fetch(i,a).then(g8t)}function b8t(i){return(a,f)=>p8t(a,f).then(p=>new DOMParser().parseFromString(p,i))}var v8t=b8t("image/svg+xml");function w8t(i){return Math.abs(i=Math.round(i))>=1e21?i.toLocaleString("en").replace(/,/g,""):i.toString(10)}function DU(i,a){if((f=(i=a?i.toExponential(a-1):i.toExponential()).indexOf("e"))<0)return null;var f,p=i.slice(0,f);return[p.length>1?p[0]+p.slice(2):p,+i.slice(f+1)]}function wA(i){return i=DU(Math.abs(i)),i?i[1]:NaN}function m8t(i,a){return function(f,p){for(var w=f.length,y=[],b=0,E=i[0],S=0;w>0&&E>0&&(S+E+1>p&&(E=Math.max(1,p-S)),y.push(f.substring(w-=E,w+E)),!((S+=E+1)>p));)E=i[b=(b+1)%i.length];return y.reverse().join(a)}}function y8t(i){return function(a){return a.replace(/[0-9]/g,function(f){return i[+f]})}}var k8t=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function IU(i){if(!(a=k8t.exec(i)))throw new Error("invalid format: "+i);var a;return new k1e({fill:a[1],align:a[2],sign:a[3],symbol:a[4],zero:a[5],width:a[6],comma:a[7],precision:a[8]&&a[8].slice(1),trim:a[9],type:a[10]})}IU.prototype=k1e.prototype;function k1e(i){this.fill=i.fill===void 0?" ":i.fill+"",this.align=i.align===void 0?">":i.align+"",this.sign=i.sign===void 0?"-":i.sign+"",this.symbol=i.symbol===void 0?"":i.symbol+"",this.zero=!!i.zero,this.width=i.width===void 0?void 0:+i.width,this.comma=!!i.comma,this.precision=i.precision===void 0?void 0:+i.precision,this.trim=!!i.trim,this.type=i.type===void 0?"":i.type+""}k1e.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(this.width===void 0?"":Math.max(1,this.width|0))+(this.comma?",":"")+(this.precision===void 0?"":"."+Math.max(0,this.precision|0))+(this.trim?"~":"")+this.type};function x8t(i){e:for(var a=i.length,f=1,p=-1,w;f0&&(p=0);break}return p>0?i.slice(0,p)+i.slice(w+1):i}var xMe;function E8t(i,a){var f=DU(i,a);if(!f)return i+"";var p=f[0],w=f[1],y=w-(xMe=Math.max(-8,Math.min(8,Math.floor(w/3)))*3)+1,b=p.length;return y===b?p:y>b?p+new Array(y-b+1).join("0"):y>0?p.slice(0,y)+"."+p.slice(y):"0."+new Array(1-y).join("0")+DU(i,Math.max(0,a+y-1))[0]}function EMe(i,a){var f=DU(i,a);if(!f)return i+"";var p=f[0],w=f[1];return w<0?"0."+new Array(-w).join("0")+p:p.length>w+1?p.slice(0,w+1)+"."+p.slice(w+1):p+new Array(w-p.length+2).join("0")}const TMe={"%":(i,a)=>(i*100).toFixed(a),b:i=>Math.round(i).toString(2),c:i=>i+"",d:w8t,e:(i,a)=>i.toExponential(a),f:(i,a)=>i.toFixed(a),g:(i,a)=>i.toPrecision(a),o:i=>Math.round(i).toString(8),p:(i,a)=>EMe(i*100,a),r:EMe,s:E8t,X:i=>Math.round(i).toString(16).toUpperCase(),x:i=>Math.round(i).toString(16)};function _Me(i){return i}var CMe=Array.prototype.map,SMe=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];function T8t(i){var a=i.grouping===void 0||i.thousands===void 0?_Me:m8t(CMe.call(i.grouping,Number),i.thousands+""),f=i.currency===void 0?"":i.currency[0]+"",p=i.currency===void 0?"":i.currency[1]+"",w=i.decimal===void 0?".":i.decimal+"",y=i.numerals===void 0?_Me:y8t(CMe.call(i.numerals,String)),b=i.percent===void 0?"%":i.percent+"",E=i.minus===void 0?"−":i.minus+"",S=i.nan===void 0?"NaN":i.nan+"";function N(R){R=IU(R);var j=R.fill,$=R.align,V=R.sign,Q=R.symbol,oe=R.zero,ce=R.width,se=R.comma,ge=R.precision,ye=R.trim,ke=R.type;ke==="n"?(se=!0,ke="g"):TMe[ke]||(ge===void 0&&(ge=12),ye=!0,ke="g"),(oe||j==="0"&&$==="=")&&(oe=!0,j="0",$="=");var Ae=Q==="$"?f:Q==="#"&&/[boxX]/.test(ke)?"0"+ke.toLowerCase():"",de=Q==="$"?p:/[%p]/.test(ke)?b:"",ve=TMe[ke],te=/[defgprs%]/.test(ke);ge=ge===void 0?6:/[gprs]/.test(ke)?Math.max(1,Math.min(21,ge)):Math.max(0,Math.min(20,ge));function xe(De){var he=Ae,Ie=de,ee,rt,me;if(ke==="c")Ie=ve(De)+Ie,De="";else{De=+De;var gt=De<0||1/De<0;if(De=isNaN(De)?S:ve(Math.abs(De),ge),ye&&(De=x8t(De)),gt&&+De==0&&V!=="+"&&(gt=!1),he=(gt?V==="("?V:E:V==="-"||V==="("?"":V)+he,Ie=(ke==="s"?SMe[8+xMe/3]:"")+Ie+(gt&&V==="("?")":""),te){for(ee=-1,rt=De.length;++eeme||me>57){Ie=(me===46?w+De.slice(ee+1):De.slice(ee))+Ie,De=De.slice(0,ee);break}}}se&&!oe&&(De=a(De,1/0));var pe=he.length+De.length+Ie.length,Et=pe>1)+he+De+Ie+Et.slice(pe);break;default:De=Et+he+De+Ie;break}return y(De)}return xe.toString=function(){return R+""},xe}function B(R,j){var $=N((R=IU(R),R.type="f",R)),V=Math.max(-8,Math.min(8,Math.floor(wA(j)/3)))*3,Q=Math.pow(10,-V),oe=SMe[8+V/3];return function(ce){return $(Q*ce)+oe}}return{format:N,formatPrefix:B}}var OU,AMe,LMe;_8t({thousands:",",grouping:[3],currency:["$",""]});function _8t(i){return OU=T8t(i),AMe=OU.format,LMe=OU.formatPrefix,OU}function C8t(i){return Math.max(0,-wA(Math.abs(i)))}function S8t(i,a){return Math.max(0,Math.max(-8,Math.min(8,Math.floor(wA(a)/3)))*3-wA(Math.abs(i)))}function A8t(i,a){return i=Math.abs(i),a=Math.abs(a)-i,Math.max(0,wA(a)-wA(i))+1}function x1e(i,a){switch(arguments.length){case 0:break;case 1:this.range(i);break;default:this.range(a).domain(i);break}return this}const MMe=Symbol("implicit");function DMe(){var i=new ELe,a=[],f=[],p=MMe;function w(y){let b=i.get(y);if(b===void 0){if(p!==MMe)return p;i.set(y,b=a.push(y)-1)}return f[b%f.length]}return w.domain=function(y){if(!arguments.length)return a.slice();a=[],i=new ELe;for(const b of y)i.has(b)||i.set(b,a.push(b)-1);return w},w.range=function(y){return arguments.length?(f=Array.from(y),w):f.slice()},w.unknown=function(y){return arguments.length?(p=y,w):p},w.copy=function(){return DMe(a,f).unknown(p)},x1e.apply(w,arguments),w}function L8t(i){return function(){return i}}function M8t(i){return+i}var IMe=[0,1];function mA(i){return i}function E1e(i,a){return(a-=i=+i)?function(f){return(f-i)/a}:L8t(isNaN(a)?NaN:.5)}function D8t(i,a){var f;return i>a&&(f=i,i=a,a=f),function(p){return Math.max(i,Math.min(a,p))}}function I8t(i,a,f){var p=i[0],w=i[1],y=a[0],b=a[1];return w2?O8t:I8t,S=N=null,R}function R(j){return j==null||isNaN(j=+j)?y:(S||(S=E(i.map(p),a,f)))(p(b(j)))}return R.invert=function(j){return b(w((N||(N=E(a,i.map(p),Hw)))(j)))},R.domain=function(j){return arguments.length?(i=Array.from(j,M8t),B()):i.slice()},R.range=function(j){return arguments.length?(a=Array.from(j),B()):a.slice()},R.rangeRound=function(j){return a=Array.from(j),f=Kkt,B()},R.clamp=function(j){return arguments.length?(b=j?!0:mA,B()):b!==mA},R.interpolate=function(j){return arguments.length?(f=j,B()):f},R.unknown=function(j){return arguments.length?(y=j,R):y},function(j,$){return p=j,w=$,B()}}function NMe(){return N8t()(mA,mA)}function P8t(i,a,f,p){var w=Ufe(i,a,f),y;switch(p=IU(p??",f"),p.type){case"s":{var b=Math.max(Math.abs(i),Math.abs(a));return p.precision==null&&!isNaN(y=S8t(w,b))&&(p.precision=y),LMe(p,b)}case"":case"e":case"g":case"p":case"r":{p.precision==null&&!isNaN(y=A8t(w,Math.max(Math.abs(i),Math.abs(a))))&&(p.precision=y-(p.type==="e"));break}case"f":case"%":{p.precision==null&&!isNaN(y=C8t(w))&&(p.precision=y-(p.type==="%")*2);break}}return AMe(p)}function B8t(i){var a=i.domain;return i.ticks=function(f){var p=a();return D5t(p[0],p[p.length-1],f??10)},i.tickFormat=function(f,p){var w=a();return P8t(w[0],w[w.length-1],f??10,p)},i.nice=function(f){f==null&&(f=10);var p=a(),w=0,y=p.length-1,b=p[w],E=p[y],S,N,B=10;for(E0;){if(N=_Le(b,E,f),N===S)return p[w]=b,p[y]=E,a(p);if(N>0)b=Math.floor(b/N)*N,E=Math.ceil(E/N)*N;else if(N<0)b=Math.ceil(b*N)/N,E=Math.floor(E*N)/N;else break;S=N}return i},i}function PMe(){var i=NMe();return i.copy=function(){return OMe(i,PMe())},x1e.apply(i,arguments),B8t(i)}function R8t(i,a){i=i.slice();var f=0,p=i.length-1,w=i[f],y=i[p],b;return y0))return S;do S.push(N=new Date(+y)),a(y,E),i(y);while(N=b)for(;i(b),!y(b);)b.setTime(b-1)},function(b,E){if(b>=b)if(E<0)for(;++E<=0;)for(;a(b,-1),!y(b););else for(;--E>=0;)for(;a(b,1),!y(b););})},f&&(w.count=function(y,b){return T1e.setTime(+y),_1e.setTime(+b),i(T1e),i(_1e),Math.floor(f(T1e,_1e))},w.every=function(y){return y=Math.floor(y),!isFinite(y)||!(y>0)?null:y>1?w.filter(p?function(b){return p(b)%y===0}:function(b){return w.count(0,b)%y===0}):w}),w}var NU=tg(function(){},function(i,a){i.setTime(+i+a)},function(i,a){return a-i});NU.every=function(i){return i=Math.floor(i),!isFinite(i)||!(i>0)?null:i>1?tg(function(a){a.setTime(Math.floor(a/i)*i)},function(a,f){a.setTime(+a+f*i)},function(a,f){return(f-a)/i}):NU};const F8t=NU;NU.range;const d5=1e3,t3=d5*60,HE=t3*60,zE=HE*24,C1e=zE*7,BMe=zE*30,S1e=zE*365;var RMe=tg(function(i){i.setTime(i-i.getMilliseconds())},function(i,a){i.setTime(+i+a*d5)},function(i,a){return(a-i)/d5},function(i){return i.getUTCSeconds()});const DN=RMe;RMe.range;var FMe=tg(function(i){i.setTime(i-i.getMilliseconds()-i.getSeconds()*d5)},function(i,a){i.setTime(+i+a*t3)},function(i,a){return(a-i)/t3},function(i){return i.getMinutes()});const PU=FMe;FMe.range;var jMe=tg(function(i){i.setTime(i-i.getMilliseconds()-i.getSeconds()*d5-i.getMinutes()*t3)},function(i,a){i.setTime(+i+a*HE)},function(i,a){return(a-i)/HE},function(i){return i.getHours()});const BU=jMe;jMe.range;var $Me=tg(i=>i.setHours(0,0,0,0),(i,a)=>i.setDate(i.getDate()+a),(i,a)=>(a-i-(a.getTimezoneOffset()-i.getTimezoneOffset())*t3)/zE,i=>i.getDate()-1);const yA=$Me;$Me.range;function GE(i){return tg(function(a){a.setDate(a.getDate()-(a.getDay()+7-i)%7),a.setHours(0,0,0,0)},function(a,f){a.setDate(a.getDate()+f*7)},function(a,f){return(f-a-(f.getTimezoneOffset()-a.getTimezoneOffset())*t3)/C1e})}var kA=GE(0),RU=GE(1),j8t=GE(2),$8t=GE(3),xA=GE(4),H8t=GE(5),z8t=GE(6);kA.range,RU.range,j8t.range,$8t.range,xA.range,H8t.range,z8t.range;var HMe=tg(function(i){i.setDate(1),i.setHours(0,0,0,0)},function(i,a){i.setMonth(i.getMonth()+a)},function(i,a){return a.getMonth()-i.getMonth()+(a.getFullYear()-i.getFullYear())*12},function(i){return i.getMonth()});const FU=HMe;HMe.range;var A1e=tg(function(i){i.setMonth(0,1),i.setHours(0,0,0,0)},function(i,a){i.setFullYear(i.getFullYear()+a)},function(i,a){return a.getFullYear()-i.getFullYear()},function(i){return i.getFullYear()});A1e.every=function(i){return!isFinite(i=Math.floor(i))||!(i>0)?null:tg(function(a){a.setFullYear(Math.floor(a.getFullYear()/i)*i),a.setMonth(0,1),a.setHours(0,0,0,0)},function(a,f){a.setFullYear(a.getFullYear()+f*i)})};const qE=A1e;A1e.range;var zMe=tg(function(i){i.setUTCHours(0,0,0,0)},function(i,a){i.setUTCDate(i.getUTCDate()+a)},function(i,a){return(a-i)/zE},function(i){return i.getUTCDate()-1});const GMe=zMe;zMe.range;function VE(i){return tg(function(a){a.setUTCDate(a.getUTCDate()-(a.getUTCDay()+7-i)%7),a.setUTCHours(0,0,0,0)},function(a,f){a.setUTCDate(a.getUTCDate()+f*7)},function(a,f){return(f-a)/C1e})}var qMe=VE(0),jU=VE(1),G8t=VE(2),q8t=VE(3),EA=VE(4),V8t=VE(5),U8t=VE(6);qMe.range,jU.range,G8t.range,q8t.range,EA.range,V8t.range,U8t.range;var L1e=tg(function(i){i.setUTCMonth(0,1),i.setUTCHours(0,0,0,0)},function(i,a){i.setUTCFullYear(i.getUTCFullYear()+a)},function(i,a){return a.getUTCFullYear()-i.getUTCFullYear()},function(i){return i.getUTCFullYear()});L1e.every=function(i){return!isFinite(i=Math.floor(i))||!(i>0)?null:tg(function(a){a.setUTCFullYear(Math.floor(a.getUTCFullYear()/i)*i),a.setUTCMonth(0,1),a.setUTCHours(0,0,0,0)},function(a,f){a.setUTCFullYear(a.getUTCFullYear()+f*i)})};const IN=L1e;L1e.range;function W8t(i,a,f,p,w,y){const b=[[DN,1,d5],[DN,5,5*d5],[DN,15,15*d5],[DN,30,30*d5],[y,1,t3],[y,5,5*t3],[y,15,15*t3],[y,30,30*t3],[w,1,HE],[w,3,3*HE],[w,6,6*HE],[w,12,12*HE],[p,1,zE],[p,2,2*zE],[f,1,C1e],[a,1,BMe],[a,3,3*BMe],[i,1,S1e]];function E(N,B,R){const j=Boe).right(b,j);if($===b.length)return i.every(Ufe(N/S1e,B/S1e,R));if($===0)return F8t.every(Math.max(Ufe(N,B,R),1));const[V,Q]=b[j/b[$-1][2]53)return null;"w"in ze||(ze.w=1),"Z"in ze?(Lt=D1e(ON(ze.y,0,1)),Ge=Lt.getUTCDay(),Lt=Ge>4||Ge===0?jU.ceil(Lt):jU(Lt),Lt=GMe.offset(Lt,(ze.V-1)*7),ze.y=Lt.getUTCFullYear(),ze.m=Lt.getUTCMonth(),ze.d=Lt.getUTCDate()+(ze.w+6)%7):(Lt=M1e(ON(ze.y,0,1)),Ge=Lt.getDay(),Lt=Ge>4||Ge===0?RU.ceil(Lt):RU(Lt),Lt=yA.offset(Lt,(ze.V-1)*7),ze.y=Lt.getFullYear(),ze.m=Lt.getMonth(),ze.d=Lt.getDate()+(ze.w+6)%7)}else("W"in ze||"U"in ze)&&("w"in ze||(ze.w="u"in ze?ze.u%7:"W"in ze?1:0),Ge="Z"in ze?D1e(ON(ze.y,0,1)).getUTCDay():M1e(ON(ze.y,0,1)).getDay(),ze.m=0,ze.d="W"in ze?(ze.w+6)%7+ze.W*7-(Ge+5)%7:ze.w+ze.U*7-(Ge+6)%7);return"Z"in ze?(ze.H+=ze.Z/100|0,ze.M+=ze.Z%100,D1e(ze)):M1e(ze)}}function ve(Dt,vt,Nt,ze){for(var Xe=0,Lt=vt.length,Ge=Nt.length,Bn,Oe;Xe=Ge)return-1;if(Bn=vt.charCodeAt(Xe++),Bn===37){if(Bn=vt.charAt(Xe++),Oe=ke[Bn in VMe?vt.charAt(Xe++):Bn],!Oe||(ze=Oe(Dt,Nt,ze))<0)return-1}else if(Bn!=Nt.charCodeAt(ze++))return-1}return ze}function te(Dt,vt,Nt){var ze=N.exec(vt.slice(Nt));return ze?(Dt.p=B.get(ze[0].toLowerCase()),Nt+ze[0].length):-1}function xe(Dt,vt,Nt){var ze=$.exec(vt.slice(Nt));return ze?(Dt.w=V.get(ze[0].toLowerCase()),Nt+ze[0].length):-1}function De(Dt,vt,Nt){var ze=R.exec(vt.slice(Nt));return ze?(Dt.w=j.get(ze[0].toLowerCase()),Nt+ze[0].length):-1}function he(Dt,vt,Nt){var ze=ce.exec(vt.slice(Nt));return ze?(Dt.m=se.get(ze[0].toLowerCase()),Nt+ze[0].length):-1}function Ie(Dt,vt,Nt){var ze=Q.exec(vt.slice(Nt));return ze?(Dt.m=oe.get(ze[0].toLowerCase()),Nt+ze[0].length):-1}function ee(Dt,vt,Nt){return ve(Dt,a,vt,Nt)}function rt(Dt,vt,Nt){return ve(Dt,f,vt,Nt)}function me(Dt,vt,Nt){return ve(Dt,p,vt,Nt)}function gt(Dt){return b[Dt.getDay()]}function pe(Dt){return y[Dt.getDay()]}function Et(Dt){return S[Dt.getMonth()]}function wt(Dt){return E[Dt.getMonth()]}function jt(Dt){return w[+(Dt.getHours()>=12)]}function At(Dt){return 1+~~(Dt.getMonth()/3)}function Bt(Dt){return b[Dt.getUTCDay()]}function cn(Dt){return y[Dt.getUTCDay()]}function Nn(Dt){return S[Dt.getUTCMonth()]}function Ot(Dt){return E[Dt.getUTCMonth()]}function oi(Dt){return w[+(Dt.getUTCHours()>=12)]}function kt(Dt){return 1+~~(Dt.getUTCMonth()/3)}return{format:function(Dt){var vt=Ae(Dt+="",ge);return vt.toString=function(){return Dt},vt},parse:function(Dt){var vt=de(Dt+="",!1);return vt.toString=function(){return Dt},vt},utcFormat:function(Dt){var vt=Ae(Dt+="",ye);return vt.toString=function(){return Dt},vt},utcParse:function(Dt){var vt=de(Dt+="",!0);return vt.toString=function(){return Dt},vt}}}var VMe={"-":"",_:" ",0:"0"},td=/^\s*\d+/,Q8t=/^%/,Z8t=/[\\^$*+?|[\]().{}]/g;function zc(i,a,f){var p=i<0?"-":"",w=(p?-i:i)+"",y=w.length;return p+(y[a.toLowerCase(),f]))}function e7t(i,a,f){var p=td.exec(a.slice(f,f+1));return p?(i.w=+p[0],f+p[0].length):-1}function t7t(i,a,f){var p=td.exec(a.slice(f,f+1));return p?(i.u=+p[0],f+p[0].length):-1}function n7t(i,a,f){var p=td.exec(a.slice(f,f+2));return p?(i.U=+p[0],f+p[0].length):-1}function r7t(i,a,f){var p=td.exec(a.slice(f,f+2));return p?(i.V=+p[0],f+p[0].length):-1}function i7t(i,a,f){var p=td.exec(a.slice(f,f+2));return p?(i.W=+p[0],f+p[0].length):-1}function UMe(i,a,f){var p=td.exec(a.slice(f,f+4));return p?(i.y=+p[0],f+p[0].length):-1}function WMe(i,a,f){var p=td.exec(a.slice(f,f+2));return p?(i.y=+p[0]+(+p[0]>68?1900:2e3),f+p[0].length):-1}function s7t(i,a,f){var p=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(a.slice(f,f+6));return p?(i.Z=p[1]?0:-(p[2]+(p[3]||"00")),f+p[0].length):-1}function a7t(i,a,f){var p=td.exec(a.slice(f,f+1));return p?(i.q=p[0]*3-3,f+p[0].length):-1}function o7t(i,a,f){var p=td.exec(a.slice(f,f+2));return p?(i.m=p[0]-1,f+p[0].length):-1}function KMe(i,a,f){var p=td.exec(a.slice(f,f+2));return p?(i.d=+p[0],f+p[0].length):-1}function c7t(i,a,f){var p=td.exec(a.slice(f,f+3));return p?(i.m=0,i.d=+p[0],f+p[0].length):-1}function YMe(i,a,f){var p=td.exec(a.slice(f,f+2));return p?(i.H=+p[0],f+p[0].length):-1}function u7t(i,a,f){var p=td.exec(a.slice(f,f+2));return p?(i.M=+p[0],f+p[0].length):-1}function l7t(i,a,f){var p=td.exec(a.slice(f,f+2));return p?(i.S=+p[0],f+p[0].length):-1}function h7t(i,a,f){var p=td.exec(a.slice(f,f+3));return p?(i.L=+p[0],f+p[0].length):-1}function f7t(i,a,f){var p=td.exec(a.slice(f,f+6));return p?(i.L=Math.floor(p[0]/1e3),f+p[0].length):-1}function d7t(i,a,f){var p=Q8t.exec(a.slice(f,f+1));return p?f+p[0].length:-1}function g7t(i,a,f){var p=td.exec(a.slice(f));return p?(i.Q=+p[0],f+p[0].length):-1}function p7t(i,a,f){var p=td.exec(a.slice(f));return p?(i.s=+p[0],f+p[0].length):-1}function XMe(i,a){return zc(i.getDate(),a,2)}function b7t(i,a){return zc(i.getHours(),a,2)}function v7t(i,a){return zc(i.getHours()%12||12,a,2)}function w7t(i,a){return zc(1+yA.count(qE(i),i),a,3)}function QMe(i,a){return zc(i.getMilliseconds(),a,3)}function m7t(i,a){return QMe(i,a)+"000"}function y7t(i,a){return zc(i.getMonth()+1,a,2)}function k7t(i,a){return zc(i.getMinutes(),a,2)}function x7t(i,a){return zc(i.getSeconds(),a,2)}function E7t(i){var a=i.getDay();return a===0?7:a}function T7t(i,a){return zc(kA.count(qE(i)-1,i),a,2)}function ZMe(i){var a=i.getDay();return a>=4||a===0?xA(i):xA.ceil(i)}function _7t(i,a){return i=ZMe(i),zc(xA.count(qE(i),i)+(qE(i).getDay()===4),a,2)}function C7t(i){return i.getDay()}function S7t(i,a){return zc(RU.count(qE(i)-1,i),a,2)}function A7t(i,a){return zc(i.getFullYear()%100,a,2)}function L7t(i,a){return i=ZMe(i),zc(i.getFullYear()%100,a,2)}function M7t(i,a){return zc(i.getFullYear()%1e4,a,4)}function D7t(i,a){var f=i.getDay();return i=f>=4||f===0?xA(i):xA.ceil(i),zc(i.getFullYear()%1e4,a,4)}function I7t(i){var a=i.getTimezoneOffset();return(a>0?"-":(a*=-1,"+"))+zc(a/60|0,"0",2)+zc(a%60,"0",2)}function JMe(i,a){return zc(i.getUTCDate(),a,2)}function O7t(i,a){return zc(i.getUTCHours(),a,2)}function N7t(i,a){return zc(i.getUTCHours()%12||12,a,2)}function P7t(i,a){return zc(1+GMe.count(IN(i),i),a,3)}function eDe(i,a){return zc(i.getUTCMilliseconds(),a,3)}function B7t(i,a){return eDe(i,a)+"000"}function R7t(i,a){return zc(i.getUTCMonth()+1,a,2)}function F7t(i,a){return zc(i.getUTCMinutes(),a,2)}function j7t(i,a){return zc(i.getUTCSeconds(),a,2)}function $7t(i){var a=i.getUTCDay();return a===0?7:a}function H7t(i,a){return zc(qMe.count(IN(i)-1,i),a,2)}function tDe(i){var a=i.getUTCDay();return a>=4||a===0?EA(i):EA.ceil(i)}function z7t(i,a){return i=tDe(i),zc(EA.count(IN(i),i)+(IN(i).getUTCDay()===4),a,2)}function G7t(i){return i.getUTCDay()}function q7t(i,a){return zc(jU.count(IN(i)-1,i),a,2)}function V7t(i,a){return zc(i.getUTCFullYear()%100,a,2)}function U7t(i,a){return i=tDe(i),zc(i.getUTCFullYear()%100,a,2)}function W7t(i,a){return zc(i.getUTCFullYear()%1e4,a,4)}function K7t(i,a){var f=i.getUTCDay();return i=f>=4||f===0?EA(i):EA.ceil(i),zc(i.getUTCFullYear()%1e4,a,4)}function Y7t(){return"+0000"}function nDe(){return"%"}function rDe(i){return+i}function iDe(i){return Math.floor(+i/1e3)}var TA,$U;X7t({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});function X7t(i){return TA=X8t(i),$U=TA.format,TA.parse,TA.utcFormat,TA.utcParse,TA}function Q7t(i){return new Date(i)}function Z7t(i){return i instanceof Date?+i:+new Date(+i)}function sDe(i,a,f,p,w,y,b,E,S,N){var B=NMe(),R=B.invert,j=B.domain,$=N(".%L"),V=N(":%S"),Q=N("%I:%M"),oe=N("%I %p"),ce=N("%a %d"),se=N("%b %d"),ge=N("%B"),ye=N("%Y");function ke(Ae){return(S(Ae)1?0:i<-1?BN:Math.acos(i)}function oDe(i){return i>=1?HU:i<=-1?-HU:Math.asin(i)}function nEt(i){return i.innerRadius}function rEt(i){return i.outerRadius}function iEt(i){return i.startAngle}function sEt(i){return i.endAngle}function aEt(i){return i&&i.padAngle}function oEt(i,a,f,p,w,y,b,E){var S=f-i,N=p-a,B=b-w,R=E-y,j=R*S-B*N;if(!(j*jee*ee+rt*rt&&(ve=xe,te=De),{cx:ve,cy:te,x01:-B,y01:-R,x11:ve*(w/ke-1),y11:te*(w/ke-1)}}function CA(){var i=nEt,a=rEt,f=of(0),p=null,w=iEt,y=sEt,b=aEt,E=null;function S(){var N,B,R=+i.apply(this,arguments),j=+a.apply(this,arguments),$=w.apply(this,arguments)-HU,V=y.apply(this,arguments)-HU,Q=aDe(V-$),oe=V>$;if(E||(E=N=y1e()),jm0))E.moveTo(0,0);else if(Q>zU-m0)E.moveTo(j*UE($),j*n3($)),E.arc(0,0,j,$,V,!oe),R>m0&&(E.moveTo(R*UE(V),R*n3(V)),E.arc(0,0,R,V,$,oe));else{var ce=$,se=V,ge=$,ye=V,ke=Q,Ae=Q,de=b.apply(this,arguments)/2,ve=de>m0&&(p?+p.apply(this,arguments):_A(R*R+j*j)),te=I1e(aDe(j-R)/2,+f.apply(this,arguments)),xe=te,De=te,he,Ie;if(ve>m0){var ee=oDe(ve/R*n3(de)),rt=oDe(ve/j*n3(de));(ke-=ee*2)>m0?(ee*=oe?1:-1,ge+=ee,ye-=ee):(ke=0,ge=ye=($+V)/2),(Ae-=rt*2)>m0?(rt*=oe?1:-1,ce+=rt,se-=rt):(Ae=0,ce=se=($+V)/2)}var me=j*UE(ce),gt=j*n3(ce),pe=R*UE(ye),Et=R*n3(ye);if(te>m0){var wt=j*UE(se),jt=j*n3(se),At=R*UE(ge),Bt=R*n3(ge),cn;if(Qm0?De>m0?(he=GU(At,Bt,me,gt,j,De,oe),Ie=GU(wt,jt,pe,Et,j,De,oe),E.moveTo(he.cx+he.x01,he.cy+he.y01),Dem0)||!(ke>m0)?E.lineTo(pe,Et):xe>m0?(he=GU(pe,Et,wt,jt,R,-xe,oe),Ie=GU(me,gt,At,Bt,R,-xe,oe),E.lineTo(he.cx+he.x01,he.cy+he.y01),xei?1:a>=i?0:NaN}function hEt(i){return i}function fEt(){var i=hEt,a=lEt,f=null,p=of(0),w=of(zU),y=of(0);function b(E){var S,N=(E=cDe(E)).length,B,R,j=0,$=new Array(N),V=new Array(N),Q=+p.apply(this,arguments),oe=Math.min(zU,Math.max(-zU,w.apply(this,arguments)-Q)),ce,se=Math.min(Math.abs(oe)/N,y.apply(this,arguments)),ge=se*(oe<0?-1:1),ye;for(S=0;S0&&(j+=ye);for(a!=null?$.sort(function(ke,Ae){return a(V[ke],V[Ae])}):f!=null&&$.sort(function(ke,Ae){return f(E[ke],E[Ae])}),S=0,R=j?(oe-N*ge)/j:0;S0?ye*R:0)+ge,V[B]={data:E[B],index:S,value:ye,startAngle:Q,endAngle:ce,padAngle:se};return V}return b.value=function(E){return arguments.length?(i=typeof E=="function"?E:of(+E),b):i},b.sortValues=function(E){return arguments.length?(a=E,f=null,b):a},b.sort=function(E){return arguments.length?(f=E,a=null,b):f},b.startAngle=function(E){return arguments.length?(p=typeof E=="function"?E:of(+E),b):p},b.endAngle=function(E){return arguments.length?(w=typeof E=="function"?E:of(+E),b):w},b.padAngle=function(E){return arguments.length?(y=typeof E=="function"?E:of(+E),b):y},b}class lDe{constructor(a,f){this._context=a,this._x=f}areaStart(){this._line=0}areaEnd(){this._line=NaN}lineStart(){this._point=0}lineEnd(){(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line}point(a,f){switch(a=+a,f=+f,this._point){case 0:{this._point=1,this._line?this._context.lineTo(a,f):this._context.moveTo(a,f);break}case 1:this._point=2;default:{this._x?this._context.bezierCurveTo(this._x0=(this._x0+a)/2,this._y0,this._x0,f,a,f):this._context.bezierCurveTo(this._x0,this._y0=(this._y0+f)/2,a,this._y0,a,f);break}}this._x0=a,this._y0=f}}function dEt(i){return new lDe(i,!0)}function gEt(i){return new lDe(i,!1)}function Kk(){}function qU(i,a,f){i._context.bezierCurveTo((2*i._x0+i._x1)/3,(2*i._y0+i._y1)/3,(i._x0+2*i._x1)/3,(i._y0+2*i._y1)/3,(i._x0+4*i._x1+a)/6,(i._y0+4*i._y1+f)/6)}function VU(i){this._context=i}VU.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:qU(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1);break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(i,a){switch(i=+i,a=+a,this._point){case 0:this._point=1,this._line?this._context.lineTo(i,a):this._context.moveTo(i,a);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:qU(this,i,a);break}this._x0=this._x1,this._x1=i,this._y0=this._y1,this._y1=a}};function SA(i){return new VU(i)}function hDe(i){this._context=i}hDe.prototype={areaStart:Kk,areaEnd:Kk,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:{this._context.moveTo(this._x2,this._y2),this._context.closePath();break}case 2:{this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath();break}case 3:{this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4);break}}},point:function(i,a){switch(i=+i,a=+a,this._point){case 0:this._point=1,this._x2=i,this._y2=a;break;case 1:this._point=2,this._x3=i,this._y3=a;break;case 2:this._point=3,this._x4=i,this._y4=a,this._context.moveTo((this._x0+4*this._x1+i)/6,(this._y0+4*this._y1+a)/6);break;default:qU(this,i,a);break}this._x0=this._x1,this._x1=i,this._y0=this._y1,this._y1=a}};function pEt(i){return new hDe(i)}function fDe(i){this._context=i}fDe.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||this._line!==0&&this._point===3)&&this._context.closePath(),this._line=1-this._line},point:function(i,a){switch(i=+i,a=+a,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var f=(this._x0+4*this._x1+i)/6,p=(this._y0+4*this._y1+a)/6;this._line?this._context.lineTo(f,p):this._context.moveTo(f,p);break;case 3:this._point=4;default:qU(this,i,a);break}this._x0=this._x1,this._x1=i,this._y0=this._y1,this._y1=a}};function bEt(i){return new fDe(i)}function dDe(i,a){this._basis=new VU(i),this._beta=a}dDe.prototype={lineStart:function(){this._x=[],this._y=[],this._basis.lineStart()},lineEnd:function(){var i=this._x,a=this._y,f=i.length-1;if(f>0)for(var p=i[0],w=a[0],y=i[f]-p,b=a[f]-w,E=-1,S;++E<=f;)S=E/f,this._basis.point(this._beta*i[E]+(1-this._beta)*(p+S*y),this._beta*a[E]+(1-this._beta)*(w+S*b));this._x=this._y=null,this._basis.lineEnd()},point:function(i,a){this._x.push(+i),this._y.push(+a)}};const vEt=function i(a){function f(p){return a===1?new VU(p):new dDe(p,a)}return f.beta=function(p){return i(+p)},f}(.85);function UU(i,a,f){i._context.bezierCurveTo(i._x1+i._k*(i._x2-i._x0),i._y1+i._k*(i._y2-i._y0),i._x2+i._k*(i._x1-a),i._y2+i._k*(i._y1-f),i._x2,i._y2)}function O1e(i,a){this._context=i,this._k=(1-a)/6}O1e.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:UU(this,this._x1,this._y1);break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(i,a){switch(i=+i,a=+a,this._point){case 0:this._point=1,this._line?this._context.lineTo(i,a):this._context.moveTo(i,a);break;case 1:this._point=2,this._x1=i,this._y1=a;break;case 2:this._point=3;default:UU(this,i,a);break}this._x0=this._x1,this._x1=this._x2,this._x2=i,this._y0=this._y1,this._y1=this._y2,this._y2=a}};const wEt=function i(a){function f(p){return new O1e(p,a)}return f.tension=function(p){return i(+p)},f}(0);function N1e(i,a){this._context=i,this._k=(1-a)/6}N1e.prototype={areaStart:Kk,areaEnd:Kk,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:{this._context.moveTo(this._x3,this._y3),this._context.closePath();break}case 2:{this._context.lineTo(this._x3,this._y3),this._context.closePath();break}case 3:{this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5);break}}},point:function(i,a){switch(i=+i,a=+a,this._point){case 0:this._point=1,this._x3=i,this._y3=a;break;case 1:this._point=2,this._context.moveTo(this._x4=i,this._y4=a);break;case 2:this._point=3,this._x5=i,this._y5=a;break;default:UU(this,i,a);break}this._x0=this._x1,this._x1=this._x2,this._x2=i,this._y0=this._y1,this._y1=this._y2,this._y2=a}};const mEt=function i(a){function f(p){return new N1e(p,a)}return f.tension=function(p){return i(+p)},f}(0);function P1e(i,a){this._context=i,this._k=(1-a)/6}P1e.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){(this._line||this._line!==0&&this._point===3)&&this._context.closePath(),this._line=1-this._line},point:function(i,a){switch(i=+i,a=+a,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:UU(this,i,a);break}this._x0=this._x1,this._x1=this._x2,this._x2=i,this._y0=this._y1,this._y1=this._y2,this._y2=a}};const yEt=function i(a){function f(p){return new P1e(p,a)}return f.tension=function(p){return i(+p)},f}(0);function B1e(i,a,f){var p=i._x1,w=i._y1,y=i._x2,b=i._y2;if(i._l01_a>m0){var E=2*i._l01_2a+3*i._l01_a*i._l12_a+i._l12_2a,S=3*i._l01_a*(i._l01_a+i._l12_a);p=(p*E-i._x0*i._l12_2a+i._x2*i._l01_2a)/S,w=(w*E-i._y0*i._l12_2a+i._y2*i._l01_2a)/S}if(i._l23_a>m0){var N=2*i._l23_2a+3*i._l23_a*i._l12_a+i._l12_2a,B=3*i._l23_a*(i._l23_a+i._l12_a);y=(y*N+i._x1*i._l23_2a-a*i._l12_2a)/B,b=(b*N+i._y1*i._l23_2a-f*i._l12_2a)/B}i._context.bezierCurveTo(p,w,y,b,i._x2,i._y2)}function gDe(i,a){this._context=i,this._alpha=a}gDe.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:this.point(this._x2,this._y2);break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(i,a){if(i=+i,a=+a,this._point){var f=this._x2-i,p=this._y2-a;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(f*f+p*p,this._alpha))}switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(i,a):this._context.moveTo(i,a);break;case 1:this._point=2;break;case 2:this._point=3;default:B1e(this,i,a);break}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=i,this._y0=this._y1,this._y1=this._y2,this._y2=a}};const kEt=function i(a){function f(p){return a?new gDe(p,a):new O1e(p,0)}return f.alpha=function(p){return i(+p)},f}(.5);function pDe(i,a){this._context=i,this._alpha=a}pDe.prototype={areaStart:Kk,areaEnd:Kk,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 1:{this._context.moveTo(this._x3,this._y3),this._context.closePath();break}case 2:{this._context.lineTo(this._x3,this._y3),this._context.closePath();break}case 3:{this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5);break}}},point:function(i,a){if(i=+i,a=+a,this._point){var f=this._x2-i,p=this._y2-a;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(f*f+p*p,this._alpha))}switch(this._point){case 0:this._point=1,this._x3=i,this._y3=a;break;case 1:this._point=2,this._context.moveTo(this._x4=i,this._y4=a);break;case 2:this._point=3,this._x5=i,this._y5=a;break;default:B1e(this,i,a);break}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=i,this._y0=this._y1,this._y1=this._y2,this._y2=a}};const xEt=function i(a){function f(p){return a?new pDe(p,a):new N1e(p,0)}return f.alpha=function(p){return i(+p)},f}(.5);function bDe(i,a){this._context=i,this._alpha=a}bDe.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){(this._line||this._line!==0&&this._point===3)&&this._context.closePath(),this._line=1-this._line},point:function(i,a){if(i=+i,a=+a,this._point){var f=this._x2-i,p=this._y2-a;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(f*f+p*p,this._alpha))}switch(this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:B1e(this,i,a);break}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=i,this._y0=this._y1,this._y1=this._y2,this._y2=a}};const EEt=function i(a){function f(p){return a?new bDe(p,a):new P1e(p,0)}return f.alpha=function(p){return i(+p)},f}(.5);function vDe(i){this._context=i}vDe.prototype={areaStart:Kk,areaEnd:Kk,lineStart:function(){this._point=0},lineEnd:function(){this._point&&this._context.closePath()},point:function(i,a){i=+i,a=+a,this._point?this._context.lineTo(i,a):(this._point=1,this._context.moveTo(i,a))}};function TEt(i){return new vDe(i)}function wDe(i){return i<0?-1:1}function mDe(i,a,f){var p=i._x1-i._x0,w=a-i._x1,y=(i._y1-i._y0)/(p||w<0&&-0),b=(f-i._y1)/(w||p<0&&-0),E=(y*w+b*p)/(p+w);return(wDe(y)+wDe(b))*Math.min(Math.abs(y),Math.abs(b),.5*Math.abs(E))||0}function yDe(i,a){var f=i._x1-i._x0;return f?(3*(i._y1-i._y0)/f-a)/2:a}function R1e(i,a,f){var p=i._x0,w=i._y0,y=i._x1,b=i._y1,E=(y-p)/3;i._context.bezierCurveTo(p+E,w+E*a,y-E,b-E*f,y,b)}function WU(i){this._context=i}WU.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=this._t0=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x1,this._y1);break;case 3:R1e(this,this._t0,yDe(this,this._t0));break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(i,a){var f=NaN;if(i=+i,a=+a,!(i===this._x1&&a===this._y1)){switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(i,a):this._context.moveTo(i,a);break;case 1:this._point=2;break;case 2:this._point=3,R1e(this,yDe(this,f=mDe(this,i,a)),f);break;default:R1e(this,this._t0,f=mDe(this,i,a));break}this._x0=this._x1,this._x1=i,this._y0=this._y1,this._y1=a,this._t0=f}}};function kDe(i){this._context=new xDe(i)}(kDe.prototype=Object.create(WU.prototype)).point=function(i,a){WU.prototype.point.call(this,a,i)};function xDe(i){this._context=i}xDe.prototype={moveTo:function(i,a){this._context.moveTo(a,i)},closePath:function(){this._context.closePath()},lineTo:function(i,a){this._context.lineTo(a,i)},bezierCurveTo:function(i,a,f,p,w,y){this._context.bezierCurveTo(a,i,p,f,y,w)}};function _Et(i){return new WU(i)}function CEt(i){return new kDe(i)}function EDe(i){this._context=i}EDe.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=[],this._y=[]},lineEnd:function(){var i=this._x,a=this._y,f=i.length;if(f)if(this._line?this._context.lineTo(i[0],a[0]):this._context.moveTo(i[0],a[0]),f===2)this._context.lineTo(i[1],a[1]);else for(var p=TDe(i),w=TDe(a),y=0,b=1;b=0;--a)w[a]=(b[a]-w[a+1])/y[a];for(y[f-1]=(i[f]+w[f-1])/2,a=0;a=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(i,a){switch(i=+i,a=+a,this._point){case 0:this._point=1,this._line?this._context.lineTo(i,a):this._context.moveTo(i,a);break;case 1:this._point=2;default:{if(this._t<=0)this._context.lineTo(this._x,a),this._context.lineTo(i,a);else{var f=this._x*(1-this._t)+i*this._t;this._context.lineTo(f,this._y),this._context.lineTo(f,a)}break}}this._x=i,this._y=a}};function AEt(i){return new KU(i,.5)}function LEt(i){return new KU(i,0)}function MEt(i){return new KU(i,1)}function RN(i,a,f){this.k=i,this.x=a,this.y=f}RN.prototype={constructor:RN,scale:function(i){return i===1?this:new RN(this.k*i,this.x,this.y)},translate:function(i,a){return i===0&a===0?this:new RN(this.k,this.x+this.k*i,this.y+this.k*a)},apply:function(i){return[i[0]*this.k+this.x,i[1]*this.k+this.y]},applyX:function(i){return i*this.k+this.x},applyY:function(i){return i*this.k+this.y},invert:function(i){return[(i[0]-this.x)/this.k,(i[1]-this.y)/this.k]},invertX:function(i){return(i-this.x)/this.k},invertY:function(i){return(i-this.y)/this.k},rescaleX:function(i){return i.copy().domain(i.range().map(this.invertX,this).map(i.invert,i))},rescaleY:function(i){return i.copy().domain(i.range().map(this.invertY,this).map(i.invert,i))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}},RN.prototype;/*! @license DOMPurify 3.0.2 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.0.2/LICENSE */const{entries:_De,setPrototypeOf:CDe,isFrozen:DEt,getPrototypeOf:IEt,getOwnPropertyDescriptor:OEt}=Object;let{freeze:rg,seal:Gw,create:NEt}=Object,{apply:F1e,construct:j1e}=typeof Reflect<"u"&&Reflect;F1e||(F1e=function(a,f,p){return a.apply(f,p)}),rg||(rg=function(a){return a}),Gw||(Gw=function(a){return a}),j1e||(j1e=function(a,f){return new a(...f)});const PEt=qb(Array.prototype.forEach),SDe=qb(Array.prototype.pop),FN=qb(Array.prototype.push),YU=qb(String.prototype.toLowerCase),$1e=qb(String.prototype.toString),BEt=qb(String.prototype.match),qw=qb(String.prototype.replace),REt=qb(String.prototype.indexOf),FEt=qb(String.prototype.trim),A2=qb(RegExp.prototype.test),H1e=jEt(TypeError);function qb(i){return function(a){for(var f=arguments.length,p=new Array(f>1?f-1:0),w=1;w/gm),qEt=Gw(/\${[\w\W]*}/gm),VEt=Gw(/^data-[\-\w.\u00B7-\uFFFF]/),UEt=Gw(/^aria-[\-\w]+$/),IDe=Gw(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),WEt=Gw(/^(?:\w+script|data):/i),KEt=Gw(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),ODe=Gw(/^html$/i);var NDe=Object.freeze({__proto__:null,MUSTACHE_EXPR:zEt,ERB_EXPR:GEt,TMPLIT_EXPR:qEt,DATA_ATTR:VEt,ARIA_ATTR:UEt,IS_ALLOWED_URI:IDe,IS_SCRIPT_OR_DATA:WEt,ATTR_WHITESPACE:KEt,DOCTYPE_NAME:ODe});const YEt=()=>typeof window>"u"?null:window,XEt=function(a,f){if(typeof a!="object"||typeof a.createPolicy!="function")return null;let p=null;const w="data-tt-policy-suffix";f.currentScript&&f.currentScript.hasAttribute(w)&&(p=f.currentScript.getAttribute(w));const y="dompurify"+(p?"#"+p:"");try{return a.createPolicy(y,{createHTML(b){return b},createScriptURL(b){return b}})}catch{return console.warn("TrustedTypes policy "+y+" could not be created."),null}};function PDe(){let i=arguments.length>0&&arguments[0]!==void 0?arguments[0]:YEt();const a=Ai=>PDe(Ai);if(a.version="3.0.2",a.removed=[],!i||!i.document||i.document.nodeType!==9)return a.isSupported=!1,a;const f=i.document;let{document:p}=i;const{DocumentFragment:w,HTMLTemplateElement:y,Node:b,Element:E,NodeFilter:S,NamedNodeMap:N=i.NamedNodeMap||i.MozNamedAttrMap,HTMLFormElement:B,DOMParser:R,trustedTypes:j}=i,$=E.prototype,V=XU($,"cloneNode"),Q=XU($,"nextSibling"),oe=XU($,"childNodes"),ce=XU($,"parentNode");if(typeof y=="function"){const Ai=p.createElement("template");Ai.content&&Ai.content.ownerDocument&&(p=Ai.content.ownerDocument)}const se=XEt(j,f),ge=se?se.createHTML(""):"",{implementation:ye,createNodeIterator:ke,createDocumentFragment:Ae,getElementsByTagName:de}=p,{importNode:ve}=f;let te={};a.isSupported=typeof _De=="function"&&typeof ce=="function"&&ye&&typeof ye.createHTMLDocument<"u";const{MUSTACHE_EXPR:xe,ERB_EXPR:De,TMPLIT_EXPR:he,DATA_ATTR:Ie,ARIA_ATTR:ee,IS_SCRIPT_OR_DATA:rt,ATTR_WHITESPACE:me}=NDe;let{IS_ALLOWED_URI:gt}=NDe,pe=null;const Et=Lo({},[...ADe,...z1e,...G1e,...q1e,...LDe]);let wt=null;const jt=Lo({},[...MDe,...V1e,...DDe,...QU]);let At=Object.seal(Object.create(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),Bt=null,cn=null,Nn=!0,Ot=!0,oi=!1,kt=!0,Dt=!1,vt=!1,Nt=!1,ze=!1,Xe=!1,Lt=!1,Ge=!1,Bn=!0,Oe=!1;const Ri="user-content-";let tn=!0,hi=!1,Sr={},Zn=null;const Xn=Lo({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let ir=null;const Hn=Lo({},["audio","video","img","source","image","track"]);let tr=null;const ha=Lo({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),Zs="http://www.w3.org/1998/Math/MathML",ns="http://www.w3.org/2000/svg",Hi="http://www.w3.org/1999/xhtml";let Js=Hi,Pc=!1,Ga=null;const ws=Lo({},[Zs,ns,Hi],$1e);let Oi;const Er=["application/xhtml+xml","text/html"],br="text/html";let Dr,Vn=null;const qi=p.createElement("form"),yn=function(nn){return nn instanceof RegExp||nn instanceof Function},Bc=function(nn){Vn&&Vn===nn||((!nn||typeof nn!="object")&&(nn={}),nn=AA(nn),Oi=Er.indexOf(nn.PARSER_MEDIA_TYPE)===-1?Oi=br:Oi=nn.PARSER_MEDIA_TYPE,Dr=Oi==="application/xhtml+xml"?$1e:YU,pe="ALLOWED_TAGS"in nn?Lo({},nn.ALLOWED_TAGS,Dr):Et,wt="ALLOWED_ATTR"in nn?Lo({},nn.ALLOWED_ATTR,Dr):jt,Ga="ALLOWED_NAMESPACES"in nn?Lo({},nn.ALLOWED_NAMESPACES,$1e):ws,tr="ADD_URI_SAFE_ATTR"in nn?Lo(AA(ha),nn.ADD_URI_SAFE_ATTR,Dr):ha,ir="ADD_DATA_URI_TAGS"in nn?Lo(AA(Hn),nn.ADD_DATA_URI_TAGS,Dr):Hn,Zn="FORBID_CONTENTS"in nn?Lo({},nn.FORBID_CONTENTS,Dr):Xn,Bt="FORBID_TAGS"in nn?Lo({},nn.FORBID_TAGS,Dr):{},cn="FORBID_ATTR"in nn?Lo({},nn.FORBID_ATTR,Dr):{},Sr="USE_PROFILES"in nn?nn.USE_PROFILES:!1,Nn=nn.ALLOW_ARIA_ATTR!==!1,Ot=nn.ALLOW_DATA_ATTR!==!1,oi=nn.ALLOW_UNKNOWN_PROTOCOLS||!1,kt=nn.ALLOW_SELF_CLOSE_IN_ATTR!==!1,Dt=nn.SAFE_FOR_TEMPLATES||!1,vt=nn.WHOLE_DOCUMENT||!1,Xe=nn.RETURN_DOM||!1,Lt=nn.RETURN_DOM_FRAGMENT||!1,Ge=nn.RETURN_TRUSTED_TYPE||!1,ze=nn.FORCE_BODY||!1,Bn=nn.SANITIZE_DOM!==!1,Oe=nn.SANITIZE_NAMED_PROPS||!1,tn=nn.KEEP_CONTENT!==!1,hi=nn.IN_PLACE||!1,gt=nn.ALLOWED_URI_REGEXP||IDe,Js=nn.NAMESPACE||Hi,At=nn.CUSTOM_ELEMENT_HANDLING||{},nn.CUSTOM_ELEMENT_HANDLING&&yn(nn.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(At.tagNameCheck=nn.CUSTOM_ELEMENT_HANDLING.tagNameCheck),nn.CUSTOM_ELEMENT_HANDLING&&yn(nn.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(At.attributeNameCheck=nn.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),nn.CUSTOM_ELEMENT_HANDLING&&typeof nn.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements=="boolean"&&(At.allowCustomizedBuiltInElements=nn.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),Dt&&(Ot=!1),Lt&&(Xe=!0),Sr&&(pe=Lo({},[...LDe]),wt=[],Sr.html===!0&&(Lo(pe,ADe),Lo(wt,MDe)),Sr.svg===!0&&(Lo(pe,z1e),Lo(wt,V1e),Lo(wt,QU)),Sr.svgFilters===!0&&(Lo(pe,G1e),Lo(wt,V1e),Lo(wt,QU)),Sr.mathMl===!0&&(Lo(pe,q1e),Lo(wt,DDe),Lo(wt,QU))),nn.ADD_TAGS&&(pe===Et&&(pe=AA(pe)),Lo(pe,nn.ADD_TAGS,Dr)),nn.ADD_ATTR&&(wt===jt&&(wt=AA(wt)),Lo(wt,nn.ADD_ATTR,Dr)),nn.ADD_URI_SAFE_ATTR&&Lo(tr,nn.ADD_URI_SAFE_ATTR,Dr),nn.FORBID_CONTENTS&&(Zn===Xn&&(Zn=AA(Zn)),Lo(Zn,nn.FORBID_CONTENTS,Dr)),tn&&(pe["#text"]=!0),vt&&Lo(pe,["html","head","body"]),pe.table&&(Lo(pe,["tbody"]),delete Bt.tbody),rg&&rg(nn),Vn=nn)},jn=Lo({},["mi","mo","mn","ms","mtext"]),Ms=Lo({},["foreignobject","desc","title","annotation-xml"]),Pa=Lo({},["title","style","font","a","script"]),Ta=Lo({},z1e);Lo(Ta,G1e),Lo(Ta,$Et);const _a=Lo({},q1e);Lo(_a,HEt);const ka=function(nn){let Tr=ce(nn);(!Tr||!Tr.tagName)&&(Tr={namespaceURI:Js,tagName:"template"});const ai=YU(nn.tagName),Ns=YU(Tr.tagName);return Ga[nn.namespaceURI]?nn.namespaceURI===ns?Tr.namespaceURI===Hi?ai==="svg":Tr.namespaceURI===Zs?ai==="svg"&&(Ns==="annotation-xml"||jn[Ns]):!!Ta[ai]:nn.namespaceURI===Zs?Tr.namespaceURI===Hi?ai==="math":Tr.namespaceURI===ns?ai==="math"&&Ms[Ns]:!!_a[ai]:nn.namespaceURI===Hi?Tr.namespaceURI===ns&&!Ms[Ns]||Tr.namespaceURI===Zs&&!jn[Ns]?!1:!_a[ai]&&(Pa[ai]||!Ta[ai]):!!(Oi==="application/xhtml+xml"&&Ga[nn.namespaceURI]):!1},Qi=function(nn){FN(a.removed,{element:nn});try{nn.parentNode.removeChild(nn)}catch{nn.remove()}},ea=function(nn,Tr){try{FN(a.removed,{attribute:Tr.getAttributeNode(nn),from:Tr})}catch{FN(a.removed,{attribute:null,from:Tr})}if(Tr.removeAttribute(nn),nn==="is"&&!wt[nn])if(Xe||Lt)try{Qi(Tr)}catch{}else try{Tr.setAttribute(nn,"")}catch{}},Ca=function(nn){let Tr,ai;if(ze)nn=""+nn;else{const yu=BEt(nn,/^[\r\n\t ]+/);ai=yu&&yu[0]}Oi==="application/xhtml+xml"&&Js===Hi&&(nn=''+nn+"");const Ns=se?se.createHTML(nn):nn;if(Js===Hi)try{Tr=new R().parseFromString(Ns,Oi)}catch{}if(!Tr||!Tr.documentElement){Tr=ye.createDocument(Js,"template",null);try{Tr.documentElement.innerHTML=Pc?ge:Ns}catch{}}const mc=Tr.body||Tr.documentElement;return nn&&ai&&mc.insertBefore(p.createTextNode(ai),mc.childNodes[0]||null),Js===Hi?de.call(Tr,vt?"html":"body")[0]:vt?Tr.documentElement:mc},Sa=function(nn){return ke.call(nn.ownerDocument||nn,nn,S.SHOW_ELEMENT|S.SHOW_COMMENT|S.SHOW_TEXT,null,!1)},Ka=function(nn){return nn instanceof B&&(typeof nn.nodeName!="string"||typeof nn.textContent!="string"||typeof nn.removeChild!="function"||!(nn.attributes instanceof N)||typeof nn.removeAttribute!="function"||typeof nn.setAttribute!="function"||typeof nn.namespaceURI!="string"||typeof nn.insertBefore!="function"||typeof nn.hasChildNodes!="function")},cg=function(nn){return typeof b=="object"?nn instanceof b:nn&&typeof nn=="object"&&typeof nn.nodeType=="number"&&typeof nn.nodeName=="string"},Gc=function(nn,Tr,ai){te[nn]&&PEt(te[nn],Ns=>{Ns.call(a,Tr,ai,Vn)})},Dh=function(nn){let Tr;if(Gc("beforeSanitizeElements",nn,null),Ka(nn))return Qi(nn),!0;const ai=Dr(nn.nodeName);if(Gc("uponSanitizeElement",nn,{tagName:ai,allowedTags:pe}),nn.hasChildNodes()&&!cg(nn.firstElementChild)&&(!cg(nn.content)||!cg(nn.content.firstElementChild))&&A2(/<[/\w]/g,nn.innerHTML)&&A2(/<[/\w]/g,nn.textContent))return Qi(nn),!0;if(!pe[ai]||Bt[ai]){if(!Bt[ai]&&lp(ai)&&(At.tagNameCheck instanceof RegExp&&A2(At.tagNameCheck,ai)||At.tagNameCheck instanceof Function&&At.tagNameCheck(ai)))return!1;if(tn&&!Zn[ai]){const Ns=ce(nn)||nn.parentNode,mc=oe(nn)||nn.childNodes;if(mc&&Ns){const yu=mc.length;for(let Mo=yu-1;Mo>=0;--Mo)Ns.insertBefore(V(mc[Mo],!0),Q(nn))}}return Qi(nn),!0}return nn instanceof E&&!ka(nn)||(ai==="noscript"||ai==="noembed")&&A2(/<\/no(script|embed)/i,nn.innerHTML)?(Qi(nn),!0):(Dt&&nn.nodeType===3&&(Tr=nn.textContent,Tr=qw(Tr,xe," "),Tr=qw(Tr,De," "),Tr=qw(Tr,he," "),nn.textContent!==Tr&&(FN(a.removed,{element:nn.cloneNode()}),nn.textContent=Tr)),Gc("afterSanitizeElements",nn,null),!1)},Es=function(nn,Tr,ai){if(Bn&&(Tr==="id"||Tr==="name")&&(ai in p||ai in qi))return!1;if(!(Ot&&!cn[Tr]&&A2(Ie,Tr))){if(!(Nn&&A2(ee,Tr))){if(!wt[Tr]||cn[Tr]){if(!(lp(nn)&&(At.tagNameCheck instanceof RegExp&&A2(At.tagNameCheck,nn)||At.tagNameCheck instanceof Function&&At.tagNameCheck(nn))&&(At.attributeNameCheck instanceof RegExp&&A2(At.attributeNameCheck,Tr)||At.attributeNameCheck instanceof Function&&At.attributeNameCheck(Tr))||Tr==="is"&&At.allowCustomizedBuiltInElements&&(At.tagNameCheck instanceof RegExp&&A2(At.tagNameCheck,ai)||At.tagNameCheck instanceof Function&&At.tagNameCheck(ai))))return!1}else if(!tr[Tr]){if(!A2(gt,qw(ai,me,""))){if(!((Tr==="src"||Tr==="xlink:href"||Tr==="href")&&nn!=="script"&&REt(ai,"data:")===0&&ir[nn])){if(!(oi&&!A2(rt,qw(ai,me,"")))){if(ai)return!1}}}}}}return!0},lp=function(nn){return nn.indexOf("-")>0},sd=function(nn){let Tr,ai,Ns,mc;Gc("beforeSanitizeAttributes",nn,null);const{attributes:yu}=nn;if(!yu)return;const Mo={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:wt};for(mc=yu.length;mc--;){Tr=yu[mc];const{name:ku,namespaceURI:Ih}=Tr;if(ai=ku==="value"?Tr.value:FEt(Tr.value),Ns=Dr(ku),Mo.attrName=Ns,Mo.attrValue=ai,Mo.keepAttr=!0,Mo.forceKeepAttr=void 0,Gc("uponSanitizeAttribute",nn,Mo),ai=Mo.attrValue,Mo.forceKeepAttr||(ea(ku,nn),!Mo.keepAttr))continue;if(!kt&&A2(/\/>/i,ai)){ea(ku,nn);continue}Dt&&(ai=qw(ai,xe," "),ai=qw(ai,De," "),ai=qw(ai,he," "));const qf=Dr(nn.nodeName);if(Es(qf,Ns,ai)){if(Oe&&(Ns==="id"||Ns==="name")&&(ea(ku,nn),ai=Ri+ai),se&&typeof j=="object"&&typeof j.getAttributeType=="function"&&!Ih)switch(j.getAttributeType(qf,Ns)){case"TrustedHTML":ai=se.createHTML(ai);break;case"TrustedScriptURL":ai=se.createScriptURL(ai);break}try{Ih?nn.setAttributeNS(Ih,ku,ai):nn.setAttribute(ku,ai),SDe(a.removed)}catch{}}}Gc("afterSanitizeAttributes",nn,null)},sh=function Ai(nn){let Tr;const ai=Sa(nn);for(Gc("beforeSanitizeShadowDOM",nn,null);Tr=ai.nextNode();)Gc("uponSanitizeShadowNode",Tr,null),!Dh(Tr)&&(Tr.content instanceof w&&Ai(Tr.content),sd(Tr));Gc("afterSanitizeShadowDOM",nn,null)};return a.sanitize=function(Ai){let nn=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},Tr,ai,Ns,mc;if(Pc=!Ai,Pc&&(Ai=""),typeof Ai!="string"&&!cg(Ai)){if(typeof Ai.toString!="function")throw H1e("toString is not a function");if(Ai=Ai.toString(),typeof Ai!="string")throw H1e("dirty is not a string, aborting")}if(!a.isSupported)return Ai;if(Nt||Bc(nn),a.removed=[],typeof Ai=="string"&&(hi=!1),hi){if(Ai.nodeName){const ku=Dr(Ai.nodeName);if(!pe[ku]||Bt[ku])throw H1e("root node is forbidden and cannot be sanitized in-place")}}else if(Ai instanceof b)Tr=Ca(""),ai=Tr.ownerDocument.importNode(Ai,!0),ai.nodeType===1&&ai.nodeName==="BODY"||ai.nodeName==="HTML"?Tr=ai:Tr.appendChild(ai);else{if(!Xe&&!Dt&&!vt&&Ai.indexOf("<")===-1)return se&&Ge?se.createHTML(Ai):Ai;if(Tr=Ca(Ai),!Tr)return Xe?null:Ge?ge:""}Tr&&ze&&Qi(Tr.firstChild);const yu=Sa(hi?Ai:Tr);for(;Ns=yu.nextNode();)Dh(Ns)||(Ns.content instanceof w&&sh(Ns.content),sd(Ns));if(hi)return Ai;if(Xe){if(Lt)for(mc=Ae.call(Tr.ownerDocument);Tr.firstChild;)mc.appendChild(Tr.firstChild);else mc=Tr;return(wt.shadowroot||wt.shadowrootmod)&&(mc=ve.call(f,mc,!0)),mc}let Mo=vt?Tr.outerHTML:Tr.innerHTML;return vt&&pe["!doctype"]&&Tr.ownerDocument&&Tr.ownerDocument.doctype&&Tr.ownerDocument.doctype.name&&A2(ODe,Tr.ownerDocument.doctype.name)&&(Mo=" +`+Mo),Dt&&(Mo=qw(Mo,xe," "),Mo=qw(Mo,De," "),Mo=qw(Mo,he," ")),se&&Ge?se.createHTML(Mo):Mo},a.setConfig=function(Ai){Bc(Ai),Nt=!0},a.clearConfig=function(){Vn=null,Nt=!1},a.isValidAttribute=function(Ai,nn,Tr){Vn||Bc({});const ai=Dr(Ai),Ns=Dr(nn);return Es(ai,Ns,Tr)},a.addHook=function(Ai,nn){typeof nn=="function"&&(te[Ai]=te[Ai]||[],FN(te[Ai],nn))},a.removeHook=function(Ai){if(te[Ai])return SDe(te[Ai])},a.removeHooks=function(Ai){te[Ai]&&(te[Ai]=[])},a.removeAllHooks=function(){te={}},a}var ZU=PDe();const JU=//gi,QEt=i=>i?FDe(i).replace(/\\n/g,"#br#").split("#br#"):[""],BDe=i=>ZU.sanitize(i),RDe=(i,a)=>{var f;if(((f=a.flowchart)==null?void 0:f.htmlLabels)!==!1){const p=a.securityLevel;p==="antiscript"||p==="strict"?i=BDe(i):p!=="loose"&&(i=FDe(i),i=i.replace(//g,">"),i=i.replace(/=/g,"="),i=t9t(i))}return i},ep=(i,a)=>i&&(a.dompurifyConfig?i=ZU.sanitize(RDe(i,a),a.dompurifyConfig).toString():i=ZU.sanitize(RDe(i,a),{FORBID_TAGS:["style"]}).toString(),i),ZEt=(i,a)=>typeof i=="string"?ep(i,a):i.flat().map(f=>ep(f,a)),JEt=i=>JU.test(i),e9t=i=>i.split(JU),t9t=i=>i.replace(/#br#/g,"
"),FDe=i=>i.replace(JU,"#br#"),n9t=i=>{let a="";return i&&(a=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search,a=a.replaceAll(/\(/g,"\\("),a=a.replaceAll(/\)/g,"\\)")),a},d1=i=>!(i===!1||["false","null","0"].includes(String(i).trim().toLowerCase())),Yk=function(i){let a=i;if(i.split("~").length-1>=2){let f=a;do a=f,f=a.replace(/~([^\s,:;]+)~/,"<$1>");while(f!=a);return Yk(f)}else return a},Wa={getRows:QEt,sanitizeText:ep,sanitizeTextOrArray:ZEt,hasBreaks:JEt,splitBreaks:e9t,lineBreakRegex:JU,removeScript:BDe,getUrl:n9t,evaluate:d1},eW={min:{r:0,g:0,b:0,s:0,l:0,a:0},max:{r:255,g:255,b:255,h:360,s:100,l:100,a:1},clamp:{r:i=>i>=255?255:i<0?0:i,g:i=>i>=255?255:i<0?0:i,b:i=>i>=255?255:i<0?0:i,h:i=>i%360,s:i=>i>=100?100:i<0?0:i,l:i=>i>=100?100:i<0?0:i,a:i=>i>=1?1:i<0?0:i},toLinear:i=>{const a=i/255;return i>.03928?Math.pow((a+.055)/1.055,2.4):a/12.92},hue2rgb:(i,a,f)=>(f<0&&(f+=1),f>1&&(f-=1),f<1/6?i+(a-i)*6*f:f<1/2?a:f<2/3?i+(a-i)*(2/3-f)*6:i),hsl2rgb:({h:i,s:a,l:f},p)=>{if(!a)return f*2.55;i/=360,a/=100,f/=100;const w=f<.5?f*(1+a):f+a-f*a,y=2*f-w;switch(p){case"r":return eW.hue2rgb(y,w,i+1/3)*255;case"g":return eW.hue2rgb(y,w,i)*255;case"b":return eW.hue2rgb(y,w,i-1/3)*255}},rgb2hsl:({r:i,g:a,b:f},p)=>{i/=255,a/=255,f/=255;const w=Math.max(i,a,f),y=Math.min(i,a,f),b=(w+y)/2;if(p==="l")return b*100;if(w===y)return 0;const E=w-y,S=b>.5?E/(2-w-y):E/(w+y);if(p==="s")return S*100;switch(w){case i:return((a-f)/E+(aa>f?Math.min(a,Math.max(f,i)):Math.min(f,Math.max(a,i)),round:i=>Math.round(i*1e10)/1e10},unit:{dec2hex:i=>{const a=Math.round(i).toString(16);return a.length>1?a:`0${a}`}}},Xk={};for(let i=0;i<=255;i++)Xk[i]=Na.unit.dec2hex(i);const y0={ALL:0,RGB:1,HSL:2};class r9t{constructor(){this.type=y0.ALL}get(){return this.type}set(a){if(this.type&&this.type!==a)throw new Error("Cannot change both RGB and HSL channels at the same time");this.type=a}reset(){this.type=y0.ALL}is(a){return this.type===a}}const i9t=r9t;class s9t{constructor(a,f){this.color=f,this.changed=!1,this.data=a,this.type=new i9t}set(a,f){return this.color=f,this.changed=!1,this.data=a,this.type.type=y0.ALL,this}_ensureHSL(){const a=this.data,{h:f,s:p,l:w}=a;f===void 0&&(a.h=Na.channel.rgb2hsl(a,"h")),p===void 0&&(a.s=Na.channel.rgb2hsl(a,"s")),w===void 0&&(a.l=Na.channel.rgb2hsl(a,"l"))}_ensureRGB(){const a=this.data,{r:f,g:p,b:w}=a;f===void 0&&(a.r=Na.channel.hsl2rgb(a,"r")),p===void 0&&(a.g=Na.channel.hsl2rgb(a,"g")),w===void 0&&(a.b=Na.channel.hsl2rgb(a,"b"))}get r(){const a=this.data,f=a.r;return!this.type.is(y0.HSL)&&f!==void 0?f:(this._ensureHSL(),Na.channel.hsl2rgb(a,"r"))}get g(){const a=this.data,f=a.g;return!this.type.is(y0.HSL)&&f!==void 0?f:(this._ensureHSL(),Na.channel.hsl2rgb(a,"g"))}get b(){const a=this.data,f=a.b;return!this.type.is(y0.HSL)&&f!==void 0?f:(this._ensureHSL(),Na.channel.hsl2rgb(a,"b"))}get h(){const a=this.data,f=a.h;return!this.type.is(y0.RGB)&&f!==void 0?f:(this._ensureRGB(),Na.channel.rgb2hsl(a,"h"))}get s(){const a=this.data,f=a.s;return!this.type.is(y0.RGB)&&f!==void 0?f:(this._ensureRGB(),Na.channel.rgb2hsl(a,"s"))}get l(){const a=this.data,f=a.l;return!this.type.is(y0.RGB)&&f!==void 0?f:(this._ensureRGB(),Na.channel.rgb2hsl(a,"l"))}get a(){return this.data.a}set r(a){this.type.set(y0.RGB),this.changed=!0,this.data.r=a}set g(a){this.type.set(y0.RGB),this.changed=!0,this.data.g=a}set b(a){this.type.set(y0.RGB),this.changed=!0,this.data.b=a}set h(a){this.type.set(y0.HSL),this.changed=!0,this.data.h=a}set s(a){this.type.set(y0.HSL),this.changed=!0,this.data.s=a}set l(a){this.type.set(y0.HSL),this.changed=!0,this.data.l=a}set a(a){this.changed=!0,this.data.a=a}}const a9t=s9t,tW=new a9t({r:0,g:0,b:0,a:0},"transparent"),jDe={re:/^#((?:[a-f0-9]{2}){2,4}|[a-f0-9]{3})$/i,parse:i=>{if(i.charCodeAt(0)!==35)return;const a=i.match(jDe.re);if(!a)return;const f=a[1],p=parseInt(f,16),w=f.length,y=w%4===0,b=w>4,E=b?1:17,S=b?8:4,N=y?0:-1,B=b?255:15;return tW.set({r:(p>>S*(N+3)&B)*E,g:(p>>S*(N+2)&B)*E,b:(p>>S*(N+1)&B)*E,a:y?(p&B)*E/255:1},i)},stringify:i=>{const{r:a,g:f,b:p,a:w}=i;return w<1?`#${Xk[Math.round(a)]}${Xk[Math.round(f)]}${Xk[Math.round(p)]}${Xk[Math.round(w*255)]}`:`#${Xk[Math.round(a)]}${Xk[Math.round(f)]}${Xk[Math.round(p)]}`}},jN=jDe,nW={re:/^hsla?\(\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?(?:deg|grad|rad|turn)?)\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?%)\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?%)(?:\s*?(?:,|\/)\s*?\+?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?(%)?))?\s*?\)$/i,hueRe:/^(.+?)(deg|grad|rad|turn)$/i,_hue2deg:i=>{const a=i.match(nW.hueRe);if(a){const[,f,p]=a;switch(p){case"grad":return Na.channel.clamp.h(parseFloat(f)*.9);case"rad":return Na.channel.clamp.h(parseFloat(f)*180/Math.PI);case"turn":return Na.channel.clamp.h(parseFloat(f)*360)}}return Na.channel.clamp.h(parseFloat(i))},parse:i=>{const a=i.charCodeAt(0);if(a!==104&&a!==72)return;const f=i.match(nW.re);if(!f)return;const[,p,w,y,b,E]=f;return tW.set({h:nW._hue2deg(p),s:Na.channel.clamp.s(parseFloat(w)),l:Na.channel.clamp.l(parseFloat(y)),a:b?Na.channel.clamp.a(E?parseFloat(b)/100:parseFloat(b)):1},i)},stringify:i=>{const{h:a,s:f,l:p,a:w}=i;return w<1?`hsla(${Na.lang.round(a)}, ${Na.lang.round(f)}%, ${Na.lang.round(p)}%, ${w})`:`hsl(${Na.lang.round(a)}, ${Na.lang.round(f)}%, ${Na.lang.round(p)}%)`}},rW=nW,iW={colors:{aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyanaqua:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",rebeccapurple:"#663399",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",transparent:"#00000000",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"},parse:i=>{i=i.toLowerCase();const a=iW.colors[i];if(a)return jN.parse(a)},stringify:i=>{const a=jN.stringify(i);for(const f in iW.colors)if(iW.colors[f]===a)return f}},$De=iW,HDe={re:/^rgba?\(\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e\d+)?(%?))\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e\d+)?(%?))\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e\d+)?(%?))(?:\s*?(?:,|\/)\s*?\+?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e\d+)?(%?)))?\s*?\)$/i,parse:i=>{const a=i.charCodeAt(0);if(a!==114&&a!==82)return;const f=i.match(HDe.re);if(!f)return;const[,p,w,y,b,E,S,N,B]=f;return tW.set({r:Na.channel.clamp.r(w?parseFloat(p)*2.55:parseFloat(p)),g:Na.channel.clamp.g(b?parseFloat(y)*2.55:parseFloat(y)),b:Na.channel.clamp.b(S?parseFloat(E)*2.55:parseFloat(E)),a:N?Na.channel.clamp.a(B?parseFloat(N)/100:parseFloat(N)):1},i)},stringify:i=>{const{r:a,g:f,b:p,a:w}=i;return w<1?`rgba(${Na.lang.round(a)}, ${Na.lang.round(f)}, ${Na.lang.round(p)}, ${Na.lang.round(w)})`:`rgb(${Na.lang.round(a)}, ${Na.lang.round(f)}, ${Na.lang.round(p)})`}},sW=HDe,r3={format:{keyword:$De,hex:jN,rgb:sW,rgba:sW,hsl:rW,hsla:rW},parse:i=>{if(typeof i!="string")return i;const a=jN.parse(i)||sW.parse(i)||rW.parse(i)||$De.parse(i);if(a)return a;throw new Error(`Unsupported color format: "${i}"`)},stringify:i=>!i.changed&&i.color?i.color:i.type.is(y0.HSL)||i.data.r===void 0?rW.stringify(i):i.a<1||!Number.isInteger(i.r)||!Number.isInteger(i.g)||!Number.isInteger(i.b)?sW.stringify(i):jN.stringify(i)},zDe=(i,a)=>{const f=r3.parse(i);for(const p in a)f[p]=Na.channel.clamp[p](a[p]);return r3.stringify(f)},$N=(i,a,f=0,p=1)=>{if(typeof i!="number")return zDe(i,{a});const w=tW.set({r:Na.channel.clamp.r(i),g:Na.channel.clamp.g(a),b:Na.channel.clamp.b(f),a:Na.channel.clamp.a(p)});return r3.stringify(w)},o9t=i=>{const{r:a,g:f,b:p}=r3.parse(i),w=.2126*Na.channel.toLinear(a)+.7152*Na.channel.toLinear(f)+.0722*Na.channel.toLinear(p);return Na.lang.round(w)},c9t=i=>o9t(i)>=.5,GDe=i=>!c9t(i),qDe=(i,a,f)=>{const p=r3.parse(i),w=p[a],y=Na.channel.clamp[a](w+f);return w!==y&&(p[a]=y),r3.stringify(p)},Qs=(i,a)=>qDe(i,"l",a),ya=(i,a)=>qDe(i,"l",-a),Gn=(i,a)=>{const f=r3.parse(i),p={};for(const w in a)a[w]&&(p[w]=f[w]+a[w]);return zDe(i,p)},u9t=(i,a,f=50)=>{const{r:p,g:w,b:y,a:b}=r3.parse(i),{r:E,g:S,b:N,a:B}=r3.parse(a),R=f/100,j=R*2-1,$=b-B,Q=((j*$===-1?j:(j+$)/(1+j*$))+1)/2,oe=1-Q,ce=p*Q+E*oe,se=w*Q+S*oe,ge=y*Q+N*oe,ye=b*R+B*(1-R);return $N(ce,se,ge,ye)},Bi=(i,a=100)=>{const f=r3.parse(i);return f.r=255-f.r,f.g=255-f.g,f.b=255-f.b,u9t(f,i,a)},ig=(i,a)=>a?Gn(i,{s:-40,l:10}):Gn(i,{s:-40,l:-10}),aW="#ffffff",oW="#f2f2f2";let l9t=class{constructor(){this.background="#f4f4f4",this.primaryColor="#fff4dd",this.noteBkgColor="#fff5ad",this.noteTextColor="#333",this.THEME_COLOR_LIMIT=12,this.fontFamily='"trebuchet ms", verdana, arial, sans-serif',this.fontSize="16px"}updateColors(){if(this.primaryTextColor=this.primaryTextColor||(this.darkMode?"#eee":"#333"),this.secondaryColor=this.secondaryColor||Gn(this.primaryColor,{h:-120}),this.tertiaryColor=this.tertiaryColor||Gn(this.primaryColor,{h:180,l:5}),this.primaryBorderColor=this.primaryBorderColor||ig(this.primaryColor,this.darkMode),this.secondaryBorderColor=this.secondaryBorderColor||ig(this.secondaryColor,this.darkMode),this.tertiaryBorderColor=this.tertiaryBorderColor||ig(this.tertiaryColor,this.darkMode),this.noteBorderColor=this.noteBorderColor||ig(this.noteBkgColor,this.darkMode),this.noteBkgColor=this.noteBkgColor||"#fff5ad",this.noteTextColor=this.noteTextColor||"#333",this.secondaryTextColor=this.secondaryTextColor||Bi(this.secondaryColor),this.tertiaryTextColor=this.tertiaryTextColor||Bi(this.tertiaryColor),this.lineColor=this.lineColor||Bi(this.background),this.arrowheadColor=this.arrowheadColor||Bi(this.background),this.textColor=this.textColor||this.primaryTextColor,this.border2=this.border2||this.tertiaryBorderColor,this.nodeBkg=this.nodeBkg||this.primaryColor,this.mainBkg=this.mainBkg||this.primaryColor,this.nodeBorder=this.nodeBorder||this.primaryBorderColor,this.clusterBkg=this.clusterBkg||this.tertiaryColor,this.clusterBorder=this.clusterBorder||this.tertiaryBorderColor,this.defaultLinkColor=this.defaultLinkColor||this.lineColor,this.titleColor=this.titleColor||this.tertiaryTextColor,this.edgeLabelBackground=this.edgeLabelBackground||(this.darkMode?ya(this.secondaryColor,30):this.secondaryColor),this.nodeTextColor=this.nodeTextColor||this.primaryTextColor,this.actorBorder=this.actorBorder||this.primaryBorderColor,this.actorBkg=this.actorBkg||this.mainBkg,this.actorTextColor=this.actorTextColor||this.primaryTextColor,this.actorLineColor=this.actorLineColor||"grey",this.labelBoxBkgColor=this.labelBoxBkgColor||this.actorBkg,this.signalColor=this.signalColor||this.textColor,this.signalTextColor=this.signalTextColor||this.textColor,this.labelBoxBorderColor=this.labelBoxBorderColor||this.actorBorder,this.labelTextColor=this.labelTextColor||this.actorTextColor,this.loopTextColor=this.loopTextColor||this.actorTextColor,this.activationBorderColor=this.activationBorderColor||ya(this.secondaryColor,10),this.activationBkgColor=this.activationBkgColor||this.secondaryColor,this.sequenceNumberColor=this.sequenceNumberColor||Bi(this.lineColor),this.sectionBkgColor=this.sectionBkgColor||this.tertiaryColor,this.altSectionBkgColor=this.altSectionBkgColor||"white",this.sectionBkgColor=this.sectionBkgColor||this.secondaryColor,this.sectionBkgColor2=this.sectionBkgColor2||this.primaryColor,this.excludeBkgColor=this.excludeBkgColor||"#eeeeee",this.taskBorderColor=this.taskBorderColor||this.primaryBorderColor,this.taskBkgColor=this.taskBkgColor||this.primaryColor,this.activeTaskBorderColor=this.activeTaskBorderColor||this.primaryColor,this.activeTaskBkgColor=this.activeTaskBkgColor||Qs(this.primaryColor,23),this.gridColor=this.gridColor||"lightgrey",this.doneTaskBkgColor=this.doneTaskBkgColor||"lightgrey",this.doneTaskBorderColor=this.doneTaskBorderColor||"grey",this.critBorderColor=this.critBorderColor||"#ff8888",this.critBkgColor=this.critBkgColor||"red",this.todayLineColor=this.todayLineColor||"red",this.taskTextColor=this.taskTextColor||this.textColor,this.taskTextOutsideColor=this.taskTextOutsideColor||this.textColor,this.taskTextLightColor=this.taskTextLightColor||this.textColor,this.taskTextColor=this.taskTextColor||this.primaryTextColor,this.taskTextDarkColor=this.taskTextDarkColor||this.textColor,this.taskTextClickableColor=this.taskTextClickableColor||"#003163",this.personBorder=this.personBorder||this.primaryBorderColor,this.personBkg=this.personBkg||this.mainBkg,this.transitionColor=this.transitionColor||this.lineColor,this.transitionLabelColor=this.transitionLabelColor||this.textColor,this.stateLabelColor=this.stateLabelColor||this.stateBkg||this.primaryTextColor,this.stateBkg=this.stateBkg||this.mainBkg,this.labelBackgroundColor=this.labelBackgroundColor||this.stateBkg,this.compositeBackground=this.compositeBackground||this.background||this.tertiaryColor,this.altBackground=this.altBackground||this.tertiaryColor,this.compositeTitleBackground=this.compositeTitleBackground||this.mainBkg,this.compositeBorder=this.compositeBorder||this.nodeBorder,this.innerEndBackground=this.nodeBorder,this.errorBkgColor=this.errorBkgColor||this.tertiaryColor,this.errorTextColor=this.errorTextColor||this.tertiaryTextColor,this.transitionColor=this.transitionColor||this.lineColor,this.specialStateColor=this.lineColor,this.cScale0=this.cScale0||this.primaryColor,this.cScale1=this.cScale1||this.secondaryColor,this.cScale2=this.cScale2||this.tertiaryColor,this.cScale3=this.cScale3||Gn(this.primaryColor,{h:30}),this.cScale4=this.cScale4||Gn(this.primaryColor,{h:60}),this.cScale5=this.cScale5||Gn(this.primaryColor,{h:90}),this.cScale6=this.cScale6||Gn(this.primaryColor,{h:120}),this.cScale7=this.cScale7||Gn(this.primaryColor,{h:150}),this.cScale8=this.cScale8||Gn(this.primaryColor,{h:210,l:150}),this.cScale9=this.cScale9||Gn(this.primaryColor,{h:270}),this.cScale10=this.cScale10||Gn(this.primaryColor,{h:300}),this.cScale11=this.cScale11||Gn(this.primaryColor,{h:330}),this.darkMode)for(let f=0;f{this[p]=a[p]}),this.updateColors(),f.forEach(p=>{this[p]=a[p]})}};const h9t=i=>{const a=new l9t;return a.calculate(i),a};let f9t=class{constructor(){this.background="#333",this.primaryColor="#1f2020",this.secondaryColor=Qs(this.primaryColor,16),this.tertiaryColor=Gn(this.primaryColor,{h:-160}),this.primaryBorderColor=Bi(this.background),this.secondaryBorderColor=ig(this.secondaryColor,this.darkMode),this.tertiaryBorderColor=ig(this.tertiaryColor,this.darkMode),this.primaryTextColor=Bi(this.primaryColor),this.secondaryTextColor=Bi(this.secondaryColor),this.tertiaryTextColor=Bi(this.tertiaryColor),this.lineColor=Bi(this.background),this.textColor=Bi(this.background),this.mainBkg="#1f2020",this.secondBkg="calculated",this.mainContrastColor="lightgrey",this.darkTextColor=Qs(Bi("#323D47"),10),this.lineColor="calculated",this.border1="#81B1DB",this.border2=$N(255,255,255,.25),this.arrowheadColor="calculated",this.fontFamily='"trebuchet ms", verdana, arial, sans-serif',this.fontSize="16px",this.labelBackground="#181818",this.textColor="#ccc",this.THEME_COLOR_LIMIT=12,this.nodeBkg="calculated",this.nodeBorder="calculated",this.clusterBkg="calculated",this.clusterBorder="calculated",this.defaultLinkColor="calculated",this.titleColor="#F9FFFE",this.edgeLabelBackground="calculated",this.actorBorder="calculated",this.actorBkg="calculated",this.actorTextColor="calculated",this.actorLineColor="calculated",this.signalColor="calculated",this.signalTextColor="calculated",this.labelBoxBkgColor="calculated",this.labelBoxBorderColor="calculated",this.labelTextColor="calculated",this.loopTextColor="calculated",this.noteBorderColor="calculated",this.noteBkgColor="#fff5ad",this.noteTextColor="calculated",this.activationBorderColor="calculated",this.activationBkgColor="calculated",this.sequenceNumberColor="black",this.sectionBkgColor=ya("#EAE8D9",30),this.altSectionBkgColor="calculated",this.sectionBkgColor2="#EAE8D9",this.excludeBkgColor=ya(this.sectionBkgColor,10),this.taskBorderColor=$N(255,255,255,70),this.taskBkgColor="calculated",this.taskTextColor="calculated",this.taskTextLightColor="calculated",this.taskTextOutsideColor="calculated",this.taskTextClickableColor="#003163",this.activeTaskBorderColor=$N(255,255,255,50),this.activeTaskBkgColor="#81B1DB",this.gridColor="calculated",this.doneTaskBkgColor="calculated",this.doneTaskBorderColor="grey",this.critBorderColor="#E83737",this.critBkgColor="#E83737",this.taskTextDarkColor="calculated",this.todayLineColor="#DB5757",this.personBorder=this.primaryBorderColor,this.personBkg=this.mainBkg,this.labelColor="calculated",this.errorBkgColor="#a44141",this.errorTextColor="#ddd"}updateColors(){this.secondBkg=Qs(this.mainBkg,16),this.lineColor=this.mainContrastColor,this.arrowheadColor=this.mainContrastColor,this.nodeBkg=this.mainBkg,this.nodeBorder=this.border1,this.clusterBkg=this.secondBkg,this.clusterBorder=this.border2,this.defaultLinkColor=this.lineColor,this.edgeLabelBackground=Qs(this.labelBackground,25),this.actorBorder=this.border1,this.actorBkg=this.mainBkg,this.actorTextColor=this.mainContrastColor,this.actorLineColor=this.mainContrastColor,this.signalColor=this.mainContrastColor,this.signalTextColor=this.mainContrastColor,this.labelBoxBkgColor=this.actorBkg,this.labelBoxBorderColor=this.actorBorder,this.labelTextColor=this.mainContrastColor,this.loopTextColor=this.mainContrastColor,this.noteBorderColor=this.secondaryBorderColor,this.noteBkgColor=this.secondBkg,this.noteTextColor=this.secondaryTextColor,this.activationBorderColor=this.border1,this.activationBkgColor=this.secondBkg,this.altSectionBkgColor=this.background,this.taskBkgColor=Qs(this.mainBkg,23),this.taskTextColor=this.darkTextColor,this.taskTextLightColor=this.mainContrastColor,this.taskTextOutsideColor=this.taskTextLightColor,this.gridColor=this.mainContrastColor,this.doneTaskBkgColor=this.mainContrastColor,this.taskTextDarkColor=this.darkTextColor,this.transitionColor=this.transitionColor||this.lineColor,this.transitionLabelColor=this.transitionLabelColor||this.textColor,this.stateLabelColor=this.stateLabelColor||this.stateBkg||this.primaryTextColor,this.stateBkg=this.stateBkg||this.mainBkg,this.labelBackgroundColor=this.labelBackgroundColor||this.stateBkg,this.compositeBackground=this.compositeBackground||this.background||this.tertiaryColor,this.altBackground=this.altBackground||"#555",this.compositeTitleBackground=this.compositeTitleBackground||this.mainBkg,this.compositeBorder=this.compositeBorder||this.nodeBorder,this.innerEndBackground=this.primaryBorderColor,this.specialStateColor="#f4f4f4",this.errorBkgColor=this.errorBkgColor||this.tertiaryColor,this.errorTextColor=this.errorTextColor||this.tertiaryTextColor,this.fillType0=this.primaryColor,this.fillType1=this.secondaryColor,this.fillType2=Gn(this.primaryColor,{h:64}),this.fillType3=Gn(this.secondaryColor,{h:64}),this.fillType4=Gn(this.primaryColor,{h:-64}),this.fillType5=Gn(this.secondaryColor,{h:-64}),this.fillType6=Gn(this.primaryColor,{h:128}),this.fillType7=Gn(this.secondaryColor,{h:128}),this.cScale1=this.cScale1||"#0b0000",this.cScale2=this.cScale2||"#4d1037",this.cScale3=this.cScale3||"#3f5258",this.cScale4=this.cScale4||"#4f2f1b",this.cScale5=this.cScale5||"#6e0a0a",this.cScale6=this.cScale6||"#3b0048",this.cScale7=this.cScale7||"#995a01",this.cScale8=this.cScale8||"#154706",this.cScale9=this.cScale9||"#161722",this.cScale10=this.cScale10||"#00296f",this.cScale11=this.cScale11||"#01629c",this.cScale12=this.cScale12||"#010029",this.cScale0=this.cScale0||this.primaryColor,this.cScale1=this.cScale1||this.secondaryColor,this.cScale2=this.cScale2||this.tertiaryColor,this.cScale3=this.cScale3||Gn(this.primaryColor,{h:30}),this.cScale4=this.cScale4||Gn(this.primaryColor,{h:60}),this.cScale5=this.cScale5||Gn(this.primaryColor,{h:90}),this.cScale6=this.cScale6||Gn(this.primaryColor,{h:120}),this.cScale7=this.cScale7||Gn(this.primaryColor,{h:150}),this.cScale8=this.cScale8||Gn(this.primaryColor,{h:210}),this.cScale9=this.cScale9||Gn(this.primaryColor,{h:270}),this.cScale10=this.cScale10||Gn(this.primaryColor,{h:300}),this.cScale11=this.cScale11||Gn(this.primaryColor,{h:330});for(let a=0;a{this[p]=a[p]}),this.updateColors(),f.forEach(p=>{this[p]=a[p]})}};const d9t=i=>{const a=new f9t;return a.calculate(i),a};let g9t=class{constructor(){this.background="#f4f4f4",this.primaryColor="#ECECFF",this.secondaryColor=Gn(this.primaryColor,{h:120}),this.secondaryColor="#ffffde",this.tertiaryColor=Gn(this.primaryColor,{h:-160}),this.primaryBorderColor=ig(this.primaryColor,this.darkMode),this.secondaryBorderColor=ig(this.secondaryColor,this.darkMode),this.tertiaryBorderColor=ig(this.tertiaryColor,this.darkMode),this.primaryTextColor=Bi(this.primaryColor),this.secondaryTextColor=Bi(this.secondaryColor),this.tertiaryTextColor=Bi(this.tertiaryColor),this.lineColor=Bi(this.background),this.textColor=Bi(this.background),this.background="white",this.mainBkg="#ECECFF",this.secondBkg="#ffffde",this.lineColor="#333333",this.border1="#9370DB",this.border2="#aaaa33",this.arrowheadColor="#333333",this.fontFamily='"trebuchet ms", verdana, arial, sans-serif',this.fontSize="16px",this.labelBackground="#e8e8e8",this.textColor="#333",this.THEME_COLOR_LIMIT=12,this.nodeBkg="calculated",this.nodeBorder="calculated",this.clusterBkg="calculated",this.clusterBorder="calculated",this.defaultLinkColor="calculated",this.titleColor="calculated",this.edgeLabelBackground="calculated",this.actorBorder="calculated",this.actorBkg="calculated",this.actorTextColor="black",this.actorLineColor="grey",this.signalColor="calculated",this.signalTextColor="calculated",this.labelBoxBkgColor="calculated",this.labelBoxBorderColor="calculated",this.labelTextColor="calculated",this.loopTextColor="calculated",this.noteBorderColor="calculated",this.noteBkgColor="#fff5ad",this.noteTextColor="calculated",this.activationBorderColor="#666",this.activationBkgColor="#f4f4f4",this.sequenceNumberColor="white",this.sectionBkgColor="calculated",this.altSectionBkgColor="calculated",this.sectionBkgColor2="calculated",this.excludeBkgColor="#eeeeee",this.taskBorderColor="calculated",this.taskBkgColor="calculated",this.taskTextLightColor="calculated",this.taskTextColor=this.taskTextLightColor,this.taskTextDarkColor="calculated",this.taskTextOutsideColor=this.taskTextDarkColor,this.taskTextClickableColor="calculated",this.activeTaskBorderColor="calculated",this.activeTaskBkgColor="calculated",this.gridColor="calculated",this.doneTaskBkgColor="calculated",this.doneTaskBorderColor="calculated",this.critBorderColor="calculated",this.critBkgColor="calculated",this.todayLineColor="calculated",this.sectionBkgColor=$N(102,102,255,.49),this.altSectionBkgColor="white",this.sectionBkgColor2="#fff400",this.taskBorderColor="#534fbc",this.taskBkgColor="#8a90dd",this.taskTextLightColor="white",this.taskTextColor="calculated",this.taskTextDarkColor="black",this.taskTextOutsideColor="calculated",this.taskTextClickableColor="#003163",this.activeTaskBorderColor="#534fbc",this.activeTaskBkgColor="#bfc7ff",this.gridColor="lightgrey",this.doneTaskBkgColor="lightgrey",this.doneTaskBorderColor="grey",this.critBorderColor="#ff8888",this.critBkgColor="red",this.todayLineColor="red",this.personBorder=this.primaryBorderColor,this.personBkg=this.mainBkg,this.labelColor="black",this.errorBkgColor="#552222",this.errorTextColor="#552222",this.updateColors()}updateColors(){this.cScale0=this.cScale0||this.primaryColor,this.cScale1=this.cScale1||this.secondaryColor,this.cScale2=this.cScale2||this.tertiaryColor,this.cScale3=this.cScale3||Gn(this.primaryColor,{h:30}),this.cScale4=this.cScale4||Gn(this.primaryColor,{h:60}),this.cScale5=this.cScale5||Gn(this.primaryColor,{h:90}),this.cScale6=this.cScale6||Gn(this.primaryColor,{h:120}),this.cScale7=this.cScale7||Gn(this.primaryColor,{h:150}),this.cScale8=this.cScale8||Gn(this.primaryColor,{h:210}),this.cScale9=this.cScale9||Gn(this.primaryColor,{h:270}),this.cScale10=this.cScale10||Gn(this.primaryColor,{h:300}),this.cScale11=this.cScale11||Gn(this.primaryColor,{h:330}),this["cScalePeer1"]=this["cScalePeer1"]||ya(this.secondaryColor,45),this["cScalePeer2"]=this["cScalePeer2"]||ya(this.tertiaryColor,40);for(let a=0;a{this[p]=a[p]}),this.updateColors(),f.forEach(p=>{this[p]=a[p]})}};const p9t=i=>{const a=new g9t;return a.calculate(i),a};let b9t=class{constructor(){this.background="#f4f4f4",this.primaryColor="#cde498",this.secondaryColor="#cdffb2",this.background="white",this.mainBkg="#cde498",this.secondBkg="#cdffb2",this.lineColor="green",this.border1="#13540c",this.border2="#6eaa49",this.arrowheadColor="green",this.fontFamily='"trebuchet ms", verdana, arial, sans-serif',this.fontSize="16px",this.tertiaryColor=Qs("#cde498",10),this.primaryBorderColor=ig(this.primaryColor,this.darkMode),this.secondaryBorderColor=ig(this.secondaryColor,this.darkMode),this.tertiaryBorderColor=ig(this.tertiaryColor,this.darkMode),this.primaryTextColor=Bi(this.primaryColor),this.secondaryTextColor=Bi(this.secondaryColor),this.tertiaryTextColor=Bi(this.primaryColor),this.lineColor=Bi(this.background),this.textColor=Bi(this.background),this.THEME_COLOR_LIMIT=12,this.nodeBkg="calculated",this.nodeBorder="calculated",this.clusterBkg="calculated",this.clusterBorder="calculated",this.defaultLinkColor="calculated",this.titleColor="#333",this.edgeLabelBackground="#e8e8e8",this.actorBorder="calculated",this.actorBkg="calculated",this.actorTextColor="black",this.actorLineColor="grey",this.signalColor="#333",this.signalTextColor="#333",this.labelBoxBkgColor="calculated",this.labelBoxBorderColor="#326932",this.labelTextColor="calculated",this.loopTextColor="calculated",this.noteBorderColor="calculated",this.noteBkgColor="#fff5ad",this.noteTextColor="calculated",this.activationBorderColor="#666",this.activationBkgColor="#f4f4f4",this.sequenceNumberColor="white",this.sectionBkgColor="#6eaa49",this.altSectionBkgColor="white",this.sectionBkgColor2="#6eaa49",this.excludeBkgColor="#eeeeee",this.taskBorderColor="calculated",this.taskBkgColor="#487e3a",this.taskTextLightColor="white",this.taskTextColor="calculated",this.taskTextDarkColor="black",this.taskTextOutsideColor="calculated",this.taskTextClickableColor="#003163",this.activeTaskBorderColor="calculated",this.activeTaskBkgColor="calculated",this.gridColor="lightgrey",this.doneTaskBkgColor="lightgrey",this.doneTaskBorderColor="grey",this.critBorderColor="#ff8888",this.critBkgColor="red",this.todayLineColor="red",this.personBorder=this.primaryBorderColor,this.personBkg=this.mainBkg,this.labelColor="black",this.errorBkgColor="#552222",this.errorTextColor="#552222"}updateColors(){this.actorBorder=ya(this.mainBkg,20),this.actorBkg=this.mainBkg,this.labelBoxBkgColor=this.actorBkg,this.labelTextColor=this.actorTextColor,this.loopTextColor=this.actorTextColor,this.noteBorderColor=this.border2,this.noteTextColor=this.actorTextColor,this.cScale0=this.cScale0||this.primaryColor,this.cScale1=this.cScale1||this.secondaryColor,this.cScale2=this.cScale2||this.tertiaryColor,this.cScale3=this.cScale3||Gn(this.primaryColor,{h:30}),this.cScale4=this.cScale4||Gn(this.primaryColor,{h:60}),this.cScale5=this.cScale5||Gn(this.primaryColor,{h:90}),this.cScale6=this.cScale6||Gn(this.primaryColor,{h:120}),this.cScale7=this.cScale7||Gn(this.primaryColor,{h:150}),this.cScale8=this.cScale8||Gn(this.primaryColor,{h:210}),this.cScale9=this.cScale9||Gn(this.primaryColor,{h:270}),this.cScale10=this.cScale10||Gn(this.primaryColor,{h:300}),this.cScale11=this.cScale11||Gn(this.primaryColor,{h:330}),this["cScalePeer1"]=this["cScalePeer1"]||ya(this.secondaryColor,45),this["cScalePeer2"]=this["cScalePeer2"]||ya(this.tertiaryColor,40);for(let a=0;a{this[p]=a[p]}),this.updateColors(),f.forEach(p=>{this[p]=a[p]})}};const v9t=i=>{const a=new b9t;return a.calculate(i),a};class w9t{constructor(){this.primaryColor="#eee",this.contrast="#707070",this.secondaryColor=Qs(this.contrast,55),this.background="#ffffff",this.tertiaryColor=Gn(this.primaryColor,{h:-160}),this.primaryBorderColor=ig(this.primaryColor,this.darkMode),this.secondaryBorderColor=ig(this.secondaryColor,this.darkMode),this.tertiaryBorderColor=ig(this.tertiaryColor,this.darkMode),this.primaryTextColor=Bi(this.primaryColor),this.secondaryTextColor=Bi(this.secondaryColor),this.tertiaryTextColor=Bi(this.tertiaryColor),this.lineColor=Bi(this.background),this.textColor=Bi(this.background),this.mainBkg="#eee",this.secondBkg="calculated",this.lineColor="#666",this.border1="#999",this.border2="calculated",this.note="#ffa",this.text="#333",this.critical="#d42",this.done="#bbb",this.arrowheadColor="#333333",this.fontFamily='"trebuchet ms", verdana, arial, sans-serif',this.fontSize="16px",this.THEME_COLOR_LIMIT=12,this.nodeBkg="calculated",this.nodeBorder="calculated",this.clusterBkg="calculated",this.clusterBorder="calculated",this.defaultLinkColor="calculated",this.titleColor="calculated",this.edgeLabelBackground="white",this.actorBorder="calculated",this.actorBkg="calculated",this.actorTextColor="calculated",this.actorLineColor="calculated",this.signalColor="calculated",this.signalTextColor="calculated",this.labelBoxBkgColor="calculated",this.labelBoxBorderColor="calculated",this.labelTextColor="calculated",this.loopTextColor="calculated",this.noteBorderColor="calculated",this.noteBkgColor="calculated",this.noteTextColor="calculated",this.activationBorderColor="#666",this.activationBkgColor="#f4f4f4",this.sequenceNumberColor="white",this.sectionBkgColor="calculated",this.altSectionBkgColor="white",this.sectionBkgColor2="calculated",this.excludeBkgColor="#eeeeee",this.taskBorderColor="calculated",this.taskBkgColor="calculated",this.taskTextLightColor="white",this.taskTextColor="calculated",this.taskTextDarkColor="calculated",this.taskTextOutsideColor="calculated",this.taskTextClickableColor="#003163",this.activeTaskBorderColor="calculated",this.activeTaskBkgColor="calculated",this.gridColor="calculated",this.doneTaskBkgColor="calculated",this.doneTaskBorderColor="calculated",this.critBkgColor="calculated",this.critBorderColor="calculated",this.todayLineColor="calculated",this.personBorder=this.primaryBorderColor,this.personBkg=this.mainBkg,this.labelColor="black",this.errorBkgColor="#552222",this.errorTextColor="#552222"}updateColors(){this.secondBkg=Qs(this.contrast,55),this.border2=this.contrast,this.actorBorder=Qs(this.border1,23),this.actorBkg=this.mainBkg,this.actorTextColor=this.text,this.actorLineColor=this.lineColor,this.signalColor=this.text,this.signalTextColor=this.text,this.labelBoxBkgColor=this.actorBkg,this.labelBoxBorderColor=this.actorBorder,this.labelTextColor=this.text,this.loopTextColor=this.text,this.noteBorderColor="#999",this.noteBkgColor="#666",this.noteTextColor="#fff",this.cScale0=this.cScale0||"#555",this.cScale1=this.cScale1||"#F4F4F4",this.cScale2=this.cScale2||"#555",this.cScale3=this.cScale3||"#BBB",this.cScale4=this.cScale4||"#777",this.cScale5=this.cScale5||"#999",this.cScale6=this.cScale6||"#DDD",this.cScale7=this.cScale7||"#FFF",this.cScale8=this.cScale8||"#DDD",this.cScale9=this.cScale9||"#BBB",this.cScale10=this.cScale10||"#999",this.cScale11=this.cScale11||"#777";for(let a=0;a{this[p]=a[p]}),this.updateColors(),f.forEach(p=>{this[p]=a[p]})}}const g5={base:{getThemeVariables:h9t},dark:{getThemeVariables:d9t},default:{getThemeVariables:p9t},forest:{getThemeVariables:v9t},neutral:{getThemeVariables:i=>{const a=new w9t;return a.calculate(i),a}}},Qk={theme:"default",themeVariables:g5.default.getThemeVariables(),themeCSS:void 0,maxTextSize:5e4,darkMode:!1,fontFamily:'"trebuchet ms", verdana, arial, sans-serif;',logLevel:5,securityLevel:"strict",startOnLoad:!0,arrowMarkerAbsolute:!1,secure:["secure","securityLevel","startOnLoad","maxTextSize"],deterministicIds:!1,deterministicIDSeed:void 0,flowchart:{titleTopMargin:25,diagramPadding:8,htmlLabels:!0,nodeSpacing:50,rankSpacing:50,curve:"basis",padding:15,useMaxWidth:!0,defaultRenderer:"dagre-wrapper",wrappingWidth:200},sequence:{hideUnusedParticipants:!1,activationWidth:10,diagramMarginX:50,diagramMarginY:10,actorMargin:50,width:150,height:65,boxMargin:10,boxTextMargin:5,noteMargin:10,messageMargin:35,messageAlign:"center",mirrorActors:!0,forceMenus:!1,bottomMarginAdj:1,useMaxWidth:!0,rightAngles:!1,showSequenceNumbers:!1,actorFontSize:14,actorFontFamily:'"Open Sans", sans-serif',actorFontWeight:400,noteFontSize:14,noteFontFamily:'"trebuchet ms", verdana, arial, sans-serif',noteFontWeight:400,noteAlign:"center",messageFontSize:16,messageFontFamily:'"trebuchet ms", verdana, arial, sans-serif',messageFontWeight:400,wrap:!1,wrapPadding:10,labelBoxWidth:50,labelBoxHeight:20,messageFont:function(){return{fontFamily:this.messageFontFamily,fontSize:this.messageFontSize,fontWeight:this.messageFontWeight}},noteFont:function(){return{fontFamily:this.noteFontFamily,fontSize:this.noteFontSize,fontWeight:this.noteFontWeight}},actorFont:function(){return{fontFamily:this.actorFontFamily,fontSize:this.actorFontSize,fontWeight:this.actorFontWeight}}},gantt:{titleTopMargin:25,barHeight:20,barGap:4,topPadding:50,rightPadding:75,leftPadding:75,gridLineStartPadding:35,fontSize:11,sectionFontSize:11,numberSectionStyles:4,displayMode:"",axisFormat:"%Y-%m-%d",tickInterval:void 0,useMaxWidth:!0,topAxis:!1,useWidth:void 0},journey:{diagramMarginX:50,diagramMarginY:10,leftMargin:150,width:150,height:50,boxMargin:10,boxTextMargin:5,noteMargin:10,messageMargin:35,messageAlign:"center",bottomMarginAdj:1,useMaxWidth:!0,rightAngles:!1,taskFontSize:14,taskFontFamily:'"Open Sans", sans-serif',taskMargin:50,activationWidth:10,textPlacement:"fo",actorColours:["#8FBC8F","#7CFC00","#00FFFF","#20B2AA","#B0E0E6","#FFFFE0"],sectionFills:["#191970","#8B008B","#4B0082","#2F4F4F","#800000","#8B4513","#00008B"],sectionColours:["#fff"]},timeline:{diagramMarginX:50,diagramMarginY:10,leftMargin:150,width:150,height:50,boxMargin:10,boxTextMargin:5,noteMargin:10,messageMargin:35,messageAlign:"center",bottomMarginAdj:1,useMaxWidth:!0,rightAngles:!1,taskFontSize:14,taskFontFamily:'"Open Sans", sans-serif',taskMargin:50,activationWidth:10,textPlacement:"fo",actorColours:["#8FBC8F","#7CFC00","#00FFFF","#20B2AA","#B0E0E6","#FFFFE0"],sectionFills:["#191970","#8B008B","#4B0082","#2F4F4F","#800000","#8B4513","#00008B"],sectionColours:["#fff"],disableMulticolor:!1},class:{titleTopMargin:25,arrowMarkerAbsolute:!1,dividerMargin:10,padding:5,textHeight:10,useMaxWidth:!0,defaultRenderer:"dagre-wrapper"},state:{titleTopMargin:25,dividerMargin:10,sizeUnit:5,padding:8,textHeight:10,titleShift:-15,noteMargin:10,forkWidth:70,forkHeight:7,miniPadding:2,fontSizeFactor:5.02,fontSize:24,labelHeight:16,edgeLengthFactor:"20",compositTitleSize:35,radius:5,useMaxWidth:!0,defaultRenderer:"dagre-wrapper"},er:{titleTopMargin:25,diagramPadding:20,layoutDirection:"TB",minEntityWidth:100,minEntityHeight:75,entityPadding:15,stroke:"gray",fill:"honeydew",fontSize:12,useMaxWidth:!0},pie:{useWidth:void 0,useMaxWidth:!0,textPosition:.75},requirement:{useWidth:void 0,useMaxWidth:!0,rect_fill:"#f9f9f9",text_color:"#333",rect_border_size:"0.5px",rect_border_color:"#bbb",rect_min_width:200,rect_min_height:200,fontSize:14,rect_padding:10,line_height:20},gitGraph:{titleTopMargin:25,diagramPadding:8,nodeLabel:{width:75,height:100,x:-25,y:0},mainBranchName:"main",mainBranchOrder:0,showCommitLabel:!0,showBranches:!0,rotateCommitLabel:!0},c4:{useWidth:void 0,diagramMarginX:50,diagramMarginY:10,c4ShapeMargin:50,c4ShapePadding:20,width:216,height:60,boxMargin:10,useMaxWidth:!0,c4ShapeInRow:4,nextLinePaddingX:0,c4BoundaryInRow:2,personFontSize:14,personFontFamily:'"Open Sans", sans-serif',personFontWeight:"normal",external_personFontSize:14,external_personFontFamily:'"Open Sans", sans-serif',external_personFontWeight:"normal",systemFontSize:14,systemFontFamily:'"Open Sans", sans-serif',systemFontWeight:"normal",external_systemFontSize:14,external_systemFontFamily:'"Open Sans", sans-serif',external_systemFontWeight:"normal",system_dbFontSize:14,system_dbFontFamily:'"Open Sans", sans-serif',system_dbFontWeight:"normal",external_system_dbFontSize:14,external_system_dbFontFamily:'"Open Sans", sans-serif',external_system_dbFontWeight:"normal",system_queueFontSize:14,system_queueFontFamily:'"Open Sans", sans-serif',system_queueFontWeight:"normal",external_system_queueFontSize:14,external_system_queueFontFamily:'"Open Sans", sans-serif',external_system_queueFontWeight:"normal",boundaryFontSize:14,boundaryFontFamily:'"Open Sans", sans-serif',boundaryFontWeight:"normal",messageFontSize:12,messageFontFamily:'"Open Sans", sans-serif',messageFontWeight:"normal",containerFontSize:14,containerFontFamily:'"Open Sans", sans-serif',containerFontWeight:"normal",external_containerFontSize:14,external_containerFontFamily:'"Open Sans", sans-serif',external_containerFontWeight:"normal",container_dbFontSize:14,container_dbFontFamily:'"Open Sans", sans-serif',container_dbFontWeight:"normal",external_container_dbFontSize:14,external_container_dbFontFamily:'"Open Sans", sans-serif',external_container_dbFontWeight:"normal",container_queueFontSize:14,container_queueFontFamily:'"Open Sans", sans-serif',container_queueFontWeight:"normal",external_container_queueFontSize:14,external_container_queueFontFamily:'"Open Sans", sans-serif',external_container_queueFontWeight:"normal",componentFontSize:14,componentFontFamily:'"Open Sans", sans-serif',componentFontWeight:"normal",external_componentFontSize:14,external_componentFontFamily:'"Open Sans", sans-serif',external_componentFontWeight:"normal",component_dbFontSize:14,component_dbFontFamily:'"Open Sans", sans-serif',component_dbFontWeight:"normal",external_component_dbFontSize:14,external_component_dbFontFamily:'"Open Sans", sans-serif',external_component_dbFontWeight:"normal",component_queueFontSize:14,component_queueFontFamily:'"Open Sans", sans-serif',component_queueFontWeight:"normal",external_component_queueFontSize:14,external_component_queueFontFamily:'"Open Sans", sans-serif',external_component_queueFontWeight:"normal",wrap:!0,wrapPadding:10,personFont:function(){return{fontFamily:this.personFontFamily,fontSize:this.personFontSize,fontWeight:this.personFontWeight}},external_personFont:function(){return{fontFamily:this.external_personFontFamily,fontSize:this.external_personFontSize,fontWeight:this.external_personFontWeight}},systemFont:function(){return{fontFamily:this.systemFontFamily,fontSize:this.systemFontSize,fontWeight:this.systemFontWeight}},external_systemFont:function(){return{fontFamily:this.external_systemFontFamily,fontSize:this.external_systemFontSize,fontWeight:this.external_systemFontWeight}},system_dbFont:function(){return{fontFamily:this.system_dbFontFamily,fontSize:this.system_dbFontSize,fontWeight:this.system_dbFontWeight}},external_system_dbFont:function(){return{fontFamily:this.external_system_dbFontFamily,fontSize:this.external_system_dbFontSize,fontWeight:this.external_system_dbFontWeight}},system_queueFont:function(){return{fontFamily:this.system_queueFontFamily,fontSize:this.system_queueFontSize,fontWeight:this.system_queueFontWeight}},external_system_queueFont:function(){return{fontFamily:this.external_system_queueFontFamily,fontSize:this.external_system_queueFontSize,fontWeight:this.external_system_queueFontWeight}},containerFont:function(){return{fontFamily:this.containerFontFamily,fontSize:this.containerFontSize,fontWeight:this.containerFontWeight}},external_containerFont:function(){return{fontFamily:this.external_containerFontFamily,fontSize:this.external_containerFontSize,fontWeight:this.external_containerFontWeight}},container_dbFont:function(){return{fontFamily:this.container_dbFontFamily,fontSize:this.container_dbFontSize,fontWeight:this.container_dbFontWeight}},external_container_dbFont:function(){return{fontFamily:this.external_container_dbFontFamily,fontSize:this.external_container_dbFontSize,fontWeight:this.external_container_dbFontWeight}},container_queueFont:function(){return{fontFamily:this.container_queueFontFamily,fontSize:this.container_queueFontSize,fontWeight:this.container_queueFontWeight}},external_container_queueFont:function(){return{fontFamily:this.external_container_queueFontFamily,fontSize:this.external_container_queueFontSize,fontWeight:this.external_container_queueFontWeight}},componentFont:function(){return{fontFamily:this.componentFontFamily,fontSize:this.componentFontSize,fontWeight:this.componentFontWeight}},external_componentFont:function(){return{fontFamily:this.external_componentFontFamily,fontSize:this.external_componentFontSize,fontWeight:this.external_componentFontWeight}},component_dbFont:function(){return{fontFamily:this.component_dbFontFamily,fontSize:this.component_dbFontSize,fontWeight:this.component_dbFontWeight}},external_component_dbFont:function(){return{fontFamily:this.external_component_dbFontFamily,fontSize:this.external_component_dbFontSize,fontWeight:this.external_component_dbFontWeight}},component_queueFont:function(){return{fontFamily:this.component_queueFontFamily,fontSize:this.component_queueFontSize,fontWeight:this.component_queueFontWeight}},external_component_queueFont:function(){return{fontFamily:this.external_component_queueFontFamily,fontSize:this.external_component_queueFontSize,fontWeight:this.external_component_queueFontWeight}},boundaryFont:function(){return{fontFamily:this.boundaryFontFamily,fontSize:this.boundaryFontSize,fontWeight:this.boundaryFontWeight}},messageFont:function(){return{fontFamily:this.messageFontFamily,fontSize:this.messageFontSize,fontWeight:this.messageFontWeight}},person_bg_color:"#08427B",person_border_color:"#073B6F",external_person_bg_color:"#686868",external_person_border_color:"#8A8A8A",system_bg_color:"#1168BD",system_border_color:"#3C7FC0",system_db_bg_color:"#1168BD",system_db_border_color:"#3C7FC0",system_queue_bg_color:"#1168BD",system_queue_border_color:"#3C7FC0",external_system_bg_color:"#999999",external_system_border_color:"#8A8A8A",external_system_db_bg_color:"#999999",external_system_db_border_color:"#8A8A8A",external_system_queue_bg_color:"#999999",external_system_queue_border_color:"#8A8A8A",container_bg_color:"#438DD5",container_border_color:"#3C7FC0",container_db_bg_color:"#438DD5",container_db_border_color:"#3C7FC0",container_queue_bg_color:"#438DD5",container_queue_border_color:"#3C7FC0",external_container_bg_color:"#B3B3B3",external_container_border_color:"#A6A6A6",external_container_db_bg_color:"#B3B3B3",external_container_db_border_color:"#A6A6A6",external_container_queue_bg_color:"#B3B3B3",external_container_queue_border_color:"#A6A6A6",component_bg_color:"#85BBF0",component_border_color:"#78A8D8",component_db_bg_color:"#85BBF0",component_db_border_color:"#78A8D8",component_queue_bg_color:"#85BBF0",component_queue_border_color:"#78A8D8",external_component_bg_color:"#CCCCCC",external_component_border_color:"#BFBFBF",external_component_db_bg_color:"#CCCCCC",external_component_db_border_color:"#BFBFBF",external_component_queue_bg_color:"#CCCCCC",external_component_queue_border_color:"#BFBFBF"},mindmap:{useMaxWidth:!0,padding:10,maxNodeWidth:200},fontSize:16};Qk.class&&(Qk.class.arrowMarkerAbsolute=Qk.arrowMarkerAbsolute),Qk.gitGraph&&(Qk.gitGraph.arrowMarkerAbsolute=Qk.arrowMarkerAbsolute);const VDe=(i,a="")=>Object.keys(i).reduce((f,p)=>Array.isArray(i[p])?f:typeof i[p]=="object"&&i[p]!==null?[...f,a+p,...VDe(i[p],"")]:[...f,a+p],[]),m9t=VDe(Qk,""),y9t=Qk;/*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT */function UDe(i){return typeof i>"u"||i===null}function k9t(i){return typeof i=="object"&&i!==null}function x9t(i){return Array.isArray(i)?i:UDe(i)?[]:[i]}function E9t(i,a){var f,p,w,y;if(a)for(y=Object.keys(a),f=0,p=y.length;fE&&(y=" ... ",a=p-E+y.length),f-p>E&&(b=" ...",f=p+E-b.length),{str:y+i.slice(a,f).replace(/\t/g,"→")+b,pos:p-a+y.length}}function W1e(i,a){return sg.repeat(" ",a-i.length)+i}function I9t(i,a){if(a=Object.create(a||null),!i.buffer)return null;a.maxLength||(a.maxLength=79),typeof a.indent!="number"&&(a.indent=1),typeof a.linesBefore!="number"&&(a.linesBefore=3),typeof a.linesAfter!="number"&&(a.linesAfter=2);for(var f=/\r?\n|\r|\0/g,p=[0],w=[],y,b=-1;y=f.exec(i.buffer);)w.push(y.index),p.push(y.index+y[0].length),i.position<=y.index&&b<0&&(b=p.length-2);b<0&&(b=p.length-1);var E="",S,N,B=Math.min(i.line+a.linesAfter,w.length).toString().length,R=a.maxLength-(a.indent+B+3);for(S=1;S<=a.linesBefore&&!(b-S<0);S++)N=U1e(i.buffer,p[b-S],w[b-S],i.position-(p[b]-p[b-S]),R),E=sg.repeat(" ",a.indent)+W1e((i.line-S+1).toString(),B)+" | "+N.str+` +`+E;for(N=U1e(i.buffer,p[b],w[b],i.position,R),E+=sg.repeat(" ",a.indent)+W1e((i.line+1).toString(),B)+" | "+N.str+` +`,E+=sg.repeat("-",a.indent+B+3+N.pos)+`^ +`,S=1;S<=a.linesAfter&&!(b+S>=w.length);S++)N=U1e(i.buffer,p[b+S],w[b+S],i.position-(p[b]-p[b+S]),R),E+=sg.repeat(" ",a.indent)+W1e((i.line+S+1).toString(),B)+" | "+N.str+` +`;return E.replace(/\n$/,"")}var O9t=I9t,N9t=["kind","multi","resolve","construct","instanceOf","predicate","represent","representName","defaultStyle","styleAliases"],P9t=["scalar","sequence","mapping"];function B9t(i){var a={};return i!==null&&Object.keys(i).forEach(function(f){i[f].forEach(function(p){a[String(p)]=f})}),a}function R9t(i,a){if(a=a||{},Object.keys(a).forEach(function(f){if(N9t.indexOf(f)===-1)throw new p5('Unknown option "'+f+'" is met in definition of "'+i+'" YAML type.')}),this.options=a,this.tag=i,this.kind=a.kind||null,this.resolve=a.resolve||function(){return!0},this.construct=a.construct||function(f){return f},this.instanceOf=a.instanceOf||null,this.predicate=a.predicate||null,this.represent=a.represent||null,this.representName=a.representName||null,this.defaultStyle=a.defaultStyle||null,this.multi=a.multi||!1,this.styleAliases=B9t(a.styleAliases||null),P9t.indexOf(this.kind)===-1)throw new p5('Unknown kind "'+this.kind+'" is specified for "'+i+'" YAML type.')}var k0=R9t;function KDe(i,a){var f=[];return i[a].forEach(function(p){var w=f.length;f.forEach(function(y,b){y.tag===p.tag&&y.kind===p.kind&&y.multi===p.multi&&(w=b)}),f[w]=p}),f}function F9t(){var i={scalar:{},sequence:{},mapping:{},fallback:{},multi:{scalar:[],sequence:[],mapping:[],fallback:[]}},a,f;function p(w){w.multi?(i.multi[w.kind].push(w),i.multi.fallback.push(w)):i[w.kind][w.tag]=i.fallback[w.tag]=w}for(a=0,f=arguments.length;a=0?"0b"+i.toString(2):"-0b"+i.toString(2).slice(1)},octal:function(i){return i>=0?"0o"+i.toString(8):"-0o"+i.toString(8).slice(1)},decimal:function(i){return i.toString(10)},hexadecimal:function(i){return i>=0?"0x"+i.toString(16).toUpperCase():"-0x"+i.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}}),iTt=new RegExp("^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");function sTt(i){return!(i===null||!iTt.test(i)||i[i.length-1]==="_")}function aTt(i){var a,f;return a=i.replace(/_/g,"").toLowerCase(),f=a[0]==="-"?-1:1,"+-".indexOf(a[0])>=0&&(a=a.slice(1)),a===".inf"?f===1?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:a===".nan"?NaN:f*parseFloat(a,10)}var oTt=/^[-+]?[0-9]+e/;function cTt(i,a){var f;if(isNaN(i))switch(a){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===i)switch(a){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===i)switch(a){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(sg.isNegativeZero(i))return"-0.0";return f=i.toString(10),oTt.test(f)?f.replace("e",".e"):f}function uTt(i){return Object.prototype.toString.call(i)==="[object Number]"&&(i%1!==0||sg.isNegativeZero(i))}var lTt=new k0("tag:yaml.org,2002:float",{kind:"scalar",resolve:sTt,construct:aTt,predicate:uTt,represent:cTt,defaultStyle:"lowercase"}),hTt=YDe.extend({implicit:[U9t,X9t,rTt,lTt]}),fTt=hTt,XDe=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),QDe=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");function dTt(i){return i===null?!1:XDe.exec(i)!==null||QDe.exec(i)!==null}function gTt(i){var a,f,p,w,y,b,E,S=0,N=null,B,R,j;if(a=XDe.exec(i),a===null&&(a=QDe.exec(i)),a===null)throw new Error("Date resolve error");if(f=+a[1],p=+a[2]-1,w=+a[3],!a[4])return new Date(Date.UTC(f,p,w));if(y=+a[4],b=+a[5],E=+a[6],a[7]){for(S=a[7].slice(0,3);S.length<3;)S+="0";S=+S}return a[9]&&(B=+a[10],R=+(a[11]||0),N=(B*60+R)*6e4,a[9]==="-"&&(N=-N)),j=new Date(Date.UTC(f,p,w,y,b,E,S)),N&&j.setTime(j.getTime()-N),j}function pTt(i){return i.toISOString()}var bTt=new k0("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:dTt,construct:gTt,instanceOf:Date,represent:pTt});function vTt(i){return i==="<<"||i===null}var wTt=new k0("tag:yaml.org,2002:merge",{kind:"scalar",resolve:vTt}),Y1e=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/= +\r`;function mTt(i){if(i===null)return!1;var a,f,p=0,w=i.length,y=Y1e;for(f=0;f64)){if(a<0)return!1;p+=6}return p%8===0}function yTt(i){var a,f,p=i.replace(/[\r\n=]/g,""),w=p.length,y=Y1e,b=0,E=[];for(a=0;a>16&255),E.push(b>>8&255),E.push(b&255)),b=b<<6|y.indexOf(p.charAt(a));return f=w%4*6,f===0?(E.push(b>>16&255),E.push(b>>8&255),E.push(b&255)):f===18?(E.push(b>>10&255),E.push(b>>2&255)):f===12&&E.push(b>>4&255),new Uint8Array(E)}function kTt(i){var a="",f=0,p,w,y=i.length,b=Y1e;for(p=0;p>18&63],a+=b[f>>12&63],a+=b[f>>6&63],a+=b[f&63]),f=(f<<8)+i[p];return w=y%3,w===0?(a+=b[f>>18&63],a+=b[f>>12&63],a+=b[f>>6&63],a+=b[f&63]):w===2?(a+=b[f>>10&63],a+=b[f>>4&63],a+=b[f<<2&63],a+=b[64]):w===1&&(a+=b[f>>2&63],a+=b[f<<4&63],a+=b[64],a+=b[64]),a}function xTt(i){return Object.prototype.toString.call(i)==="[object Uint8Array]"}var ETt=new k0("tag:yaml.org,2002:binary",{kind:"scalar",resolve:mTt,construct:yTt,predicate:xTt,represent:kTt}),TTt=Object.prototype.hasOwnProperty,_Tt=Object.prototype.toString;function CTt(i){if(i===null)return!0;var a=[],f,p,w,y,b,E=i;for(f=0,p=E.length;f>10)+55296,(i-65536&1023)+56320)}for(var sIe=new Array(256),aIe=new Array(256),MA=0;MA<256;MA++)sIe[MA]=iIe(MA)?1:0,aIe[MA]=iIe(MA);function UTt(i,a){this.input=i,this.filename=a.filename||null,this.schema=a.schema||RTt,this.onWarning=a.onWarning||null,this.legacy=a.legacy||!1,this.json=a.json||!1,this.listener=a.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=i.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.firstTabInLine=-1,this.documents=[]}function oIe(i,a){var f={name:i.filename,buffer:i.input.slice(0,-1),position:i.position,line:i.line,column:i.position-i.lineStart};return f.snippet=O9t(f),new p5(a,f)}function Os(i,a){throw oIe(i,a)}function lW(i,a){i.onWarning&&i.onWarning.call(null,oIe(i,a))}var cIe={YAML:function(a,f,p){var w,y,b;a.version!==null&&Os(a,"duplication of %YAML directive"),p.length!==1&&Os(a,"YAML directive accepts exactly one argument"),w=/^([0-9]+)\.([0-9]+)$/.exec(p[0]),w===null&&Os(a,"ill-formed argument of the YAML directive"),y=parseInt(w[1],10),b=parseInt(w[2],10),y!==1&&Os(a,"unacceptable YAML version of the document"),a.version=p[0],a.checkLineBreaks=b<2,b!==1&&b!==2&&lW(a,"unsupported YAML version of the document")},TAG:function(a,f,p){var w,y;p.length!==2&&Os(a,"TAG directive accepts exactly two arguments"),w=p[0],y=p[1],tIe.test(w)||Os(a,"ill-formed tag handle (first argument) of the TAG directive"),Zk.call(a.tagMap,w)&&Os(a,'there is a previously declared suffix for "'+w+'" tag handle'),nIe.test(y)||Os(a,"ill-formed tag prefix (second argument) of the TAG directive");try{y=decodeURIComponent(y)}catch{Os(a,"tag prefix is malformed: "+y)}a.tagMap[w]=y}};function Jk(i,a,f,p){var w,y,b,E;if(a1&&(i.result+=sg.repeat(` +`,a-1))}function WTt(i,a,f){var p,w,y,b,E,S,N,B,R=i.kind,j=i.result,$;if($=i.input.charCodeAt(i.position),tp($)||LA($)||$===35||$===38||$===42||$===33||$===124||$===62||$===39||$===34||$===37||$===64||$===96||($===63||$===45)&&(w=i.input.charCodeAt(i.position+1),tp(w)||f&&LA(w)))return!1;for(i.kind="scalar",i.result="",y=b=i.position,E=!1;$!==0;){if($===58){if(w=i.input.charCodeAt(i.position+1),tp(w)||f&&LA(w))break}else if($===35){if(p=i.input.charCodeAt(i.position-1),tp(p))break}else{if(i.position===i.lineStart&&hW(i)||f&&LA($))break;if(i3($))if(S=i.line,N=i.lineStart,B=i.lineIndent,Ff(i,!1,-1),i.lineIndent>=a){E=!0,$=i.input.charCodeAt(i.position);continue}else{i.position=b,i.line=S,i.lineStart=N,i.lineIndent=B;break}}E&&(Jk(i,y,b,!1),Z1e(i,i.line-S),y=b=i.position,E=!1),KE($)||(b=i.position+1),$=i.input.charCodeAt(++i.position)}return Jk(i,y,b,!1),i.result?!0:(i.kind=R,i.result=j,!1)}function KTt(i,a){var f,p,w;if(f=i.input.charCodeAt(i.position),f!==39)return!1;for(i.kind="scalar",i.result="",i.position++,p=w=i.position;(f=i.input.charCodeAt(i.position))!==0;)if(f===39)if(Jk(i,p,i.position,!0),f=i.input.charCodeAt(++i.position),f===39)p=i.position,i.position++,w=i.position;else return!0;else i3(f)?(Jk(i,p,w,!0),Z1e(i,Ff(i,!1,a)),p=w=i.position):i.position===i.lineStart&&hW(i)?Os(i,"unexpected end of the document within a single quoted scalar"):(i.position++,w=i.position);Os(i,"unexpected end of the stream within a single quoted scalar")}function YTt(i,a){var f,p,w,y,b,E;if(E=i.input.charCodeAt(i.position),E!==34)return!1;for(i.kind="scalar",i.result="",i.position++,f=p=i.position;(E=i.input.charCodeAt(i.position))!==0;){if(E===34)return Jk(i,f,i.position,!0),i.position++,!0;if(E===92){if(Jk(i,f,i.position,!0),E=i.input.charCodeAt(++i.position),i3(E))Ff(i,!1,a);else if(E<256&&sIe[E])i.result+=aIe[E],i.position++;else if((b=GTt(E))>0){for(w=b,y=0;w>0;w--)E=i.input.charCodeAt(++i.position),(b=zTt(E))>=0?y=(y<<4)+b:Os(i,"expected hexadecimal character");i.result+=VTt(y),i.position++}else Os(i,"unknown escape sequence");f=p=i.position}else i3(E)?(Jk(i,f,p,!0),Z1e(i,Ff(i,!1,a)),f=p=i.position):i.position===i.lineStart&&hW(i)?Os(i,"unexpected end of the document within a double quoted scalar"):(i.position++,p=i.position)}Os(i,"unexpected end of the stream within a double quoted scalar")}function XTt(i,a){var f=!0,p,w,y,b=i.tag,E,S=i.anchor,N,B,R,j,$,V=Object.create(null),Q,oe,ce,se;if(se=i.input.charCodeAt(i.position),se===91)B=93,$=!1,E=[];else if(se===123)B=125,$=!0,E={};else return!1;for(i.anchor!==null&&(i.anchorMap[i.anchor]=E),se=i.input.charCodeAt(++i.position);se!==0;){if(Ff(i,!0,a),se=i.input.charCodeAt(i.position),se===B)return i.position++,i.tag=b,i.anchor=S,i.kind=$?"mapping":"sequence",i.result=E,!0;f?se===44&&Os(i,"expected the node content, but found ','"):Os(i,"missed comma between flow collection entries"),oe=Q=ce=null,R=j=!1,se===63&&(N=i.input.charCodeAt(i.position+1),tp(N)&&(R=j=!0,i.position++,Ff(i,!0,a))),p=i.line,w=i.lineStart,y=i.position,IA(i,a,cW,!1,!0),oe=i.tag,Q=i.result,Ff(i,!0,a),se=i.input.charCodeAt(i.position),(j||i.line===p)&&se===58&&(R=!0,se=i.input.charCodeAt(++i.position),Ff(i,!0,a),IA(i,a,cW,!1,!0),ce=i.result),$?DA(i,E,V,oe,Q,ce,p,w,y):R?E.push(DA(i,null,V,oe,Q,ce,p,w,y)):E.push(Q),Ff(i,!0,a),se=i.input.charCodeAt(i.position),se===44?(f=!0,se=i.input.charCodeAt(++i.position)):f=!1}Os(i,"unexpected end of the stream within a flow collection")}function QTt(i,a){var f,p,w=X1e,y=!1,b=!1,E=a,S=0,N=!1,B,R;if(R=i.input.charCodeAt(i.position),R===124)p=!1;else if(R===62)p=!0;else return!1;for(i.kind="scalar",i.result="";R!==0;)if(R=i.input.charCodeAt(++i.position),R===43||R===45)X1e===w?w=R===43?eIe:FTt:Os(i,"repeat of a chomping mode identifier");else if((B=qTt(R))>=0)B===0?Os(i,"bad explicit indentation width of a block scalar; it cannot be less than one"):b?Os(i,"repeat of an indentation width identifier"):(E=a+B-1,b=!0);else break;if(KE(R)){do R=i.input.charCodeAt(++i.position);while(KE(R));if(R===35)do R=i.input.charCodeAt(++i.position);while(!i3(R)&&R!==0)}for(;R!==0;){for(Q1e(i),i.lineIndent=0,R=i.input.charCodeAt(i.position);(!b||i.lineIndentE&&(E=i.lineIndent),i3(R)){S++;continue}if(i.lineIndenta)&&S!==0)Os(i,"bad indentation of a sequence entry");else if(i.lineIndenta)&&(oe&&(b=i.line,E=i.lineStart,S=i.position),IA(i,a,uW,!0,w)&&(oe?V=i.result:Q=i.result),oe||(DA(i,R,j,$,V,Q,b,E,S),$=V=Q=null),Ff(i,!0,-1),se=i.input.charCodeAt(i.position)),(i.line===y||i.lineIndent>a)&&se!==0)Os(i,"bad indentation of a mapping entry");else if(i.lineIndenta?S=1:i.lineIndent===a?S=0:i.lineIndenta?S=1:i.lineIndent===a?S=0:i.lineIndent tag; it should be "scalar", not "'+i.kind+'"'),R=0,j=i.implicitTypes.length;R"),i.result!==null&&V.kind!==i.kind&&Os(i,"unacceptable node kind for !<"+i.tag+'> tag; it should be "'+V.kind+'", not "'+i.kind+'"'),V.resolve(i.result,i.tag)?(i.result=V.construct(i.result,i.tag),i.anchor!==null&&(i.anchorMap[i.anchor]=i.result)):Os(i,"cannot resolve a node with !<"+i.tag+"> explicit tag")}return i.listener!==null&&i.listener("close",i),i.tag!==null||i.anchor!==null||B}function n_t(i){var a=i.position,f,p,w,y=!1,b;for(i.version=null,i.checkLineBreaks=i.legacy,i.tagMap=Object.create(null),i.anchorMap=Object.create(null);(b=i.input.charCodeAt(i.position))!==0&&(Ff(i,!0,-1),b=i.input.charCodeAt(i.position),!(i.lineIndent>0||b!==37));){for(y=!0,b=i.input.charCodeAt(++i.position),f=i.position;b!==0&&!tp(b);)b=i.input.charCodeAt(++i.position);for(p=i.input.slice(f,i.position),w=[],p.length<1&&Os(i,"directive name must not be less than one character in length");b!==0;){for(;KE(b);)b=i.input.charCodeAt(++i.position);if(b===35){do b=i.input.charCodeAt(++i.position);while(b!==0&&!i3(b));break}if(i3(b))break;for(f=i.position;b!==0&&!tp(b);)b=i.input.charCodeAt(++i.position);w.push(i.input.slice(f,i.position))}b!==0&&Q1e(i),Zk.call(cIe,p)?cIe[p](i,p,w):lW(i,'unknown document directive "'+p+'"')}if(Ff(i,!0,-1),i.lineIndent===0&&i.input.charCodeAt(i.position)===45&&i.input.charCodeAt(i.position+1)===45&&i.input.charCodeAt(i.position+2)===45?(i.position+=3,Ff(i,!0,-1)):y&&Os(i,"directives end mark is expected"),IA(i,i.lineIndent-1,uW,!1,!0),Ff(i,!0,-1),i.checkLineBreaks&&$Tt.test(i.input.slice(a,i.position))&&lW(i,"non-ASCII line breaks are interpreted as content"),i.documents.push(i.result),i.position===i.lineStart&&hW(i)){i.input.charCodeAt(i.position)===46&&(i.position+=3,Ff(i,!0,-1));return}if(i.position"u"&&(f=a,a=null);var p=hIe(i,f);if(typeof a!="function")return p;for(var w=0,y=p.length;wJ1e(i,y,f)),i):Array.isArray(a)&&Array.isArray(i)?(a.forEach(y=>{i.includes(y)||i.push(y)}),i):i===void 0||p<=0?i!=null&&typeof i=="object"&&typeof a=="object"?Object.assign(i,a):a:(a!==void 0&&typeof i=="object"&&typeof a=="object"&&Object.keys(a).forEach(y=>{typeof a[y]=="object"&&(i[y]===void 0||typeof i[y]=="object")?(i[y]===void 0&&(i[y]=Array.isArray(a[y])?[]:{}),i[y]=J1e(i[y],a[y],{depth:p-1,clobber:w})):(w||typeof i[y]!="object"&&typeof a[y]!="object")&&(i[y]=a[y])}),i)},nd=J1e,OA=Object.freeze(y9t);let np=nd({},OA),dIe,NA=[],zN=nd({},OA);const fW=(i,a)=>{let f=nd({},i),p={};for(const w of a)bIe(w),p=nd(p,w);if(f=nd(f,p),p.theme&&p.theme in g5){const w=nd({},dIe),y=nd(w.themeVariables||{},p.themeVariables);f.theme&&f.theme in g5&&(f.themeVariables=g5[f.theme].getThemeVariables(y))}return zN=f,yIe(zN),zN},h_t=i=>(np=nd({},OA),np=nd(np,i),i.theme&&g5[i.theme]&&(np.themeVariables=g5[i.theme].getThemeVariables(i.themeVariables)),fW(np,NA),np),f_t=i=>{dIe=nd({},i)},d_t=i=>(np=nd(np,i),fW(np,NA),np),gIe=()=>nd({},np),pIe=i=>(yIe(i),nd(zN,i),Tt()),Tt=()=>nd({},zN),bIe=i=>{["secure",...np.secure??[]].forEach(a=>{i[a]!==void 0&&(Fe.debug(`Denied attempt to modify a secure key ${a}`,i[a]),delete i[a])}),Object.keys(i).forEach(a=>{a.indexOf("__")===0&&delete i[a]}),Object.keys(i).forEach(a=>{typeof i[a]=="string"&&(i[a].includes("<")||i[a].includes(">")||i[a].includes("url(data:"))&&delete i[a],typeof i[a]=="object"&&bIe(i[a])})},vIe=i=>{i.fontFamily&&(i.themeVariables?i.themeVariables.fontFamily||(i.themeVariables={fontFamily:i.fontFamily}):i.themeVariables={fontFamily:i.fontFamily}),NA.push(i),fW(np,NA)},dW=(i=np)=>{NA=[],fW(i,NA)};var wIe=(i=>(i.LAZY_LOAD_DEPRECATED="The configuration options lazyLoadedDiagrams and loadExternalDiagramsAtStartup are deprecated. Please use registerExternalDiagrams instead.",i))(wIe||{});const mIe={},g_t=i=>{mIe[i]||(Fe.warn(wIe[i]),mIe[i]=!0)},yIe=i=>{i&&(i.lazyLoadedDiagrams||i.loadExternalDiagramsAtStartup)&&g_t("LAZY_LOAD_DEPRECATED")},p_t=function(i,a){for(let f of a)i.attr(f[0],f[1])},b_t=function(i,a,f){let p=new Map;return f?(p.set("width","100%"),p.set("style",`max-width: ${a}px;`)):(p.set("height",i),p.set("width",a)),p},Vw=function(i,a,f,p){const w=b_t(a,f,p);p_t(i,w)},YE=function(i,a,f,p){const w=a.node().getBBox(),y=w.width,b=w.height;Fe.info(`SVG bounds: ${y}x${b}`,w);let E=0,S=0;Fe.info(`Graph bounds: ${E}x${S}`,i),E=y+f*2,S=b+f*2,Fe.info(`Calculated bounds: ${E}x${S}`),Vw(a,S,E,p);const N=`${w.x-f} ${w.y-f} ${w.width+2*f} ${w.height+2*f}`;a.attr("viewBox",N)},gW={},v_t=(i,a,f)=>{let p="";return i in gW&&gW[i]?p=gW[i](f):Fe.warn(`No theme found for ${i}`),` & { + font-family: ${f.fontFamily}; + font-size: ${f.fontSize}; + fill: ${f.textColor} + } + + /* Classes common for multiple diagrams */ + + & .error-icon { + fill: ${f.errorBkgColor}; + } + & .error-text { + fill: ${f.errorTextColor}; + stroke: ${f.errorTextColor}; + } + + & .edge-thickness-normal { + stroke-width: 2px; + } + & .edge-thickness-thick { + stroke-width: 3.5px + } + & .edge-pattern-solid { + stroke-dasharray: 0; + } + + & .edge-pattern-dashed{ + stroke-dasharray: 3; + } + .edge-pattern-dotted { + stroke-dasharray: 2; + } + + & .marker { + fill: ${f.lineColor}; + stroke: ${f.lineColor}; + } + & .marker.cross { + stroke: ${f.lineColor}; + } + + & svg { + font-family: ${f.fontFamily}; + font-size: ${f.fontSize}; + } + + ${p} + + ${a} +`},w_t=(i,a)=>{gW[i]=a},m_t=v_t;let ede="",pW="",tde="";const nde=i=>ep(i,Tt()),rp=function(){ede="",tde="",pW=""},ip=function(i){ede=nde(i).replace(/^\s+/g,"")},L2=function(){return ede||pW},M2=function(i){tde=nde(i).replace(/\n\s+/g,` +`)},D2=function(){return tde},Uw=function(i){pW=nde(i)},Ww=function(){return pW},kIe=Object.freeze(Object.defineProperty({__proto__:null,clear:rp,default:{getAccTitle:L2,setAccTitle:ip,getDiagramTitle:Ww,setDiagramTitle:Uw,getAccDescription:D2,setAccDescription:M2,clear:rp},getAccDescription:D2,getAccTitle:L2,getDiagramTitle:Ww,setAccDescription:M2,setAccTitle:ip,setDiagramTitle:Uw},Symbol.toStringTag,{value:"Module"}));let XE={};const rde=function(i,a,f,p){Fe.debug("parseDirective is being called",a,f,p);try{if(a!==void 0)switch(a=a.trim(),f){case"open_directive":XE={};break;case"type_directive":if(!XE)throw new Error("currentDirective is undefined");XE.type=a.toLowerCase();break;case"arg_directive":if(!XE)throw new Error("currentDirective is undefined");XE.args=JSON.parse(a);break;case"close_directive":y_t(i,XE,p),XE=void 0;break}}catch(w){Fe.error(`Error while rendering sequenceDiagram directive: ${a} jison context: ${f}`),Fe.error(w.message)}},y_t=function(i,a,f){switch(Fe.info(`Directive type=${a.type} with args:`,a.args),a.type){case"init":case"initialize":{["config"].forEach(p=>{a.args[p]!==void 0&&(f==="flowchart-v2"&&(f="flowchart"),a.args[f]=a.args[p],delete a.args[p])}),Fe.info("sanitize in handleDirective",a.args),jA(a.args),Fe.info("sanitize in handleDirective (done)",a.args),vIe(a.args);break}case"wrap":case"nowrap":i&&i.setWrap&&i.setWrap(a.type==="wrap");break;case"themeCss":Fe.warn("themeCss encountered");break;default:Fe.warn(`Unhandled directive: source: '%%{${a.type}: ${JSON.stringify(a.args?a.args:{})}}%%`,a);break}},k_t=Fe,x_t=$fe,GN=Tt,E_t=i=>ep(i,GN()),xIe=YE,T_t=()=>kIe,__t=(i,a,f,p)=>rde(i,a,f,p),bW={},vW=(i,a,f)=>{if(bW[i])throw new Error(`Diagram ${i} already registered.`);bW[i]=a,f&&_Ie(i,f),w_t(i,a.styles),a.injectUtils&&a.injectUtils(k_t,x_t,GN,E_t,xIe,T_t(),__t)},ide=i=>{if(i in bW)return bW[i];throw new Error(`Diagram ${i} not found.`)};class EIe extends Error{constructor(a){super(a),this.name="UnknownDiagramError"}}const C_t=/%{2}{\s*(?:(\w+)\s*:|(\w+))\s*(?:(\w+)|((?:(?!}%{2}).|\r?\n)*))?\s*(?:}%{2})?/gi,S_t=/\s*%%.*\n/gm,PA={},wW=function(i,a){i=i.replace(fIe,"").replace(C_t,"").replace(S_t,` +`);for(const[f,{detector:p}]of Object.entries(PA))if(p(i,a))return f;throw new EIe(`No diagram type detected matching given configuration for text: ${i}`)},TIe=(...i)=>{for(const{id:a,detector:f,loader:p}of i)_Ie(a,f,p)},A_t=async()=>{Fe.debug("Loading registered diagrams");const a=(await Promise.allSettled(Object.entries(PA).map(async([f,{detector:p,loader:w}])=>{if(w)try{ide(f)}catch{try{const{diagram:b,id:E}=await w();vW(E,b,p)}catch(b){throw Fe.error(`Failed to load external diagram with key ${f}. Removing from detectors.`),delete PA[f],b}}}))).filter(f=>f.status==="rejected");if(a.length>0){Fe.error(`Failed to load ${a.length} external diagrams`);for(const f of a)Fe.error(f);throw new Error(`Failed to load ${a.length} external diagrams`)}},_Ie=(i,a,f)=>{PA[i]?Fe.error(`Detector with key ${i} already exists`):PA[i]={detector:a,loader:f},Fe.debug(`Detector with key ${i} added${f?" with loader":""}`)},L_t=i=>PA[i].loader;var M_t=typeof global=="object"&&global&&global.Object===Object&&global;const CIe=M_t;var D_t=typeof self=="object"&&self&&self.Object===Object&&self,I_t=CIe||D_t||Function("return this")();const Kw=I_t;var O_t=Kw.Symbol;const Vb=O_t;var SIe=Object.prototype,N_t=SIe.hasOwnProperty,P_t=SIe.toString,qN=Vb?Vb.toStringTag:void 0;function B_t(i){var a=N_t.call(i,qN),f=i[qN];try{i[qN]=void 0;var p=!0}catch{}var w=P_t.call(i);return p&&(a?i[qN]=f:delete i[qN]),w}var R_t=Object.prototype,F_t=R_t.toString;function j_t(i){return F_t.call(i)}var $_t="[object Null]",H_t="[object Undefined]",AIe=Vb?Vb.toStringTag:void 0;function QE(i){return i==null?i===void 0?H_t:$_t:AIe&&AIe in Object(i)?B_t(i):j_t(i)}function I2(i){var a=typeof i;return i!=null&&(a=="object"||a=="function")}var z_t="[object AsyncFunction]",G_t="[object Function]",q_t="[object GeneratorFunction]",V_t="[object Proxy]";function BA(i){if(!I2(i))return!1;var a=QE(i);return a==G_t||a==q_t||a==z_t||a==V_t}var U_t=Kw["__core-js_shared__"];const sde=U_t;var LIe=function(){var i=/[^.]+$/.exec(sde&&sde.keys&&sde.keys.IE_PROTO||"");return i?"Symbol(src)_1."+i:""}();function W_t(i){return!!LIe&&LIe in i}var K_t=Function.prototype,Y_t=K_t.toString;function ZE(i){if(i!=null){try{return Y_t.call(i)}catch{}try{return i+""}catch{}}return""}var X_t=/[\\^$.*+?()[\]{}|]/g,Q_t=/^\[object .+?Constructor\]$/,Z_t=Function.prototype,J_t=Object.prototype,eCt=Z_t.toString,tCt=J_t.hasOwnProperty,nCt=RegExp("^"+eCt.call(tCt).replace(X_t,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function rCt(i){if(!I2(i)||W_t(i))return!1;var a=BA(i)?nCt:Q_t;return a.test(ZE(i))}function iCt(i,a){return i==null?void 0:i[a]}function JE(i,a){var f=iCt(i,a);return rCt(f)?f:void 0}var sCt=JE(Object,"create");const VN=sCt;function aCt(){this.__data__=VN?VN(null):{},this.size=0}function oCt(i){var a=this.has(i)&&delete this.__data__[i];return this.size-=a?1:0,a}var cCt="__lodash_hash_undefined__",uCt=Object.prototype,lCt=uCt.hasOwnProperty;function hCt(i){var a=this.__data__;if(VN){var f=a[i];return f===cCt?void 0:f}return lCt.call(a,i)?a[i]:void 0}var fCt=Object.prototype,dCt=fCt.hasOwnProperty;function gCt(i){var a=this.__data__;return VN?a[i]!==void 0:dCt.call(a,i)}var pCt="__lodash_hash_undefined__";function bCt(i,a){var f=this.__data__;return this.size+=this.has(i)?0:1,f[i]=VN&&a===void 0?pCt:a,this}function e9(i){var a=-1,f=i==null?0:i.length;for(this.clear();++a-1}function ECt(i,a){var f=this.__data__,p=mW(f,i);return p<0?(++this.size,f.push([i,a])):f[p][1]=a,this}function b5(i){var a=-1,f=i==null?0:i.length;for(this.clear();++ay.args);jA(w),p=nd(p,[...w])}else p=f.args;if(p){let w=wW(i,a);["config"].forEach(y=>{p[y]!==void 0&&(w==="flowchart-v2"&&(w="flowchart"),p[w]=p[y],delete p[y])})}return p},MIe=function(i,a=null){try{const f=new RegExp(`[%]{2}(?![{]${OCt.source})(?=[}][%]{2}).* +`,"ig");i=i.trim().replace(f,"").replace(/'/gm,'"'),Fe.debug(`Detecting diagram directive${a!==null?" type:"+a:""} based on the text:${i}`);let p;const w=[];for(;(p=ade.exec(i))!==null;)if(p.index===ade.lastIndex&&ade.lastIndex++,p&&!a||a&&p[1]&&p[1].match(a)||a&&p[2]&&p[2].match(a)){const y=p[1]?p[1]:p[2],b=p[3]?p[3].trim():p[4]?JSON.parse(p[4].trim()):null;w.push({type:y,args:b})}return w.length===0&&w.push({type:i,args:null}),w.length===1?w[0]:w}catch(f){return Fe.error(`ERROR: ${f.message} - Unable to parse directive + ${a!==null?" type:"+a:""} based on the text:${i}`),{type:null,args:null}}},PCt=function(i,a){for(const[f,p]of a.entries())if(p.match(i))return f;return-1};function Ub(i,a){if(!i)return a;const f=`curve${i.charAt(0).toUpperCase()+i.slice(1)}`;return ICt[f]||a}function BCt(i,a){const f=i.trim();if(f)return a.securityLevel!=="loose"?u5(f):f}const RCt=(i,...a)=>{const f=i.split("."),p=f.length-1,w=f[p];let y=window;for(let b=0;b{f+=kW(y,a),a=y});let p=f/2,w;return a=void 0,i.forEach(y=>{if(a&&!w){const b=kW(y,a);if(b=1&&(w={x:y.x,y:y.y}),E>0&&E<1&&(w={x:(1-E)*a.x+E*y.x,y:(1-E)*a.y+E*y.y})}}a=y}),w}function jCt(i){return i.length===1?i[0]:FCt(i)}const $Ct=(i,a,f)=>{let p;Fe.info(`our points ${JSON.stringify(a)}`),a[0]!==f&&(a=a.reverse());let y=25,b;p=void 0,a.forEach(B=>{if(p&&!b){const R=kW(B,p);if(R=1&&(b={x:B.x,y:B.y}),j>0&&j<1&&(b={x:(1-j)*p.x+j*B.x,y:(1-j)*p.y+j*B.y})}}p=B});const E=i?10:5,S=Math.atan2(a[0].y-b.y,a[0].x-b.x),N={x:0,y:0};return N.x=Math.sin(S)*E+(a[0].x+b.x)/2,N.y=-Math.cos(S)*E+(a[0].y+b.y)/2,N};function HCt(i,a,f){let p=JSON.parse(JSON.stringify(f)),w;Fe.info("our points",p),a!=="start_left"&&a!=="start_right"&&(p=p.reverse()),p.forEach(R=>{w=R});let b=25+i,E;w=void 0,p.forEach(R=>{if(w&&!E){const j=kW(R,w);if(j=1&&(E={x:R.x,y:R.y}),$>0&&$<1&&(E={x:(1-$)*w.x+$*R.x,y:(1-$)*w.y+$*R.y})}}w=R});const S=10+i*.5,N=Math.atan2(p[0].y-E.y,p[0].x-E.x),B={x:0,y:0};return B.x=Math.sin(N)*S+(p[0].x+E.x)/2,B.y=-Math.cos(N)*S+(p[0].y+E.y)/2,a==="start_left"&&(B.x=Math.sin(N+Math.PI)*S+(p[0].x+E.x)/2,B.y=-Math.cos(N+Math.PI)*S+(p[0].y+E.y)/2),a==="end_right"&&(B.x=Math.sin(N-Math.PI)*S+(p[0].x+E.x)/2-5,B.y=-Math.cos(N-Math.PI)*S+(p[0].y+E.y)/2-5),a==="end_left"&&(B.x=Math.sin(N)*S+(p[0].x+E.x)/2-5,B.y=-Math.cos(N)*S+(p[0].y+E.y)/2-5),B}function Yw(i){let a="",f="";for(const p of i)p!==void 0&&(p.startsWith("color:")||p.startsWith("text-align:")?f=f+p+";":a=a+p+";");return{style:a,labelStyle:f}}let DIe=0;const IIe=()=>(DIe++,"id-"+Math.random().toString(36).substr(2,12)+"-"+DIe);function zCt(i){let a="";const f="0123456789abcdef",p=f.length;for(let w=0;wzCt(i.length),GCt=function(){return{x:0,y:0,fill:void 0,anchor:"start",style:"#666",width:100,height:100,textMargin:0,rx:0,ry:0,valign:void 0}},qCt=function(i,a){const f=a.text.replace(Wa.lineBreakRegex," "),[,p]=$A(a.fontSize),w=i.append("text");w.attr("x",a.x),w.attr("y",a.y),w.style("text-anchor",a.anchor),w.style("font-family",a.fontFamily),w.style("font-size",p),w.style("font-weight",a.fontWeight),w.attr("fill",a.fill),a.class!==void 0&&w.attr("class",a.class);const y=w.append("tspan");return y.attr("x",a.x+a.textMargin*2),y.attr("fill",a.fill),y.text(f),w},NIe=FA((i,a,f)=>{if(!i||(f=Object.assign({fontSize:12,fontWeight:400,fontFamily:"Arial",joinWith:"
"},f),Wa.lineBreakRegex.test(i)))return i;const p=i.split(" "),w=[];let y="";return p.forEach((b,E)=>{const S=s3(`${b} `,f),N=s3(y,f);if(S>a){const{hyphenatedStrings:j,remainingWord:$}=VCt(b,a,"-",f);w.push(y,...j),y=$}else N+S>=a?(w.push(y),y=b):y=[y,b].filter(Boolean).join(" ");E+1===p.length&&w.push(y)}),w.filter(b=>b!=="").join(f.joinWith)},(i,a,f)=>`${i}${a}${f.fontSize}${f.fontWeight}${f.fontFamily}${f.joinWith}`),VCt=FA((i,a,f="-",p)=>{p=Object.assign({fontSize:12,fontWeight:400,fontFamily:"Arial",margin:0},p);const w=[...i],y=[];let b="";return w.forEach((E,S)=>{const N=`${b}${E}`;if(s3(N,p)>=a){const R=S+1,j=w.length===R,$=`${N}${f}`;y.push(j?N:$),b=""}else b=N}),{hyphenatedStrings:y,remainingWord:b}},(i,a,f="-",p)=>`${i}${a}${f}${p.fontSize}${p.fontWeight}${p.fontFamily}`);function ode(i,a){return a=Object.assign({fontSize:12,fontWeight:400,fontFamily:"Arial",margin:15},a),cde(i,a).height}function s3(i,a){return a=Object.assign({fontSize:12,fontWeight:400,fontFamily:"Arial"},a),cde(i,a).width}const cde=FA((i,a)=>{a=Object.assign({fontSize:12,fontWeight:400,fontFamily:"Arial"},a);const{fontSize:f,fontFamily:p,fontWeight:w}=a;if(!i)return{width:0,height:0};const[,y]=$A(f),b=["sans-serif",p],E=i.split(Wa.lineBreakRegex),S=[],N=Cr("body");if(!N.remove)return{width:0,height:0,lineHeight:0};const B=N.append("svg");for(const j of b){let $=0;const V={width:0,height:0,lineHeight:0};for(const Q of E){const oe=GCt();oe.text=Q;const ce=qCt(B,oe).style("font-size",y).style("font-weight",w).style("font-family",j),se=(ce._groups||ce)[0][0].getBBox();if(se.width===0&&se.height===0)throw new Error("svg element not in render tree");V.width=Math.round(Math.max(V.width,se.width)),$=Math.round(se.height),V.height+=$,V.lineHeight=Math.round(Math.max(V.lineHeight,$))}S.push(V)}B.remove();const R=isNaN(S[1].height)||isNaN(S[1].width)||isNaN(S[1].lineHeight)||S[0].height>S[1].height&&S[0].width>S[1].width&&S[0].lineHeight>S[1].lineHeight?0:1;return S[R]},(i,a)=>`${i}${a.fontSize}${a.fontWeight}${a.fontFamily}`),UCt=class{constructor(a,f){this.deterministic=a,this.seed=f,this.count=f?f.length:0}next(){return this.deterministic?this.count++:Date.now()}};let xW;const WCt=function(i){return xW=xW||document.createElement("div"),i=escape(i).replace(/%26/g,"&").replace(/%23/g,"#").replace(/%3B/g,";"),xW.innerHTML=i,unescape(xW.textContent)},jA=i=>{if(Fe.debug("directiveSanitizer called with",i),typeof i=="object"&&(i.length?i.forEach(a=>jA(a)):Object.keys(i).forEach(a=>{Fe.debug("Checking key",a),a.startsWith("__")&&(Fe.debug("sanitize deleting __ option",a),delete i[a]),a.includes("proto")&&(Fe.debug("sanitize deleting proto option",a),delete i[a]),a.includes("constr")&&(Fe.debug("sanitize deleting constr option",a),delete i[a]),a.includes("themeCSS")&&(Fe.debug("sanitizing themeCss option"),i[a]=EW(i[a])),a.includes("fontFamily")&&(Fe.debug("sanitizing fontFamily option"),i[a]=EW(i[a])),a.includes("altFontFamily")&&(Fe.debug("sanitizing altFontFamily option"),i[a]=EW(i[a])),m9t.includes(a)?typeof i[a]=="object"&&(Fe.debug("sanitize deleting object",a),jA(i[a])):(Fe.debug("sanitize deleting option",a),delete i[a])})),i.themeVariables){const a=Object.keys(i.themeVariables);for(const f of a){const p=i.themeVariables[f];p&&p.match&&!p.match(/^[\d "#%(),.;A-Za-z]+$/)&&(i.themeVariables[f]="")}}Fe.debug("After sanitization",i)},EW=i=>{let a=0,f=0;for(const p of i){if(a{if(!p)return;const w=i.node().getBBox();i.append("text").text(p).attr("x",w.x+w.width/2).attr("y",-f).attr("class",a)},$A=i=>{if(typeof i=="number")return[i,i+"px"];const a=parseInt(i,10);return Number.isNaN(a)?[void 0,void 0]:i===String(a)?[a,i+"px"]:[a,i]},co={assignWithDepth:nd,wrapLabel:NIe,calculateTextHeight:ode,calculateTextWidth:s3,calculateTextDimensions:cde,detectInit:NCt,detectDirective:MIe,isSubstringInArray:PCt,interpolateToCurve:Ub,calcLabelPosition:jCt,calcCardinalityPosition:$Ct,calcTerminalLabelPosition:HCt,formatUrl:BCt,getStylesFromArray:Yw,generateId:IIe,random:OIe,runFunc:RCt,entityDecode:WCt,initIdGenerator:UCt,directiveSanitizer:jA,sanitizeCss:EW,insertTitle:YCt,parseFontSize:$A};var BIe="comm",RIe="rule",FIe="decl",XCt="@import",QCt="@keyframes",ZCt=Math.abs,ude=String.fromCharCode;function jIe(i){return i.trim()}function lde(i,a,f){return i.replace(a,f)}function JCt(i,a){return i.indexOf(a)}function WN(i,a){return i.charCodeAt(a)|0}function KN(i,a,f){return i.slice(a,f)}function ex(i){return i.length}function $Ie(i){return i.length}function TW(i,a){return a.push(i),i}var _W=1,HA=1,HIe=0,Wb=0,jf=0,zA="";function hde(i,a,f,p,w,y,b){return{value:i,root:a,parent:f,type:p,props:w,children:y,line:_W,column:HA,length:b,return:""}}function eSt(){return jf}function tSt(){return jf=Wb>0?WN(zA,--Wb):0,HA--,jf===10&&(HA=1,_W--),jf}function Xw(){return jf=Wb2||fde(jf)>3?"":" "}function sSt(i,a){for(;--a&&Xw()&&!(jf<48||jf>102||jf>57&&jf<65||jf>70&&jf<97););return SW(i,CW()+(a<6&&t9()==32&&Xw()==32))}function gde(i){for(;Xw();)switch(jf){case i:return Wb;case 34:case 39:i!==34&&i!==39&&gde(jf);break;case 40:i===41&&gde(i);break;case 92:Xw();break}return Wb}function aSt(i,a){for(;Xw()&&i+jf!==47+10;)if(i+jf===42+42&&t9()===47)break;return"/*"+SW(a,Wb-1)+"*"+ude(i===47?i:Xw())}function oSt(i){for(;!fde(t9());)Xw();return SW(i,Wb)}function cSt(i){return rSt(AW("",null,null,null,[""],i=nSt(i),0,[0],i))}function AW(i,a,f,p,w,y,b,E,S){for(var N=0,B=0,R=b,j=0,$=0,V=0,Q=1,oe=1,ce=1,se=0,ge="",ye=w,ke=y,Ae=p,de=ge;oe;)switch(V=se,se=Xw()){case 40:if(V!=108&&WN(de,R-1)==58){JCt(de+=lde(dde(se),"&","&\f"),"&\f")!=-1&&(ce=-1);break}case 34:case 39:case 91:de+=dde(se);break;case 9:case 10:case 13:case 32:de+=iSt(V);break;case 92:de+=sSt(CW()-1,7);continue;case 47:switch(t9()){case 42:case 47:TW(uSt(aSt(Xw(),CW()),a,f),S);break;default:de+="/"}break;case 123*Q:E[N++]=ex(de)*ce;case 125*Q:case 59:case 0:switch(se){case 0:case 125:oe=0;case 59+B:$>0&&ex(de)-R&&TW($>32?GIe(de+";",p,f,R-1):GIe(lde(de," ","")+";",p,f,R-2),S);break;case 59:de+=";";default:if(TW(Ae=zIe(de,a,f,N,B,w,E,ge,ye=[],ke=[],R),y),se===123)if(B===0)AW(de,a,Ae,Ae,ye,y,R,E,ke);else switch(j===99&&WN(de,3)===110?100:j){case 100:case 109:case 115:AW(i,Ae,Ae,p&&TW(zIe(i,Ae,Ae,0,0,w,E,ge,w,ye=[],R),ke),w,ke,R,E,p?ye:ke);break;default:AW(de,Ae,Ae,Ae,[""],ke,0,E,ke)}}N=B=$=0,Q=ce=1,ge=de="",R=b;break;case 58:R=1+ex(de),$=V;default:if(Q<1){if(se==123)--Q;else if(se==125&&Q++==0&&tSt()==125)continue}switch(de+=ude(se),se*Q){case 38:ce=B>0?1:(de+="\f",-1);break;case 44:E[N++]=(ex(de)-1)*ce,ce=1;break;case 64:t9()===45&&(de+=dde(Xw())),j=t9(),B=R=ex(ge=de+=oSt(CW())),se++;break;case 45:V===45&&ex(de)==2&&(Q=0)}}return y}function zIe(i,a,f,p,w,y,b,E,S,N,B){for(var R=w-1,j=w===0?y:[""],$=$Ie(j),V=0,Q=0,oe=0;V0?j[ce]+" "+se:lde(se,/&\f/g,j[ce])))&&(S[oe++]=ge);return hde(i,a,f,w===0?RIe:E,S,N,B)}function uSt(i,a,f){return hde(i,a,f,BIe,ude(eSt()),KN(i,2,-2),0)}function GIe(i,a,f,p){return hde(i,a,f,FIe,KN(i,0,p),KN(i,p+1,-1),p)}function pde(i,a){for(var f="",p=$Ie(i),w=0;wi.match(/^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/)!==null,loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>rMt);return{id:VIe,diagram:i}}},UIe="flowchart",fSt={id:UIe,detector:(i,a)=>{var f,p;return((f=a==null?void 0:a.flowchart)==null?void 0:f.defaultRenderer)==="dagre-wrapper"||((p=a==null?void 0:a.flowchart)==null?void 0:p.defaultRenderer)==="elk"?!1:i.match(/^\s*graph/)!==null},loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>kFt);return{id:UIe,diagram:i}}},WIe="flowchart-v2",dSt={id:WIe,detector:(i,a)=>{var f,p,w;return((f=a==null?void 0:a.flowchart)==null?void 0:f.defaultRenderer)==="dagre-d3"||((p=a==null?void 0:a.flowchart)==null?void 0:p.defaultRenderer)==="elk"?!1:i.match(/^\s*graph/)!==null&&((w=a==null?void 0:a.flowchart)==null?void 0:w.defaultRenderer)==="dagre-wrapper"?!0:i.match(/^\s*flowchart/)!==null},loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>xFt);return{id:WIe,diagram:i}}},KIe="er",gSt={id:KIe,detector:i=>i.match(/^\s*erDiagram/)!==null,loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>YFt);return{id:KIe,diagram:i}}},YIe="gitGraph",pSt={id:YIe,detector:i=>i.match(/^\s*gitGraph/)!==null,loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>xjt);return{id:YIe,diagram:i}}},XIe="gantt",bSt={id:XIe,detector:i=>i.match(/^\s*gantt/)!==null,loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>x$t);return{id:XIe,diagram:i}}},QIe="info",vSt={id:QIe,detector:i=>i.match(/^\s*info/)!==null,loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>T$t);return{id:QIe,diagram:i}}},ZIe="pie",wSt={id:ZIe,detector:i=>i.match(/^\s*pie/)!==null,loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>A$t);return{id:ZIe,diagram:i}}},JIe="requirement",mSt={id:JIe,detector:i=>i.match(/^\s*requirement(Diagram)?/)!==null,loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>F$t);return{id:JIe,diagram:i}}},eOe="sequence",ySt={id:eOe,detector:i=>i.match(/^\s*sequenceDiagram/)!==null,loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>$Ht);return{id:eOe,diagram:i}}},tOe="class",kSt={id:tOe,detector:(i,a)=>{var f;return((f=a==null?void 0:a.class)==null?void 0:f.defaultRenderer)==="dagre-wrapper"?!1:i.match(/^\s*classDiagram/)!==null},loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>czt);return{id:tOe,diagram:i}}},nOe="classDiagram",xSt={id:nOe,detector:(i,a)=>{var f;return i.match(/^\s*classDiagram/)!==null&&((f=a==null?void 0:a.class)==null?void 0:f.defaultRenderer)==="dagre-wrapper"?!0:i.match(/^\s*classDiagram-v2/)!==null},loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>gzt);return{id:nOe,diagram:i}}},rOe="state",ESt={id:rOe,detector:(i,a)=>{var f;return((f=a==null?void 0:a.state)==null?void 0:f.defaultRenderer)==="dagre-wrapper"?!1:i.match(/^\s*stateDiagram/)!==null},loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>nGt);return{id:rOe,diagram:i}}},iOe="stateDiagram",TSt={id:iOe,detector:(i,a)=>{var f,p;return!!(i.match(/^\s*stateDiagram-v2/)!==null||i.match(/^\s*stateDiagram/)&&((f=a==null?void 0:a.state)==null?void 0:f.defaultRenderer)==="dagre-wrapper"||i.match(/^\s*stateDiagram/)&&((p=a==null?void 0:a.state)==null?void 0:p.defaultRenderer)==="dagre-wrapper")},loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>kGt);return{id:iOe,diagram:i}}},sOe="journey",_St={id:sOe,detector:i=>i.match(/^\s*journey/)!==null,loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>zGt);return{id:sOe,diagram:i}}},CSt=()=>"",aOe={setConf:function(){},draw:(i,a,f)=>{try{Fe.debug(`Renering svg for syntax error +`);const p=Cr("#"+a),w=p.append("g");w.append("path").attr("class","error-icon").attr("d","m411.313,123.313c6.25-6.25 6.25-16.375 0-22.625s-16.375-6.25-22.625,0l-32,32-9.375,9.375-20.688-20.688c-12.484-12.5-32.766-12.5-45.25,0l-16,16c-1.261,1.261-2.304,2.648-3.31,4.051-21.739-8.561-45.324-13.426-70.065-13.426-105.867,0-192,86.133-192,192s86.133,192 192,192 192-86.133 192-192c0-24.741-4.864-48.327-13.426-70.065 1.402-1.007 2.79-2.049 4.051-3.31l16-16c12.5-12.492 12.5-32.758 0-45.25l-20.688-20.688 9.375-9.375 32.001-31.999zm-219.313,100.687c-52.938,0-96,43.063-96,96 0,8.836-7.164,16-16,16s-16-7.164-16-16c0-70.578 57.422-128 128-128 8.836,0 16,7.164 16,16s-7.164,16-16,16z"),w.append("path").attr("class","error-icon").attr("d","m459.02,148.98c-6.25-6.25-16.375-6.25-22.625,0s-6.25,16.375 0,22.625l16,16c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688 6.25-6.25 6.25-16.375 0-22.625l-16.001-16z"),w.append("path").attr("class","error-icon").attr("d","m340.395,75.605c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688 6.25-6.25 6.25-16.375 0-22.625l-16-16c-6.25-6.25-16.375-6.25-22.625,0s-6.25,16.375 0,22.625l15.999,16z"),w.append("path").attr("class","error-icon").attr("d","m400,64c8.844,0 16-7.164 16-16v-32c0-8.836-7.156-16-16-16-8.844,0-16,7.164-16,16v32c0,8.836 7.156,16 16,16z"),w.append("path").attr("class","error-icon").attr("d","m496,96.586h-32c-8.844,0-16,7.164-16,16 0,8.836 7.156,16 16,16h32c8.844,0 16-7.164 16-16 0-8.836-7.156-16-16-16z"),w.append("path").attr("class","error-icon").attr("d","m436.98,75.605c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688l32-32c6.25-6.25 6.25-16.375 0-22.625s-16.375-6.25-22.625,0l-32,32c-6.251,6.25-6.251,16.375-0.001,22.625z"),w.append("text").attr("class","error-text").attr("x",1440).attr("y",250).attr("font-size","150px").style("text-anchor","middle").text("Syntax error in text"),w.append("text").attr("class","error-text").attr("x",1250).attr("y",400).attr("font-size","100px").style("text-anchor","middle").text("mermaid version "+f),p.attr("height",100),p.attr("width",500),p.attr("viewBox","768 0 912 512")}catch(p){Fe.error("Error while rendering info diagram"),Fe.error(KCt(p))}}},SSt={db:{clear:()=>{}},styles:CSt,renderer:aOe,parser:{parser:{yy:{}},parse:()=>{}},init:()=>{}},oOe="flowchart-elk",ASt={id:oOe,detector:(i,a)=>{var f;return!!(i.match(/^\s*flowchart-elk/)||i.match(/^\s*flowchart|graph/)&&((f=a==null?void 0:a.flowchart)==null?void 0:f.defaultRenderer)==="elk")},loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>iqt);return{id:oOe,diagram:i}}},cOe="timeline",LSt={id:cOe,detector:i=>i.match(/^\s*timeline/)!==null,loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>Eqt);return{id:cOe,diagram:i}}},uOe="mindmap",MSt={id:uOe,detector:i=>i.match(/^\s*mindmap/)!==null,loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>tVt);return{id:uOe,diagram:i}}};let lOe=!1;const bde=()=>{lOe||(lOe=!0,vW("error",SSt,i=>i.toLowerCase().trim()==="error"),vW("---",{db:{clear:()=>{}},styles:{},renderer:{},parser:{parser:{yy:{}},parse:()=>{throw new Error("Diagrams beginning with --- are not valid. If you were trying to use a YAML front-matter, please ensure that you've correctly opened and closed the YAML front-matter with un-indented `---` blocks")}},init:()=>null},i=>i.toLowerCase().trimStart().startsWith("---")),TIe(hSt,xSt,kSt,gSt,bSt,vSt,wSt,mSt,ySt,ASt,dSt,fSt,MSt,LSt,pSt,TSt,ESt,_St))},DSt=i=>i.trimStart().replace(/^\s*%%(?!{)[^\n]+\n?/gm,"");class hOe{constructor(a){var y,b;this.text=a,this.type="graph",this.text+=` +`;const f=Tt();try{this.type=wW(a,f)}catch(E){this.type="error",this.detectError=E}const p=ide(this.type);Fe.debug("Type "+this.type),this.db=p.db,(b=(y=this.db).clear)==null||b.call(y),this.renderer=p.renderer,this.parser=p.parser;const w=this.parser.parse.bind(this.parser);this.parser.parse=E=>w(DSt(l_t(E,this.db))),this.parser.parser.yy=this.db,p.init&&(p.init(f),Fe.info("Initialized diagram "+this.type,f)),this.parse()}parse(){var a,f;if(this.detectError)throw this.detectError;(f=(a=this.db).clear)==null||f.call(a),this.parser.parse(this.text)}async render(a,f){await this.renderer.draw(this.text,a,f,this)}getParser(){return this.parser}getType(){return this.type}}const vde=async i=>{const a=wW(i,Tt());try{ide(a)}catch{const p=L_t(a);if(!p)throw new EIe(`Diagram ${a} not found.`);const{id:w,diagram:y}=await p();vW(w,y)}return new hOe(i)};let wde=[];const ISt=i=>{wde.push(i)},OSt=()=>{wde.forEach(i=>{i()}),wde=[]};var NSt=Object.prototype;function LW(i){var a=i&&i.constructor,f=typeof a=="function"&&a.prototype||NSt;return i===f}function fOe(i,a){return function(f){return i(a(f))}}var PSt=fOe(Object.keys,Object);const BSt=PSt;var RSt=Object.prototype,FSt=RSt.hasOwnProperty;function dOe(i){if(!LW(i))return BSt(i);var a=[];for(var f in Object(i))FSt.call(i,f)&&f!="constructor"&&a.push(f);return a}var jSt=JE(Kw,"DataView");const mde=jSt;var $St=JE(Kw,"Promise");const yde=$St;var HSt=JE(Kw,"Set");const GA=HSt;var zSt=JE(Kw,"WeakMap");const kde=zSt;var gOe="[object Map]",GSt="[object Object]",pOe="[object Promise]",bOe="[object Set]",vOe="[object WeakMap]",wOe="[object DataView]",qSt=ZE(mde),VSt=ZE(UN),USt=ZE(yde),WSt=ZE(GA),KSt=ZE(kde),n9=QE;(mde&&n9(new mde(new ArrayBuffer(1)))!=wOe||UN&&n9(new UN)!=gOe||yde&&n9(yde.resolve())!=pOe||GA&&n9(new GA)!=bOe||kde&&n9(new kde)!=vOe)&&(n9=function(i){var a=QE(i),f=a==GSt?i.constructor:void 0,p=f?ZE(f):"";if(p)switch(p){case qSt:return wOe;case VSt:return gOe;case USt:return pOe;case WSt:return bOe;case KSt:return vOe}return a});const qA=n9;function a3(i){return i!=null&&typeof i=="object"}var YSt="[object Arguments]";function mOe(i){return a3(i)&&QE(i)==YSt}var yOe=Object.prototype,XSt=yOe.hasOwnProperty,QSt=yOe.propertyIsEnumerable,ZSt=mOe(function(){return arguments}())?mOe:function(i){return a3(i)&&XSt.call(i,"callee")&&!QSt.call(i,"callee")};const VA=ZSt;var JSt=Array.isArray;const $f=JSt;var eAt=9007199254740991;function xde(i){return typeof i=="number"&&i>-1&&i%1==0&&i<=eAt}function tx(i){return i!=null&&xde(i.length)&&!BA(i)}function tAt(){return!1}var kOe=typeof exports=="object"&&exports&&!exports.nodeType&&exports,xOe=kOe&&typeof module=="object"&&module&&!module.nodeType&&module,nAt=xOe&&xOe.exports===kOe,EOe=nAt?Kw.Buffer:void 0,rAt=EOe?EOe.isBuffer:void 0,iAt=rAt||tAt;const UA=iAt;var sAt="[object Arguments]",aAt="[object Array]",oAt="[object Boolean]",cAt="[object Date]",uAt="[object Error]",lAt="[object Function]",hAt="[object Map]",fAt="[object Number]",dAt="[object Object]",gAt="[object RegExp]",pAt="[object Set]",bAt="[object String]",vAt="[object WeakMap]",wAt="[object ArrayBuffer]",mAt="[object DataView]",yAt="[object Float32Array]",kAt="[object Float64Array]",xAt="[object Int8Array]",EAt="[object Int16Array]",TAt="[object Int32Array]",_At="[object Uint8Array]",CAt="[object Uint8ClampedArray]",SAt="[object Uint16Array]",AAt="[object Uint32Array]",Tl={};Tl[yAt]=Tl[kAt]=Tl[xAt]=Tl[EAt]=Tl[TAt]=Tl[_At]=Tl[CAt]=Tl[SAt]=Tl[AAt]=!0,Tl[sAt]=Tl[aAt]=Tl[wAt]=Tl[oAt]=Tl[mAt]=Tl[cAt]=Tl[uAt]=Tl[lAt]=Tl[hAt]=Tl[fAt]=Tl[dAt]=Tl[gAt]=Tl[pAt]=Tl[bAt]=Tl[vAt]=!1;function LAt(i){return a3(i)&&xde(i.length)&&!!Tl[QE(i)]}function MW(i){return function(a){return i(a)}}var TOe=typeof exports=="object"&&exports&&!exports.nodeType&&exports,YN=TOe&&typeof module=="object"&&module&&!module.nodeType&&module,MAt=YN&&YN.exports===TOe,Ede=MAt&&CIe.process,DAt=function(){try{var i=YN&&YN.require&&YN.require("util").types;return i||Ede&&Ede.binding&&Ede.binding("util")}catch{}}();const WA=DAt;var _Oe=WA&&WA.isTypedArray,IAt=_Oe?MW(_Oe):LAt;const DW=IAt;var OAt="[object Map]",NAt="[object Set]",PAt=Object.prototype,BAt=PAt.hasOwnProperty;function KA(i){if(i==null)return!0;if(tx(i)&&($f(i)||typeof i=="string"||typeof i.splice=="function"||UA(i)||DW(i)||VA(i)))return!i.length;var a=qA(i);if(a==OAt||a==NAt)return!i.size;if(LW(i))return!dOe(i).length;for(var f in i)if(BAt.call(i,f))return!1;return!0}const RAt="graphics-document document";function FAt(i,a){i.attr("role",RAt),KA(a)||i.attr("aria-roledescription",a)}function jAt(i,a,f,p){if(i.insert!==void 0)if(a||f){if(f){const w="chart-desc-"+p;i.attr("aria-describedby",w),i.insert("desc",":first-child").attr("id",w).text(f)}if(a){const w="chart-title-"+p;i.attr("aria-labelledby",w),i.insert("title",":first-child").attr("id",w).text(a)}}else return}const COe=["graph","flowchart","flowchart-v2","flowchart-elk","stateDiagram","stateDiagram-v2"],$At=5e4,HAt="graph TB;a[Maximum text size in diagram exceeded];style a fill:#faa",zAt="sandbox",GAt="loose",qAt="http://www.w3.org/2000/svg",VAt="http://www.w3.org/1999/xlink",UAt="http://www.w3.org/1999/xhtml",WAt="100%",KAt="100%",YAt="border:0;margin:0;",XAt="margin:0",QAt="allow-top-navigation-by-user-activation allow-popups",ZAt='The "iframe" tag is not supported by your browser.',JAt=["foreignobject"],eLt=["dominant-baseline"];async function tLt(i,a){bde();try{(await vde(i)).parse()}catch(f){if(a!=null&&a.suppressErrors)return!1;throw f}return!0}const nLt=function(i){let a=i;return a=a.replace(/style.*:\S*#.*;/g,function(f){return f.substring(0,f.length-1)}),a=a.replace(/classDef.*:\S*#.*;/g,function(f){return f.substring(0,f.length-1)}),a=a.replace(/#\w+;/g,function(f){const p=f.substring(1,f.length-1);return/^\+?\d+$/.test(p)?"fl°°"+p+"¶ß":"fl°"+p+"¶ß"}),a},XN=function(i){let a=i;return a=a.replace(/fl°°/g,"&#"),a=a.replace(/fl°/g,"&"),a=a.replace(/¶ß/g,";"),a},SOe=(i,a,f=[])=>` +.${i} ${a} { ${f.join(" !important; ")} !important; }`,rLt=(i,a,f={})=>{var w;let p="";if(i.themeCSS!==void 0&&(p+=` +${i.themeCSS}`),i.fontFamily!==void 0&&(p+=` +:root { --mermaid-font-family: ${i.fontFamily}}`),i.altFontFamily!==void 0&&(p+=` +:root { --mermaid-alt-font-family: ${i.altFontFamily}}`),!KA(f)&&COe.includes(a)){const S=i.htmlLabels||((w=i.flowchart)==null?void 0:w.htmlLabels)?["> *","span"]:["rect","polygon","ellipse","circle","path"];for(const N in f){const B=f[N];KA(B.styles)||S.forEach(R=>{p+=SOe(B.id,R,B.styles)}),KA(B.textStyles)||(p+=SOe(B.id,"tspan",B.textStyles))}}return p},iLt=(i,a,f,p)=>{const w=rLt(i,a,f),y=m_t(a,w,i.themeVariables);return pde(cSt(`${p}{${y}}`),lSt)},sLt=(i="",a,f)=>{let p=i;return!f&&!a&&(p=p.replace(/marker-end="url\(.*?#/g,'marker-end="url(#')),p=XN(p),p=p.replace(/
/g,"
"),p},aLt=(i="",a)=>{const f=a?a.viewBox.baseVal.height+"px":KAt,p=btoa(''+i+"");return``},AOe=(i,a,f,p,w)=>{const y=i.append("div");y.attr("id",f),p&&y.attr("style",p);const b=y.append("svg").attr("id",a).attr("width","100%").attr("xmlns",qAt);return w&&b.attr("xmlns:xlink",w),b.append("g"),i};function LOe(i,a){return i.append("iframe").attr("id",a).attr("style","width: 100%; height: 100%;").attr("sandbox","")}const oLt=(i,a,f,p)=>{var w,y,b;(w=i.getElementById(a))==null||w.remove(),(y=i.getElementById(f))==null||y.remove(),(b=i.getElementById(p))==null||b.remove()},cLt=async function(i,a,f){var Ie,ee,rt,me;bde(),dW();const p=co.detectInit(a);p&&(jA(p),vIe(p));const w=Tt();Fe.debug(w),a.length>((w==null?void 0:w.maxTextSize)??$At)&&(a=HAt),a=a.replace(/\r\n?/g,` +`),a=a.replace(/<(\w+)([^>]*)>/g,(gt,pe,Et)=>"<"+pe+Et.replace(/="([^"]*)"/g,"='$1'")+">");const y="#"+i,b="i"+i,E="#"+b,S="d"+i,N="#"+S;let B=Cr("body");const R=w.securityLevel===zAt,j=w.securityLevel===GAt,$=w.fontFamily;if(f!==void 0){if(f&&(f.innerHTML=""),R){const gt=LOe(Cr(f),b);B=Cr(gt.nodes()[0].contentDocument.body),B.node().style.margin=0}else B=Cr(f);AOe(B,i,S,`font-family: ${$}`,VAt)}else{if(oLt(document,i,S,b),R){const gt=LOe(Cr("body"),b);B=Cr(gt.nodes()[0].contentDocument.body),B.node().style.margin=0}else B=Cr("body");AOe(B,i,S)}a=nLt(a);let V,Q;try{V=await vde(a)}catch(gt){V=new hOe("error"),Q=gt}const oe=B.select(N).node(),ce=V.type,se=oe.firstChild,ge=se.firstChild,ye=COe.includes(ce)?V.renderer.getClasses(a,V):{},ke=iLt(w,ce,ye,y),Ae=document.createElement("style");Ae.innerHTML=ke,se.insertBefore(Ae,ge);try{await V.renderer.draw(a,i,qIe,V)}catch(gt){throw aOe.draw(a,i,qIe),gt}const de=B.select(`${N} svg`),ve=(ee=(Ie=V.db).getAccTitle)==null?void 0:ee.call(Ie),te=(me=(rt=V.db).getAccDescription)==null?void 0:me.call(rt);lLt(ce,de,ve,te),B.select(`[id="${i}"]`).selectAll("foreignobject > *").attr("xmlns",UAt);let xe=B.select(N).node().innerHTML;if(Fe.debug("config.arrowMarkerAbsolute",w.arrowMarkerAbsolute),xe=sLt(xe,R,d1(w.arrowMarkerAbsolute)),R){const gt=B.select(N+" svg").node();xe=aLt(xe,gt)}else j||(xe=ZU.sanitize(xe,{ADD_TAGS:JAt,ADD_ATTR:eLt}));if(OSt(),Q)throw Q;const he=Cr(R?E:N).node();return he&&"remove"in he&&he.remove(),{svg:xe,bindFunctions:V.db.bindFunctions}};function uLt(i={}){var f;i!=null&&i.fontFamily&&!((f=i.themeVariables)!=null&&f.fontFamily)&&(i.themeVariables||(i.themeVariables={}),i.themeVariables.fontFamily=i.fontFamily),f_t(i),i!=null&&i.theme&&i.theme in g5?i.themeVariables=g5[i.theme].getThemeVariables(i.themeVariables):i&&(i.themeVariables=g5.default.getThemeVariables(i.themeVariables));const a=typeof i=="object"?h_t(i):gIe();$fe(a.logLevel),bde()}function lLt(i,a,f,p){FAt(a,i),jAt(a,f,p,a.attr("id"))}const rd=Object.freeze({render:cLt,parse:tLt,parseDirective:rde,getDiagramFromText:vde,initialize:uLt,getConfig:Tt,setConfig:pIe,getSiteConfig:gIe,updateSiteConfig:d_t,reset:()=>{dW()},globalReset:()=>{dW(OA)},defaultConfig:OA});$fe(Tt().logLevel),dW(Tt());const hLt=(i,a,f)=>{Fe.warn(i),PIe(i)?(f&&f(i.str,i.hash),a.push({...i,message:i.str,error:i})):(f&&f(i),i instanceof Error&&a.push({str:i.message,message:i.message,hash:i.name,error:i}))},MOe=async function(i={querySelector:".mermaid"}){try{await fLt(i)}catch(a){if(PIe(a)&&Fe.error(a.str),O2.parseError&&O2.parseError(a),!i.suppressErrors)throw Fe.error("Use the suppressErrors option to suppress these errors"),a}},fLt=async function({postRenderCallback:i,querySelector:a,nodes:f}={querySelector:".mermaid"}){const p=rd.getConfig();Fe.debug(`${i?"":"No "}Callback function found`);let w;if(f)w=f;else if(a)w=document.querySelectorAll(a);else throw new Error("Nodes and querySelector are both undefined");Fe.debug(`Found ${w.length} diagrams`),(p==null?void 0:p.startOnLoad)!==void 0&&(Fe.debug("Start On Load: "+(p==null?void 0:p.startOnLoad)),rd.updateSiteConfig({startOnLoad:p==null?void 0:p.startOnLoad}));const y=new co.initIdGenerator(p.deterministicIds,p.deterministicIDSeed);let b;const E=[];for(const S of Array.from(w)){Fe.info("Rendering diagram: "+S.id);/*! Check if previously processed */if(S.getAttribute("data-processed"))continue;S.setAttribute("data-processed","true");const N=`mermaid-${y.next()}`;b=S.innerHTML,b=mN(co.entityDecode(b)).trim().replace(//gi,"
");const B=co.detectInit(b);B&&Fe.debug("Detected early reinit: ",B);try{const{svg:R,bindFunctions:j}=await NOe(N,b,S);S.innerHTML=R,i&&await i(N),j&&j(S)}catch(R){hLt(R,E,O2.parseError)}}if(E.length>0)throw E[0]},DOe=function(i){rd.initialize(i)},dLt=async function(i,a,f){Fe.warn("mermaid.init is deprecated. Please use run instead."),i&&DOe(i);const p={postRenderCallback:f,querySelector:".mermaid"};typeof a=="string"?p.querySelector=a:a&&(a instanceof HTMLElement?p.nodes=[a]:p.nodes=a),await MOe(p)},gLt=async(i,{lazyLoad:a=!0}={})=>{TIe(...i),a===!1&&await A_t()},IOe=function(){if(O2.startOnLoad){const{startOnLoad:i}=rd.getConfig();i&&O2.run().catch(a=>Fe.error("Mermaid failed to initialize",a))}};if(typeof document<"u"){/*! + * Wait for document loaded before starting the execution + */window.addEventListener("load",IOe,!1)}const pLt=function(i){O2.parseError=i},IW=[];let Tde=!1;const OOe=async()=>{if(!Tde){for(Tde=!0;IW.length>0;){const i=IW.shift();if(i)try{await i()}catch(a){Fe.error("Error executing queue",a)}}Tde=!1}},bLt=async(i,a)=>new Promise((f,p)=>{const w=()=>new Promise((y,b)=>{rd.parse(i,a).then(E=>{y(E),f(E)},E=>{var S;Fe.error("Error parsing",E),(S=O2.parseError)==null||S.call(O2,E),b(E),p(E)})});IW.push(w),OOe().catch(p)}),NOe=(i,a,f)=>new Promise((p,w)=>{const y=()=>new Promise((b,E)=>{rd.render(i,a,f).then(S=>{b(S),p(S)},S=>{var N;Fe.error("Error parsing",S),(N=O2.parseError)==null||N.call(O2,S),E(S),w(S)})});IW.push(y),OOe().catch(w)}),O2={startOnLoad:!0,mermaidAPI:rd,parse:bLt,render:NOe,init:dLt,run:MOe,registerExternalDiagrams:gLt,initialize:DOe,parseError:void 0,contentLoaded:IOe,setParseErrorHandler:pLt,detectType:wW};var OW=function(){var i=function(Oi,Er,br,Dr){for(br=br||{},Dr=Oi.length;Dr--;br[Oi[Dr]]=Er);return br},a=[1,6],f=[1,7],p=[1,8],w=[1,9],y=[1,16],b=[1,11],E=[1,12],S=[1,13],N=[1,14],B=[1,15],R=[1,27],j=[1,33],$=[1,34],V=[1,35],Q=[1,36],oe=[1,37],ce=[1,72],se=[1,73],ge=[1,74],ye=[1,75],ke=[1,76],Ae=[1,77],de=[1,78],ve=[1,38],te=[1,39],xe=[1,40],De=[1,41],he=[1,42],Ie=[1,43],ee=[1,44],rt=[1,45],me=[1,46],gt=[1,47],pe=[1,48],Et=[1,49],wt=[1,50],jt=[1,51],At=[1,52],Bt=[1,53],cn=[1,54],Nn=[1,55],Ot=[1,56],oi=[1,57],kt=[1,59],Dt=[1,60],vt=[1,61],Nt=[1,62],ze=[1,63],Xe=[1,64],Lt=[1,65],Ge=[1,66],Bn=[1,67],Oe=[1,68],Ri=[1,69],tn=[24,52],hi=[24,44,46,47,48,49,50,51,52,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84],Sr=[15,24,44,46,47,48,49,50,51,52,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84],Zn=[1,94],Xn=[1,95],ir=[1,96],Hn=[1,97],tr=[15,24,52],ha=[7,8,9,10,18,22,25,26,27,28],Zs=[15,24,43,52],ns=[15,24,43,52,86,87,89,90],Hi=[15,43],Js=[44,46,47,48,49,50,51,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84],Pc={trace:function(){},yy:{},symbols_:{error:2,start:3,mermaidDoc:4,direction:5,directive:6,direction_tb:7,direction_bt:8,direction_rl:9,direction_lr:10,graphConfig:11,openDirective:12,typeDirective:13,closeDirective:14,NEWLINE:15,":":16,argDirective:17,open_directive:18,type_directive:19,arg_directive:20,close_directive:21,C4_CONTEXT:22,statements:23,EOF:24,C4_CONTAINER:25,C4_COMPONENT:26,C4_DYNAMIC:27,C4_DEPLOYMENT:28,otherStatements:29,diagramStatements:30,otherStatement:31,title:32,accDescription:33,acc_title:34,acc_title_value:35,acc_descr:36,acc_descr_value:37,acc_descr_multiline_value:38,boundaryStatement:39,boundaryStartStatement:40,boundaryStopStatement:41,boundaryStart:42,LBRACE:43,ENTERPRISE_BOUNDARY:44,attributes:45,SYSTEM_BOUNDARY:46,BOUNDARY:47,CONTAINER_BOUNDARY:48,NODE:49,NODE_L:50,NODE_R:51,RBRACE:52,diagramStatement:53,PERSON:54,PERSON_EXT:55,SYSTEM:56,SYSTEM_DB:57,SYSTEM_QUEUE:58,SYSTEM_EXT:59,SYSTEM_EXT_DB:60,SYSTEM_EXT_QUEUE:61,CONTAINER:62,CONTAINER_DB:63,CONTAINER_QUEUE:64,CONTAINER_EXT:65,CONTAINER_EXT_DB:66,CONTAINER_EXT_QUEUE:67,COMPONENT:68,COMPONENT_DB:69,COMPONENT_QUEUE:70,COMPONENT_EXT:71,COMPONENT_EXT_DB:72,COMPONENT_EXT_QUEUE:73,REL:74,BIREL:75,REL_U:76,REL_D:77,REL_L:78,REL_R:79,REL_B:80,REL_INDEX:81,UPDATE_EL_STYLE:82,UPDATE_REL_STYLE:83,UPDATE_LAYOUT_CONFIG:84,attribute:85,STR:86,STR_KEY:87,STR_VALUE:88,ATTRIBUTE:89,ATTRIBUTE_EMPTY:90,$accept:0,$end:1},terminals_:{2:"error",7:"direction_tb",8:"direction_bt",9:"direction_rl",10:"direction_lr",15:"NEWLINE",16:":",18:"open_directive",19:"type_directive",20:"arg_directive",21:"close_directive",22:"C4_CONTEXT",24:"EOF",25:"C4_CONTAINER",26:"C4_COMPONENT",27:"C4_DYNAMIC",28:"C4_DEPLOYMENT",32:"title",33:"accDescription",34:"acc_title",35:"acc_title_value",36:"acc_descr",37:"acc_descr_value",38:"acc_descr_multiline_value",43:"LBRACE",44:"ENTERPRISE_BOUNDARY",46:"SYSTEM_BOUNDARY",47:"BOUNDARY",48:"CONTAINER_BOUNDARY",49:"NODE",50:"NODE_L",51:"NODE_R",52:"RBRACE",54:"PERSON",55:"PERSON_EXT",56:"SYSTEM",57:"SYSTEM_DB",58:"SYSTEM_QUEUE",59:"SYSTEM_EXT",60:"SYSTEM_EXT_DB",61:"SYSTEM_EXT_QUEUE",62:"CONTAINER",63:"CONTAINER_DB",64:"CONTAINER_QUEUE",65:"CONTAINER_EXT",66:"CONTAINER_EXT_DB",67:"CONTAINER_EXT_QUEUE",68:"COMPONENT",69:"COMPONENT_DB",70:"COMPONENT_QUEUE",71:"COMPONENT_EXT",72:"COMPONENT_EXT_DB",73:"COMPONENT_EXT_QUEUE",74:"REL",75:"BIREL",76:"REL_U",77:"REL_D",78:"REL_L",79:"REL_R",80:"REL_B",81:"REL_INDEX",82:"UPDATE_EL_STYLE",83:"UPDATE_REL_STYLE",84:"UPDATE_LAYOUT_CONFIG",86:"STR",87:"STR_KEY",88:"STR_VALUE",89:"ATTRIBUTE",90:"ATTRIBUTE_EMPTY"},productions_:[0,[3,1],[3,1],[3,2],[5,1],[5,1],[5,1],[5,1],[4,1],[6,4],[6,6],[12,1],[13,1],[17,1],[14,1],[11,4],[11,4],[11,4],[11,4],[11,4],[23,1],[23,1],[23,2],[29,1],[29,2],[29,3],[31,1],[31,1],[31,2],[31,2],[31,1],[39,3],[40,3],[40,3],[40,4],[42,2],[42,2],[42,2],[42,2],[42,2],[42,2],[42,2],[41,1],[30,1],[30,2],[30,3],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[53,1],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[53,2],[45,1],[45,2],[85,1],[85,2],[85,1],[85,1]],performAction:function(Er,br,Dr,Vn,qi,yn,Bc){var jn=yn.length-1;switch(qi){case 4:Vn.setDirection("TB");break;case 5:Vn.setDirection("BT");break;case 6:Vn.setDirection("RL");break;case 7:Vn.setDirection("LR");break;case 11:Vn.parseDirective("%%{","open_directive");break;case 12:break;case 13:yn[jn]=yn[jn].trim().replace(/'/g,'"'),Vn.parseDirective(yn[jn],"arg_directive");break;case 14:Vn.parseDirective("}%%","close_directive","c4Context");break;case 15:case 16:case 17:case 18:case 19:Vn.setC4Type(yn[jn-3]);break;case 26:Vn.setTitle(yn[jn].substring(6)),this.$=yn[jn].substring(6);break;case 27:Vn.setAccDescription(yn[jn].substring(15)),this.$=yn[jn].substring(15);break;case 28:this.$=yn[jn].trim(),Vn.setTitle(this.$);break;case 29:case 30:this.$=yn[jn].trim(),Vn.setAccDescription(this.$);break;case 35:case 36:yn[jn].splice(2,0,"ENTERPRISE"),Vn.addPersonOrSystemBoundary(...yn[jn]),this.$=yn[jn];break;case 37:Vn.addPersonOrSystemBoundary(...yn[jn]),this.$=yn[jn];break;case 38:yn[jn].splice(2,0,"CONTAINER"),Vn.addContainerBoundary(...yn[jn]),this.$=yn[jn];break;case 39:Vn.addDeploymentNode("node",...yn[jn]),this.$=yn[jn];break;case 40:Vn.addDeploymentNode("nodeL",...yn[jn]),this.$=yn[jn];break;case 41:Vn.addDeploymentNode("nodeR",...yn[jn]),this.$=yn[jn];break;case 42:Vn.popBoundaryParseStack();break;case 46:Vn.addPersonOrSystem("person",...yn[jn]),this.$=yn[jn];break;case 47:Vn.addPersonOrSystem("external_person",...yn[jn]),this.$=yn[jn];break;case 48:Vn.addPersonOrSystem("system",...yn[jn]),this.$=yn[jn];break;case 49:Vn.addPersonOrSystem("system_db",...yn[jn]),this.$=yn[jn];break;case 50:Vn.addPersonOrSystem("system_queue",...yn[jn]),this.$=yn[jn];break;case 51:Vn.addPersonOrSystem("external_system",...yn[jn]),this.$=yn[jn];break;case 52:Vn.addPersonOrSystem("external_system_db",...yn[jn]),this.$=yn[jn];break;case 53:Vn.addPersonOrSystem("external_system_queue",...yn[jn]),this.$=yn[jn];break;case 54:Vn.addContainer("container",...yn[jn]),this.$=yn[jn];break;case 55:Vn.addContainer("container_db",...yn[jn]),this.$=yn[jn];break;case 56:Vn.addContainer("container_queue",...yn[jn]),this.$=yn[jn];break;case 57:Vn.addContainer("external_container",...yn[jn]),this.$=yn[jn];break;case 58:Vn.addContainer("external_container_db",...yn[jn]),this.$=yn[jn];break;case 59:Vn.addContainer("external_container_queue",...yn[jn]),this.$=yn[jn];break;case 60:Vn.addComponent("component",...yn[jn]),this.$=yn[jn];break;case 61:Vn.addComponent("component_db",...yn[jn]),this.$=yn[jn];break;case 62:Vn.addComponent("component_queue",...yn[jn]),this.$=yn[jn];break;case 63:Vn.addComponent("external_component",...yn[jn]),this.$=yn[jn];break;case 64:Vn.addComponent("external_component_db",...yn[jn]),this.$=yn[jn];break;case 65:Vn.addComponent("external_component_queue",...yn[jn]),this.$=yn[jn];break;case 67:Vn.addRel("rel",...yn[jn]),this.$=yn[jn];break;case 68:Vn.addRel("birel",...yn[jn]),this.$=yn[jn];break;case 69:Vn.addRel("rel_u",...yn[jn]),this.$=yn[jn];break;case 70:Vn.addRel("rel_d",...yn[jn]),this.$=yn[jn];break;case 71:Vn.addRel("rel_l",...yn[jn]),this.$=yn[jn];break;case 72:Vn.addRel("rel_r",...yn[jn]),this.$=yn[jn];break;case 73:Vn.addRel("rel_b",...yn[jn]),this.$=yn[jn];break;case 74:yn[jn].splice(0,1),Vn.addRel("rel",...yn[jn]),this.$=yn[jn];break;case 75:Vn.updateElStyle("update_el_style",...yn[jn]),this.$=yn[jn];break;case 76:Vn.updateRelStyle("update_rel_style",...yn[jn]),this.$=yn[jn];break;case 77:Vn.updateLayoutConfig("update_layout_config",...yn[jn]),this.$=yn[jn];break;case 78:this.$=[yn[jn]];break;case 79:yn[jn].unshift(yn[jn-1]),this.$=yn[jn];break;case 80:case 82:this.$=yn[jn].trim();break;case 81:let Ms={};Ms[yn[jn-1].trim()]=yn[jn].trim(),this.$=Ms;break;case 83:this.$="";break}},table:[{3:1,4:2,5:3,6:4,7:a,8:f,9:p,10:w,11:5,12:10,18:y,22:b,25:E,26:S,27:N,28:B},{1:[3]},{1:[2,1]},{1:[2,2]},{3:17,4:2,5:3,6:4,7:a,8:f,9:p,10:w,11:5,12:10,18:y,22:b,25:E,26:S,27:N,28:B},{1:[2,8]},{1:[2,4]},{1:[2,5]},{1:[2,6]},{1:[2,7]},{13:18,19:[1,19]},{15:[1,20]},{15:[1,21]},{15:[1,22]},{15:[1,23]},{15:[1,24]},{19:[2,11]},{1:[2,3]},{14:25,16:[1,26],21:R},i([16,21],[2,12]),{23:28,29:29,30:30,31:31,32:j,33:$,34:V,36:Q,38:oe,39:58,40:70,42:71,44:ce,46:se,47:ge,48:ye,49:ke,50:Ae,51:de,53:32,54:ve,55:te,56:xe,57:De,58:he,59:Ie,60:ee,61:rt,62:me,63:gt,64:pe,65:Et,66:wt,67:jt,68:At,69:Bt,70:cn,71:Nn,72:Ot,73:oi,74:kt,75:Dt,76:vt,77:Nt,78:ze,79:Xe,80:Lt,81:Ge,82:Bn,83:Oe,84:Ri},{23:79,29:29,30:30,31:31,32:j,33:$,34:V,36:Q,38:oe,39:58,40:70,42:71,44:ce,46:se,47:ge,48:ye,49:ke,50:Ae,51:de,53:32,54:ve,55:te,56:xe,57:De,58:he,59:Ie,60:ee,61:rt,62:me,63:gt,64:pe,65:Et,66:wt,67:jt,68:At,69:Bt,70:cn,71:Nn,72:Ot,73:oi,74:kt,75:Dt,76:vt,77:Nt,78:ze,79:Xe,80:Lt,81:Ge,82:Bn,83:Oe,84:Ri},{23:80,29:29,30:30,31:31,32:j,33:$,34:V,36:Q,38:oe,39:58,40:70,42:71,44:ce,46:se,47:ge,48:ye,49:ke,50:Ae,51:de,53:32,54:ve,55:te,56:xe,57:De,58:he,59:Ie,60:ee,61:rt,62:me,63:gt,64:pe,65:Et,66:wt,67:jt,68:At,69:Bt,70:cn,71:Nn,72:Ot,73:oi,74:kt,75:Dt,76:vt,77:Nt,78:ze,79:Xe,80:Lt,81:Ge,82:Bn,83:Oe,84:Ri},{23:81,29:29,30:30,31:31,32:j,33:$,34:V,36:Q,38:oe,39:58,40:70,42:71,44:ce,46:se,47:ge,48:ye,49:ke,50:Ae,51:de,53:32,54:ve,55:te,56:xe,57:De,58:he,59:Ie,60:ee,61:rt,62:me,63:gt,64:pe,65:Et,66:wt,67:jt,68:At,69:Bt,70:cn,71:Nn,72:Ot,73:oi,74:kt,75:Dt,76:vt,77:Nt,78:ze,79:Xe,80:Lt,81:Ge,82:Bn,83:Oe,84:Ri},{23:82,29:29,30:30,31:31,32:j,33:$,34:V,36:Q,38:oe,39:58,40:70,42:71,44:ce,46:se,47:ge,48:ye,49:ke,50:Ae,51:de,53:32,54:ve,55:te,56:xe,57:De,58:he,59:Ie,60:ee,61:rt,62:me,63:gt,64:pe,65:Et,66:wt,67:jt,68:At,69:Bt,70:cn,71:Nn,72:Ot,73:oi,74:kt,75:Dt,76:vt,77:Nt,78:ze,79:Xe,80:Lt,81:Ge,82:Bn,83:Oe,84:Ri},{15:[1,83]},{17:84,20:[1,85]},{15:[2,14]},{24:[1,86]},i(tn,[2,20],{53:32,39:58,40:70,42:71,30:87,44:ce,46:se,47:ge,48:ye,49:ke,50:Ae,51:de,54:ve,55:te,56:xe,57:De,58:he,59:Ie,60:ee,61:rt,62:me,63:gt,64:pe,65:Et,66:wt,67:jt,68:At,69:Bt,70:cn,71:Nn,72:Ot,73:oi,74:kt,75:Dt,76:vt,77:Nt,78:ze,79:Xe,80:Lt,81:Ge,82:Bn,83:Oe,84:Ri}),i(tn,[2,21]),i(hi,[2,23],{15:[1,88]}),i(tn,[2,43],{15:[1,89]}),i(Sr,[2,26]),i(Sr,[2,27]),{35:[1,90]},{37:[1,91]},i(Sr,[2,30]),{45:92,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:98,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:99,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:100,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:101,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:102,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:103,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:104,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:105,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:106,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:107,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:108,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:109,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:110,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:111,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:112,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:113,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:114,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:115,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:116,85:93,86:Zn,87:Xn,89:ir,90:Hn},i(tr,[2,66]),{45:117,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:118,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:119,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:120,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:121,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:122,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:123,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:124,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:125,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:126,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:127,85:93,86:Zn,87:Xn,89:ir,90:Hn},{30:128,39:58,40:70,42:71,44:ce,46:se,47:ge,48:ye,49:ke,50:Ae,51:de,53:32,54:ve,55:te,56:xe,57:De,58:he,59:Ie,60:ee,61:rt,62:me,63:gt,64:pe,65:Et,66:wt,67:jt,68:At,69:Bt,70:cn,71:Nn,72:Ot,73:oi,74:kt,75:Dt,76:vt,77:Nt,78:ze,79:Xe,80:Lt,81:Ge,82:Bn,83:Oe,84:Ri},{15:[1,130],43:[1,129]},{45:131,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:132,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:133,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:134,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:135,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:136,85:93,86:Zn,87:Xn,89:ir,90:Hn},{45:137,85:93,86:Zn,87:Xn,89:ir,90:Hn},{24:[1,138]},{24:[1,139]},{24:[1,140]},{24:[1,141]},i(ha,[2,9]),{14:142,21:R},{21:[2,13]},{1:[2,15]},i(tn,[2,22]),i(hi,[2,24],{31:31,29:143,32:j,33:$,34:V,36:Q,38:oe}),i(tn,[2,44],{29:29,30:30,31:31,53:32,39:58,40:70,42:71,23:144,32:j,33:$,34:V,36:Q,38:oe,44:ce,46:se,47:ge,48:ye,49:ke,50:Ae,51:de,54:ve,55:te,56:xe,57:De,58:he,59:Ie,60:ee,61:rt,62:me,63:gt,64:pe,65:Et,66:wt,67:jt,68:At,69:Bt,70:cn,71:Nn,72:Ot,73:oi,74:kt,75:Dt,76:vt,77:Nt,78:ze,79:Xe,80:Lt,81:Ge,82:Bn,83:Oe,84:Ri}),i(Sr,[2,28]),i(Sr,[2,29]),i(tr,[2,46]),i(Zs,[2,78],{85:93,45:145,86:Zn,87:Xn,89:ir,90:Hn}),i(ns,[2,80]),{88:[1,146]},i(ns,[2,82]),i(ns,[2,83]),i(tr,[2,47]),i(tr,[2,48]),i(tr,[2,49]),i(tr,[2,50]),i(tr,[2,51]),i(tr,[2,52]),i(tr,[2,53]),i(tr,[2,54]),i(tr,[2,55]),i(tr,[2,56]),i(tr,[2,57]),i(tr,[2,58]),i(tr,[2,59]),i(tr,[2,60]),i(tr,[2,61]),i(tr,[2,62]),i(tr,[2,63]),i(tr,[2,64]),i(tr,[2,65]),i(tr,[2,67]),i(tr,[2,68]),i(tr,[2,69]),i(tr,[2,70]),i(tr,[2,71]),i(tr,[2,72]),i(tr,[2,73]),i(tr,[2,74]),i(tr,[2,75]),i(tr,[2,76]),i(tr,[2,77]),{41:147,52:[1,148]},{15:[1,149]},{43:[1,150]},i(Hi,[2,35]),i(Hi,[2,36]),i(Hi,[2,37]),i(Hi,[2,38]),i(Hi,[2,39]),i(Hi,[2,40]),i(Hi,[2,41]),{1:[2,16]},{1:[2,17]},{1:[2,18]},{1:[2,19]},{15:[1,151]},i(hi,[2,25]),i(tn,[2,45]),i(Zs,[2,79]),i(ns,[2,81]),i(tr,[2,31]),i(tr,[2,42]),i(Js,[2,32]),i(Js,[2,33],{15:[1,152]}),i(ha,[2,10]),i(Js,[2,34])],defaultActions:{2:[2,1],3:[2,2],5:[2,8],6:[2,4],7:[2,5],8:[2,6],9:[2,7],16:[2,11],17:[2,3],27:[2,14],85:[2,13],86:[2,15],138:[2,16],139:[2,17],140:[2,18],141:[2,19]},parseError:function(Er,br){if(br.recoverable)this.trace(Er);else{var Dr=new Error(Er);throw Dr.hash=br,Dr}},parse:function(Er){var br=this,Dr=[0],Vn=[],qi=[null],yn=[],Bc=this.table,jn="",Ms=0,Pa=0,Ta=2,_a=1,ka=yn.slice.call(arguments,1),Qi=Object.create(this.lexer),ea={yy:{}};for(var Ca in this.yy)Object.prototype.hasOwnProperty.call(this.yy,Ca)&&(ea.yy[Ca]=this.yy[Ca]);Qi.setInput(Er,ea.yy),ea.yy.lexer=Qi,ea.yy.parser=this,typeof Qi.yylloc>"u"&&(Qi.yylloc={});var Sa=Qi.yylloc;yn.push(Sa);var Ka=Qi.options&&Qi.options.ranges;typeof ea.yy.parseError=="function"?this.parseError=ea.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function cg(){var Ns;return Ns=Vn.pop()||Qi.lex()||_a,typeof Ns!="number"&&(Ns instanceof Array&&(Vn=Ns,Ns=Vn.pop()),Ns=br.symbols_[Ns]||Ns),Ns}for(var Gc,Dh,Es,lp,sd={},sh,Ai,nn,Tr;;){if(Dh=Dr[Dr.length-1],this.defaultActions[Dh]?Es=this.defaultActions[Dh]:((Gc===null||typeof Gc>"u")&&(Gc=cg()),Es=Bc[Dh]&&Bc[Dh][Gc]),typeof Es>"u"||!Es.length||!Es[0]){var ai="";Tr=[];for(sh in Bc[Dh])this.terminals_[sh]&&sh>Ta&&Tr.push("'"+this.terminals_[sh]+"'");Qi.showPosition?ai="Parse error on line "+(Ms+1)+`: +`+Qi.showPosition()+` +Expecting `+Tr.join(", ")+", got '"+(this.terminals_[Gc]||Gc)+"'":ai="Parse error on line "+(Ms+1)+": Unexpected "+(Gc==_a?"end of input":"'"+(this.terminals_[Gc]||Gc)+"'"),this.parseError(ai,{text:Qi.match,token:this.terminals_[Gc]||Gc,line:Qi.yylineno,loc:Sa,expected:Tr})}if(Es[0]instanceof Array&&Es.length>1)throw new Error("Parse Error: multiple actions possible at state: "+Dh+", token: "+Gc);switch(Es[0]){case 1:Dr.push(Gc),qi.push(Qi.yytext),yn.push(Qi.yylloc),Dr.push(Es[1]),Gc=null,Pa=Qi.yyleng,jn=Qi.yytext,Ms=Qi.yylineno,Sa=Qi.yylloc;break;case 2:if(Ai=this.productions_[Es[1]][1],sd.$=qi[qi.length-Ai],sd._$={first_line:yn[yn.length-(Ai||1)].first_line,last_line:yn[yn.length-1].last_line,first_column:yn[yn.length-(Ai||1)].first_column,last_column:yn[yn.length-1].last_column},Ka&&(sd._$.range=[yn[yn.length-(Ai||1)].range[0],yn[yn.length-1].range[1]]),lp=this.performAction.apply(sd,[jn,Pa,Ms,ea.yy,Es[1],qi,yn].concat(ka)),typeof lp<"u")return lp;Ai&&(Dr=Dr.slice(0,-1*Ai*2),qi=qi.slice(0,-1*Ai),yn=yn.slice(0,-1*Ai)),Dr.push(this.productions_[Es[1]][0]),qi.push(sd.$),yn.push(sd._$),nn=Bc[Dr[Dr.length-2]][Dr[Dr.length-1]],Dr.push(nn);break;case 3:return!0}}return!0}},Ga=function(){var Oi={EOF:1,parseError:function(br,Dr){if(this.yy.parser)this.yy.parser.parseError(br,Dr);else throw new Error(br)},setInput:function(Er,br){return this.yy=br||this.yy||{},this._input=Er,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var Er=this._input[0];this.yytext+=Er,this.yyleng++,this.offset++,this.match+=Er,this.matched+=Er;var br=Er.match(/(?:\r\n?|\n).*/g);return br?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),Er},unput:function(Er){var br=Er.length,Dr=Er.split(/(?:\r\n?|\n)/g);this._input=Er+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-br),this.offset-=br;var Vn=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),Dr.length-1&&(this.yylineno-=Dr.length-1);var qi=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:Dr?(Dr.length===Vn.length?this.yylloc.first_column:0)+Vn[Vn.length-Dr.length].length-Dr[0].length:this.yylloc.first_column-br},this.options.ranges&&(this.yylloc.range=[qi[0],qi[0]+this.yyleng-br]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(Er){this.unput(this.match.slice(Er))},pastInput:function(){var Er=this.matched.substr(0,this.matched.length-this.match.length);return(Er.length>20?"...":"")+Er.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var Er=this.match;return Er.length<20&&(Er+=this._input.substr(0,20-Er.length)),(Er.substr(0,20)+(Er.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var Er=this.pastInput(),br=new Array(Er.length+1).join("-");return Er+this.upcomingInput()+` +`+br+"^"},test_match:function(Er,br){var Dr,Vn,qi;if(this.options.backtrack_lexer&&(qi={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(qi.yylloc.range=this.yylloc.range.slice(0))),Vn=Er[0].match(/(?:\r\n?|\n).*/g),Vn&&(this.yylineno+=Vn.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:Vn?Vn[Vn.length-1].length-Vn[Vn.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+Er[0].length},this.yytext+=Er[0],this.match+=Er[0],this.matches=Er,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(Er[0].length),this.matched+=Er[0],Dr=this.performAction.call(this,this.yy,this,br,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),Dr)return Dr;if(this._backtrack){for(var yn in qi)this[yn]=qi[yn];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var Er,br,Dr,Vn;this._more||(this.yytext="",this.match="");for(var qi=this._currentRules(),yn=0;ynbr[0].length)){if(br=Dr,Vn=yn,this.options.backtrack_lexer){if(Er=this.test_match(Dr,qi[yn]),Er!==!1)return Er;if(this._backtrack){br=!1;continue}else return!1}else if(!this.options.flex)break}return br?(Er=this.test_match(br,qi[Vn]),Er!==!1?Er:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var br=this.next();return br||this.lex()},begin:function(br){this.conditionStack.push(br)},popState:function(){var br=this.conditionStack.length-1;return br>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(br){return br=this.conditionStack.length-1-Math.abs(br||0),br>=0?this.conditionStack[br]:"INITIAL"},pushState:function(br){this.begin(br)},stateStackSize:function(){return this.conditionStack.length},options:{},performAction:function(br,Dr,Vn,qi){switch(Vn){case 0:return this.begin("open_directive"),18;case 1:return 7;case 2:return 8;case 3:return 9;case 4:return 10;case 5:return this.begin("type_directive"),19;case 6:return this.popState(),this.begin("arg_directive"),16;case 7:return this.popState(),this.popState(),21;case 8:return 20;case 9:return 32;case 10:return 33;case 11:return this.begin("acc_title"),34;case 12:return this.popState(),"acc_title_value";case 13:return this.begin("acc_descr"),36;case 14:return this.popState(),"acc_descr_value";case 15:this.begin("acc_descr_multiline");break;case 16:this.popState();break;case 17:return"acc_descr_multiline_value";case 18:break;case 19:c;break;case 20:return 15;case 21:break;case 22:return 22;case 23:return 25;case 24:return 26;case 25:return 27;case 26:return 28;case 27:return this.begin("person_ext"),55;case 28:return this.begin("person"),54;case 29:return this.begin("system_ext_queue"),61;case 30:return this.begin("system_ext_db"),60;case 31:return this.begin("system_ext"),59;case 32:return this.begin("system_queue"),58;case 33:return this.begin("system_db"),57;case 34:return this.begin("system"),56;case 35:return this.begin("boundary"),47;case 36:return this.begin("enterprise_boundary"),44;case 37:return this.begin("system_boundary"),46;case 38:return this.begin("container_ext_queue"),67;case 39:return this.begin("container_ext_db"),66;case 40:return this.begin("container_ext"),65;case 41:return this.begin("container_queue"),64;case 42:return this.begin("container_db"),63;case 43:return this.begin("container"),62;case 44:return this.begin("container_boundary"),48;case 45:return this.begin("component_ext_queue"),73;case 46:return this.begin("component_ext_db"),72;case 47:return this.begin("component_ext"),71;case 48:return this.begin("component_queue"),70;case 49:return this.begin("component_db"),69;case 50:return this.begin("component"),68;case 51:return this.begin("node"),49;case 52:return this.begin("node"),49;case 53:return this.begin("node_l"),50;case 54:return this.begin("node_r"),51;case 55:return this.begin("rel"),74;case 56:return this.begin("birel"),75;case 57:return this.begin("rel_u"),76;case 58:return this.begin("rel_u"),76;case 59:return this.begin("rel_d"),77;case 60:return this.begin("rel_d"),77;case 61:return this.begin("rel_l"),78;case 62:return this.begin("rel_l"),78;case 63:return this.begin("rel_r"),79;case 64:return this.begin("rel_r"),79;case 65:return this.begin("rel_b"),80;case 66:return this.begin("rel_index"),81;case 67:return this.begin("update_el_style"),82;case 68:return this.begin("update_rel_style"),83;case 69:return this.begin("update_layout_config"),84;case 70:return"EOF_IN_STRUCT";case 71:return this.begin("attribute"),"ATTRIBUTE_EMPTY";case 72:this.begin("attribute");break;case 73:this.popState(),this.popState();break;case 74:return 90;case 75:break;case 76:return 90;case 77:this.begin("string");break;case 78:this.popState();break;case 79:return"STR";case 80:this.begin("string_kv");break;case 81:return this.begin("string_kv_key"),"STR_KEY";case 82:this.popState(),this.begin("string_kv_value");break;case 83:return"STR_VALUE";case 84:this.popState(),this.popState();break;case 85:return"STR";case 86:return"LBRACE";case 87:return"RBRACE";case 88:return"SPACE";case 89:return"EOL";case 90:return 24}},rules:[/^(?:%%\{)/,/^(?:.*direction\s+TB[^\n]*)/,/^(?:.*direction\s+BT[^\n]*)/,/^(?:.*direction\s+RL[^\n]*)/,/^(?:.*direction\s+LR[^\n]*)/,/^(?:((?:(?!\}%%)[^:.])*))/,/^(?::)/,/^(?:\}%%)/,/^(?:((?:(?!\}%%).|\n)*))/,/^(?:title\s[^#\n;]+)/,/^(?:accDescription\s[^#\n;]+)/,/^(?:accTitle\s*:\s*)/,/^(?:(?!\n||)*[^\n]*)/,/^(?:accDescr\s*:\s*)/,/^(?:(?!\n||)*[^\n]*)/,/^(?:accDescr\s*\{\s*)/,/^(?:[\}])/,/^(?:[^\}]*)/,/^(?:%%(?!\{)*[^\n]*(\r?\n?)+)/,/^(?:%%[^\n]*(\r?\n)*)/,/^(?:\s*(\r?\n)+)/,/^(?:\s+)/,/^(?:C4Context\b)/,/^(?:C4Container\b)/,/^(?:C4Component\b)/,/^(?:C4Dynamic\b)/,/^(?:C4Deployment\b)/,/^(?:Person_Ext\b)/,/^(?:Person\b)/,/^(?:SystemQueue_Ext\b)/,/^(?:SystemDb_Ext\b)/,/^(?:System_Ext\b)/,/^(?:SystemQueue\b)/,/^(?:SystemDb\b)/,/^(?:System\b)/,/^(?:Boundary\b)/,/^(?:Enterprise_Boundary\b)/,/^(?:System_Boundary\b)/,/^(?:ContainerQueue_Ext\b)/,/^(?:ContainerDb_Ext\b)/,/^(?:Container_Ext\b)/,/^(?:ContainerQueue\b)/,/^(?:ContainerDb\b)/,/^(?:Container\b)/,/^(?:Container_Boundary\b)/,/^(?:ComponentQueue_Ext\b)/,/^(?:ComponentDb_Ext\b)/,/^(?:Component_Ext\b)/,/^(?:ComponentQueue\b)/,/^(?:ComponentDb\b)/,/^(?:Component\b)/,/^(?:Deployment_Node\b)/,/^(?:Node\b)/,/^(?:Node_L\b)/,/^(?:Node_R\b)/,/^(?:Rel\b)/,/^(?:BiRel\b)/,/^(?:Rel_Up\b)/,/^(?:Rel_U\b)/,/^(?:Rel_Down\b)/,/^(?:Rel_D\b)/,/^(?:Rel_Left\b)/,/^(?:Rel_L\b)/,/^(?:Rel_Right\b)/,/^(?:Rel_R\b)/,/^(?:Rel_Back\b)/,/^(?:RelIndex\b)/,/^(?:UpdateElementStyle\b)/,/^(?:UpdateRelStyle\b)/,/^(?:UpdateLayoutConfig\b)/,/^(?:$)/,/^(?:[(][ ]*[,])/,/^(?:[(])/,/^(?:[)])/,/^(?:,,)/,/^(?:,)/,/^(?:[ ]*["]["])/,/^(?:[ ]*["])/,/^(?:["])/,/^(?:[^"]*)/,/^(?:[ ]*[\$])/,/^(?:[^=]*)/,/^(?:[=][ ]*["])/,/^(?:[^"]+)/,/^(?:["])/,/^(?:[^,]+)/,/^(?:\{)/,/^(?:\})/,/^(?:[\s]+)/,/^(?:[\n\r]+)/,/^(?:$)/],conditions:{acc_descr_multiline:{rules:[16,17],inclusive:!1},acc_descr:{rules:[14],inclusive:!1},acc_title:{rules:[12],inclusive:!1},close_directive:{rules:[],inclusive:!1},arg_directive:{rules:[7,8],inclusive:!1},type_directive:{rules:[6,7],inclusive:!1},open_directive:{rules:[5],inclusive:!1},string_kv_value:{rules:[83,84],inclusive:!1},string_kv_key:{rules:[82],inclusive:!1},string_kv:{rules:[81],inclusive:!1},string:{rules:[78,79],inclusive:!1},attribute:{rules:[73,74,75,76,77,80,85],inclusive:!1},update_layout_config:{rules:[70,71,72,73],inclusive:!1},update_rel_style:{rules:[70,71,72,73],inclusive:!1},update_el_style:{rules:[70,71,72,73],inclusive:!1},rel_b:{rules:[70,71,72,73],inclusive:!1},rel_r:{rules:[70,71,72,73],inclusive:!1},rel_l:{rules:[70,71,72,73],inclusive:!1},rel_d:{rules:[70,71,72,73],inclusive:!1},rel_u:{rules:[70,71,72,73],inclusive:!1},rel_bi:{rules:[],inclusive:!1},rel:{rules:[70,71,72,73],inclusive:!1},node_r:{rules:[70,71,72,73],inclusive:!1},node_l:{rules:[70,71,72,73],inclusive:!1},node:{rules:[70,71,72,73],inclusive:!1},index:{rules:[],inclusive:!1},rel_index:{rules:[70,71,72,73],inclusive:!1},component_ext_queue:{rules:[],inclusive:!1},component_ext_db:{rules:[70,71,72,73],inclusive:!1},component_ext:{rules:[70,71,72,73],inclusive:!1},component_queue:{rules:[70,71,72,73],inclusive:!1},component_db:{rules:[70,71,72,73],inclusive:!1},component:{rules:[70,71,72,73],inclusive:!1},container_boundary:{rules:[70,71,72,73],inclusive:!1},container_ext_queue:{rules:[],inclusive:!1},container_ext_db:{rules:[70,71,72,73],inclusive:!1},container_ext:{rules:[70,71,72,73],inclusive:!1},container_queue:{rules:[70,71,72,73],inclusive:!1},container_db:{rules:[70,71,72,73],inclusive:!1},container:{rules:[70,71,72,73],inclusive:!1},birel:{rules:[70,71,72,73],inclusive:!1},system_boundary:{rules:[70,71,72,73],inclusive:!1},enterprise_boundary:{rules:[70,71,72,73],inclusive:!1},boundary:{rules:[70,71,72,73],inclusive:!1},system_ext_queue:{rules:[70,71,72,73],inclusive:!1},system_ext_db:{rules:[70,71,72,73],inclusive:!1},system_ext:{rules:[70,71,72,73],inclusive:!1},system_queue:{rules:[70,71,72,73],inclusive:!1},system_db:{rules:[70,71,72,73],inclusive:!1},system:{rules:[70,71,72,73],inclusive:!1},person_ext:{rules:[70,71,72,73],inclusive:!1},person:{rules:[70,71,72,73],inclusive:!1},INITIAL:{rules:[0,1,2,3,4,9,10,11,13,15,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,86,87,88,89,90],inclusive:!0}}};return Oi}();Pc.lexer=Ga;function ws(){this.yy={}}return ws.prototype=Pc,Pc.Parser=ws,new ws}();OW.parser=OW;const vLt=OW;let Qw=[],nx=[""],ag="global",Zw="",o3=[{alias:"global",label:{text:"global"},type:{text:"global"},tags:null,link:null,parentBoundary:""}],QN=[],_de="",Cde=!1,NW=4,PW=2;var POe;const wLt=function(){return POe},mLt=function(i){POe=ep(i,Tt())},yLt=function(i,a,f){rd.parseDirective(this,i,a,f)},kLt=function(i,a,f,p,w,y,b,E,S){if(i==null||a===void 0||a===null||f===void 0||f===null||p===void 0||p===null)return;let N={};const B=QN.find(R=>R.from===a&&R.to===f);if(B?N=B:QN.push(N),N.type=i,N.from=a,N.to=f,N.label={text:p},w==null)N.techn={text:""};else if(typeof w=="object"){let[R,j]=Object.entries(w)[0];N[R]={text:j}}else N.techn={text:w};if(y==null)N.descr={text:""};else if(typeof y=="object"){let[R,j]=Object.entries(y)[0];N[R]={text:j}}else N.descr={text:y};if(typeof b=="object"){let[R,j]=Object.entries(b)[0];N[R]=j}else N.sprite=b;if(typeof E=="object"){let[R,j]=Object.entries(E)[0];N[R]=j}else N.tags=E;if(typeof S=="object"){let[R,j]=Object.entries(S)[0];N[R]=j}else N.link=S;N.wrap=rx()},xLt=function(i,a,f,p,w,y,b){if(a===null||f===null)return;let E={};const S=Qw.find(N=>N.alias===a);if(S&&a===S.alias?E=S:(E.alias=a,Qw.push(E)),f==null?E.label={text:""}:E.label={text:f},p==null)E.descr={text:""};else if(typeof p=="object"){let[N,B]=Object.entries(p)[0];E[N]={text:B}}else E.descr={text:p};if(typeof w=="object"){let[N,B]=Object.entries(w)[0];E[N]=B}else E.sprite=w;if(typeof y=="object"){let[N,B]=Object.entries(y)[0];E[N]=B}else E.tags=y;if(typeof b=="object"){let[N,B]=Object.entries(b)[0];E[N]=B}else E.link=b;E.typeC4Shape={text:i},E.parentBoundary=ag,E.wrap=rx()},ELt=function(i,a,f,p,w,y,b,E){if(a===null||f===null)return;let S={};const N=Qw.find(B=>B.alias===a);if(N&&a===N.alias?S=N:(S.alias=a,Qw.push(S)),f==null?S.label={text:""}:S.label={text:f},p==null)S.techn={text:""};else if(typeof p=="object"){let[B,R]=Object.entries(p)[0];S[B]={text:R}}else S.techn={text:p};if(w==null)S.descr={text:""};else if(typeof w=="object"){let[B,R]=Object.entries(w)[0];S[B]={text:R}}else S.descr={text:w};if(typeof y=="object"){let[B,R]=Object.entries(y)[0];S[B]=R}else S.sprite=y;if(typeof b=="object"){let[B,R]=Object.entries(b)[0];S[B]=R}else S.tags=b;if(typeof E=="object"){let[B,R]=Object.entries(E)[0];S[B]=R}else S.link=E;S.wrap=rx(),S.typeC4Shape={text:i},S.parentBoundary=ag},TLt=function(i,a,f,p,w,y,b,E){if(a===null||f===null)return;let S={};const N=Qw.find(B=>B.alias===a);if(N&&a===N.alias?S=N:(S.alias=a,Qw.push(S)),f==null?S.label={text:""}:S.label={text:f},p==null)S.techn={text:""};else if(typeof p=="object"){let[B,R]=Object.entries(p)[0];S[B]={text:R}}else S.techn={text:p};if(w==null)S.descr={text:""};else if(typeof w=="object"){let[B,R]=Object.entries(w)[0];S[B]={text:R}}else S.descr={text:w};if(typeof y=="object"){let[B,R]=Object.entries(y)[0];S[B]=R}else S.sprite=y;if(typeof b=="object"){let[B,R]=Object.entries(b)[0];S[B]=R}else S.tags=b;if(typeof E=="object"){let[B,R]=Object.entries(E)[0];S[B]=R}else S.link=E;S.wrap=rx(),S.typeC4Shape={text:i},S.parentBoundary=ag},_Lt=function(i,a,f,p,w){if(i===null||a===null)return;let y={};const b=o3.find(E=>E.alias===i);if(b&&i===b.alias?y=b:(y.alias=i,o3.push(y)),a==null?y.label={text:""}:y.label={text:a},f==null)y.type={text:"system"};else if(typeof f=="object"){let[E,S]=Object.entries(f)[0];y[E]={text:S}}else y.type={text:f};if(typeof p=="object"){let[E,S]=Object.entries(p)[0];y[E]=S}else y.tags=p;if(typeof w=="object"){let[E,S]=Object.entries(w)[0];y[E]=S}else y.link=w;y.parentBoundary=ag,y.wrap=rx(),Zw=ag,ag=i,nx.push(Zw)},CLt=function(i,a,f,p,w){if(i===null||a===null)return;let y={};const b=o3.find(E=>E.alias===i);if(b&&i===b.alias?y=b:(y.alias=i,o3.push(y)),a==null?y.label={text:""}:y.label={text:a},f==null)y.type={text:"container"};else if(typeof f=="object"){let[E,S]=Object.entries(f)[0];y[E]={text:S}}else y.type={text:f};if(typeof p=="object"){let[E,S]=Object.entries(p)[0];y[E]=S}else y.tags=p;if(typeof w=="object"){let[E,S]=Object.entries(w)[0];y[E]=S}else y.link=w;y.parentBoundary=ag,y.wrap=rx(),Zw=ag,ag=i,nx.push(Zw)},SLt=function(i,a,f,p,w,y,b,E){if(a===null||f===null)return;let S={};const N=o3.find(B=>B.alias===a);if(N&&a===N.alias?S=N:(S.alias=a,o3.push(S)),f==null?S.label={text:""}:S.label={text:f},p==null)S.type={text:"node"};else if(typeof p=="object"){let[B,R]=Object.entries(p)[0];S[B]={text:R}}else S.type={text:p};if(w==null)S.descr={text:""};else if(typeof w=="object"){let[B,R]=Object.entries(w)[0];S[B]={text:R}}else S.descr={text:w};if(typeof b=="object"){let[B,R]=Object.entries(b)[0];S[B]=R}else S.tags=b;if(typeof E=="object"){let[B,R]=Object.entries(E)[0];S[B]=R}else S.link=E;S.nodeType=i,S.parentBoundary=ag,S.wrap=rx(),Zw=ag,ag=a,nx.push(Zw)},ALt=function(){ag=Zw,nx.pop(),Zw=nx.pop(),nx.push(Zw)},LLt=function(i,a,f,p,w,y,b,E,S,N,B){let R=Qw.find(j=>j.alias===a);if(!(R===void 0&&(R=o3.find(j=>j.alias===a),R===void 0))){if(f!=null)if(typeof f=="object"){let[j,$]=Object.entries(f)[0];R[j]=$}else R.bgColor=f;if(p!=null)if(typeof p=="object"){let[j,$]=Object.entries(p)[0];R[j]=$}else R.fontColor=p;if(w!=null)if(typeof w=="object"){let[j,$]=Object.entries(w)[0];R[j]=$}else R.borderColor=w;if(y!=null)if(typeof y=="object"){let[j,$]=Object.entries(y)[0];R[j]=$}else R.shadowing=y;if(b!=null)if(typeof b=="object"){let[j,$]=Object.entries(b)[0];R[j]=$}else R.shape=b;if(E!=null)if(typeof E=="object"){let[j,$]=Object.entries(E)[0];R[j]=$}else R.sprite=E;if(S!=null)if(typeof S=="object"){let[j,$]=Object.entries(S)[0];R[j]=$}else R.techn=S;if(N!=null)if(typeof N=="object"){let[j,$]=Object.entries(N)[0];R[j]=$}else R.legendText=N;if(B!=null)if(typeof B=="object"){let[j,$]=Object.entries(B)[0];R[j]=$}else R.legendSprite=B}},MLt=function(i,a,f,p,w,y,b){const E=QN.find(S=>S.from===a&&S.to===f);if(E!==void 0){if(p!=null)if(typeof p=="object"){let[S,N]=Object.entries(p)[0];E[S]=N}else E.textColor=p;if(w!=null)if(typeof w=="object"){let[S,N]=Object.entries(w)[0];E[S]=N}else E.lineColor=w;if(y!=null)if(typeof y=="object"){let[S,N]=Object.entries(y)[0];E[S]=parseInt(N)}else E.offsetX=parseInt(y);if(b!=null)if(typeof b=="object"){let[S,N]=Object.entries(b)[0];E[S]=parseInt(N)}else E.offsetY=parseInt(b)}},DLt=function(i,a,f){let p=NW,w=PW;if(typeof a=="object"){const y=Object.values(a)[0];p=parseInt(y)}else p=parseInt(a);if(typeof f=="object"){const y=Object.values(f)[0];w=parseInt(y)}else w=parseInt(f);p>=1&&(NW=p),w>=1&&(PW=w)},ILt=function(){return NW},OLt=function(){return PW},NLt=function(){return ag},PLt=function(){return Zw},BOe=function(i){return i==null?Qw:Qw.filter(a=>a.parentBoundary===i)},BLt=function(i){return Qw.find(a=>a.alias===i)},RLt=function(i){return Object.keys(BOe(i))},FLt=function(i){return i==null?o3:o3.filter(a=>a.parentBoundary===i)},jLt=function(){return QN},$Lt=function(){return _de},HLt=function(i){Cde=i},rx=function(){return Cde},ROe={addPersonOrSystem:xLt,addPersonOrSystemBoundary:_Lt,addContainer:ELt,addContainerBoundary:CLt,addComponent:TLt,addDeploymentNode:SLt,popBoundaryParseStack:ALt,addRel:kLt,updateElStyle:LLt,updateRelStyle:MLt,updateLayoutConfig:DLt,autoWrap:rx,setWrap:HLt,getC4ShapeArray:BOe,getC4Shape:BLt,getC4ShapeKeys:RLt,getBoundarys:FLt,getCurrentBoundaryParse:NLt,getParentBoundaryParse:PLt,getRels:jLt,getTitle:$Lt,getC4Type:wLt,getC4ShapeInRow:ILt,getC4BoundaryInRow:OLt,setAccTitle:ip,getAccTitle:L2,getAccDescription:D2,setAccDescription:M2,parseDirective:yLt,getConfig:()=>Tt().c4,clear:function(){Qw=[],o3=[{alias:"global",label:{text:"global"},type:{text:"global"},tags:null,link:null,parentBoundary:""}],Zw="",ag="global",nx=[""],QN=[],nx=[""],_de="",Cde=!1,NW=4,PW=2},LINETYPE:{SOLID:0,DOTTED:1,NOTE:2,SOLID_CROSS:3,DOTTED_CROSS:4,SOLID_OPEN:5,DOTTED_OPEN:6,LOOP_START:10,LOOP_END:11,ALT_START:12,ALT_ELSE:13,ALT_END:14,OPT_START:15,OPT_END:16,ACTIVE_START:17,ACTIVE_END:18,PAR_START:19,PAR_AND:20,PAR_END:21,RECT_START:22,RECT_END:23,SOLID_POINT:24,DOTTED_POINT:25},ARROWTYPE:{FILLED:0,OPEN:1},PLACEMENT:{LEFTOF:0,RIGHTOF:1,OVER:2},setTitle:function(i){_de=ep(i,Tt())},setC4Type:mLt},Sde=function(i,a){const f=i.append("rect");if(f.attr("x",a.x),f.attr("y",a.y),f.attr("fill",a.fill),f.attr("stroke",a.stroke),f.attr("width",a.width),f.attr("height",a.height),f.attr("rx",a.rx),f.attr("ry",a.ry),a.attrs!=="undefined"&&a.attrs!==null)for(let p in a.attrs)f.attr(p,a.attrs[p]);return a.class!=="undefined"&&f.attr("class",a.class),f},FOe=function(i,a,f,p,w,y){const b=i.append("image");b.attr("width",a),b.attr("height",f),b.attr("x",p),b.attr("y",w);let E=y.startsWith("data:image/png;base64")?y:u5(y);b.attr("xlink:href",E)},zLt=(i,a,f)=>{const p=i.append("g");let w=0;for(let y of a){let b=y.textColor?y.textColor:"#444444",E=y.lineColor?y.lineColor:"#444444",S=y.offsetX?parseInt(y.offsetX):0,N=y.offsetY?parseInt(y.offsetY):0,B="";if(w===0){let j=p.append("line");j.attr("x1",y.startPoint.x),j.attr("y1",y.startPoint.y),j.attr("x2",y.endPoint.x),j.attr("y2",y.endPoint.y),j.attr("stroke-width","1"),j.attr("stroke",E),j.style("fill","none"),y.type!=="rel_b"&&j.attr("marker-end","url("+B+"#arrowhead)"),(y.type==="birel"||y.type==="rel_b")&&j.attr("marker-start","url("+B+"#arrowend)"),w=-1}else{let j=p.append("path");j.attr("fill","none").attr("stroke-width","1").attr("stroke",E).attr("d","Mstartx,starty Qcontrolx,controly stopx,stopy ".replaceAll("startx",y.startPoint.x).replaceAll("starty",y.startPoint.y).replaceAll("controlx",y.startPoint.x+(y.endPoint.x-y.startPoint.x)/2-(y.endPoint.x-y.startPoint.x)/4).replaceAll("controly",y.startPoint.y+(y.endPoint.y-y.startPoint.y)/2).replaceAll("stopx",y.endPoint.x).replaceAll("stopy",y.endPoint.y)),y.type!=="rel_b"&&j.attr("marker-end","url("+B+"#arrowhead)"),(y.type==="birel"||y.type==="rel_b")&&j.attr("marker-start","url("+B+"#arrowend)")}let R=f.messageFont();w5(f)(y.label.text,p,Math.min(y.startPoint.x,y.endPoint.x)+Math.abs(y.endPoint.x-y.startPoint.x)/2+S,Math.min(y.startPoint.y,y.endPoint.y)+Math.abs(y.endPoint.y-y.startPoint.y)/2+N,y.label.width,y.label.height,{fill:b},R),y.techn&&y.techn.text!==""&&(R=f.messageFont(),w5(f)("["+y.techn.text+"]",p,Math.min(y.startPoint.x,y.endPoint.x)+Math.abs(y.endPoint.x-y.startPoint.x)/2+S,Math.min(y.startPoint.y,y.endPoint.y)+Math.abs(y.endPoint.y-y.startPoint.y)/2+f.messageFontSize+5+N,Math.max(y.label.width,y.techn.width),y.techn.height,{fill:b,"font-style":"italic"},R))}},GLt=function(i,a,f){const p=i.append("g");let w=a.bgColor?a.bgColor:"none",y=a.borderColor?a.borderColor:"#444444",b=a.fontColor?a.fontColor:"black",E={"stroke-width":1,"stroke-dasharray":"7.0,7.0"};a.nodeType&&(E={"stroke-width":1});let S={x:a.x,y:a.y,fill:w,stroke:y,width:a.width,height:a.height,rx:2.5,ry:2.5,attrs:E};Sde(p,S);let N=f.boundaryFont();N.fontWeight="bold",N.fontSize=N.fontSize+2,N.fontColor=b,w5(f)(a.label.text,p,a.x,a.y+a.label.Y,a.width,a.height,{fill:"#444444"},N),a.type&&a.type.text!==""&&(N=f.boundaryFont(),N.fontColor=b,w5(f)(a.type.text,p,a.x,a.y+a.type.Y,a.width,a.height,{fill:"#444444"},N)),a.descr&&a.descr.text!==""&&(N=f.boundaryFont(),N.fontSize=N.fontSize-2,N.fontColor=b,w5(f)(a.descr.text,p,a.x,a.y+a.descr.Y,a.width,a.height,{fill:"#444444"},N))},qLt=function(i,a,f){var R;let p=a.bgColor?a.bgColor:f[a.typeC4Shape.text+"_bg_color"],w=a.borderColor?a.borderColor:f[a.typeC4Shape.text+"_border_color"],y=a.fontColor?a.fontColor:"#FFFFFF",b="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAIAAADYYG7QAAACD0lEQVR4Xu2YoU4EMRCGT+4j8Ai8AhaH4QHgAUjQuFMECUgMIUgwJAgMhgQsAYUiJCiQIBBY+EITsjfTdme6V24v4c8vyGbb+ZjOtN0bNcvjQXmkH83WvYBWto6PLm6v7p7uH1/w2fXD+PBycX1Pv2l3IdDm/vn7x+dXQiAubRzoURa7gRZWd0iGRIiJbOnhnfYBQZNJjNbuyY2eJG8fkDE3bbG4ep6MHUAsgYxmE3nVs6VsBWJSGccsOlFPmLIViMzLOB7pCVO2AtHJMohH7Fh6zqitQK7m0rJvAVYgGcEpe//PLdDz65sM4pF9N7ICcXDKIB5Nv6j7tD0NoSdM2QrU9Gg0ewE1LqBhHR3BBdvj2vapnidjHxD/q6vd7Pvhr31AwcY8eXMTXAKECZZJFXuEq27aLgQK5uLMohCenGGuGewOxSjBvYBqeG6B+Nqiblggdjnc+ZXDy+FNFpFzw76O3UBAROuXh6FoiAcf5g9eTvUgzy0nWg6I8cXHRUpg5bOVBCo+KDpFajOf23GgPme7RSQ+lacIENUgJ6gg1k6HjgOlqnLqip4tEuhv0hNEMXUD0clyXE3p6pZA0S2nnvTlXwLJEZWlb7cTQH1+USgTN4VhAenm/wea1OCAOmqo6fE1WCb9WSKBah+rbUWPWAmE2Rvk0ApiB45eOyNAzU8xcTvj8KvkKEoOaIYeHNA3ZuygAvFMUO0AAAAASUVORK5CYII=";switch(a.typeC4Shape.text){case"person":b="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAIAAADYYG7QAAACD0lEQVR4Xu2YoU4EMRCGT+4j8Ai8AhaH4QHgAUjQuFMECUgMIUgwJAgMhgQsAYUiJCiQIBBY+EITsjfTdme6V24v4c8vyGbb+ZjOtN0bNcvjQXmkH83WvYBWto6PLm6v7p7uH1/w2fXD+PBycX1Pv2l3IdDm/vn7x+dXQiAubRzoURa7gRZWd0iGRIiJbOnhnfYBQZNJjNbuyY2eJG8fkDE3bbG4ep6MHUAsgYxmE3nVs6VsBWJSGccsOlFPmLIViMzLOB7pCVO2AtHJMohH7Fh6zqitQK7m0rJvAVYgGcEpe//PLdDz65sM4pF9N7ICcXDKIB5Nv6j7tD0NoSdM2QrU9Gg0ewE1LqBhHR3BBdvj2vapnidjHxD/q6vd7Pvhr31AwcY8eXMTXAKECZZJFXuEq27aLgQK5uLMohCenGGuGewOxSjBvYBqeG6B+Nqiblggdjnc+ZXDy+FNFpFzw76O3UBAROuXh6FoiAcf5g9eTvUgzy0nWg6I8cXHRUpg5bOVBCo+KDpFajOf23GgPme7RSQ+lacIENUgJ6gg1k6HjgOlqnLqip4tEuhv0hNEMXUD0clyXE3p6pZA0S2nnvTlXwLJEZWlb7cTQH1+USgTN4VhAenm/wea1OCAOmqo6fE1WCb9WSKBah+rbUWPWAmE2Rvk0ApiB45eOyNAzU8xcTvj8KvkKEoOaIYeHNA3ZuygAvFMUO0AAAAASUVORK5CYII=";break;case"external_person":b="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAIAAADYYG7QAAAB6ElEQVR4Xu2YLY+EMBCG9+dWr0aj0Wg0Go1Go0+j8Xdv2uTCvv1gpt0ebHKPuhDaeW4605Z9mJvx4AdXUyTUdd08z+u6flmWZRnHsWkafk9DptAwDPu+f0eAYtu2PEaGWuj5fCIZrBAC2eLBAnRCsEkkxmeaJp7iDJ2QMDdHsLg8SxKFEJaAo8lAXnmuOFIhTMpxxKATebo4UiFknuNo4OniSIXQyRxEA3YsnjGCVEjVXD7yLUAqxBGUyPv/Y4W2beMgGuS7kVQIBycH0fD+oi5pezQETxdHKmQKGk1eQEYldK+jw5GxPfZ9z7Mk0Qnhf1W1m3w//EUn5BDmSZsbR44QQLBEqrBHqOrmSKaQAxdnLArCrxZcM7A7ZKs4ioRq8LFC+NpC3WCBJsvpVw5edm9iEXFuyNfxXAgSwfrFQ1c0iNda8AdejvUgnktOtJQQxmcfFzGglc5WVCj7oDgFqU18boeFSs52CUh8LE8BIVQDT1ABrB0HtgSEYlX5doJnCwv9TXocKCaKbnwhdDKPq4lf3SwU3HLq4V/+WYhHVMa/3b4IlfyikAduCkcBc7mQ3/z/Qq/cTuikhkzB12Ae/mcJC9U+Vo8Ej1gWAtgbeGgFsAMHr50BIWOLCbezvhpBFUdY6EJuJ/QDW0XoMX60zZ0AAAAASUVORK5CYII=";break}const E=i.append("g");E.attr("class","person-man");const S=jOe();switch(a.typeC4Shape.text){case"person":case"external_person":case"system":case"external_system":case"container":case"external_container":case"component":case"external_component":S.x=a.x,S.y=a.y,S.fill=p,S.width=a.width,S.height=a.height,S.stroke=w,S.rx=2.5,S.ry=2.5,S.attrs={"stroke-width":.5},Sde(E,S);break;case"system_db":case"external_system_db":case"container_db":case"external_container_db":case"component_db":case"external_component_db":E.append("path").attr("fill",p).attr("stroke-width","0.5").attr("stroke",w).attr("d","Mstartx,startyc0,-10 half,-10 half,-10c0,0 half,0 half,10l0,heightc0,10 -half,10 -half,10c0,0 -half,0 -half,-10l0,-height".replaceAll("startx",a.x).replaceAll("starty",a.y).replaceAll("half",a.width/2).replaceAll("height",a.height)),E.append("path").attr("fill","none").attr("stroke-width","0.5").attr("stroke",w).attr("d","Mstartx,startyc0,10 half,10 half,10c0,0 half,0 half,-10".replaceAll("startx",a.x).replaceAll("starty",a.y).replaceAll("half",a.width/2));break;case"system_queue":case"external_system_queue":case"container_queue":case"external_container_queue":case"component_queue":case"external_component_queue":E.append("path").attr("fill",p).attr("stroke-width","0.5").attr("stroke",w).attr("d","Mstartx,startylwidth,0c5,0 5,half 5,halfc0,0 0,half -5,halfl-width,0c-5,0 -5,-half -5,-halfc0,0 0,-half 5,-half".replaceAll("startx",a.x).replaceAll("starty",a.y).replaceAll("width",a.width).replaceAll("half",a.height/2)),E.append("path").attr("fill","none").attr("stroke-width","0.5").attr("stroke",w).attr("d","Mstartx,startyc-5,0 -5,half -5,halfc0,half 5,half 5,half".replaceAll("startx",a.x+a.width).replaceAll("starty",a.y).replaceAll("half",a.height/2));break}let N=JLt(f,a.typeC4Shape.text);switch(E.append("text").attr("fill",y).attr("font-family",N.fontFamily).attr("font-size",N.fontSize-2).attr("font-style","italic").attr("lengthAdjust","spacing").attr("textLength",a.typeC4Shape.width).attr("x",a.x+a.width/2-a.typeC4Shape.width/2).attr("y",a.y+a.typeC4Shape.Y).text("<<"+a.typeC4Shape.text+">>"),a.typeC4Shape.text){case"person":case"external_person":FOe(E,48,48,a.x+a.width/2-24,a.y+a.image.Y,b);break}let B=f[a.typeC4Shape.text+"Font"]();return B.fontWeight="bold",B.fontSize=B.fontSize+2,B.fontColor=y,w5(f)(a.label.text,E,a.x,a.y+a.label.Y,a.width,a.height,{fill:y},B),B=f[a.typeC4Shape.text+"Font"](),B.fontColor=y,a.techn&&((R=a.techn)==null?void 0:R.text)!==""?w5(f)(a.techn.text,E,a.x,a.y+a.techn.Y,a.width,a.height,{fill:y,"font-style":"italic"},B):a.type&&a.type.text!==""&&w5(f)(a.type.text,E,a.x,a.y+a.type.Y,a.width,a.height,{fill:y,"font-style":"italic"},B),a.descr&&a.descr.text!==""&&(B=f.personFont(),B.fontColor=y,w5(f)(a.descr.text,E,a.x,a.y+a.descr.Y,a.width,a.height,{fill:y},B)),a.height},VLt=function(i){i.append("defs").append("symbol").attr("id","database").attr("fill-rule","evenodd").attr("clip-rule","evenodd").append("path").attr("transform","scale(.5)").attr("d","M12.258.001l.256.004.255.005.253.008.251.01.249.012.247.015.246.016.242.019.241.02.239.023.236.024.233.027.231.028.229.031.225.032.223.034.22.036.217.038.214.04.211.041.208.043.205.045.201.046.198.048.194.05.191.051.187.053.183.054.18.056.175.057.172.059.168.06.163.061.16.063.155.064.15.066.074.033.073.033.071.034.07.034.069.035.068.035.067.035.066.035.064.036.064.036.062.036.06.036.06.037.058.037.058.037.055.038.055.038.053.038.052.038.051.039.05.039.048.039.047.039.045.04.044.04.043.04.041.04.04.041.039.041.037.041.036.041.034.041.033.042.032.042.03.042.029.042.027.042.026.043.024.043.023.043.021.043.02.043.018.044.017.043.015.044.013.044.012.044.011.045.009.044.007.045.006.045.004.045.002.045.001.045v17l-.001.045-.002.045-.004.045-.006.045-.007.045-.009.044-.011.045-.012.044-.013.044-.015.044-.017.043-.018.044-.02.043-.021.043-.023.043-.024.043-.026.043-.027.042-.029.042-.03.042-.032.042-.033.042-.034.041-.036.041-.037.041-.039.041-.04.041-.041.04-.043.04-.044.04-.045.04-.047.039-.048.039-.05.039-.051.039-.052.038-.053.038-.055.038-.055.038-.058.037-.058.037-.06.037-.06.036-.062.036-.064.036-.064.036-.066.035-.067.035-.068.035-.069.035-.07.034-.071.034-.073.033-.074.033-.15.066-.155.064-.16.063-.163.061-.168.06-.172.059-.175.057-.18.056-.183.054-.187.053-.191.051-.194.05-.198.048-.201.046-.205.045-.208.043-.211.041-.214.04-.217.038-.22.036-.223.034-.225.032-.229.031-.231.028-.233.027-.236.024-.239.023-.241.02-.242.019-.246.016-.247.015-.249.012-.251.01-.253.008-.255.005-.256.004-.258.001-.258-.001-.256-.004-.255-.005-.253-.008-.251-.01-.249-.012-.247-.015-.245-.016-.243-.019-.241-.02-.238-.023-.236-.024-.234-.027-.231-.028-.228-.031-.226-.032-.223-.034-.22-.036-.217-.038-.214-.04-.211-.041-.208-.043-.204-.045-.201-.046-.198-.048-.195-.05-.19-.051-.187-.053-.184-.054-.179-.056-.176-.057-.172-.059-.167-.06-.164-.061-.159-.063-.155-.064-.151-.066-.074-.033-.072-.033-.072-.034-.07-.034-.069-.035-.068-.035-.067-.035-.066-.035-.064-.036-.063-.036-.062-.036-.061-.036-.06-.037-.058-.037-.057-.037-.056-.038-.055-.038-.053-.038-.052-.038-.051-.039-.049-.039-.049-.039-.046-.039-.046-.04-.044-.04-.043-.04-.041-.04-.04-.041-.039-.041-.037-.041-.036-.041-.034-.041-.033-.042-.032-.042-.03-.042-.029-.042-.027-.042-.026-.043-.024-.043-.023-.043-.021-.043-.02-.043-.018-.044-.017-.043-.015-.044-.013-.044-.012-.044-.011-.045-.009-.044-.007-.045-.006-.045-.004-.045-.002-.045-.001-.045v-17l.001-.045.002-.045.004-.045.006-.045.007-.045.009-.044.011-.045.012-.044.013-.044.015-.044.017-.043.018-.044.02-.043.021-.043.023-.043.024-.043.026-.043.027-.042.029-.042.03-.042.032-.042.033-.042.034-.041.036-.041.037-.041.039-.041.04-.041.041-.04.043-.04.044-.04.046-.04.046-.039.049-.039.049-.039.051-.039.052-.038.053-.038.055-.038.056-.038.057-.037.058-.037.06-.037.061-.036.062-.036.063-.036.064-.036.066-.035.067-.035.068-.035.069-.035.07-.034.072-.034.072-.033.074-.033.151-.066.155-.064.159-.063.164-.061.167-.06.172-.059.176-.057.179-.056.184-.054.187-.053.19-.051.195-.05.198-.048.201-.046.204-.045.208-.043.211-.041.214-.04.217-.038.22-.036.223-.034.226-.032.228-.031.231-.028.234-.027.236-.024.238-.023.241-.02.243-.019.245-.016.247-.015.249-.012.251-.01.253-.008.255-.005.256-.004.258-.001.258.001zm-9.258 20.499v.01l.001.021.003.021.004.022.005.021.006.022.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.023.018.024.019.024.021.024.022.025.023.024.024.025.052.049.056.05.061.051.066.051.07.051.075.051.079.052.084.052.088.052.092.052.097.052.102.051.105.052.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.048.144.049.147.047.152.047.155.047.16.045.163.045.167.043.171.043.176.041.178.041.183.039.187.039.19.037.194.035.197.035.202.033.204.031.209.03.212.029.216.027.219.025.222.024.226.021.23.02.233.018.236.016.24.015.243.012.246.01.249.008.253.005.256.004.259.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.021.224-.024.22-.026.216-.027.212-.028.21-.031.205-.031.202-.034.198-.034.194-.036.191-.037.187-.039.183-.04.179-.04.175-.042.172-.043.168-.044.163-.045.16-.046.155-.046.152-.047.148-.048.143-.049.139-.049.136-.05.131-.05.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.053.083-.051.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.05.023-.024.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.023.01-.022.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.127l-.077.055-.08.053-.083.054-.085.053-.087.052-.09.052-.093.051-.095.05-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.045-.118.044-.12.043-.122.042-.124.042-.126.041-.128.04-.13.04-.132.038-.134.038-.135.037-.138.037-.139.035-.142.035-.143.034-.144.033-.147.032-.148.031-.15.03-.151.03-.153.029-.154.027-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.01-.179.008-.179.008-.181.006-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.006-.179-.008-.179-.008-.178-.01-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.027-.153-.029-.151-.03-.15-.03-.148-.031-.146-.032-.145-.033-.143-.034-.141-.035-.14-.035-.137-.037-.136-.037-.134-.038-.132-.038-.13-.04-.128-.04-.126-.041-.124-.042-.122-.042-.12-.044-.117-.043-.116-.045-.113-.045-.112-.046-.109-.047-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.05-.093-.052-.09-.051-.087-.052-.085-.053-.083-.054-.08-.054-.077-.054v4.127zm0-5.654v.011l.001.021.003.021.004.021.005.022.006.022.007.022.009.022.01.022.011.023.012.023.013.023.015.024.016.023.017.024.018.024.019.024.021.024.022.024.023.025.024.024.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.052.11.051.114.051.119.052.123.05.127.051.131.05.135.049.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.044.171.042.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.022.23.02.233.018.236.016.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.012.241-.015.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.048.139-.05.136-.049.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.051.051-.049.023-.025.023-.024.021-.025.02-.024.019-.024.018-.024.017-.024.015-.023.014-.023.013-.024.012-.022.01-.023.01-.023.008-.022.006-.022.006-.022.004-.021.004-.022.001-.021.001-.021v-4.139l-.077.054-.08.054-.083.054-.085.052-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.044-.118.044-.12.044-.122.042-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.035-.143.033-.144.033-.147.033-.148.031-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.009-.179.009-.179.007-.181.007-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.007-.179-.007-.179-.009-.178-.009-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.031-.146-.033-.145-.033-.143-.033-.141-.035-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.04-.126-.041-.124-.042-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.051-.093-.051-.09-.051-.087-.053-.085-.052-.083-.054-.08-.054-.077-.054v4.139zm0-5.666v.011l.001.02.003.022.004.021.005.022.006.021.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.024.018.023.019.024.021.025.022.024.023.024.024.025.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.051.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.043.171.043.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.021.23.02.233.018.236.017.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.013.241-.014.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.049.139-.049.136-.049.131-.051.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.049.023-.025.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.022.01-.023.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.153l-.077.054-.08.054-.083.053-.085.053-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.048-.105.048-.106.048-.109.046-.111.046-.114.046-.115.044-.118.044-.12.043-.122.043-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.034-.143.034-.144.033-.147.032-.148.032-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.024-.161.024-.162.023-.163.023-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.01-.178.01-.179.009-.179.007-.181.006-.182.006-.182.004-.184.003-.184.001-.185.001-.185-.001-.184-.001-.184-.003-.182-.004-.182-.006-.181-.006-.179-.007-.179-.009-.178-.01-.176-.01-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.023-.162-.023-.161-.024-.159-.024-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.032-.146-.032-.145-.033-.143-.034-.141-.034-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.041-.126-.041-.124-.041-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.048-.105-.048-.102-.048-.1-.05-.097-.049-.095-.051-.093-.051-.09-.052-.087-.052-.085-.053-.083-.053-.08-.054-.077-.054v4.153zm8.74-8.179l-.257.004-.254.005-.25.008-.247.011-.244.012-.241.014-.237.016-.233.018-.231.021-.226.022-.224.023-.22.026-.216.027-.212.028-.21.031-.205.032-.202.033-.198.034-.194.036-.191.038-.187.038-.183.04-.179.041-.175.042-.172.043-.168.043-.163.045-.16.046-.155.046-.152.048-.148.048-.143.048-.139.049-.136.05-.131.05-.126.051-.123.051-.118.051-.114.052-.11.052-.106.052-.101.052-.096.052-.092.052-.088.052-.083.052-.079.052-.074.051-.07.052-.065.051-.06.05-.056.05-.051.05-.023.025-.023.024-.021.024-.02.025-.019.024-.018.024-.017.023-.015.024-.014.023-.013.023-.012.023-.01.023-.01.022-.008.022-.006.023-.006.021-.004.022-.004.021-.001.021-.001.021.001.021.001.021.004.021.004.022.006.021.006.023.008.022.01.022.01.023.012.023.013.023.014.023.015.024.017.023.018.024.019.024.02.025.021.024.023.024.023.025.051.05.056.05.06.05.065.051.07.052.074.051.079.052.083.052.088.052.092.052.096.052.101.052.106.052.11.052.114.052.118.051.123.051.126.051.131.05.136.05.139.049.143.048.148.048.152.048.155.046.16.046.163.045.168.043.172.043.175.042.179.041.183.04.187.038.191.038.194.036.198.034.202.033.205.032.21.031.212.028.216.027.22.026.224.023.226.022.231.021.233.018.237.016.241.014.244.012.247.011.25.008.254.005.257.004.26.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.022.224-.023.22-.026.216-.027.212-.028.21-.031.205-.032.202-.033.198-.034.194-.036.191-.038.187-.038.183-.04.179-.041.175-.042.172-.043.168-.043.163-.045.16-.046.155-.046.152-.048.148-.048.143-.048.139-.049.136-.05.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.05.051-.05.023-.025.023-.024.021-.024.02-.025.019-.024.018-.024.017-.023.015-.024.014-.023.013-.023.012-.023.01-.023.01-.022.008-.022.006-.023.006-.021.004-.022.004-.021.001-.021.001-.021-.001-.021-.001-.021-.004-.021-.004-.022-.006-.021-.006-.023-.008-.022-.01-.022-.01-.023-.012-.023-.013-.023-.014-.023-.015-.024-.017-.023-.018-.024-.019-.024-.02-.025-.021-.024-.023-.024-.023-.025-.051-.05-.056-.05-.06-.05-.065-.051-.07-.052-.074-.051-.079-.052-.083-.052-.088-.052-.092-.052-.096-.052-.101-.052-.106-.052-.11-.052-.114-.052-.118-.051-.123-.051-.126-.051-.131-.05-.136-.05-.139-.049-.143-.048-.148-.048-.152-.048-.155-.046-.16-.046-.163-.045-.168-.043-.172-.043-.175-.042-.179-.041-.183-.04-.187-.038-.191-.038-.194-.036-.198-.034-.202-.033-.205-.032-.21-.031-.212-.028-.216-.027-.22-.026-.224-.023-.226-.022-.231-.021-.233-.018-.237-.016-.241-.014-.244-.012-.247-.011-.25-.008-.254-.005-.257-.004-.26-.001-.26.001z")},ULt=function(i){i.append("defs").append("symbol").attr("id","computer").attr("width","24").attr("height","24").append("path").attr("transform","scale(.5)").attr("d","M2 2v13h20v-13h-20zm18 11h-16v-9h16v9zm-10.228 6l.466-1h3.524l.467 1h-4.457zm14.228 3h-24l2-6h2.104l-1.33 4h18.45l-1.297-4h2.073l2 6zm-5-10h-14v-7h14v7z")},WLt=function(i){i.append("defs").append("symbol").attr("id","clock").attr("width","24").attr("height","24").append("path").attr("transform","scale(.5)").attr("d","M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm5.848 12.459c.202.038.202.333.001.372-1.907.361-6.045 1.111-6.547 1.111-.719 0-1.301-.582-1.301-1.301 0-.512.77-5.447 1.125-7.445.034-.192.312-.181.343.014l.985 6.238 5.394 1.011z")},KLt=function(i){i.append("defs").append("marker").attr("id","arrowhead").attr("refX",9).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",12).attr("markerHeight",12).attr("orient","auto").append("path").attr("d","M 0 0 L 10 5 L 0 10 z")},YLt=function(i){i.append("defs").append("marker").attr("id","arrowend").attr("refX",1).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",12).attr("markerHeight",12).attr("orient","auto").append("path").attr("d","M 10 0 L 0 5 L 10 10 z")},XLt=function(i){i.append("defs").append("marker").attr("id","filled-head").attr("refX",18).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L14,7 L9,1 Z")},QLt=function(i){i.append("defs").append("marker").attr("id","sequencenumber").attr("refX",15).attr("refY",15).attr("markerWidth",60).attr("markerHeight",40).attr("orient","auto").append("circle").attr("cx",15).attr("cy",15).attr("r",6)},ZLt=function(i){const f=i.append("defs").append("marker").attr("id","crosshead").attr("markerWidth",15).attr("markerHeight",8).attr("orient","auto").attr("refX",16).attr("refY",4);f.append("path").attr("fill","black").attr("stroke","#000000").style("stroke-dasharray","0, 0").attr("stroke-width","1px").attr("d","M 9,2 V 6 L16,4 Z"),f.append("path").attr("fill","none").attr("stroke","#000000").style("stroke-dasharray","0, 0").attr("stroke-width","1px").attr("d","M 0,1 L 6,7 M 6,1 L 0,7")},jOe=function(){return{x:0,y:0,fill:"#EDF2AE",stroke:"#666",width:100,anchor:"start",height:100,rx:0,ry:0}},JLt=(i,a)=>({fontFamily:i[a+"FontFamily"],fontSize:i[a+"FontSize"],fontWeight:i[a+"FontWeight"]}),w5=function(){function i(w,y,b,E,S,N,B){const R=y.append("text").attr("x",b+S/2).attr("y",E+N/2+5).style("text-anchor","middle").text(w);p(R,B)}function a(w,y,b,E,S,N,B,R){const{fontSize:j,fontFamily:$,fontWeight:V}=R,Q=w.split(Wa.lineBreakRegex);for(let oe=0;oe=this.data.widthLimit||p>=this.data.widthLimit||this.nextData.cnt>$Oe)&&(f=this.nextData.startx+a.margin+xs.nextLinePaddingX,w=this.nextData.stopy+a.margin*2,this.nextData.stopx=p=f+a.width,this.nextData.starty=this.nextData.stopy,this.nextData.stopy=y=w+a.height,this.nextData.cnt=1),a.x=f,a.y=w,this.updateVal(this.data,"startx",f,Math.min),this.updateVal(this.data,"starty",w,Math.min),this.updateVal(this.data,"stopx",p,Math.max),this.updateVal(this.data,"stopy",y,Math.max),this.updateVal(this.nextData,"startx",f,Math.min),this.updateVal(this.nextData,"starty",w,Math.min),this.updateVal(this.nextData,"stopx",p,Math.max),this.updateVal(this.nextData,"stopy",y,Math.max)}init(a){this.name="",this.data={startx:void 0,stopx:void 0,starty:void 0,stopy:void 0,widthLimit:void 0},this.nextData={startx:void 0,stopx:void 0,starty:void 0,stopy:void 0,cnt:0},Lde(a.db.getConfig())}bumpLastMargin(a){this.data.stopx+=a,this.data.stopy+=a}}const Lde=function(i){nd(xs,i),i.fontFamily&&(xs.personFontFamily=xs.systemFontFamily=xs.messageFontFamily=i.fontFamily),i.fontSize&&(xs.personFontSize=xs.systemFontSize=xs.messageFontSize=i.fontSize),i.fontWeight&&(xs.personFontWeight=xs.systemFontWeight=xs.messageFontWeight=i.fontWeight)},ZN=(i,a)=>({fontFamily:i[a+"FontFamily"],fontSize:i[a+"FontSize"],fontWeight:i[a+"FontWeight"]}),FW=i=>({fontFamily:i.boundaryFontFamily,fontSize:i.boundaryFontSize,fontWeight:i.boundaryFontWeight}),eMt=i=>({fontFamily:i.messageFontFamily,fontSize:i.messageFontSize,fontWeight:i.messageFontWeight});function Jw(i,a,f,p,w){if(!a[i].width)if(f)a[i].text=NIe(a[i].text,w,p),a[i].textLines=a[i].text.split(Wa.lineBreakRegex).length,a[i].width=w,a[i].height=ode(a[i].text,p);else{let y=a[i].text.split(Wa.lineBreakRegex);a[i].textLines=y.length;let b=0;a[i].height=0,a[i].width=0;for(const E of y)a[i].width=Math.max(s3(E,p),a[i].width),b=ode(E,p),a[i].height=a[i].height+b}}const zOe=function(i,a,f){a.x=f.data.startx,a.y=f.data.starty,a.width=f.data.stopx-f.data.startx,a.height=f.data.stopy-f.data.starty,a.label.y=xs.c4ShapeMargin-35;let p=a.wrap&&xs.wrap,w=FW(xs);w.fontSize=w.fontSize+2,w.fontWeight="bold";let y=s3(a.label.text,w);Jw("label",a,p,w,y),c3.drawBoundary(i,a,xs)},GOe=function(i,a,f,p){let w=0;for(const y of p){w=0;const b=f[y];let E=ZN(xs,b.typeC4Shape.text);switch(E.fontSize=E.fontSize-2,b.typeC4Shape.width=s3("<<"+b.typeC4Shape.text+">>",E),b.typeC4Shape.height=E.fontSize+2,b.typeC4Shape.Y=xs.c4ShapePadding,w=b.typeC4Shape.Y+b.typeC4Shape.height-4,b.image={width:0,height:0,Y:0},b.typeC4Shape.text){case"person":case"external_person":b.image.width=48,b.image.height=48,b.image.Y=w,w=b.image.Y+b.image.height;break}b.sprite&&(b.image.width=48,b.image.height=48,b.image.Y=w,w=b.image.Y+b.image.height);let S=b.wrap&&xs.wrap,N=xs.width-xs.c4ShapePadding*2,B=ZN(xs,b.typeC4Shape.text);if(B.fontSize=B.fontSize+2,B.fontWeight="bold",Jw("label",b,S,B,N),b.label.Y=w+8,w=b.label.Y+b.label.height,b.type&&b.type.text!==""){b.type.text="["+b.type.text+"]";let $=ZN(xs,b.typeC4Shape.text);Jw("type",b,S,$,N),b.type.Y=w+5,w=b.type.Y+b.type.height}else if(b.techn&&b.techn.text!==""){b.techn.text="["+b.techn.text+"]";let $=ZN(xs,b.techn.text);Jw("techn",b,S,$,N),b.techn.Y=w+5,w=b.techn.Y+b.techn.height}let R=w,j=b.label.width;if(b.descr&&b.descr.text!==""){let $=ZN(xs,b.typeC4Shape.text);Jw("descr",b,S,$,N),b.descr.Y=w+20,w=b.descr.Y+b.descr.height,j=Math.max(b.label.width,b.descr.width),R=w-b.descr.textLines*5}j=j+xs.c4ShapePadding,b.width=Math.max(b.width||xs.width,j,xs.width),b.height=Math.max(b.height||xs.height,R,xs.height),b.margin=b.margin||xs.c4ShapeMargin,i.insert(b),c3.drawC4Shape(a,b,xs)}i.bumpLastMargin(xs.c4ShapeMargin)};let Kb=class{constructor(a,f){this.x=a,this.y=f}},qOe=function(i,a){let f=i.x,p=i.y,w=a.x,y=a.y,b=f+i.width/2,E=p+i.height/2,S=Math.abs(f-w),N=Math.abs(p-y),B=N/S,R=i.height/i.width,j=null;return p==y&&fw?j=new Kb(f,E):f==w&&py&&(j=new Kb(b,p)),f>w&&p=B?j=new Kb(f,E+B*i.width/2):j=new Kb(b-S/N*i.height/2,p+i.height):f=B?j=new Kb(f+i.width,E+B*i.width/2):j=new Kb(b+S/N*i.height/2,p+i.height):fy?R>=B?j=new Kb(f+i.width,E-B*i.width/2):j=new Kb(b+i.height/2*S/N,p):f>w&&p>y&&(R>=B?j=new Kb(f,E-i.width/2*B):j=new Kb(b-i.height/2*S/N,p)),j},tMt=function(i,a){let f={x:0,y:0};f.x=a.x+a.width/2,f.y=a.y+a.height/2;let p=qOe(i,f);f.x=i.x+i.width/2,f.y=i.y+i.height/2;let w=qOe(a,f);return{startPoint:p,endPoint:w}};const nMt=function(i,a,f,p){let w=0;for(let y of a){w=w+1;let b=y.wrap&&xs.wrap,E=eMt(xs);p.db.getC4Type()==="C4Dynamic"&&(y.label.text=w+": "+y.label.text);let N=s3(y.label.text,E);Jw("label",y,b,E,N),y.techn&&y.techn.text!==""&&(N=s3(y.techn.text,E),Jw("techn",y,b,E,N)),y.descr&&y.descr.text!==""&&(N=s3(y.descr.text,E),Jw("descr",y,b,E,N));let B=f(y.from),R=f(y.to),j=tMt(B,R);y.startPoint=j.startPoint,y.endPoint=j.endPoint}c3.drawRels(i,a,xs)};function VOe(i,a,f,p,w){let y=new HOe(w);y.data.widthLimit=f.data.widthLimit/Math.min(Ade,p.length);for(let[b,E]of p.entries()){let S=0;E.image={width:0,height:0,Y:0},E.sprite&&(E.image.width=48,E.image.height=48,E.image.Y=S,S=E.image.Y+E.image.height);let N=E.wrap&&xs.wrap,B=FW(xs);if(B.fontSize=B.fontSize+2,B.fontWeight="bold",Jw("label",E,N,B,y.data.widthLimit),E.label.Y=S+8,S=E.label.Y+E.label.height,E.type&&E.type.text!==""){E.type.text="["+E.type.text+"]";let V=FW(xs);Jw("type",E,N,V,y.data.widthLimit),E.type.Y=S+5,S=E.type.Y+E.type.height}if(E.descr&&E.descr.text!==""){let V=FW(xs);V.fontSize=V.fontSize-2,Jw("descr",E,N,V,y.data.widthLimit),E.descr.Y=S+20,S=E.descr.Y+E.descr.height}if(b==0||b%Ade===0){let V=f.data.startx+xs.diagramMarginX,Q=f.data.stopy+xs.diagramMarginY+S;y.setData(V,V,Q,Q)}else{let V=y.data.stopx!==y.data.startx?y.data.stopx+xs.diagramMarginX:y.data.startx,Q=y.data.starty;y.setData(V,V,Q,Q)}y.name=E.alias;let R=w.db.getC4ShapeArray(E.alias),j=w.db.getC4ShapeKeys(E.alias);j.length>0&&GOe(y,i,R,j),a=E.alias;let $=w.db.getBoundarys(a);$.length>0&&VOe(i,a,y,$,w),E.alias!=="global"&&zOe(i,E,y),f.data.stopy=Math.max(y.data.stopy+xs.c4ShapeMargin,f.data.stopy),f.data.stopx=Math.max(y.data.stopx+xs.c4ShapeMargin,f.data.stopx),BW=Math.max(BW,f.data.stopx),RW=Math.max(RW,f.data.stopy)}}const UOe={drawPersonOrSystemArray:GOe,drawBoundary:zOe,setConf:Lde,draw:function(i,a,f,p){xs=Tt().c4;const w=Tt().securityLevel;let y;w==="sandbox"&&(y=Cr("#i"+a));const b=Cr(w==="sandbox"?y.nodes()[0].contentDocument.body:"body");let E=p.db;p.db.setWrap(xs.wrap),$Oe=E.getC4ShapeInRow(),Ade=E.getC4BoundaryInRow(),Fe.debug(`C:${JSON.stringify(xs,null,2)}`);const S=w==="sandbox"?b.select(`[id="${a}"]`):Cr(`[id="${a}"]`);c3.insertComputerIcon(S),c3.insertDatabaseIcon(S),c3.insertClockIcon(S);let N=new HOe(p);N.setData(xs.diagramMarginX,xs.diagramMarginX,xs.diagramMarginY,xs.diagramMarginY),N.data.widthLimit=screen.availWidth,BW=xs.diagramMarginX,RW=xs.diagramMarginY;const B=p.db.getTitle();let R=p.db.getBoundarys("");VOe(S,"",N,R,p),c3.insertArrowHead(S),c3.insertArrowEnd(S),c3.insertArrowCrossHead(S),c3.insertArrowFilledHead(S),nMt(S,p.db.getRels(),p.db.getC4Shape,p),N.data.stopx=BW,N.data.stopy=RW;const j=N.data;let V=j.stopy-j.starty+2*xs.diagramMarginY;const oe=j.stopx-j.startx+2*xs.diagramMarginX;B&&S.append("text").text(B).attr("x",(j.stopx-j.startx)/2-4*xs.diagramMarginX).attr("y",j.starty+xs.diagramMarginY),Vw(S,V,oe,xs.useMaxWidth);const ce=B?60:0;S.attr("viewBox",j.startx-xs.diagramMarginX+" -"+(xs.diagramMarginY+ce)+" "+oe+" "+(V+ce)),Fe.debug("models:",j)}},rMt=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:vLt,db:ROe,renderer:UOe,styles:i=>`.person { + stroke: ${i.personBorder}; + fill: ${i.personBkg}; + } +`,init:i=>{UOe.setConf(i.c4)}}},Symbol.toStringTag,{value:"Module"}));var Mde=function(){var i=function(ug,rs,Ps,Aa){for(Ps=Ps||{},Aa=ug.length;Aa--;Ps[ug[Aa]]=rs);return Ps},a=[1,9],f=[1,7],p=[1,6],w=[1,8],y=[1,20,21,22,23,38,44,46,48,52,66,67,87,88,89,90,91,92,96,106,107,110,112,113,119,120,121,122,123,124,125,126,127,128],b=[2,10],E=[1,20],S=[1,21],N=[1,22],B=[1,23],R=[1,30],j=[1,32],$=[1,33],V=[1,34],Q=[1,62],oe=[1,48],ce=[1,52],se=[1,36],ge=[1,37],ye=[1,38],ke=[1,39],Ae=[1,40],de=[1,56],ve=[1,63],te=[1,51],xe=[1,53],De=[1,55],he=[1,59],Ie=[1,60],ee=[1,41],rt=[1,42],me=[1,43],gt=[1,44],pe=[1,61],Et=[1,50],wt=[1,54],jt=[1,57],At=[1,58],Bt=[1,49],cn=[1,66],Nn=[1,71],Ot=[1,20,21,22,23,38,42,44,46,48,52,66,67,87,88,89,90,91,92,96,106,107,110,112,113,119,120,121,122,123,124,125,126,127,128],oi=[1,75],kt=[1,74],Dt=[1,76],vt=[20,21,23,81,82],Nt=[1,99],ze=[1,104],Xe=[1,107],Lt=[1,108],Ge=[1,101],Bn=[1,106],Oe=[1,109],Ri=[1,102],tn=[1,114],hi=[1,113],Sr=[1,103],Zn=[1,105],Xn=[1,110],ir=[1,111],Hn=[1,112],tr=[1,115],ha=[20,21,22,23,81,82],Zs=[20,21,22,23,53,81,82],ns=[20,21,22,23,40,52,53,55,57,59,61,63,65,66,67,69,71,73,74,76,81,82,92,96,106,107,110,112,113,123,124,125,126,127,128],Hi=[20,21,23],Js=[20,21,23,52,66,67,81,82,92,96,106,107,110,112,113,123,124,125,126,127,128],Pc=[1,12,20,21,22,23,24,38,42,44,46,48,52,66,67,87,88,89,90,91,92,96,106,107,110,112,113,119,120,121,122,123,124,125,126,127,128],Ga=[52,66,67,92,96,106,107,110,112,113,123,124,125,126,127,128],ws=[1,150],Oi=[1,158],Er=[1,159],br=[1,160],Dr=[1,161],Vn=[1,145],qi=[1,146],yn=[1,141],Bc=[1,142],jn=[1,153],Ms=[1,154],Pa=[1,155],Ta=[1,156],_a=[1,157],ka=[1,162],Qi=[1,163],ea=[1,148],Ca=[1,151],Sa=[1,147],Ka=[1,144],cg=[20,21,22,23,38,42,44,46,48,52,66,67,87,88,89,90,91,92,96,106,107,110,112,113,119,120,121,122,123,124,125,126,127,128],Gc=[1,166],Dh=[20,21,22,23,26,52,66,67,92,106,107,110,112,113,123,124,125,126,127,128],Es=[20,21,22,23,24,26,38,40,41,42,52,56,58,60,62,64,66,67,68,70,72,73,75,77,81,82,87,88,89,90,91,92,93,96,106,107,110,112,113,114,115,123,124,125,126,127,128],lp=[12,21,22,24],sd=[22,107],sh=[1,251],Ai=[1,246],nn=[1,247],Tr=[1,255],ai=[1,252],Ns=[1,249],mc=[1,248],yu=[1,250],Mo=[1,253],ku=[1,254],Ih=[1,256],qf=[1,274],lx=[20,21,23,107],ad=[20,21,22,23,66,67,87,103,106,107,110,111,112,113,114],b3={trace:function(){},yy:{},symbols_:{error:2,start:3,mermaidDoc:4,directive:5,openDirective:6,typeDirective:7,closeDirective:8,separator:9,":":10,argDirective:11,open_directive:12,type_directive:13,arg_directive:14,close_directive:15,graphConfig:16,document:17,line:18,statement:19,SEMI:20,NEWLINE:21,SPACE:22,EOF:23,GRAPH:24,NODIR:25,DIR:26,FirstStmtSeperator:27,ending:28,endToken:29,spaceList:30,spaceListNewline:31,verticeStatement:32,styleStatement:33,linkStyleStatement:34,classDefStatement:35,classStatement:36,clickStatement:37,subgraph:38,text:39,SQS:40,SQE:41,end:42,direction:43,acc_title:44,acc_title_value:45,acc_descr:46,acc_descr_value:47,acc_descr_multiline_value:48,link:49,node:50,vertex:51,AMP:52,STYLE_SEPARATOR:53,idString:54,DOUBLECIRCLESTART:55,DOUBLECIRCLEEND:56,PS:57,PE:58,"(-":59,"-)":60,STADIUMSTART:61,STADIUMEND:62,SUBROUTINESTART:63,SUBROUTINEEND:64,VERTEX_WITH_PROPS_START:65,ALPHA:66,COLON:67,PIPE:68,CYLINDERSTART:69,CYLINDEREND:70,DIAMOND_START:71,DIAMOND_STOP:72,TAGEND:73,TRAPSTART:74,TRAPEND:75,INVTRAPSTART:76,INVTRAPEND:77,linkStatement:78,arrowText:79,TESTSTR:80,START_LINK:81,LINK:82,textToken:83,STR:84,MD_STR:85,keywords:86,STYLE:87,LINKSTYLE:88,CLASSDEF:89,CLASS:90,CLICK:91,DOWN:92,UP:93,textNoTags:94,textNoTagsToken:95,DEFAULT:96,stylesOpt:97,alphaNum:98,CALLBACKNAME:99,CALLBACKARGS:100,HREF:101,LINK_TARGET:102,HEX:103,numList:104,INTERPOLATE:105,NUM:106,COMMA:107,style:108,styleComponent:109,MINUS:110,UNIT:111,BRKT:112,DOT:113,PCT:114,TAGSTART:115,alphaNumToken:116,idStringToken:117,alphaNumStatement:118,direction_tb:119,direction_bt:120,direction_rl:121,direction_lr:122,PUNCTUATION:123,UNICODE_TEXT:124,PLUS:125,EQUALS:126,MULT:127,UNDERSCORE:128,graphCodeTokens:129,ARROW_CROSS:130,ARROW_POINT:131,ARROW_CIRCLE:132,ARROW_OPEN:133,QUOTE:134,$accept:0,$end:1},terminals_:{2:"error",10:":",12:"open_directive",13:"type_directive",14:"arg_directive",15:"close_directive",20:"SEMI",21:"NEWLINE",22:"SPACE",23:"EOF",24:"GRAPH",25:"NODIR",26:"DIR",38:"subgraph",40:"SQS",41:"SQE",42:"end",44:"acc_title",45:"acc_title_value",46:"acc_descr",47:"acc_descr_value",48:"acc_descr_multiline_value",52:"AMP",53:"STYLE_SEPARATOR",55:"DOUBLECIRCLESTART",56:"DOUBLECIRCLEEND",57:"PS",58:"PE",59:"(-",60:"-)",61:"STADIUMSTART",62:"STADIUMEND",63:"SUBROUTINESTART",64:"SUBROUTINEEND",65:"VERTEX_WITH_PROPS_START",66:"ALPHA",67:"COLON",68:"PIPE",69:"CYLINDERSTART",70:"CYLINDEREND",71:"DIAMOND_START",72:"DIAMOND_STOP",73:"TAGEND",74:"TRAPSTART",75:"TRAPEND",76:"INVTRAPSTART",77:"INVTRAPEND",80:"TESTSTR",81:"START_LINK",82:"LINK",84:"STR",85:"MD_STR",87:"STYLE",88:"LINKSTYLE",89:"CLASSDEF",90:"CLASS",91:"CLICK",92:"DOWN",93:"UP",96:"DEFAULT",99:"CALLBACKNAME",100:"CALLBACKARGS",101:"HREF",102:"LINK_TARGET",103:"HEX",105:"INTERPOLATE",106:"NUM",107:"COMMA",110:"MINUS",111:"UNIT",112:"BRKT",113:"DOT",114:"PCT",115:"TAGSTART",119:"direction_tb",120:"direction_bt",121:"direction_rl",122:"direction_lr",123:"PUNCTUATION",124:"UNICODE_TEXT",125:"PLUS",126:"EQUALS",127:"MULT",128:"UNDERSCORE",130:"ARROW_CROSS",131:"ARROW_POINT",132:"ARROW_CIRCLE",133:"ARROW_OPEN",134:"QUOTE"},productions_:[0,[3,1],[3,2],[5,4],[5,6],[6,1],[7,1],[11,1],[8,1],[4,2],[17,0],[17,2],[18,1],[18,1],[18,1],[18,1],[18,1],[16,2],[16,2],[16,2],[16,3],[28,2],[28,1],[29,1],[29,1],[29,1],[27,1],[27,1],[27,2],[31,2],[31,2],[31,1],[31,1],[30,2],[30,1],[19,2],[19,2],[19,2],[19,2],[19,2],[19,2],[19,9],[19,6],[19,4],[19,1],[19,2],[19,2],[19,1],[9,1],[9,1],[9,1],[32,3],[32,4],[32,2],[32,1],[50,1],[50,5],[50,3],[51,4],[51,4],[51,6],[51,4],[51,4],[51,4],[51,8],[51,4],[51,4],[51,4],[51,6],[51,4],[51,4],[51,4],[51,4],[51,4],[51,1],[49,2],[49,3],[49,3],[49,1],[49,3],[78,1],[79,3],[39,1],[39,2],[39,1],[39,1],[86,1],[86,1],[86,1],[86,1],[86,1],[86,1],[86,1],[86,1],[86,1],[86,1],[86,1],[94,1],[94,2],[35,5],[35,5],[36,5],[37,2],[37,4],[37,3],[37,5],[37,2],[37,4],[37,4],[37,6],[37,2],[37,4],[37,2],[37,4],[37,4],[37,6],[33,5],[33,5],[34,5],[34,5],[34,9],[34,9],[34,7],[34,7],[104,1],[104,3],[97,1],[97,3],[108,1],[108,2],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[83,1],[83,1],[83,1],[83,1],[83,1],[83,1],[95,1],[95,1],[95,1],[95,1],[54,1],[54,2],[98,1],[98,2],[118,1],[118,1],[118,1],[118,1],[43,1],[43,1],[43,1],[43,1],[116,1],[116,1],[116,1],[116,1],[116,1],[116,1],[116,1],[116,1],[116,1],[116,1],[116,1],[116,1],[116,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1],[129,1]],performAction:function(rs,Ps,Aa,pi,Rc,_t,hp){var Gt=_t.length-1;switch(Rc){case 5:pi.parseDirective("%%{","open_directive");break;case 6:pi.parseDirective(_t[Gt],"type_directive");break;case 7:_t[Gt]=_t[Gt].trim().replace(/'/g,'"'),pi.parseDirective(_t[Gt],"arg_directive");break;case 8:pi.parseDirective("}%%","close_directive","flowchart");break;case 10:this.$=[];break;case 11:(!Array.isArray(_t[Gt])||_t[Gt].length>0)&&_t[Gt-1].push(_t[Gt]),this.$=_t[Gt-1];break;case 12:case 97:case 153:case 155:case 156:this.$=_t[Gt];break;case 19:pi.setDirection("TB"),this.$="TB";break;case 20:pi.setDirection(_t[Gt-1]),this.$=_t[Gt-1];break;case 35:this.$=_t[Gt-1].nodes;break;case 36:case 37:case 38:case 39:case 40:this.$=[];break;case 41:this.$=pi.addSubGraph(_t[Gt-6],_t[Gt-1],_t[Gt-4]);break;case 42:this.$=pi.addSubGraph(_t[Gt-3],_t[Gt-1],_t[Gt-3]);break;case 43:this.$=pi.addSubGraph(void 0,_t[Gt-1],void 0);break;case 45:this.$=_t[Gt].trim(),pi.setAccTitle(this.$);break;case 46:case 47:this.$=_t[Gt].trim(),pi.setAccDescription(this.$);break;case 51:pi.addLink(_t[Gt-2].stmt,_t[Gt],_t[Gt-1]),this.$={stmt:_t[Gt],nodes:_t[Gt].concat(_t[Gt-2].nodes)};break;case 52:pi.addLink(_t[Gt-3].stmt,_t[Gt-1],_t[Gt-2]),this.$={stmt:_t[Gt-1],nodes:_t[Gt-1].concat(_t[Gt-3].nodes)};break;case 53:this.$={stmt:_t[Gt-1],nodes:_t[Gt-1]};break;case 54:this.$={stmt:_t[Gt],nodes:_t[Gt]};break;case 55:this.$=[_t[Gt]];break;case 56:this.$=_t[Gt-4].concat(_t[Gt]);break;case 57:this.$=[_t[Gt-2]],pi.setClass(_t[Gt-2],_t[Gt]);break;case 58:this.$=_t[Gt-3],pi.addVertex(_t[Gt-3],_t[Gt-1],"square");break;case 59:this.$=_t[Gt-3],pi.addVertex(_t[Gt-3],_t[Gt-1],"doublecircle");break;case 60:this.$=_t[Gt-5],pi.addVertex(_t[Gt-5],_t[Gt-2],"circle");break;case 61:this.$=_t[Gt-3],pi.addVertex(_t[Gt-3],_t[Gt-1],"ellipse");break;case 62:this.$=_t[Gt-3],pi.addVertex(_t[Gt-3],_t[Gt-1],"stadium");break;case 63:this.$=_t[Gt-3],pi.addVertex(_t[Gt-3],_t[Gt-1],"subroutine");break;case 64:this.$=_t[Gt-7],pi.addVertex(_t[Gt-7],_t[Gt-1],"rect",void 0,void 0,void 0,Object.fromEntries([[_t[Gt-5],_t[Gt-3]]]));break;case 65:this.$=_t[Gt-3],pi.addVertex(_t[Gt-3],_t[Gt-1],"cylinder");break;case 66:this.$=_t[Gt-3],pi.addVertex(_t[Gt-3],_t[Gt-1],"round");break;case 67:this.$=_t[Gt-3],pi.addVertex(_t[Gt-3],_t[Gt-1],"diamond");break;case 68:this.$=_t[Gt-5],pi.addVertex(_t[Gt-5],_t[Gt-2],"hexagon");break;case 69:this.$=_t[Gt-3],pi.addVertex(_t[Gt-3],_t[Gt-1],"odd");break;case 70:this.$=_t[Gt-3],pi.addVertex(_t[Gt-3],_t[Gt-1],"trapezoid");break;case 71:this.$=_t[Gt-3],pi.addVertex(_t[Gt-3],_t[Gt-1],"inv_trapezoid");break;case 72:this.$=_t[Gt-3],pi.addVertex(_t[Gt-3],_t[Gt-1],"lean_right");break;case 73:this.$=_t[Gt-3],pi.addVertex(_t[Gt-3],_t[Gt-1],"lean_left");break;case 74:this.$=_t[Gt],pi.addVertex(_t[Gt]);break;case 75:_t[Gt-1].text=_t[Gt],this.$=_t[Gt-1];break;case 76:case 77:_t[Gt-2].text=_t[Gt-1],this.$=_t[Gt-2];break;case 78:this.$=_t[Gt];break;case 79:var ff=pi.destructLink(_t[Gt],_t[Gt-2]);this.$={type:ff.type,stroke:ff.stroke,length:ff.length,text:_t[Gt-1]};break;case 80:var ff=pi.destructLink(_t[Gt]);this.$={type:ff.type,stroke:ff.stroke,length:ff.length};break;case 81:this.$=_t[Gt-1];break;case 82:this.$={text:_t[Gt],type:"text"};break;case 83:this.$={text:_t[Gt-1].text+""+_t[Gt],type:_t[Gt-1].type};break;case 84:this.$={text:_t[Gt],type:"text"};break;case 85:this.$={text:_t[Gt],type:"markdown"};break;case 98:case 154:this.$=_t[Gt-1]+""+_t[Gt];break;case 99:case 100:this.$=_t[Gt-4],pi.addClass(_t[Gt-2],_t[Gt]);break;case 101:this.$=_t[Gt-4],pi.setClass(_t[Gt-2],_t[Gt]);break;case 102:case 110:this.$=_t[Gt-1],pi.setClickEvent(_t[Gt-1],_t[Gt]);break;case 103:case 111:this.$=_t[Gt-3],pi.setClickEvent(_t[Gt-3],_t[Gt-2]),pi.setTooltip(_t[Gt-3],_t[Gt]);break;case 104:this.$=_t[Gt-2],pi.setClickEvent(_t[Gt-2],_t[Gt-1],_t[Gt]);break;case 105:this.$=_t[Gt-4],pi.setClickEvent(_t[Gt-4],_t[Gt-3],_t[Gt-2]),pi.setTooltip(_t[Gt-4],_t[Gt]);break;case 106:case 112:this.$=_t[Gt-1],pi.setLink(_t[Gt-1],_t[Gt]);break;case 107:case 113:this.$=_t[Gt-3],pi.setLink(_t[Gt-3],_t[Gt-2]),pi.setTooltip(_t[Gt-3],_t[Gt]);break;case 108:case 114:this.$=_t[Gt-3],pi.setLink(_t[Gt-3],_t[Gt-2],_t[Gt]);break;case 109:case 115:this.$=_t[Gt-5],pi.setLink(_t[Gt-5],_t[Gt-4],_t[Gt]),pi.setTooltip(_t[Gt-5],_t[Gt-2]);break;case 116:this.$=_t[Gt-4],pi.addVertex(_t[Gt-2],void 0,void 0,_t[Gt]);break;case 117:case 119:this.$=_t[Gt-4],pi.updateLink(_t[Gt-2],_t[Gt]);break;case 118:this.$=_t[Gt-4],pi.updateLink([_t[Gt-2]],_t[Gt]);break;case 120:this.$=_t[Gt-8],pi.updateLinkInterpolate([_t[Gt-6]],_t[Gt-2]),pi.updateLink([_t[Gt-6]],_t[Gt]);break;case 121:this.$=_t[Gt-8],pi.updateLinkInterpolate(_t[Gt-6],_t[Gt-2]),pi.updateLink(_t[Gt-6],_t[Gt]);break;case 122:this.$=_t[Gt-6],pi.updateLinkInterpolate([_t[Gt-4]],_t[Gt]);break;case 123:this.$=_t[Gt-6],pi.updateLinkInterpolate(_t[Gt-4],_t[Gt]);break;case 124:case 126:this.$=[_t[Gt]];break;case 125:case 127:_t[Gt-2].push(_t[Gt]),this.$=_t[Gt-2];break;case 129:this.$=_t[Gt-1]+_t[Gt];break;case 151:this.$=_t[Gt];break;case 152:this.$=_t[Gt-1]+""+_t[Gt];break;case 157:this.$="v";break;case 158:this.$="-";break;case 159:this.$={stmt:"dir",value:"TB"};break;case 160:this.$={stmt:"dir",value:"BT"};break;case 161:this.$={stmt:"dir",value:"RL"};break;case 162:this.$={stmt:"dir",value:"LR"};break}},table:[{3:1,4:2,5:3,6:5,12:a,16:4,21:f,22:p,24:w},{1:[3]},{1:[2,1]},{3:10,4:2,5:3,6:5,12:a,16:4,21:f,22:p,24:w},i(y,b,{17:11}),{7:12,13:[1,13]},{16:14,21:f,22:p,24:w},{16:15,21:f,22:p,24:w},{25:[1,16],26:[1,17]},{13:[2,5]},{1:[2,2]},{1:[2,9],18:18,19:19,20:E,21:S,22:N,23:B,32:24,33:25,34:26,35:27,36:28,37:29,38:R,43:31,44:j,46:$,48:V,50:35,51:45,52:Q,54:46,66:oe,67:ce,87:se,88:ge,89:ye,90:ke,91:Ae,92:de,96:ve,106:te,107:xe,110:De,112:he,113:Ie,117:47,119:ee,120:rt,121:me,122:gt,123:pe,124:Et,125:wt,126:jt,127:At,128:Bt},{8:64,10:[1,65],15:cn},i([10,15],[2,6]),i(y,[2,17]),i(y,[2,18]),i(y,[2,19]),{20:[1,68],21:[1,69],22:Nn,27:67,30:70},i(Ot,[2,11]),i(Ot,[2,12]),i(Ot,[2,13]),i(Ot,[2,14]),i(Ot,[2,15]),i(Ot,[2,16]),{9:72,20:oi,21:kt,23:Dt,49:73,78:77,81:[1,78],82:[1,79]},{9:80,20:oi,21:kt,23:Dt},{9:81,20:oi,21:kt,23:Dt},{9:82,20:oi,21:kt,23:Dt},{9:83,20:oi,21:kt,23:Dt},{9:84,20:oi,21:kt,23:Dt},{9:86,20:oi,21:kt,22:[1,85],23:Dt},i(Ot,[2,44]),{45:[1,87]},{47:[1,88]},i(Ot,[2,47]),i(vt,[2,54],{30:89,22:Nn}),{22:[1,90]},{22:[1,91]},{22:[1,92]},{22:[1,93]},{26:Nt,52:ze,66:Xe,67:Lt,84:[1,97],92:Ge,98:96,99:[1,94],101:[1,95],106:Bn,107:Oe,110:Ri,112:tn,113:hi,116:100,118:98,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},i(Ot,[2,159]),i(Ot,[2,160]),i(Ot,[2,161]),i(Ot,[2,162]),i(ha,[2,55],{53:[1,116]}),i(Zs,[2,74],{117:129,40:[1,117],52:Q,55:[1,118],57:[1,119],59:[1,120],61:[1,121],63:[1,122],65:[1,123],66:oe,67:ce,69:[1,124],71:[1,125],73:[1,126],74:[1,127],76:[1,128],92:de,96:ve,106:te,107:xe,110:De,112:he,113:Ie,123:pe,124:Et,125:wt,126:jt,127:At,128:Bt}),i(ns,[2,151]),i(ns,[2,176]),i(ns,[2,177]),i(ns,[2,178]),i(ns,[2,179]),i(ns,[2,180]),i(ns,[2,181]),i(ns,[2,182]),i(ns,[2,183]),i(ns,[2,184]),i(ns,[2,185]),i(ns,[2,186]),i(ns,[2,187]),i(ns,[2,188]),i(ns,[2,189]),i(ns,[2,190]),i(ns,[2,191]),{9:130,20:oi,21:kt,23:Dt},{11:131,14:[1,132]},i(Hi,[2,8]),i(y,[2,20]),i(y,[2,26]),i(y,[2,27]),{21:[1,133]},i(Js,[2,34],{30:134,22:Nn}),i(Ot,[2,35]),{50:135,51:45,52:Q,54:46,66:oe,67:ce,92:de,96:ve,106:te,107:xe,110:De,112:he,113:Ie,117:47,123:pe,124:Et,125:wt,126:jt,127:At,128:Bt},i(Pc,[2,48]),i(Pc,[2,49]),i(Pc,[2,50]),i(Ga,[2,78],{79:136,68:[1,138],80:[1,137]}),{22:ws,24:Oi,26:Er,38:br,39:139,42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:140,84:yn,85:Bc,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},i([52,66,67,68,80,92,96,106,107,110,112,113,123,124,125,126,127,128],[2,80]),i(Ot,[2,36]),i(Ot,[2,37]),i(Ot,[2,38]),i(Ot,[2,39]),i(Ot,[2,40]),{22:ws,24:Oi,26:Er,38:br,39:164,42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:140,84:yn,85:Bc,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},i(cg,b,{17:165}),i(Ot,[2,45]),i(Ot,[2,46]),i(vt,[2,53],{52:Gc}),{26:Nt,52:ze,66:Xe,67:Lt,92:Ge,98:167,103:[1,168],106:Bn,107:Oe,110:Ri,112:tn,113:hi,116:100,118:98,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{96:[1,169],104:170,106:[1,171]},{26:Nt,52:ze,66:Xe,67:Lt,92:Ge,96:[1,172],98:173,106:Bn,107:Oe,110:Ri,112:tn,113:hi,116:100,118:98,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{26:Nt,52:ze,66:Xe,67:Lt,92:Ge,98:174,106:Bn,107:Oe,110:Ri,112:tn,113:hi,116:100,118:98,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},i(Hi,[2,102],{22:[1,175],100:[1,176]}),i(Hi,[2,106],{22:[1,177]}),i(Hi,[2,110],{116:100,118:179,22:[1,178],26:Nt,52:ze,66:Xe,67:Lt,92:Ge,106:Bn,107:Oe,110:Ri,112:tn,113:hi,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr}),i(Hi,[2,112],{22:[1,180]}),i(Dh,[2,153]),i(Dh,[2,155]),i(Dh,[2,156]),i(Dh,[2,157]),i(Dh,[2,158]),i(Es,[2,163]),i(Es,[2,164]),i(Es,[2,165]),i(Es,[2,166]),i(Es,[2,167]),i(Es,[2,168]),i(Es,[2,169]),i(Es,[2,170]),i(Es,[2,171]),i(Es,[2,172]),i(Es,[2,173]),i(Es,[2,174]),i(Es,[2,175]),{52:Q,54:181,66:oe,67:ce,92:de,96:ve,106:te,107:xe,110:De,112:he,113:Ie,117:47,123:pe,124:Et,125:wt,126:jt,127:At,128:Bt},{22:ws,24:Oi,26:Er,38:br,39:182,42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:140,84:yn,85:Bc,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,39:183,42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:140,84:yn,85:Bc,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,39:185,42:Dr,52:ze,57:[1,184],66:Xe,67:Lt,73:Vn,81:qi,83:140,84:yn,85:Bc,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,39:186,42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:140,84:yn,85:Bc,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,39:187,42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:140,84:yn,85:Bc,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,39:188,42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:140,84:yn,85:Bc,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{66:[1,189]},{22:ws,24:Oi,26:Er,38:br,39:190,42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:140,84:yn,85:Bc,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,39:191,42:Dr,52:ze,66:Xe,67:Lt,71:[1,192],73:Vn,81:qi,83:140,84:yn,85:Bc,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,39:193,42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:140,84:yn,85:Bc,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,39:194,42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:140,84:yn,85:Bc,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,39:195,42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:140,84:yn,85:Bc,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},i(ns,[2,152]),i(lp,[2,3]),{8:196,15:cn},{15:[2,7]},i(y,[2,28]),i(Js,[2,33]),i(vt,[2,51],{30:197,22:Nn}),i(Ga,[2,75],{22:[1,198]}),{22:[1,199]},{22:ws,24:Oi,26:Er,38:br,39:200,42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:140,84:yn,85:Bc,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,82:[1,201],83:202,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},i(Es,[2,82]),i(Es,[2,84]),i(Es,[2,85]),i(Es,[2,141]),i(Es,[2,142]),i(Es,[2,143]),i(Es,[2,144]),i(Es,[2,145]),i(Es,[2,146]),i(Es,[2,147]),i(Es,[2,148]),i(Es,[2,149]),i(Es,[2,150]),i(Es,[2,86]),i(Es,[2,87]),i(Es,[2,88]),i(Es,[2,89]),i(Es,[2,90]),i(Es,[2,91]),i(Es,[2,92]),i(Es,[2,93]),i(Es,[2,94]),i(Es,[2,95]),i(Es,[2,96]),{9:204,20:oi,21:kt,22:ws,23:Dt,24:Oi,26:Er,38:br,40:[1,203],42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:202,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{18:18,19:19,20:E,21:S,22:N,23:B,32:24,33:25,34:26,35:27,36:28,37:29,38:R,42:[1,205],43:31,44:j,46:$,48:V,50:35,51:45,52:Q,54:46,66:oe,67:ce,87:se,88:ge,89:ye,90:ke,91:Ae,92:de,96:ve,106:te,107:xe,110:De,112:he,113:Ie,117:47,119:ee,120:rt,121:me,122:gt,123:pe,124:Et,125:wt,126:jt,127:At,128:Bt},{22:Nn,30:206},{22:[1,207],26:Nt,52:ze,66:Xe,67:Lt,92:Ge,106:Bn,107:Oe,110:Ri,112:tn,113:hi,116:100,118:179,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:[1,208]},{22:[1,209]},{22:[1,210],107:[1,211]},i(sd,[2,124]),{22:[1,212]},{22:[1,213],26:Nt,52:ze,66:Xe,67:Lt,92:Ge,106:Bn,107:Oe,110:Ri,112:tn,113:hi,116:100,118:179,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:[1,214],26:Nt,52:ze,66:Xe,67:Lt,92:Ge,106:Bn,107:Oe,110:Ri,112:tn,113:hi,116:100,118:179,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{84:[1,215]},i(Hi,[2,104],{22:[1,216]}),{84:[1,217],102:[1,218]},{84:[1,219]},i(Dh,[2,154]),{84:[1,220],102:[1,221]},i(ha,[2,57],{117:129,52:Q,66:oe,67:ce,92:de,96:ve,106:te,107:xe,110:De,112:he,113:Ie,123:pe,124:Et,125:wt,126:jt,127:At,128:Bt}),{22:ws,24:Oi,26:Er,38:br,41:[1,222],42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:202,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,42:Dr,52:ze,56:[1,223],66:Xe,67:Lt,73:Vn,81:qi,83:202,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,39:224,42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:140,84:yn,85:Bc,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,42:Dr,52:ze,58:[1,225],66:Xe,67:Lt,73:Vn,81:qi,83:202,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,42:Dr,52:ze,60:[1,226],66:Xe,67:Lt,73:Vn,81:qi,83:202,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,42:Dr,52:ze,62:[1,227],66:Xe,67:Lt,73:Vn,81:qi,83:202,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,42:Dr,52:ze,64:[1,228],66:Xe,67:Lt,73:Vn,81:qi,83:202,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{67:[1,229]},{22:ws,24:Oi,26:Er,38:br,42:Dr,52:ze,66:Xe,67:Lt,70:[1,230],73:Vn,81:qi,83:202,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,42:Dr,52:ze,66:Xe,67:Lt,72:[1,231],73:Vn,81:qi,83:202,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,39:232,42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:140,84:yn,85:Bc,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,41:[1,233],42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:202,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,42:Dr,52:ze,66:Xe,67:Lt,73:Vn,75:[1,234],77:[1,235],81:qi,83:202,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{22:ws,24:Oi,26:Er,38:br,42:Dr,52:ze,66:Xe,67:Lt,73:Vn,75:[1,237],77:[1,236],81:qi,83:202,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{9:238,20:oi,21:kt,23:Dt},i(vt,[2,52],{52:Gc}),i(Ga,[2,77]),i(Ga,[2,76]),{22:ws,24:Oi,26:Er,38:br,42:Dr,52:ze,66:Xe,67:Lt,68:[1,239],73:Vn,81:qi,83:202,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},i(Ga,[2,79]),i(Es,[2,83]),{22:ws,24:Oi,26:Er,38:br,39:240,42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:140,84:yn,85:Bc,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},i(cg,b,{17:241}),i(Ot,[2,43]),{51:242,52:Q,54:46,66:oe,67:ce,92:de,96:ve,106:te,107:xe,110:De,112:he,113:Ie,117:47,123:pe,124:Et,125:wt,126:jt,127:At,128:Bt},{22:sh,66:Ai,67:nn,87:Tr,97:243,103:ai,106:Ns,108:244,109:245,110:mc,111:yu,112:Mo,113:ku,114:Ih},{22:sh,66:Ai,67:nn,87:Tr,97:257,103:ai,106:Ns,108:244,109:245,110:mc,111:yu,112:Mo,113:ku,114:Ih},{22:sh,66:Ai,67:nn,87:Tr,97:258,103:ai,105:[1,259],106:Ns,108:244,109:245,110:mc,111:yu,112:Mo,113:ku,114:Ih},{22:sh,66:Ai,67:nn,87:Tr,97:260,103:ai,105:[1,261],106:Ns,108:244,109:245,110:mc,111:yu,112:Mo,113:ku,114:Ih},{106:[1,262]},{22:sh,66:Ai,67:nn,87:Tr,97:263,103:ai,106:Ns,108:244,109:245,110:mc,111:yu,112:Mo,113:ku,114:Ih},{22:sh,66:Ai,67:nn,87:Tr,97:264,103:ai,106:Ns,108:244,109:245,110:mc,111:yu,112:Mo,113:ku,114:Ih},{26:Nt,52:ze,66:Xe,67:Lt,92:Ge,98:265,106:Bn,107:Oe,110:Ri,112:tn,113:hi,116:100,118:98,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},i(Hi,[2,103]),{84:[1,266]},i(Hi,[2,107],{22:[1,267]}),i(Hi,[2,108]),i(Hi,[2,111]),i(Hi,[2,113],{22:[1,268]}),i(Hi,[2,114]),i(Zs,[2,58]),i(Zs,[2,59]),{22:ws,24:Oi,26:Er,38:br,42:Dr,52:ze,58:[1,269],66:Xe,67:Lt,73:Vn,81:qi,83:202,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},i(Zs,[2,66]),i(Zs,[2,61]),i(Zs,[2,62]),i(Zs,[2,63]),{66:[1,270]},i(Zs,[2,65]),i(Zs,[2,67]),{22:ws,24:Oi,26:Er,38:br,42:Dr,52:ze,66:Xe,67:Lt,72:[1,271],73:Vn,81:qi,83:202,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},i(Zs,[2,69]),i(Zs,[2,70]),i(Zs,[2,72]),i(Zs,[2,71]),i(Zs,[2,73]),i(lp,[2,4]),i([22,52,66,67,92,96,106,107,110,112,113,123,124,125,126,127,128],[2,81]),{22:ws,24:Oi,26:Er,38:br,41:[1,272],42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:202,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{18:18,19:19,20:E,21:S,22:N,23:B,32:24,33:25,34:26,35:27,36:28,37:29,38:R,42:[1,273],43:31,44:j,46:$,48:V,50:35,51:45,52:Q,54:46,66:oe,67:ce,87:se,88:ge,89:ye,90:ke,91:Ae,92:de,96:ve,106:te,107:xe,110:De,112:he,113:Ie,117:47,119:ee,120:rt,121:me,122:gt,123:pe,124:Et,125:wt,126:jt,127:At,128:Bt},i(ha,[2,56]),i(Hi,[2,116],{107:qf}),i(lx,[2,126],{109:275,22:sh,66:Ai,67:nn,87:Tr,103:ai,106:Ns,110:mc,111:yu,112:Mo,113:ku,114:Ih}),i(ad,[2,128]),i(ad,[2,130]),i(ad,[2,131]),i(ad,[2,132]),i(ad,[2,133]),i(ad,[2,134]),i(ad,[2,135]),i(ad,[2,136]),i(ad,[2,137]),i(ad,[2,138]),i(ad,[2,139]),i(ad,[2,140]),i(Hi,[2,117],{107:qf}),i(Hi,[2,118],{107:qf}),{22:[1,276]},i(Hi,[2,119],{107:qf}),{22:[1,277]},i(sd,[2,125]),i(Hi,[2,99],{107:qf}),i(Hi,[2,100],{107:qf}),i(Hi,[2,101],{116:100,118:179,26:Nt,52:ze,66:Xe,67:Lt,92:Ge,106:Bn,107:Oe,110:Ri,112:tn,113:hi,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr}),i(Hi,[2,105]),{102:[1,278]},{102:[1,279]},{58:[1,280]},{68:[1,281]},{72:[1,282]},{9:283,20:oi,21:kt,23:Dt},i(Ot,[2,42]),{22:sh,66:Ai,67:nn,87:Tr,103:ai,106:Ns,108:284,109:245,110:mc,111:yu,112:Mo,113:ku,114:Ih},i(ad,[2,129]),{26:Nt,52:ze,66:Xe,67:Lt,92:Ge,98:285,106:Bn,107:Oe,110:Ri,112:tn,113:hi,116:100,118:98,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{26:Nt,52:ze,66:Xe,67:Lt,92:Ge,98:286,106:Bn,107:Oe,110:Ri,112:tn,113:hi,116:100,118:98,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},i(Hi,[2,109]),i(Hi,[2,115]),i(Zs,[2,60]),{22:ws,24:Oi,26:Er,38:br,39:287,42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:140,84:yn,85:Bc,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},i(Zs,[2,68]),i(cg,b,{17:288}),i(lx,[2,127],{109:275,22:sh,66:Ai,67:nn,87:Tr,103:ai,106:Ns,110:mc,111:yu,112:Mo,113:ku,114:Ih}),i(Hi,[2,122],{116:100,118:179,22:[1,289],26:Nt,52:ze,66:Xe,67:Lt,92:Ge,106:Bn,107:Oe,110:Ri,112:tn,113:hi,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr}),i(Hi,[2,123],{116:100,118:179,22:[1,290],26:Nt,52:ze,66:Xe,67:Lt,92:Ge,106:Bn,107:Oe,110:Ri,112:tn,113:hi,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr}),{22:ws,24:Oi,26:Er,38:br,41:[1,291],42:Dr,52:ze,66:Xe,67:Lt,73:Vn,81:qi,83:202,86:152,87:jn,88:Ms,89:Pa,90:Ta,91:_a,92:ka,93:Qi,95:143,96:ea,106:Bn,107:Oe,110:Ca,112:tn,113:hi,114:Sa,115:Ka,116:149,123:Sr,124:Zn,125:Xn,126:ir,127:Hn,128:tr},{18:18,19:19,20:E,21:S,22:N,23:B,32:24,33:25,34:26,35:27,36:28,37:29,38:R,42:[1,292],43:31,44:j,46:$,48:V,50:35,51:45,52:Q,54:46,66:oe,67:ce,87:se,88:ge,89:ye,90:ke,91:Ae,92:de,96:ve,106:te,107:xe,110:De,112:he,113:Ie,117:47,119:ee,120:rt,121:me,122:gt,123:pe,124:Et,125:wt,126:jt,127:At,128:Bt},{22:sh,66:Ai,67:nn,87:Tr,97:293,103:ai,106:Ns,108:244,109:245,110:mc,111:yu,112:Mo,113:ku,114:Ih},{22:sh,66:Ai,67:nn,87:Tr,97:294,103:ai,106:Ns,108:244,109:245,110:mc,111:yu,112:Mo,113:ku,114:Ih},i(Zs,[2,64]),i(Ot,[2,41]),i(Hi,[2,120],{107:qf}),i(Hi,[2,121],{107:qf})],defaultActions:{2:[2,1],9:[2,5],10:[2,2],132:[2,7]},parseError:function(rs,Ps){if(Ps.recoverable)this.trace(rs);else{var Aa=new Error(rs);throw Aa.hash=Ps,Aa}},parse:function(rs){var Ps=this,Aa=[0],pi=[],Rc=[null],_t=[],hp=this.table,Gt="",ff=0,sm=0,m9=2,fp=1,N5=_t.slice.call(arguments,1),ah=Object.create(this.lexer),od={yy:{}};for(var P5 in this.yy)Object.prototype.hasOwnProperty.call(this.yy,P5)&&(od.yy[P5]=this.yy[P5]);ah.setInput(rs,od.yy),od.yy.lexer=ah,od.yy.parser=this,typeof ah.yylloc>"u"&&(ah.yylloc={});var B5=ah.yylloc;_t.push(B5);var y9=ah.options&&ah.options.ranges;typeof od.yy.parseError=="function"?this.parseError=od.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function vL(){var oh;return oh=pi.pop()||ah.lex()||fp,typeof oh!="number"&&(oh instanceof Array&&(pi=oh,oh=pi.pop()),oh=Ps.symbols_[oh]||oh),oh}for(var v1,dp,cd,am,ev={},om,yc,hx,Vo;;){if(dp=Aa[Aa.length-1],this.defaultActions[dp]?cd=this.defaultActions[dp]:((v1===null||typeof v1>"u")&&(v1=vL()),cd=hp[dp]&&hp[dp][v1]),typeof cd>"u"||!cd.length||!cd[0]){var fx="";Vo=[];for(om in hp[dp])this.terminals_[om]&&om>m9&&Vo.push("'"+this.terminals_[om]+"'");ah.showPosition?fx="Parse error on line "+(ff+1)+`: +`+ah.showPosition()+` +Expecting `+Vo.join(", ")+", got '"+(this.terminals_[v1]||v1)+"'":fx="Parse error on line "+(ff+1)+": Unexpected "+(v1==fp?"end of input":"'"+(this.terminals_[v1]||v1)+"'"),this.parseError(fx,{text:ah.match,token:this.terminals_[v1]||v1,line:ah.yylineno,loc:B5,expected:Vo})}if(cd[0]instanceof Array&&cd.length>1)throw new Error("Parse Error: multiple actions possible at state: "+dp+", token: "+v1);switch(cd[0]){case 1:Aa.push(v1),Rc.push(ah.yytext),_t.push(ah.yylloc),Aa.push(cd[1]),v1=null,sm=ah.yyleng,Gt=ah.yytext,ff=ah.yylineno,B5=ah.yylloc;break;case 2:if(yc=this.productions_[cd[1]][1],ev.$=Rc[Rc.length-yc],ev._$={first_line:_t[_t.length-(yc||1)].first_line,last_line:_t[_t.length-1].last_line,first_column:_t[_t.length-(yc||1)].first_column,last_column:_t[_t.length-1].last_column},y9&&(ev._$.range=[_t[_t.length-(yc||1)].range[0],_t[_t.length-1].range[1]]),am=this.performAction.apply(ev,[Gt,sm,ff,od.yy,cd[1],Rc,_t].concat(N5)),typeof am<"u")return am;yc&&(Aa=Aa.slice(0,-1*yc*2),Rc=Rc.slice(0,-1*yc),_t=_t.slice(0,-1*yc)),Aa.push(this.productions_[cd[1]][0]),Rc.push(ev.$),_t.push(ev._$),hx=hp[Aa[Aa.length-2]][Aa[Aa.length-1]],Aa.push(hx);break;case 3:return!0}}return!0}},bL=function(){var ug={EOF:1,parseError:function(Ps,Aa){if(this.yy.parser)this.yy.parser.parseError(Ps,Aa);else throw new Error(Ps)},setInput:function(rs,Ps){return this.yy=Ps||this.yy||{},this._input=rs,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var rs=this._input[0];this.yytext+=rs,this.yyleng++,this.offset++,this.match+=rs,this.matched+=rs;var Ps=rs.match(/(?:\r\n?|\n).*/g);return Ps?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),rs},unput:function(rs){var Ps=rs.length,Aa=rs.split(/(?:\r\n?|\n)/g);this._input=rs+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-Ps),this.offset-=Ps;var pi=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),Aa.length-1&&(this.yylineno-=Aa.length-1);var Rc=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:Aa?(Aa.length===pi.length?this.yylloc.first_column:0)+pi[pi.length-Aa.length].length-Aa[0].length:this.yylloc.first_column-Ps},this.options.ranges&&(this.yylloc.range=[Rc[0],Rc[0]+this.yyleng-Ps]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(rs){this.unput(this.match.slice(rs))},pastInput:function(){var rs=this.matched.substr(0,this.matched.length-this.match.length);return(rs.length>20?"...":"")+rs.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var rs=this.match;return rs.length<20&&(rs+=this._input.substr(0,20-rs.length)),(rs.substr(0,20)+(rs.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var rs=this.pastInput(),Ps=new Array(rs.length+1).join("-");return rs+this.upcomingInput()+` +`+Ps+"^"},test_match:function(rs,Ps){var Aa,pi,Rc;if(this.options.backtrack_lexer&&(Rc={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(Rc.yylloc.range=this.yylloc.range.slice(0))),pi=rs[0].match(/(?:\r\n?|\n).*/g),pi&&(this.yylineno+=pi.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:pi?pi[pi.length-1].length-pi[pi.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+rs[0].length},this.yytext+=rs[0],this.match+=rs[0],this.matches=rs,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(rs[0].length),this.matched+=rs[0],Aa=this.performAction.call(this,this.yy,this,Ps,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),Aa)return Aa;if(this._backtrack){for(var _t in Rc)this[_t]=Rc[_t];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var rs,Ps,Aa,pi;this._more||(this.yytext="",this.match="");for(var Rc=this._currentRules(),_t=0;_tPs[0].length)){if(Ps=Aa,pi=_t,this.options.backtrack_lexer){if(rs=this.test_match(Aa,Rc[_t]),rs!==!1)return rs;if(this._backtrack){Ps=!1;continue}else return!1}else if(!this.options.flex)break}return Ps?(rs=this.test_match(Ps,Rc[pi]),rs!==!1?rs:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var Ps=this.next();return Ps||this.lex()},begin:function(Ps){this.conditionStack.push(Ps)},popState:function(){var Ps=this.conditionStack.length-1;return Ps>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(Ps){return Ps=this.conditionStack.length-1-Math.abs(Ps||0),Ps>=0?this.conditionStack[Ps]:"INITIAL"},pushState:function(Ps){this.begin(Ps)},stateStackSize:function(){return this.conditionStack.length},options:{},performAction:function(Ps,Aa,pi,Rc){switch(pi){case 0:return this.begin("open_directive"),12;case 1:return this.begin("type_directive"),13;case 2:return this.popState(),this.begin("arg_directive"),10;case 3:return this.popState(),this.popState(),15;case 4:return 14;case 5:return this.begin("acc_title"),44;case 6:return this.popState(),"acc_title_value";case 7:return this.begin("acc_descr"),46;case 8:return this.popState(),"acc_descr_value";case 9:this.begin("acc_descr_multiline");break;case 10:this.popState();break;case 11:return"acc_descr_multiline_value";case 12:this.begin("md_string");break;case 13:return"MD_STR";case 14:this.popState();break;case 15:this.begin("string");break;case 16:this.popState();break;case 17:return"STR";case 18:return 87;case 19:return 96;case 20:return 88;case 21:return 105;case 22:return 89;case 23:return 90;case 24:this.begin("href");break;case 25:this.popState();break;case 26:return 101;case 27:this.begin("callbackname");break;case 28:this.popState();break;case 29:this.popState(),this.begin("callbackargs");break;case 30:return 99;case 31:this.popState();break;case 32:return 100;case 33:this.begin("click");break;case 34:this.popState();break;case 35:return 91;case 36:return Ps.lex.firstGraph()&&this.begin("dir"),24;case 37:return Ps.lex.firstGraph()&&this.begin("dir"),24;case 38:return Ps.lex.firstGraph()&&this.begin("dir"),24;case 39:return 38;case 40:return 42;case 41:return 102;case 42:return 102;case 43:return 102;case 44:return 102;case 45:return this.popState(),25;case 46:return this.popState(),26;case 47:return this.popState(),26;case 48:return this.popState(),26;case 49:return this.popState(),26;case 50:return this.popState(),26;case 51:return this.popState(),26;case 52:return this.popState(),26;case 53:return this.popState(),26;case 54:return this.popState(),26;case 55:return this.popState(),26;case 56:return 119;case 57:return 120;case 58:return 121;case 59:return 122;case 60:return 106;case 61:return 112;case 62:return 53;case 63:return 67;case 64:return 52;case 65:return 20;case 66:return 107;case 67:return 127;case 68:return 82;case 69:return 82;case 70:return 82;case 71:return 82;case 72:return 81;case 73:return 81;case 74:return 81;case 75:return 59;case 76:return 60;case 77:return 61;case 78:return 62;case 79:return 63;case 80:return 64;case 81:return 65;case 82:return 69;case 83:return 70;case 84:return 55;case 85:return 56;case 86:return 110;case 87:return 113;case 88:return 128;case 89:return 125;case 90:return 114;case 91:return 126;case 92:return 126;case 93:return 115;case 94:return 73;case 95:return 93;case 96:return"SEP";case 97:return 92;case 98:return 66;case 99:return 75;case 100:return 74;case 101:return 77;case 102:return 76;case 103:return 123;case 104:return 124;case 105:return 68;case 106:return 57;case 107:return 58;case 108:return 40;case 109:return 41;case 110:return 71;case 111:return 72;case 112:return 134;case 113:return 21;case 114:return 22;case 115:return 23}},rules:[/^(?:%%\{)/,/^(?:((?:(?!\}%%)[^:.])*))/,/^(?::)/,/^(?:\}%%)/,/^(?:((?:(?!\}%%).|\n)*))/,/^(?:accTitle\s*:\s*)/,/^(?:(?!\n||)*[^\n]*)/,/^(?:accDescr\s*:\s*)/,/^(?:(?!\n||)*[^\n]*)/,/^(?:accDescr\s*\{\s*)/,/^(?:[\}])/,/^(?:[^\}]*)/,/^(?:["][`])/,/^(?:[^`"]+)/,/^(?:[`]["])/,/^(?:["])/,/^(?:["])/,/^(?:[^"]*)/,/^(?:style\b)/,/^(?:default\b)/,/^(?:linkStyle\b)/,/^(?:interpolate\b)/,/^(?:classDef\b)/,/^(?:class\b)/,/^(?:href[\s]+["])/,/^(?:["])/,/^(?:[^"]*)/,/^(?:call[\s]+)/,/^(?:\([\s]*\))/,/^(?:\()/,/^(?:[^(]*)/,/^(?:\))/,/^(?:[^)]*)/,/^(?:click[\s]+)/,/^(?:[\s\n])/,/^(?:[^\s\n]*)/,/^(?:flowchart-elk\b)/,/^(?:graph\b)/,/^(?:flowchart\b)/,/^(?:subgraph\b)/,/^(?:end\b\s*)/,/^(?:_self\b)/,/^(?:_blank\b)/,/^(?:_parent\b)/,/^(?:_top\b)/,/^(?:(\r?\n)*\s*\n)/,/^(?:\s*LR\b)/,/^(?:\s*RL\b)/,/^(?:\s*TB\b)/,/^(?:\s*BT\b)/,/^(?:\s*TD\b)/,/^(?:\s*BR\b)/,/^(?:\s*<)/,/^(?:\s*>)/,/^(?:\s*\^)/,/^(?:\s*v\b)/,/^(?:.*direction\s+TB[^\n]*)/,/^(?:.*direction\s+BT[^\n]*)/,/^(?:.*direction\s+RL[^\n]*)/,/^(?:.*direction\s+LR[^\n]*)/,/^(?:[0-9]+)/,/^(?:#)/,/^(?::::)/,/^(?::)/,/^(?:&)/,/^(?:;)/,/^(?:,)/,/^(?:\*)/,/^(?:\s*[xo<]?--+[-xo>]\s*)/,/^(?:\s*[xo<]?==+[=xo>]\s*)/,/^(?:\s*[xo<]?-?\.+-[xo>]?\s*)/,/^(?:\s*~~[\~]+\s*)/,/^(?:\s*[xo<]?--\s*)/,/^(?:\s*[xo<]?==\s*)/,/^(?:\s*[xo<]?-\.\s*)/,/^(?:\(-)/,/^(?:-\))/,/^(?:\(\[)/,/^(?:\]\))/,/^(?:\[\[)/,/^(?:\]\])/,/^(?:\[\|)/,/^(?:\[\()/,/^(?:\)\])/,/^(?:\(\(\()/,/^(?:\)\)\))/,/^(?:-)/,/^(?:\.)/,/^(?:[\_])/,/^(?:\+)/,/^(?:%)/,/^(?:=)/,/^(?:=)/,/^(?:<)/,/^(?:>)/,/^(?:\^)/,/^(?:\\\|)/,/^(?:v\b)/,/^(?:[A-Za-z]+)/,/^(?:\\\])/,/^(?:\[\/)/,/^(?:\/\])/,/^(?:\[\\)/,/^(?:[!"#$%&'*+,-.`?\\_/])/,/^(?:[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|[\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA]|[\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE]|[\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA]|[\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0]|[\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977]|[\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2]|[\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A]|[\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39]|[\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8]|[\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C]|[\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C]|[\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99]|[\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0]|[\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D]|[\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3]|[\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10]|[\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1]|[\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81]|[\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3]|[\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6]|[\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A]|[\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081]|[\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D]|[\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0]|[\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310]|[\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C]|[\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711]|[\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7]|[\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C]|[\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16]|[\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF]|[\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC]|[\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D]|[\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D]|[\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3]|[\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F]|[\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128]|[\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184]|[\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3]|[\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6]|[\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE]|[\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C]|[\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D]|[\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC]|[\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B]|[\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788]|[\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805]|[\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB]|[\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28]|[\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5]|[\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4]|[\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E]|[\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D]|[\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36]|[\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D]|[\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC]|[\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]|[\uFFD2-\uFFD7\uFFDA-\uFFDC])/,/^(?:\|)/,/^(?:\()/,/^(?:\))/,/^(?:\[)/,/^(?:\])/,/^(?:\{)/,/^(?:\})/,/^(?:")/,/^(?:(\r?\n)+)/,/^(?:\s)/,/^(?:$)/],conditions:{close_directive:{rules:[],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},open_directive:{rules:[1],inclusive:!1},callbackargs:{rules:[31,32],inclusive:!1},callbackname:{rules:[28,29,30],inclusive:!1},href:{rules:[25,26],inclusive:!1},click:{rules:[34,35],inclusive:!1},vertex:{rules:[],inclusive:!1},dir:{rules:[45,46,47,48,49,50,51,52,53,54,55],inclusive:!1},acc_descr_multiline:{rules:[10,11],inclusive:!1},acc_descr:{rules:[8],inclusive:!1},acc_title:{rules:[6],inclusive:!1},md_string:{rules:[13,14],inclusive:!1},string:{rules:[16,17],inclusive:!1},INITIAL:{rules:[0,5,7,9,12,15,18,19,20,21,22,23,24,27,33,36,37,38,39,40,41,42,43,44,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115],inclusive:!0}}};return ug}();b3.lexer=bL;function im(){this.yy={}}return im.prototype=b3,b3.Parser=im,new im}();Mde.parser=Mde;const Dde=Mde,iMt="flowchart-";let WOe=0,Ide=Tt(),_l={},r9=[],YA={},m5=[],jW={},Ode={},$W=0,Nde=!0,Yb,HW,zW=[];const GW=i=>Wa.sanitizeText(i,Ide),KOe=function(i,a,f){rd.parseDirective(this,i,a,f)},JN=function(i){const a=Object.keys(_l);for(const f of a)if(_l[f].id===i)return _l[f].domId;return i},YOe=function(i,a,f,p,w,y,b={}){let E,S=i;S!==void 0&&S.trim().length!==0&&(_l[S]===void 0&&(_l[S]={id:S,labelType:"text",domId:iMt+S+"-"+WOe,styles:[],classes:[]}),WOe++,a!==void 0?(Ide=Tt(),E=GW(a.text.trim()),_l[S].labelType=a.type,E[0]==='"'&&E[E.length-1]==='"'&&(E=E.substring(1,E.length-1)),_l[S].text=E):_l[S].text===void 0&&(_l[S].text=i),f!==void 0&&(_l[S].type=f),p!=null&&p.forEach(function(N){_l[S].styles.push(N)}),w!=null&&w.forEach(function(N){_l[S].classes.push(N)}),y!==void 0&&(_l[S].dir=y),_l[S].props===void 0?_l[S].props=b:b!==void 0&&Object.assign(_l[S].props,b))},XOe=function(i,a,f){const y={start:i,end:a,type:void 0,text:"",labelType:"text"};Fe.info("abc78 Got edge...",y);const b=f.text;b!==void 0&&(y.text=GW(b.text.trim()),y.text[0]==='"'&&y.text[y.text.length-1]==='"'&&(y.text=y.text.substring(1,y.text.length-1)),y.labelType=b.type),f!==void 0&&(y.type=f.type,y.stroke=f.stroke,y.length=f.length),r9.push(y)},QOe=function(i,a,f){Fe.info("addLink (abc78)",i,a,f);let p,w;for(p=0;p/)&&(Yb="LR"),Yb.match(/.*v/)&&(Yb="TB"),Yb==="TD"&&(Yb="TB")},qW=function(i,a){i.split(",").forEach(function(f){let p=f;_l[p]!==void 0&&_l[p].classes.push(a),jW[p]!==void 0&&jW[p].classes.push(a)})},sMt=function(i,a){i.split(",").forEach(function(f){a!==void 0&&(Ode[HW==="gen-1"?JN(f):f]=GW(a))})},aMt=function(i,a,f){let p=JN(i);if(Tt().securityLevel!=="loose"||a===void 0)return;let w=[];if(typeof f=="string"){w=f.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);for(let y=0;y")),w.classed("hover",!0)}).on("mouseout",function(){a.transition().duration(500).style("opacity",0),Cr(this).classed("hover",!1)})};zW.push(lNe);const hNe=function(i="gen-1"){_l={},YA={},r9=[],zW=[lNe],m5=[],jW={},$W=0,Ode=[],Nde=!0,HW=i,rp()},fNe=i=>{HW=i||"gen-2"},dNe=function(){return"fill:#ffa;stroke: #f66; stroke-width: 3px; stroke-dasharray: 5, 5;fill:#ffa;stroke: #666;"},gNe=function(i,a,f){let p=i.text.trim(),w=f.text;i===f&&f.text.match(/\s/)&&(p=void 0);function y(B){const R={boolean:{},number:{},string:{}},j=[];let $;return{nodeList:B.filter(function(Q){const oe=typeof Q;return Q.stmt&&Q.stmt==="dir"?($=Q.value,!1):Q.trim()===""?!1:oe in R?R[oe].hasOwnProperty(Q)?!1:R[oe][Q]=!0:j.includes(Q)?!1:j.push(Q)}),dir:$}}let b=[];const{nodeList:E,dir:S}=y(b.concat.apply(b,a));if(b=E,HW==="gen-1")for(let B=0;B2e3)return;if(pNe[eP]=a,m5[a].id===i)return{result:!0,count:0};let p=0,w=1;for(;p=0){const b=bNe(i,y);if(b.result)return{result:!0,count:w+b.count};w=w+b.count}p=p+1}return{result:!1,count:w}},vNe=function(i){return pNe[i]},wNe=function(){eP=-1,m5.length>0&&bNe("none",m5.length-1)},mNe=function(){return m5},yNe=()=>Nde?(Nde=!1,!0):!1,cMt=i=>{let a=i.trim(),f="arrow_open";switch(a[0]){case"<":f="arrow_point",a=a.slice(1);break;case"x":f="arrow_cross",a=a.slice(1);break;case"o":f="arrow_circle",a=a.slice(1);break}let p="normal";return a.includes("=")&&(p="thick"),a.includes(".")&&(p="dotted"),{type:f,stroke:p}},uMt=(i,a)=>{const f=a.length;let p=0;for(let w=0;w{const a=i.trim();let f=a.slice(0,-1),p="arrow_open";switch(a.slice(-1)){case"x":p="arrow_cross",a[0]==="x"&&(p="double_"+p,f=f.slice(1));break;case">":p="arrow_point",a[0]==="<"&&(p="double_"+p,f=f.slice(1));break;case"o":p="arrow_circle",a[0]==="o"&&(p="double_"+p,f=f.slice(1));break}let w="normal",y=f.length-1;f[0]==="="&&(w="thick"),f[0]==="~"&&(w="invisible");let b=uMt(".",f);return b&&(w="dotted",y=b),{type:p,stroke:w,length:y}},kNe=(i,a)=>{const f=lMt(i);let p;if(a){if(p=cMt(a),p.stroke!==f.stroke)return{type:"INVALID",stroke:"INVALID"};if(p.type==="arrow_open")p.type=f.type;else{if(p.type!==f.type)return{type:"INVALID",stroke:"INVALID"};p.type="double_"+p.type}return p.type==="double_arrow"&&(p.type="double_arrow_point"),p.length=f.length,p}return f},xNe=(i,a)=>{let f=!1;return i.forEach(p=>{p.nodes.indexOf(a)>=0&&(f=!0)}),f},ENe=(i,a)=>{const f=[];return i.nodes.forEach((p,w)=>{xNe(a,p)||f.push(i.nodes[w])}),{nodes:f}},TNe={firstGraph:yNe},ix={parseDirective:KOe,defaultConfig:()=>OA.flowchart,setAccTitle:ip,getAccTitle:L2,getAccDescription:D2,setAccDescription:M2,addVertex:YOe,lookUpDomId:JN,addLink:QOe,updateLinkInterpolate:ZOe,updateLink:JOe,addClass:eNe,setDirection:tNe,setClass:qW,setTooltip:sMt,getTooltip:rNe,setClickEvent:iNe,setLink:nNe,bindFunctions:sNe,getDirection:aNe,getVertices:oNe,getEdges:cNe,getClasses:uNe,clear:hNe,setGen:fNe,defaultStyle:dNe,addSubGraph:gNe,getDepthFirstPos:vNe,indexNodes:wNe,getSubGraphs:mNe,destructLink:kNe,lex:TNe,exists:xNe,makeUniq:ENe,setDiagramTitle:Uw,getDiagramTitle:Ww},hMt=Object.freeze(Object.defineProperty({__proto__:null,addClass:eNe,addLink:QOe,addSingleLink:XOe,addSubGraph:gNe,addVertex:YOe,bindFunctions:sNe,clear:hNe,default:ix,defaultStyle:dNe,destructLink:kNe,firstGraph:yNe,getClasses:uNe,getDepthFirstPos:vNe,getDirection:aNe,getEdges:cNe,getSubGraphs:mNe,getTooltip:rNe,getVertices:oNe,indexNodes:wNe,lex:TNe,lookUpDomId:JN,parseDirective:KOe,setClass:qW,setClickEvent:iNe,setDirection:tNe,setGen:fNe,setLink:nNe,updateLink:JOe,updateLinkInterpolate:ZOe},Symbol.toStringTag,{value:"Module"}));var fMt="[object Symbol]";function i9(i){return typeof i=="symbol"||a3(i)&&QE(i)==fMt}function XA(i,a){for(var f=-1,p=i==null?0:i.length,w=Array(p);++f0){if(++a>=LMt)return arguments[0]}else a=0;return i.apply(void 0,arguments)}}function QA(i){return function(){return i}}var OMt=function(){try{var i=JE(Object,"defineProperty");return i({},"",{}),i}catch{}}();const UW=OMt;var NMt=UW?function(i,a){return UW(i,"toString",{configurable:!0,enumerable:!1,value:QA(a),writable:!0})}:s9,PMt=IMt(NMt);const INe=PMt;function ONe(i,a){for(var f=-1,p=i==null?0:i.length;++f-1}var $Mt=9007199254740991,HMt=/^(?:0|[1-9]\d*)$/;function WW(i,a){var f=typeof i;return a=a??$Mt,!!a&&(f=="number"||f!="symbol"&&HMt.test(i))&&i>-1&&i%1==0&&i1?f[w-1]:void 0,b=w>2?f[2]:void 0;for(y=i.length>3&&typeof y=="function"?(w--,y):void 0,b&&nP(f[0],f[1],b)&&(y=w<3?void 0:y,w=1),a=Object(a);++p0&&f(E)?a>1?JW(E,a-1,f,p,w):Bde(w,E):p||(w[w.length]=E)}return w}function ZA(i){var a=i==null?0:i.length;return a?JW(i,1):[]}function uDt(i){return INe(BNe(i,void 0,ZA),i+"")}var lDt=fOe(Object.getPrototypeOf,Object);const Rde=lDt;var hDt="[object Object]",fDt=Function.prototype,dDt=Object.prototype,$Ne=fDt.toString,gDt=dDt.hasOwnProperty,pDt=$Ne.call(Object);function HNe(i){if(!a3(i)||QE(i)!=hDt)return!1;var a=Rde(i);if(a===null)return!0;var f=gDt.call(a,"constructor")&&a.constructor;return typeof f=="function"&&f instanceof f&&$Ne.call(f)==pDt}function bDt(i,a,f,p){var w=-1,y=i==null?0:i.length;for(p&&y&&(f=i[++w]);++wE))return!1;var N=y.get(i),B=y.get(a);if(N&&B)return N==a&&B==i;var R=-1,j=!0,$=f&ZIt?new sP:void 0;for(y.set(i,a),y.set(a,i);++R2?a[2]:void 0;for(w&&nP(a[0],a[1],w)&&(p=1);++f-1?w[y?a[b]:b]:void 0}}var VOt=Math.max;function UOt(i,a,f){var p=i==null?0:i.length;if(!p)return-1;var w=f==null?0:TMt(f);return w<0&&(w=VOt(p+w,0)),NNe(i,sx(a),w)}var WOt=qOt(UOt);const Yde=WOt;function kPe(i,a){var f=-1,p=tx(i)?Array(i.length):[];return nK(i,function(w,y,b){p[++f]=a(w,y,b)}),p}function Hf(i,a){var f=$f(i)?XA:kPe;return f(i,sx(a))}function KOt(i,a){return i==null?i:qde(i,Kde(a),a9)}function YOt(i,a){return i&&Vde(i,Kde(a))}function XOt(i,a){return i>a}var QOt=Object.prototype,ZOt=QOt.hasOwnProperty;function JOt(i,a){return i!=null&&ZOt.call(i,a)}function Ja(i,a){return i!=null&&pPe(i,a,JOt)}function eNt(i,a){return XA(a,function(f){return i[f]})}function k5(i){return i==null?[]:eNt(i,N2(i))}function cf(i){return i===void 0}function xPe(i,a){return ia||y&&b&&S&&!E&&!N||p&&b&&S||!f&&S||!w)return 1;if(!p&&!y&&!N&&i=E)return S;var N=f[p];return S*(N=="desc"?-1:1)}}return i.index-a.index}function oNt(i,a,f){a.length?a=XA(a,function(y){return $f(y)?function(b){return ZW(b,y.length===1?y[0]:y)}:y}):a=[s9];var p=-1;a=XA(a,MW(sx));var w=kPe(i,function(y,b,E){var S=XA(a,function(N){return N(y)});return{criteria:S,index:++p,value:y}});return iNt(w,function(y,b){return aNt(y,b,f)})}function cNt(i,a){return rNt(i,a,function(f,p){return bPe(i,p)})}var uNt=uDt(function(i,a){return i==null?{}:cNt(i,a)});const oP=uNt;var lNt=Math.ceil,hNt=Math.max;function fNt(i,a,f,p){for(var w=-1,y=hNt(lNt((a-i)/(f||1)),0),b=Array(y);y--;)b[p?y:++w]=i,i+=f;return b}function dNt(i){return function(a,f,p){return p&&typeof p!="number"&&nP(a,f,p)&&(f=p=void 0),a=VW(a),f===void 0?(f=a,a=0):f=VW(f),p=p===void 0?a1&&nP(i,a[0],a[1])?a=[]:f>2&&nP(a[0],a[1],a[2])&&(a=[a[0]]),oNt(i,JW(a,1),[])});const uP=bNt;var vNt=1/0,wNt=GA&&1/Hde(new GA([,-0]))[1]==vNt?function(i){return new GA(i)}:AMt;const mNt=wNt;var yNt=200;function kNt(i,a,f){var p=-1,w=jMt,y=i.length,b=!0,E=[],S=E;if(f)b=!1,w=zOt;else if(y>=yNt){var N=a?null:mNt(i);if(N)return Hde(N);b=!1,w=oPe,S=new sP}else S=a?[]:E;e:for(;++p1?w.setNode(y,f):w.setNode(y)}),this}setNode(a,f){return Ja(this._nodes,a)?(arguments.length>1&&(this._nodes[a]=f),this):(this._nodes[a]=arguments.length>1?f:this._defaultNodeLabelFn(a),this._isCompound&&(this._parent[a]=u9,this._children[a]={},this._children[u9][a]=!0),this._in[a]={},this._preds[a]={},this._out[a]={},this._sucs[a]={},++this._nodeCount,this)}node(a){return this._nodes[a]}hasNode(a){return Ja(this._nodes,a)}removeNode(a){var f=this;if(Ja(this._nodes,a)){var p=function(w){f.removeEdge(f._edgeObjs[w])};delete this._nodes[a],this._isCompound&&(this._removeFromParentsChildList(a),delete this._parent[a],lr(this.children(a),function(w){f.setParent(w)}),delete this._children[a]),lr(N2(this._in[a]),p),delete this._in[a],delete this._preds[a],lr(N2(this._out[a]),p),delete this._out[a],delete this._sucs[a],--this._nodeCount}return this}setParent(a,f){if(!this._isCompound)throw new Error("Cannot set parent in a non-compound graph");if(cf(f))f=u9;else{f+="";for(var p=f;!cf(p);p=this.parent(p))if(p===a)throw new Error("Setting "+f+" as parent of "+a+" would create a cycle");this.setNode(f)}return this.setNode(a),this._removeFromParentsChildList(a),this._parent[a]=f,this._children[f][a]=!0,this}_removeFromParentsChildList(a){delete this._children[this._parent[a]][a]}parent(a){if(this._isCompound){var f=this._parent[a];if(f!==u9)return f}}children(a){if(cf(a)&&(a=u9),this._isCompound){var f=this._children[a];if(f)return N2(f)}else{if(a===u9)return this.nodes();if(this.hasNode(a))return[]}}predecessors(a){var f=this._preds[a];if(f)return N2(f)}successors(a){var f=this._sucs[a];if(f)return N2(f)}neighbors(a){var f=this.predecessors(a);if(f)return ENt(f,this.successors(a))}isLeaf(a){var f;return this.isDirected()?f=this.successors(a):f=this.neighbors(a),f.length===0}filterNodes(a){var f=new this.constructor({directed:this._isDirected,multigraph:this._isMultigraph,compound:this._isCompound});f.setGraph(this.graph());var p=this;lr(this._nodes,function(b,E){a(E)&&f.setNode(E,b)}),lr(this._edgeObjs,function(b){f.hasNode(b.v)&&f.hasNode(b.w)&&f.setEdge(b,p.edge(b))});var w={};function y(b){var E=p.parent(b);return E===void 0||f.hasNode(E)?(w[b]=E,E):E in w?w[E]:y(E)}return this._isCompound&&lr(f.nodes(),function(b){f.setParent(b,y(b))}),f}setDefaultEdgeLabel(a){return BA(a)||(a=QA(a)),this._defaultEdgeLabelFn=a,this}edgeCount(){return this._edgeCount}edges(){return k5(this._edgeObjs)}setPath(a,f){var p=this,w=arguments;return cP(a,function(y,b){return w.length>1?p.setEdge(y,b,f):p.setEdge(y,b),b}),this}setEdge(){var a,f,p,w,y=!1,b=arguments[0];typeof b=="object"&&b!==null&&"v"in b?(a=b.v,f=b.w,p=b.name,arguments.length===2&&(w=arguments[1],y=!0)):(a=b,f=arguments[1],p=arguments[3],arguments.length>2&&(w=arguments[2],y=!0)),a=""+a,f=""+f,cf(p)||(p=""+p);var E=lP(this._isDirected,a,f,p);if(Ja(this._edgeLabels,E))return y&&(this._edgeLabels[E]=w),this;if(!cf(p)&&!this._isMultigraph)throw new Error("Cannot set a named edge when isMultigraph = false");this.setNode(a),this.setNode(f),this._edgeLabels[E]=y?w:this._defaultEdgeLabelFn(a,f,p);var S=ANt(this._isDirected,a,f,p);return a=S.v,f=S.w,Object.freeze(S),this._edgeObjs[E]=S,TPe(this._preds[f],a),TPe(this._sucs[a],f),this._in[f][E]=S,this._out[a][E]=S,this._edgeCount++,this}edge(a,f,p){var w=arguments.length===1?Jde(this._isDirected,arguments[0]):lP(this._isDirected,a,f,p);return this._edgeLabels[w]}hasEdge(a,f,p){var w=arguments.length===1?Jde(this._isDirected,arguments[0]):lP(this._isDirected,a,f,p);return Ja(this._edgeLabels,w)}removeEdge(a,f,p){var w=arguments.length===1?Jde(this._isDirected,arguments[0]):lP(this._isDirected,a,f,p),y=this._edgeObjs[w];return y&&(a=y.v,f=y.w,delete this._edgeLabels[w],delete this._edgeObjs[w],_Pe(this._preds[f],a),_Pe(this._sucs[a],f),delete this._in[f][w],delete this._out[a][w],this._edgeCount--),this}inEdges(a,f){var p=this._in[a];if(p){var w=k5(p);return f?y5(w,function(y){return y.v===f}):w}}outEdges(a,f){var p=this._out[a];if(p){var w=k5(p);return f?y5(w,function(y){return y.w===f}):w}}nodeEdges(a,f){var p=this.inEdges(a,f);if(p)return p.concat(this.outEdges(a,f))}}zf.prototype._nodeCount=0,zf.prototype._edgeCount=0;function TPe(i,a){i[a]?i[a]++:i[a]=1}function _Pe(i,a){--i[a]||delete i[a]}function lP(i,a,f,p){var w=""+a,y=""+f;if(!i&&w>y){var b=w;w=y,y=b}return w+EPe+y+EPe+(cf(p)?SNt:p)}function ANt(i,a,f,p){var w=""+a,y=""+f;if(!i&&w>y){var b=w;w=y,y=b}var E={v:w,w:y};return p&&(E.name=p),E}function Jde(i,a){return lP(i,a.v,a.w,a.name)}class LNt{constructor(){var a={};a._next=a._prev=a,this._sentinel=a}dequeue(){var a=this._sentinel,f=a._prev;if(f!==a)return CPe(f),f}enqueue(a){var f=this._sentinel;a._prev&&a._next&&CPe(a),a._next=f._next,f._next._prev=a,f._next=a,a._prev=f}toString(){for(var a=[],f=this._sentinel,p=f._prev;p!==f;)a.push(JSON.stringify(p,MNt)),p=p._prev;return"["+a.join(", ")+"]"}}function CPe(i){i._prev._next=i._next,i._next._prev=i._prev,delete i._next,delete i._prev}function MNt(i,a){if(i!=="_next"&&i!=="_prev")return a}var DNt=QA(1);function INt(i,a){if(i.nodeCount()<=1)return[];var f=NNt(i,a||DNt),p=ONt(f.graph,f.buckets,f.zeroIdx);return ZA(Hf(p,function(w){return i.outEdges(w.v,w.w)}))}function ONt(i,a,f){for(var p=[],w=a[a.length-1],y=a[0],b;i.nodeCount();){for(;b=y.dequeue();)e0e(i,a,f,b);for(;b=w.dequeue();)e0e(i,a,f,b);if(i.nodeCount()){for(var E=a.length-2;E>0;--E)if(b=a[E].dequeue(),b){p=p.concat(e0e(i,a,f,b,!0));break}}}return p}function e0e(i,a,f,p,w){var y=w?[]:void 0;return lr(i.inEdges(p.v),function(b){var E=i.edge(b),S=i.node(b.v);w&&y.push({v:b.v,w:b.w}),S.out-=E,t0e(a,f,S)}),lr(i.outEdges(p.v),function(b){var E=i.edge(b),S=b.w,N=i.node(S);N.in-=E,t0e(a,f,N)}),i.removeNode(p.v),y}function NNt(i,a){var f=new zf,p=0,w=0;lr(i.nodes(),function(E){f.setNode(E,{v:E,in:0,out:0})}),lr(i.edges(),function(E){var S=f.edge(E.v,E.w)||0,N=a(E),B=S+N;f.setEdge(E.v,E.w,B),w=Math.max(w,f.node(E.v).out+=N),p=Math.max(p,f.node(E.w).in+=N)});var y=c9(w+p+3).map(function(){return new LNt}),b=p+1;return lr(f.nodes(),function(E){t0e(y,b,f.node(E))}),{graph:f,buckets:y,zeroIdx:b}}function t0e(i,a,f){f.out?f.in?i[f.out-f.in+a].enqueue(f):i[i.length-1].enqueue(f):i[0].enqueue(f)}function PNt(i){var a=i.graph().acyclicer==="greedy"?INt(i,f(i)):BNt(i);lr(a,function(p){var w=i.edge(p);i.removeEdge(p),w.forwardName=p.name,w.reversed=!0,i.setEdge(p.w,p.v,w,sK("rev"))});function f(p){return function(w){return p.edge(w).weight}}}function BNt(i){var a=[],f={},p={};function w(y){Ja(p,y)||(p[y]=!0,f[y]=!0,lr(i.outEdges(y),function(b){Ja(f,b.w)?a.push(b):w(b.w)}),delete f[y])}return lr(i.nodes(),w),a}function RNt(i){lr(i.edges(),function(a){var f=i.edge(a);if(f.reversed){i.removeEdge(a);var p=f.forwardName;delete f.reversed,delete f.forwardName,i.setEdge(a.w,a.v,f,p)}})}function eL(i,a,f,p){var w;do w=sK(p);while(i.hasNode(w));return f.dummy=a,i.setNode(w,f),w}function FNt(i){var a=new zf().setGraph(i.graph());return lr(i.nodes(),function(f){a.setNode(f,i.node(f))}),lr(i.edges(),function(f){var p=a.edge(f.v,f.w)||{weight:0,minlen:1},w=i.edge(f);a.setEdge(f.v,f.w,{weight:p.weight+w.weight,minlen:Math.max(p.minlen,w.minlen)})}),a}function SPe(i){var a=new zf({multigraph:i.isMultigraph()}).setGraph(i.graph());return lr(i.nodes(),function(f){i.children(f).length||a.setNode(f,i.node(f))}),lr(i.edges(),function(f){a.setEdge(f,i.edge(f))}),a}function APe(i,a){var f=i.x,p=i.y,w=a.x-f,y=a.y-p,b=i.width/2,E=i.height/2;if(!w&&!y)throw new Error("Not possible to find intersection inside of the rectangle");var S,N;return Math.abs(y)*b>Math.abs(w)*E?(y<0&&(E=-E),S=E*w/y,N=E):(w<0&&(b=-b),S=b,N=b*y/w),{x:f+S,y:p+N}}function aK(i){var a=Hf(c9(MPe(i)+1),function(){return[]});return lr(i.nodes(),function(f){var p=i.node(f),w=p.rank;cf(w)||(a[w][p.order]=f)}),a}function jNt(i){var a=aP(Hf(i.nodes(),function(f){return i.node(f).rank}));lr(i.nodes(),function(f){var p=i.node(f);Ja(p,"rank")&&(p.rank-=a)})}function $Nt(i){var a=aP(Hf(i.nodes(),function(y){return i.node(y).rank})),f=[];lr(i.nodes(),function(y){var b=i.node(y).rank-a;f[b]||(f[b]=[]),f[b].push(y)});var p=0,w=i.graph().nodeRankFactor;lr(f,function(y,b){cf(y)&&b%w!==0?--p:p&&lr(y,function(E){i.node(E).rank+=p})})}function LPe(i,a,f,p){var w={width:0,height:0};return arguments.length>=4&&(w.rank=f,w.order=p),eL(i,"border",w,a)}function MPe(i){return o9(Hf(i.nodes(),function(a){var f=i.node(a).rank;if(!cf(f))return f}))}function HNt(i,a){var f={lhs:[],rhs:[]};return lr(i,function(p){a(p)?f.lhs.push(p):f.rhs.push(p)}),f}function zNt(i,a){var f=vPe();try{return a()}finally{console.log(i+" time: "+(vPe()-f)+"ms")}}function GNt(i,a){return a()}function qNt(i){function a(f){var p=i.children(f),w=i.node(f);if(p.length&&lr(p,a),Ja(w,"minRank")){w.borderLeft=[],w.borderRight=[];for(var y=w.minRank,b=w.maxRank+1;yb.lim&&(E=b,S=!0);var N=y5(a.edges(),function(B){return S===zPe(i,i.node(B.v),E)&&S!==zPe(i,i.node(B.w),E)});return Zde(N,function(B){return hP(a,B)})}function HPe(i,a,f,p){var w=f.v,y=f.w;i.removeEdge(w,y),i.setEdge(p.v,p.w,{}),a0e(i),s0e(i,a),sPt(i,a)}function sPt(i,a){var f=Yde(i.nodes(),function(w){return!a.node(w).parent}),p=rPt(i,f);p=p.slice(1),lr(p,function(w){var y=i.node(w).parent,b=a.edge(w,y),E=!1;b||(b=a.edge(y,w),E=!0),a.node(w).rank=a.node(y).rank+(E?b.minlen:-b.minlen)})}function aPt(i,a,f){return i.hasEdge(a,f)}function zPe(i,a,f){return f.low<=a.lim&&a.lim<=f.lim}function oPt(i){switch(i.graph().ranker){case"network-simplex":GPe(i);break;case"tight-tree":uPt(i);break;case"longest-path":cPt(i);break;default:GPe(i)}}var cPt=i0e;function uPt(i){i0e(i),NPe(i)}function GPe(i){l9(i)}function lPt(i){var a=eL(i,"root",{},"_root"),f=hPt(i),p=o9(k5(f))-1,w=2*p+1;i.graph().nestingRoot=a,lr(i.edges(),function(b){i.edge(b).minlen*=w});var y=fPt(i)+1;lr(i.children(),function(b){qPe(i,a,w,y,p,f,b)}),i.graph().nodeRankFactor=w}function qPe(i,a,f,p,w,y,b){var E=i.children(b);if(!E.length){b!==a&&i.setEdge(a,b,{weight:0,minlen:f});return}var S=LPe(i,"_bt"),N=LPe(i,"_bb"),B=i.node(b);i.setParent(S,b),B.borderTop=S,i.setParent(N,b),B.borderBottom=N,lr(E,function(R){qPe(i,a,f,p,w,y,R);var j=i.node(R),$=j.borderTop?j.borderTop:R,V=j.borderBottom?j.borderBottom:R,Q=j.borderTop?p:2*p,oe=$!==V?1:w-y[b]+1;i.setEdge(S,$,{weight:Q,minlen:oe,nestingEdge:!0}),i.setEdge(V,N,{weight:Q,minlen:oe,nestingEdge:!0})}),i.parent(b)||i.setEdge(a,S,{weight:0,minlen:w+y[b]})}function hPt(i){var a={};function f(p,w){var y=i.children(p);y&&y.length&&lr(y,function(b){f(b,w+1)}),a[p]=w}return lr(i.children(),function(p){f(p,1)}),a}function fPt(i){return cP(i.edges(),function(a,f){return a+i.edge(f).weight},0)}function dPt(i){var a=i.graph();i.removeNode(a.nestingRoot),delete a.nestingRoot,lr(i.edges(),function(f){var p=i.edge(f);p.nestingEdge&&i.removeEdge(f)})}function gPt(i,a,f){var p={},w;lr(f,function(y){for(var b=i.parent(y),E,S;b;){if(E=i.parent(b),E?(S=p[E],p[E]=b):(S=w,w=b),S&&S!==b){a.setEdge(S,b);return}b=E}})}function pPt(i,a,f){var p=bPt(i),w=new zf({compound:!0}).setGraph({root:p}).setDefaultNodeLabel(function(y){return i.node(y)});return lr(i.nodes(),function(y){var b=i.node(y),E=i.parent(y);(b.rank===a||b.minRank<=a&&a<=b.maxRank)&&(w.setNode(y),w.setParent(y,E||p),lr(i[f](y),function(S){var N=S.v===y?S.w:S.v,B=w.edge(N,y),R=cf(B)?0:B.weight;w.setEdge(N,y,{weight:i.edge(S).weight+R})}),Ja(b,"minRank")&&w.setNode(y,{borderLeft:b.borderLeft[a],borderRight:b.borderRight[a]}))}),w}function bPt(i){for(var a;i.hasNode(a=sK("_root")););return a}function vPt(i,a){for(var f=0,p=1;p0;)B%2&&(R+=E[B+1]),B=B-1>>1,E[B]+=N.weight;S+=N.weight*R})),S}function mPt(i){var a={},f=y5(i.nodes(),function(E){return!i.children(E).length}),p=o9(Hf(f,function(E){return i.node(E).rank})),w=Hf(c9(p+1),function(){return[]});function y(E){if(!Ja(a,E)){a[E]=!0;var S=i.node(E);w[S.rank].push(E),lr(i.successors(E),y)}}var b=uP(f,function(E){return i.node(E).rank});return lr(b,y),w}function yPt(i,a){return Hf(a,function(f){var p=i.inEdges(f);if(p.length){var w=cP(p,function(y,b){var E=i.edge(b),S=i.node(b.v);return{sum:y.sum+E.weight*S.order,weight:y.weight+E.weight}},{sum:0,weight:0});return{v:f,barycenter:w.sum/w.weight,weight:w.weight}}else return{v:f}})}function kPt(i,a){var f={};lr(i,function(w,y){var b=f[w.v]={indegree:0,in:[],out:[],vs:[w.v],i:y};cf(w.barycenter)||(b.barycenter=w.barycenter,b.weight=w.weight)}),lr(a.edges(),function(w){var y=f[w.v],b=f[w.w];!cf(y)&&!cf(b)&&(b.indegree++,y.out.push(f[w.w]))});var p=y5(f,function(w){return!w.indegree});return xPt(p)}function xPt(i){var a=[];function f(y){return function(b){b.merged||(cf(b.barycenter)||cf(y.barycenter)||b.barycenter>=y.barycenter)&&EPt(y,b)}}function p(y){return function(b){b.in.push(y),--b.indegree===0&&i.push(b)}}for(;i.length;){var w=i.pop();a.push(w),lr(w.in.reverse(),f(w)),lr(w.out,p(w))}return Hf(y5(a,function(y){return!y.merged}),function(y){return oP(y,["vs","i","barycenter","weight"])})}function EPt(i,a){var f=0,p=0;i.weight&&(f+=i.barycenter*i.weight,p+=i.weight),a.weight&&(f+=a.barycenter*a.weight,p+=a.weight),i.vs=a.vs.concat(i.vs),i.barycenter=f/p,i.weight=p,i.i=Math.min(a.i,i.i),a.merged=!0}function TPt(i,a){var f=HNt(i,function(B){return Ja(B,"barycenter")}),p=f.lhs,w=uP(f.rhs,function(B){return-B.i}),y=[],b=0,E=0,S=0;p.sort(_Pt(!!a)),S=VPe(y,w,S),lr(p,function(B){S+=B.vs.length,y.push(B.vs),b+=B.barycenter*B.weight,E+=B.weight,S=VPe(y,w,S)});var N={vs:ZA(y)};return E&&(N.barycenter=b/E,N.weight=E),N}function VPe(i,a,f){for(var p;a.length&&(p=rK(a)).i<=f;)a.pop(),i.push(p.vs),f++;return f}function _Pt(i){return function(a,f){return a.barycenterf.barycenter?1:i?f.i-a.i:a.i-f.i}}function UPe(i,a,f,p){var w=i.children(a),y=i.node(a),b=y?y.borderLeft:void 0,E=y?y.borderRight:void 0,S={};b&&(w=y5(w,function(V){return V!==b&&V!==E}));var N=yPt(i,w);lr(N,function(V){if(i.children(V.v).length){var Q=UPe(i,V.v,f,p);S[V.v]=Q,Ja(Q,"barycenter")&&SPt(V,Q)}});var B=kPt(N,f);CPt(B,S);var R=TPt(B,p);if(b&&(R.vs=ZA([b,R.vs,E]),i.predecessors(b).length)){var j=i.node(i.predecessors(b)[0]),$=i.node(i.predecessors(E)[0]);Ja(R,"barycenter")||(R.barycenter=0,R.weight=0),R.barycenter=(R.barycenter*R.weight+j.order+$.order)/(R.weight+2),R.weight+=2}return R}function CPt(i,a){lr(i,function(f){f.vs=ZA(f.vs.map(function(p){return a[p]?a[p].vs:p}))})}function SPt(i,a){cf(i.barycenter)?(i.barycenter=a.barycenter,i.weight=a.weight):(i.barycenter=(i.barycenter*i.weight+a.barycenter*a.weight)/(i.weight+a.weight),i.weight+=a.weight)}function APt(i){var a=MPe(i),f=WPe(i,c9(1,a+1),"inEdges"),p=WPe(i,c9(a-1,-1,-1),"outEdges"),w=mPt(i);KPe(i,w);for(var y=Number.POSITIVE_INFINITY,b,E=0,S=0;S<4;++E,++S){LPt(E%2?f:p,E%4>=2),w=aK(i);var N=vPt(i,w);Nb||E>a[S].lim));for(N=S,S=p;(S=i.parent(S))!==N;)y.push(S);return{path:w.concat(y.reverse()),lca:N}}function IPt(i){var a={},f=0;function p(w){var y=f;lr(i.children(w),p),a[w]={low:y,lim:f++}}return lr(i.children(),p),a}function OPt(i,a){var f={};function p(w,y){var b=0,E=0,S=w.length,N=rK(y);return lr(y,function(B,R){var j=PPt(i,B),$=j?i.node(j).order:S;(j||B===N)&&(lr(y.slice(E,R+1),function(V){lr(i.predecessors(V),function(Q){var oe=i.node(Q),ce=oe.order;(ceN)&&YPe(f,j,B)})})}function w(y,b){var E=-1,S,N=0;return lr(b,function(B,R){if(i.node(B).dummy==="border"){var j=i.predecessors(B);j.length&&(S=i.node(j[0]).order,p(b,N,R,E,S),N=R,E=S)}p(b,N,b.length,S,y.length)}),b}return cP(a,w),f}function PPt(i,a){if(i.node(a).dummy)return Yde(i.predecessors(a),function(f){return i.node(f).dummy})}function YPe(i,a,f){if(a>f){var p=a;a=f,f=p}var w=i[a];w||(i[a]=w={}),w[f]=!0}function BPt(i,a,f){if(a>f){var p=a;a=f,f=p}return Ja(i[a],f)}function RPt(i,a,f,p){var w={},y={},b={};return lr(a,function(E){lr(E,function(S,N){w[S]=S,y[S]=S,b[S]=N})}),lr(a,function(E){var S=-1;lr(E,function(N){var B=p(N);if(B.length){B=uP(B,function(Q){return b[Q]});for(var R=(B.length-1)/2,j=Math.floor(R),$=Math.ceil(R);j<=$;++j){var V=B[j];y[N]===N&&S0}function l3(i,a,f){var p=i.x,w=i.y,y=[],b=Number.POSITIVE_INFINITY,E=Number.POSITIVE_INFINITY;a.forEach(function(V){b=Math.min(b,V.x),E=Math.min(E,V.y)});for(var S=p-i.width/2-b,N=w-i.height/2-E,B=0;B1&&y.sort(function(V,Q){var oe=V.x-f.x,ce=V.y-f.y,se=Math.sqrt(oe*oe+ce*ce),ge=Q.x-f.x,ye=Q.y-f.y,ke=Math.sqrt(ge*ge+ye*ye);return seMath.abs(w)*E?(y<0&&(E=-E),S=y===0?0:E*w/y,N=E):(w<0&&(b=-b),S=b,N=w===0?0:b*y/w),{x:f+S,y:p+N}}var w0e={rect:$Bt,ellipse:HBt,circle:zBt,diamond:GBt};function jBt(i){w0e=i}function $Bt(i,a,f){var p=i.insert("rect",":first-child").attr("rx",f.rx).attr("ry",f.ry).attr("x",-a.width/2).attr("y",-a.height/2).attr("width",a.width).attr("height",a.height);return f.intersect=function(w){return v0e(f,w)},p}function HBt(i,a,f){var p=a.width/2,w=a.height/2,y=i.insert("ellipse",":first-child").attr("x",-a.width/2).attr("y",-a.height/2).attr("rx",p).attr("ry",w);return f.intersect=function(b){return tBe(f,p,w,b)},y}function zBt(i,a,f){var p=Math.max(a.width,a.height)/2,w=i.insert("circle",":first-child").attr("x",-a.width/2).attr("y",-a.height/2).attr("r",p);return f.intersect=function(y){return RBt(f,p,y)},w}function GBt(i,a,f){var p=a.width*Math.SQRT2/2,w=a.height*Math.SQRT2/2,y=[{x:0,y:-w},{x:-p,y:0},{x:0,y:w},{x:p,y:0}],b=i.insert("polygon",":first-child").attr("points",y.map(function(E){return E.x+","+E.y}).join(" "));return f.intersect=function(E){return l3(f,y,E)},b}function qBt(){var i=function(a,f){WBt(f);var p=fP(a,"output"),w=fP(p,"clusters"),y=fP(p,"edgePaths"),b=g0e(fP(p,"edgeLabels"),f),E=b0e(fP(p,"nodes"),f,w0e);tL(f),BBt(E,f),PBt(b,f),p0e(y,f,l0e);var S=d0e(w,f);NBt(S,f),KBt(f)};return i.createNodes=function(a){return arguments.length?(OBt(a),i):b0e},i.createClusters=function(a){return arguments.length?(_Bt(a),i):d0e},i.createEdgeLabels=function(a){return arguments.length?(CBt(a),i):g0e},i.createEdgePaths=function(a){return arguments.length?(SBt(a),i):p0e},i.shapes=function(a){return arguments.length?(jBt(a),i):w0e},i.arrows=function(a){return arguments.length?(wBt(a),i):l0e},i}var VBt={paddingLeft:10,paddingRight:10,paddingTop:10,paddingBottom:10,rx:0,ry:0,shape:"rect"},UBt={arrowhead:"normal",curve:ng};function WBt(i){i.nodes().forEach(function(a){var f=i.node(a);!Ja(f,"label")&&!i.children(a).length&&(f.label=a),Ja(f,"paddingX")&&JA(f,{paddingLeft:f.paddingX,paddingRight:f.paddingX}),Ja(f,"paddingY")&&JA(f,{paddingTop:f.paddingY,paddingBottom:f.paddingY}),Ja(f,"padding")&&JA(f,{paddingLeft:f.padding,paddingRight:f.padding,paddingTop:f.padding,paddingBottom:f.padding}),JA(f,VBt),lr(["paddingLeft","paddingRight","paddingTop","paddingBottom"],function(p){f[p]=Number(f[p])}),Ja(f,"width")&&(f._prevWidth=f.width),Ja(f,"height")&&(f._prevHeight=f.height)}),i.edges().forEach(function(a){var f=i.edge(a);Ja(f,"label")||(f.label=""),JA(f,UBt)})}function KBt(i){lr(i.nodes(),function(a){var f=i.node(a);Ja(f,"_prevWidth")?f.width=f._prevWidth:delete f.width,Ja(f,"_prevHeight")?f.height=f._prevHeight:delete f.height,delete f._prevWidth,delete f._prevHeight})}function fP(i,a){var f=i.select("g."+a);return f.empty()&&(f=i.append("g").attr("class",a)),f}function rBe(i,a,f){const p=a.width,w=a.height,y=(p+w)*.9,b=[{x:y/2,y:0},{x:y,y:-y/2},{x:y/2,y:-y},{x:0,y:-y/2}],E=x5(i,y,y,b);return f.intersect=function(S){return l3(f,b,S)},E}function iBe(i,a,f){const w=a.height,y=w/4,b=a.width+2*y,E=[{x:y,y:0},{x:b-y,y:0},{x:b,y:-w/2},{x:b-y,y:-w},{x:y,y:-w},{x:0,y:-w/2}],S=x5(i,b,w,E);return f.intersect=function(N){return l3(f,E,N)},S}function sBe(i,a,f){const p=a.width,w=a.height,y=[{x:-w/2,y:0},{x:p,y:0},{x:p,y:-w},{x:-w/2,y:-w},{x:0,y:-w/2}],b=x5(i,p,w,y);return f.intersect=function(E){return l3(f,y,E)},b}function aBe(i,a,f){const p=a.width,w=a.height,y=[{x:-2*w/6,y:0},{x:p-w/6,y:0},{x:p+2*w/6,y:-w},{x:w/6,y:-w}],b=x5(i,p,w,y);return f.intersect=function(E){return l3(f,y,E)},b}function oBe(i,a,f){const p=a.width,w=a.height,y=[{x:2*w/6,y:0},{x:p+w/6,y:0},{x:p-2*w/6,y:-w},{x:-w/6,y:-w}],b=x5(i,p,w,y);return f.intersect=function(E){return l3(f,y,E)},b}function cBe(i,a,f){const p=a.width,w=a.height,y=[{x:-2*w/6,y:0},{x:p+2*w/6,y:0},{x:p-w/6,y:-w},{x:w/6,y:-w}],b=x5(i,p,w,y);return f.intersect=function(E){return l3(f,y,E)},b}function uBe(i,a,f){const p=a.width,w=a.height,y=[{x:w/6,y:0},{x:p-w/6,y:0},{x:p+2*w/6,y:-w},{x:-2*w/6,y:-w}],b=x5(i,p,w,y);return f.intersect=function(E){return l3(f,y,E)},b}function lBe(i,a,f){const p=a.width,w=a.height,y=[{x:0,y:0},{x:p+w/2,y:0},{x:p,y:-w/2},{x:p+w/2,y:-w},{x:0,y:-w}],b=x5(i,p,w,y);return f.intersect=function(E){return l3(f,y,E)},b}function hBe(i,a,f){const p=a.height,w=a.width+p/4,y=i.insert("rect",":first-child").attr("rx",p/2).attr("ry",p/2).attr("x",-w/2).attr("y",-p/2).attr("width",w).attr("height",p);return f.intersect=function(b){return v0e(f,b)},y}function fBe(i,a,f){const p=a.width,w=a.height,y=[{x:0,y:0},{x:p,y:0},{x:p,y:-w},{x:0,y:-w},{x:0,y:0},{x:-8,y:0},{x:p+8,y:0},{x:p+8,y:-w},{x:-8,y:-w},{x:-8,y:0}],b=x5(i,p,w,y);return f.intersect=function(E){return l3(f,y,E)},b}function dBe(i,a,f){const p=a.width,w=p/2,y=w/(2.5+p/50),b=a.height+y,E="M 0,"+y+" a "+w+","+y+" 0,0,0 "+p+" 0 a "+w+","+y+" 0,0,0 "+-p+" 0 l 0,"+b+" a "+w+","+y+" 0,0,0 "+p+" 0 l 0,"+-b,S=i.attr("label-offset-y",y).insert("path",":first-child").attr("d",E).attr("transform","translate("+-p/2+","+-(b/2+y)+")");return f.intersect=function(N){const B=v0e(f,N),R=B.x-f.x;if(w!=0&&(Math.abs(R)f.height/2-y)){let j=y*y*(1-R*R/(w*w));j!=0&&(j=Math.sqrt(j)),j=y-j,N.y-f.y>0&&(j=-j),B.y+=j}return B},S}function YBt(i){i.shapes().question=rBe,i.shapes().hexagon=iBe,i.shapes().stadium=hBe,i.shapes().subroutine=fBe,i.shapes().cylinder=dBe,i.shapes().rect_left_inv_arrow=sBe,i.shapes().lean_right=aBe,i.shapes().lean_left=oBe,i.shapes().trapezoid=cBe,i.shapes().inv_trapezoid=uBe,i.shapes().rect_right_inv_arrow=lBe}function XBt(i){i({question:rBe}),i({hexagon:iBe}),i({stadium:hBe}),i({subroutine:fBe}),i({cylinder:dBe}),i({rect_left_inv_arrow:sBe}),i({lean_right:aBe}),i({lean_left:oBe}),i({trapezoid:cBe}),i({inv_trapezoid:uBe}),i({rect_right_inv_arrow:lBe})}function x5(i,a,f,p){return i.insert("polygon",":first-child").attr("points",p.map(function(w){return w.x+","+w.y}).join(" ")).attr("transform","translate("+-a/2+","+f/2+")")}const QBt={addToRender:YBt,addToRenderV2:XBt},gBe={},ZBt=function(i){const a=Object.keys(i);for(const f of a)gBe[f]=i[f]},pBe=function(i,a,f,p,w,y){const b=p?p.select(`[id="${f}"]`):Cr(`[id="${f}"]`),E=w||document;Object.keys(i).forEach(function(N){const B=i[N];let R="default";B.classes.length>0&&(R=B.classes.join(" "));const j=Yw(B.styles);let $=B.text!==void 0?B.text:B.id,V;if(d1(Tt().flowchart.htmlLabels)){const ce={label:$.replace(/fa[blrs]?:fa-[\w-]+/g,se=>``)};V=h0e(b,ce).node(),V.parentNode.removeChild(V)}else{const ce=E.createElementNS("http://www.w3.org/2000/svg","text");ce.setAttribute("style",j.labelStyle.replace("color:","fill:"));const se=$.split(Wa.lineBreakRegex);for(const ge of se){const ye=E.createElementNS("http://www.w3.org/2000/svg","tspan");ye.setAttributeNS("http://www.w3.org/XML/1998/namespace","xml:space","preserve"),ye.setAttribute("dy","1em"),ye.setAttribute("x","1"),ye.textContent=ge,ce.appendChild(ye)}V=ce}let Q=0,oe="";switch(B.type){case"round":Q=5,oe="rect";break;case"square":oe="rect";break;case"diamond":oe="question";break;case"hexagon":oe="hexagon";break;case"odd":oe="rect_left_inv_arrow";break;case"lean_right":oe="lean_right";break;case"lean_left":oe="lean_left";break;case"trapezoid":oe="trapezoid";break;case"inv_trapezoid":oe="inv_trapezoid";break;case"odd_right":oe="rect_left_inv_arrow";break;case"circle":oe="circle";break;case"ellipse":oe="ellipse";break;case"stadium":oe="stadium";break;case"subroutine":oe="subroutine";break;case"cylinder":oe="cylinder";break;case"group":oe="rect";break;default:oe="rect"}Fe.warn("Adding node",B.id,B.domId),a.setNode(y.db.lookUpDomId(B.id),{labelType:"svg",labelStyle:j.labelStyle,shape:oe,label:V,rx:Q,ry:Q,class:R,style:j.style,id:y.db.lookUpDomId(B.id)})})},bBe=function(i,a,f){let p=0,w,y;if(i.defaultStyle!==void 0){const b=Yw(i.defaultStyle);w=b.style,y=b.labelStyle}i.forEach(function(b){p++;var E="L-"+b.start+"-"+b.end,S="LS-"+b.start,N="LE-"+b.end;const B={};b.type==="arrow_open"?B.arrowhead="none":B.arrowhead="normal";let R="",j="";if(b.style!==void 0){const $=Yw(b.style);R=$.style,j=$.labelStyle}else switch(b.stroke){case"normal":R="fill:none",w!==void 0&&(R=w),y!==void 0&&(j=y);break;case"dotted":R="fill:none;stroke-width:2px;stroke-dasharray:3;";break;case"thick":R=" stroke-width: 3.5px;fill:none";break}B.style=R,B.labelStyle=j,b.interpolate!==void 0?B.curve=Ub(b.interpolate,ng):i.defaultInterpolate!==void 0?B.curve=Ub(i.defaultInterpolate,ng):B.curve=Ub(gBe.curve,ng),b.text===void 0?b.style!==void 0&&(B.arrowheadStyle="fill: #333"):(B.arrowheadStyle="fill: #333",B.labelpos="c",d1(Tt().flowchart.htmlLabels)?(B.labelType="html",B.label=`${b.text.replace(/fa[blrs]?:fa-[\w-]+/g,$=>``)}`):(B.labelType="text",B.label=b.text.replace(Wa.lineBreakRegex,` +`),b.style===void 0&&(B.style=B.style||"stroke: #333; stroke-width: 1.5px;fill:none"),B.labelStyle=B.labelStyle.replace("color:","fill:"))),B.id=E,B.class=S+" "+N,B.minlen=b.length||1,a.setEdge(f.db.lookUpDomId(b.start),f.db.lookUpDomId(b.end),B,p)})},JBt={setConf:ZBt,addVertices:pBe,addEdges:bBe,getClasses:function(i,a){Fe.info("Extracting classes"),a.db.clear();try{return a.parse(i),a.db.getClasses()}catch(f){return Fe.error(f),{}}},draw:function(i,a,f,p){Fe.info("Drawing flowchart"),p.db.clear();const{securityLevel:w,flowchart:y}=Tt();let b;w==="sandbox"&&(b=Cr("#i"+a));const E=Cr(w==="sandbox"?b.nodes()[0].contentDocument.body:"body"),S=w==="sandbox"?b.nodes()[0].contentDocument:document;try{p.parser.parse(i)}catch{Fe.debug("Parsing failed")}let N=p.db.getDirection();N===void 0&&(N="TD");const B=y.nodeSpacing||50,R=y.rankSpacing||50,j=new zf({multigraph:!0,compound:!0}).setGraph({rankdir:N,nodesep:B,ranksep:R,marginx:8,marginy:8}).setDefaultEdgeLabel(function(){return{}});let $;const V=p.db.getSubGraphs();for(let Ae=V.length-1;Ae>=0;Ae--)$=V[Ae],p.db.addVertex($.id,$.title,"group",void 0,$.classes);const Q=p.db.getVertices();Fe.warn("Get vertices",Q);const oe=p.db.getEdges();let ce=0;for(ce=V.length-1;ce>=0;ce--){$=V[ce],Jfe("cluster").append("text");for(let Ae=0;Ae<$.nodes.length;Ae++)Fe.warn("Setting subgraph",$.nodes[Ae],p.db.lookUpDomId($.nodes[Ae]),p.db.lookUpDomId($.id)),j.setParent(p.db.lookUpDomId($.nodes[Ae]),p.db.lookUpDomId($.id))}pBe(Q,j,a,E,S,p),bBe(oe,j,p);const se=new qBt;QBt.addToRender(se),se.arrows().none=function(de,ve,te,xe){const he=de.append("marker").attr("id",ve).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto").append("path").attr("d","M 0 0 L 0 0 L 0 0 z");u3(he,te[xe+"Style"])},se.arrows().normal=function(de,ve){de.append("marker").attr("id",ve).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto").append("path").attr("d","M 0 0 L 10 5 L 0 10 z").attr("class","arrowheadPath").style("stroke-width",1).style("stroke-dasharray","1,0")};const ge=E.select(`[id="${a}"]`),ye=E.select("#"+a+" g");for(se(ye,j),ye.selectAll("g.node").attr("title",function(){return p.db.getTooltip(this.id)}),p.db.indexNodes("subGraph"+ce),ce=0;ce{a.forEach(w=>{rRt[w](i,f,p)})},rRt={extension:(i,a,f)=>{Fe.trace("Making markers for ",f),i.append("defs").append("marker").attr("id",a+"-extensionStart").attr("class","marker extension "+a).attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 1,7 L18,13 V 1 Z"),i.append("defs").append("marker").attr("id",a+"-extensionEnd").attr("class","marker extension "+a).attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 1,1 V 13 L18,7 Z")},composition:(i,a)=>{i.append("defs").append("marker").attr("id",a+"-compositionStart").attr("class","marker composition "+a).attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id",a+"-compositionEnd").attr("class","marker composition "+a).attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z")},aggregation:(i,a)=>{i.append("defs").append("marker").attr("id",a+"-aggregationStart").attr("class","marker aggregation "+a).attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id",a+"-aggregationEnd").attr("class","marker aggregation "+a).attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z")},dependency:(i,a)=>{i.append("defs").append("marker").attr("id",a+"-dependencyStart").attr("class","marker dependency "+a).attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 5,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id",a+"-dependencyEnd").attr("class","marker dependency "+a).attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L14,7 L9,1 Z")},lollipop:(i,a)=>{i.append("defs").append("marker").attr("id",a+"-lollipopStart").attr("class","marker lollipop "+a).attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("circle").attr("stroke","black").attr("fill","white").attr("cx",6).attr("cy",7).attr("r",6)},point:(i,a)=>{i.append("marker").attr("id",a+"-pointEnd").attr("class","marker "+a).attr("viewBox","0 0 10 10").attr("refX",10).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",12).attr("markerHeight",12).attr("orient","auto").append("path").attr("d","M 0 0 L 10 5 L 0 10 z").attr("class","arrowMarkerPath").style("stroke-width",1).style("stroke-dasharray","1,0"),i.append("marker").attr("id",a+"-pointStart").attr("class","marker "+a).attr("viewBox","0 0 10 10").attr("refX",0).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",12).attr("markerHeight",12).attr("orient","auto").append("path").attr("d","M 0 5 L 10 10 L 10 0 z").attr("class","arrowMarkerPath").style("stroke-width",1).style("stroke-dasharray","1,0")},circle:(i,a)=>{i.append("marker").attr("id",a+"-circleEnd").attr("class","marker "+a).attr("viewBox","0 0 10 10").attr("refX",11).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",11).attr("markerHeight",11).attr("orient","auto").append("circle").attr("cx","5").attr("cy","5").attr("r","5").attr("class","arrowMarkerPath").style("stroke-width",1).style("stroke-dasharray","1,0"),i.append("marker").attr("id",a+"-circleStart").attr("class","marker "+a).attr("viewBox","0 0 10 10").attr("refX",-1).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",11).attr("markerHeight",11).attr("orient","auto").append("circle").attr("cx","5").attr("cy","5").attr("r","5").attr("class","arrowMarkerPath").style("stroke-width",1).style("stroke-dasharray","1,0")},cross:(i,a)=>{i.append("marker").attr("id",a+"-crossEnd").attr("class","marker cross "+a).attr("viewBox","0 0 11 11").attr("refX",12).attr("refY",5.2).attr("markerUnits","userSpaceOnUse").attr("markerWidth",11).attr("markerHeight",11).attr("orient","auto").append("path").attr("d","M 1,1 l 9,9 M 10,1 l -9,9").attr("class","arrowMarkerPath").style("stroke-width",2).style("stroke-dasharray","1,0"),i.append("marker").attr("id",a+"-crossStart").attr("class","marker cross "+a).attr("viewBox","0 0 11 11").attr("refX",-1).attr("refY",5.2).attr("markerUnits","userSpaceOnUse").attr("markerWidth",11).attr("markerHeight",11).attr("orient","auto").append("path").attr("d","M 1,1 l 9,9 M 10,1 l -9,9").attr("class","arrowMarkerPath").style("stroke-width",2).style("stroke-dasharray","1,0")},barb:(i,a)=>{i.append("defs").append("marker").attr("id",a+"-barbEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",14).attr("markerUnits","strokeWidth").attr("orient","auto").append("path").attr("d","M 19,7 L9,13 L14,7 L9,1 Z")}},vBe=nRt;function iRt(i,a){a&&i.attr("style",a)}function sRt(i){const a=Cr(document.createElementNS("http://www.w3.org/2000/svg","foreignObject")),f=a.append("xhtml:div"),p=i.label,w=i.isNode?"nodeLabel":"edgeLabel";return f.html('"+p+""),iRt(f,i.labelStyle),f.style("display","inline-block"),f.style("white-space","nowrap"),f.attr("xmlns","http://www.w3.org/1999/xhtml"),a.node()}const sp=(i,a,f,p)=>{let w=i||"";if(typeof w=="object"&&(w=w[0]),d1(Tt().flowchart.htmlLabels)){w=w.replace(/\\n|\n/g,"
"),Fe.info("vertexText"+w);const y={isNode:p,label:XN(w).replace(/fa[blrs]?:fa-[\w-]+/g,E=>``),labelStyle:a.replace("fill:","color:")};return sRt(y)}else{const y=document.createElementNS("http://www.w3.org/2000/svg","text");y.setAttribute("style",a.replace("color:","fill:"));let b=[];typeof w=="string"?b=w.split(/\\n|\n|/gi):Array.isArray(w)?b=w:b=[];for(const E of b){const S=document.createElementNS("http://www.w3.org/2000/svg","tspan");S.setAttributeNS("http://www.w3.org/XML/1998/namespace","xml:space","preserve"),S.setAttribute("dy","1em"),S.setAttribute("x","0"),f?S.setAttribute("class","title-row"):S.setAttribute("class","row"),S.textContent=E.trim(),y.appendChild(S)}return y}};var aRt=/\r\n?/g,oRt=/\t/g,cRt=/\f/g,wBe=function(a){return a.replace(aRt,` +`).replace(cRt,"").replace(oRt," ")},mBe=function(a,f){var p=a||{};if(f!=null)for(var w in f)Object.prototype.hasOwnProperty.call(f,w)&&(p[w]=f[w]);return p},yBe=function(a,f){var p=Object.keys(a).filter(function(E){var S=a[E];if(S==null||S.match==null)return!1;var N=S.order;return(typeof N!="number"||!isFinite(N))&&typeof console<"u"&&console.warn("simple-markdown: Invalid order for rule `"+E+"`: "+String(N)),!0});p.sort(function(E,S){var N=a[E],B=a[S],R=N.order,j=B.order;if(R!==j)return R-j;var $=N.quality?0:1,V=B.quality?0:1;return $!==V?$-V:ES?1:0});var w,y=function E(S,N){var B=[];for(N=N||w,w=N;S;){var R=null,j=null,$=null,V=NaN,Q=0,oe=p[0],ce=a[oe];do{var se=ce.order,ge=N.prevCapture==null?"":N.prevCapture[0],ye=ce.match(S,N,ge);if(ye){var ke=ce.quality?ce.quality(ye,N,ge):0;ke<=V||(R=oe,j=ce,$=ye,V=ke)}Q++,oe=p[Q],ce=a[oe]}while(ce&&(!$||ce.order===se&&ce.quality));if(j==null||$==null)throw new Error("Could not find a matching rule for the below content. The rule with highest `order` should always match content provided to it. Check the definition of `match` for '"+p[p.length-1]+`'. It seems to not match the following source: +`+S);if($.index)throw new Error("`match` must return a capture starting at index 0 (the current parse index). Did you forget a ^ at the start of the RegExp?");var Ae=j.parse($,E,N);if(Array.isArray(Ae))Array.prototype.push.apply(B,Ae);else{if(Ae==null||typeof Ae!="object")throw new Error(`parse() function returned invalid parse result: '${Ae}'`);Ae.type==null&&(Ae.type=R),B.push(Ae)}N.prevCapture=$,S=S.substring(N.prevCapture[0].length)}return B},b=function(S,N){return w=mBe(N,f),!w.inline&&!w.disableAutoBlockNewlines&&(S=S+` + +`),w.prevCapture=null,y(wBe(S),w)};return b},ap=function(a){var f=function(w,y,b){return y.inline?a.exec(w):null};return f.regex=a,f},Xb=function(a){var f=function(w,y){return y.inline?null:a.exec(w)};return f.regex=a,f},m0e=function(a){var f=function(w,y){return a.exec(w)};return f.regex=a,f},uRt=typeof Symbol=="function"&&Symbol.for&&Symbol.for("react.element")||60103,Cl=function(a,f,p){var w={$$typeof:uRt,type:a,key:f??void 0,ref:null,props:p,_owner:null};return w},Ah=function(a,f,p,w){p=p||{},w=typeof w<"u"?w:!0;var y="";for(var b in p){var E=p[b];Object.prototype.hasOwnProperty.call(p,b)&&E&&(y+=" "+nL(b)+'="'+nL(E)+'"')}var S="<"+a+y+">";return w?S+f+"":S},kBe={},dP=function(a){if(a==null)return null;try{var f=new URL(a,"https://localhost").protocol;if(f.indexOf("javascript:")===0||f.indexOf("vbscript:")===0||f.indexOf("data:")===0)return null}catch{return null}return a},lRt=/[<>&"']/g,hRt={"<":"<",">":">","&":"&",'"':""","'":"'","/":"/","`":"`"},nL=function(a){return String(a).replace(lRt,function(f){return hRt[f]})},fRt=/\\([^0-9A-Za-z\s])/g,y0e=function(a){return a.replace(fRt,"$1")},oK=function(a,f,p){var w=p.inline||!1;p.inline=!0;var y=a(f,p);return p.inline=w,y},dRt=function(a,f,p){var w=p.inline||!1;p.inline=!1;var y=a(f+` + +`,p);return p.inline=w,y},cK=function(a,f,p){return{content:oK(f,a[1],p)}},k0e=function(){return{}},uK="(?:[*+-]|\\d+\\.)",xBe="( *)("+uK+") +",EBe=new RegExp("^"+xBe),gRt=new RegExp(xBe+"[^\\n]*(?:\\n(?!\\1"+uK+` )[^\\n]*)*( +|$)`,"gm"),TBe=/\n{2,}$/,pRt=/^ (?= *`)|(` *) $/g,bRt=TBe,_Be=/ *\n+$/,vRt=new RegExp("^( *)("+uK+`) [\\s\\S]+?(?: +{2,}(?! )(?!\\1`+uK+` )\\n*|\\s* +*$)`),wRt=/(?:^|\n)( *)$/,lK=function(){var i=/^ *\| *| *\| *$/g,a=/ *$/,f=/^ *-+: *$/,p=/^ *:-+: *$/,w=/^ *:-+ *$/,y=function(R){return f.test(R)?"right":p.test(R)?"center":w.test(R)?"left":null},b=function(R,j,$,V){V&&(R=R.replace(i,""));var Q=R.trim().split("|");return Q.map(y)},E=function(R,j,$,V){var Q=$.inTable;$.inTable=!0;var oe=j(R.trim(),$);$.inTable=Q;var ce=[[]];return oe.forEach(function(se,ge){se.type==="tableSeparator"?(!V||ge!==0&&ge!==oe.length-1)&&ce.push([]):(se.type==="text"&&(oe[ge+1]==null||oe[ge+1].type==="tableSeparator")&&(se.content=se.content.replace(a,"")),ce[ce.length-1].push(se))}),ce},S=function(R,j,$,V){var Q=R.trim().split(` +`);return Q.map(function(oe){return E(oe,j,$,V)})},N=function(R){return function(j,$,V){V.inline=!0;var Q=E(j[1],$,V,R),oe=b(j[2],$,V,R),ce=S(j[3],$,V,R);return V.inline=!1,{type:"table",header:Q,align:oe,cells:ce}}};return{parseTable:N(!0),parseNpTable:N(!1),TABLE_REGEX:/^ *(\|.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/,NPTABLE_REGEX:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/}}(),hK="(?:\\[[^\\]]*\\]|[^\\[\\]]|\\](?=[^\\[]*\\]))*",CBe=`\\s*?(?:\\s+['"]([\\s\\S]*?)['"])?\\s*`,mRt=/mailto:/i,SBe=function(a,f,p){var w=(a[2]||a[1]).replace(/\s+/g," ").toLowerCase();if(f._defs&&f._defs[w]){var y=f._defs[w];p.target=y.target,p.title=y.title}return f._refs=f._refs||{},f._refs[w]=f._refs[w]||[],f._refs[w].push(p),p},$u=0,gP={Array:{react:function(i,a,f){for(var p=f.key,w=[],y=0,b=0;y"}},codeBlock:{order:$u++,match:Xb(/^(?: [^\n]+\n*)+(?:\n *)+\n/),parse:function(i,a,f){var p=i[0].replace(/^ /gm,"").replace(/\n+$/,"");return{lang:void 0,content:p}},react:function(i,a,f){var p=i.lang?"markdown-code-"+i.lang:void 0;return Cl("pre",f.key,{children:Cl("code",null,{className:p,children:i.content})})},html:function(i,a,f){var p=i.lang?"markdown-code-"+i.lang:void 0,w=Ah("code",nL(i.content),{class:p});return Ah("pre",w)}},fence:{order:$u++,match:Xb(/^ *(`{3,}|~{3,}) *(?:(\S+) *)?\n([\s\S]+?)\n?\1 *(?:\n *)+\n/),parse:function(i,a,f){return{type:"codeBlock",lang:i[2]||void 0,content:i[3]}},react:null,html:null},blockQuote:{order:$u++,match:Xb(/^( *>[^\n]+(\n[^\n]+)*\n*)+\n{2,}/),parse:function(i,a,f){var p=i[0].replace(/^ *> ?/gm,"");return{content:a(p,f)}},react:function(i,a,f){return Cl("blockquote",f.key,{children:a(i.content,f)})},html:function(i,a,f){return Ah("blockquote",a(i.content,f))}},list:{order:$u++,match:function(i,a){var f=a.prevCapture==null?"":a.prevCapture[0],p=wRt.exec(f),w=a._list||!a.inline;return p&&w?(i=p[1]+i,vRt.exec(i)):null},parse:function(i,a,f){var p=i[2],w=p.length>1,y=w?+p:void 0,b=i[0].replace(bRt,` +`).match(gRt),E=!1,S=b.map(function(N,B){var R=EBe.exec(N),j=R?R[0].length:0,$=new RegExp("^ {1,"+j+"}","gm"),V=N.replace($,"").replace(EBe,""),Q=B===b.length-1,oe=V.indexOf(` + +`)!==-1,ce=oe||Q&&E;E=ce;var se=f.inline,ge=f._list;f._list=!0;var ye;ce?(f.inline=!1,ye=V.replace(_Be,` + +`)):(f.inline=!0,ye=V.replace(_Be,""));var ke=a(ye,f);return f.inline=se,f._list=ge,ke});return{ordered:w,start:y,items:S}},react:function(i,a,f){var p=i.ordered?"ol":"ul";return Cl(p,f.key,{start:i.start,children:i.items.map(function(w,y){return Cl("li",""+y,{children:a(w,f)})})})},html:function(i,a,f){var p=i.items.map(function(b){return Ah("li",a(b,f))}).join(""),w=i.ordered?"ol":"ul",y={start:i.start};return Ah(w,p,y)}},def:{order:$u++,match:Xb(/^ *\[([^\]]+)\]: *]*)>?(?: +["(]([^\n]+)[")])? *\n(?: *\n)*/),parse:function(i,a,f){var p=i[1].replace(/\s+/g," ").toLowerCase(),w=i[2],y=i[3];return f._refs&&f._refs[p]&&f._refs[p].forEach(function(b){b.target=w,b.title=y}),f._defs=f._defs||{},f._defs[p]={target:w,title:y},{def:p,target:w,title:y}},react:function(){return null},html:function(){return""}},table:{order:$u++,match:Xb(lK.TABLE_REGEX),parse:lK.parseTable,react:function(i,a,f){var p=function(E){return i.align[E]==null?{}:{textAlign:i.align[E]}},w=i.header.map(function(b,E){return Cl("th",""+E,{style:p(E),scope:"col",children:a(b,f)})}),y=i.cells.map(function(b,E){return Cl("tr",""+E,{children:b.map(function(S,N){return Cl("td",""+N,{style:p(N),children:a(S,f)})})})});return Cl("table",f.key,{children:[Cl("thead","thead",{children:Cl("tr",null,{children:w})}),Cl("tbody","tbody",{children:y})]})},html:function(i,a,f){var p=function(N){return i.align[N]==null?"":"text-align:"+i.align[N]+";"},w=i.header.map(function(S,N){return Ah("th",a(S,f),{style:p(N),scope:"col"})}).join(""),y=i.cells.map(function(S){var N=S.map(function(B,R){return Ah("td",a(B,f),{style:p(R)})}).join("");return Ah("tr",N)}).join(""),b=Ah("thead",Ah("tr",w)),E=Ah("tbody",y);return Ah("table",b+E)}},newline:{order:$u++,match:Xb(/^(?:\n *)*\n/),parse:k0e,react:function(i,a,f){return` +`},html:function(i,a,f){return` +`}},paragraph:{order:$u++,match:Xb(/^((?:[^\n]|\n(?! *\n))+)(?:\n *)+\n/),parse:cK,react:function(i,a,f){return Cl("div",f.key,{className:"paragraph",children:a(i.content,f)})},html:function(i,a,f){var p={class:"paragraph"};return Ah("div",a(i.content,f),p)}},escape:{order:$u++,match:ap(/^\\([^0-9A-Za-z\s])/),parse:function(i,a,f){return{type:"text",content:i[1]}},react:null,html:null},tableSeparator:{order:$u++,match:function(i,a){return a.inTable?/^ *\| */.exec(i):null},parse:function(){return{type:"tableSeparator"}},react:function(){return" | "},html:function(){return" | "}},autolink:{order:$u++,match:ap(/^<([^: >]+:\/[^ >]+)>/),parse:function(i,a,f){return{type:"link",content:[{type:"text",content:i[1]}],target:i[1]}},react:null,html:null},mailto:{order:$u++,match:ap(/^<([^ >]+@[^ >]+)>/),parse:function(i,a,f){var p=i[1],w=i[1];return mRt.test(w)||(w="mailto:"+w),{type:"link",content:[{type:"text",content:p}],target:w}},react:null,html:null},url:{order:$u++,match:ap(/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/),parse:function(i,a,f){return{type:"link",content:[{type:"text",content:i[1]}],target:i[1],title:void 0}},react:null,html:null},link:{order:$u++,match:ap(new RegExp("^\\[("+hK+")\\]\\("+CBe+"\\)")),parse:function(i,a,f){var p={content:a(i[1],f),target:y0e(i[2]),title:i[3]};return p},react:function(i,a,f){return Cl("a",f.key,{href:dP(i.target),title:i.title,children:a(i.content,f)})},html:function(i,a,f){var p={href:dP(i.target),title:i.title};return Ah("a",a(i.content,f),p)}},image:{order:$u++,match:ap(new RegExp("^!\\[("+hK+")\\]\\("+CBe+"\\)")),parse:function(i,a,f){var p={alt:i[1],target:y0e(i[2]),title:i[3]};return p},react:function(i,a,f){return Cl("img",f.key,{src:dP(i.target),alt:i.alt,title:i.title})},html:function(i,a,f){var p={src:dP(i.target),alt:i.alt,title:i.title};return Ah("img","",p,!1)}},reflink:{order:$u++,match:ap(new RegExp("^\\[("+hK+")\\]\\s*\\[([^\\]]*)\\]")),parse:function(i,a,f){return SBe(i,f,{type:"link",content:a(i[1],f)})},react:null,html:null},refimage:{order:$u++,match:ap(new RegExp("^!\\[("+hK+")\\]\\s*\\[([^\\]]*)\\]")),parse:function(i,a,f){return SBe(i,f,{type:"image",alt:i[1]})},react:null,html:null},em:{order:$u,match:ap(new RegExp("^\\b_((?:__|\\\\[\\s\\S]|[^\\\\_])+?)_\\b|^\\*(?=\\S)((?:\\*\\*|\\\\[\\s\\S]|\\s+(?:\\\\[\\s\\S]|[^\\s\\*\\\\]|\\*\\*)|[^\\s\\*\\\\])+?)\\*(?!\\*)")),quality:function(i){return i[0].length+.2},parse:function(i,a,f){return{content:a(i[2]||i[1],f)}},react:function(i,a,f){return Cl("em",f.key,{children:a(i.content,f)})},html:function(i,a,f){return Ah("em",a(i.content,f))}},strong:{order:$u,match:ap(/^\*\*((?:\\[\s\S]|[^\\])+?)\*\*(?!\*)/),quality:function(i){return i[0].length+.1},parse:cK,react:function(i,a,f){return Cl("strong",f.key,{children:a(i.content,f)})},html:function(i,a,f){return Ah("strong",a(i.content,f))}},u:{order:$u++,match:ap(/^__((?:\\[\s\S]|[^\\])+?)__(?!_)/),quality:function(i){return i[0].length},parse:cK,react:function(i,a,f){return Cl("u",f.key,{children:a(i.content,f)})},html:function(i,a,f){return Ah("u",a(i.content,f))}},del:{order:$u++,match:ap(/^~~(?=\S)((?:\\[\s\S]|~(?!~)|[^\s~\\]|\s(?!~~))+?)~~/),parse:cK,react:function(i,a,f){return Cl("del",f.key,{children:a(i.content,f)})},html:function(i,a,f){return Ah("del",a(i.content,f))}},inlineCode:{order:$u++,match:ap(/^(`+)([\s\S]*?[^`])\1(?!`)/),parse:function(i,a,f){return{content:i[2].replace(pRt,"$1")}},react:function(i,a,f){return Cl("code",f.key,{children:i.content})},html:function(i,a,f){return Ah("code",nL(i.content))}},br:{order:$u++,match:m0e(/^ {2,}\n/),parse:k0e,react:function(i,a,f){return Cl("br",f.key,kBe)},html:function(i,a,f){return"
"}},text:{order:$u++,match:m0e(/^[\s\S]+?(?=[^0-9A-Za-z\s\u00c0-\uffff]|\n\n| {2,}\n|\w+:\S|$)/),parse:function(i,a,f){return{content:i[0]}},react:function(i,a,f){return i.content},html:function(i,a,f){return nL(i.content)}}},yRt=function(a,f){!f&&typeof console<"u"&&console.warn("simple-markdown ruleOutput should take 'react' or 'html' as the second argument.");var p=function(y,b,E){return a[y.type][f](y,b,E)};return p},kRt=function(a){var f=function p(w,y){if(y=y||{},Array.isArray(w)){for(var b=y.key,E=[],S=null,N=0;N{R!==0&&(y++,w.push([])),B.split(" ").forEach(j=>{j&&w[y].push({content:j,type:S||"normal"})})}):(E.type==="strong"||E.type==="em")&&E.content.forEach(N=>{b(N,E.type)})}return p.forEach(E=>{E.type==="paragraph"&&E.content.forEach(S=>{b(S)})}),w}function ARt(i){const a=DBe.defaultBlockParse,f=a(i);function p(w){return w.type==="text"?w.content.replace(/\n/g,"
"):w.type==="strong"?`${w.content.map(p).join("")}`:w.type==="em"?`${w.content.map(p).join("")}`:w.type==="paragraph"?`

${w.content.map(p).join("")}

`:""}return f.map(p).join("")}function LRt(i,a){a&&i.attr("style",a)}function MRt(i,a,f,p){const w=i.append("foreignObject"),y=w.append("xhtml:div"),b=a.label,E=a.isNode?"nodeLabel":"edgeLabel";y.html(`"+b+""),LRt(y,a.labelStyle),y.style("display","table-cell"),y.style("white-space","nowrap"),y.style("max-width",f+"px"),y.attr("xmlns","http://www.w3.org/1999/xhtml");let S=y.node().getBoundingClientRect();return S.width===f&&(y.style("display","table"),y.style("white-space","break-spaces"),y.style("width",f+"px"),S=y.node().getBoundingClientRect()),w.style("width",S.width),w.style("height",S.height),w.node()}function IBe(i,a,f){return i.append("tspan").attr("class","text-outer-tspan").attr("x",0).attr("y",a*f-.1+"em").attr("dy",f+"em")}function DRt(i,a,f,p=!1){const y=a.append("g");let b=y.insert("rect").attr("class","background");const E=y.append("text").attr("y","-10.1");let S=-1;if(f.forEach(N=>{S++;let B=IBe(E,S,1.1),R=[...N].reverse(),j,$=[];for(;R.length;)j=R.pop(),$.push(j),OBe(B,$),B.node().getComputedTextLength()>i&&($.pop(),R.push(j),OBe(B,$),$=[],S++,B=IBe(E,S,1.1))}),p){const N=E.node().getBBox(),B=2;return b.attr("x",-B).attr("y",-B).attr("width",N.width+2*B).attr("height",N.height+2*B),y.node()}else return E.node()}function OBe(i,a){i.text(""),a.forEach((f,p)=>{const w=i.append("tspan").attr("font-style",f.type==="em"?"italic":"normal").attr("class","text-inner-tspan").attr("font-weight",f.type==="strong"?"bold":"normal");p===0?w.text(f.content):w.text(" "+f.content)})}const dK=(i,a="",{style:f="",isTitle:p=!1,classes:w="",useHtmlLabels:y=!0,isNode:b=!0,width:E,addSvgBackground:S=!1}={})=>{if(Fe.info("createText",a,f,p,w,y,b,S),y){const N=ARt(a),B={isNode:b,label:XN(N).replace(/fa[blrs]?:fa-[\w-]+/g,j=>``),labelStyle:f.replace("fill:","color:")};return MRt(i,B,E,w)}else{const N=SRt(a),B=['"',"'",".",",",":",";","!","?","(",")","[","]","{","}"];let R;return N.forEach($=>{$.forEach(V=>{B.includes(V.content)&&R&&(R.content+=V.content,V.content=""),R=V})}),DRt(E,i,N,S)}},jd=async(i,a,f,p)=>{let w;const y=a.useHtmlLabels||d1(Tt().flowchart.htmlLabels);f?w=f:w="node default";const b=i.insert("g").attr("class",w).attr("id",a.domId||a.id),E=b.insert("g").attr("class","label").attr("style",a.labelStyle);let S;a.labelText===void 0?S="":S=typeof a.labelText=="string"?a.labelText:a.labelText[0];const N=E.node();let B;a.labelType==="markdown"?B=dK(E,ep(XN(S),Tt()),{useHtmlLabels:y,width:a.width||Tt().flowchart.wrappingWidth,classes:"markdown-node-label"}):B=N.appendChild(sp(ep(XN(S),Tt()),a.labelStyle,!1,p));let R=B.getBBox();const j=a.padding/2;if(d1(Tt().flowchart.htmlLabels)){const $=B.children[0],V=Cr(B),Q=$.getElementsByTagName("img");if(Q){const oe=S.replace(/]*>/g,"").trim()==="";await Promise.all([...Q].map(ce=>new Promise(se=>ce.addEventListener("load",function(){if(ce.style.display="flex",ce.style.flexDirection="column",oe){const ge=Tt().fontSize?Tt().fontSize:window.getComputedStyle(document.body).fontSize,ye=5;ce.style.width=parseInt(ge,10)*ye+"px"}else ce.style.width="100%";se(ce)}))))}R=$.getBoundingClientRect(),V.attr("width",R.width),V.attr("height",R.height)}return y?E.attr("transform","translate("+-R.width/2+", "+-R.height/2+")"):E.attr("transform","translate(0, "+-R.height/2+")"),a.centerLabel&&E.attr("transform","translate("+-R.width/2+", "+-R.height/2+")"),E.insert("rect",":first-child"),{shapeSvg:b,bbox:R,halfPadding:j,label:E}},uf=(i,a)=>{const f=a.node().getBBox();i.width=f.width,i.height=f.height};function T5(i,a,f,p){return i.insert("polygon",":first-child").attr("points",p.map(function(w){return w.x+","+w.y}).join(" ")).attr("class","label-container").attr("transform","translate("+-a/2+","+f/2+")")}let ec={},nm={},NBe={};const IRt=()=>{nm={},NBe={},ec={}},gK=(i,a)=>(Fe.trace("In isDecendant",a," ",i," = ",nm[a].includes(i)),!!nm[a].includes(i)),ORt=(i,a)=>(Fe.info("Decendants of ",a," is ",nm[a]),Fe.info("Edge is ",i),i.v===a||i.w===a?!1:nm[a]?nm[a].includes(i.v)||gK(i.v,a)||gK(i.w,a)||nm[a].includes(i.w):(Fe.debug("Tilt, ",a,",not in decendants"),!1)),PBe=(i,a,f,p)=>{Fe.warn("Copying children of ",i,"root",p,"data",a.node(i),p);const w=a.children(i)||[];i!==p&&w.push(i),Fe.warn("Copying (nodes) clusterId",i,"nodes",w),w.forEach(y=>{if(a.children(y).length>0)PBe(y,a,f,p);else{const b=a.node(y);Fe.info("cp ",y," to ",p," with parent ",i),f.setNode(y,b),p!==a.parent(y)&&(Fe.warn("Setting parent",y,a.parent(y)),f.setParent(y,a.parent(y))),i!==p&&y!==i?(Fe.debug("Setting parent",y,i),f.setParent(y,i)):(Fe.info("In copy ",i,"root",p,"data",a.node(i),p),Fe.debug("Not Setting parent for node=",y,"cluster!==rootId",i!==p,"node!==clusterId",y!==i));const E=a.edges(y);Fe.debug("Copying Edges",E),E.forEach(S=>{Fe.info("Edge",S);const N=a.edge(S.v,S.w,S.name);Fe.info("Edge data",N,p);try{ORt(S,p)?(Fe.info("Copying as ",S.v,S.w,N,S.name),f.setEdge(S.v,S.w,N,S.name),Fe.info("newGraph edges ",f.edges(),f.edge(f.edges()[0]))):Fe.info("Skipping copy of edge ",S.v,"-->",S.w," rootId: ",p," clusterId:",i)}catch(B){Fe.error(B)}})}Fe.debug("Removing node",y),a.removeNode(y)})},BBe=(i,a)=>{const f=a.children(i);let p=[...f];for(const w of f)NBe[w]=i,p=[...p,...BBe(w,a)];return p},pP=(i,a)=>{Fe.trace("Searching",i);const f=a.children(i);if(Fe.trace("Searching children of id ",i,f),f.length<1)return Fe.trace("This is a valid node",i),i;for(const p of f){const w=pP(p,a);if(w)return Fe.trace("Found replacement for",i," => ",w),w}},pK=i=>!ec[i]||!ec[i].externalConnections?i:ec[i]?ec[i].id:i,NRt=(i,a)=>{if(!i||a>10){Fe.debug("Opting out, no graph ");return}else Fe.debug("Opting in, graph ");i.nodes().forEach(function(f){i.children(f).length>0&&(Fe.warn("Cluster identified",f," Replacement id in edges: ",pP(f,i)),nm[f]=BBe(f,i),ec[f]={id:pP(f,i),clusterData:i.node(f)})}),i.nodes().forEach(function(f){const p=i.children(f),w=i.edges();p.length>0?(Fe.debug("Cluster identified",f,nm),w.forEach(y=>{if(y.v!==f&&y.w!==f){const b=gK(y.v,f),E=gK(y.w,f);b^E&&(Fe.warn("Edge: ",y," leaves cluster ",f),Fe.warn("Decendants of XXX ",f,": ",nm[f]),ec[f].externalConnections=!0)}})):Fe.debug("Not a cluster ",f,nm)}),i.edges().forEach(function(f){const p=i.edge(f);Fe.warn("Edge "+f.v+" -> "+f.w+": "+JSON.stringify(f)),Fe.warn("Edge "+f.v+" -> "+f.w+": "+JSON.stringify(i.edge(f)));let w=f.v,y=f.w;if(Fe.warn("Fix XXX",ec,"ids:",f.v,f.w,"Translating: ",ec[f.v]," --- ",ec[f.w]),ec[f.v]&&ec[f.w]&&ec[f.v]===ec[f.w]){Fe.warn("Fixing and trixing link to self - removing XXX",f.v,f.w,f.name),Fe.warn("Fixing and trixing - removing XXX",f.v,f.w,f.name),w=pK(f.v),y=pK(f.w),i.removeEdge(f.v,f.w,f.name);const b=f.w+"---"+f.v;i.setNode(b,{domId:b,id:b,labelStyle:"",labelText:p.label,padding:0,shape:"labelRect",style:""});const E=JSON.parse(JSON.stringify(p)),S=JSON.parse(JSON.stringify(p));E.label="",E.arrowTypeEnd="none",S.label="",E.fromCluster=f.v,S.toCluster=f.v,i.setEdge(w,b,E,f.name+"-cyclic-special"),i.setEdge(b,y,S,f.name+"-cyclic-special")}else(ec[f.v]||ec[f.w])&&(Fe.warn("Fixing and trixing - removing XXX",f.v,f.w,f.name),w=pK(f.v),y=pK(f.w),i.removeEdge(f.v,f.w,f.name),w!==f.v&&(p.fromCluster=f.v),y!==f.w&&(p.toCluster=f.w),Fe.warn("Fix Replacing with XXX",w,y,f.name),i.setEdge(w,y,p,f.name))}),Fe.warn("Adjusted Graph",E5(i)),RBe(i,0),Fe.trace(ec)},RBe=(i,a)=>{if(Fe.warn("extractor - ",a,E5(i),i.children("D")),a>10){Fe.error("Bailing out");return}let f=i.nodes(),p=!1;for(const w of f){const y=i.children(w);p=p||y.length>0}if(!p){Fe.debug("Done, no node has children",i.nodes());return}Fe.debug("Nodes = ",f,a);for(const w of f)if(Fe.debug("Extracting node",w,ec,ec[w]&&!ec[w].externalConnections,!i.parent(w),i.node(w),i.children("D")," Depth ",a),!ec[w])Fe.debug("Not a cluster",w,a);else if(!ec[w].externalConnections&&i.children(w)&&i.children(w).length>0){Fe.warn("Cluster without external connections, without a parent and with children",w,a);let b=i.graph().rankdir==="TB"?"LR":"TB";ec[w]&&ec[w].clusterData&&ec[w].clusterData.dir&&(b=ec[w].clusterData.dir,Fe.warn("Fixing dir",ec[w].clusterData.dir,b));const E=new zf({multigraph:!0,compound:!0}).setGraph({rankdir:b,nodesep:50,ranksep:50,marginx:8,marginy:8}).setDefaultEdgeLabel(function(){return{}});Fe.warn("Old graph before copy",E5(i)),PBe(w,i,E,w),i.setNode(w,{clusterNode:!0,id:w,clusterData:ec[w].clusterData,labelText:ec[w].labelText,graph:E}),Fe.warn("New graph after copy node: (",w,")",E5(E)),Fe.debug("Old graph after copy",E5(i))}else Fe.warn("Cluster ** ",w," **not meeting the criteria !externalConnections:",!ec[w].externalConnections," no parent: ",!i.parent(w)," children ",i.children(w)&&i.children(w).length>0,i.children("D"),a),Fe.debug(ec);f=i.nodes(),Fe.warn("New list of nodes",f);for(const w of f){const y=i.node(w);Fe.warn(" Now next level",w,y),y.clusterNode&&RBe(y.graph,a+1)}},FBe=(i,a)=>{if(a.length===0)return[];let f=Object.assign(a);return a.forEach(p=>{const w=i.children(p),y=FBe(i,w);f=[...f,...y]}),f},PRt=i=>FBe(i,i.children());function BRt(i,a){return i.intersect(a)}function jBe(i,a,f,p){var w=i.x,y=i.y,b=w-p.x,E=y-p.y,S=Math.sqrt(a*a*E*E+f*f*b*b),N=Math.abs(a*f*b/S);p.x0}function jRt(i,a,f){var p=i.x,w=i.y,y=[],b=Number.POSITIVE_INFINITY,E=Number.POSITIVE_INFINITY;typeof a.forEach=="function"?a.forEach(function(V){b=Math.min(b,V.x),E=Math.min(E,V.y)}):(b=Math.min(b,a.x),E=Math.min(E,a.y));for(var S=p-i.width/2-b,N=w-i.height/2-E,B=0;B1&&y.sort(function(V,Q){var oe=V.x-f.x,ce=V.y-f.y,se=Math.sqrt(oe*oe+ce*ce),ge=Q.x-f.x,ye=Q.y-f.y,ke=Math.sqrt(ge*ge+ye*ye);return se{var f=i.x,p=i.y,w=a.x-f,y=a.y-p,b=i.width/2,E=i.height/2,S,N;return Math.abs(y)*b>Math.abs(w)*E?(y<0&&(E=-E),S=y===0?0:E*w/y,N=E):(w<0&&(b=-b),S=b,N=w===0?0:b*y/w),{x:f+S,y:p+N}},Lh={node:BRt,circle:RRt,ellipse:jBe,polygon:jRt,rect:bP},$Rt=async(i,a)=>{a.useHtmlLabels||Tt().flowchart.htmlLabels||(a.centerLabel=!0);const{shapeSvg:p,bbox:w,halfPadding:y}=await jd(i,a,"node "+a.classes,!0);Fe.info("Classes = ",a.classes);const b=p.insert("rect",":first-child");return b.attr("rx",a.rx).attr("ry",a.ry).attr("x",-w.width/2-y).attr("y",-w.height/2-y).attr("width",w.width+a.padding).attr("height",w.height+a.padding),uf(a,b),a.intersect=function(E){return Lh.rect(a,E)},p};let HBe=0;const HRt=function(i,a,f,p,w){const y=function(se){switch(se){case w.db.relationType.AGGREGATION:return"aggregation";case w.db.relationType.EXTENSION:return"extension";case w.db.relationType.COMPOSITION:return"composition";case w.db.relationType.DEPENDENCY:return"dependency";case w.db.relationType.LOLLIPOP:return"lollipop"}};a.points=a.points.filter(se=>!Number.isNaN(se.y));const b=a.points,E=WE().x(function(se){return se.x}).y(function(se){return se.y}).curve(SA),S=i.append("path").attr("d",E(b)).attr("id","edge"+HBe).attr("class","relation");let N="";p.arrowMarkerAbsolute&&(N=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search,N=N.replace(/\(/g,"\\("),N=N.replace(/\)/g,"\\)")),f.relation.lineType==1&&S.attr("class","relation dashed-line"),f.relation.lineType==10&&S.attr("class","relation dotted-line"),f.relation.type1!=="none"&&S.attr("marker-start","url("+N+"#"+y(f.relation.type1)+"Start)"),f.relation.type2!=="none"&&S.attr("marker-end","url("+N+"#"+y(f.relation.type2)+"End)");let B,R;const j=a.points.length;let $=co.calcLabelPosition(a.points);B=$.x,R=$.y;let V,Q,oe,ce;if(j%2!==0&&j>1){let se=co.calcCardinalityPosition(f.relation.type1!=="none",a.points,a.points[0]),ge=co.calcCardinalityPosition(f.relation.type2!=="none",a.points,a.points[j-1]);Fe.debug("cardinality_1_point "+JSON.stringify(se)),Fe.debug("cardinality_2_point "+JSON.stringify(ge)),V=se.x,Q=se.y,oe=ge.x,ce=ge.y}if(f.title!==void 0){const se=i.append("g").attr("class","classLabel"),ge=se.append("text").attr("class","label").attr("x",B).attr("y",R).attr("fill","red").attr("text-anchor","middle").text(f.title);window.label=ge;const ye=ge.node().getBBox();se.insert("rect",":first-child").attr("class","box").attr("x",ye.x-p.padding/2).attr("y",ye.y-p.padding/2).attr("width",ye.width+p.padding).attr("height",ye.height+p.padding)}Fe.info("Rendering relation "+JSON.stringify(f)),f.relationTitle1!==void 0&&f.relationTitle1!=="none"&&i.append("g").attr("class","cardinality").append("text").attr("class","type1").attr("x",V).attr("y",Q).attr("fill","black").attr("font-size","6").text(f.relationTitle1),f.relationTitle2!==void 0&&f.relationTitle2!=="none"&&i.append("g").attr("class","cardinality").append("text").attr("class","type2").attr("x",oe).attr("y",ce).attr("fill","black").attr("font-size","6").text(f.relationTitle2),HBe++},zRt=function(i,a,f,p){Fe.debug("Rendering class ",a,f);const w=a.id,y={id:w,label:a.id,width:0,height:0},b=i.append("g").attr("id",p.db.lookUpDomId(w)).attr("class","classGroup");let E;a.link?E=b.append("svg:a").attr("xlink:href",a.link).attr("target",a.linkTarget).append("text").attr("y",f.textHeight+f.padding).attr("x",0):E=b.append("text").attr("y",f.textHeight+f.padding).attr("x",0);let S=!0;a.annotations.forEach(function(ke){const Ae=E.append("tspan").text("«"+ke+"»");S||Ae.attr("dy",f.textHeight),S=!1});let N=zBe(a);const B=E.append("tspan").text(N).attr("class","title");S||B.attr("dy",f.textHeight);const R=E.node().getBBox().height,j=b.append("line").attr("x1",0).attr("y1",f.padding+R+f.dividerMargin/2).attr("y2",f.padding+R+f.dividerMargin/2),$=b.append("text").attr("x",f.padding).attr("y",R+f.dividerMargin+f.textHeight).attr("fill","white").attr("class","classText");S=!0,a.members.forEach(function(ke){GBe($,ke,S,f),S=!1});const V=$.node().getBBox(),Q=b.append("line").attr("x1",0).attr("y1",f.padding+R+f.dividerMargin+V.height).attr("y2",f.padding+R+f.dividerMargin+V.height),oe=b.append("text").attr("x",f.padding).attr("y",R+2*f.dividerMargin+V.height+f.textHeight).attr("fill","white").attr("class","classText");S=!0,a.methods.forEach(function(ke){GBe(oe,ke,S,f),S=!1});const ce=b.node().getBBox();var se=" ";a.cssClasses.length>0&&(se=se+a.cssClasses.join(" "));const ye=b.insert("rect",":first-child").attr("x",0).attr("y",0).attr("width",ce.width+2*f.padding).attr("height",ce.height+f.padding+.5*f.dividerMargin).attr("class",se).node().getBBox().width;return E.node().childNodes.forEach(function(ke){ke.setAttribute("x",(ye-ke.getBBox().width)/2)}),a.tooltip&&E.insert("title").text(a.tooltip),j.attr("x2",ye),Q.attr("x2",ye),y.width=ye,y.height=ce.height+f.padding+.5*f.dividerMargin,y},zBe=function(i){let a=i.id;return i.type&&(a+="<"+i.type+">"),a},GRt=function(i,a,f,p){Fe.debug("Rendering note ",a,f);const w=a.id,y={id:w,text:a.text,width:0,height:0},b=i.append("g").attr("id",w).attr("class","classGroup");let E=b.append("text").attr("y",f.textHeight+f.padding).attr("x",0);const S=JSON.parse(`"${a.text}"`).split(` +`);S.forEach(function(j){Fe.debug(`Adding line: ${j}`),E.append("tspan").text(j).attr("class","title").attr("dy",f.textHeight)});const N=b.node().getBBox(),R=b.insert("rect",":first-child").attr("x",0).attr("y",0).attr("width",N.width+2*f.padding).attr("height",N.height+S.length*f.textHeight+f.padding+.5*f.dividerMargin).node().getBBox().width;return E.node().childNodes.forEach(function(j){j.setAttribute("x",(R-j.getBBox().width)/2)}),y.width=R,y.height=N.height+S.length*f.textHeight+f.padding+.5*f.dividerMargin,y},bK=function(i){const a=/^([#+~-])?(\w+)(~\w+~|\[])?\s+(\w+) *([$*])?$/,f=/^([#+|~-])?(\w+) *\( *(.*)\) *([$*])? *(\w*[[\]|~]*\s*\w*~?)$/;let p=i.match(a),w=i.match(f);return p&&!w?qRt(p):w?VRt(w):URt(i)},qRt=function(i){let a="",f="";try{let p=i[1]?i[1].trim():"",w=i[2]?i[2].trim():"",y=i[3]?Yk(i[3].trim()):"",b=i[4]?i[4].trim():"",E=i[5]?i[5].trim():"";f=p+w+y+" "+b,a=vK(E)}catch{f=i}return{displayText:f,cssStyle:a}},VRt=function(i){let a="",f="";try{let p=i[1]?i[1].trim():"",w=i[2]?i[2].trim():"",y=i[3]?Yk(i[3].trim()):"",b=i[4]?i[4].trim():"",E=i[5]?" : "+Yk(i[5]).trim():"";f=p+w+"("+y+")"+E,a=vK(b)}catch{f=i}return{displayText:f,cssStyle:a}},URt=function(i){let a="",f="",p="",w="",y=i.substring(0,1),b=i.substring(i.length-1,i.length);y.match(/[#+~-]/)&&(w=y);let E=/[\s\w)~]/;b.match(E)||(f=vK(b));let S=w===""?0:1,N=f===""?i.length:i.length-1;i=i.substring(S,N);let B=i.indexOf("("),R=i.indexOf(")");if(B>1&&R>B&&R<=i.length){let j=i.substring(0,B).trim();const $=i.substring(B+1,R);if(a=w+j+"("+Yk($.trim())+")",R{const{shapeSvg:f,bbox:p}=await jd(i,a,void 0,!0),w=p.width+a.padding,y=p.height+a.padding,b=w+y,E=[{x:b/2,y:0},{x:b,y:-b/2},{x:b/2,y:-b},{x:0,y:-b/2}];Fe.info("Question main (Circle)");const S=T5(f,b,b,E);return S.attr("style",a.style),uf(a,S),a.intersect=function(N){return Fe.warn("Intersect called"),Lh.polygon(a,E,N)},f},WRt=(i,a)=>{const f=i.insert("g").attr("class","node default").attr("id",a.domId||a.id),p=28,w=[{x:0,y:p/2},{x:p/2,y:0},{x:0,y:-p/2},{x:-p/2,y:0}];return f.insert("polygon",":first-child").attr("points",w.map(function(b){return b.x+","+b.y}).join(" ")).attr("class","state-start").attr("r",7).attr("width",28).attr("height",28),a.width=28,a.height=28,a.intersect=function(b){return Lh.circle(a,14,b)},f},KRt=async(i,a)=>{const{shapeSvg:f,bbox:p}=await jd(i,a,void 0,!0),w=4,y=p.height+a.padding,b=y/w,E=p.width+2*b+a.padding,S=[{x:b,y:0},{x:E-b,y:0},{x:E,y:-y/2},{x:E-b,y:-y},{x:b,y:-y},{x:0,y:-y/2}],N=T5(f,E,y,S);return N.attr("style",a.style),uf(a,N),a.intersect=function(B){return Lh.polygon(a,S,B)},f},YRt=async(i,a)=>{const{shapeSvg:f,bbox:p}=await jd(i,a,void 0,!0),w=p.width+a.padding,y=p.height+a.padding,b=[{x:-y/2,y:0},{x:w,y:0},{x:w,y:-y},{x:-y/2,y:-y},{x:0,y:-y/2}];return T5(f,w,y,b).attr("style",a.style),a.width=w+y,a.height=y,a.intersect=function(S){return Lh.polygon(a,b,S)},f},XRt=async(i,a)=>{const{shapeSvg:f,bbox:p}=await jd(i,a,void 0,!0),w=p.width+a.padding,y=p.height+a.padding,b=[{x:-2*y/6,y:0},{x:w-y/6,y:0},{x:w+2*y/6,y:-y},{x:y/6,y:-y}],E=T5(f,w,y,b);return E.attr("style",a.style),uf(a,E),a.intersect=function(S){return Lh.polygon(a,b,S)},f},QRt=async(i,a)=>{const{shapeSvg:f,bbox:p}=await jd(i,a,void 0,!0),w=p.width+a.padding,y=p.height+a.padding,b=[{x:2*y/6,y:0},{x:w+y/6,y:0},{x:w-2*y/6,y:-y},{x:-y/6,y:-y}],E=T5(f,w,y,b);return E.attr("style",a.style),uf(a,E),a.intersect=function(S){return Lh.polygon(a,b,S)},f},ZRt=async(i,a)=>{const{shapeSvg:f,bbox:p}=await jd(i,a,void 0,!0),w=p.width+a.padding,y=p.height+a.padding,b=[{x:-2*y/6,y:0},{x:w+2*y/6,y:0},{x:w-y/6,y:-y},{x:y/6,y:-y}],E=T5(f,w,y,b);return E.attr("style",a.style),uf(a,E),a.intersect=function(S){return Lh.polygon(a,b,S)},f},JRt=async(i,a)=>{const{shapeSvg:f,bbox:p}=await jd(i,a,void 0,!0),w=p.width+a.padding,y=p.height+a.padding,b=[{x:y/6,y:0},{x:w-y/6,y:0},{x:w+2*y/6,y:-y},{x:-2*y/6,y:-y}],E=T5(f,w,y,b);return E.attr("style",a.style),uf(a,E),a.intersect=function(S){return Lh.polygon(a,b,S)},f},eFt=async(i,a)=>{const{shapeSvg:f,bbox:p}=await jd(i,a,void 0,!0),w=p.width+a.padding,y=p.height+a.padding,b=[{x:0,y:0},{x:w+y/2,y:0},{x:w,y:-y/2},{x:w+y/2,y:-y},{x:0,y:-y}],E=T5(f,w,y,b);return E.attr("style",a.style),uf(a,E),a.intersect=function(S){return Lh.polygon(a,b,S)},f},tFt=async(i,a)=>{const{shapeSvg:f,bbox:p}=await jd(i,a,void 0,!0),w=p.width+a.padding,y=w/2,b=y/(2.5+w/50),E=p.height+b+a.padding,S="M 0,"+b+" a "+y+","+b+" 0,0,0 "+w+" 0 a "+y+","+b+" 0,0,0 "+-w+" 0 l 0,"+E+" a "+y+","+b+" 0,0,0 "+w+" 0 l 0,"+-E,N=f.attr("label-offset-y",b).insert("path",":first-child").attr("style",a.style).attr("d",S).attr("transform","translate("+-w/2+","+-(E/2+b)+")");return uf(a,N),a.intersect=function(B){const R=Lh.rect(a,B),j=R.x-a.x;if(y!=0&&(Math.abs(j)a.height/2-b)){let $=b*b*(1-j*j/(y*y));$!=0&&($=Math.sqrt($)),$=b-$,B.y-a.y>0&&($=-$),R.y+=$}return R},f},nFt=async(i,a)=>{const{shapeSvg:f,bbox:p,halfPadding:w}=await jd(i,a,"node "+a.classes,!0),y=f.insert("rect",":first-child"),b=p.width+a.padding,E=p.height+a.padding;if(y.attr("class","basic label-container").attr("style",a.style).attr("rx",a.rx).attr("ry",a.ry).attr("x",-p.width/2-w).attr("y",-p.height/2-w).attr("width",b).attr("height",E),a.props){const S=new Set(Object.keys(a.props));a.props.borders&&(VBe(y,a.props.borders,b,E),S.delete("borders")),S.forEach(N=>{Fe.warn(`Unknown node property ${N}`)})}return uf(a,y),a.intersect=function(S){return Lh.rect(a,S)},f},rFt=async(i,a)=>{const{shapeSvg:f}=await jd(i,a,"label",!0);Fe.trace("Classes = ",a.classes);const p=f.insert("rect",":first-child"),w=0,y=0;if(p.attr("width",w).attr("height",y),f.attr("class","label edgeLabel"),a.props){const b=new Set(Object.keys(a.props));a.props.borders&&(VBe(p,a.props.borders,w,y),b.delete("borders")),b.forEach(E=>{Fe.warn(`Unknown node property ${E}`)})}return uf(a,p),a.intersect=function(b){return Lh.rect(a,b)},f};function VBe(i,a,f,p){const w=[],y=E=>{w.push(E,0)},b=E=>{w.push(0,E)};a.includes("t")?(Fe.debug("add top border"),y(f)):b(f),a.includes("r")?(Fe.debug("add right border"),y(p)):b(p),a.includes("b")?(Fe.debug("add bottom border"),y(f)):b(f),a.includes("l")?(Fe.debug("add left border"),y(p)):b(p),i.attr("stroke-dasharray",w.join(" "))}const iFt=(i,a)=>{let f;a.classes?f="node "+a.classes:f="node default";const p=i.insert("g").attr("class",f).attr("id",a.domId||a.id),w=p.insert("rect",":first-child"),y=p.insert("line"),b=p.insert("g").attr("class","label"),E=a.labelText.flat?a.labelText.flat():a.labelText;let S="";typeof E=="object"?S=E[0]:S=E,Fe.info("Label text abc79",S,E,typeof E=="object");const N=b.node().appendChild(sp(S,a.labelStyle,!0,!0));let B={width:0,height:0};if(d1(Tt().flowchart.htmlLabels)){const Q=N.children[0],oe=Cr(N);B=Q.getBoundingClientRect(),oe.attr("width",B.width),oe.attr("height",B.height)}Fe.info("Text 2",E);const R=E.slice(1,E.length);let j=N.getBBox();const $=b.node().appendChild(sp(R.join?R.join("
"):R,a.labelStyle,!0,!0));if(d1(Tt().flowchart.htmlLabels)){const Q=$.children[0],oe=Cr($);B=Q.getBoundingClientRect(),oe.attr("width",B.width),oe.attr("height",B.height)}const V=a.padding/2;return Cr($).attr("transform","translate( "+(B.width>j.width?0:(j.width-B.width)/2)+", "+(j.height+V+5)+")"),Cr(N).attr("transform","translate( "+(B.width{const{shapeSvg:f,bbox:p}=await jd(i,a,void 0,!0),w=p.height+a.padding,y=p.width+w/4+a.padding,b=f.insert("rect",":first-child").attr("style",a.style).attr("rx",w/2).attr("ry",w/2).attr("x",-y/2).attr("y",-w/2).attr("width",y).attr("height",w);return uf(a,b),a.intersect=function(E){return Lh.rect(a,E)},f},aFt=async(i,a)=>{const{shapeSvg:f,bbox:p,halfPadding:w}=await jd(i,a,void 0,!0),y=f.insert("circle",":first-child");return y.attr("style",a.style).attr("rx",a.rx).attr("ry",a.ry).attr("r",p.width/2+w).attr("width",p.width+a.padding).attr("height",p.height+a.padding),Fe.info("Circle main"),uf(a,y),a.intersect=function(b){return Fe.info("Circle intersect",a,p.width/2+w,b),Lh.circle(a,p.width/2+w,b)},f},oFt=async(i,a)=>{const{shapeSvg:f,bbox:p,halfPadding:w}=await jd(i,a,void 0,!0),y=5,b=f.insert("g",":first-child"),E=b.insert("circle"),S=b.insert("circle");return E.attr("style",a.style).attr("rx",a.rx).attr("ry",a.ry).attr("r",p.width/2+w+y).attr("width",p.width+a.padding+y*2).attr("height",p.height+a.padding+y*2),S.attr("style",a.style).attr("rx",a.rx).attr("ry",a.ry).attr("r",p.width/2+w).attr("width",p.width+a.padding).attr("height",p.height+a.padding),Fe.info("DoubleCircle main"),uf(a,E),a.intersect=function(N){return Fe.info("DoubleCircle intersect",a,p.width/2+w+y,N),Lh.circle(a,p.width/2+w+y,N)},f},cFt=async(i,a)=>{const{shapeSvg:f,bbox:p}=await jd(i,a,void 0,!0),w=p.width+a.padding,y=p.height+a.padding,b=[{x:0,y:0},{x:w,y:0},{x:w,y:-y},{x:0,y:-y},{x:0,y:0},{x:-8,y:0},{x:w+8,y:0},{x:w+8,y:-y},{x:-8,y:-y},{x:-8,y:0}],E=T5(f,w,y,b);return E.attr("style",a.style),uf(a,E),a.intersect=function(S){return Lh.polygon(a,b,S)},f},uFt=(i,a)=>{const f=i.insert("g").attr("class","node default").attr("id",a.domId||a.id),p=f.insert("circle",":first-child");return p.attr("class","state-start").attr("r",7).attr("width",14).attr("height",14),uf(a,p),a.intersect=function(w){return Lh.circle(a,7,w)},f},UBe=(i,a,f)=>{const p=i.insert("g").attr("class","node default").attr("id",a.domId||a.id);let w=70,y=10;f==="LR"&&(w=10,y=70);const b=p.append("rect").attr("x",-1*w/2).attr("y",-1*y/2).attr("width",w).attr("height",y).attr("class","fork-join");return uf(a,b),a.height=a.height+a.padding/2,a.width=a.width+a.padding/2,a.intersect=function(E){return Lh.rect(a,E)},p},WBe={rhombus:qBe,question:qBe,rect:nFt,labelRect:rFt,rectWithTitle:iFt,choice:WRt,circle:aFt,doublecircle:oFt,stadium:sFt,hexagon:KRt,rect_left_inv_arrow:YRt,lean_right:XRt,lean_left:QRt,trapezoid:ZRt,inv_trapezoid:JRt,rect_right_inv_arrow:eFt,cylinder:tFt,start:uFt,end:(i,a)=>{const f=i.insert("g").attr("class","node default").attr("id",a.domId||a.id),p=f.insert("circle",":first-child"),w=f.insert("circle",":first-child");return w.attr("class","state-start").attr("r",7).attr("width",14).attr("height",14),p.attr("class","state-end").attr("r",5).attr("width",10).attr("height",10),uf(a,w),a.intersect=function(y){return Lh.circle(a,7,y)},f},note:$Rt,subroutine:cFt,fork:UBe,join:UBe,class_box:(i,a)=>{const f=a.padding/2,p=4,w=8;let y;a.classes?y="node "+a.classes:y="node default";const b=i.insert("g").attr("class",y).attr("id",a.domId||a.id),E=b.insert("rect",":first-child"),S=b.insert("line"),N=b.insert("line");let B=0,R=p;const j=b.insert("g").attr("class","label");let $=0;const V=a.classData.annotations&&a.classData.annotations[0],Q=a.classData.annotations[0]?"«"+a.classData.annotations[0]+"»":"",oe=j.node().appendChild(sp(Q,a.labelStyle,!0,!0));let ce=oe.getBBox();if(d1(Tt().flowchart.htmlLabels)){const ve=oe.children[0],te=Cr(oe);ce=ve.getBoundingClientRect(),te.attr("width",ce.width),te.attr("height",ce.height)}a.classData.annotations[0]&&(R+=ce.height+p,B+=ce.width);let se=a.classData.label;a.classData.type!==void 0&&a.classData.type!==""&&(Tt().flowchart.htmlLabels?se+="<"+a.classData.type+">":se+="<"+a.classData.type+">");const ge=j.node().appendChild(sp(se,a.labelStyle,!0,!0));Cr(ge).attr("class","classTitle");let ye=ge.getBBox();if(d1(Tt().flowchart.htmlLabels)){const ve=ge.children[0],te=Cr(ge);ye=ve.getBoundingClientRect(),te.attr("width",ye.width),te.attr("height",ye.height)}R+=ye.height+p,ye.width>B&&(B=ye.width);const ke=[];a.classData.members.forEach(ve=>{const te=bK(ve);let xe=te.displayText;Tt().flowchart.htmlLabels&&(xe=xe.replace(//g,">"));const De=j.node().appendChild(sp(xe,te.cssStyle?te.cssStyle:a.labelStyle,!0,!0));let he=De.getBBox();if(d1(Tt().flowchart.htmlLabels)){const Ie=De.children[0],ee=Cr(De);he=Ie.getBoundingClientRect(),ee.attr("width",he.width),ee.attr("height",he.height)}he.width>B&&(B=he.width),R+=he.height+p,ke.push(De)}),R+=w;const Ae=[];if(a.classData.methods.forEach(ve=>{const te=bK(ve);let xe=te.displayText;Tt().flowchart.htmlLabels&&(xe=xe.replace(//g,">"));const De=j.node().appendChild(sp(xe,te.cssStyle?te.cssStyle:a.labelStyle,!0,!0));let he=De.getBBox();if(d1(Tt().flowchart.htmlLabels)){const Ie=De.children[0],ee=Cr(De);he=Ie.getBoundingClientRect(),ee.attr("width",he.width),ee.attr("height",he.height)}he.width>B&&(B=he.width),R+=he.height+p,Ae.push(De)}),R+=w,V){let ve=(B-ce.width)/2;Cr(oe).attr("transform","translate( "+(-1*B/2+ve)+", "+-1*R/2+")"),$=ce.height+p}let de=(B-ye.width)/2;return Cr(ge).attr("transform","translate( "+(-1*B/2+de)+", "+(-1*R/2+$)+")"),$+=ye.height+p,S.attr("class","divider").attr("x1",-B/2-f).attr("x2",B/2+f).attr("y1",-R/2-f+w+$).attr("y2",-R/2-f+w+$),$+=w,ke.forEach(ve=>{Cr(ve).attr("transform","translate( "+-B/2+", "+(-1*R/2+$+w/2)+")"),$+=ye.height+p}),$+=w,N.attr("class","divider").attr("x1",-B/2-f).attr("x2",B/2+f).attr("y1",-R/2-f+w+$).attr("y2",-R/2-f+w+$),$+=w,Ae.forEach(ve=>{Cr(ve).attr("transform","translate( "+-B/2+", "+(-1*R/2+$)+")"),$+=ye.height+p}),E.attr("class","outer title-state").attr("x",-B/2-f).attr("y",-(R/2)-f).attr("width",B+a.padding).attr("height",R+a.padding),uf(a,E),a.intersect=function(ve){return Lh.rect(a,ve)},b}};let rL={};const KBe=async(i,a,f)=>{let p,w;if(a.link){let y;Tt().securityLevel==="sandbox"?y="_top":a.linkTarget&&(y=a.linkTarget||"_blank"),p=i.insert("svg:a").attr("xlink:href",a.link).attr("target",y),w=await WBe[a.shape](p,a,f)}else w=await WBe[a.shape](i,a,f),p=w;return a.tooltip&&w.attr("title",a.tooltip),a.class&&w.attr("class","node default "+a.class),rL[a.id]=p,a.haveCallback&&rL[a.id].attr("class",rL[a.id].attr("class")+" clickable"),p},lFt=(i,a)=>{rL[a.id]=i},hFt=()=>{rL={}},YBe=i=>{const a=rL[i.id];Fe.trace("Transforming node",i.diff,i,"translate("+(i.x-i.width/2-5)+", "+i.width/2+")");const f=8,p=i.diff||0;return i.clusterNode?a.attr("transform","translate("+(i.x+p-i.width/2)+", "+(i.y-i.height/2-f)+")"):a.attr("transform","translate("+i.x+", "+i.y+")"),p},fFt={rect:(i,a)=>{Fe.info("Creating subgraph rect for ",a.id,a);const f=i.insert("g").attr("class","cluster"+(a.class?" "+a.class:"")).attr("id",a.id),p=f.insert("rect",":first-child"),w=d1(Tt().flowchart.htmlLabels),y=f.insert("g").attr("class","cluster-label"),b=a.labelType==="markdown"?dK(y,a.labelText,{style:a.labelStyle,useHtmlLabels:w}):y.node().appendChild(sp(a.labelText,a.labelStyle,void 0,!0));let E=b.getBBox();if(d1(Tt().flowchart.htmlLabels)){const j=b.children[0],$=Cr(b);E=j.getBoundingClientRect(),$.attr("width",E.width),$.attr("height",E.height)}const S=0*a.padding,N=S/2,B=a.width<=E.width+S?E.width+S:a.width;a.width<=E.width+S?a.diff=(E.width-a.width)/2-a.padding/2:a.diff=-a.padding/2,Fe.trace("Data ",a,JSON.stringify(a)),p.attr("style",a.style).attr("rx",a.rx).attr("ry",a.ry).attr("x",a.x-B/2).attr("y",a.y-a.height/2-N).attr("width",B).attr("height",a.height+S),w?y.attr("transform","translate("+(a.x-E.width/2)+", "+(a.y-a.height/2)+")"):y.attr("transform","translate("+a.x+", "+(a.y-a.height/2)+")");const R=p.node().getBBox();return a.width=R.width,a.height=R.height,a.intersect=function(j){return bP(a,j)},f},roundedWithTitle:(i,a)=>{const f=i.insert("g").attr("class",a.classes).attr("id",a.id),p=f.insert("rect",":first-child"),w=f.insert("g").attr("class","cluster-label"),y=f.append("rect"),b=w.node().appendChild(sp(a.labelText,a.labelStyle,void 0,!0));let E=b.getBBox();if(d1(Tt().flowchart.htmlLabels)){const j=b.children[0],$=Cr(b);E=j.getBoundingClientRect(),$.attr("width",E.width),$.attr("height",E.height)}E=b.getBBox();const S=0*a.padding,N=S/2,B=a.width<=E.width+a.padding?E.width+a.padding:a.width;a.width<=E.width+a.padding?a.diff=(E.width+a.padding*0-a.width)/2:a.diff=-a.padding/2,p.attr("class","outer").attr("x",a.x-B/2-N).attr("y",a.y-a.height/2-N).attr("width",B+S).attr("height",a.height+S),y.attr("class","inner").attr("x",a.x-B/2-N).attr("y",a.y-a.height/2-N+E.height-1).attr("width",B+S).attr("height",a.height+S-E.height-3),w.attr("transform","translate("+(a.x-E.width/2)+", "+(a.y-a.height/2-a.padding/3+(d1(Tt().flowchart.htmlLabels)?5:3))+")");const R=p.node().getBBox();return a.height=R.height,a.intersect=function(j){return bP(a,j)},f},noteGroup:(i,a)=>{const f=i.insert("g").attr("class","note-cluster").attr("id",a.id),p=f.insert("rect",":first-child"),w=0*a.padding,y=w/2;p.attr("rx",a.rx).attr("ry",a.ry).attr("x",a.x-a.width/2-y).attr("y",a.y-a.height/2-y).attr("width",a.width+w).attr("height",a.height+w).attr("fill","none");const b=p.node().getBBox();return a.width=b.width,a.height=b.height,a.intersect=function(E){return bP(a,E)},f},divider:(i,a)=>{const f=i.insert("g").attr("class",a.classes).attr("id",a.id),p=f.insert("rect",":first-child"),w=0*a.padding,y=w/2;p.attr("class","divider").attr("x",a.x-a.width/2-y).attr("y",a.y-a.height/2).attr("width",a.width+w).attr("height",a.height+w);const b=p.node().getBBox();return a.width=b.width,a.height=b.height,a.diff=-a.padding/2,a.intersect=function(E){return bP(a,E)},f}};let XBe={};const dFt=(i,a)=>{Fe.trace("Inserting cluster");const f=a.shape||"rect";XBe[a.id]=fFt[f](i,a)},gFt=()=>{XBe={}};let wK={},$d={};const pFt=()=>{wK={},$d={}},QBe=(i,a)=>{const f=d1(Tt().flowchart.htmlLabels),p=a.labelType==="markdown"?dK(i,a.label,{style:a.labelStyle,useHtmlLabels:f,addSvgBackground:!0}):sp(a.label,a.labelStyle);Fe.info("abc82",a,a.labelType);const w=i.insert("g").attr("class","edgeLabel"),y=w.insert("g").attr("class","label");y.node().appendChild(p);let b=p.getBBox();if(f){const S=p.children[0],N=Cr(p);b=S.getBoundingClientRect(),N.attr("width",b.width),N.attr("height",b.height)}y.attr("transform","translate("+-b.width/2+", "+-b.height/2+")"),wK[a.id]=w,a.width=b.width,a.height=b.height;let E;if(a.startLabelLeft){const S=sp(a.startLabelLeft,a.labelStyle),N=i.insert("g").attr("class","edgeTerminals"),B=N.insert("g").attr("class","inner");E=B.node().appendChild(S);const R=S.getBBox();B.attr("transform","translate("+-R.width/2+", "+-R.height/2+")"),$d[a.id]||($d[a.id]={}),$d[a.id].startLeft=N,mK(E,a.startLabelLeft)}if(a.startLabelRight){const S=sp(a.startLabelRight,a.labelStyle),N=i.insert("g").attr("class","edgeTerminals"),B=N.insert("g").attr("class","inner");E=N.node().appendChild(S),B.node().appendChild(S);const R=S.getBBox();B.attr("transform","translate("+-R.width/2+", "+-R.height/2+")"),$d[a.id]||($d[a.id]={}),$d[a.id].startRight=N,mK(E,a.startLabelRight)}if(a.endLabelLeft){const S=sp(a.endLabelLeft,a.labelStyle),N=i.insert("g").attr("class","edgeTerminals"),B=N.insert("g").attr("class","inner");E=B.node().appendChild(S);const R=S.getBBox();B.attr("transform","translate("+-R.width/2+", "+-R.height/2+")"),N.node().appendChild(S),$d[a.id]||($d[a.id]={}),$d[a.id].endLeft=N,mK(E,a.endLabelLeft)}if(a.endLabelRight){const S=sp(a.endLabelRight,a.labelStyle),N=i.insert("g").attr("class","edgeTerminals"),B=N.insert("g").attr("class","inner");E=B.node().appendChild(S);const R=S.getBBox();B.attr("transform","translate("+-R.width/2+", "+-R.height/2+")"),N.node().appendChild(S),$d[a.id]||($d[a.id]={}),$d[a.id].endRight=N,mK(E,a.endLabelRight)}return p};function mK(i,a){Tt().flowchart.htmlLabels&&i&&(i.style.width=a.length*9+"px",i.style.height="12px")}const bFt=(i,a)=>{Fe.info("Moving label abc78 ",i.id,i.label,wK[i.id]);let f=a.updatedPath?a.updatedPath:a.originalPath;if(i.label){const p=wK[i.id];let w=i.x,y=i.y;if(f){const b=co.calcLabelPosition(f);Fe.info("Moving label "+i.label+" from (",w,",",y,") to (",b.x,",",b.y,") abc78"),a.updatedPath&&(w=b.x,y=b.y)}p.attr("transform","translate("+w+", "+y+")")}if(i.startLabelLeft){const p=$d[i.id].startLeft;let w=i.x,y=i.y;if(f){const b=co.calcTerminalLabelPosition(i.arrowTypeStart?10:0,"start_left",f);w=b.x,y=b.y}p.attr("transform","translate("+w+", "+y+")")}if(i.startLabelRight){const p=$d[i.id].startRight;let w=i.x,y=i.y;if(f){const b=co.calcTerminalLabelPosition(i.arrowTypeStart?10:0,"start_right",f);w=b.x,y=b.y}p.attr("transform","translate("+w+", "+y+")")}if(i.endLabelLeft){const p=$d[i.id].endLeft;let w=i.x,y=i.y;if(f){const b=co.calcTerminalLabelPosition(i.arrowTypeEnd?10:0,"end_left",f);w=b.x,y=b.y}p.attr("transform","translate("+w+", "+y+")")}if(i.endLabelRight){const p=$d[i.id].endRight;let w=i.x,y=i.y;if(f){const b=co.calcTerminalLabelPosition(i.arrowTypeEnd?10:0,"end_right",f);w=b.x,y=b.y}p.attr("transform","translate("+w+", "+y+")")}},vFt=(i,a)=>{const f=i.x,p=i.y,w=Math.abs(a.x-f),y=Math.abs(a.y-p),b=i.width/2,E=i.height/2;return w>=b||y>=E},wFt=(i,a,f)=>{Fe.warn(`intersection calc abc89: + outsidePoint: ${JSON.stringify(a)} + insidePoint : ${JSON.stringify(f)} + node : x:${i.x} y:${i.y} w:${i.width} h:${i.height}`);const p=i.x,w=i.y,y=Math.abs(p-f.x),b=i.width/2;let E=f.xMath.abs(p-a.x)*S){let R=f.y{Fe.warn("abc88 cutPathAtIntersect",i,a);let f=[],p=i[0],w=!1;return i.forEach(y=>{if(Fe.info("abc88 checking point",y,a),!vFt(a,y)&&!w){const b=wFt(a,p,y);Fe.warn("abc88 inside",y,p,b),Fe.warn("abc88 intersection",b);let E=!1;f.forEach(S=>{E=E||S.x===b.x&&S.y===b.y}),f.some(S=>S.x===b.x&&S.y===b.y)?Fe.warn("abc88 no intersect",b,f):f.push(b),w=!0}else Fe.warn("abc88 outside",y,p),p=y,w||f.push(y)}),Fe.warn("abc88 returning points",f),f},mFt=function(i,a,f,p,w,y){let b=f.points,E=!1;const S=y.node(a.v);var N=y.node(a.w);Fe.info("abc88 InsertEdge: ",f),N.intersect&&S.intersect&&(b=b.slice(1,f.points.length-1),b.unshift(S.intersect(b[0])),Fe.info("Last point",b[b.length-1],N,N.intersect(b[b.length-1])),b.push(N.intersect(b[b.length-1]))),f.toCluster&&(Fe.info("to cluster abc88",p[f.toCluster]),b=ZBe(f.points,p[f.toCluster].node),E=!0),f.fromCluster&&(Fe.info("from cluster abc88",p[f.fromCluster]),b=ZBe(b.reverse(),p[f.fromCluster].node).reverse(),E=!0);const B=b.filter(ce=>!Number.isNaN(ce.y));let R;w==="graph"||w==="flowchart"?R=f.curve||SA:R=SA;const j=WE().x(function(ce){return ce.x}).y(function(ce){return ce.y}).curve(R);let $;switch(f.thickness){case"normal":$="edge-thickness-normal";break;case"thick":$="edge-thickness-thick";break;case"invisible":$="edge-thickness-thick";break;default:$=""}switch(f.pattern){case"solid":$+=" edge-pattern-solid";break;case"dotted":$+=" edge-pattern-dotted";break;case"dashed":$+=" edge-pattern-dashed";break}const V=i.append("path").attr("d",j(B)).attr("id",f.id).attr("class"," "+$+(f.classes?" "+f.classes:"")).attr("style",f.style);let Q="";switch((Tt().flowchart.arrowMarkerAbsolute||Tt().state.arrowMarkerAbsolute)&&(Q=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search,Q=Q.replace(/\(/g,"\\("),Q=Q.replace(/\)/g,"\\)")),Fe.info("arrowTypeStart",f.arrowTypeStart),Fe.info("arrowTypeEnd",f.arrowTypeEnd),f.arrowTypeStart){case"arrow_cross":V.attr("marker-start","url("+Q+"#"+w+"-crossStart)");break;case"arrow_point":V.attr("marker-start","url("+Q+"#"+w+"-pointStart)");break;case"arrow_barb":V.attr("marker-start","url("+Q+"#"+w+"-barbStart)");break;case"arrow_circle":V.attr("marker-start","url("+Q+"#"+w+"-circleStart)");break;case"aggregation":V.attr("marker-start","url("+Q+"#"+w+"-aggregationStart)");break;case"extension":V.attr("marker-start","url("+Q+"#"+w+"-extensionStart)");break;case"composition":V.attr("marker-start","url("+Q+"#"+w+"-compositionStart)");break;case"dependency":V.attr("marker-start","url("+Q+"#"+w+"-dependencyStart)");break;case"lollipop":V.attr("marker-start","url("+Q+"#"+w+"-lollipopStart)");break}switch(f.arrowTypeEnd){case"arrow_cross":V.attr("marker-end","url("+Q+"#"+w+"-crossEnd)");break;case"arrow_point":V.attr("marker-end","url("+Q+"#"+w+"-pointEnd)");break;case"arrow_barb":V.attr("marker-end","url("+Q+"#"+w+"-barbEnd)");break;case"arrow_circle":V.attr("marker-end","url("+Q+"#"+w+"-circleEnd)");break;case"aggregation":V.attr("marker-end","url("+Q+"#"+w+"-aggregationEnd)");break;case"extension":V.attr("marker-end","url("+Q+"#"+w+"-extensionEnd)");break;case"composition":V.attr("marker-end","url("+Q+"#"+w+"-compositionEnd)");break;case"dependency":V.attr("marker-end","url("+Q+"#"+w+"-dependencyEnd)");break;case"lollipop":V.attr("marker-end","url("+Q+"#"+w+"-lollipopEnd)");break}let oe={};return E&&(oe.updatedPath=b),oe.originalPath=f.points,oe},JBe=async(i,a,f,p)=>{Fe.info("Graph in recursive render: XXX",E5(a),p);const w=a.graph().rankdir;Fe.trace("Dir in recursive render - dir:",w);const y=i.insert("g").attr("class","root");a.nodes()?Fe.info("Recursive render XXX",a.nodes()):Fe.info("No nodes found for",a),a.edges().length>0&&Fe.trace("Recursive edges",a.edge(a.edges()[0]));const b=y.insert("g").attr("class","clusters"),E=y.insert("g").attr("class","edgePaths"),S=y.insert("g").attr("class","edgeLabels"),N=y.insert("g").attr("class","nodes");await Promise.all(a.nodes().map(async function(R){const j=a.node(R);if(p!==void 0){const $=JSON.parse(JSON.stringify(p.clusterData));Fe.info("Setting data for cluster XXX (",R,") ",$,p),a.setNode(p.id,$),a.parent(R)||(Fe.trace("Setting parent",R,p.id),a.setParent(R,p.id,$))}if(Fe.info("(Insert) Node XXX"+R+": "+JSON.stringify(a.node(R))),j&&j.clusterNode){Fe.info("Cluster identified",R,j.width,a.node(R));const $=await JBe(N,j.graph,f,a.node(R)),V=$.elem;uf(j,V),j.diff=$.diff||0,Fe.info("Node bounds (abc123)",R,j,j.width,j.x,j.y),lFt(V,j),Fe.warn("Recursive render complete ",V,j)}else a.children(R).length>0?(Fe.info("Cluster - the non recursive path XXX",R,j.id,j,a),Fe.info(pP(j.id,a)),ec[j.id]={id:pP(j.id,a),node:j}):(Fe.info("Node - the non recursive path",R,j.id,j),await KBe(N,a.node(R),w))})),a.edges().forEach(function(R){const j=a.edge(R.v,R.w,R.name);Fe.info("Edge "+R.v+" -> "+R.w+": "+JSON.stringify(R)),Fe.info("Edge "+R.v+" -> "+R.w+": ",R," ",JSON.stringify(a.edge(R))),Fe.info("Fix",ec,"ids:",R.v,R.w,"Translateing: ",ec[R.v],ec[R.w]),QBe(S,j)}),a.edges().forEach(function(R){Fe.info("Edge "+R.v+" -> "+R.w+": "+JSON.stringify(R))}),Fe.info("#############################################"),Fe.info("### Layout ###"),Fe.info("#############################################"),Fe.info(a),tL(a),Fe.info("Graph after layout:",E5(a));let B=0;return PRt(a).forEach(function(R){const j=a.node(R);Fe.info("Position "+R+": "+JSON.stringify(a.node(R))),Fe.info("Position "+R+": ("+j.x,","+j.y,") width: ",j.width," height: ",j.height),j&&j.clusterNode?YBe(j):a.children(R).length>0?(dFt(b,j),ec[j.id].node=j):YBe(j)}),a.edges().forEach(function(R){const j=a.edge(R);Fe.info("Edge "+R.v+" -> "+R.w+": "+JSON.stringify(j),j);const $=mFt(E,R,j,ec,f,a);bFt(j,$)}),a.nodes().forEach(function(R){const j=a.node(R);Fe.info(R,j.type,j.diff),j.type==="group"&&(B=j.diff)}),{elem:y,diff:B}},C0e=async(i,a,f,p,w)=>{vBe(i,f,p,w),hFt(),pFt(),gFt(),IRt(),Fe.warn("Graph at first:",E5(a)),NRt(a),Fe.warn("Graph after:",E5(a)),await JBe(i,a,p)},eRe={},yFt=function(i){const a=Object.keys(i);for(const f of a)eRe[f]=i[f]},tRe=function(i,a,f,p,w,y){const b=p.select(`[id="${f}"]`);Object.keys(i).forEach(function(S){const N=i[S];let B="default";N.classes.length>0&&(B=N.classes.join(" ")),B=B+" flowchart-label";const R=Yw(N.styles);let j=N.text!==void 0?N.text:N.id,$;if(Fe.info("vertex",N,N.labelType),N.labelType==="markdown")Fe.info("vertex",N,N.labelType);else if(d1(Tt().flowchart.htmlLabels)){const oe={label:j.replace(/fa[blrs]?:fa-[\w-]+/g,ce=>``)};$=h0e(b,oe).node(),$.parentNode.removeChild($)}else{const oe=w.createElementNS("http://www.w3.org/2000/svg","text");oe.setAttribute("style",R.labelStyle.replace("color:","fill:"));const ce=j.split(Wa.lineBreakRegex);for(const se of ce){const ge=w.createElementNS("http://www.w3.org/2000/svg","tspan");ge.setAttributeNS("http://www.w3.org/XML/1998/namespace","xml:space","preserve"),ge.setAttribute("dy","1em"),ge.setAttribute("x","1"),ge.textContent=se,oe.appendChild(ge)}$=oe}let V=0,Q="";switch(N.type){case"round":V=5,Q="rect";break;case"square":Q="rect";break;case"diamond":Q="question";break;case"hexagon":Q="hexagon";break;case"odd":Q="rect_left_inv_arrow";break;case"lean_right":Q="lean_right";break;case"lean_left":Q="lean_left";break;case"trapezoid":Q="trapezoid";break;case"inv_trapezoid":Q="inv_trapezoid";break;case"odd_right":Q="rect_left_inv_arrow";break;case"circle":Q="circle";break;case"ellipse":Q="ellipse";break;case"stadium":Q="stadium";break;case"subroutine":Q="subroutine";break;case"cylinder":Q="cylinder";break;case"group":Q="rect";break;case"doublecircle":Q="doublecircle";break;default:Q="rect"}a.setNode(N.id,{labelStyle:R.labelStyle,shape:Q,labelText:j,labelType:N.labelType,rx:V,ry:V,class:B,style:R.style,id:N.id,link:N.link,linkTarget:N.linkTarget,tooltip:y.db.getTooltip(N.id)||"",domId:y.db.lookUpDomId(N.id),haveCallback:N.haveCallback,width:N.type==="group"?500:void 0,dir:N.dir,type:N.type,props:N.props,padding:Tt().flowchart.padding}),Fe.info("setNode",{labelStyle:R.labelStyle,labelType:N.labelType,shape:Q,labelText:j,rx:V,ry:V,class:B,style:R.style,id:N.id,domId:y.db.lookUpDomId(N.id),width:N.type==="group"?500:void 0,type:N.type,dir:N.dir,props:N.props,padding:Tt().flowchart.padding})})},nRe=function(i,a,f){Fe.info("abc78 edges = ",i);let p=0,w={},y,b;if(i.defaultStyle!==void 0){const E=Yw(i.defaultStyle);y=E.style,b=E.labelStyle}i.forEach(function(E){p++;var S="L-"+E.start+"-"+E.end;w[S]===void 0?(w[S]=0,Fe.info("abc78 new entry",S,w[S])):(w[S]++,Fe.info("abc78 new entry",S,w[S]));let N=S+"-"+w[S];Fe.info("abc78 new link id to be used is",S,N,w[S]);var B="LS-"+E.start,R="LE-"+E.end;const j={style:"",labelStyle:""};switch(j.minlen=E.length||1,E.type==="arrow_open"?j.arrowhead="none":j.arrowhead="normal",j.arrowTypeStart="arrow_open",j.arrowTypeEnd="arrow_open",E.type){case"double_arrow_cross":j.arrowTypeStart="arrow_cross";case"arrow_cross":j.arrowTypeEnd="arrow_cross";break;case"double_arrow_point":j.arrowTypeStart="arrow_point";case"arrow_point":j.arrowTypeEnd="arrow_point";break;case"double_arrow_circle":j.arrowTypeStart="arrow_circle";case"arrow_circle":j.arrowTypeEnd="arrow_circle";break}let $="",V="";switch(E.stroke){case"normal":$="fill:none;",y!==void 0&&($=y),b!==void 0&&(V=b),j.thickness="normal",j.pattern="solid";break;case"dotted":j.thickness="normal",j.pattern="dotted",j.style="fill:none;stroke-width:2px;stroke-dasharray:3;";break;case"thick":j.thickness="thick",j.pattern="solid",j.style="stroke-width: 3.5px;fill:none;";break;case"invisible":j.thickness="invisible",j.pattern="solid",j.style="stroke-width: 0;fill:none;";break}if(E.style!==void 0){const Q=Yw(E.style);$=Q.style,V=Q.labelStyle}j.style=j.style+=$,j.labelStyle=j.labelStyle+=V,E.interpolate!==void 0?j.curve=Ub(E.interpolate,ng):i.defaultInterpolate!==void 0?j.curve=Ub(i.defaultInterpolate,ng):j.curve=Ub(eRe.curve,ng),E.text===void 0?E.style!==void 0&&(j.arrowheadStyle="fill: #333"):(j.arrowheadStyle="fill: #333",j.labelpos="c"),j.labelType=E.labelType,j.label=E.text.replace(Wa.lineBreakRegex,` +`),E.style===void 0&&(j.style=j.style||"stroke: #333; stroke-width: 1.5px;fill:none;"),j.labelStyle=j.labelStyle.replace("color:","fill:"),j.id=N,j.classes="flowchart-link "+B+" "+R,a.setEdge(E.start,E.end,j,p)})},S0e={setConf:yFt,addVertices:tRe,addEdges:nRe,getClasses:function(i,a){Fe.info("Extracting classes"),a.db.clear();try{return a.parse(i),a.db.getClasses()}catch{return}},draw:async function(i,a,f,p){Fe.info("Drawing flowchart"),p.db.clear(),ix.setGen("gen-2"),p.parser.parse(i);let w=p.db.getDirection();w===void 0&&(w="TD");const{securityLevel:y,flowchart:b}=Tt(),E=b.nodeSpacing||50,S=b.rankSpacing||50;let N;y==="sandbox"&&(N=Cr("#i"+a));const B=Cr(y==="sandbox"?N.nodes()[0].contentDocument.body:"body"),R=y==="sandbox"?N.nodes()[0].contentDocument:document,j=new zf({multigraph:!0,compound:!0}).setGraph({rankdir:w,nodesep:E,ranksep:S,marginx:0,marginy:0}).setDefaultEdgeLabel(function(){return{}});let $;const V=p.db.getSubGraphs();Fe.info("Subgraphs - ",V);for(let ke=V.length-1;ke>=0;ke--)$=V[ke],Fe.info("Subgraph - ",$),p.db.addVertex($.id,{text:$.title,type:$.labelType},"group",void 0,$.classes,$.dir);const Q=p.db.getVertices(),oe=p.db.getEdges();Fe.info("Edges",oe);let ce=0;for(ce=V.length-1;ce>=0;ce--){$=V[ce],Jfe("cluster").append("text");for(let ke=0;ke<$.nodes.length;ke++)Fe.info("Setting up subgraphs",$.nodes[ke],$.id),j.setParent($.nodes[ke],$.id)}tRe(Q,j,a,B,R,p),nRe(oe,j);const se=B.select(`[id="${a}"]`),ge=B.select("#"+a+" g");if(await C0e(ge,j,["point","circle","cross"],"flowchart",a),co.insertTitle(se,"flowchartTitleText",b.titleTopMargin,p.db.getDiagramTitle()),YE(j,se,b.diagramPadding,b.useMaxWidth),p.db.indexNodes("subGraph"+ce),!b.htmlLabels){const ke=R.querySelectorAll('[id="'+a+'"] .edgeLabel .label');for(const Ae of ke){const de=Ae.getBBox(),ve=R.createElementNS("http://www.w3.org/2000/svg","rect");ve.setAttribute("rx",0),ve.setAttribute("ry",0),ve.setAttribute("width",de.width),ve.setAttribute("height",de.height),Ae.insertBefore(ve,Ae.firstChild)}}Object.keys(Q).forEach(function(ke){const Ae=Q[ke];if(Ae.link){const de=Cr("#"+a+' [id="'+ke+'"]');if(de){const ve=R.createElementNS("http://www.w3.org/2000/svg","a");ve.setAttributeNS("http://www.w3.org/2000/svg","class",Ae.classes.join(" ")),ve.setAttributeNS("http://www.w3.org/2000/svg","href",Ae.link),ve.setAttributeNS("http://www.w3.org/2000/svg","rel","noopener"),y==="sandbox"?ve.setAttributeNS("http://www.w3.org/2000/svg","target","_top"):Ae.linkTarget&&ve.setAttributeNS("http://www.w3.org/2000/svg","target",Ae.linkTarget);const te=de.insert(function(){return ve},":first-child"),xe=de.select(".label-container");xe&&te.append(function(){return xe.node()});const De=de.select(".label");De&&te.append(function(){return De.node()})}}})}},rRe=i=>`.label { + font-family: ${i.fontFamily}; + color: ${i.nodeTextColor||i.textColor}; + } + .cluster-label text { + fill: ${i.titleColor}; + } + .cluster-label span,p { + color: ${i.titleColor}; + } + + .label text,span,p { + fill: ${i.nodeTextColor||i.textColor}; + color: ${i.nodeTextColor||i.textColor}; + } + + .node rect, + .node circle, + .node ellipse, + .node polygon, + .node path { + fill: ${i.mainBkg}; + stroke: ${i.nodeBorder}; + stroke-width: 1px; + } + .flowchart-label text { + text-anchor: middle; + } + // .flowchart-label .text-outer-tspan { + // text-anchor: middle; + // } + // .flowchart-label .text-inner-tspan { + // text-anchor: start; + // } + + .node .label { + text-align: center; + } + .node.clickable { + cursor: pointer; + } + + .arrowheadPath { + fill: ${i.arrowheadColor}; + } + + .edgePath .path { + stroke: ${i.lineColor}; + stroke-width: 2.0px; + } + + .flowchart-link { + stroke: ${i.lineColor}; + fill: none; + } + + .edgeLabel { + background-color: ${i.edgeLabelBackground}; + rect { + opacity: 0.5; + background-color: ${i.edgeLabelBackground}; + fill: ${i.edgeLabelBackground}; + } + text-align: center; + } + + .cluster rect { + fill: ${i.clusterBkg}; + stroke: ${i.clusterBorder}; + stroke-width: 1px; + } + + .cluster text { + fill: ${i.titleColor}; + } + + .cluster span,p { + color: ${i.titleColor}; + } + /* .cluster div { + color: ${i.titleColor}; + } */ + + div.mermaidTooltip { + position: absolute; + text-align: center; + max-width: 200px; + padding: 2px; + font-family: ${i.fontFamily}; + font-size: 12px; + background: ${i.tertiaryColor}; + border: 1px solid ${i.border2}; + border-radius: 2px; + pointer-events: none; + z-index: 100; + } + + .flowchartTitleText { + text-anchor: middle; + font-size: 18px; + fill: ${i.textColor}; + } +`,kFt=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:Dde,db:ix,renderer:S0e,styles:rRe,init:i=>{i.flowchart||(i.flowchart={}),i.flowchart.arrowMarkerAbsolute=i.arrowMarkerAbsolute,JBt.setConf(i.flowchart),ix.clear(),ix.setGen("gen-1")}}},Symbol.toStringTag,{value:"Module"})),xFt=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:Dde,db:ix,renderer:S0e,styles:rRe,init:i=>{i.flowchart||(i.flowchart={}),i.flowchart.arrowMarkerAbsolute=i.arrowMarkerAbsolute,pIe({flowchart:{arrowMarkerAbsolute:i.arrowMarkerAbsolute}}),S0e.setConf(i.flowchart),ix.clear(),ix.setGen("gen-2")}}},Symbol.toStringTag,{value:"Module"}));var A0e=function(){var i=function(De,he,Ie,ee){for(Ie=Ie||{},ee=De.length;ee--;Ie[De[ee]]=he);return Ie},a=[1,2],f=[1,5],p=[6,9,11,23,25,27,29,30,31,51],w=[1,17],y=[1,18],b=[1,19],E=[1,20],S=[1,21],N=[1,22],B=[1,25],R=[1,30],j=[1,31],$=[1,32],V=[1,33],Q=[6,9,11,15,20,23,25,27,29,30,31,44,45,46,47,51],oe=[1,45],ce=[30,31,48,49],se=[4,6,9,11,23,25,27,29,30,31,51],ge=[44,45,46,47],ye=[22,37],ke=[1,65],Ae=[1,64],de=[22,37,39,41],ve={trace:function(){},yy:{},symbols_:{error:2,start:3,ER_DIAGRAM:4,document:5,EOF:6,directive:7,line:8,SPACE:9,statement:10,NEWLINE:11,openDirective:12,typeDirective:13,closeDirective:14,":":15,argDirective:16,entityName:17,relSpec:18,role:19,BLOCK_START:20,attributes:21,BLOCK_STOP:22,title:23,title_value:24,acc_title:25,acc_title_value:26,acc_descr:27,acc_descr_value:28,acc_descr_multiline_value:29,ALPHANUM:30,ENTITY_NAME:31,attribute:32,attributeType:33,attributeName:34,attributeKeyTypeList:35,attributeComment:36,ATTRIBUTE_WORD:37,attributeKeyType:38,COMMA:39,ATTRIBUTE_KEY:40,COMMENT:41,cardinality:42,relType:43,ZERO_OR_ONE:44,ZERO_OR_MORE:45,ONE_OR_MORE:46,ONLY_ONE:47,NON_IDENTIFYING:48,IDENTIFYING:49,WORD:50,open_directive:51,type_directive:52,arg_directive:53,close_directive:54,$accept:0,$end:1},terminals_:{2:"error",4:"ER_DIAGRAM",6:"EOF",9:"SPACE",11:"NEWLINE",15:":",20:"BLOCK_START",22:"BLOCK_STOP",23:"title",24:"title_value",25:"acc_title",26:"acc_title_value",27:"acc_descr",28:"acc_descr_value",29:"acc_descr_multiline_value",30:"ALPHANUM",31:"ENTITY_NAME",37:"ATTRIBUTE_WORD",39:"COMMA",40:"ATTRIBUTE_KEY",41:"COMMENT",44:"ZERO_OR_ONE",45:"ZERO_OR_MORE",46:"ONE_OR_MORE",47:"ONLY_ONE",48:"NON_IDENTIFYING",49:"IDENTIFYING",50:"WORD",51:"open_directive",52:"type_directive",53:"arg_directive",54:"close_directive"},productions_:[0,[3,3],[3,2],[5,0],[5,2],[8,2],[8,1],[8,1],[8,1],[7,4],[7,6],[10,1],[10,5],[10,4],[10,3],[10,1],[10,2],[10,2],[10,2],[10,1],[17,1],[17,1],[21,1],[21,2],[32,2],[32,3],[32,3],[32,4],[33,1],[34,1],[35,1],[35,3],[38,1],[36,1],[18,3],[42,1],[42,1],[42,1],[42,1],[43,1],[43,1],[19,1],[19,1],[19,1],[12,1],[13,1],[16,1],[14,1]],performAction:function(he,Ie,ee,rt,me,gt,pe){var Et=gt.length-1;switch(me){case 1:break;case 3:this.$=[];break;case 4:gt[Et-1].push(gt[Et]),this.$=gt[Et-1];break;case 5:case 6:this.$=gt[Et];break;case 7:case 8:this.$=[];break;case 12:rt.addEntity(gt[Et-4]),rt.addEntity(gt[Et-2]),rt.addRelationship(gt[Et-4],gt[Et],gt[Et-2],gt[Et-3]);break;case 13:rt.addEntity(gt[Et-3]),rt.addAttributes(gt[Et-3],gt[Et-1]);break;case 14:rt.addEntity(gt[Et-2]);break;case 15:rt.addEntity(gt[Et]);break;case 16:case 17:this.$=gt[Et].trim(),rt.setAccTitle(this.$);break;case 18:case 19:this.$=gt[Et].trim(),rt.setAccDescription(this.$);break;case 20:case 43:this.$=gt[Et];break;case 21:case 41:case 42:this.$=gt[Et].replace(/"/g,"");break;case 22:case 30:this.$=[gt[Et]];break;case 23:gt[Et].push(gt[Et-1]),this.$=gt[Et];break;case 24:this.$={attributeType:gt[Et-1],attributeName:gt[Et]};break;case 25:this.$={attributeType:gt[Et-2],attributeName:gt[Et-1],attributeKeyTypeList:gt[Et]};break;case 26:this.$={attributeType:gt[Et-2],attributeName:gt[Et-1],attributeComment:gt[Et]};break;case 27:this.$={attributeType:gt[Et-3],attributeName:gt[Et-2],attributeKeyTypeList:gt[Et-1],attributeComment:gt[Et]};break;case 28:case 29:case 32:this.$=gt[Et];break;case 31:gt[Et-2].push(gt[Et]),this.$=gt[Et-2];break;case 33:this.$=gt[Et].replace(/"/g,"");break;case 34:this.$={cardA:gt[Et],relType:gt[Et-1],cardB:gt[Et-2]};break;case 35:this.$=rt.Cardinality.ZERO_OR_ONE;break;case 36:this.$=rt.Cardinality.ZERO_OR_MORE;break;case 37:this.$=rt.Cardinality.ONE_OR_MORE;break;case 38:this.$=rt.Cardinality.ONLY_ONE;break;case 39:this.$=rt.Identification.NON_IDENTIFYING;break;case 40:this.$=rt.Identification.IDENTIFYING;break;case 44:rt.parseDirective("%%{","open_directive");break;case 45:rt.parseDirective(gt[Et],"type_directive");break;case 46:gt[Et]=gt[Et].trim().replace(/'/g,'"'),rt.parseDirective(gt[Et],"arg_directive");break;case 47:rt.parseDirective("}%%","close_directive","er");break}},table:[{3:1,4:a,7:3,12:4,51:f},{1:[3]},i(p,[2,3],{5:6}),{3:7,4:a,7:3,12:4,51:f},{13:8,52:[1,9]},{52:[2,44]},{6:[1,10],7:15,8:11,9:[1,12],10:13,11:[1,14],12:4,17:16,23:w,25:y,27:b,29:E,30:S,31:N,51:f},{1:[2,2]},{14:23,15:[1,24],54:B},i([15,54],[2,45]),i(p,[2,8],{1:[2,1]}),i(p,[2,4]),{7:15,10:26,12:4,17:16,23:w,25:y,27:b,29:E,30:S,31:N,51:f},i(p,[2,6]),i(p,[2,7]),i(p,[2,11]),i(p,[2,15],{18:27,42:29,20:[1,28],44:R,45:j,46:$,47:V}),{24:[1,34]},{26:[1,35]},{28:[1,36]},i(p,[2,19]),i(Q,[2,20]),i(Q,[2,21]),{11:[1,37]},{16:38,53:[1,39]},{11:[2,47]},i(p,[2,5]),{17:40,30:S,31:N},{21:41,22:[1,42],32:43,33:44,37:oe},{43:46,48:[1,47],49:[1,48]},i(ce,[2,35]),i(ce,[2,36]),i(ce,[2,37]),i(ce,[2,38]),i(p,[2,16]),i(p,[2,17]),i(p,[2,18]),i(se,[2,9]),{14:49,54:B},{54:[2,46]},{15:[1,50]},{22:[1,51]},i(p,[2,14]),{21:52,22:[2,22],32:43,33:44,37:oe},{34:53,37:[1,54]},{37:[2,28]},{42:55,44:R,45:j,46:$,47:V},i(ge,[2,39]),i(ge,[2,40]),{11:[1,56]},{19:57,30:[1,60],31:[1,59],50:[1,58]},i(p,[2,13]),{22:[2,23]},i(ye,[2,24],{35:61,36:62,38:63,40:ke,41:Ae}),i([22,37,40,41],[2,29]),i([30,31],[2,34]),i(se,[2,10]),i(p,[2,12]),i(p,[2,41]),i(p,[2,42]),i(p,[2,43]),i(ye,[2,25],{36:66,39:[1,67],41:Ae}),i(ye,[2,26]),i(de,[2,30]),i(ye,[2,33]),i(de,[2,32]),i(ye,[2,27]),{38:68,40:ke},i(de,[2,31])],defaultActions:{5:[2,44],7:[2,2],25:[2,47],39:[2,46],45:[2,28],52:[2,23]},parseError:function(he,Ie){if(Ie.recoverable)this.trace(he);else{var ee=new Error(he);throw ee.hash=Ie,ee}},parse:function(he){var Ie=this,ee=[0],rt=[],me=[null],gt=[],pe=this.table,Et="",wt=0,jt=0,At=2,Bt=1,cn=gt.slice.call(arguments,1),Nn=Object.create(this.lexer),Ot={yy:{}};for(var oi in this.yy)Object.prototype.hasOwnProperty.call(this.yy,oi)&&(Ot.yy[oi]=this.yy[oi]);Nn.setInput(he,Ot.yy),Ot.yy.lexer=Nn,Ot.yy.parser=this,typeof Nn.yylloc>"u"&&(Nn.yylloc={});var kt=Nn.yylloc;gt.push(kt);var Dt=Nn.options&&Nn.options.ranges;typeof Ot.yy.parseError=="function"?this.parseError=Ot.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function vt(){var Sr;return Sr=rt.pop()||Nn.lex()||Bt,typeof Sr!="number"&&(Sr instanceof Array&&(rt=Sr,Sr=rt.pop()),Sr=Ie.symbols_[Sr]||Sr),Sr}for(var Nt,ze,Xe,Lt,Ge={},Bn,Oe,Ri,tn;;){if(ze=ee[ee.length-1],this.defaultActions[ze]?Xe=this.defaultActions[ze]:((Nt===null||typeof Nt>"u")&&(Nt=vt()),Xe=pe[ze]&&pe[ze][Nt]),typeof Xe>"u"||!Xe.length||!Xe[0]){var hi="";tn=[];for(Bn in pe[ze])this.terminals_[Bn]&&Bn>At&&tn.push("'"+this.terminals_[Bn]+"'");Nn.showPosition?hi="Parse error on line "+(wt+1)+`: +`+Nn.showPosition()+` +Expecting `+tn.join(", ")+", got '"+(this.terminals_[Nt]||Nt)+"'":hi="Parse error on line "+(wt+1)+": Unexpected "+(Nt==Bt?"end of input":"'"+(this.terminals_[Nt]||Nt)+"'"),this.parseError(hi,{text:Nn.match,token:this.terminals_[Nt]||Nt,line:Nn.yylineno,loc:kt,expected:tn})}if(Xe[0]instanceof Array&&Xe.length>1)throw new Error("Parse Error: multiple actions possible at state: "+ze+", token: "+Nt);switch(Xe[0]){case 1:ee.push(Nt),me.push(Nn.yytext),gt.push(Nn.yylloc),ee.push(Xe[1]),Nt=null,jt=Nn.yyleng,Et=Nn.yytext,wt=Nn.yylineno,kt=Nn.yylloc;break;case 2:if(Oe=this.productions_[Xe[1]][1],Ge.$=me[me.length-Oe],Ge._$={first_line:gt[gt.length-(Oe||1)].first_line,last_line:gt[gt.length-1].last_line,first_column:gt[gt.length-(Oe||1)].first_column,last_column:gt[gt.length-1].last_column},Dt&&(Ge._$.range=[gt[gt.length-(Oe||1)].range[0],gt[gt.length-1].range[1]]),Lt=this.performAction.apply(Ge,[Et,jt,wt,Ot.yy,Xe[1],me,gt].concat(cn)),typeof Lt<"u")return Lt;Oe&&(ee=ee.slice(0,-1*Oe*2),me=me.slice(0,-1*Oe),gt=gt.slice(0,-1*Oe)),ee.push(this.productions_[Xe[1]][0]),me.push(Ge.$),gt.push(Ge._$),Ri=pe[ee[ee.length-2]][ee[ee.length-1]],ee.push(Ri);break;case 3:return!0}}return!0}},te=function(){var De={EOF:1,parseError:function(Ie,ee){if(this.yy.parser)this.yy.parser.parseError(Ie,ee);else throw new Error(Ie)},setInput:function(he,Ie){return this.yy=Ie||this.yy||{},this._input=he,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var he=this._input[0];this.yytext+=he,this.yyleng++,this.offset++,this.match+=he,this.matched+=he;var Ie=he.match(/(?:\r\n?|\n).*/g);return Ie?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),he},unput:function(he){var Ie=he.length,ee=he.split(/(?:\r\n?|\n)/g);this._input=he+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-Ie),this.offset-=Ie;var rt=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),ee.length-1&&(this.yylineno-=ee.length-1);var me=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:ee?(ee.length===rt.length?this.yylloc.first_column:0)+rt[rt.length-ee.length].length-ee[0].length:this.yylloc.first_column-Ie},this.options.ranges&&(this.yylloc.range=[me[0],me[0]+this.yyleng-Ie]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(he){this.unput(this.match.slice(he))},pastInput:function(){var he=this.matched.substr(0,this.matched.length-this.match.length);return(he.length>20?"...":"")+he.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var he=this.match;return he.length<20&&(he+=this._input.substr(0,20-he.length)),(he.substr(0,20)+(he.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var he=this.pastInput(),Ie=new Array(he.length+1).join("-");return he+this.upcomingInput()+` +`+Ie+"^"},test_match:function(he,Ie){var ee,rt,me;if(this.options.backtrack_lexer&&(me={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(me.yylloc.range=this.yylloc.range.slice(0))),rt=he[0].match(/(?:\r\n?|\n).*/g),rt&&(this.yylineno+=rt.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:rt?rt[rt.length-1].length-rt[rt.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+he[0].length},this.yytext+=he[0],this.match+=he[0],this.matches=he,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(he[0].length),this.matched+=he[0],ee=this.performAction.call(this,this.yy,this,Ie,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),ee)return ee;if(this._backtrack){for(var gt in me)this[gt]=me[gt];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var he,Ie,ee,rt;this._more||(this.yytext="",this.match="");for(var me=this._currentRules(),gt=0;gtIe[0].length)){if(Ie=ee,rt=gt,this.options.backtrack_lexer){if(he=this.test_match(ee,me[gt]),he!==!1)return he;if(this._backtrack){Ie=!1;continue}else return!1}else if(!this.options.flex)break}return Ie?(he=this.test_match(Ie,me[rt]),he!==!1?he:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var Ie=this.next();return Ie||this.lex()},begin:function(Ie){this.conditionStack.push(Ie)},popState:function(){var Ie=this.conditionStack.length-1;return Ie>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(Ie){return Ie=this.conditionStack.length-1-Math.abs(Ie||0),Ie>=0?this.conditionStack[Ie]:"INITIAL"},pushState:function(Ie){this.begin(Ie)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(Ie,ee,rt,me){switch(rt){case 0:return this.begin("acc_title"),25;case 1:return this.popState(),"acc_title_value";case 2:return this.begin("acc_descr"),27;case 3:return this.popState(),"acc_descr_value";case 4:this.begin("acc_descr_multiline");break;case 5:this.popState();break;case 6:return"acc_descr_multiline_value";case 7:return this.begin("open_directive"),51;case 8:return this.begin("type_directive"),52;case 9:return this.popState(),this.begin("arg_directive"),15;case 10:return this.popState(),this.popState(),54;case 11:return 53;case 12:return 11;case 13:break;case 14:return 9;case 15:return 31;case 16:return 50;case 17:return 4;case 18:return this.begin("block"),20;case 19:return 39;case 20:break;case 21:return 40;case 22:return 37;case 23:return 37;case 24:return 41;case 25:break;case 26:return this.popState(),22;case 27:return ee.yytext[0];case 28:return 44;case 29:return 46;case 30:return 46;case 31:return 46;case 32:return 44;case 33:return 44;case 34:return 45;case 35:return 45;case 36:return 45;case 37:return 45;case 38:return 45;case 39:return 46;case 40:return 45;case 41:return 46;case 42:return 47;case 43:return 47;case 44:return 47;case 45:return 47;case 46:return 44;case 47:return 45;case 48:return 46;case 49:return 48;case 50:return 49;case 51:return 49;case 52:return 48;case 53:return 48;case 54:return 48;case 55:return 30;case 56:return ee.yytext[0];case 57:return 6}},rules:[/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:[\s]+)/i,/^(?:"[^"%\r\n\v\b\\]+")/i,/^(?:"[^"]*")/i,/^(?:erDiagram\b)/i,/^(?:\{)/i,/^(?:,)/i,/^(?:\s+)/i,/^(?:\b((?:PK)|(?:FK)|(?:UK))\b)/i,/^(?:(.*?)[~](.*?)*[~])/i,/^(?:[A-Za-z_][A-Za-z0-9\-_\[\]\(\)]*)/i,/^(?:"[^"]*")/i,/^(?:[\n]+)/i,/^(?:\})/i,/^(?:.)/i,/^(?:one or zero\b)/i,/^(?:one or more\b)/i,/^(?:one or many\b)/i,/^(?:1\+)/i,/^(?:\|o\b)/i,/^(?:zero or one\b)/i,/^(?:zero or more\b)/i,/^(?:zero or many\b)/i,/^(?:0\+)/i,/^(?:\}o\b)/i,/^(?:many\(0\))/i,/^(?:many\(1\))/i,/^(?:many\b)/i,/^(?:\}\|)/i,/^(?:one\b)/i,/^(?:only one\b)/i,/^(?:1\b)/i,/^(?:\|\|)/i,/^(?:o\|)/i,/^(?:o\{)/i,/^(?:\|\{)/i,/^(?:\.\.)/i,/^(?:--)/i,/^(?:to\b)/i,/^(?:optionally to\b)/i,/^(?:\.-)/i,/^(?:-\.)/i,/^(?:[A-Za-z][A-Za-z0-9\-_]*)/i,/^(?:.)/i,/^(?:$)/i],conditions:{acc_descr_multiline:{rules:[5,6],inclusive:!1},acc_descr:{rules:[3],inclusive:!1},acc_title:{rules:[1],inclusive:!1},open_directive:{rules:[8],inclusive:!1},type_directive:{rules:[9,10],inclusive:!1},arg_directive:{rules:[10,11],inclusive:!1},block:{rules:[19,20,21,22,23,24,25,26,27],inclusive:!1},INITIAL:{rules:[0,2,4,7,12,13,14,15,16,17,18,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57],inclusive:!0}}};return De}();ve.lexer=te;function xe(){this.yy={}}return xe.prototype=ve,ve.Parser=xe,new xe}();A0e.parser=A0e;const EFt=A0e;let vP={},L0e=[];const TFt={ZERO_OR_ONE:"ZERO_OR_ONE",ZERO_OR_MORE:"ZERO_OR_MORE",ONE_OR_MORE:"ONE_OR_MORE",ONLY_ONE:"ONLY_ONE"},_Ft={NON_IDENTIFYING:"NON_IDENTIFYING",IDENTIFYING:"IDENTIFYING"},CFt=function(i,a,f){rd.parseDirective(this,i,a,f)},iRe=function(i){return vP[i]===void 0&&(vP[i]={attributes:[]},Fe.info("Added new entity :",i)),vP[i]},SFt={Cardinality:TFt,Identification:_Ft,parseDirective:CFt,getConfig:()=>Tt().er,addEntity:iRe,addAttributes:function(i,a){let f=iRe(i),p;for(p=a.length-1;p>=0;p--)f.attributes.push(a[p]),Fe.debug("Added attribute ",a[p].attributeName)},getEntities:()=>vP,addRelationship:function(i,a,f,p){let w={entityA:i,roleA:a,entityB:f,relSpec:p};L0e.push(w),Fe.debug("Added new relationship :",w)},getRelationships:()=>L0e,clear:function(){vP={},L0e=[],rp()},setAccTitle:ip,getAccTitle:L2,setAccDescription:M2,getAccDescription:D2,setDiagramTitle:Uw,getDiagramTitle:Ww},_5={ONLY_ONE_START:"ONLY_ONE_START",ONLY_ONE_END:"ONLY_ONE_END",ZERO_OR_ONE_START:"ZERO_OR_ONE_START",ZERO_OR_ONE_END:"ZERO_OR_ONE_END",ONE_OR_MORE_START:"ONE_OR_MORE_START",ONE_OR_MORE_END:"ONE_OR_MORE_END",ZERO_OR_MORE_START:"ZERO_OR_MORE_START",ZERO_OR_MORE_END:"ZERO_OR_MORE_END"},C5={ERMarkers:_5,insertMarkers:function(i,a){let f;i.append("defs").append("marker").attr("id",_5.ONLY_ONE_START).attr("refX",0).attr("refY",9).attr("markerWidth",18).attr("markerHeight",18).attr("orient","auto").append("path").attr("stroke",a.stroke).attr("fill","none").attr("d","M9,0 L9,18 M15,0 L15,18"),i.append("defs").append("marker").attr("id",_5.ONLY_ONE_END).attr("refX",18).attr("refY",9).attr("markerWidth",18).attr("markerHeight",18).attr("orient","auto").append("path").attr("stroke",a.stroke).attr("fill","none").attr("d","M3,0 L3,18 M9,0 L9,18"),f=i.append("defs").append("marker").attr("id",_5.ZERO_OR_ONE_START).attr("refX",0).attr("refY",9).attr("markerWidth",30).attr("markerHeight",18).attr("orient","auto"),f.append("circle").attr("stroke",a.stroke).attr("fill","white").attr("cx",21).attr("cy",9).attr("r",6),f.append("path").attr("stroke",a.stroke).attr("fill","none").attr("d","M9,0 L9,18"),f=i.append("defs").append("marker").attr("id",_5.ZERO_OR_ONE_END).attr("refX",30).attr("refY",9).attr("markerWidth",30).attr("markerHeight",18).attr("orient","auto"),f.append("circle").attr("stroke",a.stroke).attr("fill","white").attr("cx",9).attr("cy",9).attr("r",6),f.append("path").attr("stroke",a.stroke).attr("fill","none").attr("d","M21,0 L21,18"),i.append("defs").append("marker").attr("id",_5.ONE_OR_MORE_START).attr("refX",18).attr("refY",18).attr("markerWidth",45).attr("markerHeight",36).attr("orient","auto").append("path").attr("stroke",a.stroke).attr("fill","none").attr("d","M0,18 Q 18,0 36,18 Q 18,36 0,18 M42,9 L42,27"),i.append("defs").append("marker").attr("id",_5.ONE_OR_MORE_END).attr("refX",27).attr("refY",18).attr("markerWidth",45).attr("markerHeight",36).attr("orient","auto").append("path").attr("stroke",a.stroke).attr("fill","none").attr("d","M3,9 L3,27 M9,18 Q27,0 45,18 Q27,36 9,18"),f=i.append("defs").append("marker").attr("id",_5.ZERO_OR_MORE_START).attr("refX",18).attr("refY",18).attr("markerWidth",57).attr("markerHeight",36).attr("orient","auto"),f.append("circle").attr("stroke",a.stroke).attr("fill","white").attr("cx",48).attr("cy",18).attr("r",6),f.append("path").attr("stroke",a.stroke).attr("fill","none").attr("d","M0,18 Q18,0 36,18 Q18,36 0,18"),f=i.append("defs").append("marker").attr("id",_5.ZERO_OR_MORE_END).attr("refX",39).attr("refY",18).attr("markerWidth",57).attr("markerHeight",36).attr("orient","auto"),f.append("circle").attr("stroke",a.stroke).attr("fill","white").attr("cx",9).attr("cy",18).attr("r",6),f.append("path").attr("stroke",a.stroke).attr("fill","none").attr("d","M21,18 Q39,0 57,18 Q39,36 21,18")}},AFt=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;function LFt(i){return typeof i=="string"&&AFt.test(i)}const Hd=[];for(let i=0;i<256;++i)Hd.push((i+256).toString(16).slice(1));function MFt(i,a=0){return(Hd[i[a+0]]+Hd[i[a+1]]+Hd[i[a+2]]+Hd[i[a+3]]+"-"+Hd[i[a+4]]+Hd[i[a+5]]+"-"+Hd[i[a+6]]+Hd[i[a+7]]+"-"+Hd[i[a+8]]+Hd[i[a+9]]+"-"+Hd[i[a+10]]+Hd[i[a+11]]+Hd[i[a+12]]+Hd[i[a+13]]+Hd[i[a+14]]+Hd[i[a+15]]).toLowerCase()}function DFt(i){if(!LFt(i))throw TypeError("Invalid UUID");let a;const f=new Uint8Array(16);return f[0]=(a=parseInt(i.slice(0,8),16))>>>24,f[1]=a>>>16&255,f[2]=a>>>8&255,f[3]=a&255,f[4]=(a=parseInt(i.slice(9,13),16))>>>8,f[5]=a&255,f[6]=(a=parseInt(i.slice(14,18),16))>>>8,f[7]=a&255,f[8]=(a=parseInt(i.slice(19,23),16))>>>8,f[9]=a&255,f[10]=(a=parseInt(i.slice(24,36),16))/1099511627776&255,f[11]=a/4294967296&255,f[12]=a>>>24&255,f[13]=a>>>16&255,f[14]=a>>>8&255,f[15]=a&255,f}function IFt(i){i=unescape(encodeURIComponent(i));const a=[];for(let f=0;f>>32-a}function RFt(i){const a=[1518500249,1859775393,2400959708,3395469782],f=[1732584193,4023233417,2562383102,271733878,3285377520];if(typeof i=="string"){const b=unescape(encodeURIComponent(i));i=[];for(let E=0;E>>0;j=R,R=B,B=M0e(N,30)>>>0,N=S,S=Q}f[0]=f[0]+S>>>0,f[1]=f[1]+N>>>0,f[2]=f[2]+B>>>0,f[3]=f[3]+R>>>0,f[4]=f[4]+j>>>0}return[f[0]>>24&255,f[0]>>16&255,f[0]>>8&255,f[0]&255,f[1]>>24&255,f[1]>>16&255,f[1]>>8&255,f[1]&255,f[2]>>24&255,f[2]>>16&255,f[2]>>8&255,f[2]&255,f[3]>>24&255,f[3]>>16&255,f[3]>>8&255,f[3]&255,f[4]>>24&255,f[4]>>16&255,f[4]>>8&255,f[4]&255]}const FFt=PFt("v5",80,RFt),jFt=/[^\dA-Za-z](\W)*/g;let g1={},wP=new Map;const $Ft=function(i){const a=Object.keys(i);for(const f of a)g1[f]=i[f]},HFt=(i,a,f)=>{const p=g1.entityPadding/3,w=g1.entityPadding/3,y=g1.fontSize*.85,b=a.node().getBBox(),E=[];let S=!1,N=!1,B=0,R=0,j=0,$=0,V=b.height+p*2,Q=1;f.forEach(ge=>{ge.attributeKeyTypeList!==void 0&&ge.attributeKeyTypeList.length>0&&(S=!0),ge.attributeComment!==void 0&&(N=!0)}),f.forEach(ge=>{const ye=`${a.node().id}-attr-${Q}`;let ke=0;const Ae=Yk(ge.attributeType),de=i.append("text").classed("er entityLabel",!0).attr("id",`${ye}-type`).attr("x",0).attr("y",0).style("dominant-baseline","middle").style("text-anchor","left").style("font-family",Tt().fontFamily).style("font-size",y+"px").text(Ae),ve=i.append("text").classed("er entityLabel",!0).attr("id",`${ye}-name`).attr("x",0).attr("y",0).style("dominant-baseline","middle").style("text-anchor","left").style("font-family",Tt().fontFamily).style("font-size",y+"px").text(ge.attributeName),te={};te.tn=de,te.nn=ve;const xe=de.node().getBBox(),De=ve.node().getBBox();if(B=Math.max(B,xe.width),R=Math.max(R,De.width),ke=Math.max(xe.height,De.height),S){const he=ge.attributeKeyTypeList!==void 0?ge.attributeKeyTypeList.join(","):"",Ie=i.append("text").classed("er entityLabel",!0).attr("id",`${ye}-key`).attr("x",0).attr("y",0).style("dominant-baseline","middle").style("text-anchor","left").style("font-family",Tt().fontFamily).style("font-size",y+"px").text(he);te.kn=Ie;const ee=Ie.node().getBBox();j=Math.max(j,ee.width),ke=Math.max(ke,ee.height)}if(N){const he=i.append("text").classed("er entityLabel",!0).attr("id",`${ye}-comment`).attr("x",0).attr("y",0).style("dominant-baseline","middle").style("text-anchor","left").style("font-family",Tt().fontFamily).style("font-size",y+"px").text(ge.attributeComment||"");te.cn=he;const Ie=he.node().getBBox();$=Math.max($,Ie.width),ke=Math.max(ke,Ie.height)}te.height=ke,E.push(te),V+=ke+p*2,Q+=1});let oe=4;S&&(oe+=2),N&&(oe+=2);const ce=B+R+j+$,se={width:Math.max(g1.minEntityWidth,Math.max(b.width+g1.entityPadding*2,ce+w*oe)),height:f.length>0?V:Math.max(g1.minEntityHeight,b.height+g1.entityPadding*2)};if(f.length>0){const ge=Math.max(0,(se.width-ce-w*oe)/(oe/2));a.attr("transform","translate("+se.width/2+","+(p+b.height/2)+")");let ye=b.height+p*2,ke="attributeBoxOdd";E.forEach(Ae=>{const de=ye+p+Ae.height/2;Ae.tn.attr("transform","translate("+w+","+de+")");const ve=i.insert("rect","#"+Ae.tn.node().id).classed(`er ${ke}`,!0).attr("x",0).attr("y",ye).attr("width",B+w*2+ge).attr("height",Ae.height+p*2),te=parseFloat(ve.attr("x"))+parseFloat(ve.attr("width"));Ae.nn.attr("transform","translate("+(te+w)+","+de+")");const xe=i.insert("rect","#"+Ae.nn.node().id).classed(`er ${ke}`,!0).attr("x",te).attr("y",ye).attr("width",R+w*2+ge).attr("height",Ae.height+p*2);let De=parseFloat(xe.attr("x"))+parseFloat(xe.attr("width"));if(S){Ae.kn.attr("transform","translate("+(De+w)+","+de+")");const he=i.insert("rect","#"+Ae.kn.node().id).classed(`er ${ke}`,!0).attr("x",De).attr("y",ye).attr("width",j+w*2+ge).attr("height",Ae.height+p*2);De=parseFloat(he.attr("x"))+parseFloat(he.attr("width"))}N&&(Ae.cn.attr("transform","translate("+(De+w)+","+de+")"),i.insert("rect","#"+Ae.cn.node().id).classed(`er ${ke}`,"true").attr("x",De).attr("y",ye).attr("width",$+w*2+ge).attr("height",Ae.height+p*2)),ye+=Ae.height+p*2,ke=ke==="attributeBoxOdd"?"attributeBoxEven":"attributeBoxOdd"})}else se.height=Math.max(g1.minEntityHeight,V),a.attr("transform","translate("+se.width/2+","+se.height/2+")");return se},zFt=function(i,a,f){const p=Object.keys(a);let w;return p.forEach(function(y){const b=KFt(y,"entity");wP.set(y,b);const E=i.append("g").attr("id",b);w=w===void 0?b:w;const S="text-"+b,N=E.append("text").classed("er entityLabel",!0).attr("id",S).attr("x",0).attr("y",0).style("dominant-baseline","middle").style("text-anchor","middle").style("font-family",Tt().fontFamily).style("font-size",g1.fontSize+"px").text(y),{width:B,height:R}=HFt(E,N,a[y].attributes),$=E.insert("rect","#"+S).classed("er entityBox",!0).attr("x",0).attr("y",0).attr("width",B).attr("height",R).node().getBBox();f.setNode(b,{width:$.width,height:$.height,shape:"rect",id:b})}),w},GFt=function(i,a){a.nodes().forEach(function(f){f!==void 0&&a.node(f)!==void 0&&i.select("#"+f).attr("transform","translate("+(a.node(f).x-a.node(f).width/2)+","+(a.node(f).y-a.node(f).height/2)+" )")})},sRe=function(i){return(i.entityA+i.roleA+i.entityB).replace(/\s/g,"")},qFt=function(i,a){return i.forEach(function(f){a.setEdge(wP.get(f.entityA),wP.get(f.entityB),{relationship:f},sRe(f))}),i};let aRe=0;const VFt=function(i,a,f,p,w){aRe++;const y=f.edge(wP.get(a.entityA),wP.get(a.entityB),sRe(a)),b=WE().x(function(V){return V.x}).y(function(V){return V.y}).curve(SA),E=i.insert("path","#"+p).classed("er relationshipLine",!0).attr("d",b(y.points)).style("stroke",g1.stroke).style("fill","none");a.relSpec.relType===w.db.Identification.NON_IDENTIFYING&&E.attr("stroke-dasharray","8,8");let S="";switch(g1.arrowMarkerAbsolute&&(S=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search,S=S.replace(/\(/g,"\\("),S=S.replace(/\)/g,"\\)")),a.relSpec.cardA){case w.db.Cardinality.ZERO_OR_ONE:E.attr("marker-end","url("+S+"#"+C5.ERMarkers.ZERO_OR_ONE_END+")");break;case w.db.Cardinality.ZERO_OR_MORE:E.attr("marker-end","url("+S+"#"+C5.ERMarkers.ZERO_OR_MORE_END+")");break;case w.db.Cardinality.ONE_OR_MORE:E.attr("marker-end","url("+S+"#"+C5.ERMarkers.ONE_OR_MORE_END+")");break;case w.db.Cardinality.ONLY_ONE:E.attr("marker-end","url("+S+"#"+C5.ERMarkers.ONLY_ONE_END+")");break}switch(a.relSpec.cardB){case w.db.Cardinality.ZERO_OR_ONE:E.attr("marker-start","url("+S+"#"+C5.ERMarkers.ZERO_OR_ONE_START+")");break;case w.db.Cardinality.ZERO_OR_MORE:E.attr("marker-start","url("+S+"#"+C5.ERMarkers.ZERO_OR_MORE_START+")");break;case w.db.Cardinality.ONE_OR_MORE:E.attr("marker-start","url("+S+"#"+C5.ERMarkers.ONE_OR_MORE_START+")");break;case w.db.Cardinality.ONLY_ONE:E.attr("marker-start","url("+S+"#"+C5.ERMarkers.ONLY_ONE_START+")");break}const N=E.node().getTotalLength(),B=E.node().getPointAtLength(N*.5),R="rel"+aRe,$=i.append("text").classed("er relationshipLabel",!0).attr("id",R).attr("x",B.x).attr("y",B.y).style("text-anchor","middle").style("dominant-baseline","middle").style("font-family",Tt().fontFamily).style("font-size",g1.fontSize+"px").text(a.roleA).node().getBBox();i.insert("rect","#"+R).classed("er relationshipLabelBox",!0).attr("x",B.x-$.width/2).attr("y",B.y-$.height/2).attr("width",$.width).attr("height",$.height)},UFt=function(i,a,f,p){g1=Tt().er,Fe.info("Drawing ER diagram");const w=Tt().securityLevel;let y;w==="sandbox"&&(y=Cr("#i"+a));const E=Cr(w==="sandbox"?y.nodes()[0].contentDocument.body:"body").select(`[id='${a}']`);C5.insertMarkers(E,g1);let S;S=new zf({multigraph:!0,directed:!0,compound:!1}).setGraph({rankdir:g1.layoutDirection,marginx:20,marginy:20,nodesep:100,edgesep:100,ranksep:100}).setDefaultEdgeLabel(function(){return{}});const N=zFt(E,p.db.getEntities(),S),B=qFt(p.db.getRelationships(),S);tL(S),GFt(E,S),B.forEach(function(Q){VFt(E,Q,S,N,p)});const R=g1.diagramPadding;co.insertTitle(E,"entityTitleText",g1.titleTopMargin,p.db.getDiagramTitle());const j=E.node().getBBox(),$=j.width+R*2,V=j.height+R*2;Vw(E,V,$,g1.useMaxWidth),E.attr("viewBox",`${j.x-R} ${j.y-R} ${$} ${V}`)},WFt="28e9f9db-3c8d-5aa5-9faf-44286ae5937c";function KFt(i="",a=""){const f=i.replace(jFt,"");return`${oRe(a)}${oRe(f)}${FFt(i,WFt)}`}function oRe(i=""){return i.length>0?`${i}-`:""}const YFt=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:EFt,db:SFt,renderer:{setConf:$Ft,draw:UFt},styles:i=>` + .entityBox { + fill: ${i.mainBkg}; + stroke: ${i.nodeBorder}; + } + + .attributeBoxOdd { + fill: ${i.attributeBackgroundColorOdd}; + stroke: ${i.nodeBorder}; + } + + .attributeBoxEven { + fill: ${i.attributeBackgroundColorEven}; + stroke: ${i.nodeBorder}; + } + + .relationshipLabelBox { + fill: ${i.tertiaryColor}; + opacity: 0.7; + background-color: ${i.tertiaryColor}; + rect { + opacity: 0.5; + } + } + + .relationshipLine { + stroke: ${i.lineColor}; + } + + .entityTitleText { + text-anchor: middle; + font-size: 18px; + fill: ${i.textColor}; + } +`}},Symbol.toStringTag,{value:"Module"}));var D0e=function(){var i=function(ve,te,xe,De){for(xe=xe||{},De=ve.length;De--;xe[ve[De]]=te);return xe},a=[1,4],f=[1,7],p=[1,5],w=[1,9],y=[1,6],b=[2,6],E=[1,16],S=[6,8,14,20,22,24,25,27,29,32,37,40,50,55],N=[8,14,20,22,24,25,27,29,32,37,40],B=[8,13,14,20,22,24,25,27,29,32,37,40],R=[1,26],j=[6,8,14,50,55],$=[8,14,55],V=[1,53],Q=[1,52],oe=[8,14,30,33,35,38,55],ce=[1,67],se=[1,68],ge=[1,69],ye=[8,14,33,35,42,55],ke={trace:function(){},yy:{},symbols_:{error:2,start:3,eol:4,directive:5,GG:6,document:7,EOF:8,":":9,DIR:10,options:11,body:12,OPT:13,NL:14,line:15,statement:16,commitStatement:17,mergeStatement:18,cherryPickStatement:19,acc_title:20,acc_title_value:21,acc_descr:22,acc_descr_value:23,acc_descr_multiline_value:24,section:25,branchStatement:26,CHECKOUT:27,ref:28,BRANCH:29,ORDER:30,NUM:31,CHERRY_PICK:32,COMMIT_ID:33,STR:34,COMMIT_TAG:35,EMPTYSTR:36,MERGE:37,COMMIT_TYPE:38,commitType:39,COMMIT:40,commit_arg:41,COMMIT_MSG:42,NORMAL:43,REVERSE:44,HIGHLIGHT:45,openDirective:46,typeDirective:47,closeDirective:48,argDirective:49,open_directive:50,type_directive:51,arg_directive:52,close_directive:53,ID:54,";":55,$accept:0,$end:1},terminals_:{2:"error",6:"GG",8:"EOF",9:":",10:"DIR",13:"OPT",14:"NL",20:"acc_title",21:"acc_title_value",22:"acc_descr",23:"acc_descr_value",24:"acc_descr_multiline_value",25:"section",27:"CHECKOUT",29:"BRANCH",30:"ORDER",31:"NUM",32:"CHERRY_PICK",33:"COMMIT_ID",34:"STR",35:"COMMIT_TAG",36:"EMPTYSTR",37:"MERGE",38:"COMMIT_TYPE",40:"COMMIT",42:"COMMIT_MSG",43:"NORMAL",44:"REVERSE",45:"HIGHLIGHT",50:"open_directive",51:"type_directive",52:"arg_directive",53:"close_directive",54:"ID",55:";"},productions_:[0,[3,2],[3,2],[3,3],[3,4],[3,5],[7,0],[7,2],[11,2],[11,1],[12,0],[12,2],[15,2],[15,1],[16,1],[16,1],[16,1],[16,2],[16,2],[16,1],[16,1],[16,1],[16,2],[26,2],[26,4],[19,3],[19,5],[19,5],[19,5],[19,5],[18,2],[18,4],[18,4],[18,4],[18,6],[18,6],[18,6],[18,6],[18,6],[18,6],[18,8],[18,8],[18,8],[18,8],[18,8],[18,8],[17,2],[17,3],[17,3],[17,5],[17,5],[17,3],[17,5],[17,5],[17,5],[17,5],[17,7],[17,7],[17,7],[17,7],[17,7],[17,7],[17,3],[17,5],[17,5],[17,5],[17,5],[17,5],[17,5],[17,7],[17,7],[17,7],[17,7],[17,7],[17,7],[17,7],[17,7],[17,7],[17,7],[17,7],[17,7],[17,7],[17,7],[17,7],[17,7],[17,7],[17,7],[17,9],[17,9],[17,9],[17,9],[17,9],[17,9],[17,9],[17,9],[17,9],[17,9],[17,9],[17,9],[17,9],[17,9],[17,9],[17,9],[17,9],[17,9],[17,9],[17,9],[17,9],[17,9],[17,9],[17,9],[41,0],[41,1],[39,1],[39,1],[39,1],[5,3],[5,5],[46,1],[47,1],[49,1],[48,1],[28,1],[28,1],[4,1],[4,1],[4,1]],performAction:function(te,xe,De,he,Ie,ee,rt){var me=ee.length-1;switch(Ie){case 3:return ee[me];case 4:return ee[me-1];case 5:return he.setDirection(ee[me-3]),ee[me-1];case 7:he.setOptions(ee[me-1]),this.$=ee[me];break;case 8:ee[me-1]+=ee[me],this.$=ee[me-1];break;case 10:this.$=[];break;case 11:ee[me-1].push(ee[me]),this.$=ee[me-1];break;case 12:this.$=ee[me-1];break;case 17:this.$=ee[me].trim(),he.setAccTitle(this.$);break;case 18:case 19:this.$=ee[me].trim(),he.setAccDescription(this.$);break;case 20:he.addSection(ee[me].substr(8)),this.$=ee[me].substr(8);break;case 22:he.checkout(ee[me]);break;case 23:he.branch(ee[me]);break;case 24:he.branch(ee[me-2],ee[me]);break;case 25:he.cherryPick(ee[me],"",void 0);break;case 26:he.cherryPick(ee[me-2],"",ee[me]);break;case 27:case 29:he.cherryPick(ee[me-2],"","");break;case 28:he.cherryPick(ee[me],"",ee[me-2]);break;case 30:he.merge(ee[me],"","","");break;case 31:he.merge(ee[me-2],ee[me],"","");break;case 32:he.merge(ee[me-2],"",ee[me],"");break;case 33:he.merge(ee[me-2],"","",ee[me]);break;case 34:he.merge(ee[me-4],ee[me],"",ee[me-2]);break;case 35:he.merge(ee[me-4],"",ee[me],ee[me-2]);break;case 36:he.merge(ee[me-4],"",ee[me-2],ee[me]);break;case 37:he.merge(ee[me-4],ee[me-2],ee[me],"");break;case 38:he.merge(ee[me-4],ee[me-2],"",ee[me]);break;case 39:he.merge(ee[me-4],ee[me],ee[me-2],"");break;case 40:he.merge(ee[me-6],ee[me-4],ee[me-2],ee[me]);break;case 41:he.merge(ee[me-6],ee[me],ee[me-4],ee[me-2]);break;case 42:he.merge(ee[me-6],ee[me-4],ee[me],ee[me-2]);break;case 43:he.merge(ee[me-6],ee[me-2],ee[me-4],ee[me]);break;case 44:he.merge(ee[me-6],ee[me],ee[me-2],ee[me-4]);break;case 45:he.merge(ee[me-6],ee[me-2],ee[me],ee[me-4]);break;case 46:he.commit(ee[me]);break;case 47:he.commit("","",he.commitType.NORMAL,ee[me]);break;case 48:he.commit("","",ee[me],"");break;case 49:he.commit("","",ee[me],ee[me-2]);break;case 50:he.commit("","",ee[me-2],ee[me]);break;case 51:he.commit("",ee[me],he.commitType.NORMAL,"");break;case 52:he.commit("",ee[me-2],he.commitType.NORMAL,ee[me]);break;case 53:he.commit("",ee[me],he.commitType.NORMAL,ee[me-2]);break;case 54:he.commit("",ee[me-2],ee[me],"");break;case 55:he.commit("",ee[me],ee[me-2],"");break;case 56:he.commit("",ee[me-4],ee[me-2],ee[me]);break;case 57:he.commit("",ee[me-4],ee[me],ee[me-2]);break;case 58:he.commit("",ee[me-2],ee[me-4],ee[me]);break;case 59:he.commit("",ee[me],ee[me-4],ee[me-2]);break;case 60:he.commit("",ee[me],ee[me-2],ee[me-4]);break;case 61:he.commit("",ee[me-2],ee[me],ee[me-4]);break;case 62:he.commit(ee[me],"",he.commitType.NORMAL,"");break;case 63:he.commit(ee[me],"",he.commitType.NORMAL,ee[me-2]);break;case 64:he.commit(ee[me-2],"",he.commitType.NORMAL,ee[me]);break;case 65:he.commit(ee[me-2],"",ee[me],"");break;case 66:he.commit(ee[me],"",ee[me-2],"");break;case 67:he.commit(ee[me],ee[me-2],he.commitType.NORMAL,"");break;case 68:he.commit(ee[me-2],ee[me],he.commitType.NORMAL,"");break;case 69:he.commit(ee[me-4],"",ee[me-2],ee[me]);break;case 70:he.commit(ee[me-4],"",ee[me],ee[me-2]);break;case 71:he.commit(ee[me-2],"",ee[me-4],ee[me]);break;case 72:he.commit(ee[me],"",ee[me-4],ee[me-2]);break;case 73:he.commit(ee[me],"",ee[me-2],ee[me-4]);break;case 74:he.commit(ee[me-2],"",ee[me],ee[me-4]);break;case 75:he.commit(ee[me-4],ee[me],ee[me-2],"");break;case 76:he.commit(ee[me-4],ee[me-2],ee[me],"");break;case 77:he.commit(ee[me-2],ee[me],ee[me-4],"");break;case 78:he.commit(ee[me],ee[me-2],ee[me-4],"");break;case 79:he.commit(ee[me],ee[me-4],ee[me-2],"");break;case 80:he.commit(ee[me-2],ee[me-4],ee[me],"");break;case 81:he.commit(ee[me-4],ee[me],he.commitType.NORMAL,ee[me-2]);break;case 82:he.commit(ee[me-4],ee[me-2],he.commitType.NORMAL,ee[me]);break;case 83:he.commit(ee[me-2],ee[me],he.commitType.NORMAL,ee[me-4]);break;case 84:he.commit(ee[me],ee[me-2],he.commitType.NORMAL,ee[me-4]);break;case 85:he.commit(ee[me],ee[me-4],he.commitType.NORMAL,ee[me-2]);break;case 86:he.commit(ee[me-2],ee[me-4],he.commitType.NORMAL,ee[me]);break;case 87:he.commit(ee[me-6],ee[me-4],ee[me-2],ee[me]);break;case 88:he.commit(ee[me-6],ee[me-4],ee[me],ee[me-2]);break;case 89:he.commit(ee[me-6],ee[me-2],ee[me-4],ee[me]);break;case 90:he.commit(ee[me-6],ee[me],ee[me-4],ee[me-2]);break;case 91:he.commit(ee[me-6],ee[me-2],ee[me],ee[me-4]);break;case 92:he.commit(ee[me-6],ee[me],ee[me-2],ee[me-4]);break;case 93:he.commit(ee[me-4],ee[me-6],ee[me-2],ee[me]);break;case 94:he.commit(ee[me-4],ee[me-6],ee[me],ee[me-2]);break;case 95:he.commit(ee[me-2],ee[me-6],ee[me-4],ee[me]);break;case 96:he.commit(ee[me],ee[me-6],ee[me-4],ee[me-2]);break;case 97:he.commit(ee[me-2],ee[me-6],ee[me],ee[me-4]);break;case 98:he.commit(ee[me],ee[me-6],ee[me-2],ee[me-4]);break;case 99:he.commit(ee[me],ee[me-4],ee[me-2],ee[me-6]);break;case 100:he.commit(ee[me-2],ee[me-4],ee[me],ee[me-6]);break;case 101:he.commit(ee[me],ee[me-2],ee[me-4],ee[me-6]);break;case 102:he.commit(ee[me-2],ee[me],ee[me-4],ee[me-6]);break;case 103:he.commit(ee[me-4],ee[me-2],ee[me],ee[me-6]);break;case 104:he.commit(ee[me-4],ee[me],ee[me-2],ee[me-6]);break;case 105:he.commit(ee[me-2],ee[me-4],ee[me-6],ee[me]);break;case 106:he.commit(ee[me],ee[me-4],ee[me-6],ee[me-2]);break;case 107:he.commit(ee[me-2],ee[me],ee[me-6],ee[me-4]);break;case 108:he.commit(ee[me],ee[me-2],ee[me-6],ee[me-4]);break;case 109:he.commit(ee[me-4],ee[me-2],ee[me-6],ee[me]);break;case 110:he.commit(ee[me-4],ee[me],ee[me-6],ee[me-2]);break;case 111:this.$="";break;case 112:this.$=ee[me];break;case 113:this.$=he.commitType.NORMAL;break;case 114:this.$=he.commitType.REVERSE;break;case 115:this.$=he.commitType.HIGHLIGHT;break;case 118:he.parseDirective("%%{","open_directive");break;case 119:he.parseDirective(ee[me],"type_directive");break;case 120:ee[me]=ee[me].trim().replace(/'/g,'"'),he.parseDirective(ee[me],"arg_directive");break;case 121:he.parseDirective("}%%","close_directive","gitGraph");break}},table:[{3:1,4:2,5:3,6:a,8:f,14:p,46:8,50:w,55:y},{1:[3]},{3:10,4:2,5:3,6:a,8:f,14:p,46:8,50:w,55:y},{3:11,4:2,5:3,6:a,8:f,14:p,46:8,50:w,55:y},{7:12,8:b,9:[1,13],10:[1,14],11:15,14:E},i(S,[2,124]),i(S,[2,125]),i(S,[2,126]),{47:17,51:[1,18]},{51:[2,118]},{1:[2,1]},{1:[2,2]},{8:[1,19]},{7:20,8:b,11:15,14:E},{9:[1,21]},i(N,[2,10],{12:22,13:[1,23]}),i(B,[2,9]),{9:[1,25],48:24,53:R},i([9,53],[2,119]),{1:[2,3]},{8:[1,27]},{7:28,8:b,11:15,14:E},{8:[2,7],14:[1,31],15:29,16:30,17:32,18:33,19:34,20:[1,35],22:[1,36],24:[1,37],25:[1,38],26:39,27:[1,40],29:[1,44],32:[1,43],37:[1,42],40:[1,41]},i(B,[2,8]),i(j,[2,116]),{49:45,52:[1,46]},i(j,[2,121]),{1:[2,4]},{8:[1,47]},i(N,[2,11]),{4:48,8:f,14:p,55:y},i(N,[2,13]),i($,[2,14]),i($,[2,15]),i($,[2,16]),{21:[1,49]},{23:[1,50]},i($,[2,19]),i($,[2,20]),i($,[2,21]),{28:51,34:V,54:Q},i($,[2,111],{41:54,33:[1,57],34:[1,59],35:[1,55],38:[1,56],42:[1,58]}),{28:60,34:V,54:Q},{33:[1,61],35:[1,62]},{28:63,34:V,54:Q},{48:64,53:R},{53:[2,120]},{1:[2,5]},i(N,[2,12]),i($,[2,17]),i($,[2,18]),i($,[2,22]),i(oe,[2,122]),i(oe,[2,123]),i($,[2,46]),{34:[1,65]},{39:66,43:ce,44:se,45:ge},{34:[1,70]},{34:[1,71]},i($,[2,112]),i($,[2,30],{33:[1,72],35:[1,74],38:[1,73]}),{34:[1,75]},{34:[1,76],36:[1,77]},i($,[2,23],{30:[1,78]}),i(j,[2,117]),i($,[2,47],{33:[1,80],38:[1,79],42:[1,81]}),i($,[2,48],{33:[1,83],35:[1,82],42:[1,84]}),i(ye,[2,113]),i(ye,[2,114]),i(ye,[2,115]),i($,[2,51],{35:[1,85],38:[1,86],42:[1,87]}),i($,[2,62],{33:[1,90],35:[1,88],38:[1,89]}),{34:[1,91]},{39:92,43:ce,44:se,45:ge},{34:[1,93]},i($,[2,25],{35:[1,94]}),{33:[1,95]},{33:[1,96]},{31:[1,97]},{39:98,43:ce,44:se,45:ge},{34:[1,99]},{34:[1,100]},{34:[1,101]},{34:[1,102]},{34:[1,103]},{34:[1,104]},{39:105,43:ce,44:se,45:ge},{34:[1,106]},{34:[1,107]},{39:108,43:ce,44:se,45:ge},{34:[1,109]},i($,[2,31],{35:[1,111],38:[1,110]}),i($,[2,32],{33:[1,113],35:[1,112]}),i($,[2,33],{33:[1,114],38:[1,115]}),{34:[1,116],36:[1,117]},{34:[1,118]},{34:[1,119]},i($,[2,24]),i($,[2,49],{33:[1,120],42:[1,121]}),i($,[2,53],{38:[1,122],42:[1,123]}),i($,[2,63],{33:[1,125],38:[1,124]}),i($,[2,50],{33:[1,126],42:[1,127]}),i($,[2,55],{35:[1,128],42:[1,129]}),i($,[2,66],{33:[1,131],35:[1,130]}),i($,[2,52],{38:[1,132],42:[1,133]}),i($,[2,54],{35:[1,134],42:[1,135]}),i($,[2,67],{35:[1,137],38:[1,136]}),i($,[2,64],{33:[1,139],38:[1,138]}),i($,[2,65],{33:[1,141],35:[1,140]}),i($,[2,68],{35:[1,143],38:[1,142]}),{39:144,43:ce,44:se,45:ge},{34:[1,145]},{34:[1,146]},{34:[1,147]},{34:[1,148]},{39:149,43:ce,44:se,45:ge},i($,[2,26]),i($,[2,27]),i($,[2,28]),i($,[2,29]),{34:[1,150]},{34:[1,151]},{39:152,43:ce,44:se,45:ge},{34:[1,153]},{39:154,43:ce,44:se,45:ge},{34:[1,155]},{34:[1,156]},{34:[1,157]},{34:[1,158]},{34:[1,159]},{34:[1,160]},{34:[1,161]},{39:162,43:ce,44:se,45:ge},{34:[1,163]},{34:[1,164]},{34:[1,165]},{39:166,43:ce,44:se,45:ge},{34:[1,167]},{39:168,43:ce,44:se,45:ge},{34:[1,169]},{34:[1,170]},{34:[1,171]},{39:172,43:ce,44:se,45:ge},{34:[1,173]},i($,[2,37],{35:[1,174]}),i($,[2,38],{38:[1,175]}),i($,[2,36],{33:[1,176]}),i($,[2,39],{35:[1,177]}),i($,[2,34],{38:[1,178]}),i($,[2,35],{33:[1,179]}),i($,[2,60],{42:[1,180]}),i($,[2,73],{33:[1,181]}),i($,[2,61],{42:[1,182]}),i($,[2,84],{38:[1,183]}),i($,[2,74],{33:[1,184]}),i($,[2,83],{38:[1,185]}),i($,[2,59],{42:[1,186]}),i($,[2,72],{33:[1,187]}),i($,[2,58],{42:[1,188]}),i($,[2,78],{35:[1,189]}),i($,[2,71],{33:[1,190]}),i($,[2,77],{35:[1,191]}),i($,[2,57],{42:[1,192]}),i($,[2,85],{38:[1,193]}),i($,[2,56],{42:[1,194]}),i($,[2,79],{35:[1,195]}),i($,[2,80],{35:[1,196]}),i($,[2,86],{38:[1,197]}),i($,[2,70],{33:[1,198]}),i($,[2,81],{38:[1,199]}),i($,[2,69],{33:[1,200]}),i($,[2,75],{35:[1,201]}),i($,[2,76],{35:[1,202]}),i($,[2,82],{38:[1,203]}),{34:[1,204]},{39:205,43:ce,44:se,45:ge},{34:[1,206]},{34:[1,207]},{39:208,43:ce,44:se,45:ge},{34:[1,209]},{34:[1,210]},{34:[1,211]},{34:[1,212]},{39:213,43:ce,44:se,45:ge},{34:[1,214]},{39:215,43:ce,44:se,45:ge},{34:[1,216]},{34:[1,217]},{34:[1,218]},{34:[1,219]},{34:[1,220]},{34:[1,221]},{34:[1,222]},{39:223,43:ce,44:se,45:ge},{34:[1,224]},{34:[1,225]},{34:[1,226]},{39:227,43:ce,44:se,45:ge},{34:[1,228]},{39:229,43:ce,44:se,45:ge},{34:[1,230]},{34:[1,231]},{34:[1,232]},{39:233,43:ce,44:se,45:ge},i($,[2,40]),i($,[2,42]),i($,[2,41]),i($,[2,43]),i($,[2,45]),i($,[2,44]),i($,[2,101]),i($,[2,102]),i($,[2,99]),i($,[2,100]),i($,[2,104]),i($,[2,103]),i($,[2,108]),i($,[2,107]),i($,[2,106]),i($,[2,105]),i($,[2,110]),i($,[2,109]),i($,[2,98]),i($,[2,97]),i($,[2,96]),i($,[2,95]),i($,[2,93]),i($,[2,94]),i($,[2,92]),i($,[2,91]),i($,[2,90]),i($,[2,89]),i($,[2,87]),i($,[2,88])],defaultActions:{9:[2,118],10:[2,1],11:[2,2],19:[2,3],27:[2,4],46:[2,120],47:[2,5]},parseError:function(te,xe){if(xe.recoverable)this.trace(te);else{var De=new Error(te);throw De.hash=xe,De}},parse:function(te){var xe=this,De=[0],he=[],Ie=[null],ee=[],rt=this.table,me="",gt=0,pe=0,Et=2,wt=1,jt=ee.slice.call(arguments,1),At=Object.create(this.lexer),Bt={yy:{}};for(var cn in this.yy)Object.prototype.hasOwnProperty.call(this.yy,cn)&&(Bt.yy[cn]=this.yy[cn]);At.setInput(te,Bt.yy),Bt.yy.lexer=At,Bt.yy.parser=this,typeof At.yylloc>"u"&&(At.yylloc={});var Nn=At.yylloc;ee.push(Nn);var Ot=At.options&&At.options.ranges;typeof Bt.yy.parseError=="function"?this.parseError=Bt.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function oi(){var Ri;return Ri=he.pop()||At.lex()||wt,typeof Ri!="number"&&(Ri instanceof Array&&(he=Ri,Ri=he.pop()),Ri=xe.symbols_[Ri]||Ri),Ri}for(var kt,Dt,vt,Nt,ze={},Xe,Lt,Ge,Bn;;){if(Dt=De[De.length-1],this.defaultActions[Dt]?vt=this.defaultActions[Dt]:((kt===null||typeof kt>"u")&&(kt=oi()),vt=rt[Dt]&&rt[Dt][kt]),typeof vt>"u"||!vt.length||!vt[0]){var Oe="";Bn=[];for(Xe in rt[Dt])this.terminals_[Xe]&&Xe>Et&&Bn.push("'"+this.terminals_[Xe]+"'");At.showPosition?Oe="Parse error on line "+(gt+1)+`: +`+At.showPosition()+` +Expecting `+Bn.join(", ")+", got '"+(this.terminals_[kt]||kt)+"'":Oe="Parse error on line "+(gt+1)+": Unexpected "+(kt==wt?"end of input":"'"+(this.terminals_[kt]||kt)+"'"),this.parseError(Oe,{text:At.match,token:this.terminals_[kt]||kt,line:At.yylineno,loc:Nn,expected:Bn})}if(vt[0]instanceof Array&&vt.length>1)throw new Error("Parse Error: multiple actions possible at state: "+Dt+", token: "+kt);switch(vt[0]){case 1:De.push(kt),Ie.push(At.yytext),ee.push(At.yylloc),De.push(vt[1]),kt=null,pe=At.yyleng,me=At.yytext,gt=At.yylineno,Nn=At.yylloc;break;case 2:if(Lt=this.productions_[vt[1]][1],ze.$=Ie[Ie.length-Lt],ze._$={first_line:ee[ee.length-(Lt||1)].first_line,last_line:ee[ee.length-1].last_line,first_column:ee[ee.length-(Lt||1)].first_column,last_column:ee[ee.length-1].last_column},Ot&&(ze._$.range=[ee[ee.length-(Lt||1)].range[0],ee[ee.length-1].range[1]]),Nt=this.performAction.apply(ze,[me,pe,gt,Bt.yy,vt[1],Ie,ee].concat(jt)),typeof Nt<"u")return Nt;Lt&&(De=De.slice(0,-1*Lt*2),Ie=Ie.slice(0,-1*Lt),ee=ee.slice(0,-1*Lt)),De.push(this.productions_[vt[1]][0]),Ie.push(ze.$),ee.push(ze._$),Ge=rt[De[De.length-2]][De[De.length-1]],De.push(Ge);break;case 3:return!0}}return!0}},Ae=function(){var ve={EOF:1,parseError:function(xe,De){if(this.yy.parser)this.yy.parser.parseError(xe,De);else throw new Error(xe)},setInput:function(te,xe){return this.yy=xe||this.yy||{},this._input=te,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var te=this._input[0];this.yytext+=te,this.yyleng++,this.offset++,this.match+=te,this.matched+=te;var xe=te.match(/(?:\r\n?|\n).*/g);return xe?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),te},unput:function(te){var xe=te.length,De=te.split(/(?:\r\n?|\n)/g);this._input=te+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-xe),this.offset-=xe;var he=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),De.length-1&&(this.yylineno-=De.length-1);var Ie=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:De?(De.length===he.length?this.yylloc.first_column:0)+he[he.length-De.length].length-De[0].length:this.yylloc.first_column-xe},this.options.ranges&&(this.yylloc.range=[Ie[0],Ie[0]+this.yyleng-xe]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(te){this.unput(this.match.slice(te))},pastInput:function(){var te=this.matched.substr(0,this.matched.length-this.match.length);return(te.length>20?"...":"")+te.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var te=this.match;return te.length<20&&(te+=this._input.substr(0,20-te.length)),(te.substr(0,20)+(te.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var te=this.pastInput(),xe=new Array(te.length+1).join("-");return te+this.upcomingInput()+` +`+xe+"^"},test_match:function(te,xe){var De,he,Ie;if(this.options.backtrack_lexer&&(Ie={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(Ie.yylloc.range=this.yylloc.range.slice(0))),he=te[0].match(/(?:\r\n?|\n).*/g),he&&(this.yylineno+=he.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:he?he[he.length-1].length-he[he.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+te[0].length},this.yytext+=te[0],this.match+=te[0],this.matches=te,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(te[0].length),this.matched+=te[0],De=this.performAction.call(this,this.yy,this,xe,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),De)return De;if(this._backtrack){for(var ee in Ie)this[ee]=Ie[ee];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var te,xe,De,he;this._more||(this.yytext="",this.match="");for(var Ie=this._currentRules(),ee=0;eexe[0].length)){if(xe=De,he=ee,this.options.backtrack_lexer){if(te=this.test_match(De,Ie[ee]),te!==!1)return te;if(this._backtrack){xe=!1;continue}else return!1}else if(!this.options.flex)break}return xe?(te=this.test_match(xe,Ie[he]),te!==!1?te:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var xe=this.next();return xe||this.lex()},begin:function(xe){this.conditionStack.push(xe)},popState:function(){var xe=this.conditionStack.length-1;return xe>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(xe){return xe=this.conditionStack.length-1-Math.abs(xe||0),xe>=0?this.conditionStack[xe]:"INITIAL"},pushState:function(xe){this.begin(xe)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(xe,De,he,Ie){switch(he){case 0:return this.begin("open_directive"),50;case 1:return this.begin("type_directive"),51;case 2:return this.popState(),this.begin("arg_directive"),9;case 3:return this.popState(),this.popState(),53;case 4:return 52;case 5:return this.begin("acc_title"),20;case 6:return this.popState(),"acc_title_value";case 7:return this.begin("acc_descr"),22;case 8:return this.popState(),"acc_descr_value";case 9:this.begin("acc_descr_multiline");break;case 10:this.popState();break;case 11:return"acc_descr_multiline_value";case 12:return 14;case 13:break;case 14:break;case 15:return 6;case 16:return 40;case 17:return 33;case 18:return 38;case 19:return 42;case 20:return 43;case 21:return 44;case 22:return 45;case 23:return 35;case 24:return 29;case 25:return 30;case 26:return 37;case 27:return 32;case 28:return 27;case 29:return 10;case 30:return 10;case 31:return 9;case 32:return"CARET";case 33:this.begin("options");break;case 34:this.popState();break;case 35:return 13;case 36:return 36;case 37:this.begin("string");break;case 38:this.popState();break;case 39:return 34;case 40:return 31;case 41:return 54;case 42:return 8}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:(\r?\n)+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:gitGraph\b)/i,/^(?:commit(?=\s|$))/i,/^(?:id:)/i,/^(?:type:)/i,/^(?:msg:)/i,/^(?:NORMAL\b)/i,/^(?:REVERSE\b)/i,/^(?:HIGHLIGHT\b)/i,/^(?:tag:)/i,/^(?:branch(?=\s|$))/i,/^(?:order:)/i,/^(?:merge(?=\s|$))/i,/^(?:cherry-pick(?=\s|$))/i,/^(?:checkout(?=\s|$))/i,/^(?:LR\b)/i,/^(?:BT\b)/i,/^(?::)/i,/^(?:\^)/i,/^(?:options\r?\n)/i,/^(?:[ \r\n\t]+end\b)/i,/^(?:[\s\S]+(?=[ \r\n\t]+end))/i,/^(?:["]["])/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[0-9]+(?=\s|$))/i,/^(?:\w([-\./\w]*[-\w])?)/i,/^(?:$)/i,/^(?:\s+)/i],conditions:{acc_descr_multiline:{rules:[10,11],inclusive:!1},acc_descr:{rules:[8],inclusive:!1},acc_title:{rules:[6],inclusive:!1},close_directive:{rules:[],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},open_directive:{rules:[1],inclusive:!1},options:{rules:[34,35],inclusive:!1},string:{rules:[38,39],inclusive:!1},INITIAL:{rules:[0,5,7,9,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,36,37,40,41,42,43],inclusive:!0}}};return ve}();ke.lexer=Ae;function de(){this.yy={}}return de.prototype=ke,ke.Parser=de,new de}();D0e.parser=D0e;const XFt=D0e;let yK=Tt().gitGraph.mainBranchName,QFt=Tt().gitGraph.mainBranchOrder,p1={},og=null,mP={};mP[yK]={name:yK,order:QFt};let Gf={};Gf[yK]=og;let id=yK,cRe="LR",h9=0;function I0e(){return OIe({length:7})}const ZFt=function(i,a,f){rd.parseDirective(this,i,a,f)};function JFt(i,a){const f=Object.create(null);return i.reduce((p,w)=>{const y=a(w);return f[y]||(f[y]=!0,p.push(w)),p},[])}const ejt=function(i){cRe=i};let uRe={};const tjt=function(i){Fe.debug("options str",i),i=i&&i.trim(),i=i||"{}";try{uRe=JSON.parse(i)}catch(a){Fe.error("error while parsing gitGraph options",a.message)}},njt=function(){return uRe},rjt=function(i,a,f,p){Fe.debug("Entering commit:",i,a,f,p),a=Wa.sanitizeText(a,Tt()),i=Wa.sanitizeText(i,Tt()),p=Wa.sanitizeText(p,Tt());const w={id:a||h9+"-"+I0e(),message:i,seq:h9++,type:f||yP.NORMAL,tag:p||"",parents:og==null?[]:[og.id],branch:id};og=w,p1[w.id]=w,Gf[id]=w.id,Fe.debug("in pushCommit "+w.id)},ijt=function(i,a){if(i=Wa.sanitizeText(i,Tt()),Gf[i]===void 0)Gf[i]=og!=null?og.id:null,mP[i]={name:i,order:a?parseInt(a,10):null},lRe(i),Fe.debug("in createBranch");else{let f=new Error('Trying to create an existing branch. (Help: Either use a new name if you want create a new branch or try using "checkout '+i+'")');throw f.hash={text:"branch "+i,token:"branch "+i,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:['"checkout '+i+'"']},f}},sjt=function(i,a,f,p){i=Wa.sanitizeText(i,Tt()),a=Wa.sanitizeText(a,Tt());const w=p1[Gf[id]],y=p1[Gf[i]];if(id===i){let E=new Error('Incorrect usage of "merge". Cannot merge a branch to itself');throw E.hash={text:"merge "+i,token:"merge "+i,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["branch abc"]},E}else if(w===void 0||!w){let E=new Error('Incorrect usage of "merge". Current branch ('+id+")has no commits");throw E.hash={text:"merge "+i,token:"merge "+i,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["commit"]},E}else if(Gf[i]===void 0){let E=new Error('Incorrect usage of "merge". Branch to be merged ('+i+") does not exist");throw E.hash={text:"merge "+i,token:"merge "+i,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["branch "+i]},E}else if(y===void 0||!y){let E=new Error('Incorrect usage of "merge". Branch to be merged ('+i+") has no commits");throw E.hash={text:"merge "+i,token:"merge "+i,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:['"commit"']},E}else if(w===y){let E=new Error('Incorrect usage of "merge". Both branches have same head');throw E.hash={text:"merge "+i,token:"merge "+i,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["branch abc"]},E}else if(a&&p1[a]!==void 0){let E=new Error('Incorrect usage of "merge". Commit with id:'+a+" already exists, use different custom Id");throw E.hash={text:"merge "+i+a+f+p,token:"merge "+i+a+f+p,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["merge "+i+" "+a+"_UNIQUE "+f+" "+p]},E}const b={id:a||h9+"-"+I0e(),message:"merged branch "+i+" into "+id,seq:h9++,parents:[og==null?null:og.id,Gf[i]],branch:id,type:yP.MERGE,customType:f,customId:!!a,tag:p||""};og=b,p1[b.id]=b,Gf[id]=b.id,Fe.debug(Gf),Fe.debug("in mergeBranch")},ajt=function(i,a,f){if(Fe.debug("Entering cherryPick:",i,a,f),i=Wa.sanitizeText(i,Tt()),a=Wa.sanitizeText(a,Tt()),f=Wa.sanitizeText(f,Tt()),!i||p1[i]===void 0){let y=new Error('Incorrect usage of "cherryPick". Source commit id should exist and provided');throw y.hash={text:"cherryPick "+i+" "+a,token:"cherryPick "+i+" "+a,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["cherry-pick abc"]},y}let p=p1[i],w=p.branch;if(p.type===yP.MERGE){let y=new Error('Incorrect usage of "cherryPick". Source commit should not be a merge commit');throw y.hash={text:"cherryPick "+i+" "+a,token:"cherryPick "+i+" "+a,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["cherry-pick abc"]},y}if(!a||p1[a]===void 0){if(w===id){let E=new Error('Incorrect usage of "cherryPick". Source commit is already on current branch');throw E.hash={text:"cherryPick "+i+" "+a,token:"cherryPick "+i+" "+a,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["cherry-pick abc"]},E}const y=p1[Gf[id]];if(y===void 0||!y){let E=new Error('Incorrect usage of "cherry-pick". Current branch ('+id+")has no commits");throw E.hash={text:"cherryPick "+i+" "+a,token:"cherryPick "+i+" "+a,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["cherry-pick abc"]},E}const b={id:h9+"-"+I0e(),message:"cherry-picked "+p+" into "+id,seq:h9++,parents:[og==null?null:og.id,p.id],branch:id,type:yP.CHERRY_PICK,tag:f??"cherry-pick:"+p.id};og=b,p1[b.id]=b,Gf[id]=b.id,Fe.debug(Gf),Fe.debug("in cherryPick")}},lRe=function(i){if(i=Wa.sanitizeText(i,Tt()),Gf[i]===void 0){let a=new Error('Trying to checkout branch which is not yet created. (Help try using "branch '+i+'")');throw a.hash={text:"checkout "+i,token:"checkout "+i,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:['"branch '+i+'"']},a}else{id=i;const a=Gf[id];og=p1[a]}};function hRe(i,a,f){const p=i.indexOf(a);p===-1?i.push(f):i.splice(p,1,f)}function fRe(i){const a=i.reduce((w,y)=>w.seq>y.seq?w:y,i[0]);let f="";i.forEach(function(w){w===a?f+=" *":f+=" |"});const p=[f,a.id,a.seq];for(let w in Gf)Gf[w]===a.id&&p.push(w);if(Fe.debug(p.join(" ")),a.parents&&a.parents.length==2){const w=p1[a.parents[0]];hRe(i,a,w),i.push(p1[a.parents[1]])}else{if(a.parents.length==0)return;{const w=p1[a.parents];hRe(i,a,w)}}i=JFt(i,w=>w.id),fRe(i)}const ojt=function(){Fe.debug(p1);const i=dRe()[0];fRe([i])},cjt=function(){p1={},og=null;let i=Tt().gitGraph.mainBranchName,a=Tt().gitGraph.mainBranchOrder;Gf={},Gf[i]=null,mP={},mP[i]={name:i,order:a},id=i,h9=0,rp()},ujt=function(){return Object.values(mP).map((a,f)=>a.order!==null?a:{...a,order:parseFloat(`0.${f}`,10)}).sort((a,f)=>a.order-f.order).map(({name:a})=>({name:a}))},ljt=function(){return Gf},hjt=function(){return p1},dRe=function(){const i=Object.keys(p1).map(function(a){return p1[a]});return i.forEach(function(a){Fe.debug(a.id)}),i.sort((a,f)=>a.seq-f.seq),i},fjt=function(){return id},djt=function(){return cRe},gjt=function(){return og},yP={NORMAL:0,REVERSE:1,HIGHLIGHT:2,MERGE:3,CHERRY_PICK:4},pjt={parseDirective:ZFt,getConfig:()=>Tt().gitGraph,setDirection:ejt,setOptions:tjt,getOptions:njt,commit:rjt,branch:ijt,merge:sjt,cherryPick:ajt,checkout:lRe,prettyPrint:ojt,clear:cjt,getBranchesAsObjArray:ujt,getBranches:ljt,getCommits:hjt,getCommitsArray:dRe,getCurrentBranch:fjt,getDirection:djt,getHead:gjt,setAccTitle:ip,getAccTitle:L2,getAccDescription:D2,setAccDescription:M2,setDiagramTitle:Uw,getDiagramTitle:Ww,commitType:yP};let kP={};const P2={NORMAL:0,REVERSE:1,HIGHLIGHT:2,MERGE:3,CHERRY_PICK:4},f9=8;let op={},kK={},xK=[],EK=0;const bjt=()=>{op={},kK={},kP={},EK=0,xK=[]},vjt=i=>{const a=document.createElementNS("http://www.w3.org/2000/svg","text");let f=[];typeof i=="string"?f=i.split(/\\n|\n|/gi):Array.isArray(i)?f=i:f=[];for(const p of f){const w=document.createElementNS("http://www.w3.org/2000/svg","tspan");w.setAttributeNS("http://www.w3.org/XML/1998/namespace","xml:space","preserve"),w.setAttribute("dy","1em"),w.setAttribute("x","0"),w.setAttribute("class","row"),w.textContent=p.trim(),a.appendChild(w)}return a},gRe=(i,a,f)=>{const p=GN().gitGraph,w=i.append("g").attr("class","commit-bullets"),y=i.append("g").attr("class","commit-labels");let b=0;Object.keys(a).sort((N,B)=>a[N].seq-a[B].seq).forEach(N=>{const B=a[N],R=op[B.branch].pos,j=b+10;if(f){let $,V=B.customType!==void 0&&B.customType!==""?B.customType:B.type;switch(V){case P2.NORMAL:$="commit-normal";break;case P2.REVERSE:$="commit-reverse";break;case P2.HIGHLIGHT:$="commit-highlight";break;case P2.MERGE:$="commit-merge";break;case P2.CHERRY_PICK:$="commit-cherry-pick";break;default:$="commit-normal"}if(V===P2.HIGHLIGHT){const Q=w.append("rect");Q.attr("x",j-10),Q.attr("y",R-10),Q.attr("height",20),Q.attr("width",20),Q.attr("class",`commit ${B.id} commit-highlight${op[B.branch].index%f9} ${$}-outer`),w.append("rect").attr("x",j-6).attr("y",R-6).attr("height",12).attr("width",12).attr("class",`commit ${B.id} commit${op[B.branch].index%f9} ${$}-inner`)}else if(V===P2.CHERRY_PICK)w.append("circle").attr("cx",j).attr("cy",R).attr("r",10).attr("class",`commit ${B.id} ${$}`),w.append("circle").attr("cx",j-3).attr("cy",R+2).attr("r",2.75).attr("fill","#fff").attr("class",`commit ${B.id} ${$}`),w.append("circle").attr("cx",j+3).attr("cy",R+2).attr("r",2.75).attr("fill","#fff").attr("class",`commit ${B.id} ${$}`),w.append("line").attr("x1",j+3).attr("y1",R+1).attr("x2",j).attr("y2",R-5).attr("stroke","#fff").attr("class",`commit ${B.id} ${$}`),w.append("line").attr("x1",j-3).attr("y1",R+1).attr("x2",j).attr("y2",R-5).attr("stroke","#fff").attr("class",`commit ${B.id} ${$}`);else{const Q=w.append("circle");if(Q.attr("cx",j),Q.attr("cy",R),Q.attr("r",B.type===P2.MERGE?9:10),Q.attr("class",`commit ${B.id} commit${op[B.branch].index%f9}`),V===P2.MERGE){const oe=w.append("circle");oe.attr("cx",j),oe.attr("cy",R),oe.attr("r",6),oe.attr("class",`commit ${$} ${B.id} commit${op[B.branch].index%f9}`)}V===P2.REVERSE&&w.append("path").attr("d",`M ${j-5},${R-5}L${j+5},${R+5}M${j-5},${R+5}L${j+5},${R-5}`).attr("class",`commit ${$} ${B.id} commit${op[B.branch].index%f9}`)}}if(kK[B.id]={x:b+10,y:R},f){if(B.type!==P2.CHERRY_PICK&&(B.customId&&B.type===P2.MERGE||B.type!==P2.MERGE)&&p.showCommitLabel){const Q=y.append("g"),oe=Q.insert("rect").attr("class","commit-label-bkg"),ce=Q.append("text").attr("x",b).attr("y",R+25).attr("class","commit-label").text(B.id);let se=ce.node().getBBox();if(oe.attr("x",b+10-se.width/2-2).attr("y",R+13.5).attr("width",se.width+2*2).attr("height",se.height+2*2),ce.attr("x",b+10-se.width/2),p.rotateCommitLabel){let ge=-7.5-(se.width+10)/25*9.5,ye=10+se.width/25*8.5;Q.attr("transform","translate("+ge+", "+ye+") rotate(-45, "+b+", "+R+")")}}if(B.tag){const Q=y.insert("polygon"),oe=y.append("circle"),ce=y.append("text").attr("y",R-16).attr("class","tag-label").text(B.tag);let se=ce.node().getBBox();ce.attr("x",b+10-se.width/2);const ge=se.height/2,ye=R-19.2;Q.attr("class","tag-label-bkg").attr("points",` + ${b-se.width/2-4/2},${ye+2} + ${b-se.width/2-4/2},${ye-2} + ${b+10-se.width/2-4},${ye-ge-2} + ${b+10+se.width/2+4},${ye-ge-2} + ${b+10+se.width/2+4},${ye+ge+2} + ${b+10-se.width/2-4},${ye+ge+2}`),oe.attr("cx",b-se.width/2+4/2).attr("cy",ye).attr("r",1.5).attr("class","tag-hole")}}b+=50,b>EK&&(EK=b)})},wjt=(i,a,f)=>Object.keys(f).filter(y=>f[y].branch===a.branch&&f[y].seq>i.seq&&f[y].seq0,O0e=(i,a,f=0)=>{const p=i+Math.abs(i-a)/2;if(f>5)return p;if(xK.every(b=>Math.abs(b-p)>=10))return xK.push(p),p;const y=Math.abs(i-a);return O0e(i,a-y/5,f+1)},mjt=(i,a,f,p)=>{const w=kK[a.id],y=kK[f.id],b=wjt(a,f,p);let E="",S="",N=0,B=0,R=op[f.branch].index,j;if(b){E="A 10 10, 0, 0, 0,",S="A 10 10, 0, 0, 1,",N=10,B=10,R=op[f.branch].index;const $=w.yy.y&&(E="A 20 20, 0, 0, 0,",N=20,B=20,R=op[a.branch].index,j=`M ${w.x} ${w.y} L ${y.x-N} ${w.y} ${E} ${y.x} ${w.y-B} L ${y.x} ${y.y}`),w.y===y.y&&(R=op[a.branch].index,j=`M ${w.x} ${w.y} L ${w.x} ${y.y-N} ${E} ${w.x+B} ${y.y} L ${y.x} ${y.y}`);i.append("path").attr("d",j).attr("class","arrow arrow"+R%f9)},yjt=(i,a)=>{const f=i.append("g").attr("class","commit-arrows");Object.keys(a).forEach(p=>{const w=a[p];w.parents&&w.parents.length>0&&w.parents.forEach(y=>{mjt(f,a[y],w,a)})})},kjt=(i,a)=>{const f=GN().gitGraph,p=i.append("g");a.forEach((w,y)=>{const b=y%f9,E=op[w.name].pos,S=p.append("line");S.attr("x1",0),S.attr("y1",E),S.attr("x2",EK),S.attr("y2",E),S.attr("class","branch branch"+b),xK.push(E);let N=w.name;const B=vjt(N),R=p.insert("rect"),$=p.insert("g").attr("class","branchLabel").insert("g").attr("class","label branch-label"+b);$.node().appendChild(B);let V=B.getBBox();R.attr("class","branchLabelBkg label"+b).attr("rx",4).attr("ry",4).attr("x",-V.width-4-(f.rotateCommitLabel===!0?30:0)).attr("y",-V.height/2+8).attr("width",V.width+18).attr("height",V.height+4),$.attr("transform","translate("+(-V.width-14-(f.rotateCommitLabel===!0?30:0))+", "+(E-V.height/2-1)+")"),R.attr("transform","translate(-19, "+(E-V.height/2)+")")})},xjt=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:XFt,db:pjt,renderer:{draw:function(i,a,f,p){bjt();const w=GN(),y=w.gitGraph;Fe.debug("in gitgraph renderer",i+` +`,"id:",a,f),kP=p.db.getCommits();const b=p.db.getBranchesAsObjArray();let E=0;b.forEach((N,B)=>{op[N.name]={pos:E,index:B},E+=50+(y.rotateCommitLabel?40:0)});const S=Cr(`[id="${a}"]`);gRe(S,kP,!1),y.showBranches&&kjt(S,b),yjt(S,kP),gRe(S,kP,!0),co.insertTitle(S,"gitTitleText",y.titleTopMargin,p.db.getDiagramTitle()),xIe(void 0,S,y.diagramPadding,y.useMaxWidth??w.useMaxWidth)}},styles:i=>` + .commit-id, + .commit-msg, + .branch-label { + fill: lightgrey; + color: lightgrey; + font-family: 'trebuchet ms', verdana, arial, sans-serif; + font-family: var(--mermaid-font-family); + } + ${[0,1,2,3,4,5,6,7].map(a=>` + .branch-label${a} { fill: ${i["gitBranchLabel"+a]}; } + .commit${a} { stroke: ${i["git"+a]}; fill: ${i["git"+a]}; } + .commit-highlight${a} { stroke: ${i["gitInv"+a]}; fill: ${i["gitInv"+a]}; } + .label${a} { fill: ${i["git"+a]}; } + .arrow${a} { stroke: ${i["git"+a]}; } + `).join(` +`)} + + .branch { + stroke-width: 1; + stroke: ${i.lineColor}; + stroke-dasharray: 2; + } + .commit-label { font-size: ${i.commitLabelFontSize}; fill: ${i.commitLabelColor};} + .commit-label-bkg { font-size: ${i.commitLabelFontSize}; fill: ${i.commitLabelBackground}; opacity: 0.5; } + .tag-label { font-size: ${i.tagLabelFontSize}; fill: ${i.tagLabelColor};} + .tag-label-bkg { fill: ${i.tagLabelBackground}; stroke: ${i.tagLabelBorder}; } + .tag-hole { fill: ${i.textColor}; } + + .commit-merge { + stroke: ${i.primaryColor}; + fill: ${i.primaryColor}; + } + .commit-reverse { + stroke: ${i.primaryColor}; + fill: ${i.primaryColor}; + stroke-width: 3; + } + .commit-highlight-outer { + } + .commit-highlight-inner { + stroke: ${i.primaryColor}; + fill: ${i.primaryColor}; + } + + .arrow { stroke-width: 8; stroke-linecap: round; fill: none} + .gitTitleText { + text-anchor: middle; + font-size: 18px; + fill: ${i.textColor}; + } +`}},Symbol.toStringTag,{value:"Module"}));var N0e=function(){var i=function(ve,te,xe,De){for(xe=xe||{},De=ve.length;De--;xe[ve[De]]=te);return xe},a=[1,3],f=[1,5],p=[7,9,11,12,13,14,15,16,17,18,19,20,21,23,25,26,28,35,40],w=[1,15],y=[1,16],b=[1,17],E=[1,18],S=[1,19],N=[1,20],B=[1,21],R=[1,22],j=[1,23],$=[1,24],V=[1,25],Q=[1,26],oe=[1,27],ce=[1,29],se=[1,31],ge=[1,34],ye=[5,7,9,11,12,13,14,15,16,17,18,19,20,21,23,25,26,28,35,40],ke={trace:function(){},yy:{},symbols_:{error:2,start:3,directive:4,gantt:5,document:6,EOF:7,line:8,SPACE:9,statement:10,NL:11,dateFormat:12,inclusiveEndDates:13,topAxis:14,axisFormat:15,tickInterval:16,excludes:17,includes:18,todayMarker:19,title:20,acc_title:21,acc_title_value:22,acc_descr:23,acc_descr_value:24,acc_descr_multiline_value:25,section:26,clickStatement:27,taskTxt:28,taskData:29,openDirective:30,typeDirective:31,closeDirective:32,":":33,argDirective:34,click:35,callbackname:36,callbackargs:37,href:38,clickStatementDebug:39,open_directive:40,type_directive:41,arg_directive:42,close_directive:43,$accept:0,$end:1},terminals_:{2:"error",5:"gantt",7:"EOF",9:"SPACE",11:"NL",12:"dateFormat",13:"inclusiveEndDates",14:"topAxis",15:"axisFormat",16:"tickInterval",17:"excludes",18:"includes",19:"todayMarker",20:"title",21:"acc_title",22:"acc_title_value",23:"acc_descr",24:"acc_descr_value",25:"acc_descr_multiline_value",26:"section",28:"taskTxt",29:"taskData",33:":",35:"click",36:"callbackname",37:"callbackargs",38:"href",40:"open_directive",41:"type_directive",42:"arg_directive",43:"close_directive"},productions_:[0,[3,2],[3,3],[6,0],[6,2],[8,2],[8,1],[8,1],[8,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,2],[10,2],[10,1],[10,1],[10,1],[10,2],[10,1],[4,4],[4,6],[27,2],[27,3],[27,3],[27,4],[27,3],[27,4],[27,2],[39,2],[39,3],[39,3],[39,4],[39,3],[39,4],[39,2],[30,1],[31,1],[34,1],[32,1]],performAction:function(te,xe,De,he,Ie,ee,rt){var me=ee.length-1;switch(Ie){case 2:return ee[me-1];case 3:this.$=[];break;case 4:ee[me-1].push(ee[me]),this.$=ee[me-1];break;case 5:case 6:this.$=ee[me];break;case 7:case 8:this.$=[];break;case 9:he.setDateFormat(ee[me].substr(11)),this.$=ee[me].substr(11);break;case 10:he.enableInclusiveEndDates(),this.$=ee[me].substr(18);break;case 11:he.TopAxis(),this.$=ee[me].substr(8);break;case 12:he.setAxisFormat(ee[me].substr(11)),this.$=ee[me].substr(11);break;case 13:he.setTickInterval(ee[me].substr(13)),this.$=ee[me].substr(13);break;case 14:he.setExcludes(ee[me].substr(9)),this.$=ee[me].substr(9);break;case 15:he.setIncludes(ee[me].substr(9)),this.$=ee[me].substr(9);break;case 16:he.setTodayMarker(ee[me].substr(12)),this.$=ee[me].substr(12);break;case 17:he.setDiagramTitle(ee[me].substr(6)),this.$=ee[me].substr(6);break;case 18:this.$=ee[me].trim(),he.setAccTitle(this.$);break;case 19:case 20:this.$=ee[me].trim(),he.setAccDescription(this.$);break;case 21:he.addSection(ee[me].substr(8)),this.$=ee[me].substr(8);break;case 23:he.addTask(ee[me-1],ee[me]),this.$="task";break;case 27:this.$=ee[me-1],he.setClickEvent(ee[me-1],ee[me],null);break;case 28:this.$=ee[me-2],he.setClickEvent(ee[me-2],ee[me-1],ee[me]);break;case 29:this.$=ee[me-2],he.setClickEvent(ee[me-2],ee[me-1],null),he.setLink(ee[me-2],ee[me]);break;case 30:this.$=ee[me-3],he.setClickEvent(ee[me-3],ee[me-2],ee[me-1]),he.setLink(ee[me-3],ee[me]);break;case 31:this.$=ee[me-2],he.setClickEvent(ee[me-2],ee[me],null),he.setLink(ee[me-2],ee[me-1]);break;case 32:this.$=ee[me-3],he.setClickEvent(ee[me-3],ee[me-1],ee[me]),he.setLink(ee[me-3],ee[me-2]);break;case 33:this.$=ee[me-1],he.setLink(ee[me-1],ee[me]);break;case 34:case 40:this.$=ee[me-1]+" "+ee[me];break;case 35:case 36:case 38:this.$=ee[me-2]+" "+ee[me-1]+" "+ee[me];break;case 37:case 39:this.$=ee[me-3]+" "+ee[me-2]+" "+ee[me-1]+" "+ee[me];break;case 41:he.parseDirective("%%{","open_directive");break;case 42:he.parseDirective(ee[me],"type_directive");break;case 43:ee[me]=ee[me].trim().replace(/'/g,'"'),he.parseDirective(ee[me],"arg_directive");break;case 44:he.parseDirective("}%%","close_directive","gantt");break}},table:[{3:1,4:2,5:a,30:4,40:f},{1:[3]},{3:6,4:2,5:a,30:4,40:f},i(p,[2,3],{6:7}),{31:8,41:[1,9]},{41:[2,41]},{1:[2,1]},{4:30,7:[1,10],8:11,9:[1,12],10:13,11:[1,14],12:w,13:y,14:b,15:E,16:S,17:N,18:B,19:R,20:j,21:$,23:V,25:Q,26:oe,27:28,28:ce,30:4,35:se,40:f},{32:32,33:[1,33],43:ge},i([33,43],[2,42]),i(p,[2,8],{1:[2,2]}),i(p,[2,4]),{4:30,10:35,12:w,13:y,14:b,15:E,16:S,17:N,18:B,19:R,20:j,21:$,23:V,25:Q,26:oe,27:28,28:ce,30:4,35:se,40:f},i(p,[2,6]),i(p,[2,7]),i(p,[2,9]),i(p,[2,10]),i(p,[2,11]),i(p,[2,12]),i(p,[2,13]),i(p,[2,14]),i(p,[2,15]),i(p,[2,16]),i(p,[2,17]),{22:[1,36]},{24:[1,37]},i(p,[2,20]),i(p,[2,21]),i(p,[2,22]),{29:[1,38]},i(p,[2,24]),{36:[1,39],38:[1,40]},{11:[1,41]},{34:42,42:[1,43]},{11:[2,44]},i(p,[2,5]),i(p,[2,18]),i(p,[2,19]),i(p,[2,23]),i(p,[2,27],{37:[1,44],38:[1,45]}),i(p,[2,33],{36:[1,46]}),i(ye,[2,25]),{32:47,43:ge},{43:[2,43]},i(p,[2,28],{38:[1,48]}),i(p,[2,29]),i(p,[2,31],{37:[1,49]}),{11:[1,50]},i(p,[2,30]),i(p,[2,32]),i(ye,[2,26])],defaultActions:{5:[2,41],6:[2,1],34:[2,44],43:[2,43]},parseError:function(te,xe){if(xe.recoverable)this.trace(te);else{var De=new Error(te);throw De.hash=xe,De}},parse:function(te){var xe=this,De=[0],he=[],Ie=[null],ee=[],rt=this.table,me="",gt=0,pe=0,Et=2,wt=1,jt=ee.slice.call(arguments,1),At=Object.create(this.lexer),Bt={yy:{}};for(var cn in this.yy)Object.prototype.hasOwnProperty.call(this.yy,cn)&&(Bt.yy[cn]=this.yy[cn]);At.setInput(te,Bt.yy),Bt.yy.lexer=At,Bt.yy.parser=this,typeof At.yylloc>"u"&&(At.yylloc={});var Nn=At.yylloc;ee.push(Nn);var Ot=At.options&&At.options.ranges;typeof Bt.yy.parseError=="function"?this.parseError=Bt.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function oi(){var Ri;return Ri=he.pop()||At.lex()||wt,typeof Ri!="number"&&(Ri instanceof Array&&(he=Ri,Ri=he.pop()),Ri=xe.symbols_[Ri]||Ri),Ri}for(var kt,Dt,vt,Nt,ze={},Xe,Lt,Ge,Bn;;){if(Dt=De[De.length-1],this.defaultActions[Dt]?vt=this.defaultActions[Dt]:((kt===null||typeof kt>"u")&&(kt=oi()),vt=rt[Dt]&&rt[Dt][kt]),typeof vt>"u"||!vt.length||!vt[0]){var Oe="";Bn=[];for(Xe in rt[Dt])this.terminals_[Xe]&&Xe>Et&&Bn.push("'"+this.terminals_[Xe]+"'");At.showPosition?Oe="Parse error on line "+(gt+1)+`: +`+At.showPosition()+` +Expecting `+Bn.join(", ")+", got '"+(this.terminals_[kt]||kt)+"'":Oe="Parse error on line "+(gt+1)+": Unexpected "+(kt==wt?"end of input":"'"+(this.terminals_[kt]||kt)+"'"),this.parseError(Oe,{text:At.match,token:this.terminals_[kt]||kt,line:At.yylineno,loc:Nn,expected:Bn})}if(vt[0]instanceof Array&&vt.length>1)throw new Error("Parse Error: multiple actions possible at state: "+Dt+", token: "+kt);switch(vt[0]){case 1:De.push(kt),Ie.push(At.yytext),ee.push(At.yylloc),De.push(vt[1]),kt=null,pe=At.yyleng,me=At.yytext,gt=At.yylineno,Nn=At.yylloc;break;case 2:if(Lt=this.productions_[vt[1]][1],ze.$=Ie[Ie.length-Lt],ze._$={first_line:ee[ee.length-(Lt||1)].first_line,last_line:ee[ee.length-1].last_line,first_column:ee[ee.length-(Lt||1)].first_column,last_column:ee[ee.length-1].last_column},Ot&&(ze._$.range=[ee[ee.length-(Lt||1)].range[0],ee[ee.length-1].range[1]]),Nt=this.performAction.apply(ze,[me,pe,gt,Bt.yy,vt[1],Ie,ee].concat(jt)),typeof Nt<"u")return Nt;Lt&&(De=De.slice(0,-1*Lt*2),Ie=Ie.slice(0,-1*Lt),ee=ee.slice(0,-1*Lt)),De.push(this.productions_[vt[1]][0]),Ie.push(ze.$),ee.push(ze._$),Ge=rt[De[De.length-2]][De[De.length-1]],De.push(Ge);break;case 3:return!0}}return!0}},Ae=function(){var ve={EOF:1,parseError:function(xe,De){if(this.yy.parser)this.yy.parser.parseError(xe,De);else throw new Error(xe)},setInput:function(te,xe){return this.yy=xe||this.yy||{},this._input=te,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var te=this._input[0];this.yytext+=te,this.yyleng++,this.offset++,this.match+=te,this.matched+=te;var xe=te.match(/(?:\r\n?|\n).*/g);return xe?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),te},unput:function(te){var xe=te.length,De=te.split(/(?:\r\n?|\n)/g);this._input=te+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-xe),this.offset-=xe;var he=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),De.length-1&&(this.yylineno-=De.length-1);var Ie=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:De?(De.length===he.length?this.yylloc.first_column:0)+he[he.length-De.length].length-De[0].length:this.yylloc.first_column-xe},this.options.ranges&&(this.yylloc.range=[Ie[0],Ie[0]+this.yyleng-xe]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(te){this.unput(this.match.slice(te))},pastInput:function(){var te=this.matched.substr(0,this.matched.length-this.match.length);return(te.length>20?"...":"")+te.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var te=this.match;return te.length<20&&(te+=this._input.substr(0,20-te.length)),(te.substr(0,20)+(te.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var te=this.pastInput(),xe=new Array(te.length+1).join("-");return te+this.upcomingInput()+` +`+xe+"^"},test_match:function(te,xe){var De,he,Ie;if(this.options.backtrack_lexer&&(Ie={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(Ie.yylloc.range=this.yylloc.range.slice(0))),he=te[0].match(/(?:\r\n?|\n).*/g),he&&(this.yylineno+=he.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:he?he[he.length-1].length-he[he.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+te[0].length},this.yytext+=te[0],this.match+=te[0],this.matches=te,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(te[0].length),this.matched+=te[0],De=this.performAction.call(this,this.yy,this,xe,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),De)return De;if(this._backtrack){for(var ee in Ie)this[ee]=Ie[ee];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var te,xe,De,he;this._more||(this.yytext="",this.match="");for(var Ie=this._currentRules(),ee=0;eexe[0].length)){if(xe=De,he=ee,this.options.backtrack_lexer){if(te=this.test_match(De,Ie[ee]),te!==!1)return te;if(this._backtrack){xe=!1;continue}else return!1}else if(!this.options.flex)break}return xe?(te=this.test_match(xe,Ie[he]),te!==!1?te:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var xe=this.next();return xe||this.lex()},begin:function(xe){this.conditionStack.push(xe)},popState:function(){var xe=this.conditionStack.length-1;return xe>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(xe){return xe=this.conditionStack.length-1-Math.abs(xe||0),xe>=0?this.conditionStack[xe]:"INITIAL"},pushState:function(xe){this.begin(xe)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(xe,De,he,Ie){switch(he){case 0:return this.begin("open_directive"),40;case 1:return this.begin("type_directive"),41;case 2:return this.popState(),this.begin("arg_directive"),33;case 3:return this.popState(),this.popState(),43;case 4:return 42;case 5:return this.begin("acc_title"),21;case 6:return this.popState(),"acc_title_value";case 7:return this.begin("acc_descr"),23;case 8:return this.popState(),"acc_descr_value";case 9:this.begin("acc_descr_multiline");break;case 10:this.popState();break;case 11:return"acc_descr_multiline_value";case 12:break;case 13:break;case 14:break;case 15:return 11;case 16:break;case 17:break;case 18:break;case 19:this.begin("href");break;case 20:this.popState();break;case 21:return 38;case 22:this.begin("callbackname");break;case 23:this.popState();break;case 24:this.popState(),this.begin("callbackargs");break;case 25:return 36;case 26:this.popState();break;case 27:return 37;case 28:this.begin("click");break;case 29:this.popState();break;case 30:return 35;case 31:return 5;case 32:return 12;case 33:return 13;case 34:return 14;case 35:return 15;case 36:return 16;case 37:return 18;case 38:return 17;case 39:return 19;case 40:return"date";case 41:return 20;case 42:return"accDescription";case 43:return 26;case 44:return 28;case 45:return 29;case 46:return 33;case 47:return 7;case 48:return"INVALID"}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:%%(?!\{)*[^\n]*)/i,/^(?:[^\}]%%*[^\n]*)/i,/^(?:%%*[^\n]*[\n]*)/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:href[\s]+["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:call[\s]+)/i,/^(?:\([\s]*\))/i,/^(?:\()/i,/^(?:[^(]*)/i,/^(?:\))/i,/^(?:[^)]*)/i,/^(?:click[\s]+)/i,/^(?:[\s\n])/i,/^(?:[^\s\n]*)/i,/^(?:gantt\b)/i,/^(?:dateFormat\s[^#\n;]+)/i,/^(?:inclusiveEndDates\b)/i,/^(?:topAxis\b)/i,/^(?:axisFormat\s[^#\n;]+)/i,/^(?:tickInterval\s[^#\n;]+)/i,/^(?:includes\s[^#\n;]+)/i,/^(?:excludes\s[^#\n;]+)/i,/^(?:todayMarker\s[^\n;]+)/i,/^(?:\d\d\d\d-\d\d-\d\d\b)/i,/^(?:title\s[^#\n;]+)/i,/^(?:accDescription\s[^#\n;]+)/i,/^(?:section\s[^#:\n;]+)/i,/^(?:[^#:\n;]+)/i,/^(?::[^#\n;]+)/i,/^(?::)/i,/^(?:$)/i,/^(?:.)/i],conditions:{acc_descr_multiline:{rules:[10,11],inclusive:!1},acc_descr:{rules:[8],inclusive:!1},acc_title:{rules:[6],inclusive:!1},close_directive:{rules:[],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},open_directive:{rules:[1],inclusive:!1},callbackargs:{rules:[26,27],inclusive:!1},callbackname:{rules:[23,24,25],inclusive:!1},href:{rules:[20,21],inclusive:!1},click:{rules:[29,30],inclusive:!1},INITIAL:{rules:[0,5,7,9,12,13,14,15,16,17,18,19,22,28,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48],inclusive:!0}}};return ve}();ke.lexer=Ae;function de(){this.yy={}}return de.prototype=ke,ke.Parser=de,new de}();N0e.parser=N0e;const Ejt=N0e;var Tjt="isoweek";const _jt=function(i,a,f){var p=function(S,N){var B=(N?f.utc:f)().year(S).startOf(o5),R=4-B.isoWeekday();return B.isoWeekday()>4&&(R+=7),B.add(R,Fw)},w=function(S){return S.add(4-S.isoWeekday(),Fw)},y=a.prototype;y.isoWeekYear=function(){var E=w(this);return E.year()},y.isoWeek=function(E){if(!this.$utils().u(E))return this.add((E-this.isoWeek())*7,Fw);var S=w(this),N=p(this.isoWeekYear(),this.$u);return S.diff(N,yN)+1},y.isoWeekday=function(E){return this.$utils().u(E)?this.day()||7:this.day(this.day()%7?E:E-7)};var b=y.startOf;y.startOf=function(E,S){var N=this.$utils(),B=N.u(S)?!0:S,R=N.p(E);return R===Tjt?B?this.date(this.date()-(this.isoWeekday()-1)).startOf("day"):this.date(this.date()-1-(this.isoWeekday()-1)+7).endOf("day"):b.bind(this)(E,S)}};var Cjt=function(a){return a.replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g,function(f,p,w){return p||w.slice(1)})},Sjt={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},Ajt=function(a,f){return a.replace(/(\[[^\]]+])|(LTS?|l{1,4}|L{1,4})/g,function(p,w,y){var b=y&&y.toUpperCase();return w||f[y]||Sjt[y]||Cjt(f[b])})},Ljt=/(\[[^[]*\])|([-_:/.,()\s]+)|(A|a|YYYY|YY?|MM?M?M?|Do|DD?|hh?|HH?|mm?|ss?|S{1,3}|z|ZZ?)/g,Mjt=/\d/,TK=/\d\d/,Djt=/\d{3}/,Ijt=/\d{4}/,h3=/\d\d?/,Ojt=/[+-]?\d+/,Njt=/[+-]\d\d:?(\d\d)?|Z/,xP=/\d*[^-_:/,()\s\d]+/,ax={},pRe=function(a){return a=+a,a+(a>68?1900:2e3)};function Pjt(i){if(!i||i==="Z")return 0;var a=i.match(/([+-]|\d\d)/g),f=+(a[1]*60)+(+a[2]||0);return f===0?0:a[0]==="+"?-f:f}var cp=function(a){return function(f){this[a]=+f}},bRe=[Njt,function(i){var a=this.zone||(this.zone={});a.offset=Pjt(i)}],P0e=function(a){var f=ax[a];return f&&(f.indexOf?f:f.s.concat(f.f))},vRe=function(a,f){var p,w=ax,y=w.meridiem;if(!y)p=a===(f?"pm":"PM");else for(var b=1;b<=24;b+=1)if(a.indexOf(y(b,0,f))>-1){p=b>12;break}return p},Bjt={A:[xP,function(i){this.afternoon=vRe(i,!1)}],a:[xP,function(i){this.afternoon=vRe(i,!0)}],S:[Mjt,function(i){this.milliseconds=+i*100}],SS:[TK,function(i){this.milliseconds=+i*10}],SSS:[Djt,function(i){this.milliseconds=+i}],s:[h3,cp("seconds")],ss:[h3,cp("seconds")],m:[h3,cp("minutes")],mm:[h3,cp("minutes")],H:[h3,cp("hours")],h:[h3,cp("hours")],HH:[h3,cp("hours")],hh:[h3,cp("hours")],D:[h3,cp("day")],DD:[TK,cp("day")],Do:[xP,function(i){var a=ax,f=a.ordinal,p=i.match(/\d+/);if(this.day=p[0],!!f)for(var w=1;w<=31;w+=1)f(w).replace(/\[|\]/g,"")===i&&(this.day=w)}],M:[h3,cp("month")],MM:[TK,cp("month")],MMM:[xP,function(i){var a=P0e("months"),f=P0e("monthsShort"),p=(f||a.map(function(w){return w.slice(0,3)})).indexOf(i)+1;if(p<1)throw new Error;this.month=p%12||p}],MMMM:[xP,function(i){var a=P0e("months"),f=a.indexOf(i)+1;if(f<1)throw new Error;this.month=f%12||f}],Y:[Ojt,cp("year")],YY:[TK,function(i){this.year=pRe(i)}],YYYY:[Ijt,cp("year")],Z:bRe,ZZ:bRe};function Rjt(i){var a=i.afternoon;if(a!==void 0){var f=i.hours;a?f<12&&(i.hours+=12):f===12&&(i.hours=0),delete i.afternoon}}function Fjt(i){i=Ajt(i,ax&&ax.formats);for(var a=i.match(Ljt),f=a.length,p=0;p-1)return new Date((f==="X"?1e3:1)*a);var w=Fjt(f),y=w(a),b=y.year,E=y.month,S=y.day,N=y.hours,B=y.minutes,R=y.seconds,j=y.milliseconds,$=y.zone,V=new Date,Q=S||(!b&&!E?V.getDate():1),oe=b||V.getFullYear(),ce=0;b&&!E||(ce=E>0?E-1:V.getMonth());var se=N||0,ge=B||0,ye=R||0,ke=j||0;return $?new Date(Date.UTC(oe,ce,Q,se,ge,ye,ke+$.offset*60*1e3)):p?new Date(Date.UTC(oe,ce,Q,se,ge,ye,ke)):new Date(oe,ce,Q,se,ge,ye,ke)}catch{return new Date("")}};const $jt=function(i,a,f){f.p.customParseFormat=!0,i&&i.parseTwoDigitYear&&(pRe=i.parseTwoDigitYear);var p=a.prototype,w=p.parse;p.parse=function(y){var b=y.date,E=y.utc,S=y.args;this.$u=E;var N=S[1];if(typeof N=="string"){var B=S[2]===!0,R=S[3]===!0,j=B||R,$=S[2];R&&($=S[2]),ax=this.$locale(),!B&&$&&(ax=f.Ls[$]),this.$d=jjt(b,N,E),this.init(),$&&$!==!0&&(this.$L=this.locale($).$L),j&&b!=this.format(N)&&(this.$d=new Date("")),ax={}}else if(N instanceof Array)for(var V=N.length,Q=1;Q<=V;Q+=1){S[1]=N[Q-1];var oe=f.apply(this,S);if(oe.isValid()){this.$d=oe.$d,this.$L=oe.$L,this.init();break}Q===V&&(this.$d=new Date(""))}else w.call(this,y)}},Hjt=function(i,a){var f=a.prototype,p=f.format;f.format=function(w){var y=this,b=this.$locale();if(!this.isValid())return p.bind(this)(w);var E=this.$utils(),S=w||mLe,N=S.replace(/\[([^\]]+)]|Q|wo|ww|w|WW|W|zzz|z|gggg|GGGG|Do|X|x|k{1,2}|S/g,function(B){switch(B){case"Q":return Math.ceil((y.$M+1)/3);case"Do":return b.ordinal(y.$D);case"gggg":return y.weekYear();case"GGGG":return y.isoWeekYear();case"wo":return b.ordinal(y.week(),"W");case"w":case"ww":return E.s(y.week(),B==="w"?1:2,"0");case"W":case"WW":return E.s(y.isoWeek(),B==="W"?1:2,"0");case"k":case"kk":return E.s(String(y.$H===0?24:y.$H),B==="k"?1:2,"0");case"X":return Math.floor(y.$d.getTime()/1e3);case"x":return y.$d.getTime();case"z":return"["+y.offsetName()+"]";case"zzz":return"["+y.offsetName("long")+"]";default:return B}});return p.bind(this)(N)}};ru.extend(_jt),ru.extend($jt),ru.extend(Hjt);let f3="",B0e="",R0e,F0e="",EP=[],TP=[],j0e={},$0e=[],_K=[],iL="",H0e="";const wRe=["active","done","crit","milestone"];let z0e=[],_P=!1,G0e=!1,q0e=0;const zjt=function(i,a,f){rd.parseDirective(this,i,a,f)},Gjt=function(){$0e=[],_K=[],iL="",z0e=[],CK=0,U0e=void 0,SK=void 0,b1=[],f3="",B0e="",H0e="",R0e=void 0,F0e="",EP=[],TP=[],_P=!1,G0e=!1,q0e=0,j0e={},rp()},qjt=function(i){B0e=i},Vjt=function(){return B0e},Ujt=function(i){R0e=i},Wjt=function(){return R0e},Kjt=function(i){F0e=i},Yjt=function(){return F0e},Xjt=function(i){f3=i},Qjt=function(){_P=!0},Zjt=function(){return _P},Jjt=function(){G0e=!0},e$t=function(){return G0e},t$t=function(i){H0e=i},n$t=function(){return H0e},r$t=function(){return f3},i$t=function(i){EP=i.toLowerCase().split(/[\s,]+/)},s$t=function(){return EP},a$t=function(i){TP=i.toLowerCase().split(/[\s,]+/)},o$t=function(){return TP},c$t=function(){return j0e},u$t=function(i){iL=i,$0e.push(i)},l$t=function(){return $0e},h$t=function(){let i=TRe();const a=10;let f=0;for(;!i&&f=6&&f.includes("weekends")||f.includes(i.format("dddd").toLowerCase())?!0:f.includes(i.format(a.trim()))},yRe=function(i,a,f,p){if(!f.length||i.manualEndTime)return;let w;i.startTime instanceof Date?w=ru(i.startTime):w=ru(i.startTime,a,!0),w=w.add(1,"d");let y;i.endTime instanceof Date?y=ru(i.endTime):y=ru(i.endTime,a,!0);const[b,E]=f$t(w,y,a,f,p);i.endTime=b.toDate(),i.renderEndTime=E},f$t=function(i,a,f,p,w){let y=!1,b=null;for(;i<=a;)y||(b=a.toDate()),y=mRe(i,f,p,w),y&&(a=a.add(1,"d")),i=i.add(1,"d");return[a,b]},V0e=function(i,a,f){f=f.trim();const w=/^after\s+([\d\w- ]+)/.exec(f.trim());if(w!==null){let b=null;if(w[1].split(" ").forEach(function(E){let S=aL(E);S!==void 0&&(b?S.endTime>b.endTime&&(b=S):b=S)}),b)return b.endTime;{const E=new Date;return E.setHours(0,0,0,0),E}}let y=ru(f,a.trim(),!0);if(y.isValid())return y.toDate();{Fe.debug("Invalid date:"+f),Fe.debug("With date format:"+a.trim());const b=new Date(f);if(b===void 0||isNaN(b.getTime()))throw new Error("Invalid date:"+f);return b}},kRe=function(i){const a=/^(\d+(?:\.\d+)?)([Mdhmswy]|ms)$/.exec(i.trim());return a!==null?[Number.parseFloat(a[1]),a[2]]:[NaN,"ms"]},xRe=function(i,a,f,p=!1){f=f.trim();let w=ru(f,a.trim(),!0);if(w.isValid())return p&&(w=w.add(1,"d")),w.toDate();let y=ru(i);const[b,E]=kRe(f);if(!Number.isNaN(b)){const S=y.add(b,E);S.isValid()&&(y=S)}return y.toDate()};let CK=0;const sL=function(i){return i===void 0?(CK=CK+1,"task"+CK):i},d$t=function(i,a){let f;a.substr(0,1)===":"?f=a.substr(1,a.length):f=a;const p=f.split(","),w={};SRe(p,w,wRe);for(let b=0;b{window.open(f,"_self")}),j0e[p]=f)}),_Re(i,"clickable")},_Re=function(i,a){i.split(",").forEach(function(f){let p=aL(f);p!==void 0&&p.classes.push(a)})},w$t=function(i,a,f){if(Tt().securityLevel!=="loose"||a===void 0)return;let p=[];if(typeof f=="string"){p=f.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);for(let y=0;y{co.runFunc(a,...p)})},CRe=function(i,a){z0e.push(function(){const f=document.querySelector(`[id="${i}"]`);f!==null&&f.addEventListener("click",function(){a()})},function(){const f=document.querySelector(`[id="${i}-text"]`);f!==null&&f.addEventListener("click",function(){a()})})},m$t={parseDirective:zjt,getConfig:()=>Tt().gantt,clear:Gjt,setDateFormat:Xjt,getDateFormat:r$t,enableInclusiveEndDates:Qjt,endDatesAreInclusive:Zjt,enableTopAxis:Jjt,topAxisEnabled:e$t,setAxisFormat:qjt,getAxisFormat:Vjt,setTickInterval:Ujt,getTickInterval:Wjt,setTodayMarker:Kjt,getTodayMarker:Yjt,setAccTitle:ip,getAccTitle:L2,setDiagramTitle:Uw,getDiagramTitle:Ww,setDisplayMode:t$t,getDisplayMode:n$t,setAccDescription:M2,getAccDescription:D2,addSection:u$t,getSections:l$t,getTasks:h$t,addTask:p$t,findTaskById:aL,addTaskOrg:b$t,setIncludes:i$t,getIncludes:s$t,setExcludes:a$t,getExcludes:o$t,setClickEvent:function(i,a,f){i.split(",").forEach(function(p){w$t(p,a,f)}),_Re(i,"clickable")},setLink:v$t,getLinks:c$t,bindFunctions:function(i){z0e.forEach(function(a){a(i)})},parseDuration:kRe,isInvalidDate:mRe};function SRe(i,a,f){let p=!0;for(;p;)p=!1,f.forEach(function(w){const y="^\\s*"+w+"\\s*$",b=new RegExp(y);i[0].match(b)&&(a[w]=!0,i.shift(1),p=!0)})}const y$t=function(){Fe.debug("Something is calling, setConf, remove the call")},k$t=(i,a)=>{let f=[...i].map(()=>-1/0),p=[...i].sort((y,b)=>y.startTime-b.startTime||y.order-b.order),w=0;for(const y of p)for(let b=0;b=f[b]){f[b]=y.endTime,y.order=b+a,b>w&&(w=b);break}return w};let S5;const x$t=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:Ejt,db:m$t,renderer:{setConf:y$t,draw:function(i,a,f,p){const w=Tt().gantt,y=Tt().securityLevel;let b;y==="sandbox"&&(b=Cr("#i"+a));const E=Cr(y==="sandbox"?b.nodes()[0].contentDocument.body:"body"),S=y==="sandbox"?b.nodes()[0].contentDocument:document,N=S.getElementById(a);S5=N.parentElement.offsetWidth,S5===void 0&&(S5=1200),w.useWidth!==void 0&&(S5=w.useWidth);const B=p.db.getTasks();let R=[];for(const ve of B)R.push(ve.type);R=de(R);const j={};let $=2*w.topPadding;if(p.db.getDisplayMode()==="compact"||w.displayMode==="compact"){const ve={};for(const xe of B)ve[xe.section]===void 0?ve[xe.section]=[xe]:ve[xe.section].push(xe);let te=0;for(const xe of Object.keys(ve)){const De=k$t(ve[xe],te)+1;te+=De,$+=De*(w.barHeight+w.barGap),j[xe]=De}}else{$+=B.length*(w.barHeight+w.barGap);for(const ve of R)j[ve]=B.filter(te=>te.type===ve).length}N.setAttribute("viewBox","0 0 "+S5+" "+$);const V=E.select(`[id="${a}"]`),Q=J7t().domain([O5t(B,function(ve){return ve.startTime}),I5t(B,function(ve){return ve.endTime})]).rangeRound([0,S5-w.leftPadding-w.rightPadding]);function oe(ve,te){const xe=ve.startTime,De=te.startTime;let he=0;return xe>De?he=1:xewt.order))].map(wt=>ve.find(jt=>jt.order===wt));V.append("g").selectAll("rect").data(me).enter().append("rect").attr("x",0).attr("y",function(wt,jt){return jt=wt.order,jt*te+xe-2}).attr("width",function(){return ee-w.rightPadding/2}).attr("height",te).attr("class",function(wt){for(const[jt,At]of R.entries())if(wt.type===At)return"section section"+jt%w.numberSectionStyles;return"section section0"});const gt=V.append("g").selectAll("rect").data(ve).enter(),pe=p.db.getLinks();if(gt.append("rect").attr("id",function(wt){return wt.id}).attr("rx",3).attr("ry",3).attr("x",function(wt){return wt.milestone?Q(wt.startTime)+De+.5*(Q(wt.endTime)-Q(wt.startTime))-.5*he:Q(wt.startTime)+De}).attr("y",function(wt,jt){return jt=wt.order,jt*te+xe}).attr("width",function(wt){return wt.milestone?he:Q(wt.renderEndTime||wt.endTime)-Q(wt.startTime)}).attr("height",he).attr("transform-origin",function(wt,jt){return jt=wt.order,(Q(wt.startTime)+De+.5*(Q(wt.endTime)-Q(wt.startTime))).toString()+"px "+(jt*te+xe+.5*he).toString()+"px"}).attr("class",function(wt){const jt="task";let At="";wt.classes.length>0&&(At=wt.classes.join(" "));let Bt=0;for(const[Nn,Ot]of R.entries())wt.type===Ot&&(Bt=Nn%w.numberSectionStyles);let cn="";return wt.active?wt.crit?cn+=" activeCrit":cn=" active":wt.done?wt.crit?cn=" doneCrit":cn=" done":wt.crit&&(cn+=" crit"),cn.length===0&&(cn=" task"),wt.milestone&&(cn=" milestone "+cn),cn+=Bt,cn+=" "+At,jt+cn}),gt.append("text").attr("id",function(wt){return wt.id+"-text"}).text(function(wt){return wt.task}).attr("font-size",w.fontSize).attr("x",function(wt){let jt=Q(wt.startTime),At=Q(wt.renderEndTime||wt.endTime);wt.milestone&&(jt+=.5*(Q(wt.endTime)-Q(wt.startTime))-.5*he),wt.milestone&&(At=jt+he);const Bt=this.getBBox().width;return Bt>At-jt?At+Bt+1.5*w.leftPadding>ee?jt+De-5:At+De+5:(At-jt)/2+jt+De}).attr("y",function(wt,jt){return jt=wt.order,jt*te+w.barHeight/2+(w.fontSize/2-2)+xe}).attr("text-height",he).attr("class",function(wt){const jt=Q(wt.startTime);let At=Q(wt.endTime);wt.milestone&&(At=jt+he);const Bt=this.getBBox().width;let cn="";wt.classes.length>0&&(cn=wt.classes.join(" "));let Nn=0;for(const[oi,kt]of R.entries())wt.type===kt&&(Nn=oi%w.numberSectionStyles);let Ot="";return wt.active&&(wt.crit?Ot="activeCritText"+Nn:Ot="activeText"+Nn),wt.done?wt.crit?Ot=Ot+" doneCritText"+Nn:Ot=Ot+" doneText"+Nn:wt.crit&&(Ot=Ot+" critText"+Nn),wt.milestone&&(Ot+=" milestoneText"),Bt>At-jt?At+Bt+1.5*w.leftPadding>ee?cn+" taskTextOutsideLeft taskTextOutside"+Nn+" "+Ot:cn+" taskTextOutsideRight taskTextOutside"+Nn+" "+Ot+" width-"+Bt:cn+" taskText taskText"+Nn+" "+Ot+" width-"+Bt}),Tt().securityLevel==="sandbox"){let wt;wt=Cr("#i"+a);const jt=wt.nodes()[0].contentDocument;gt.filter(function(At){return pe[At.id]!==void 0}).each(function(At){var Bt=jt.querySelector("#"+At.id),cn=jt.querySelector("#"+At.id+"-text");const Nn=Bt.parentNode;var Ot=jt.createElement("a");Ot.setAttribute("xlink:href",pe[At.id]),Ot.setAttribute("target","_top"),Nn.appendChild(Ot),Ot.appendChild(Bt),Ot.appendChild(cn)})}}function ge(ve,te,xe,De,he,Ie,ee,rt){const me=Ie.reduce((Bt,{startTime:cn})=>Bt?Math.min(Bt,cn):cn,0),gt=Ie.reduce((Bt,{endTime:cn})=>Bt?Math.max(Bt,cn):cn,0),pe=p.db.getDateFormat();if(!me||!gt)return;const Et=[];let wt=null,jt=ru(me);for(;jt.valueOf()<=gt;)p.db.isInvalidDate(jt,pe,ee,rt)?wt?wt.end=jt:wt={start:jt,end:jt}:wt&&(Et.push(wt),wt=null),jt=jt.add(1,"d");V.append("g").selectAll("rect").data(Et).enter().append("rect").attr("id",function(Bt){return"exclude-"+Bt.start.format("YYYY-MM-DD")}).attr("x",function(Bt){return Q(Bt.start)+xe}).attr("y",w.gridLineStartPadding).attr("width",function(Bt){const cn=Bt.end.add(1,"day");return Q(cn)-Q(Bt.start)}).attr("height",he-te-w.gridLineStartPadding).attr("transform-origin",function(Bt,cn){return(Q(Bt.start)+xe+.5*(Q(Bt.end)-Q(Bt.start))).toString()+"px "+(cn*ve+.5*he).toString()+"px"}).attr("class","exclude-range")}function ye(ve,te,xe,De){let he=H5t(Q).tickSize(-De+te+w.gridLineStartPadding).tickFormat($U(p.db.getAxisFormat()||w.axisFormat||"%Y-%m-%d"));const ee=/^([1-9]\d*)(minute|hour|day|week|month)$/.exec(p.db.getTickInterval()||w.tickInterval);if(ee!==null){const rt=ee[1];switch(ee[2]){case"minute":he.ticks(PU.every(rt));break;case"hour":he.ticks(BU.every(rt));break;case"day":he.ticks(yA.every(rt));break;case"week":he.ticks(kA.every(rt));break;case"month":he.ticks(FU.every(rt));break}}if(V.append("g").attr("class","grid").attr("transform","translate("+ve+", "+(De-50)+")").call(he).selectAll("text").style("text-anchor","middle").attr("fill","#000").attr("stroke","none").attr("font-size",10).attr("dy","1em"),p.db.topAxisEnabled()||w.topAxis){let rt=$5t(Q).tickSize(-De+te+w.gridLineStartPadding).tickFormat($U(p.db.getAxisFormat()||w.axisFormat||"%Y-%m-%d"));if(ee!==null){const me=ee[1];switch(ee[2]){case"minute":rt.ticks(PU.every(me));break;case"hour":rt.ticks(BU.every(me));break;case"day":rt.ticks(yA.every(me));break;case"week":rt.ticks(kA.every(me));break;case"month":rt.ticks(FU.every(me));break}}V.append("g").attr("class","grid").attr("transform","translate("+ve+", "+te+")").call(rt).selectAll("text").style("text-anchor","middle").attr("fill","#000").attr("stroke","none").attr("font-size",10)}}function ke(ve,te){let xe=0;const De=Object.keys(j).map(he=>[he,j[he]]);V.append("g").selectAll("text").data(De).enter().append(function(he){const Ie=he[0].split(Wa.lineBreakRegex),ee=-(Ie.length-1)/2,rt=S.createElementNS("http://www.w3.org/2000/svg","text");rt.setAttribute("dy",ee+"em");for(const[me,gt]of Ie.entries()){const pe=S.createElementNS("http://www.w3.org/2000/svg","tspan");pe.setAttribute("alignment-baseline","central"),pe.setAttribute("x","10"),me>0&&pe.setAttribute("dy","1em"),pe.textContent=gt,rt.appendChild(pe)}return rt}).attr("x",10).attr("y",function(he,Ie){if(Ie>0)for(let ee=0;ee` + .mermaid-main-font { + font-family: "trebuchet ms", verdana, arial, sans-serif; + font-family: var(--mermaid-font-family); + } + .exclude-range { + fill: ${i.excludeBkgColor}; + } + + .section { + stroke: none; + opacity: 0.2; + } + + .section0 { + fill: ${i.sectionBkgColor}; + } + + .section2 { + fill: ${i.sectionBkgColor2}; + } + + .section1, + .section3 { + fill: ${i.altSectionBkgColor}; + opacity: 0.2; + } + + .sectionTitle0 { + fill: ${i.titleColor}; + } + + .sectionTitle1 { + fill: ${i.titleColor}; + } + + .sectionTitle2 { + fill: ${i.titleColor}; + } + + .sectionTitle3 { + fill: ${i.titleColor}; + } + + .sectionTitle { + text-anchor: start; + // font-size: ${i.ganttFontSize}; + // text-height: 14px; + font-family: 'trebuchet ms', verdana, arial, sans-serif; + font-family: var(--mermaid-font-family); + + } + + + /* Grid and axis */ + + .grid .tick { + stroke: ${i.gridColor}; + opacity: 0.8; + shape-rendering: crispEdges; + text { + font-family: ${i.fontFamily}; + fill: ${i.textColor}; + } + } + + .grid path { + stroke-width: 0; + } + + + /* Today line */ + + .today { + fill: none; + stroke: ${i.todayLineColor}; + stroke-width: 2px; + } + + + /* Task styling */ + + /* Default task */ + + .task { + stroke-width: 2; + } + + .taskText { + text-anchor: middle; + font-family: 'trebuchet ms', verdana, arial, sans-serif; + font-family: var(--mermaid-font-family); + } + + // .taskText:not([font-size]) { + // font-size: ${i.ganttFontSize}; + // } + + .taskTextOutsideRight { + fill: ${i.taskTextDarkColor}; + text-anchor: start; + // font-size: ${i.ganttFontSize}; + font-family: 'trebuchet ms', verdana, arial, sans-serif; + font-family: var(--mermaid-font-family); + + } + + .taskTextOutsideLeft { + fill: ${i.taskTextDarkColor}; + text-anchor: end; + // font-size: ${i.ganttFontSize}; + } + + /* Special case clickable */ + .task.clickable { + cursor: pointer; + } + .taskText.clickable { + cursor: pointer; + fill: ${i.taskTextClickableColor} !important; + font-weight: bold; + } + + .taskTextOutsideLeft.clickable { + cursor: pointer; + fill: ${i.taskTextClickableColor} !important; + font-weight: bold; + } + + .taskTextOutsideRight.clickable { + cursor: pointer; + fill: ${i.taskTextClickableColor} !important; + font-weight: bold; + } + + /* Specific task settings for the sections*/ + + .taskText0, + .taskText1, + .taskText2, + .taskText3 { + fill: ${i.taskTextColor}; + } + + .task0, + .task1, + .task2, + .task3 { + fill: ${i.taskBkgColor}; + stroke: ${i.taskBorderColor}; + } + + .taskTextOutside0, + .taskTextOutside2 + { + fill: ${i.taskTextOutsideColor}; + } + + .taskTextOutside1, + .taskTextOutside3 { + fill: ${i.taskTextOutsideColor}; + } + + + /* Active task */ + + .active0, + .active1, + .active2, + .active3 { + fill: ${i.activeTaskBkgColor}; + stroke: ${i.activeTaskBorderColor}; + } + + .activeText0, + .activeText1, + .activeText2, + .activeText3 { + fill: ${i.taskTextDarkColor} !important; + } + + + /* Completed task */ + + .done0, + .done1, + .done2, + .done3 { + stroke: ${i.doneTaskBorderColor}; + fill: ${i.doneTaskBkgColor}; + stroke-width: 2; + } + + .doneText0, + .doneText1, + .doneText2, + .doneText3 { + fill: ${i.taskTextDarkColor} !important; + } + + + /* Tasks on the critical line */ + + .crit0, + .crit1, + .crit2, + .crit3 { + stroke: ${i.critBorderColor}; + fill: ${i.critBkgColor}; + stroke-width: 2; + } + + .activeCrit0, + .activeCrit1, + .activeCrit2, + .activeCrit3 { + stroke: ${i.critBorderColor}; + fill: ${i.activeTaskBkgColor}; + stroke-width: 2; + } + + .doneCrit0, + .doneCrit1, + .doneCrit2, + .doneCrit3 { + stroke: ${i.critBorderColor}; + fill: ${i.doneTaskBkgColor}; + stroke-width: 2; + cursor: pointer; + shape-rendering: crispEdges; + } + + .milestone { + transform: rotate(45deg) scale(0.8,0.8); + } + + .milestoneText { + font-style: italic; + } + .doneCritText0, + .doneCritText1, + .doneCritText2, + .doneCritText3 { + fill: ${i.taskTextDarkColor} !important; + } + + .activeCritText0, + .activeCritText1, + .activeCritText2, + .activeCritText3 { + fill: ${i.taskTextDarkColor} !important; + } + + .titleText { + text-anchor: middle; + font-size: 18px; + fill: ${i.textColor} ; + font-family: 'trebuchet ms', verdana, arial, sans-serif; + font-family: var(--mermaid-font-family); + } +`}},Symbol.toStringTag,{value:"Module"}));var W0e=function(){var i=function(y,b,E,S){for(E=E||{},S=y.length;S--;E[y[S]]=b);return E},a=[6,9,10],f={trace:function(){},yy:{},symbols_:{error:2,start:3,info:4,document:5,EOF:6,line:7,statement:8,NL:9,showInfo:10,$accept:0,$end:1},terminals_:{2:"error",4:"info",6:"EOF",9:"NL",10:"showInfo"},productions_:[0,[3,3],[5,0],[5,2],[7,1],[7,1],[8,1]],performAction:function(b,E,S,N,B,R,j){switch(R.length-1,B){case 1:return N;case 4:break;case 6:N.setInfo(!0);break}},table:[{3:1,4:[1,2]},{1:[3]},i(a,[2,2],{5:3}),{6:[1,4],7:5,8:6,9:[1,7],10:[1,8]},{1:[2,1]},i(a,[2,3]),i(a,[2,4]),i(a,[2,5]),i(a,[2,6])],defaultActions:{4:[2,1]},parseError:function(b,E){if(E.recoverable)this.trace(b);else{var S=new Error(b);throw S.hash=E,S}},parse:function(b){var E=this,S=[0],N=[],B=[null],R=[],j=this.table,$="",V=0,Q=0,oe=2,ce=1,se=R.slice.call(arguments,1),ge=Object.create(this.lexer),ye={yy:{}};for(var ke in this.yy)Object.prototype.hasOwnProperty.call(this.yy,ke)&&(ye.yy[ke]=this.yy[ke]);ge.setInput(b,ye.yy),ye.yy.lexer=ge,ye.yy.parser=this,typeof ge.yylloc>"u"&&(ge.yylloc={});var Ae=ge.yylloc;R.push(Ae);var de=ge.options&&ge.options.ranges;typeof ye.yy.parseError=="function"?this.parseError=ye.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function ve(){var Et;return Et=N.pop()||ge.lex()||ce,typeof Et!="number"&&(Et instanceof Array&&(N=Et,Et=N.pop()),Et=E.symbols_[Et]||Et),Et}for(var te,xe,De,he,Ie={},ee,rt,me,gt;;){if(xe=S[S.length-1],this.defaultActions[xe]?De=this.defaultActions[xe]:((te===null||typeof te>"u")&&(te=ve()),De=j[xe]&&j[xe][te]),typeof De>"u"||!De.length||!De[0]){var pe="";gt=[];for(ee in j[xe])this.terminals_[ee]&&ee>oe&>.push("'"+this.terminals_[ee]+"'");ge.showPosition?pe="Parse error on line "+(V+1)+`: +`+ge.showPosition()+` +Expecting `+gt.join(", ")+", got '"+(this.terminals_[te]||te)+"'":pe="Parse error on line "+(V+1)+": Unexpected "+(te==ce?"end of input":"'"+(this.terminals_[te]||te)+"'"),this.parseError(pe,{text:ge.match,token:this.terminals_[te]||te,line:ge.yylineno,loc:Ae,expected:gt})}if(De[0]instanceof Array&&De.length>1)throw new Error("Parse Error: multiple actions possible at state: "+xe+", token: "+te);switch(De[0]){case 1:S.push(te),B.push(ge.yytext),R.push(ge.yylloc),S.push(De[1]),te=null,Q=ge.yyleng,$=ge.yytext,V=ge.yylineno,Ae=ge.yylloc;break;case 2:if(rt=this.productions_[De[1]][1],Ie.$=B[B.length-rt],Ie._$={first_line:R[R.length-(rt||1)].first_line,last_line:R[R.length-1].last_line,first_column:R[R.length-(rt||1)].first_column,last_column:R[R.length-1].last_column},de&&(Ie._$.range=[R[R.length-(rt||1)].range[0],R[R.length-1].range[1]]),he=this.performAction.apply(Ie,[$,Q,V,ye.yy,De[1],B,R].concat(se)),typeof he<"u")return he;rt&&(S=S.slice(0,-1*rt*2),B=B.slice(0,-1*rt),R=R.slice(0,-1*rt)),S.push(this.productions_[De[1]][0]),B.push(Ie.$),R.push(Ie._$),me=j[S[S.length-2]][S[S.length-1]],S.push(me);break;case 3:return!0}}return!0}},p=function(){var y={EOF:1,parseError:function(E,S){if(this.yy.parser)this.yy.parser.parseError(E,S);else throw new Error(E)},setInput:function(b,E){return this.yy=E||this.yy||{},this._input=b,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var b=this._input[0];this.yytext+=b,this.yyleng++,this.offset++,this.match+=b,this.matched+=b;var E=b.match(/(?:\r\n?|\n).*/g);return E?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),b},unput:function(b){var E=b.length,S=b.split(/(?:\r\n?|\n)/g);this._input=b+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-E),this.offset-=E;var N=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),S.length-1&&(this.yylineno-=S.length-1);var B=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:S?(S.length===N.length?this.yylloc.first_column:0)+N[N.length-S.length].length-S[0].length:this.yylloc.first_column-E},this.options.ranges&&(this.yylloc.range=[B[0],B[0]+this.yyleng-E]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(b){this.unput(this.match.slice(b))},pastInput:function(){var b=this.matched.substr(0,this.matched.length-this.match.length);return(b.length>20?"...":"")+b.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var b=this.match;return b.length<20&&(b+=this._input.substr(0,20-b.length)),(b.substr(0,20)+(b.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var b=this.pastInput(),E=new Array(b.length+1).join("-");return b+this.upcomingInput()+` +`+E+"^"},test_match:function(b,E){var S,N,B;if(this.options.backtrack_lexer&&(B={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(B.yylloc.range=this.yylloc.range.slice(0))),N=b[0].match(/(?:\r\n?|\n).*/g),N&&(this.yylineno+=N.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:N?N[N.length-1].length-N[N.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+b[0].length},this.yytext+=b[0],this.match+=b[0],this.matches=b,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(b[0].length),this.matched+=b[0],S=this.performAction.call(this,this.yy,this,E,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),S)return S;if(this._backtrack){for(var R in B)this[R]=B[R];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var b,E,S,N;this._more||(this.yytext="",this.match="");for(var B=this._currentRules(),R=0;RE[0].length)){if(E=S,N=R,this.options.backtrack_lexer){if(b=this.test_match(S,B[R]),b!==!1)return b;if(this._backtrack){E=!1;continue}else return!1}else if(!this.options.flex)break}return E?(b=this.test_match(E,B[N]),b!==!1?b:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var E=this.next();return E||this.lex()},begin:function(E){this.conditionStack.push(E)},popState:function(){var E=this.conditionStack.length-1;return E>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(E){return E=this.conditionStack.length-1-Math.abs(E||0),E>=0?this.conditionStack[E]:"INITIAL"},pushState:function(E){this.begin(E)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(E,S,N,B){switch(N){case 0:return 4;case 1:return 9;case 2:return"space";case 3:return 10;case 4:return 6;case 5:return"TXT"}},rules:[/^(?:info\b)/i,/^(?:[\s\n\r]+)/i,/^(?:[\s]+)/i,/^(?:showInfo\b)/i,/^(?:$)/i,/^(?:.)/i],conditions:{INITIAL:{rules:[0,1,2,3,4,5],inclusive:!0}}};return y}();f.lexer=p;function w(){this.yy={}}return w.prototype=f,f.Parser=w,new w}();W0e.parser=W0e;const E$t=W0e;var ARe="",LRe=!1;const T$t=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:E$t,db:{setMessage:i=>{Fe.debug("Setting message to: "+i),ARe=i},getMessage:()=>ARe,setInfo:i=>{LRe=i},getInfo:()=>LRe,clear:rp},renderer:{draw:(i,a,f)=>{try{Fe.debug(`Rendering info diagram +`+i);const p=Tt().securityLevel;let w;p==="sandbox"&&(w=Cr("#i"+a));const b=Cr(p==="sandbox"?w.nodes()[0].contentDocument.body:"body").select("#"+a);b.append("g").append("text").attr("x",100).attr("y",40).attr("class","version").attr("font-size","32px").style("text-anchor","middle").text("v "+f),b.attr("height",100),b.attr("width",400)}catch(p){Fe.error("Error while rendering info diagram"),Fe.error(p.message)}}},styles:()=>""}},Symbol.toStringTag,{value:"Module"}));var K0e=function(){var i=function(Ae,de,ve,te){for(ve=ve||{},te=Ae.length;te--;ve[Ae[te]]=de);return ve},a=[1,4],f=[1,5],p=[1,6],w=[1,7],y=[1,9],b=[1,11,13,15,17,19,20,26,27,28,29],E=[2,5],S=[1,6,11,13,15,17,19,20,26,27,28,29],N=[26,27,28],B=[2,8],R=[1,18],j=[1,19],$=[1,20],V=[1,21],Q=[1,22],oe=[1,23],ce=[1,28],se=[6,26,27,28,29],ge={trace:function(){},yy:{},symbols_:{error:2,start:3,eol:4,directive:5,PIE:6,document:7,showData:8,line:9,statement:10,txt:11,value:12,title:13,title_value:14,acc_title:15,acc_title_value:16,acc_descr:17,acc_descr_value:18,acc_descr_multiline_value:19,section:20,openDirective:21,typeDirective:22,closeDirective:23,":":24,argDirective:25,NEWLINE:26,";":27,EOF:28,open_directive:29,type_directive:30,arg_directive:31,close_directive:32,$accept:0,$end:1},terminals_:{2:"error",6:"PIE",8:"showData",11:"txt",12:"value",13:"title",14:"title_value",15:"acc_title",16:"acc_title_value",17:"acc_descr",18:"acc_descr_value",19:"acc_descr_multiline_value",20:"section",24:":",26:"NEWLINE",27:";",28:"EOF",29:"open_directive",30:"type_directive",31:"arg_directive",32:"close_directive"},productions_:[0,[3,2],[3,2],[3,2],[3,3],[7,0],[7,2],[9,2],[10,0],[10,2],[10,2],[10,2],[10,2],[10,1],[10,1],[10,1],[5,3],[5,5],[4,1],[4,1],[4,1],[21,1],[22,1],[25,1],[23,1]],performAction:function(de,ve,te,xe,De,he,Ie){var ee=he.length-1;switch(De){case 4:xe.setShowData(!0);break;case 7:this.$=he[ee-1];break;case 9:xe.addSection(he[ee-1],xe.cleanupValue(he[ee]));break;case 10:this.$=he[ee].trim(),xe.setDiagramTitle(this.$);break;case 11:this.$=he[ee].trim(),xe.setAccTitle(this.$);break;case 12:case 13:this.$=he[ee].trim(),xe.setAccDescription(this.$);break;case 14:xe.addSection(he[ee].substr(8)),this.$=he[ee].substr(8);break;case 21:xe.parseDirective("%%{","open_directive");break;case 22:xe.parseDirective(he[ee],"type_directive");break;case 23:he[ee]=he[ee].trim().replace(/'/g,'"'),xe.parseDirective(he[ee],"arg_directive");break;case 24:xe.parseDirective("}%%","close_directive","pie");break}},table:[{3:1,4:2,5:3,6:a,21:8,26:f,27:p,28:w,29:y},{1:[3]},{3:10,4:2,5:3,6:a,21:8,26:f,27:p,28:w,29:y},{3:11,4:2,5:3,6:a,21:8,26:f,27:p,28:w,29:y},i(b,E,{7:12,8:[1,13]}),i(S,[2,18]),i(S,[2,19]),i(S,[2,20]),{22:14,30:[1,15]},{30:[2,21]},{1:[2,1]},{1:[2,2]},i(N,B,{21:8,9:16,10:17,5:24,1:[2,3],11:R,13:j,15:$,17:V,19:Q,20:oe,29:y}),i(b,E,{7:25}),{23:26,24:[1,27],32:ce},i([24,32],[2,22]),i(b,[2,6]),{4:29,26:f,27:p,28:w},{12:[1,30]},{14:[1,31]},{16:[1,32]},{18:[1,33]},i(N,[2,13]),i(N,[2,14]),i(N,[2,15]),i(N,B,{21:8,9:16,10:17,5:24,1:[2,4],11:R,13:j,15:$,17:V,19:Q,20:oe,29:y}),i(se,[2,16]),{25:34,31:[1,35]},i(se,[2,24]),i(b,[2,7]),i(N,[2,9]),i(N,[2,10]),i(N,[2,11]),i(N,[2,12]),{23:36,32:ce},{32:[2,23]},i(se,[2,17])],defaultActions:{9:[2,21],10:[2,1],11:[2,2],35:[2,23]},parseError:function(de,ve){if(ve.recoverable)this.trace(de);else{var te=new Error(de);throw te.hash=ve,te}},parse:function(de){var ve=this,te=[0],xe=[],De=[null],he=[],Ie=this.table,ee="",rt=0,me=0,gt=2,pe=1,Et=he.slice.call(arguments,1),wt=Object.create(this.lexer),jt={yy:{}};for(var At in this.yy)Object.prototype.hasOwnProperty.call(this.yy,At)&&(jt.yy[At]=this.yy[At]);wt.setInput(de,jt.yy),jt.yy.lexer=wt,jt.yy.parser=this,typeof wt.yylloc>"u"&&(wt.yylloc={});var Bt=wt.yylloc;he.push(Bt);var cn=wt.options&&wt.options.ranges;typeof jt.yy.parseError=="function"?this.parseError=jt.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Nn(){var Bn;return Bn=xe.pop()||wt.lex()||pe,typeof Bn!="number"&&(Bn instanceof Array&&(xe=Bn,Bn=xe.pop()),Bn=ve.symbols_[Bn]||Bn),Bn}for(var Ot,oi,kt,Dt,vt={},Nt,ze,Xe,Lt;;){if(oi=te[te.length-1],this.defaultActions[oi]?kt=this.defaultActions[oi]:((Ot===null||typeof Ot>"u")&&(Ot=Nn()),kt=Ie[oi]&&Ie[oi][Ot]),typeof kt>"u"||!kt.length||!kt[0]){var Ge="";Lt=[];for(Nt in Ie[oi])this.terminals_[Nt]&&Nt>gt&&Lt.push("'"+this.terminals_[Nt]+"'");wt.showPosition?Ge="Parse error on line "+(rt+1)+`: +`+wt.showPosition()+` +Expecting `+Lt.join(", ")+", got '"+(this.terminals_[Ot]||Ot)+"'":Ge="Parse error on line "+(rt+1)+": Unexpected "+(Ot==pe?"end of input":"'"+(this.terminals_[Ot]||Ot)+"'"),this.parseError(Ge,{text:wt.match,token:this.terminals_[Ot]||Ot,line:wt.yylineno,loc:Bt,expected:Lt})}if(kt[0]instanceof Array&&kt.length>1)throw new Error("Parse Error: multiple actions possible at state: "+oi+", token: "+Ot);switch(kt[0]){case 1:te.push(Ot),De.push(wt.yytext),he.push(wt.yylloc),te.push(kt[1]),Ot=null,me=wt.yyleng,ee=wt.yytext,rt=wt.yylineno,Bt=wt.yylloc;break;case 2:if(ze=this.productions_[kt[1]][1],vt.$=De[De.length-ze],vt._$={first_line:he[he.length-(ze||1)].first_line,last_line:he[he.length-1].last_line,first_column:he[he.length-(ze||1)].first_column,last_column:he[he.length-1].last_column},cn&&(vt._$.range=[he[he.length-(ze||1)].range[0],he[he.length-1].range[1]]),Dt=this.performAction.apply(vt,[ee,me,rt,jt.yy,kt[1],De,he].concat(Et)),typeof Dt<"u")return Dt;ze&&(te=te.slice(0,-1*ze*2),De=De.slice(0,-1*ze),he=he.slice(0,-1*ze)),te.push(this.productions_[kt[1]][0]),De.push(vt.$),he.push(vt._$),Xe=Ie[te[te.length-2]][te[te.length-1]],te.push(Xe);break;case 3:return!0}}return!0}},ye=function(){var Ae={EOF:1,parseError:function(ve,te){if(this.yy.parser)this.yy.parser.parseError(ve,te);else throw new Error(ve)},setInput:function(de,ve){return this.yy=ve||this.yy||{},this._input=de,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var de=this._input[0];this.yytext+=de,this.yyleng++,this.offset++,this.match+=de,this.matched+=de;var ve=de.match(/(?:\r\n?|\n).*/g);return ve?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),de},unput:function(de){var ve=de.length,te=de.split(/(?:\r\n?|\n)/g);this._input=de+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-ve),this.offset-=ve;var xe=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),te.length-1&&(this.yylineno-=te.length-1);var De=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:te?(te.length===xe.length?this.yylloc.first_column:0)+xe[xe.length-te.length].length-te[0].length:this.yylloc.first_column-ve},this.options.ranges&&(this.yylloc.range=[De[0],De[0]+this.yyleng-ve]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(de){this.unput(this.match.slice(de))},pastInput:function(){var de=this.matched.substr(0,this.matched.length-this.match.length);return(de.length>20?"...":"")+de.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var de=this.match;return de.length<20&&(de+=this._input.substr(0,20-de.length)),(de.substr(0,20)+(de.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var de=this.pastInput(),ve=new Array(de.length+1).join("-");return de+this.upcomingInput()+` +`+ve+"^"},test_match:function(de,ve){var te,xe,De;if(this.options.backtrack_lexer&&(De={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(De.yylloc.range=this.yylloc.range.slice(0))),xe=de[0].match(/(?:\r\n?|\n).*/g),xe&&(this.yylineno+=xe.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:xe?xe[xe.length-1].length-xe[xe.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+de[0].length},this.yytext+=de[0],this.match+=de[0],this.matches=de,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(de[0].length),this.matched+=de[0],te=this.performAction.call(this,this.yy,this,ve,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),te)return te;if(this._backtrack){for(var he in De)this[he]=De[he];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var de,ve,te,xe;this._more||(this.yytext="",this.match="");for(var De=this._currentRules(),he=0;heve[0].length)){if(ve=te,xe=he,this.options.backtrack_lexer){if(de=this.test_match(te,De[he]),de!==!1)return de;if(this._backtrack){ve=!1;continue}else return!1}else if(!this.options.flex)break}return ve?(de=this.test_match(ve,De[xe]),de!==!1?de:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var ve=this.next();return ve||this.lex()},begin:function(ve){this.conditionStack.push(ve)},popState:function(){var ve=this.conditionStack.length-1;return ve>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(ve){return ve=this.conditionStack.length-1-Math.abs(ve||0),ve>=0?this.conditionStack[ve]:"INITIAL"},pushState:function(ve){this.begin(ve)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(ve,te,xe,De){switch(xe){case 0:return this.begin("open_directive"),29;case 1:return this.begin("type_directive"),30;case 2:return this.popState(),this.begin("arg_directive"),24;case 3:return this.popState(),this.popState(),32;case 4:return 31;case 5:break;case 6:break;case 7:return 26;case 8:break;case 9:break;case 10:return this.begin("title"),13;case 11:return this.popState(),"title_value";case 12:return this.begin("acc_title"),15;case 13:return this.popState(),"acc_title_value";case 14:return this.begin("acc_descr"),17;case 15:return this.popState(),"acc_descr_value";case 16:this.begin("acc_descr_multiline");break;case 17:this.popState();break;case 18:return"acc_descr_multiline_value";case 19:this.begin("string");break;case 20:this.popState();break;case 21:return"txt";case 22:return 6;case 23:return 8;case 24:return"value";case 25:return 28}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:%%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n\r]+)/i,/^(?:%%[^\n]*)/i,/^(?:[\s]+)/i,/^(?:title\b)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:pie\b)/i,/^(?:showData\b)/i,/^(?::[\s]*[\d]+(?:\.[\d]+)?)/i,/^(?:$)/i],conditions:{acc_descr_multiline:{rules:[17,18],inclusive:!1},acc_descr:{rules:[15],inclusive:!1},acc_title:{rules:[13],inclusive:!1},close_directive:{rules:[],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},open_directive:{rules:[1],inclusive:!1},title:{rules:[11],inclusive:!1},string:{rules:[20,21],inclusive:!1},INITIAL:{rules:[0,5,6,7,8,9,10,12,14,16,19,22,23,24,25],inclusive:!0}}};return Ae}();ge.lexer=ye;function ke(){this.yy={}}return ke.prototype=ge,ge.Parser=ke,new ke}();K0e.parser=K0e;const _$t=K0e;let AK={},Y0e=!1;const C$t={parseDirective:function(i,a,f){rd.parseDirective(this,i,a,f)},getConfig:()=>Tt().pie,addSection:function(i,a){i=Wa.sanitizeText(i,Tt()),AK[i]===void 0&&(AK[i]=a,Fe.debug("Added new section :",i))},getSections:()=>AK,cleanupValue:function(i){return i.substring(0,1)===":"&&(i=i.substring(1).trim()),Number(i.trim())},clear:function(){AK={},Y0e=!1,rp()},setAccTitle:ip,getAccTitle:L2,setDiagramTitle:Uw,getDiagramTitle:Ww,setShowData:function(i){Y0e=i},getShowData:function(){return Y0e},getAccDescription:D2,setAccDescription:M2},S$t=i=>` + .pieCircle{ + stroke: ${i.pieStrokeColor}; + stroke-width : ${i.pieStrokeWidth}; + opacity : ${i.pieOpacity}; + } + .pieOuterCircle{ + stroke: ${i.pieOuterStrokeColor}; + stroke-width: ${i.pieOuterStrokeWidth}; + fill: none; + } + .pieTitleText { + text-anchor: middle; + font-size: ${i.pieTitleTextSize}; + fill: ${i.pieTitleTextColor}; + font-family: ${i.fontFamily}; + } + .slice { + font-family: ${i.fontFamily}; + fill: ${i.pieSectionTextColor}; + font-size:${i.pieSectionTextSize}; + // fill: white; + } + .legend text { + fill: ${i.pieLegendTextColor}; + font-family: ${i.fontFamily}; + font-size: ${i.pieLegendTextSize}; + } +`;let d3=Tt(),A5;const CP=450,A$t=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:_$t,db:C$t,renderer:{draw:(i,a,f,p)=>{var ge;try{d3=Tt(),Fe.debug(`Rendering info diagram +`+i);const ye=Tt().securityLevel;let ke;ye==="sandbox"&&(ke=Cr("#i"+a));const Ae=Cr(ye==="sandbox"?ke.nodes()[0].contentDocument.body:"body"),de=ye==="sandbox"?ke.nodes()[0].contentDocument:document;p.db.clear(),p.parser.parse(i),Fe.debug("Parsed info diagram");const ve=de.getElementById(a);A5=ve.parentElement.offsetWidth,A5===void 0&&(A5=1200),d3.useWidth!==void 0&&(A5=d3.useWidth),d3.pie.useWidth!==void 0&&(A5=d3.pie.useWidth);const te=Ae.select("#"+a);Vw(te,CP,A5,d3.pie.useMaxWidth),ve.setAttribute("viewBox","0 0 "+A5+" "+CP);var w=40,y=18,b=4,E=Math.min(A5,CP)/2-w,S=te.append("g").attr("transform","translate("+A5/2+","+CP/2+")"),N=p.db.getSections(),B=0;Object.keys(N).forEach(function(Ie){B+=N[Ie]});const xe=d3.themeVariables;var R=[xe.pie1,xe.pie2,xe.pie3,xe.pie4,xe.pie5,xe.pie6,xe.pie7,xe.pie8,xe.pie9,xe.pie10,xe.pie11,xe.pie12];const De=((ge=d3.pie)==null?void 0:ge.textPosition)??.75;let[he]=$A(xe.pieOuterStrokeWidth);he??(he=2);var j=DMe().range(R),$=Object.entries(N).map(function(Ie,ee){return{order:ee,name:Ie[0],value:Ie[1]}}),V=fEt().value(function(Ie){return Ie.value}).sort(function(Ie,ee){return Ie.order-ee.order}),Q=V($),oe=CA().innerRadius(0).outerRadius(E),ce=CA().innerRadius(E*De).outerRadius(E*De);S.append("circle").attr("cx",0).attr("cy",0).attr("r",E+he/2).attr("class","pieOuterCircle"),S.selectAll("mySlices").data(Q).enter().append("path").attr("d",oe).attr("fill",function(Ie){return j(Ie.data.name)}).attr("class","pieCircle"),S.selectAll("mySlices").data(Q).enter().append("text").text(function(Ie){return(Ie.data.value/B*100).toFixed(0)+"%"}).attr("transform",function(Ie){return"translate("+ce.centroid(Ie)+")"}).style("text-anchor","middle").attr("class","slice"),S.append("text").text(p.db.getDiagramTitle()).attr("x",0).attr("y",-(CP-50)/2).attr("class","pieTitleText");var se=S.selectAll(".legend").data(j.domain()).enter().append("g").attr("class","legend").attr("transform",function(Ie,ee){const rt=y+b,me=rt*j.domain().length/2,gt=12*y,pe=ee*rt-me;return"translate("+gt+","+pe+")"});se.append("rect").attr("width",y).attr("height",y).style("fill",j).style("stroke",j),se.data(Q).append("text").attr("x",y+b).attr("y",y-b).text(function(Ie){return p.db.getShowData()||d3.showData||d3.pie.showData?Ie.data.name+" ["+Ie.data.value+"]":Ie.data.name})}catch(ye){Fe.error("Error while rendering info diagram"),Fe.error(ye)}}},styles:S$t}},Symbol.toStringTag,{value:"Module"}));var X0e=function(){var i=function(oi,kt,Dt,vt){for(Dt=Dt||{},vt=oi.length;vt--;Dt[oi[vt]]=kt);return Dt},a=[1,3],f=[1,5],p=[1,6],w=[1,7],y=[1,8],b=[5,6,8,14,16,18,19,40,41,42,43,44,45,53,71,72],E=[1,22],S=[2,13],N=[1,26],B=[1,27],R=[1,28],j=[1,29],$=[1,30],V=[1,31],Q=[1,24],oe=[1,32],ce=[1,33],se=[1,36],ge=[71,72],ye=[5,8,14,16,18,19,40,41,42,43,44,45,53,60,62,71,72],ke=[1,56],Ae=[1,57],de=[1,58],ve=[1,59],te=[1,60],xe=[1,61],De=[1,62],he=[62,63],Ie=[1,74],ee=[1,70],rt=[1,71],me=[1,72],gt=[1,73],pe=[1,75],Et=[1,79],wt=[1,80],jt=[1,77],At=[1,78],Bt=[5,8,14,16,18,19,40,41,42,43,44,45,53,71,72],cn={trace:function(){},yy:{},symbols_:{error:2,start:3,directive:4,NEWLINE:5,RD:6,diagram:7,EOF:8,openDirective:9,typeDirective:10,closeDirective:11,":":12,argDirective:13,acc_title:14,acc_title_value:15,acc_descr:16,acc_descr_value:17,acc_descr_multiline_value:18,open_directive:19,type_directive:20,arg_directive:21,close_directive:22,requirementDef:23,elementDef:24,relationshipDef:25,requirementType:26,requirementName:27,STRUCT_START:28,requirementBody:29,ID:30,COLONSEP:31,id:32,TEXT:33,text:34,RISK:35,riskLevel:36,VERIFYMTHD:37,verifyType:38,STRUCT_STOP:39,REQUIREMENT:40,FUNCTIONAL_REQUIREMENT:41,INTERFACE_REQUIREMENT:42,PERFORMANCE_REQUIREMENT:43,PHYSICAL_REQUIREMENT:44,DESIGN_CONSTRAINT:45,LOW_RISK:46,MED_RISK:47,HIGH_RISK:48,VERIFY_ANALYSIS:49,VERIFY_DEMONSTRATION:50,VERIFY_INSPECTION:51,VERIFY_TEST:52,ELEMENT:53,elementName:54,elementBody:55,TYPE:56,type:57,DOCREF:58,ref:59,END_ARROW_L:60,relationship:61,LINE:62,END_ARROW_R:63,CONTAINS:64,COPIES:65,DERIVES:66,SATISFIES:67,VERIFIES:68,REFINES:69,TRACES:70,unqString:71,qString:72,$accept:0,$end:1},terminals_:{2:"error",5:"NEWLINE",6:"RD",8:"EOF",12:":",14:"acc_title",15:"acc_title_value",16:"acc_descr",17:"acc_descr_value",18:"acc_descr_multiline_value",19:"open_directive",20:"type_directive",21:"arg_directive",22:"close_directive",28:"STRUCT_START",30:"ID",31:"COLONSEP",33:"TEXT",35:"RISK",37:"VERIFYMTHD",39:"STRUCT_STOP",40:"REQUIREMENT",41:"FUNCTIONAL_REQUIREMENT",42:"INTERFACE_REQUIREMENT",43:"PERFORMANCE_REQUIREMENT",44:"PHYSICAL_REQUIREMENT",45:"DESIGN_CONSTRAINT",46:"LOW_RISK",47:"MED_RISK",48:"HIGH_RISK",49:"VERIFY_ANALYSIS",50:"VERIFY_DEMONSTRATION",51:"VERIFY_INSPECTION",52:"VERIFY_TEST",53:"ELEMENT",56:"TYPE",58:"DOCREF",60:"END_ARROW_L",62:"LINE",63:"END_ARROW_R",64:"CONTAINS",65:"COPIES",66:"DERIVES",67:"SATISFIES",68:"VERIFIES",69:"REFINES",70:"TRACES",71:"unqString",72:"qString"},productions_:[0,[3,3],[3,2],[3,4],[4,3],[4,5],[4,2],[4,2],[4,1],[9,1],[10,1],[13,1],[11,1],[7,0],[7,2],[7,2],[7,2],[7,2],[7,2],[23,5],[29,5],[29,5],[29,5],[29,5],[29,2],[29,1],[26,1],[26,1],[26,1],[26,1],[26,1],[26,1],[36,1],[36,1],[36,1],[38,1],[38,1],[38,1],[38,1],[24,5],[55,5],[55,5],[55,2],[55,1],[25,5],[25,5],[61,1],[61,1],[61,1],[61,1],[61,1],[61,1],[61,1],[27,1],[27,1],[32,1],[32,1],[34,1],[34,1],[54,1],[54,1],[57,1],[57,1],[59,1],[59,1]],performAction:function(kt,Dt,vt,Nt,ze,Xe,Lt){var Ge=Xe.length-1;switch(ze){case 6:this.$=Xe[Ge].trim(),Nt.setAccTitle(this.$);break;case 7:case 8:this.$=Xe[Ge].trim(),Nt.setAccDescription(this.$);break;case 9:Nt.parseDirective("%%{","open_directive");break;case 10:Nt.parseDirective(Xe[Ge],"type_directive");break;case 11:Xe[Ge]=Xe[Ge].trim().replace(/'/g,'"'),Nt.parseDirective(Xe[Ge],"arg_directive");break;case 12:Nt.parseDirective("}%%","close_directive","pie");break;case 13:this.$=[];break;case 19:Nt.addRequirement(Xe[Ge-3],Xe[Ge-4]);break;case 20:Nt.setNewReqId(Xe[Ge-2]);break;case 21:Nt.setNewReqText(Xe[Ge-2]);break;case 22:Nt.setNewReqRisk(Xe[Ge-2]);break;case 23:Nt.setNewReqVerifyMethod(Xe[Ge-2]);break;case 26:this.$=Nt.RequirementType.REQUIREMENT;break;case 27:this.$=Nt.RequirementType.FUNCTIONAL_REQUIREMENT;break;case 28:this.$=Nt.RequirementType.INTERFACE_REQUIREMENT;break;case 29:this.$=Nt.RequirementType.PERFORMANCE_REQUIREMENT;break;case 30:this.$=Nt.RequirementType.PHYSICAL_REQUIREMENT;break;case 31:this.$=Nt.RequirementType.DESIGN_CONSTRAINT;break;case 32:this.$=Nt.RiskLevel.LOW_RISK;break;case 33:this.$=Nt.RiskLevel.MED_RISK;break;case 34:this.$=Nt.RiskLevel.HIGH_RISK;break;case 35:this.$=Nt.VerifyType.VERIFY_ANALYSIS;break;case 36:this.$=Nt.VerifyType.VERIFY_DEMONSTRATION;break;case 37:this.$=Nt.VerifyType.VERIFY_INSPECTION;break;case 38:this.$=Nt.VerifyType.VERIFY_TEST;break;case 39:Nt.addElement(Xe[Ge-3]);break;case 40:Nt.setNewElementType(Xe[Ge-2]);break;case 41:Nt.setNewElementDocRef(Xe[Ge-2]);break;case 44:Nt.addRelationship(Xe[Ge-2],Xe[Ge],Xe[Ge-4]);break;case 45:Nt.addRelationship(Xe[Ge-2],Xe[Ge-4],Xe[Ge]);break;case 46:this.$=Nt.Relationships.CONTAINS;break;case 47:this.$=Nt.Relationships.COPIES;break;case 48:this.$=Nt.Relationships.DERIVES;break;case 49:this.$=Nt.Relationships.SATISFIES;break;case 50:this.$=Nt.Relationships.VERIFIES;break;case 51:this.$=Nt.Relationships.REFINES;break;case 52:this.$=Nt.Relationships.TRACES;break}},table:[{3:1,4:2,6:a,9:4,14:f,16:p,18:w,19:y},{1:[3]},{3:10,4:2,5:[1,9],6:a,9:4,14:f,16:p,18:w,19:y},{5:[1,11]},{10:12,20:[1,13]},{15:[1,14]},{17:[1,15]},i(b,[2,8]),{20:[2,9]},{3:16,4:2,6:a,9:4,14:f,16:p,18:w,19:y},{1:[2,2]},{4:21,5:E,7:17,8:S,9:4,14:f,16:p,18:w,19:y,23:18,24:19,25:20,26:23,32:25,40:N,41:B,42:R,43:j,44:$,45:V,53:Q,71:oe,72:ce},{11:34,12:[1,35],22:se},i([12,22],[2,10]),i(b,[2,6]),i(b,[2,7]),{1:[2,1]},{8:[1,37]},{4:21,5:E,7:38,8:S,9:4,14:f,16:p,18:w,19:y,23:18,24:19,25:20,26:23,32:25,40:N,41:B,42:R,43:j,44:$,45:V,53:Q,71:oe,72:ce},{4:21,5:E,7:39,8:S,9:4,14:f,16:p,18:w,19:y,23:18,24:19,25:20,26:23,32:25,40:N,41:B,42:R,43:j,44:$,45:V,53:Q,71:oe,72:ce},{4:21,5:E,7:40,8:S,9:4,14:f,16:p,18:w,19:y,23:18,24:19,25:20,26:23,32:25,40:N,41:B,42:R,43:j,44:$,45:V,53:Q,71:oe,72:ce},{4:21,5:E,7:41,8:S,9:4,14:f,16:p,18:w,19:y,23:18,24:19,25:20,26:23,32:25,40:N,41:B,42:R,43:j,44:$,45:V,53:Q,71:oe,72:ce},{4:21,5:E,7:42,8:S,9:4,14:f,16:p,18:w,19:y,23:18,24:19,25:20,26:23,32:25,40:N,41:B,42:R,43:j,44:$,45:V,53:Q,71:oe,72:ce},{27:43,71:[1,44],72:[1,45]},{54:46,71:[1,47],72:[1,48]},{60:[1,49],62:[1,50]},i(ge,[2,26]),i(ge,[2,27]),i(ge,[2,28]),i(ge,[2,29]),i(ge,[2,30]),i(ge,[2,31]),i(ye,[2,55]),i(ye,[2,56]),i(b,[2,4]),{13:51,21:[1,52]},i(b,[2,12]),{1:[2,3]},{8:[2,14]},{8:[2,15]},{8:[2,16]},{8:[2,17]},{8:[2,18]},{28:[1,53]},{28:[2,53]},{28:[2,54]},{28:[1,54]},{28:[2,59]},{28:[2,60]},{61:55,64:ke,65:Ae,66:de,67:ve,68:te,69:xe,70:De},{61:63,64:ke,65:Ae,66:de,67:ve,68:te,69:xe,70:De},{11:64,22:se},{22:[2,11]},{5:[1,65]},{5:[1,66]},{62:[1,67]},i(he,[2,46]),i(he,[2,47]),i(he,[2,48]),i(he,[2,49]),i(he,[2,50]),i(he,[2,51]),i(he,[2,52]),{63:[1,68]},i(b,[2,5]),{5:Ie,29:69,30:ee,33:rt,35:me,37:gt,39:pe},{5:Et,39:wt,55:76,56:jt,58:At},{32:81,71:oe,72:ce},{32:82,71:oe,72:ce},i(Bt,[2,19]),{31:[1,83]},{31:[1,84]},{31:[1,85]},{31:[1,86]},{5:Ie,29:87,30:ee,33:rt,35:me,37:gt,39:pe},i(Bt,[2,25]),i(Bt,[2,39]),{31:[1,88]},{31:[1,89]},{5:Et,39:wt,55:90,56:jt,58:At},i(Bt,[2,43]),i(Bt,[2,44]),i(Bt,[2,45]),{32:91,71:oe,72:ce},{34:92,71:[1,93],72:[1,94]},{36:95,46:[1,96],47:[1,97],48:[1,98]},{38:99,49:[1,100],50:[1,101],51:[1,102],52:[1,103]},i(Bt,[2,24]),{57:104,71:[1,105],72:[1,106]},{59:107,71:[1,108],72:[1,109]},i(Bt,[2,42]),{5:[1,110]},{5:[1,111]},{5:[2,57]},{5:[2,58]},{5:[1,112]},{5:[2,32]},{5:[2,33]},{5:[2,34]},{5:[1,113]},{5:[2,35]},{5:[2,36]},{5:[2,37]},{5:[2,38]},{5:[1,114]},{5:[2,61]},{5:[2,62]},{5:[1,115]},{5:[2,63]},{5:[2,64]},{5:Ie,29:116,30:ee,33:rt,35:me,37:gt,39:pe},{5:Ie,29:117,30:ee,33:rt,35:me,37:gt,39:pe},{5:Ie,29:118,30:ee,33:rt,35:me,37:gt,39:pe},{5:Ie,29:119,30:ee,33:rt,35:me,37:gt,39:pe},{5:Et,39:wt,55:120,56:jt,58:At},{5:Et,39:wt,55:121,56:jt,58:At},i(Bt,[2,20]),i(Bt,[2,21]),i(Bt,[2,22]),i(Bt,[2,23]),i(Bt,[2,40]),i(Bt,[2,41])],defaultActions:{8:[2,9],10:[2,2],16:[2,1],37:[2,3],38:[2,14],39:[2,15],40:[2,16],41:[2,17],42:[2,18],44:[2,53],45:[2,54],47:[2,59],48:[2,60],52:[2,11],93:[2,57],94:[2,58],96:[2,32],97:[2,33],98:[2,34],100:[2,35],101:[2,36],102:[2,37],103:[2,38],105:[2,61],106:[2,62],108:[2,63],109:[2,64]},parseError:function(kt,Dt){if(Dt.recoverable)this.trace(kt);else{var vt=new Error(kt);throw vt.hash=Dt,vt}},parse:function(kt){var Dt=this,vt=[0],Nt=[],ze=[null],Xe=[],Lt=this.table,Ge="",Bn=0,Oe=0,Ri=2,tn=1,hi=Xe.slice.call(arguments,1),Sr=Object.create(this.lexer),Zn={yy:{}};for(var Xn in this.yy)Object.prototype.hasOwnProperty.call(this.yy,Xn)&&(Zn.yy[Xn]=this.yy[Xn]);Sr.setInput(kt,Zn.yy),Zn.yy.lexer=Sr,Zn.yy.parser=this,typeof Sr.yylloc>"u"&&(Sr.yylloc={});var ir=Sr.yylloc;Xe.push(ir);var Hn=Sr.options&&Sr.options.ranges;typeof Zn.yy.parseError=="function"?this.parseError=Zn.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function tr(){var br;return br=Nt.pop()||Sr.lex()||tn,typeof br!="number"&&(br instanceof Array&&(Nt=br,br=Nt.pop()),br=Dt.symbols_[br]||br),br}for(var ha,Zs,ns,Hi,Js={},Pc,Ga,ws,Oi;;){if(Zs=vt[vt.length-1],this.defaultActions[Zs]?ns=this.defaultActions[Zs]:((ha===null||typeof ha>"u")&&(ha=tr()),ns=Lt[Zs]&&Lt[Zs][ha]),typeof ns>"u"||!ns.length||!ns[0]){var Er="";Oi=[];for(Pc in Lt[Zs])this.terminals_[Pc]&&Pc>Ri&&Oi.push("'"+this.terminals_[Pc]+"'");Sr.showPosition?Er="Parse error on line "+(Bn+1)+`: +`+Sr.showPosition()+` +Expecting `+Oi.join(", ")+", got '"+(this.terminals_[ha]||ha)+"'":Er="Parse error on line "+(Bn+1)+": Unexpected "+(ha==tn?"end of input":"'"+(this.terminals_[ha]||ha)+"'"),this.parseError(Er,{text:Sr.match,token:this.terminals_[ha]||ha,line:Sr.yylineno,loc:ir,expected:Oi})}if(ns[0]instanceof Array&&ns.length>1)throw new Error("Parse Error: multiple actions possible at state: "+Zs+", token: "+ha);switch(ns[0]){case 1:vt.push(ha),ze.push(Sr.yytext),Xe.push(Sr.yylloc),vt.push(ns[1]),ha=null,Oe=Sr.yyleng,Ge=Sr.yytext,Bn=Sr.yylineno,ir=Sr.yylloc;break;case 2:if(Ga=this.productions_[ns[1]][1],Js.$=ze[ze.length-Ga],Js._$={first_line:Xe[Xe.length-(Ga||1)].first_line,last_line:Xe[Xe.length-1].last_line,first_column:Xe[Xe.length-(Ga||1)].first_column,last_column:Xe[Xe.length-1].last_column},Hn&&(Js._$.range=[Xe[Xe.length-(Ga||1)].range[0],Xe[Xe.length-1].range[1]]),Hi=this.performAction.apply(Js,[Ge,Oe,Bn,Zn.yy,ns[1],ze,Xe].concat(hi)),typeof Hi<"u")return Hi;Ga&&(vt=vt.slice(0,-1*Ga*2),ze=ze.slice(0,-1*Ga),Xe=Xe.slice(0,-1*Ga)),vt.push(this.productions_[ns[1]][0]),ze.push(Js.$),Xe.push(Js._$),ws=Lt[vt[vt.length-2]][vt[vt.length-1]],vt.push(ws);break;case 3:return!0}}return!0}},Nn=function(){var oi={EOF:1,parseError:function(Dt,vt){if(this.yy.parser)this.yy.parser.parseError(Dt,vt);else throw new Error(Dt)},setInput:function(kt,Dt){return this.yy=Dt||this.yy||{},this._input=kt,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var kt=this._input[0];this.yytext+=kt,this.yyleng++,this.offset++,this.match+=kt,this.matched+=kt;var Dt=kt.match(/(?:\r\n?|\n).*/g);return Dt?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),kt},unput:function(kt){var Dt=kt.length,vt=kt.split(/(?:\r\n?|\n)/g);this._input=kt+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-Dt),this.offset-=Dt;var Nt=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),vt.length-1&&(this.yylineno-=vt.length-1);var ze=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:vt?(vt.length===Nt.length?this.yylloc.first_column:0)+Nt[Nt.length-vt.length].length-vt[0].length:this.yylloc.first_column-Dt},this.options.ranges&&(this.yylloc.range=[ze[0],ze[0]+this.yyleng-Dt]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(kt){this.unput(this.match.slice(kt))},pastInput:function(){var kt=this.matched.substr(0,this.matched.length-this.match.length);return(kt.length>20?"...":"")+kt.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var kt=this.match;return kt.length<20&&(kt+=this._input.substr(0,20-kt.length)),(kt.substr(0,20)+(kt.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var kt=this.pastInput(),Dt=new Array(kt.length+1).join("-");return kt+this.upcomingInput()+` +`+Dt+"^"},test_match:function(kt,Dt){var vt,Nt,ze;if(this.options.backtrack_lexer&&(ze={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(ze.yylloc.range=this.yylloc.range.slice(0))),Nt=kt[0].match(/(?:\r\n?|\n).*/g),Nt&&(this.yylineno+=Nt.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:Nt?Nt[Nt.length-1].length-Nt[Nt.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+kt[0].length},this.yytext+=kt[0],this.match+=kt[0],this.matches=kt,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(kt[0].length),this.matched+=kt[0],vt=this.performAction.call(this,this.yy,this,Dt,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),vt)return vt;if(this._backtrack){for(var Xe in ze)this[Xe]=ze[Xe];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var kt,Dt,vt,Nt;this._more||(this.yytext="",this.match="");for(var ze=this._currentRules(),Xe=0;XeDt[0].length)){if(Dt=vt,Nt=Xe,this.options.backtrack_lexer){if(kt=this.test_match(vt,ze[Xe]),kt!==!1)return kt;if(this._backtrack){Dt=!1;continue}else return!1}else if(!this.options.flex)break}return Dt?(kt=this.test_match(Dt,ze[Nt]),kt!==!1?kt:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var Dt=this.next();return Dt||this.lex()},begin:function(Dt){this.conditionStack.push(Dt)},popState:function(){var Dt=this.conditionStack.length-1;return Dt>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(Dt){return Dt=this.conditionStack.length-1-Math.abs(Dt||0),Dt>=0?this.conditionStack[Dt]:"INITIAL"},pushState:function(Dt){this.begin(Dt)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(Dt,vt,Nt,ze){switch(Nt){case 0:return this.begin("open_directive"),19;case 1:return this.begin("type_directive"),20;case 2:return this.popState(),this.begin("arg_directive"),12;case 3:return this.popState(),this.popState(),22;case 4:return 21;case 5:return"title";case 6:return this.begin("acc_title"),14;case 7:return this.popState(),"acc_title_value";case 8:return this.begin("acc_descr"),16;case 9:return this.popState(),"acc_descr_value";case 10:this.begin("acc_descr_multiline");break;case 11:this.popState();break;case 12:return"acc_descr_multiline_value";case 13:return 5;case 14:break;case 15:break;case 16:break;case 17:return 8;case 18:return 6;case 19:return 28;case 20:return 39;case 21:return 31;case 22:return 30;case 23:return 33;case 24:return 35;case 25:return 37;case 26:return 40;case 27:return 41;case 28:return 42;case 29:return 43;case 30:return 44;case 31:return 45;case 32:return 46;case 33:return 47;case 34:return 48;case 35:return 49;case 36:return 50;case 37:return 51;case 38:return 52;case 39:return 53;case 40:return 64;case 41:return 65;case 42:return 66;case 43:return 67;case 44:return 68;case 45:return 69;case 46:return 70;case 47:return 56;case 48:return 58;case 49:return 60;case 50:return 63;case 51:return 62;case 52:this.begin("string");break;case 53:this.popState();break;case 54:return"qString";case 55:return vt.yytext=vt.yytext.trim(),71}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:title\s[^#\n;]+)/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:(\r?\n)+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:$)/i,/^(?:requirementDiagram\b)/i,/^(?:\{)/i,/^(?:\})/i,/^(?::)/i,/^(?:id\b)/i,/^(?:text\b)/i,/^(?:risk\b)/i,/^(?:verifyMethod\b)/i,/^(?:requirement\b)/i,/^(?:functionalRequirement\b)/i,/^(?:interfaceRequirement\b)/i,/^(?:performanceRequirement\b)/i,/^(?:physicalRequirement\b)/i,/^(?:designConstraint\b)/i,/^(?:low\b)/i,/^(?:medium\b)/i,/^(?:high\b)/i,/^(?:analysis\b)/i,/^(?:demonstration\b)/i,/^(?:inspection\b)/i,/^(?:test\b)/i,/^(?:element\b)/i,/^(?:contains\b)/i,/^(?:copies\b)/i,/^(?:derives\b)/i,/^(?:satisfies\b)/i,/^(?:verifies\b)/i,/^(?:refines\b)/i,/^(?:traces\b)/i,/^(?:type\b)/i,/^(?:docref\b)/i,/^(?:<-)/i,/^(?:->)/i,/^(?:-)/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[\w][^\r\n\{\<\>\-\=]*)/i],conditions:{acc_descr_multiline:{rules:[11,12],inclusive:!1},acc_descr:{rules:[9],inclusive:!1},acc_title:{rules:[7],inclusive:!1},close_directive:{rules:[],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},open_directive:{rules:[1],inclusive:!1},unqString:{rules:[],inclusive:!1},token:{rules:[],inclusive:!1},string:{rules:[53,54],inclusive:!1},INITIAL:{rules:[0,5,6,8,10,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,55],inclusive:!0}}};return oi}();cn.lexer=Nn;function Ot(){this.yy={}}return Ot.prototype=cn,cn.Parser=Ot,new Ot}();X0e.parser=X0e;const L$t=X0e;let Q0e=[],up={},SP={},ox={},AP={};const M$t={RequirementType:{REQUIREMENT:"Requirement",FUNCTIONAL_REQUIREMENT:"Functional Requirement",INTERFACE_REQUIREMENT:"Interface Requirement",PERFORMANCE_REQUIREMENT:"Performance Requirement",PHYSICAL_REQUIREMENT:"Physical Requirement",DESIGN_CONSTRAINT:"Design Constraint"},RiskLevel:{LOW_RISK:"Low",MED_RISK:"Medium",HIGH_RISK:"High"},VerifyType:{VERIFY_ANALYSIS:"Analysis",VERIFY_DEMONSTRATION:"Demonstration",VERIFY_INSPECTION:"Inspection",VERIFY_TEST:"Test"},Relationships:{CONTAINS:"contains",COPIES:"copies",DERIVES:"derives",SATISFIES:"satisfies",VERIFIES:"verifies",REFINES:"refines",TRACES:"traces"},parseDirective:function(i,a,f){rd.parseDirective(this,i,a,f)},getConfig:()=>Tt().req,addRequirement:(i,a)=>(SP[i]===void 0&&(SP[i]={name:i,type:a,id:up.id,text:up.text,risk:up.risk,verifyMethod:up.verifyMethod}),up={},SP[i]),getRequirements:()=>SP,setNewReqId:i=>{up!==void 0&&(up.id=i)},setNewReqText:i=>{up!==void 0&&(up.text=i)},setNewReqRisk:i=>{up!==void 0&&(up.risk=i)},setNewReqVerifyMethod:i=>{up!==void 0&&(up.verifyMethod=i)},setAccTitle:ip,getAccTitle:L2,setAccDescription:M2,getAccDescription:D2,addElement:i=>(AP[i]===void 0&&(AP[i]={name:i,type:ox.type,docRef:ox.docRef},Fe.info("Added new requirement: ",i)),ox={},AP[i]),getElements:()=>AP,setNewElementType:i=>{ox!==void 0&&(ox.type=i)},setNewElementDocRef:i=>{ox!==void 0&&(ox.docRef=i)},addRelationship:(i,a,f)=>{Q0e.push({type:i,src:a,dst:f})},getRelationships:()=>Q0e,clear:()=>{Q0e=[],up={},SP={},ox={},AP={},rp()}},D$t=i=>` + + marker { + fill: ${i.relationColor}; + stroke: ${i.relationColor}; + } + + marker.cross { + stroke: ${i.lineColor}; + } + + svg { + font-family: ${i.fontFamily}; + font-size: ${i.fontSize}; + } + + .reqBox { + fill: ${i.requirementBackground}; + fill-opacity: 1.0; + stroke: ${i.requirementBorderColor}; + stroke-width: ${i.requirementBorderSize}; + } + + .reqTitle, .reqLabel{ + fill: ${i.requirementTextColor}; + } + .reqLabelBox { + fill: ${i.relationLabelBackground}; + fill-opacity: 1.0; + } + + .req-title-line { + stroke: ${i.requirementBorderColor}; + stroke-width: ${i.requirementBorderSize}; + } + .relationshipLine { + stroke: ${i.relationColor}; + stroke-width: 1; + } + .relationshipLabel { + fill: ${i.relationLabelColor}; + } + +`,Z0e={CONTAINS:"contains",ARROW:"arrow"},MRe={ReqMarkers:Z0e,insertLineEndings:(i,a)=>{let f=i.append("defs").append("marker").attr("id",Z0e.CONTAINS+"_line_ending").attr("refX",0).attr("refY",a.line_height/2).attr("markerWidth",a.line_height).attr("markerHeight",a.line_height).attr("orient","auto").append("g");f.append("circle").attr("cx",a.line_height/2).attr("cy",a.line_height/2).attr("r",a.line_height/2).attr("fill","none"),f.append("line").attr("x1",0).attr("x2",a.line_height).attr("y1",a.line_height/2).attr("y2",a.line_height/2).attr("stroke-width",1),f.append("line").attr("y1",0).attr("y2",a.line_height).attr("x1",a.line_height/2).attr("x2",a.line_height/2).attr("stroke-width",1),i.append("defs").append("marker").attr("id",Z0e.ARROW+"_line_ending").attr("refX",a.line_height).attr("refY",.5*a.line_height).attr("markerWidth",a.line_height).attr("markerHeight",a.line_height).attr("orient","auto").append("path").attr("d",`M0,0 + L${a.line_height},${a.line_height/2} + M${a.line_height},${a.line_height/2} + L0,${a.line_height}`).attr("stroke-width",1)}};let Mh={},DRe=0;const IRe=(i,a)=>i.insert("rect","#"+a).attr("class","req reqBox").attr("x",0).attr("y",0).attr("width",Mh.rect_min_width+"px").attr("height",Mh.rect_min_height+"px"),ORe=(i,a,f)=>{let p=Mh.rect_min_width/2,w=i.append("text").attr("class","req reqLabel reqTitle").attr("id",a).attr("x",p).attr("y",Mh.rect_padding).attr("dominant-baseline","hanging"),y=0;f.forEach(N=>{y==0?w.append("tspan").attr("text-anchor","middle").attr("x",Mh.rect_min_width/2).attr("dy",0).text(N):w.append("tspan").attr("text-anchor","middle").attr("x",Mh.rect_min_width/2).attr("dy",Mh.line_height*.75).text(N),y++});let b=1.5*Mh.rect_padding,E=y*Mh.line_height*.75,S=b+E;return i.append("line").attr("class","req-title-line").attr("x1","0").attr("x2",Mh.rect_min_width).attr("y1",S).attr("y2",S),{titleNode:w,y:S}},NRe=(i,a,f,p)=>{let w=i.append("text").attr("class","req reqLabel").attr("id",a).attr("x",Mh.rect_padding).attr("y",p).attr("dominant-baseline","hanging"),y=0;const b=30;let E=[];return f.forEach(S=>{let N=S.length;for(;N>b&&y<3;){let B=S.substring(0,b);S=S.substring(b,S.length),N=S.length,E[E.length]=B,y++}if(y==3){let B=E[E.length-1];E[E.length-1]=B.substring(0,B.length-4)+"..."}else E[E.length]=S;y=0}),E.forEach(S=>{w.append("tspan").attr("x",Mh.rect_padding).attr("dy",Mh.line_height).text(S)}),w},I$t=(i,a,f,p)=>{const w=a.node().getTotalLength(),y=a.node().getPointAtLength(w*.5),b="rel"+DRe;DRe++;const S=i.append("text").attr("class","req relationshipLabel").attr("id",b).attr("x",y.x).attr("y",y.y).attr("text-anchor","middle").attr("dominant-baseline","middle").text(p).node().getBBox();i.insert("rect","#"+b).attr("class","req reqLabelBox").attr("x",y.x-S.width/2).attr("y",y.y-S.height/2).attr("width",S.width).attr("height",S.height).attr("fill","white").attr("fill-opacity","85%")},O$t=function(i,a,f,p,w){const y=f.edge(oL(a.src),oL(a.dst)),b=WE().x(function(S){return S.x}).y(function(S){return S.y}),E=i.insert("path","#"+p).attr("class","er relationshipLine").attr("d",b(y.points)).attr("fill","none");a.type==w.db.Relationships.CONTAINS?E.attr("marker-start","url("+Wa.getUrl(Mh.arrowMarkerAbsolute)+"#"+a.type+"_line_ending)"):(E.attr("stroke-dasharray","10,7"),E.attr("marker-end","url("+Wa.getUrl(Mh.arrowMarkerAbsolute)+"#"+MRe.ReqMarkers.ARROW+"_line_ending)")),I$t(i,E,Mh,`<<${a.type}>>`)},N$t=(i,a,f)=>{Object.keys(i).forEach(p=>{let w=i[p];p=oL(p),Fe.info("Added new requirement: ",p);const y=f.append("g").attr("id",p),b="req-"+p,E=IRe(y,b);let S=ORe(y,p+"_title",[`<<${w.type}>>`,`${w.name}`]);NRe(y,p+"_body",[`Id: ${w.id}`,`Text: ${w.text}`,`Risk: ${w.risk}`,`Verification: ${w.verifyMethod}`],S.y);const N=E.node().getBBox();a.setNode(p,{width:N.width,height:N.height,shape:"rect",id:p})})},P$t=(i,a,f)=>{Object.keys(i).forEach(p=>{let w=i[p];const y=oL(p),b=f.append("g").attr("id",y),E="element-"+y,S=IRe(b,E);let N=ORe(b,E+"_title",["<>",`${p}`]);NRe(b,E+"_body",[`Type: ${w.type||"Not Specified"}`,`Doc Ref: ${w.docRef||"None"}`],N.y);const B=S.node().getBBox();a.setNode(y,{width:B.width,height:B.height,shape:"rect",id:y})})},B$t=(i,a)=>(i.forEach(function(f){let p=oL(f.src),w=oL(f.dst);a.setEdge(p,w,{relationship:f})}),i),R$t=function(i,a){a.nodes().forEach(function(f){f!==void 0&&a.node(f)!==void 0&&(i.select("#"+f),i.select("#"+f).attr("transform","translate("+(a.node(f).x-a.node(f).width/2)+","+(a.node(f).y-a.node(f).height/2)+" )"))})},oL=i=>i.replace(/\s/g,"").replace(/\./g,"_"),F$t=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:L$t,db:M$t,renderer:{draw:(i,a,f,p)=>{Mh=Tt().requirement,p.db.clear(),p.parser.parse(i);const w=Mh.securityLevel;let y;w==="sandbox"&&(y=Cr("#i"+a));const E=Cr(w==="sandbox"?y.nodes()[0].contentDocument.body:"body").select(`[id='${a}']`);MRe.insertLineEndings(E,Mh);const S=new zf({multigraph:!1,compound:!1,directed:!0}).setGraph({rankdir:Mh.layoutDirection,marginx:20,marginy:20,nodesep:100,edgesep:100,ranksep:100}).setDefaultEdgeLabel(function(){return{}});let N=p.db.getRequirements(),B=p.db.getElements(),R=p.db.getRelationships();N$t(N,S,E),P$t(B,S,E),B$t(R,S),tL(S),R$t(E,S),R.forEach(function(oe){O$t(E,oe,S,a,p)});const j=Mh.rect_padding,$=E.node().getBBox(),V=$.width+j*2,Q=$.height+j*2;Vw(E,Q,V,Mh.useMaxWidth),E.attr("viewBox",`${$.x-j} ${$.y-j} ${V} ${Q}`)}},styles:D$t}},Symbol.toStringTag,{value:"Module"}));var J0e=function(){var i=function(Dt,vt,Nt,ze){for(Nt=Nt||{},ze=Dt.length;ze--;Nt[Dt[ze]]=vt);return Nt},a=[1,2],f=[1,3],p=[1,5],w=[1,7],y=[2,5],b=[1,15],E=[1,17],S=[1,19],N=[1,21],B=[1,22],R=[1,23],j=[1,29],$=[1,30],V=[1,31],Q=[1,32],oe=[1,33],ce=[1,34],se=[1,35],ge=[1,36],ye=[1,37],ke=[1,38],Ae=[1,39],de=[1,40],ve=[1,42],te=[1,43],xe=[1,45],De=[1,46],he=[1,47],Ie=[1,48],ee=[1,49],rt=[1,50],me=[1,53],gt=[1,4,5,19,21,23,26,28,34,35,36,38,40,41,42,43,44,46,48,50,51,52,53,54,56,57,62,63,64,65,73,83],pe=[4,5,21,54,56],Et=[4,5,19,21,23,26,28,34,35,36,38,40,41,42,43,44,46,48,50,54,56,57,62,63,64,65,73,83],wt=[4,5,19,21,23,26,28,34,35,36,38,40,41,42,43,44,46,48,50,53,54,56,57,62,63,64,65,73,83],jt=[4,5,19,21,23,26,28,34,35,36,38,40,41,42,43,44,46,48,50,52,54,56,57,62,63,64,65,73,83],At=[4,5,19,21,23,26,28,34,35,36,38,40,41,42,43,44,46,48,50,51,54,56,57,62,63,64,65,73,83],Bt=[71,72,73],cn=[1,125],Nn=[1,4,5,7,19,21,23,26,28,34,35,36,38,40,41,42,43,44,46,48,50,51,52,53,54,56,57,62,63,64,65,73,83],Ot={trace:function(){},yy:{},symbols_:{error:2,start:3,SPACE:4,NEWLINE:5,directive:6,SD:7,document:8,line:9,statement:10,box_section:11,box_line:12,participant_statement:13,openDirective:14,typeDirective:15,closeDirective:16,":":17,argDirective:18,box:19,restOfLine:20,end:21,signal:22,autonumber:23,NUM:24,off:25,activate:26,actor:27,deactivate:28,note_statement:29,links_statement:30,link_statement:31,properties_statement:32,details_statement:33,title:34,legacy_title:35,acc_title:36,acc_title_value:37,acc_descr:38,acc_descr_value:39,acc_descr_multiline_value:40,loop:41,rect:42,opt:43,alt:44,else_sections:45,par:46,par_sections:47,critical:48,option_sections:49,break:50,option:51,and:52,else:53,participant:54,AS:55,participant_actor:56,note:57,placement:58,text2:59,over:60,actor_pair:61,links:62,link:63,properties:64,details:65,spaceList:66,",":67,left_of:68,right_of:69,signaltype:70,"+":71,"-":72,ACTOR:73,SOLID_OPEN_ARROW:74,DOTTED_OPEN_ARROW:75,SOLID_ARROW:76,DOTTED_ARROW:77,SOLID_CROSS:78,DOTTED_CROSS:79,SOLID_POINT:80,DOTTED_POINT:81,TXT:82,open_directive:83,type_directive:84,arg_directive:85,close_directive:86,$accept:0,$end:1},terminals_:{2:"error",4:"SPACE",5:"NEWLINE",7:"SD",17:":",19:"box",20:"restOfLine",21:"end",23:"autonumber",24:"NUM",25:"off",26:"activate",28:"deactivate",34:"title",35:"legacy_title",36:"acc_title",37:"acc_title_value",38:"acc_descr",39:"acc_descr_value",40:"acc_descr_multiline_value",41:"loop",42:"rect",43:"opt",44:"alt",46:"par",48:"critical",50:"break",51:"option",52:"and",53:"else",54:"participant",55:"AS",56:"participant_actor",57:"note",60:"over",62:"links",63:"link",64:"properties",65:"details",67:",",68:"left_of",69:"right_of",71:"+",72:"-",73:"ACTOR",74:"SOLID_OPEN_ARROW",75:"DOTTED_OPEN_ARROW",76:"SOLID_ARROW",77:"DOTTED_ARROW",78:"SOLID_CROSS",79:"DOTTED_CROSS",80:"SOLID_POINT",81:"DOTTED_POINT",82:"TXT",83:"open_directive",84:"type_directive",85:"arg_directive",86:"close_directive"},productions_:[0,[3,2],[3,2],[3,2],[3,2],[8,0],[8,2],[9,2],[9,1],[9,1],[11,0],[11,2],[12,2],[12,1],[12,1],[6,4],[6,6],[10,1],[10,4],[10,2],[10,4],[10,3],[10,3],[10,2],[10,3],[10,3],[10,2],[10,2],[10,2],[10,2],[10,2],[10,1],[10,1],[10,2],[10,2],[10,1],[10,4],[10,4],[10,4],[10,4],[10,4],[10,4],[10,4],[10,1],[49,1],[49,4],[47,1],[47,4],[45,1],[45,4],[13,5],[13,3],[13,5],[13,3],[29,4],[29,4],[30,3],[31,3],[32,3],[33,3],[66,2],[66,1],[61,3],[61,1],[58,1],[58,1],[22,5],[22,5],[22,4],[27,1],[70,1],[70,1],[70,1],[70,1],[70,1],[70,1],[70,1],[70,1],[59,1],[14,1],[15,1],[18,1],[16,1]],performAction:function(vt,Nt,ze,Xe,Lt,Ge,Bn){var Oe=Ge.length-1;switch(Lt){case 4:return Xe.apply(Ge[Oe]),Ge[Oe];case 5:case 10:this.$=[];break;case 6:case 11:Ge[Oe-1].push(Ge[Oe]),this.$=Ge[Oe-1];break;case 7:case 8:case 12:case 13:this.$=Ge[Oe];break;case 9:case 14:this.$=[];break;case 18:Ge[Oe-1].unshift({type:"boxStart",boxData:Xe.parseBoxData(Ge[Oe-2])}),Ge[Oe-1].push({type:"boxEnd",boxText:Ge[Oe-2]}),this.$=Ge[Oe-1];break;case 20:this.$={type:"sequenceIndex",sequenceIndex:Number(Ge[Oe-2]),sequenceIndexStep:Number(Ge[Oe-1]),sequenceVisible:!0,signalType:Xe.LINETYPE.AUTONUMBER};break;case 21:this.$={type:"sequenceIndex",sequenceIndex:Number(Ge[Oe-1]),sequenceIndexStep:1,sequenceVisible:!0,signalType:Xe.LINETYPE.AUTONUMBER};break;case 22:this.$={type:"sequenceIndex",sequenceVisible:!1,signalType:Xe.LINETYPE.AUTONUMBER};break;case 23:this.$={type:"sequenceIndex",sequenceVisible:!0,signalType:Xe.LINETYPE.AUTONUMBER};break;case 24:this.$={type:"activeStart",signalType:Xe.LINETYPE.ACTIVE_START,actor:Ge[Oe-1]};break;case 25:this.$={type:"activeEnd",signalType:Xe.LINETYPE.ACTIVE_END,actor:Ge[Oe-1]};break;case 31:Xe.setDiagramTitle(Ge[Oe].substring(6)),this.$=Ge[Oe].substring(6);break;case 32:Xe.setDiagramTitle(Ge[Oe].substring(7)),this.$=Ge[Oe].substring(7);break;case 33:this.$=Ge[Oe].trim(),Xe.setAccTitle(this.$);break;case 34:case 35:this.$=Ge[Oe].trim(),Xe.setAccDescription(this.$);break;case 36:Ge[Oe-1].unshift({type:"loopStart",loopText:Xe.parseMessage(Ge[Oe-2]),signalType:Xe.LINETYPE.LOOP_START}),Ge[Oe-1].push({type:"loopEnd",loopText:Ge[Oe-2],signalType:Xe.LINETYPE.LOOP_END}),this.$=Ge[Oe-1];break;case 37:Ge[Oe-1].unshift({type:"rectStart",color:Xe.parseMessage(Ge[Oe-2]),signalType:Xe.LINETYPE.RECT_START}),Ge[Oe-1].push({type:"rectEnd",color:Xe.parseMessage(Ge[Oe-2]),signalType:Xe.LINETYPE.RECT_END}),this.$=Ge[Oe-1];break;case 38:Ge[Oe-1].unshift({type:"optStart",optText:Xe.parseMessage(Ge[Oe-2]),signalType:Xe.LINETYPE.OPT_START}),Ge[Oe-1].push({type:"optEnd",optText:Xe.parseMessage(Ge[Oe-2]),signalType:Xe.LINETYPE.OPT_END}),this.$=Ge[Oe-1];break;case 39:Ge[Oe-1].unshift({type:"altStart",altText:Xe.parseMessage(Ge[Oe-2]),signalType:Xe.LINETYPE.ALT_START}),Ge[Oe-1].push({type:"altEnd",signalType:Xe.LINETYPE.ALT_END}),this.$=Ge[Oe-1];break;case 40:Ge[Oe-1].unshift({type:"parStart",parText:Xe.parseMessage(Ge[Oe-2]),signalType:Xe.LINETYPE.PAR_START}),Ge[Oe-1].push({type:"parEnd",signalType:Xe.LINETYPE.PAR_END}),this.$=Ge[Oe-1];break;case 41:Ge[Oe-1].unshift({type:"criticalStart",criticalText:Xe.parseMessage(Ge[Oe-2]),signalType:Xe.LINETYPE.CRITICAL_START}),Ge[Oe-1].push({type:"criticalEnd",signalType:Xe.LINETYPE.CRITICAL_END}),this.$=Ge[Oe-1];break;case 42:Ge[Oe-1].unshift({type:"breakStart",breakText:Xe.parseMessage(Ge[Oe-2]),signalType:Xe.LINETYPE.BREAK_START}),Ge[Oe-1].push({type:"breakEnd",optText:Xe.parseMessage(Ge[Oe-2]),signalType:Xe.LINETYPE.BREAK_END}),this.$=Ge[Oe-1];break;case 45:this.$=Ge[Oe-3].concat([{type:"option",optionText:Xe.parseMessage(Ge[Oe-1]),signalType:Xe.LINETYPE.CRITICAL_OPTION},Ge[Oe]]);break;case 47:this.$=Ge[Oe-3].concat([{type:"and",parText:Xe.parseMessage(Ge[Oe-1]),signalType:Xe.LINETYPE.PAR_AND},Ge[Oe]]);break;case 49:this.$=Ge[Oe-3].concat([{type:"else",altText:Xe.parseMessage(Ge[Oe-1]),signalType:Xe.LINETYPE.ALT_ELSE},Ge[Oe]]);break;case 50:Ge[Oe-3].type="addParticipant",Ge[Oe-3].description=Xe.parseMessage(Ge[Oe-1]),this.$=Ge[Oe-3];break;case 51:Ge[Oe-1].type="addParticipant",this.$=Ge[Oe-1];break;case 52:Ge[Oe-3].type="addActor",Ge[Oe-3].description=Xe.parseMessage(Ge[Oe-1]),this.$=Ge[Oe-3];break;case 53:Ge[Oe-1].type="addActor",this.$=Ge[Oe-1];break;case 54:this.$=[Ge[Oe-1],{type:"addNote",placement:Ge[Oe-2],actor:Ge[Oe-1].actor,text:Ge[Oe]}];break;case 55:Ge[Oe-2]=[].concat(Ge[Oe-1],Ge[Oe-1]).slice(0,2),Ge[Oe-2][0]=Ge[Oe-2][0].actor,Ge[Oe-2][1]=Ge[Oe-2][1].actor,this.$=[Ge[Oe-1],{type:"addNote",placement:Xe.PLACEMENT.OVER,actor:Ge[Oe-2].slice(0,2),text:Ge[Oe]}];break;case 56:this.$=[Ge[Oe-1],{type:"addLinks",actor:Ge[Oe-1].actor,text:Ge[Oe]}];break;case 57:this.$=[Ge[Oe-1],{type:"addALink",actor:Ge[Oe-1].actor,text:Ge[Oe]}];break;case 58:this.$=[Ge[Oe-1],{type:"addProperties",actor:Ge[Oe-1].actor,text:Ge[Oe]}];break;case 59:this.$=[Ge[Oe-1],{type:"addDetails",actor:Ge[Oe-1].actor,text:Ge[Oe]}];break;case 62:this.$=[Ge[Oe-2],Ge[Oe]];break;case 63:this.$=Ge[Oe];break;case 64:this.$=Xe.PLACEMENT.LEFTOF;break;case 65:this.$=Xe.PLACEMENT.RIGHTOF;break;case 66:this.$=[Ge[Oe-4],Ge[Oe-1],{type:"addMessage",from:Ge[Oe-4].actor,to:Ge[Oe-1].actor,signalType:Ge[Oe-3],msg:Ge[Oe]},{type:"activeStart",signalType:Xe.LINETYPE.ACTIVE_START,actor:Ge[Oe-1]}];break;case 67:this.$=[Ge[Oe-4],Ge[Oe-1],{type:"addMessage",from:Ge[Oe-4].actor,to:Ge[Oe-1].actor,signalType:Ge[Oe-3],msg:Ge[Oe]},{type:"activeEnd",signalType:Xe.LINETYPE.ACTIVE_END,actor:Ge[Oe-4]}];break;case 68:this.$=[Ge[Oe-3],Ge[Oe-1],{type:"addMessage",from:Ge[Oe-3].actor,to:Ge[Oe-1].actor,signalType:Ge[Oe-2],msg:Ge[Oe]}];break;case 69:this.$={type:"addParticipant",actor:Ge[Oe]};break;case 70:this.$=Xe.LINETYPE.SOLID_OPEN;break;case 71:this.$=Xe.LINETYPE.DOTTED_OPEN;break;case 72:this.$=Xe.LINETYPE.SOLID;break;case 73:this.$=Xe.LINETYPE.DOTTED;break;case 74:this.$=Xe.LINETYPE.SOLID_CROSS;break;case 75:this.$=Xe.LINETYPE.DOTTED_CROSS;break;case 76:this.$=Xe.LINETYPE.SOLID_POINT;break;case 77:this.$=Xe.LINETYPE.DOTTED_POINT;break;case 78:this.$=Xe.parseMessage(Ge[Oe].trim().substring(1));break;case 79:Xe.parseDirective("%%{","open_directive");break;case 80:Xe.parseDirective(Ge[Oe],"type_directive");break;case 81:Ge[Oe]=Ge[Oe].trim().replace(/'/g,'"'),Xe.parseDirective(Ge[Oe],"arg_directive");break;case 82:Xe.parseDirective("}%%","close_directive","sequence");break}},table:[{3:1,4:a,5:f,6:4,7:p,14:6,83:w},{1:[3]},{3:8,4:a,5:f,6:4,7:p,14:6,83:w},{3:9,4:a,5:f,6:4,7:p,14:6,83:w},{3:10,4:a,5:f,6:4,7:p,14:6,83:w},i([1,4,5,19,23,26,28,34,35,36,38,40,41,42,43,44,46,48,50,54,56,57,62,63,64,65,73,83],y,{8:11}),{15:12,84:[1,13]},{84:[2,79]},{1:[2,1]},{1:[2,2]},{1:[2,3]},{1:[2,4],4:b,5:E,6:41,9:14,10:16,13:18,14:6,19:S,22:20,23:N,26:B,27:44,28:R,29:24,30:25,31:26,32:27,33:28,34:j,35:$,36:V,38:Q,40:oe,41:ce,42:se,43:ge,44:ye,46:ke,48:Ae,50:de,54:ve,56:te,57:xe,62:De,63:he,64:Ie,65:ee,73:rt,83:w},{16:51,17:[1,52],86:me},i([17,86],[2,80]),i(gt,[2,6]),{6:41,10:54,13:18,14:6,19:S,22:20,23:N,26:B,27:44,28:R,29:24,30:25,31:26,32:27,33:28,34:j,35:$,36:V,38:Q,40:oe,41:ce,42:se,43:ge,44:ye,46:ke,48:Ae,50:de,54:ve,56:te,57:xe,62:De,63:he,64:Ie,65:ee,73:rt,83:w},i(gt,[2,8]),i(gt,[2,9]),i(gt,[2,17]),{20:[1,55]},{5:[1,56]},{5:[1,59],24:[1,57],25:[1,58]},{27:60,73:rt},{27:61,73:rt},{5:[1,62]},{5:[1,63]},{5:[1,64]},{5:[1,65]},{5:[1,66]},i(gt,[2,31]),i(gt,[2,32]),{37:[1,67]},{39:[1,68]},i(gt,[2,35]),{20:[1,69]},{20:[1,70]},{20:[1,71]},{20:[1,72]},{20:[1,73]},{20:[1,74]},{20:[1,75]},i(gt,[2,43]),{27:76,73:rt},{27:77,73:rt},{70:78,74:[1,79],75:[1,80],76:[1,81],77:[1,82],78:[1,83],79:[1,84],80:[1,85],81:[1,86]},{58:87,60:[1,88],68:[1,89],69:[1,90]},{27:91,73:rt},{27:92,73:rt},{27:93,73:rt},{27:94,73:rt},i([5,55,67,74,75,76,77,78,79,80,81,82],[2,69]),{5:[1,95]},{18:96,85:[1,97]},{5:[2,82]},i(gt,[2,7]),i(pe,[2,10],{11:98}),i(gt,[2,19]),{5:[1,100],24:[1,99]},{5:[1,101]},i(gt,[2,23]),{5:[1,102]},{5:[1,103]},i(gt,[2,26]),i(gt,[2,27]),i(gt,[2,28]),i(gt,[2,29]),i(gt,[2,30]),i(gt,[2,33]),i(gt,[2,34]),i(Et,y,{8:104}),i(Et,y,{8:105}),i(Et,y,{8:106}),i(wt,y,{45:107,8:108}),i(jt,y,{47:109,8:110}),i(At,y,{49:111,8:112}),i(Et,y,{8:113}),{5:[1,115],55:[1,114]},{5:[1,117],55:[1,116]},{27:120,71:[1,118],72:[1,119],73:rt},i(Bt,[2,70]),i(Bt,[2,71]),i(Bt,[2,72]),i(Bt,[2,73]),i(Bt,[2,74]),i(Bt,[2,75]),i(Bt,[2,76]),i(Bt,[2,77]),{27:121,73:rt},{27:123,61:122,73:rt},{73:[2,64]},{73:[2,65]},{59:124,82:cn},{59:126,82:cn},{59:127,82:cn},{59:128,82:cn},i(Nn,[2,15]),{16:129,86:me},{86:[2,81]},{4:[1,132],5:[1,134],12:131,13:133,21:[1,130],54:ve,56:te},{5:[1,135]},i(gt,[2,21]),i(gt,[2,22]),i(gt,[2,24]),i(gt,[2,25]),{4:b,5:E,6:41,9:14,10:16,13:18,14:6,19:S,21:[1,136],22:20,23:N,26:B,27:44,28:R,29:24,30:25,31:26,32:27,33:28,34:j,35:$,36:V,38:Q,40:oe,41:ce,42:se,43:ge,44:ye,46:ke,48:Ae,50:de,54:ve,56:te,57:xe,62:De,63:he,64:Ie,65:ee,73:rt,83:w},{4:b,5:E,6:41,9:14,10:16,13:18,14:6,19:S,21:[1,137],22:20,23:N,26:B,27:44,28:R,29:24,30:25,31:26,32:27,33:28,34:j,35:$,36:V,38:Q,40:oe,41:ce,42:se,43:ge,44:ye,46:ke,48:Ae,50:de,54:ve,56:te,57:xe,62:De,63:he,64:Ie,65:ee,73:rt,83:w},{4:b,5:E,6:41,9:14,10:16,13:18,14:6,19:S,21:[1,138],22:20,23:N,26:B,27:44,28:R,29:24,30:25,31:26,32:27,33:28,34:j,35:$,36:V,38:Q,40:oe,41:ce,42:se,43:ge,44:ye,46:ke,48:Ae,50:de,54:ve,56:te,57:xe,62:De,63:he,64:Ie,65:ee,73:rt,83:w},{21:[1,139]},{4:b,5:E,6:41,9:14,10:16,13:18,14:6,19:S,21:[2,48],22:20,23:N,26:B,27:44,28:R,29:24,30:25,31:26,32:27,33:28,34:j,35:$,36:V,38:Q,40:oe,41:ce,42:se,43:ge,44:ye,46:ke,48:Ae,50:de,53:[1,140],54:ve,56:te,57:xe,62:De,63:he,64:Ie,65:ee,73:rt,83:w},{21:[1,141]},{4:b,5:E,6:41,9:14,10:16,13:18,14:6,19:S,21:[2,46],22:20,23:N,26:B,27:44,28:R,29:24,30:25,31:26,32:27,33:28,34:j,35:$,36:V,38:Q,40:oe,41:ce,42:se,43:ge,44:ye,46:ke,48:Ae,50:de,52:[1,142],54:ve,56:te,57:xe,62:De,63:he,64:Ie,65:ee,73:rt,83:w},{21:[1,143]},{4:b,5:E,6:41,9:14,10:16,13:18,14:6,19:S,21:[2,44],22:20,23:N,26:B,27:44,28:R,29:24,30:25,31:26,32:27,33:28,34:j,35:$,36:V,38:Q,40:oe,41:ce,42:se,43:ge,44:ye,46:ke,48:Ae,50:de,51:[1,144],54:ve,56:te,57:xe,62:De,63:he,64:Ie,65:ee,73:rt,83:w},{4:b,5:E,6:41,9:14,10:16,13:18,14:6,19:S,21:[1,145],22:20,23:N,26:B,27:44,28:R,29:24,30:25,31:26,32:27,33:28,34:j,35:$,36:V,38:Q,40:oe,41:ce,42:se,43:ge,44:ye,46:ke,48:Ae,50:de,54:ve,56:te,57:xe,62:De,63:he,64:Ie,65:ee,73:rt,83:w},{20:[1,146]},i(gt,[2,51]),{20:[1,147]},i(gt,[2,53]),{27:148,73:rt},{27:149,73:rt},{59:150,82:cn},{59:151,82:cn},{59:152,82:cn},{67:[1,153],82:[2,63]},{5:[2,56]},{5:[2,78]},{5:[2,57]},{5:[2,58]},{5:[2,59]},{5:[1,154]},i(gt,[2,18]),i(pe,[2,11]),{13:155,54:ve,56:te},i(pe,[2,13]),i(pe,[2,14]),i(gt,[2,20]),i(gt,[2,36]),i(gt,[2,37]),i(gt,[2,38]),i(gt,[2,39]),{20:[1,156]},i(gt,[2,40]),{20:[1,157]},i(gt,[2,41]),{20:[1,158]},i(gt,[2,42]),{5:[1,159]},{5:[1,160]},{59:161,82:cn},{59:162,82:cn},{5:[2,68]},{5:[2,54]},{5:[2,55]},{27:163,73:rt},i(Nn,[2,16]),i(pe,[2,12]),i(wt,y,{8:108,45:164}),i(jt,y,{8:110,47:165}),i(At,y,{8:112,49:166}),i(gt,[2,50]),i(gt,[2,52]),{5:[2,66]},{5:[2,67]},{82:[2,62]},{21:[2,49]},{21:[2,47]},{21:[2,45]}],defaultActions:{7:[2,79],8:[2,1],9:[2,2],10:[2,3],53:[2,82],89:[2,64],90:[2,65],97:[2,81],124:[2,56],125:[2,78],126:[2,57],127:[2,58],128:[2,59],150:[2,68],151:[2,54],152:[2,55],161:[2,66],162:[2,67],163:[2,62],164:[2,49],165:[2,47],166:[2,45]},parseError:function(vt,Nt){if(Nt.recoverable)this.trace(vt);else{var ze=new Error(vt);throw ze.hash=Nt,ze}},parse:function(vt){var Nt=this,ze=[0],Xe=[],Lt=[null],Ge=[],Bn=this.table,Oe="",Ri=0,tn=0,hi=2,Sr=1,Zn=Ge.slice.call(arguments,1),Xn=Object.create(this.lexer),ir={yy:{}};for(var Hn in this.yy)Object.prototype.hasOwnProperty.call(this.yy,Hn)&&(ir.yy[Hn]=this.yy[Hn]);Xn.setInput(vt,ir.yy),ir.yy.lexer=Xn,ir.yy.parser=this,typeof Xn.yylloc>"u"&&(Xn.yylloc={});var tr=Xn.yylloc;Ge.push(tr);var ha=Xn.options&&Xn.options.ranges;typeof ir.yy.parseError=="function"?this.parseError=ir.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Zs(){var Vn;return Vn=Xe.pop()||Xn.lex()||Sr,typeof Vn!="number"&&(Vn instanceof Array&&(Xe=Vn,Vn=Xe.pop()),Vn=Nt.symbols_[Vn]||Vn),Vn}for(var ns,Hi,Js,Pc,Ga={},ws,Oi,Er,br;;){if(Hi=ze[ze.length-1],this.defaultActions[Hi]?Js=this.defaultActions[Hi]:((ns===null||typeof ns>"u")&&(ns=Zs()),Js=Bn[Hi]&&Bn[Hi][ns]),typeof Js>"u"||!Js.length||!Js[0]){var Dr="";br=[];for(ws in Bn[Hi])this.terminals_[ws]&&ws>hi&&br.push("'"+this.terminals_[ws]+"'");Xn.showPosition?Dr="Parse error on line "+(Ri+1)+`: +`+Xn.showPosition()+` +Expecting `+br.join(", ")+", got '"+(this.terminals_[ns]||ns)+"'":Dr="Parse error on line "+(Ri+1)+": Unexpected "+(ns==Sr?"end of input":"'"+(this.terminals_[ns]||ns)+"'"),this.parseError(Dr,{text:Xn.match,token:this.terminals_[ns]||ns,line:Xn.yylineno,loc:tr,expected:br})}if(Js[0]instanceof Array&&Js.length>1)throw new Error("Parse Error: multiple actions possible at state: "+Hi+", token: "+ns);switch(Js[0]){case 1:ze.push(ns),Lt.push(Xn.yytext),Ge.push(Xn.yylloc),ze.push(Js[1]),ns=null,tn=Xn.yyleng,Oe=Xn.yytext,Ri=Xn.yylineno,tr=Xn.yylloc;break;case 2:if(Oi=this.productions_[Js[1]][1],Ga.$=Lt[Lt.length-Oi],Ga._$={first_line:Ge[Ge.length-(Oi||1)].first_line,last_line:Ge[Ge.length-1].last_line,first_column:Ge[Ge.length-(Oi||1)].first_column,last_column:Ge[Ge.length-1].last_column},ha&&(Ga._$.range=[Ge[Ge.length-(Oi||1)].range[0],Ge[Ge.length-1].range[1]]),Pc=this.performAction.apply(Ga,[Oe,tn,Ri,ir.yy,Js[1],Lt,Ge].concat(Zn)),typeof Pc<"u")return Pc;Oi&&(ze=ze.slice(0,-1*Oi*2),Lt=Lt.slice(0,-1*Oi),Ge=Ge.slice(0,-1*Oi)),ze.push(this.productions_[Js[1]][0]),Lt.push(Ga.$),Ge.push(Ga._$),Er=Bn[ze[ze.length-2]][ze[ze.length-1]],ze.push(Er);break;case 3:return!0}}return!0}},oi=function(){var Dt={EOF:1,parseError:function(Nt,ze){if(this.yy.parser)this.yy.parser.parseError(Nt,ze);else throw new Error(Nt)},setInput:function(vt,Nt){return this.yy=Nt||this.yy||{},this._input=vt,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var vt=this._input[0];this.yytext+=vt,this.yyleng++,this.offset++,this.match+=vt,this.matched+=vt;var Nt=vt.match(/(?:\r\n?|\n).*/g);return Nt?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),vt},unput:function(vt){var Nt=vt.length,ze=vt.split(/(?:\r\n?|\n)/g);this._input=vt+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-Nt),this.offset-=Nt;var Xe=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),ze.length-1&&(this.yylineno-=ze.length-1);var Lt=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:ze?(ze.length===Xe.length?this.yylloc.first_column:0)+Xe[Xe.length-ze.length].length-ze[0].length:this.yylloc.first_column-Nt},this.options.ranges&&(this.yylloc.range=[Lt[0],Lt[0]+this.yyleng-Nt]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(vt){this.unput(this.match.slice(vt))},pastInput:function(){var vt=this.matched.substr(0,this.matched.length-this.match.length);return(vt.length>20?"...":"")+vt.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var vt=this.match;return vt.length<20&&(vt+=this._input.substr(0,20-vt.length)),(vt.substr(0,20)+(vt.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var vt=this.pastInput(),Nt=new Array(vt.length+1).join("-");return vt+this.upcomingInput()+` +`+Nt+"^"},test_match:function(vt,Nt){var ze,Xe,Lt;if(this.options.backtrack_lexer&&(Lt={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(Lt.yylloc.range=this.yylloc.range.slice(0))),Xe=vt[0].match(/(?:\r\n?|\n).*/g),Xe&&(this.yylineno+=Xe.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:Xe?Xe[Xe.length-1].length-Xe[Xe.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+vt[0].length},this.yytext+=vt[0],this.match+=vt[0],this.matches=vt,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(vt[0].length),this.matched+=vt[0],ze=this.performAction.call(this,this.yy,this,Nt,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),ze)return ze;if(this._backtrack){for(var Ge in Lt)this[Ge]=Lt[Ge];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var vt,Nt,ze,Xe;this._more||(this.yytext="",this.match="");for(var Lt=this._currentRules(),Ge=0;GeNt[0].length)){if(Nt=ze,Xe=Ge,this.options.backtrack_lexer){if(vt=this.test_match(ze,Lt[Ge]),vt!==!1)return vt;if(this._backtrack){Nt=!1;continue}else return!1}else if(!this.options.flex)break}return Nt?(vt=this.test_match(Nt,Lt[Xe]),vt!==!1?vt:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var Nt=this.next();return Nt||this.lex()},begin:function(Nt){this.conditionStack.push(Nt)},popState:function(){var Nt=this.conditionStack.length-1;return Nt>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(Nt){return Nt=this.conditionStack.length-1-Math.abs(Nt||0),Nt>=0?this.conditionStack[Nt]:"INITIAL"},pushState:function(Nt){this.begin(Nt)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(Nt,ze,Xe,Lt){switch(Xe){case 0:return this.begin("open_directive"),83;case 1:return this.begin("type_directive"),84;case 2:return this.popState(),this.begin("arg_directive"),17;case 3:return this.popState(),this.popState(),86;case 4:return 85;case 5:return 5;case 6:break;case 7:break;case 8:break;case 9:break;case 10:break;case 11:return 24;case 12:return this.begin("LINE"),19;case 13:return this.begin("ID"),54;case 14:return this.begin("ID"),56;case 15:return ze.yytext=ze.yytext.trim(),this.begin("ALIAS"),73;case 16:return this.popState(),this.popState(),this.begin("LINE"),55;case 17:return this.popState(),this.popState(),5;case 18:return this.begin("LINE"),41;case 19:return this.begin("LINE"),42;case 20:return this.begin("LINE"),43;case 21:return this.begin("LINE"),44;case 22:return this.begin("LINE"),53;case 23:return this.begin("LINE"),46;case 24:return this.begin("LINE"),52;case 25:return this.begin("LINE"),48;case 26:return this.begin("LINE"),51;case 27:return this.begin("LINE"),50;case 28:return this.popState(),20;case 29:return 21;case 30:return 68;case 31:return 69;case 32:return 62;case 33:return 63;case 34:return 64;case 35:return 65;case 36:return 60;case 37:return 57;case 38:return this.begin("ID"),26;case 39:return this.begin("ID"),28;case 40:return 34;case 41:return 35;case 42:return this.begin("acc_title"),36;case 43:return this.popState(),"acc_title_value";case 44:return this.begin("acc_descr"),38;case 45:return this.popState(),"acc_descr_value";case 46:this.begin("acc_descr_multiline");break;case 47:this.popState();break;case 48:return"acc_descr_multiline_value";case 49:return 7;case 50:return 23;case 51:return 25;case 52:return 67;case 53:return 5;case 54:return ze.yytext=ze.yytext.trim(),73;case 55:return 76;case 56:return 77;case 57:return 74;case 58:return 75;case 59:return 78;case 60:return 79;case 61:return 80;case 62:return 81;case 63:return 82;case 64:return 71;case 65:return 72;case 66:return 5;case 67:return"INVALID"}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:((?!\n)\s)+)/i,/^(?:#[^\n]*)/i,/^(?:%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[0-9]+(?=[ \n]+))/i,/^(?:box\b)/i,/^(?:participant\b)/i,/^(?:actor\b)/i,/^(?:[^\->:\n,;]+?([\-]*[^\->:\n,;]+?)*?(?=((?!\n)\s)+as(?!\n)\s|[#\n;]|$))/i,/^(?:as\b)/i,/^(?:(?:))/i,/^(?:loop\b)/i,/^(?:rect\b)/i,/^(?:opt\b)/i,/^(?:alt\b)/i,/^(?:else\b)/i,/^(?:par\b)/i,/^(?:and\b)/i,/^(?:critical\b)/i,/^(?:option\b)/i,/^(?:break\b)/i,/^(?:(?:[:]?(?:no)?wrap)?[^#\n;]*)/i,/^(?:end\b)/i,/^(?:left of\b)/i,/^(?:right of\b)/i,/^(?:links\b)/i,/^(?:link\b)/i,/^(?:properties\b)/i,/^(?:details\b)/i,/^(?:over\b)/i,/^(?:note\b)/i,/^(?:activate\b)/i,/^(?:deactivate\b)/i,/^(?:title\s[^#\n;]+)/i,/^(?:title:\s[^#\n;]+)/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:sequenceDiagram\b)/i,/^(?:autonumber\b)/i,/^(?:off\b)/i,/^(?:,)/i,/^(?:;)/i,/^(?:[^\+\->:\n,;]+((?!(-x|--x|-\)|--\)))[\-]*[^\+\->:\n,;]+)*)/i,/^(?:->>)/i,/^(?:-->>)/i,/^(?:->)/i,/^(?:-->)/i,/^(?:-[x])/i,/^(?:--[x])/i,/^(?:-[\)])/i,/^(?:--[\)])/i,/^(?::(?:(?:no)?wrap)?[^#\n;]+)/i,/^(?:\+)/i,/^(?:-)/i,/^(?:$)/i,/^(?:.)/i],conditions:{acc_descr_multiline:{rules:[47,48],inclusive:!1},acc_descr:{rules:[45],inclusive:!1},acc_title:{rules:[43],inclusive:!1},open_directive:{rules:[1,8],inclusive:!1},type_directive:{rules:[2,3,8],inclusive:!1},arg_directive:{rules:[3,4,8],inclusive:!1},ID:{rules:[7,8,15],inclusive:!1},ALIAS:{rules:[7,8,16,17],inclusive:!1},LINE:{rules:[7,8,28],inclusive:!1},INITIAL:{rules:[0,5,6,8,9,10,11,12,13,14,18,19,20,21,22,23,24,25,26,27,29,30,31,32,33,34,35,36,37,38,39,40,41,42,44,46,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67],inclusive:!0}}};return Dt}();Ot.lexer=oi;function kt(){this.yy={}}return kt.prototype=Ot,Ot.Parser=kt,new kt}();J0e.parser=J0e;const j$t=J0e;let LP,cx={},cL=[],rm=[],LK=!1,ege,L5;const $$t=function(i,a,f){rd.parseDirective(this,i,a,f)},H$t=function(i){cL.push({name:i.text,wrap:i.wrap===void 0&&d9()||!!i.wrap,fill:i.color,actorKeys:[]}),L5=cL.slice(-1)[0]},tge=function(i,a,f,p){let w=L5;const y=cx[i];if(y){if(L5&&y.box&&L5!==y.box)throw new Error("A same participant should only be defined in one Box: "+y.name+" can't be in '"+y.box.name+"' and in '"+L5.name+"' at the same time.");if(w=y.box?y.box:L5,y.box=w,y&&a===y.name&&f==null)return}(f==null||f.text==null)&&(f={text:a,wrap:null,type:p}),(p==null||f.text==null)&&(f={text:a,wrap:null,type:p}),cx[i]={box:w,name:a,description:f.text,wrap:f.wrap===void 0&&d9()||!!f.wrap,prevActor:LP,links:{},properties:{},actorCnt:null,rectData:null,type:p||"participant"},LP&&cx[LP]&&(cx[LP].nextActor=i),L5&&L5.actorKeys.push(i),LP=i},z$t=i=>{let a,f=0;for(a=0;a>-",token:"->>-",line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["'ACTIVE_PARTICIPANT'"]},y}return rm.push({from:i,to:a,message:f.text,wrap:f.wrap===void 0&&d9()||!!f.wrap,type:p}),!0},q$t=function(){return cL.length>0},V$t=function(){return cL.some(i=>i.name)},U$t=function(){return rm},W$t=function(){return cL},K$t=function(){return cx},MP=function(i){return cx[i]},Y$t=function(){return Object.keys(cx)},X$t=function(){LK=!0},Q$t=function(){LK=!1},Z$t=()=>LK,J$t=function(i){ege=i},d9=()=>ege!==void 0?ege:Tt().sequence.wrap,eHt=function(){cx={},cL=[],rm=[],LK=!1,rp()},tHt=function(i){const a=i.trim(),f={text:a.replace(/^:?(?:no)?wrap:/,"").trim(),wrap:a.match(/^:?wrap:/)!==null?!0:a.match(/^:?nowrap:/)!==null?!1:void 0};return Fe.debug("parseMessage:",f),f},nHt=function(i){const a=i.match(/^((?:rgba?|hsla?)\s*\(.*\)|\w*)(.*)$/);let f=a!=null&&a[1]?a[1].trim():"transparent",p=a!=null&&a[2]?a[2].trim():void 0;if(window&&window.CSS)window.CSS.supports("color",f)||(f="transparent",p=i.trim());else{const y=new Option().style;y.color=f,y.color!==f&&(f="transparent",p=i.trim())}return{color:f,text:p!==void 0?ep(p.replace(/^:?(?:no)?wrap:/,""),Tt()):void 0,wrap:p!==void 0?p.match(/^:?wrap:/)!==null?!0:p.match(/^:?nowrap:/)!==null?!1:void 0:void 0}},DP={SOLID:0,DOTTED:1,NOTE:2,SOLID_CROSS:3,DOTTED_CROSS:4,SOLID_OPEN:5,DOTTED_OPEN:6,LOOP_START:10,LOOP_END:11,ALT_START:12,ALT_ELSE:13,ALT_END:14,OPT_START:15,OPT_END:16,ACTIVE_START:17,ACTIVE_END:18,PAR_START:19,PAR_AND:20,PAR_END:21,RECT_START:22,RECT_END:23,SOLID_POINT:24,DOTTED_POINT:25,AUTONUMBER:26,CRITICAL_START:27,CRITICAL_OPTION:28,CRITICAL_END:29,BREAK_START:30,BREAK_END:31},rHt={FILLED:0,OPEN:1},iHt={LEFTOF:0,RIGHTOF:1,OVER:2},PRe=function(i,a,f){f.text,f.wrap===void 0&&d9()||f.wrap;const p=[].concat(i,i);rm.push({from:p[0],to:p[1],message:f.text,wrap:f.wrap===void 0&&d9()||!!f.wrap,type:DP.NOTE,placement:a})},BRe=function(i,a){const f=MP(i);try{let p=ep(a.text,Tt());p=p.replace(/&/g,"&"),p=p.replace(/=/g,"=");const w=JSON.parse(p);nge(f,w)}catch(p){Fe.error("error while parsing actor link text",p)}},sHt=function(i,a){const f=MP(i);try{const b={};let E=ep(a.text,Tt());var p=E.indexOf("@");E=E.replace(/&/g,"&"),E=E.replace(/=/g,"=");var w=E.slice(0,p-1).trim(),y=E.slice(p+1).trim();b[w]=y,nge(f,b)}catch(b){Fe.error("error while parsing actor link text",b)}};function nge(i,a){if(i.links==null)i.links=a;else for(let f in a)i.links[f]=a[f]}const RRe=function(i,a){const f=MP(i);try{let p=ep(a.text,Tt());const w=JSON.parse(p);FRe(f,w)}catch(p){Fe.error("error while parsing actor properties text",p)}};function FRe(i,a){if(i.properties==null)i.properties=a;else for(let f in a)i.properties[f]=a[f]}function aHt(){L5=void 0}const jRe=function(i,a){const f=MP(i),p=document.getElementById(a.text);try{const w=p.innerHTML,y=JSON.parse(w);y.properties&&FRe(f,y.properties),y.links&&nge(f,y.links)}catch(w){Fe.error("error while parsing actor details text",w)}},oHt=function(i,a){if(i!==void 0&&i.properties!==void 0)return i.properties[a]},$Re=function(i){if(Array.isArray(i))i.forEach(function(a){$Re(a)});else switch(i.type){case"sequenceIndex":rm.push({from:void 0,to:void 0,message:{start:i.sequenceIndex,step:i.sequenceIndexStep,visible:i.sequenceVisible},wrap:!1,type:i.signalType});break;case"addParticipant":tge(i.actor,i.actor,i.description,"participant");break;case"addActor":tge(i.actor,i.actor,i.description,"actor");break;case"activeStart":lf(i.actor,void 0,void 0,i.signalType);break;case"activeEnd":lf(i.actor,void 0,void 0,i.signalType);break;case"addNote":PRe(i.actor,i.placement,i.text);break;case"addLinks":BRe(i.actor,i.text);break;case"addALink":sHt(i.actor,i.text);break;case"addProperties":RRe(i.actor,i.text);break;case"addDetails":jRe(i.actor,i.text);break;case"addMessage":lf(i.from,i.to,i.msg,i.signalType);break;case"boxStart":H$t(i.boxData);break;case"boxEnd":aHt();break;case"loopStart":lf(void 0,void 0,i.loopText,i.signalType);break;case"loopEnd":lf(void 0,void 0,void 0,i.signalType);break;case"rectStart":lf(void 0,void 0,i.color,i.signalType);break;case"rectEnd":lf(void 0,void 0,void 0,i.signalType);break;case"optStart":lf(void 0,void 0,i.optText,i.signalType);break;case"optEnd":lf(void 0,void 0,void 0,i.signalType);break;case"altStart":lf(void 0,void 0,i.altText,i.signalType);break;case"else":lf(void 0,void 0,i.altText,i.signalType);break;case"altEnd":lf(void 0,void 0,void 0,i.signalType);break;case"setAccTitle":ip(i.text);break;case"parStart":lf(void 0,void 0,i.parText,i.signalType);break;case"and":lf(void 0,void 0,i.parText,i.signalType);break;case"parEnd":lf(void 0,void 0,void 0,i.signalType);break;case"criticalStart":lf(void 0,void 0,i.criticalText,i.signalType);break;case"option":lf(void 0,void 0,i.optionText,i.signalType);break;case"criticalEnd":lf(void 0,void 0,void 0,i.signalType);break;case"breakStart":lf(void 0,void 0,i.breakText,i.signalType);break;case"breakEnd":lf(void 0,void 0,void 0,i.signalType);break}},cHt={addActor:tge,addMessage:G$t,addSignal:lf,addLinks:BRe,addDetails:jRe,addProperties:RRe,autoWrap:d9,setWrap:J$t,enableSequenceNumbers:X$t,disableSequenceNumbers:Q$t,showSequenceNumbers:Z$t,getMessages:U$t,getActors:K$t,getActor:MP,getActorKeys:Y$t,getActorProperty:oHt,getAccTitle:L2,getBoxes:W$t,getDiagramTitle:Ww,setDiagramTitle:Uw,parseDirective:$$t,getConfig:()=>Tt().sequence,clear:eHt,parseMessage:tHt,parseBoxData:nHt,LINETYPE:DP,ARROWTYPE:rHt,PLACEMENT:iHt,addNote:PRe,setAccTitle:ip,apply:$Re,setAccDescription:M2,getAccDescription:D2,hasAtLeastOneBox:q$t,hasAtLeastOneBoxWithTitle:V$t},uHt=i=>`.actor { + stroke: ${i.actorBorder}; + fill: ${i.actorBkg}; + } + + text.actor > tspan { + fill: ${i.actorTextColor}; + stroke: none; + } + + .actor-line { + stroke: ${i.actorLineColor}; + } + + .messageLine0 { + stroke-width: 1.5; + stroke-dasharray: none; + stroke: ${i.signalColor}; + } + + .messageLine1 { + stroke-width: 1.5; + stroke-dasharray: 2, 2; + stroke: ${i.signalColor}; + } + + #arrowhead path { + fill: ${i.signalColor}; + stroke: ${i.signalColor}; + } + + .sequenceNumber { + fill: ${i.sequenceNumberColor}; + } + + #sequencenumber { + fill: ${i.signalColor}; + } + + #crosshead path { + fill: ${i.signalColor}; + stroke: ${i.signalColor}; + } + + .messageText { + fill: ${i.signalTextColor}; + stroke: none; + } + + .labelBox { + stroke: ${i.labelBoxBorderColor}; + fill: ${i.labelBoxBkgColor}; + } + + .labelText, .labelText > tspan { + fill: ${i.labelTextColor}; + stroke: none; + } + + .loopText, .loopText > tspan { + fill: ${i.loopTextColor}; + stroke: none; + } + + .loopLine { + stroke-width: 2px; + stroke-dasharray: 2, 2; + stroke: ${i.labelBoxBorderColor}; + fill: ${i.labelBoxBorderColor}; + } + + .note { + //stroke: #decc93; + stroke: ${i.noteBorderColor}; + fill: ${i.noteBkgColor}; + } + + .noteText, .noteText > tspan { + fill: ${i.noteTextColor}; + stroke: none; + } + + .activation0 { + fill: ${i.activationBkgColor}; + stroke: ${i.activationBorderColor}; + } + + .activation1 { + fill: ${i.activationBkgColor}; + stroke: ${i.activationBorderColor}; + } + + .activation2 { + fill: ${i.activationBkgColor}; + stroke: ${i.activationBorderColor}; + } + + .actorPopupMenu { + position: absolute; + } + + .actorPopupMenuPanel { + position: absolute; + fill: ${i.actorBkg}; + box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); + filter: drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4)); +} + .actor-man line { + stroke: ${i.actorBorder}; + fill: ${i.actorBkg}; + } + .actor-man circle, line { + stroke: ${i.actorBorder}; + fill: ${i.actorBkg}; + stroke-width: 2px; + } +`,MK=function(i,a){const f=i.append("rect");return f.attr("x",a.x),f.attr("y",a.y),f.attr("fill",a.fill),f.attr("stroke",a.stroke),f.attr("width",a.width),f.attr("height",a.height),f.attr("rx",a.rx),f.attr("ry",a.ry),a.class!==void 0&&f.attr("class",a.class),f},HRe=(i,a)=>{ISt(()=>{const f=document.querySelectorAll(i);f.length!==0&&(f[0].addEventListener("mouseover",function(){dHt("actor"+a+"_popup")}),f[0].addEventListener("mouseout",function(){gHt("actor"+a+"_popup")}))})},lHt=function(i,a,f,p,w){if(a.links===void 0||a.links===null||Object.keys(a.links).length===0)return{height:0,width:0};const y=a.links,b=a.actorCnt,E=a.rectData;var S="none";w&&(S="block !important");const N=i.append("g");N.attr("id","actor"+b+"_popup"),N.attr("class","actorPopupMenu"),N.attr("display",S),HRe("#actor"+b+"_popup",b);var B="";E.class!==void 0&&(B=" "+E.class);let R=E.width>f?E.width:f;const j=N.append("rect");if(j.attr("class","actorPopupMenuPanel"+B),j.attr("x",E.x),j.attr("y",E.height),j.attr("fill",E.fill),j.attr("stroke",E.stroke),j.attr("width",R),j.attr("height",E.height),j.attr("rx",E.rx),j.attr("ry",E.ry),y!=null){var $=20;for(let oe in y){var V=N.append("a"),Q=u5(y[oe]);V.attr("xlink:href",Q),V.attr("target","_blank"),LHt(p)(oe,V,E.x+10,E.height+$,R,20,{class:"actor"},p),$+=30}}return j.attr("height",$),{height:E.height+$,width:R}},zRe=function(i,a,f,p){const w=i.append("image");w.attr("x",a),w.attr("y",f);var y=u5(p);w.attr("xlink:href",y)},GRe=function(i,a,f,p){const w=i.append("use");w.attr("x",a),w.attr("y",f);var y=u5(p);w.attr("xlink:href","#"+y)},hHt=function(i){return"var pu = document.getElementById('"+i+"'); if (pu != null) { pu.style.display = 'block'; }"},fHt=function(i){return"var pu = document.getElementById('"+i+"'); if (pu != null) { pu.style.display = 'none'; }"},dHt=function(i){var a=document.getElementById(i);a!=null&&(a.style.display="block")},gHt=function(i){var a=document.getElementById(i);a!=null&&(a.style.display="none")},uL=function(i,a){let f=0,p=0;const w=a.text.split(Wa.lineBreakRegex),[y,b]=$A(a.fontSize);let E=[],S=0,N=()=>a.y;if(a.valign!==void 0&&a.textMargin!==void 0&&a.textMargin>0)switch(a.valign){case"top":case"start":N=()=>Math.round(a.y+a.textMargin);break;case"middle":case"center":N=()=>Math.round(a.y+(f+p+a.textMargin)/2);break;case"bottom":case"end":N=()=>Math.round(a.y+(f+p+2*a.textMargin)-a.textMargin);break}if(a.anchor!==void 0&&a.textMargin!==void 0&&a.width!==void 0)switch(a.anchor){case"left":case"start":a.x=Math.round(a.x+a.textMargin),a.anchor="start",a.dominantBaseline="middle",a.alignmentBaseline="middle";break;case"middle":case"center":a.x=Math.round(a.x+a.width/2),a.anchor="middle",a.dominantBaseline="middle",a.alignmentBaseline="middle";break;case"right":case"end":a.x=Math.round(a.x+a.width-a.textMargin),a.anchor="end",a.dominantBaseline="middle",a.alignmentBaseline="middle";break}for(let[B,R]of w.entries()){a.textMargin!==void 0&&a.textMargin===0&&y!==void 0&&(S=B*y);const j=i.append("text");if(j.attr("x",a.x),j.attr("y",N()),a.anchor!==void 0&&j.attr("text-anchor",a.anchor).attr("dominant-baseline",a.dominantBaseline).attr("alignment-baseline",a.alignmentBaseline),a.fontFamily!==void 0&&j.style("font-family",a.fontFamily),b!==void 0&&j.style("font-size",b),a.fontWeight!==void 0&&j.style("font-weight",a.fontWeight),a.fill!==void 0&&j.attr("fill",a.fill),a.class!==void 0&&j.attr("class",a.class),a.dy!==void 0?j.attr("dy",a.dy):S!==0&&j.attr("dy",S),a.tspan){const $=j.append("tspan");$.attr("x",a.x),a.fill!==void 0&&$.attr("fill",a.fill),$.text(R)}else j.text(R);a.valign!==void 0&&a.textMargin!==void 0&&a.textMargin>0&&(p+=(j._groups||j)[0][0].getBBox().height,f=p),E.push(j)}return E},qRe=function(i,a){function f(w,y,b,E,S){return w+","+y+" "+(w+b)+","+y+" "+(w+b)+","+(y+E-S)+" "+(w+b-S*1.2)+","+(y+E)+" "+w+","+(y+E)}const p=i.append("polygon");return p.attr("points",f(a.x,a.y,a.width,a.height,7)),p.attr("class","labelBox"),a.y=a.y+a.height/2,uL(i,a),p};let g3=-1;const VRe=(i,a)=>{i.selectAll&&i.selectAll(".actor-line").attr("class","200").attr("y2",a-55)},pHt=function(i,a,f,p){const w=a.x+a.width/2,y=a.y+5,b=i.append("g");var E=b;p||(g3++,E.append("line").attr("id","actor"+g3).attr("x1",w).attr("y1",y).attr("x2",w).attr("y2",2e3).attr("class","actor-line").attr("stroke-width","0.5px").attr("stroke","#999"),E=b.append("g"),a.actorCnt=g3,a.links!=null&&(E.attr("id","root-"+g3),HRe("#root-"+g3,g3)));const S=DK();var N="actor";a.properties!=null&&a.properties.class?N=a.properties.class:S.fill="#eaeaea",S.x=a.x,S.y=a.y,S.width=a.width,S.height=a.height,S.class=N,S.rx=3,S.ry=3;const B=MK(E,S);if(a.rectData=S,a.properties!=null&&a.properties.icon){const j=a.properties.icon.trim();j.charAt(0)==="@"?GRe(E,S.x+S.width-20,S.y+10,j.substr(1)):zRe(E,S.x+S.width-20,S.y+10,j)}ige(f)(a.description,E,S.x,S.y,S.width,S.height,{class:"actor"},f);let R=a.height;if(B.node){const j=B.node().getBBox();a.height=j.height,R=j.height}return R},bHt=function(i,a,f,p){const w=a.x+a.width/2,y=a.y+80;p||(g3++,i.append("line").attr("id","actor"+g3).attr("x1",w).attr("y1",y).attr("x2",w).attr("y2",2e3).attr("class","actor-line").attr("stroke-width","0.5px").attr("stroke","#999"));const b=i.append("g");b.attr("class","actor-man");const E=DK();E.x=a.x,E.y=a.y,E.fill="#eaeaea",E.width=a.width,E.height=a.height,E.class="actor",E.rx=3,E.ry=3,b.append("line").attr("id","actor-man-torso"+g3).attr("x1",w).attr("y1",a.y+25).attr("x2",w).attr("y2",a.y+45),b.append("line").attr("id","actor-man-arms"+g3).attr("x1",w-18).attr("y1",a.y+33).attr("x2",w+18).attr("y2",a.y+33),b.append("line").attr("x1",w-18).attr("y1",a.y+60).attr("x2",w).attr("y2",a.y+45),b.append("line").attr("x1",w).attr("y1",a.y+45).attr("x2",w+16).attr("y2",a.y+60);const S=b.append("circle");S.attr("cx",a.x+a.width/2),S.attr("cy",a.y+10),S.attr("r",15),S.attr("width",a.width),S.attr("height",a.height);const N=b.node().getBBox();return a.height=N.height,ige(f)(a.description,b,E.x,E.y+35,E.width,E.height,{class:"actor"},f),a.height},vHt=function(i,a,f,p){switch(a.type){case"actor":return bHt(i,a,f,p);case"participant":return pHt(i,a,f,p)}},wHt=function(i,a,f){const w=i.append("g");URe(w,a),a.name&&ige(f)(a.name,w,a.x,a.y+(a.textMaxHeight||0)/2,a.width,0,{class:"text"},f),w.lower()},mHt=function(i){return i.append("g")},yHt=function(i,a,f,p,w){const y=DK(),b=a.anchored;y.x=a.startx,y.y=a.starty,y.class="activation"+w%3,y.width=a.stopx-a.startx,y.height=f-a.starty,MK(b,y)},kHt=function(i,a,f,p){const{boxMargin:w,boxTextMargin:y,labelBoxHeight:b,labelBoxWidth:E,messageFontFamily:S,messageFontSize:N,messageFontWeight:B}=p,R=i.append("g"),j=function(Q,oe,ce,se){return R.append("line").attr("x1",Q).attr("y1",oe).attr("x2",ce).attr("y2",se).attr("class","loopLine")};j(a.startx,a.starty,a.stopx,a.starty),j(a.stopx,a.starty,a.stopx,a.stopy),j(a.startx,a.stopy,a.stopx,a.stopy),j(a.startx,a.starty,a.startx,a.stopy),a.sections!==void 0&&a.sections.forEach(function(Q){j(a.startx,Q.y,a.stopx,Q.y).style("stroke-dasharray","3, 3")});let $=rge();$.text=f,$.x=a.startx,$.y=a.starty,$.fontFamily=S,$.fontSize=N,$.fontWeight=B,$.anchor="middle",$.valign="middle",$.tspan=!1,$.width=E||50,$.height=b||20,$.textMargin=y,$.class="labelText",qRe(R,$),$=rge(),$.text=a.title,$.x=a.startx+E/2+(a.stopx-a.startx)/2,$.y=a.starty+w+y,$.anchor="middle",$.valign="middle",$.textMargin=y,$.class="loopText",$.fontFamily=S,$.fontSize=N,$.fontWeight=B,$.wrap=!0;let V=uL(R,$);return a.sectionTitles!==void 0&&a.sectionTitles.forEach(function(Q,oe){if(Q.message){$.text=Q.message,$.x=a.startx+(a.stopx-a.startx)/2,$.y=a.sections[oe].y+w+y,$.class="loopText",$.anchor="middle",$.valign="middle",$.tspan=!1,$.fontFamily=S,$.fontSize=N,$.fontWeight=B,$.wrap=a.wrap,V=uL(R,$);let ce=Math.round(V.map(se=>(se._groups||se)[0][0].getBBox().height).reduce((se,ge)=>se+ge));a.sections[oe].height+=ce-(w+y)}}),a.height=Math.round(a.stopy-a.starty),R},URe=function(i,a){MK(i,{x:a.startx,y:a.starty,width:a.stopx-a.startx,height:a.stopy-a.starty,fill:a.fill,stroke:a.stroke,class:"rect"}).lower()},xHt=function(i){i.append("defs").append("symbol").attr("id","database").attr("fill-rule","evenodd").attr("clip-rule","evenodd").append("path").attr("transform","scale(.5)").attr("d","M12.258.001l.256.004.255.005.253.008.251.01.249.012.247.015.246.016.242.019.241.02.239.023.236.024.233.027.231.028.229.031.225.032.223.034.22.036.217.038.214.04.211.041.208.043.205.045.201.046.198.048.194.05.191.051.187.053.183.054.18.056.175.057.172.059.168.06.163.061.16.063.155.064.15.066.074.033.073.033.071.034.07.034.069.035.068.035.067.035.066.035.064.036.064.036.062.036.06.036.06.037.058.037.058.037.055.038.055.038.053.038.052.038.051.039.05.039.048.039.047.039.045.04.044.04.043.04.041.04.04.041.039.041.037.041.036.041.034.041.033.042.032.042.03.042.029.042.027.042.026.043.024.043.023.043.021.043.02.043.018.044.017.043.015.044.013.044.012.044.011.045.009.044.007.045.006.045.004.045.002.045.001.045v17l-.001.045-.002.045-.004.045-.006.045-.007.045-.009.044-.011.045-.012.044-.013.044-.015.044-.017.043-.018.044-.02.043-.021.043-.023.043-.024.043-.026.043-.027.042-.029.042-.03.042-.032.042-.033.042-.034.041-.036.041-.037.041-.039.041-.04.041-.041.04-.043.04-.044.04-.045.04-.047.039-.048.039-.05.039-.051.039-.052.038-.053.038-.055.038-.055.038-.058.037-.058.037-.06.037-.06.036-.062.036-.064.036-.064.036-.066.035-.067.035-.068.035-.069.035-.07.034-.071.034-.073.033-.074.033-.15.066-.155.064-.16.063-.163.061-.168.06-.172.059-.175.057-.18.056-.183.054-.187.053-.191.051-.194.05-.198.048-.201.046-.205.045-.208.043-.211.041-.214.04-.217.038-.22.036-.223.034-.225.032-.229.031-.231.028-.233.027-.236.024-.239.023-.241.02-.242.019-.246.016-.247.015-.249.012-.251.01-.253.008-.255.005-.256.004-.258.001-.258-.001-.256-.004-.255-.005-.253-.008-.251-.01-.249-.012-.247-.015-.245-.016-.243-.019-.241-.02-.238-.023-.236-.024-.234-.027-.231-.028-.228-.031-.226-.032-.223-.034-.22-.036-.217-.038-.214-.04-.211-.041-.208-.043-.204-.045-.201-.046-.198-.048-.195-.05-.19-.051-.187-.053-.184-.054-.179-.056-.176-.057-.172-.059-.167-.06-.164-.061-.159-.063-.155-.064-.151-.066-.074-.033-.072-.033-.072-.034-.07-.034-.069-.035-.068-.035-.067-.035-.066-.035-.064-.036-.063-.036-.062-.036-.061-.036-.06-.037-.058-.037-.057-.037-.056-.038-.055-.038-.053-.038-.052-.038-.051-.039-.049-.039-.049-.039-.046-.039-.046-.04-.044-.04-.043-.04-.041-.04-.04-.041-.039-.041-.037-.041-.036-.041-.034-.041-.033-.042-.032-.042-.03-.042-.029-.042-.027-.042-.026-.043-.024-.043-.023-.043-.021-.043-.02-.043-.018-.044-.017-.043-.015-.044-.013-.044-.012-.044-.011-.045-.009-.044-.007-.045-.006-.045-.004-.045-.002-.045-.001-.045v-17l.001-.045.002-.045.004-.045.006-.045.007-.045.009-.044.011-.045.012-.044.013-.044.015-.044.017-.043.018-.044.02-.043.021-.043.023-.043.024-.043.026-.043.027-.042.029-.042.03-.042.032-.042.033-.042.034-.041.036-.041.037-.041.039-.041.04-.041.041-.04.043-.04.044-.04.046-.04.046-.039.049-.039.049-.039.051-.039.052-.038.053-.038.055-.038.056-.038.057-.037.058-.037.06-.037.061-.036.062-.036.063-.036.064-.036.066-.035.067-.035.068-.035.069-.035.07-.034.072-.034.072-.033.074-.033.151-.066.155-.064.159-.063.164-.061.167-.06.172-.059.176-.057.179-.056.184-.054.187-.053.19-.051.195-.05.198-.048.201-.046.204-.045.208-.043.211-.041.214-.04.217-.038.22-.036.223-.034.226-.032.228-.031.231-.028.234-.027.236-.024.238-.023.241-.02.243-.019.245-.016.247-.015.249-.012.251-.01.253-.008.255-.005.256-.004.258-.001.258.001zm-9.258 20.499v.01l.001.021.003.021.004.022.005.021.006.022.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.023.018.024.019.024.021.024.022.025.023.024.024.025.052.049.056.05.061.051.066.051.07.051.075.051.079.052.084.052.088.052.092.052.097.052.102.051.105.052.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.048.144.049.147.047.152.047.155.047.16.045.163.045.167.043.171.043.176.041.178.041.183.039.187.039.19.037.194.035.197.035.202.033.204.031.209.03.212.029.216.027.219.025.222.024.226.021.23.02.233.018.236.016.24.015.243.012.246.01.249.008.253.005.256.004.259.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.021.224-.024.22-.026.216-.027.212-.028.21-.031.205-.031.202-.034.198-.034.194-.036.191-.037.187-.039.183-.04.179-.04.175-.042.172-.043.168-.044.163-.045.16-.046.155-.046.152-.047.148-.048.143-.049.139-.049.136-.05.131-.05.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.053.083-.051.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.05.023-.024.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.023.01-.022.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.127l-.077.055-.08.053-.083.054-.085.053-.087.052-.09.052-.093.051-.095.05-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.045-.118.044-.12.043-.122.042-.124.042-.126.041-.128.04-.13.04-.132.038-.134.038-.135.037-.138.037-.139.035-.142.035-.143.034-.144.033-.147.032-.148.031-.15.03-.151.03-.153.029-.154.027-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.01-.179.008-.179.008-.181.006-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.006-.179-.008-.179-.008-.178-.01-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.027-.153-.029-.151-.03-.15-.03-.148-.031-.146-.032-.145-.033-.143-.034-.141-.035-.14-.035-.137-.037-.136-.037-.134-.038-.132-.038-.13-.04-.128-.04-.126-.041-.124-.042-.122-.042-.12-.044-.117-.043-.116-.045-.113-.045-.112-.046-.109-.047-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.05-.093-.052-.09-.051-.087-.052-.085-.053-.083-.054-.08-.054-.077-.054v4.127zm0-5.654v.011l.001.021.003.021.004.021.005.022.006.022.007.022.009.022.01.022.011.023.012.023.013.023.015.024.016.023.017.024.018.024.019.024.021.024.022.024.023.025.024.024.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.052.11.051.114.051.119.052.123.05.127.051.131.05.135.049.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.044.171.042.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.022.23.02.233.018.236.016.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.012.241-.015.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.048.139-.05.136-.049.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.051.051-.049.023-.025.023-.024.021-.025.02-.024.019-.024.018-.024.017-.024.015-.023.014-.023.013-.024.012-.022.01-.023.01-.023.008-.022.006-.022.006-.022.004-.021.004-.022.001-.021.001-.021v-4.139l-.077.054-.08.054-.083.054-.085.052-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.044-.118.044-.12.044-.122.042-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.035-.143.033-.144.033-.147.033-.148.031-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.009-.179.009-.179.007-.181.007-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.007-.179-.007-.179-.009-.178-.009-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.031-.146-.033-.145-.033-.143-.033-.141-.035-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.04-.126-.041-.124-.042-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.051-.093-.051-.09-.051-.087-.053-.085-.052-.083-.054-.08-.054-.077-.054v4.139zm0-5.666v.011l.001.02.003.022.004.021.005.022.006.021.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.024.018.023.019.024.021.025.022.024.023.024.024.025.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.051.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.043.171.043.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.021.23.02.233.018.236.017.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.013.241-.014.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.049.139-.049.136-.049.131-.051.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.049.023-.025.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.022.01-.023.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.153l-.077.054-.08.054-.083.053-.085.053-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.048-.105.048-.106.048-.109.046-.111.046-.114.046-.115.044-.118.044-.12.043-.122.043-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.034-.143.034-.144.033-.147.032-.148.032-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.024-.161.024-.162.023-.163.023-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.01-.178.01-.179.009-.179.007-.181.006-.182.006-.182.004-.184.003-.184.001-.185.001-.185-.001-.184-.001-.184-.003-.182-.004-.182-.006-.181-.006-.179-.007-.179-.009-.178-.01-.176-.01-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.023-.162-.023-.161-.024-.159-.024-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.032-.146-.032-.145-.033-.143-.034-.141-.034-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.041-.126-.041-.124-.041-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.048-.105-.048-.102-.048-.1-.05-.097-.049-.095-.051-.093-.051-.09-.052-.087-.052-.085-.053-.083-.053-.08-.054-.077-.054v4.153zm8.74-8.179l-.257.004-.254.005-.25.008-.247.011-.244.012-.241.014-.237.016-.233.018-.231.021-.226.022-.224.023-.22.026-.216.027-.212.028-.21.031-.205.032-.202.033-.198.034-.194.036-.191.038-.187.038-.183.04-.179.041-.175.042-.172.043-.168.043-.163.045-.16.046-.155.046-.152.048-.148.048-.143.048-.139.049-.136.05-.131.05-.126.051-.123.051-.118.051-.114.052-.11.052-.106.052-.101.052-.096.052-.092.052-.088.052-.083.052-.079.052-.074.051-.07.052-.065.051-.06.05-.056.05-.051.05-.023.025-.023.024-.021.024-.02.025-.019.024-.018.024-.017.023-.015.024-.014.023-.013.023-.012.023-.01.023-.01.022-.008.022-.006.023-.006.021-.004.022-.004.021-.001.021-.001.021.001.021.001.021.004.021.004.022.006.021.006.023.008.022.01.022.01.023.012.023.013.023.014.023.015.024.017.023.018.024.019.024.02.025.021.024.023.024.023.025.051.05.056.05.06.05.065.051.07.052.074.051.079.052.083.052.088.052.092.052.096.052.101.052.106.052.11.052.114.052.118.051.123.051.126.051.131.05.136.05.139.049.143.048.148.048.152.048.155.046.16.046.163.045.168.043.172.043.175.042.179.041.183.04.187.038.191.038.194.036.198.034.202.033.205.032.21.031.212.028.216.027.22.026.224.023.226.022.231.021.233.018.237.016.241.014.244.012.247.011.25.008.254.005.257.004.26.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.022.224-.023.22-.026.216-.027.212-.028.21-.031.205-.032.202-.033.198-.034.194-.036.191-.038.187-.038.183-.04.179-.041.175-.042.172-.043.168-.043.163-.045.16-.046.155-.046.152-.048.148-.048.143-.048.139-.049.136-.05.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.05.051-.05.023-.025.023-.024.021-.024.02-.025.019-.024.018-.024.017-.023.015-.024.014-.023.013-.023.012-.023.01-.023.01-.022.008-.022.006-.023.006-.021.004-.022.004-.021.001-.021.001-.021-.001-.021-.001-.021-.004-.021-.004-.022-.006-.021-.006-.023-.008-.022-.01-.022-.01-.023-.012-.023-.013-.023-.014-.023-.015-.024-.017-.023-.018-.024-.019-.024-.02-.025-.021-.024-.023-.024-.023-.025-.051-.05-.056-.05-.06-.05-.065-.051-.07-.052-.074-.051-.079-.052-.083-.052-.088-.052-.092-.052-.096-.052-.101-.052-.106-.052-.11-.052-.114-.052-.118-.051-.123-.051-.126-.051-.131-.05-.136-.05-.139-.049-.143-.048-.148-.048-.152-.048-.155-.046-.16-.046-.163-.045-.168-.043-.172-.043-.175-.042-.179-.041-.183-.04-.187-.038-.191-.038-.194-.036-.198-.034-.202-.033-.205-.032-.21-.031-.212-.028-.216-.027-.22-.026-.224-.023-.226-.022-.231-.021-.233-.018-.237-.016-.241-.014-.244-.012-.247-.011-.25-.008-.254-.005-.257-.004-.26-.001-.26.001z")},EHt=function(i){i.append("defs").append("symbol").attr("id","computer").attr("width","24").attr("height","24").append("path").attr("transform","scale(.5)").attr("d","M2 2v13h20v-13h-20zm18 11h-16v-9h16v9zm-10.228 6l.466-1h3.524l.467 1h-4.457zm14.228 3h-24l2-6h2.104l-1.33 4h18.45l-1.297-4h2.073l2 6zm-5-10h-14v-7h14v7z")},THt=function(i){i.append("defs").append("symbol").attr("id","clock").attr("width","24").attr("height","24").append("path").attr("transform","scale(.5)").attr("d","M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm5.848 12.459c.202.038.202.333.001.372-1.907.361-6.045 1.111-6.547 1.111-.719 0-1.301-.582-1.301-1.301 0-.512.77-5.447 1.125-7.445.034-.192.312-.181.343.014l.985 6.238 5.394 1.011z")},_Ht=function(i){i.append("defs").append("marker").attr("id","arrowhead").attr("refX",9).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",12).attr("markerHeight",12).attr("orient","auto").append("path").attr("d","M 0 0 L 10 5 L 0 10 z")},CHt=function(i){i.append("defs").append("marker").attr("id","filled-head").attr("refX",18).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L14,7 L9,1 Z")},SHt=function(i){i.append("defs").append("marker").attr("id","sequencenumber").attr("refX",15).attr("refY",15).attr("markerWidth",60).attr("markerHeight",40).attr("orient","auto").append("circle").attr("cx",15).attr("cy",15).attr("r",6)},AHt=function(i){i.append("defs").append("marker").attr("id","crosshead").attr("markerWidth",15).attr("markerHeight",8).attr("orient","auto").attr("refX",4).attr("refY",5).append("path").attr("fill","none").attr("stroke","#000000").style("stroke-dasharray","0, 0").attr("stroke-width","1pt").attr("d","M 1,2 L 6,7 M 6,2 L 1,7")},rge=function(){return{x:0,y:0,fill:void 0,anchor:void 0,style:"#666",width:void 0,height:void 0,textMargin:0,rx:0,ry:0,tspan:!0,valign:void 0}},DK=function(){return{x:0,y:0,fill:"#EDF2AE",stroke:"#666",width:100,anchor:"start",height:100,rx:0,ry:0}},ige=function(){function i(w,y,b,E,S,N,B){const R=y.append("text").attr("x",b+S/2).attr("y",E+N/2+5).style("text-anchor","middle").text(w);p(R,B)}function a(w,y,b,E,S,N,B,R){const{actorFontSize:j,actorFontFamily:$,actorFontWeight:V}=R,[Q,oe]=$A(j),ce=w.split(Wa.lineBreakRegex);for(let se=0;sei.height||0))+(this.loops.length===0?0:this.loops.map(i=>i.height||0).reduce((i,a)=>i+a))+(this.messages.length===0?0:this.messages.map(i=>i.height||0).reduce((i,a)=>i+a))+(this.notes.length===0?0:this.notes.map(i=>i.height||0).reduce((i,a)=>i+a))},clear:function(){this.actors=[],this.boxes=[],this.loops=[],this.messages=[],this.notes=[]},addBox:function(i){this.boxes.push(i)},addActor:function(i){this.actors.push(i)},addLoop:function(i){this.loops.push(i)},addMessage:function(i){this.messages.push(i)},addNote:function(i){this.notes.push(i)},lastActor:function(){return this.actors[this.actors.length-1]},lastLoop:function(){return this.loops[this.loops.length-1]},lastMessage:function(){return this.messages[this.messages.length-1]},lastNote:function(){return this.notes[this.notes.length-1]},actors:[],boxes:[],loops:[],messages:[],notes:[]},init:function(){this.sequenceItems=[],this.activations=[],this.models.clear(),this.data={startx:void 0,stopx:void 0,starty:void 0,stopy:void 0},this.verticalPos=0,KRe(Tt())},updateVal:function(i,a,f,p){i[a]===void 0?i[a]=f:i[a]=p(f,i[a])},updateBounds:function(i,a,f,p){const w=this;let y=0;function b(E){return function(N){y++;const B=w.sequenceItems.length-y+1;w.updateVal(N,"starty",a-B*ln.boxMargin,Math.min),w.updateVal(N,"stopy",p+B*ln.boxMargin,Math.max),w.updateVal(si.data,"startx",i-B*ln.boxMargin,Math.min),w.updateVal(si.data,"stopx",f+B*ln.boxMargin,Math.max),E!=="activation"&&(w.updateVal(N,"startx",i-B*ln.boxMargin,Math.min),w.updateVal(N,"stopx",f+B*ln.boxMargin,Math.max),w.updateVal(si.data,"starty",a-B*ln.boxMargin,Math.min),w.updateVal(si.data,"stopy",p+B*ln.boxMargin,Math.max))}}this.sequenceItems.forEach(b()),this.activations.forEach(b("activation"))},insert:function(i,a,f,p){const w=Math.min(i,f),y=Math.max(i,f),b=Math.min(a,p),E=Math.max(a,p);this.updateVal(si.data,"startx",w,Math.min),this.updateVal(si.data,"starty",b,Math.min),this.updateVal(si.data,"stopx",y,Math.max),this.updateVal(si.data,"stopy",E,Math.max),this.updateBounds(w,b,y,E)},newActivation:function(i,a,f){const p=f[i.from.actor],w=IK(i.from.actor).length||0,y=p.x+p.width/2+(w-1)*ln.activationWidth/2;this.activations.push({startx:y,starty:this.verticalPos+2,stopx:y+ln.activationWidth,stopy:void 0,actor:i.from.actor,anchored:ih.anchorElement(a)})},endActivation:function(i){const a=this.activations.map(function(f){return f.actor}).lastIndexOf(i.from.actor);return this.activations.splice(a,1)[0]},createLoop:function(i={message:void 0,wrap:!1,width:void 0},a){return{startx:void 0,starty:this.verticalPos,stopx:void 0,stopy:void 0,title:i.message,wrap:i.wrap,width:i.width,height:0,fill:a}},newLoop:function(i={message:void 0,wrap:!1,width:void 0},a){this.sequenceItems.push(this.createLoop(i,a))},endLoop:function(){return this.sequenceItems.pop()},addSectionToLoop:function(i){const a=this.sequenceItems.pop();a.sections=a.sections||[],a.sectionTitles=a.sectionTitles||[],a.sections.push({y:si.getVerticalPos(),height:0}),a.sectionTitles.push(i),this.sequenceItems.push(a)},bumpVerticalPos:function(i){this.verticalPos=this.verticalPos+i,this.data.stopy=this.verticalPos},getVerticalPos:function(){return this.verticalPos},getBounds:function(){return{bounds:this.data,models:this.models}}},MHt=function(i,a){si.bumpVerticalPos(ln.boxMargin),a.height=ln.boxMargin,a.starty=si.getVerticalPos();const f=ih.getNoteRect();f.x=a.startx,f.y=a.starty,f.width=a.width||ln.width,f.class="note";const p=i.append("g"),w=ih.drawRect(p,f),y=ih.getTextObj();y.x=a.startx,y.y=a.starty,y.width=f.width,y.dy="1em",y.text=a.message,y.class="noteText",y.fontFamily=ln.noteFontFamily,y.fontSize=ln.noteFontSize,y.fontWeight=ln.noteFontWeight,y.anchor=ln.noteAlign,y.textMargin=ln.noteMargin,y.valign="center";const b=uL(p,y),E=Math.round(b.map(S=>(S._groups||S)[0][0].getBBox().height).reduce((S,N)=>S+N));w.attr("height",E+2*ln.noteMargin),a.height+=E+2*ln.noteMargin,si.bumpVerticalPos(E+2*ln.noteMargin),a.stopy=a.starty+E+2*ln.noteMargin,a.stopx=a.startx+f.width,si.insert(a.startx,a.starty,a.stopx,a.stopy),si.models.addNote(a)},g9=i=>({fontFamily:i.messageFontFamily,fontSize:i.messageFontSize,fontWeight:i.messageFontWeight}),lL=i=>({fontFamily:i.noteFontFamily,fontSize:i.noteFontSize,fontWeight:i.noteFontWeight}),sge=i=>({fontFamily:i.actorFontFamily,fontSize:i.actorFontSize,fontWeight:i.actorFontWeight});function DHt(i,a){si.bumpVerticalPos(10);const{startx:f,stopx:p,message:w}=a,y=Wa.splitBreaks(w).length,b=co.calculateTextDimensions(w,g9(ln)),E=b.height/y;a.height+=E,si.bumpVerticalPos(E);let S,N=b.height-10;const B=b.width;if(f===p){S=si.getVerticalPos()+N,ln.rightAngles||(N+=ln.boxMargin,S=si.getVerticalPos()+N),N+=30;const R=Math.max(B/2,ln.width/2);si.insert(f-R,si.getVerticalPos()-10+N,p+R,si.getVerticalPos()+30+N)}else N+=ln.boxMargin,S=si.getVerticalPos()+N,si.insert(f,S-10,p,S);return si.bumpVerticalPos(N),a.height+=N,a.stopy=a.starty+a.height,si.insert(a.fromBounds,a.starty,a.toBounds,a.stopy),S}const IHt=function(i,a,f,p){const{startx:w,stopx:y,starty:b,message:E,type:S,sequenceIndex:N,sequenceVisible:B}=a,R=co.calculateTextDimensions(E,g9(ln)),j=ih.getTextObj();j.x=w,j.y=b+10,j.width=y-w,j.class="messageText",j.dy="1em",j.text=E,j.fontFamily=ln.messageFontFamily,j.fontSize=ln.messageFontSize,j.fontWeight=ln.messageFontWeight,j.anchor=ln.messageAlign,j.valign="center",j.textMargin=ln.wrapPadding,j.tspan=!1,uL(i,j);const $=R.width;let V;w===y?ln.rightAngles?V=i.append("path").attr("d",`M ${w},${f} H ${w+Math.max(ln.width/2,$/2)} V ${f+25} H ${w}`):V=i.append("path").attr("d","M "+w+","+f+" C "+(w+60)+","+(f-10)+" "+(w+60)+","+(f+30)+" "+w+","+(f+20)):(V=i.append("line"),V.attr("x1",w),V.attr("y1",f),V.attr("x2",y),V.attr("y2",f)),S===p.db.LINETYPE.DOTTED||S===p.db.LINETYPE.DOTTED_CROSS||S===p.db.LINETYPE.DOTTED_POINT||S===p.db.LINETYPE.DOTTED_OPEN?(V.style("stroke-dasharray","3, 3"),V.attr("class","messageLine1")):V.attr("class","messageLine0");let Q="";ln.arrowMarkerAbsolute&&(Q=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search,Q=Q.replace(/\(/g,"\\("),Q=Q.replace(/\)/g,"\\)")),V.attr("stroke-width",2),V.attr("stroke","none"),V.style("fill","none"),(S===p.db.LINETYPE.SOLID||S===p.db.LINETYPE.DOTTED)&&V.attr("marker-end","url("+Q+"#arrowhead)"),(S===p.db.LINETYPE.SOLID_POINT||S===p.db.LINETYPE.DOTTED_POINT)&&V.attr("marker-end","url("+Q+"#filled-head)"),(S===p.db.LINETYPE.SOLID_CROSS||S===p.db.LINETYPE.DOTTED_CROSS)&&V.attr("marker-end","url("+Q+"#crosshead)"),(B||ln.showSequenceNumbers)&&(V.attr("marker-start","url("+Q+"#sequencenumber)"),i.append("text").attr("x",w).attr("y",f+4).attr("font-family","sans-serif").attr("font-size","12px").attr("text-anchor","middle").attr("class","sequenceNumber").text(N))},age=function(i,a,f,p,w,y,b){if(w.hideUnusedParticipants===!0){const R=new Set;y.forEach(j=>{R.add(j.from),R.add(j.to)}),f=f.filter(j=>R.has(j))}let E=0,S=0,N=0,B;for(const R of f){const j=a[R],$=j.box;B&&B!=$&&(b||si.models.addBox(B),S+=ln.boxMargin+B.margin),$&&$!=B&&(b||($.x=E+S,$.y=p),S+=$.margin),j.width=j.width||ln.width,j.height=Math.max(j.height||ln.height,ln.height),j.margin=j.margin||ln.actorMargin,j.x=E+S,j.y=si.getVerticalPos();const V=ih.drawActor(i,j,ln,b);N=Math.max(N,V),si.insert(j.x,p,j.x+j.width,j.height),E+=j.width+S,j.box&&(j.box.width=E+$.margin-j.box.x),S=j.margin,B=j.box,si.models.addActor(j)}B&&!b&&si.models.addBox(B),si.bumpVerticalPos(N)},WRe=function(i,a,f,p){let w=0,y=0;for(const b of f){const E=a[b],S=PHt(E),N=ih.drawPopup(i,E,S,ln,ln.forceMenus,p);N.height>w&&(w=N.height),N.width+E.x>y&&(y=N.width+E.x)}return{maxHeight:w,maxWidth:y}},KRe=function(i){nd(ln,i),i.fontFamily&&(ln.actorFontFamily=ln.noteFontFamily=ln.messageFontFamily=i.fontFamily),i.fontSize&&(ln.actorFontSize=ln.noteFontSize=ln.messageFontSize=i.fontSize),i.fontWeight&&(ln.actorFontWeight=ln.noteFontWeight=ln.messageFontWeight=i.fontWeight)},IK=function(i){return si.activations.filter(function(a){return a.actor===i})},YRe=function(i,a){const f=a[i],p=IK(i),w=p.reduce(function(b,E){return Math.min(b,E.startx)},f.x+f.width/2),y=p.reduce(function(b,E){return Math.max(b,E.stopx)},f.x+f.width/2);return[w,y]};function p3(i,a,f,p,w){si.bumpVerticalPos(f);let y=p;if(a.id&&a.message&&i[a.id]){const b=i[a.id].width,E=g9(ln);a.message=co.wrapLabel(`[${a.message}]`,b-2*ln.wrapPadding,E),a.width=b,a.wrap=!0;const S=co.calculateTextDimensions(a.message,E),N=Math.max(S.height,ln.labelBoxHeight);y=p+N,Fe.debug(`${N} - ${a.message}`)}w(a),si.bumpVerticalPos(y)}const OHt=function(i,a,f,p){const{securityLevel:w,sequence:y}=Tt();ln=y,p.db.clear(),p.parser.parse(i);let b;w==="sandbox"&&(b=Cr("#i"+a));const E=Cr(w==="sandbox"?b.nodes()[0].contentDocument.body:"body"),S=w==="sandbox"?b.nodes()[0].contentDocument:document;si.init(),Fe.debug(p.db);const N=w==="sandbox"?E.select(`[id="${a}"]`):Cr(`[id="${a}"]`),B=p.db.getActors(),R=p.db.getBoxes(),j=p.db.getActorKeys(),$=p.db.getMessages(),V=p.db.getDiagramTitle(),Q=p.db.hasAtLeastOneBox(),oe=p.db.hasAtLeastOneBoxWithTitle(),ce=NHt(B,$,p);ln.height=BHt(B,ce,R),ih.insertComputerIcon(N),ih.insertDatabaseIcon(N),ih.insertClockIcon(N),Q&&(si.bumpVerticalPos(ln.boxMargin),oe&&si.bumpVerticalPos(R[0].textMaxHeight)),age(N,B,j,0,ln,$,!1);const se=jHt($,B,ce,p);ih.insertArrowHead(N),ih.insertArrowCrossHead(N),ih.insertArrowFilledHead(N),ih.insertSequenceNumber(N);function ge(rt,me){const gt=si.endActivation(rt);gt.starty+18>me&&(gt.starty=me-6,me+=12),ih.drawActivation(N,gt,me,ln,IK(rt.from.actor).length),si.insert(gt.startx,me-10,gt.stopx,me)}let ye=1,ke=1;const Ae=[];$.forEach(function(rt){let me,gt,pe;switch(rt.type){case p.db.LINETYPE.NOTE:gt=rt.noteModel,MHt(N,gt);break;case p.db.LINETYPE.ACTIVE_START:si.newActivation(rt,N,B);break;case p.db.LINETYPE.ACTIVE_END:ge(rt,si.getVerticalPos());break;case p.db.LINETYPE.LOOP_START:p3(se,rt,ln.boxMargin,ln.boxMargin+ln.boxTextMargin,Et=>si.newLoop(Et));break;case p.db.LINETYPE.LOOP_END:me=si.endLoop(),ih.drawLoop(N,me,"loop",ln),si.bumpVerticalPos(me.stopy-si.getVerticalPos()),si.models.addLoop(me);break;case p.db.LINETYPE.RECT_START:p3(se,rt,ln.boxMargin,ln.boxMargin,Et=>si.newLoop(void 0,Et.message));break;case p.db.LINETYPE.RECT_END:me=si.endLoop(),ih.drawBackgroundRect(N,me),si.models.addLoop(me),si.bumpVerticalPos(me.stopy-si.getVerticalPos());break;case p.db.LINETYPE.OPT_START:p3(se,rt,ln.boxMargin,ln.boxMargin+ln.boxTextMargin,Et=>si.newLoop(Et));break;case p.db.LINETYPE.OPT_END:me=si.endLoop(),ih.drawLoop(N,me,"opt",ln),si.bumpVerticalPos(me.stopy-si.getVerticalPos()),si.models.addLoop(me);break;case p.db.LINETYPE.ALT_START:p3(se,rt,ln.boxMargin,ln.boxMargin+ln.boxTextMargin,Et=>si.newLoop(Et));break;case p.db.LINETYPE.ALT_ELSE:p3(se,rt,ln.boxMargin+ln.boxTextMargin,ln.boxMargin,Et=>si.addSectionToLoop(Et));break;case p.db.LINETYPE.ALT_END:me=si.endLoop(),ih.drawLoop(N,me,"alt",ln),si.bumpVerticalPos(me.stopy-si.getVerticalPos()),si.models.addLoop(me);break;case p.db.LINETYPE.PAR_START:p3(se,rt,ln.boxMargin,ln.boxMargin+ln.boxTextMargin,Et=>si.newLoop(Et));break;case p.db.LINETYPE.PAR_AND:p3(se,rt,ln.boxMargin+ln.boxTextMargin,ln.boxMargin,Et=>si.addSectionToLoop(Et));break;case p.db.LINETYPE.PAR_END:me=si.endLoop(),ih.drawLoop(N,me,"par",ln),si.bumpVerticalPos(me.stopy-si.getVerticalPos()),si.models.addLoop(me);break;case p.db.LINETYPE.AUTONUMBER:ye=rt.message.start||ye,ke=rt.message.step||ke,rt.message.visible?p.db.enableSequenceNumbers():p.db.disableSequenceNumbers();break;case p.db.LINETYPE.CRITICAL_START:p3(se,rt,ln.boxMargin,ln.boxMargin+ln.boxTextMargin,Et=>si.newLoop(Et));break;case p.db.LINETYPE.CRITICAL_OPTION:p3(se,rt,ln.boxMargin+ln.boxTextMargin,ln.boxMargin,Et=>si.addSectionToLoop(Et));break;case p.db.LINETYPE.CRITICAL_END:me=si.endLoop(),ih.drawLoop(N,me,"critical",ln),si.bumpVerticalPos(me.stopy-si.getVerticalPos()),si.models.addLoop(me);break;case p.db.LINETYPE.BREAK_START:p3(se,rt,ln.boxMargin,ln.boxMargin+ln.boxTextMargin,Et=>si.newLoop(Et));break;case p.db.LINETYPE.BREAK_END:me=si.endLoop(),ih.drawLoop(N,me,"break",ln),si.bumpVerticalPos(me.stopy-si.getVerticalPos()),si.models.addLoop(me);break;default:try{pe=rt.msgModel,pe.starty=si.getVerticalPos(),pe.sequenceIndex=ye,pe.sequenceVisible=p.db.showSequenceNumbers();const Et=DHt(N,pe);Ae.push({messageModel:pe,lineStartY:Et}),si.models.addMessage(pe)}catch(Et){Fe.error("error while drawing message",Et)}}[p.db.LINETYPE.SOLID_OPEN,p.db.LINETYPE.DOTTED_OPEN,p.db.LINETYPE.SOLID,p.db.LINETYPE.DOTTED,p.db.LINETYPE.SOLID_CROSS,p.db.LINETYPE.DOTTED_CROSS,p.db.LINETYPE.SOLID_POINT,p.db.LINETYPE.DOTTED_POINT].includes(rt.type)&&(ye=ye+ke)}),Ae.forEach(rt=>IHt(N,rt.messageModel,rt.lineStartY,p)),ln.mirrorActors&&(si.bumpVerticalPos(ln.boxMargin*2),age(N,B,j,si.getVerticalPos(),ln,$,!0),si.bumpVerticalPos(ln.boxMargin),VRe(N,si.getVerticalPos())),si.models.boxes.forEach(function(rt){rt.height=si.getVerticalPos()-rt.y,si.insert(rt.x,rt.y,rt.x+rt.width,rt.height),rt.startx=rt.x,rt.starty=rt.y,rt.stopx=rt.startx+rt.width,rt.stopy=rt.starty+rt.height,rt.stroke="rgb(0,0,0, 0.5)",ih.drawBox(N,rt,ln)}),Q&&si.bumpVerticalPos(ln.boxMargin);const de=WRe(N,B,j,S),{bounds:ve}=si.getBounds();Fe.debug("For line height fix Querying: #"+a+" .actor-line"),Jfe("#"+a+" .actor-line").attr("y2",ve.stopy);let xe=ve.stopy-ve.starty;xe{const b=i[y];b.wrap&&(b.description=co.wrapLabel(b.description,ln.width-2*ln.wrapPadding,sge(ln)));const E=co.calculateTextDimensions(b.description,sge(ln));b.width=b.wrap?ln.width:Math.max(ln.width,E.width+2*ln.wrapPadding),b.height=b.wrap?Math.max(E.height,ln.height):ln.height,p=Math.max(p,b.height)});for(const y in a){const b=i[y];if(!b)continue;const E=i[b.nextActor];if(!E){const R=a[y]+ln.actorMargin-b.width/2;b.margin=Math.max(R,ln.actorMargin);continue}const N=a[y]+ln.actorMargin-b.width/2-E.width/2;b.margin=Math.max(N,ln.actorMargin)}let w=0;return f.forEach(y=>{const b=g9(ln);let E=y.actorKeys.reduce((B,R)=>B+=i[R].width+(i[R].margin||0),0);E-=2*ln.boxTextMargin,y.wrap&&(y.name=co.wrapLabel(y.name,E-2*ln.wrapPadding,b));const S=co.calculateTextDimensions(y.name,b);w=Math.max(S.height,w);const N=Math.max(E,S.width+2*ln.wrapPadding);if(y.margin=ln.boxTextMargin,Ey.textMaxHeight=w),Math.max(p,ln.height)}const RHt=function(i,a,f){const p=a[i.from].x,w=a[i.to].x,y=i.wrap&&i.message;let b=co.calculateTextDimensions(y?co.wrapLabel(i.message,ln.width,lL(ln)):i.message,lL(ln));const E={width:y?ln.width:Math.max(ln.width,b.width+2*ln.noteMargin),height:0,startx:a[i.from].x,stopx:0,starty:0,stopy:0,message:i.message};return i.placement===f.db.PLACEMENT.RIGHTOF?(E.width=y?Math.max(ln.width,b.width):Math.max(a[i.from].width/2+a[i.to].width/2,b.width+2*ln.noteMargin),E.startx=p+(a[i.from].width+ln.actorMargin)/2):i.placement===f.db.PLACEMENT.LEFTOF?(E.width=Math.max(y?ln.width:a[i.from].width/2+a[i.to].width/2,b.width+2*ln.noteMargin),E.startx=p-E.width+(a[i.from].width-ln.actorMargin)/2):i.to===i.from?(b=co.calculateTextDimensions(y?co.wrapLabel(i.message,Math.max(ln.width,a[i.from].width),lL(ln)):i.message,lL(ln)),E.width=y?Math.max(ln.width,a[i.from].width):Math.max(a[i.from].width,ln.width,b.width+2*ln.noteMargin),E.startx=p+(a[i.from].width-E.width)/2):(E.width=Math.abs(p+a[i.from].width/2-(w+a[i.to].width/2))+ln.actorMargin,E.startx=pj.actor).lastIndexOf(N.from.actor);delete si.activations.splice(R,1)[0]}break}N.placement!==void 0?(E=RHt(N,a,p),N.noteModel=E,y.forEach(R=>{b=R,b.from=Math.min(b.from,E.startx),b.to=Math.max(b.to,E.startx+E.width),b.width=Math.max(b.width,Math.abs(b.from-b.to))-ln.labelBoxWidth})):(S=FHt(N,a,p),N.msgModel=S,S.startx&&S.stopx&&y.length>0&&y.forEach(R=>{if(b=R,S.startx===S.stopx){const j=a[N.from],$=a[N.to];b.from=Math.min(j.x-S.width/2,j.x-j.width/2,b.from),b.to=Math.max($.x+S.width/2,$.x+j.width/2,b.to),b.width=Math.max(b.width,Math.abs(b.to-b.from))-ln.labelBoxWidth}else b.from=Math.min(S.startx,b.from),b.to=Math.max(S.stopx,b.to),b.width=Math.max(b.width,S.width)-ln.labelBoxWidth}))}),si.activations=[],Fe.debug("Loop type widths:",w),w},$Ht=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:j$t,db:cHt,renderer:{bounds:si,drawActors:age,drawActorsPopup:WRe,setConf:KRe,draw:OHt},styles:uHt}},Symbol.toStringTag,{value:"Module"}));var oge=function(){var i=function(Nt,ze,Xe,Lt){for(Xe=Xe||{},Lt=Nt.length;Lt--;Xe[Nt[Lt]]=ze);return Xe},a=[1,32],f=[1,33],p=[1,34],w=[1,35],y=[1,9],b=[1,8],E=[1,18],S=[1,19],N=[1,20],B=[1,38],R=[1,25],j=[1,23],$=[1,24],V=[1,30],Q=[1,31],oe=[1,26],ce=[1,27],se=[1,28],ge=[1,29],ye=[1,42],ke=[1,39],Ae=[1,40],de=[1,41],ve=[1,43],te=[1,16,24],xe=[1,57],De=[1,58],he=[1,59],Ie=[1,60],ee=[1,61],rt=[1,62],me=[1,63],gt=[1,73],pe=[1,16,24,27,28,35,48,49,63,64,65,66,67,68,69,74,76],Et=[1,16,24,27,28,33,35,48,49,54,63,64,65,66,67,68,69,74,76,89,91,92,93,94],wt=[1,80],jt=[28,89,91,92,93,94],At=[28,68,69,89,91,92,93,94],Bt=[28,63,64,65,66,67,89,91,92,93,94],cn=[1,90],Nn=[1,16,24,48,49],Ot=[1,16,24,35],oi=[8,9,10,11,19,23,42,44,46,52,53,55,56,58,60,70,71,73,77,89,91,92,93,94],kt={trace:function(){},yy:{},symbols_:{error:2,start:3,mermaidDoc:4,directive:5,statements:6,direction:7,direction_tb:8,direction_bt:9,direction_rl:10,direction_lr:11,graphConfig:12,openDirective:13,typeDirective:14,closeDirective:15,NEWLINE:16,":":17,argDirective:18,open_directive:19,type_directive:20,arg_directive:21,close_directive:22,CLASS_DIAGRAM:23,EOF:24,statement:25,classLabel:26,SQS:27,STR:28,SQE:29,className:30,alphaNumToken:31,classLiteralName:32,GENERICTYPE:33,relationStatement:34,LABEL:35,classStatement:36,methodStatement:37,annotationStatement:38,clickStatement:39,cssClassStatement:40,noteStatement:41,acc_title:42,acc_title_value:43,acc_descr:44,acc_descr_value:45,acc_descr_multiline_value:46,classIdentifier:47,STYLE_SEPARATOR:48,STRUCT_START:49,members:50,STRUCT_STOP:51,CLASS:52,ANNOTATION_START:53,ANNOTATION_END:54,MEMBER:55,SEPARATOR:56,relation:57,NOTE_FOR:58,noteText:59,NOTE:60,relationType:61,lineType:62,AGGREGATION:63,EXTENSION:64,COMPOSITION:65,DEPENDENCY:66,LOLLIPOP:67,LINE:68,DOTTED_LINE:69,CALLBACK:70,LINK:71,LINK_TARGET:72,CLICK:73,CALLBACK_NAME:74,CALLBACK_ARGS:75,HREF:76,CSSCLASS:77,commentToken:78,textToken:79,graphCodeTokens:80,textNoTagsToken:81,TAGSTART:82,TAGEND:83,"==":84,"--":85,PCT:86,DEFAULT:87,SPACE:88,MINUS:89,keywords:90,UNICODE_TEXT:91,NUM:92,ALPHA:93,BQUOTE_STR:94,$accept:0,$end:1},terminals_:{2:"error",8:"direction_tb",9:"direction_bt",10:"direction_rl",11:"direction_lr",16:"NEWLINE",17:":",19:"open_directive",20:"type_directive",21:"arg_directive",22:"close_directive",23:"CLASS_DIAGRAM",24:"EOF",27:"SQS",28:"STR",29:"SQE",33:"GENERICTYPE",35:"LABEL",42:"acc_title",43:"acc_title_value",44:"acc_descr",45:"acc_descr_value",46:"acc_descr_multiline_value",48:"STYLE_SEPARATOR",49:"STRUCT_START",51:"STRUCT_STOP",52:"CLASS",53:"ANNOTATION_START",54:"ANNOTATION_END",55:"MEMBER",56:"SEPARATOR",58:"NOTE_FOR",60:"NOTE",63:"AGGREGATION",64:"EXTENSION",65:"COMPOSITION",66:"DEPENDENCY",67:"LOLLIPOP",68:"LINE",69:"DOTTED_LINE",70:"CALLBACK",71:"LINK",72:"LINK_TARGET",73:"CLICK",74:"CALLBACK_NAME",75:"CALLBACK_ARGS",76:"HREF",77:"CSSCLASS",80:"graphCodeTokens",82:"TAGSTART",83:"TAGEND",84:"==",85:"--",86:"PCT",87:"DEFAULT",88:"SPACE",89:"MINUS",90:"keywords",91:"UNICODE_TEXT",92:"NUM",93:"ALPHA",94:"BQUOTE_STR"},productions_:[0,[3,1],[3,2],[3,1],[7,1],[7,1],[7,1],[7,1],[4,1],[5,4],[5,6],[13,1],[14,1],[18,1],[15,1],[12,4],[6,1],[6,2],[6,3],[26,3],[30,1],[30,1],[30,2],[30,2],[30,2],[25,1],[25,2],[25,1],[25,1],[25,1],[25,1],[25,1],[25,1],[25,1],[25,2],[25,2],[25,1],[36,1],[36,3],[36,4],[36,6],[47,2],[47,3],[38,4],[50,1],[50,2],[37,1],[37,2],[37,1],[37,1],[34,3],[34,4],[34,4],[34,5],[41,3],[41,2],[57,3],[57,2],[57,2],[57,1],[61,1],[61,1],[61,1],[61,1],[61,1],[62,1],[62,1],[39,3],[39,4],[39,3],[39,4],[39,4],[39,5],[39,3],[39,4],[39,4],[39,5],[39,3],[39,4],[39,4],[39,5],[40,3],[78,1],[78,1],[79,1],[79,1],[79,1],[79,1],[79,1],[79,1],[79,1],[81,1],[81,1],[81,1],[81,1],[31,1],[31,1],[31,1],[31,1],[32,1],[59,1]],performAction:function(ze,Xe,Lt,Ge,Bn,Oe,Ri){var tn=Oe.length-1;switch(Bn){case 4:Ge.setDirection("TB");break;case 5:Ge.setDirection("BT");break;case 6:Ge.setDirection("RL");break;case 7:Ge.setDirection("LR");break;case 11:Ge.parseDirective("%%{","open_directive");break;case 12:Ge.parseDirective(Oe[tn],"type_directive");break;case 13:Oe[tn]=Oe[tn].trim().replace(/'/g,'"'),Ge.parseDirective(Oe[tn],"arg_directive");break;case 14:Ge.parseDirective("}%%","close_directive","class");break;case 19:this.$=Oe[tn-1];break;case 20:case 21:this.$=Oe[tn];break;case 22:this.$=Oe[tn-1]+Oe[tn];break;case 23:case 24:this.$=Oe[tn-1]+"~"+Oe[tn]+"~";break;case 25:Ge.addRelation(Oe[tn]);break;case 26:Oe[tn-1].title=Ge.cleanupLabel(Oe[tn]),Ge.addRelation(Oe[tn-1]);break;case 34:this.$=Oe[tn].trim(),Ge.setAccTitle(this.$);break;case 35:case 36:this.$=Oe[tn].trim(),Ge.setAccDescription(this.$);break;case 38:Ge.setCssClass(Oe[tn-2],Oe[tn]);break;case 39:Ge.addMembers(Oe[tn-3],Oe[tn-1]);break;case 40:Ge.setCssClass(Oe[tn-5],Oe[tn-3]),Ge.addMembers(Oe[tn-5],Oe[tn-1]);break;case 41:this.$=Oe[tn],Ge.addClass(Oe[tn]);break;case 42:this.$=Oe[tn-1],Ge.addClass(Oe[tn-1]),Ge.setClassLabel(Oe[tn-1],Oe[tn]);break;case 43:Ge.addAnnotation(Oe[tn],Oe[tn-2]);break;case 44:this.$=[Oe[tn]];break;case 45:Oe[tn].push(Oe[tn-1]),this.$=Oe[tn];break;case 46:break;case 47:Ge.addMember(Oe[tn-1],Ge.cleanupLabel(Oe[tn]));break;case 48:break;case 49:break;case 50:this.$={id1:Oe[tn-2],id2:Oe[tn],relation:Oe[tn-1],relationTitle1:"none",relationTitle2:"none"};break;case 51:this.$={id1:Oe[tn-3],id2:Oe[tn],relation:Oe[tn-1],relationTitle1:Oe[tn-2],relationTitle2:"none"};break;case 52:this.$={id1:Oe[tn-3],id2:Oe[tn],relation:Oe[tn-2],relationTitle1:"none",relationTitle2:Oe[tn-1]};break;case 53:this.$={id1:Oe[tn-4],id2:Oe[tn],relation:Oe[tn-2],relationTitle1:Oe[tn-3],relationTitle2:Oe[tn-1]};break;case 54:Ge.addNote(Oe[tn],Oe[tn-1]);break;case 55:Ge.addNote(Oe[tn]);break;case 56:this.$={type1:Oe[tn-2],type2:Oe[tn],lineType:Oe[tn-1]};break;case 57:this.$={type1:"none",type2:Oe[tn],lineType:Oe[tn-1]};break;case 58:this.$={type1:Oe[tn-1],type2:"none",lineType:Oe[tn]};break;case 59:this.$={type1:"none",type2:"none",lineType:Oe[tn]};break;case 60:this.$=Ge.relationType.AGGREGATION;break;case 61:this.$=Ge.relationType.EXTENSION;break;case 62:this.$=Ge.relationType.COMPOSITION;break;case 63:this.$=Ge.relationType.DEPENDENCY;break;case 64:this.$=Ge.relationType.LOLLIPOP;break;case 65:this.$=Ge.lineType.LINE;break;case 66:this.$=Ge.lineType.DOTTED_LINE;break;case 67:case 73:this.$=Oe[tn-2],Ge.setClickEvent(Oe[tn-1],Oe[tn]);break;case 68:case 74:this.$=Oe[tn-3],Ge.setClickEvent(Oe[tn-2],Oe[tn-1]),Ge.setTooltip(Oe[tn-2],Oe[tn]);break;case 69:case 77:this.$=Oe[tn-2],Ge.setLink(Oe[tn-1],Oe[tn]);break;case 70:this.$=Oe[tn-3],Ge.setLink(Oe[tn-2],Oe[tn-1],Oe[tn]);break;case 71:case 79:this.$=Oe[tn-3],Ge.setLink(Oe[tn-2],Oe[tn-1]),Ge.setTooltip(Oe[tn-2],Oe[tn]);break;case 72:case 80:this.$=Oe[tn-4],Ge.setLink(Oe[tn-3],Oe[tn-2],Oe[tn]),Ge.setTooltip(Oe[tn-3],Oe[tn-1]);break;case 75:this.$=Oe[tn-3],Ge.setClickEvent(Oe[tn-2],Oe[tn-1],Oe[tn]);break;case 76:this.$=Oe[tn-4],Ge.setClickEvent(Oe[tn-3],Oe[tn-2],Oe[tn-1]),Ge.setTooltip(Oe[tn-3],Oe[tn]);break;case 78:this.$=Oe[tn-3],Ge.setLink(Oe[tn-2],Oe[tn-1],Oe[tn]);break;case 81:Ge.setCssClass(Oe[tn-1],Oe[tn]);break}},table:[{3:1,4:2,5:3,6:4,7:17,8:a,9:f,10:p,11:w,12:5,13:6,19:y,23:b,25:7,30:21,31:36,32:37,34:10,36:11,37:12,38:13,39:14,40:15,41:16,42:E,44:S,46:N,47:22,52:B,53:R,55:j,56:$,58:V,60:Q,70:oe,71:ce,73:se,77:ge,89:ye,91:ke,92:Ae,93:de,94:ve},{1:[3]},{1:[2,1]},{3:44,4:2,5:3,6:4,7:17,8:a,9:f,10:p,11:w,12:5,13:6,19:y,23:b,25:7,30:21,31:36,32:37,34:10,36:11,37:12,38:13,39:14,40:15,41:16,42:E,44:S,46:N,47:22,52:B,53:R,55:j,56:$,58:V,60:Q,70:oe,71:ce,73:se,77:ge,89:ye,91:ke,92:Ae,93:de,94:ve},{1:[2,3]},{1:[2,8]},{14:45,20:[1,46]},i($,[2,16],{16:[1,47]}),{16:[1,48]},{20:[2,11]},i(te,[2,25],{35:[1,49]}),i(te,[2,27]),i(te,[2,28]),i(te,[2,29]),i(te,[2,30]),i(te,[2,31]),i(te,[2,32]),i(te,[2,33]),{43:[1,50]},{45:[1,51]},i(te,[2,36]),i(te,[2,46],{57:52,61:55,62:56,28:[1,53],35:[1,54],63:xe,64:De,65:he,66:Ie,67:ee,68:rt,69:me}),i(te,[2,37],{48:[1,64],49:[1,65]}),i(te,[2,48]),i(te,[2,49]),{31:66,89:ye,91:ke,92:Ae,93:de},{30:67,31:36,32:37,89:ye,91:ke,92:Ae,93:de,94:ve},{30:68,31:36,32:37,89:ye,91:ke,92:Ae,93:de,94:ve},{30:69,31:36,32:37,89:ye,91:ke,92:Ae,93:de,94:ve},{28:[1,70]},{30:71,31:36,32:37,89:ye,91:ke,92:Ae,93:de,94:ve},{28:gt,59:72},i(te,[2,4]),i(te,[2,5]),i(te,[2,6]),i(te,[2,7]),i(pe,[2,20],{31:36,32:37,30:74,33:[1,75],89:ye,91:ke,92:Ae,93:de,94:ve}),i(pe,[2,21],{33:[1,76]}),{30:77,31:36,32:37,89:ye,91:ke,92:Ae,93:de,94:ve},i(Et,[2,95]),i(Et,[2,96]),i(Et,[2,97]),i(Et,[2,98]),i([1,16,24,27,28,33,35,48,49,63,64,65,66,67,68,69,74,76],[2,99]),{1:[2,2]},{15:78,17:[1,79],22:wt},i([17,22],[2,12]),i($,[2,17],{25:7,34:10,36:11,37:12,38:13,39:14,40:15,41:16,7:17,30:21,47:22,31:36,32:37,6:81,8:a,9:f,10:p,11:w,42:E,44:S,46:N,52:B,53:R,55:j,56:$,58:V,60:Q,70:oe,71:ce,73:se,77:ge,89:ye,91:ke,92:Ae,93:de,94:ve}),{6:82,7:17,8:a,9:f,10:p,11:w,25:7,30:21,31:36,32:37,34:10,36:11,37:12,38:13,39:14,40:15,41:16,42:E,44:S,46:N,47:22,52:B,53:R,55:j,56:$,58:V,60:Q,70:oe,71:ce,73:se,77:ge,89:ye,91:ke,92:Ae,93:de,94:ve},i(te,[2,26]),i(te,[2,34]),i(te,[2,35]),{28:[1,84],30:83,31:36,32:37,89:ye,91:ke,92:Ae,93:de,94:ve},{57:85,61:55,62:56,63:xe,64:De,65:he,66:Ie,67:ee,68:rt,69:me},i(te,[2,47]),{62:86,68:rt,69:me},i(jt,[2,59],{61:87,63:xe,64:De,65:he,66:Ie,67:ee}),i(At,[2,60]),i(At,[2,61]),i(At,[2,62]),i(At,[2,63]),i(At,[2,64]),i(Bt,[2,65]),i(Bt,[2,66]),{31:88,89:ye,91:ke,92:Ae,93:de},{50:89,55:cn},{54:[1,91]},{28:[1,92]},{28:[1,93]},{74:[1,94],76:[1,95]},{31:96,89:ye,91:ke,92:Ae,93:de},{28:gt,59:97},i(te,[2,55]),i(te,[2,100]),i(pe,[2,22]),i(pe,[2,23]),i(pe,[2,24]),i(Nn,[2,41],{26:98,27:[1,99]}),{16:[1,100]},{18:101,21:[1,102]},{16:[2,14]},i($,[2,18]),{24:[1,103]},i(Ot,[2,50]),{30:104,31:36,32:37,89:ye,91:ke,92:Ae,93:de,94:ve},{28:[1,106],30:105,31:36,32:37,89:ye,91:ke,92:Ae,93:de,94:ve},i(jt,[2,58],{61:107,63:xe,64:De,65:he,66:Ie,67:ee}),i(jt,[2,57]),i(te,[2,38],{49:[1,108]}),{51:[1,109]},{50:110,51:[2,44],55:cn},{30:111,31:36,32:37,89:ye,91:ke,92:Ae,93:de,94:ve},i(te,[2,67],{28:[1,112]}),i(te,[2,69],{28:[1,114],72:[1,113]}),i(te,[2,73],{28:[1,115],75:[1,116]}),i(te,[2,77],{28:[1,118],72:[1,117]}),i(te,[2,81]),i(te,[2,54]),i(Nn,[2,42]),{28:[1,119]},i(oi,[2,9]),{15:120,22:wt},{22:[2,13]},{1:[2,15]},i(Ot,[2,52]),i(Ot,[2,51]),{30:121,31:36,32:37,89:ye,91:ke,92:Ae,93:de,94:ve},i(jt,[2,56]),{50:122,55:cn},i(te,[2,39]),{51:[2,45]},i(te,[2,43]),i(te,[2,68]),i(te,[2,70]),i(te,[2,71],{72:[1,123]}),i(te,[2,74]),i(te,[2,75],{28:[1,124]}),i(te,[2,78]),i(te,[2,79],{72:[1,125]}),{29:[1,126]},{16:[1,127]},i(Ot,[2,53]),{51:[1,128]},i(te,[2,72]),i(te,[2,76]),i(te,[2,80]),i(Nn,[2,19]),i(oi,[2,10]),i(te,[2,40])],defaultActions:{2:[2,1],4:[2,3],5:[2,8],9:[2,11],44:[2,2],80:[2,14],102:[2,13],103:[2,15],110:[2,45]},parseError:function(ze,Xe){if(Xe.recoverable)this.trace(ze);else{var Lt=new Error(ze);throw Lt.hash=Xe,Lt}},parse:function(ze){var Xe=this,Lt=[0],Ge=[],Bn=[null],Oe=[],Ri=this.table,tn="",hi=0,Sr=0,Zn=2,Xn=1,ir=Oe.slice.call(arguments,1),Hn=Object.create(this.lexer),tr={yy:{}};for(var ha in this.yy)Object.prototype.hasOwnProperty.call(this.yy,ha)&&(tr.yy[ha]=this.yy[ha]);Hn.setInput(ze,tr.yy),tr.yy.lexer=Hn,tr.yy.parser=this,typeof Hn.yylloc>"u"&&(Hn.yylloc={});var Zs=Hn.yylloc;Oe.push(Zs);var ns=Hn.options&&Hn.options.ranges;typeof tr.yy.parseError=="function"?this.parseError=tr.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Hi(){var yn;return yn=Ge.pop()||Hn.lex()||Xn,typeof yn!="number"&&(yn instanceof Array&&(Ge=yn,yn=Ge.pop()),yn=Xe.symbols_[yn]||yn),yn}for(var Js,Pc,Ga,ws,Oi={},Er,br,Dr,Vn;;){if(Pc=Lt[Lt.length-1],this.defaultActions[Pc]?Ga=this.defaultActions[Pc]:((Js===null||typeof Js>"u")&&(Js=Hi()),Ga=Ri[Pc]&&Ri[Pc][Js]),typeof Ga>"u"||!Ga.length||!Ga[0]){var qi="";Vn=[];for(Er in Ri[Pc])this.terminals_[Er]&&Er>Zn&&Vn.push("'"+this.terminals_[Er]+"'");Hn.showPosition?qi="Parse error on line "+(hi+1)+`: +`+Hn.showPosition()+` +Expecting `+Vn.join(", ")+", got '"+(this.terminals_[Js]||Js)+"'":qi="Parse error on line "+(hi+1)+": Unexpected "+(Js==Xn?"end of input":"'"+(this.terminals_[Js]||Js)+"'"),this.parseError(qi,{text:Hn.match,token:this.terminals_[Js]||Js,line:Hn.yylineno,loc:Zs,expected:Vn})}if(Ga[0]instanceof Array&&Ga.length>1)throw new Error("Parse Error: multiple actions possible at state: "+Pc+", token: "+Js);switch(Ga[0]){case 1:Lt.push(Js),Bn.push(Hn.yytext),Oe.push(Hn.yylloc),Lt.push(Ga[1]),Js=null,Sr=Hn.yyleng,tn=Hn.yytext,hi=Hn.yylineno,Zs=Hn.yylloc;break;case 2:if(br=this.productions_[Ga[1]][1],Oi.$=Bn[Bn.length-br],Oi._$={first_line:Oe[Oe.length-(br||1)].first_line,last_line:Oe[Oe.length-1].last_line,first_column:Oe[Oe.length-(br||1)].first_column,last_column:Oe[Oe.length-1].last_column},ns&&(Oi._$.range=[Oe[Oe.length-(br||1)].range[0],Oe[Oe.length-1].range[1]]),ws=this.performAction.apply(Oi,[tn,Sr,hi,tr.yy,Ga[1],Bn,Oe].concat(ir)),typeof ws<"u")return ws;br&&(Lt=Lt.slice(0,-1*br*2),Bn=Bn.slice(0,-1*br),Oe=Oe.slice(0,-1*br)),Lt.push(this.productions_[Ga[1]][0]),Bn.push(Oi.$),Oe.push(Oi._$),Dr=Ri[Lt[Lt.length-2]][Lt[Lt.length-1]],Lt.push(Dr);break;case 3:return!0}}return!0}},Dt=function(){var Nt={EOF:1,parseError:function(Xe,Lt){if(this.yy.parser)this.yy.parser.parseError(Xe,Lt);else throw new Error(Xe)},setInput:function(ze,Xe){return this.yy=Xe||this.yy||{},this._input=ze,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var ze=this._input[0];this.yytext+=ze,this.yyleng++,this.offset++,this.match+=ze,this.matched+=ze;var Xe=ze.match(/(?:\r\n?|\n).*/g);return Xe?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),ze},unput:function(ze){var Xe=ze.length,Lt=ze.split(/(?:\r\n?|\n)/g);this._input=ze+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-Xe),this.offset-=Xe;var Ge=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),Lt.length-1&&(this.yylineno-=Lt.length-1);var Bn=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:Lt?(Lt.length===Ge.length?this.yylloc.first_column:0)+Ge[Ge.length-Lt.length].length-Lt[0].length:this.yylloc.first_column-Xe},this.options.ranges&&(this.yylloc.range=[Bn[0],Bn[0]+this.yyleng-Xe]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(ze){this.unput(this.match.slice(ze))},pastInput:function(){var ze=this.matched.substr(0,this.matched.length-this.match.length);return(ze.length>20?"...":"")+ze.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var ze=this.match;return ze.length<20&&(ze+=this._input.substr(0,20-ze.length)),(ze.substr(0,20)+(ze.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var ze=this.pastInput(),Xe=new Array(ze.length+1).join("-");return ze+this.upcomingInput()+` +`+Xe+"^"},test_match:function(ze,Xe){var Lt,Ge,Bn;if(this.options.backtrack_lexer&&(Bn={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(Bn.yylloc.range=this.yylloc.range.slice(0))),Ge=ze[0].match(/(?:\r\n?|\n).*/g),Ge&&(this.yylineno+=Ge.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:Ge?Ge[Ge.length-1].length-Ge[Ge.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+ze[0].length},this.yytext+=ze[0],this.match+=ze[0],this.matches=ze,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(ze[0].length),this.matched+=ze[0],Lt=this.performAction.call(this,this.yy,this,Xe,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),Lt)return Lt;if(this._backtrack){for(var Oe in Bn)this[Oe]=Bn[Oe];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var ze,Xe,Lt,Ge;this._more||(this.yytext="",this.match="");for(var Bn=this._currentRules(),Oe=0;OeXe[0].length)){if(Xe=Lt,Ge=Oe,this.options.backtrack_lexer){if(ze=this.test_match(Lt,Bn[Oe]),ze!==!1)return ze;if(this._backtrack){Xe=!1;continue}else return!1}else if(!this.options.flex)break}return Xe?(ze=this.test_match(Xe,Bn[Ge]),ze!==!1?ze:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var Xe=this.next();return Xe||this.lex()},begin:function(Xe){this.conditionStack.push(Xe)},popState:function(){var Xe=this.conditionStack.length-1;return Xe>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(Xe){return Xe=this.conditionStack.length-1-Math.abs(Xe||0),Xe>=0?this.conditionStack[Xe]:"INITIAL"},pushState:function(Xe){this.begin(Xe)},stateStackSize:function(){return this.conditionStack.length},options:{},performAction:function(Xe,Lt,Ge,Bn){switch(Ge){case 0:return this.begin("open_directive"),19;case 1:return 8;case 2:return 9;case 3:return 10;case 4:return 11;case 5:return this.begin("type_directive"),20;case 6:return this.popState(),this.begin("arg_directive"),17;case 7:return this.popState(),this.popState(),22;case 8:return 21;case 9:break;case 10:break;case 11:return this.begin("acc_title"),42;case 12:return this.popState(),"acc_title_value";case 13:return this.begin("acc_descr"),44;case 14:return this.popState(),"acc_descr_value";case 15:this.begin("acc_descr_multiline");break;case 16:this.popState();break;case 17:return"acc_descr_multiline_value";case 18:return 16;case 19:break;case 20:return 23;case 21:return 23;case 22:return this.begin("struct"),49;case 23:return"EDGE_STATE";case 24:return"EOF_IN_STRUCT";case 25:return"OPEN_IN_STRUCT";case 26:return this.popState(),51;case 27:break;case 28:return"MEMBER";case 29:return 52;case 30:return 77;case 31:return 70;case 32:return 71;case 33:return 73;case 34:return 58;case 35:return 60;case 36:return 53;case 37:return 54;case 38:this.begin("generic");break;case 39:this.popState();break;case 40:return"GENERICTYPE";case 41:this.begin("string");break;case 42:this.popState();break;case 43:return"STR";case 44:this.begin("bqstring");break;case 45:this.popState();break;case 46:return"BQUOTE_STR";case 47:this.begin("href");break;case 48:this.popState();break;case 49:return 76;case 50:this.begin("callback_name");break;case 51:this.popState();break;case 52:this.popState(),this.begin("callback_args");break;case 53:return 74;case 54:this.popState();break;case 55:return 75;case 56:return 72;case 57:return 72;case 58:return 72;case 59:return 72;case 60:return 64;case 61:return 64;case 62:return 66;case 63:return 66;case 64:return 65;case 65:return 63;case 66:return 67;case 67:return 68;case 68:return 69;case 69:return 35;case 70:return 48;case 71:return 89;case 72:return"DOT";case 73:return"PLUS";case 74:return 86;case 75:return"EQUALS";case 76:return"EQUALS";case 77:return 93;case 78:return 27;case 79:return 29;case 80:return"PUNCTUATION";case 81:return 92;case 82:return 91;case 83:return 88;case 84:return 24}},rules:[/^(?:%%\{)/,/^(?:.*direction\s+TB[^\n]*)/,/^(?:.*direction\s+BT[^\n]*)/,/^(?:.*direction\s+RL[^\n]*)/,/^(?:.*direction\s+LR[^\n]*)/,/^(?:((?:(?!\}%%)[^:.])*))/,/^(?::)/,/^(?:\}%%)/,/^(?:((?:(?!\}%%).|\n)*))/,/^(?:%%(?!\{)*[^\n]*(\r?\n?)+)/,/^(?:%%[^\n]*(\r?\n)*)/,/^(?:accTitle\s*:\s*)/,/^(?:(?!\n||)*[^\n]*)/,/^(?:accDescr\s*:\s*)/,/^(?:(?!\n||)*[^\n]*)/,/^(?:accDescr\s*\{\s*)/,/^(?:[\}])/,/^(?:[^\}]*)/,/^(?:\s*(\r?\n)+)/,/^(?:\s+)/,/^(?:classDiagram-v2\b)/,/^(?:classDiagram\b)/,/^(?:[{])/,/^(?:\[\*\])/,/^(?:$)/,/^(?:[{])/,/^(?:[}])/,/^(?:[\n])/,/^(?:[^{}\n]*)/,/^(?:class\b)/,/^(?:cssClass\b)/,/^(?:callback\b)/,/^(?:link\b)/,/^(?:click\b)/,/^(?:note for\b)/,/^(?:note\b)/,/^(?:<<)/,/^(?:>>)/,/^(?:[~])/,/^(?:[~])/,/^(?:[^~]*)/,/^(?:["])/,/^(?:["])/,/^(?:[^"]*)/,/^(?:[`])/,/^(?:[`])/,/^(?:[^`]+)/,/^(?:href[\s]+["])/,/^(?:["])/,/^(?:[^"]*)/,/^(?:call[\s]+)/,/^(?:\([\s]*\))/,/^(?:\()/,/^(?:[^(]*)/,/^(?:\))/,/^(?:[^)]*)/,/^(?:_self\b)/,/^(?:_blank\b)/,/^(?:_parent\b)/,/^(?:_top\b)/,/^(?:\s*<\|)/,/^(?:\s*\|>)/,/^(?:\s*>)/,/^(?:\s*<)/,/^(?:\s*\*)/,/^(?:\s*o\b)/,/^(?:\s*\(\))/,/^(?:--)/,/^(?:\.\.)/,/^(?::{1}[^:\n;]+)/,/^(?::{3})/,/^(?:-)/,/^(?:\.)/,/^(?:\+)/,/^(?:%)/,/^(?:=)/,/^(?:=)/,/^(?:\w+)/,/^(?:\[)/,/^(?:\])/,/^(?:[!"#$%&'*+,-.`?\\/])/,/^(?:[0-9]+)/,/^(?:[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|[\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA]|[\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE]|[\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA]|[\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0]|[\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977]|[\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2]|[\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A]|[\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39]|[\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8]|[\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C]|[\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C]|[\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99]|[\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0]|[\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D]|[\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3]|[\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10]|[\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1]|[\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81]|[\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3]|[\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6]|[\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A]|[\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081]|[\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D]|[\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0]|[\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310]|[\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C]|[\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711]|[\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7]|[\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C]|[\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16]|[\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF]|[\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC]|[\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D]|[\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D]|[\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3]|[\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F]|[\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128]|[\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184]|[\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3]|[\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6]|[\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE]|[\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C]|[\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D]|[\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC]|[\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B]|[\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788]|[\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805]|[\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB]|[\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28]|[\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5]|[\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4]|[\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E]|[\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D]|[\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36]|[\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D]|[\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC]|[\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]|[\uFFD2-\uFFD7\uFFDA-\uFFDC])/,/^(?:\s)/,/^(?:$)/],conditions:{acc_descr_multiline:{rules:[16,17],inclusive:!1},acc_descr:{rules:[14],inclusive:!1},acc_title:{rules:[12],inclusive:!1},arg_directive:{rules:[7,8],inclusive:!1},type_directive:{rules:[6,7],inclusive:!1},open_directive:{rules:[5],inclusive:!1},callback_args:{rules:[54,55],inclusive:!1},callback_name:{rules:[51,52,53],inclusive:!1},href:{rules:[48,49],inclusive:!1},struct:{rules:[23,24,25,26,27,28],inclusive:!1},generic:{rules:[39,40],inclusive:!1},bqstring:{rules:[45,46],inclusive:!1},string:{rules:[42,43],inclusive:!1},INITIAL:{rules:[0,1,2,3,4,9,10,11,13,15,18,19,20,21,22,23,29,30,31,32,33,34,35,36,37,38,41,44,47,50,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84],inclusive:!0}}};return Nt}();kt.lexer=Dt;function vt(){this.yy={}}return vt.prototype=kt,kt.Parser=vt,new vt}();oge.parser=oge;const XRe=oge,cge="classId-";let uge=[],hf={},OK=[],QRe=0,IP=[];const M5=i=>Wa.sanitizeText(i,Tt()),HHt=function(i,a,f){rd.parseDirective(this,i,a,f)},hL=function(i){let a="",f=i;if(i.indexOf("~")>0){const p=i.split("~");f=M5(p[0]),a=M5(p[1])}return{className:f,type:a}},zHt=function(i,a){a&&(a=M5(a));const{className:f}=hL(i);hf[f].label=a},lge=function(i){const a=hL(i);hf[a.className]===void 0&&(hf[a.className]={id:a.className,type:a.type,label:a.className,cssClasses:[],methods:[],members:[],annotations:[],domId:cge+a.className+"-"+QRe},QRe++)},ZRe=function(i){if(i in hf)return hf[i].domId;throw new Error("Class not found: "+i)},GHt=function(){uge=[],hf={},OK=[],IP=[],IP.push(eFe),rp()},qHt=function(i){return hf[i]},VHt=function(){return hf},UHt=function(){return uge},WHt=function(){return OK},KHt=function(i){Fe.debug("Adding relation: "+JSON.stringify(i)),lge(i.id1),lge(i.id2),i.id1=hL(i.id1).className,i.id2=hL(i.id2).className,i.relationTitle1=Wa.sanitizeText(i.relationTitle1.trim(),Tt()),i.relationTitle2=Wa.sanitizeText(i.relationTitle2.trim(),Tt()),uge.push(i)},YHt=function(i,a){const f=hL(i).className;hf[f].annotations.push(a)},JRe=function(i,a){const f=hL(i).className,p=hf[f];if(typeof a=="string"){const w=a.trim();w.startsWith("<<")&&w.endsWith(">>")?p.annotations.push(M5(w.substring(2,w.length-2))):w.indexOf(")")>0?p.methods.push(M5(w)):w&&p.members.push(M5(w))}},XHt=function(i,a){Array.isArray(a)&&(a.reverse(),a.forEach(f=>JRe(i,f)))},QHt=function(i,a){const f={id:`note${OK.length}`,class:a,text:i};OK.push(f)},ZHt=function(i){return i.startsWith(":")&&(i=i.substring(1)),M5(i.trim())},hge=function(i,a){i.split(",").forEach(function(f){let p=f;f[0].match(/\d/)&&(p=cge+p),hf[p]!==void 0&&hf[p].cssClasses.push(a)})},JHt=function(i,a){i.split(",").forEach(function(f){a!==void 0&&(hf[f].tooltip=M5(a))})},ezt=function(i){return hf[i].tooltip},tzt=function(i,a,f){const p=Tt();i.split(",").forEach(function(w){let y=w;w[0].match(/\d/)&&(y=cge+y),hf[y]!==void 0&&(hf[y].link=co.formatUrl(a,p),p.securityLevel==="sandbox"?hf[y].linkTarget="_top":typeof f=="string"?hf[y].linkTarget=M5(f):hf[y].linkTarget="_blank")}),hge(i,"clickable")},nzt=function(i,a,f){i.split(",").forEach(function(p){rzt(p,a,f),hf[p].haveCallback=!0}),hge(i,"clickable")},rzt=function(i,a,f){if(Tt().securityLevel!=="loose"||a===void 0)return;const w=i;if(hf[w]!==void 0){const y=ZRe(w);let b=[];if(typeof f=="string"){b=f.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);for(let E=0;E")),w.classed("hover",!0)}).on("mouseout",function(){a.transition().duration(500).style("opacity",0),Cr(this).classed("hover",!1)})};IP.push(eFe);let tFe="TB";const NK={parseDirective:HHt,setAccTitle:ip,getAccTitle:L2,getAccDescription:D2,setAccDescription:M2,getConfig:()=>Tt().class,addClass:lge,bindFunctions:izt,clear:GHt,getClass:qHt,getClasses:VHt,getNotes:WHt,addAnnotation:YHt,addNote:QHt,getRelations:UHt,addRelation:KHt,getDirection:()=>tFe,setDirection:i=>{tFe=i},addMember:JRe,addMembers:XHt,cleanupLabel:ZHt,lineType:szt,relationType:azt,setClickEvent:nzt,setCssClass:hge,setLink:tzt,getTooltip:ezt,setTooltip:JHt,lookUpDomId:ZRe,setDiagramTitle:Uw,getDiagramTitle:Ww,setClassLabel:zHt},nFe=i=>`g.classGroup text { + fill: ${i.nodeBorder}; + fill: ${i.classText}; + stroke: none; + font-family: ${i.fontFamily}; + font-size: 10px; + + .title { + font-weight: bolder; + } + +} + +.nodeLabel, .edgeLabel { + color: ${i.classText}; +} +.edgeLabel .label rect { + fill: ${i.mainBkg}; +} +.label text { + fill: ${i.classText}; +} +.edgeLabel .label span { + background: ${i.mainBkg}; +} + +.classTitle { + font-weight: bolder; +} +.node rect, + .node circle, + .node ellipse, + .node polygon, + .node path { + fill: ${i.mainBkg}; + stroke: ${i.nodeBorder}; + stroke-width: 1px; + } + + +.divider { + stroke: ${i.nodeBorder}; + stroke-width: 1; +} + +g.clickable { + cursor: pointer; +} + +g.classGroup rect { + fill: ${i.mainBkg}; + stroke: ${i.nodeBorder}; +} + +g.classGroup line { + stroke: ${i.nodeBorder}; + stroke-width: 1; +} + +.classLabel .box { + stroke: none; + stroke-width: 0; + fill: ${i.mainBkg}; + opacity: 0.5; +} + +.classLabel .label { + fill: ${i.nodeBorder}; + font-size: 10px; +} + +.relation { + stroke: ${i.lineColor}; + stroke-width: 1; + fill: none; +} + +.dashed-line{ + stroke-dasharray: 3; +} + +.dotted-line{ + stroke-dasharray: 1 2; +} + +#compositionStart, .composition { + fill: ${i.lineColor} !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; +} + +#compositionEnd, .composition { + fill: ${i.lineColor} !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; +} + +#dependencyStart, .dependency { + fill: ${i.lineColor} !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; +} + +#dependencyStart, .dependency { + fill: ${i.lineColor} !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; +} + +#extensionStart, .extension { + fill: ${i.mainBkg} !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; +} + +#extensionEnd, .extension { + fill: ${i.mainBkg} !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; +} + +#aggregationStart, .aggregation { + fill: ${i.mainBkg} !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; +} + +#aggregationEnd, .aggregation { + fill: ${i.mainBkg} !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; +} + +#lollipopStart, .lollipop { + fill: ${i.mainBkg} !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; +} + +#lollipopEnd, .lollipop { + fill: ${i.mainBkg} !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; +} + +.edgeTerminals { + font-size: 11px; +} + +.classTitleText { + text-anchor: middle; + font-size: 18px; + fill: ${i.textColor}; +} +`;let PK={};const BK=20,OP=function(i){const a=Object.entries(PK).find(f=>f[1].label===i);if(a)return a[0]},ozt=function(i){i.append("defs").append("marker").attr("id","extensionStart").attr("class","extension").attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 1,7 L18,13 V 1 Z"),i.append("defs").append("marker").attr("id","extensionEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 1,1 V 13 L18,7 Z"),i.append("defs").append("marker").attr("id","compositionStart").attr("class","extension").attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id","compositionEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id","aggregationStart").attr("class","extension").attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id","aggregationEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id","dependencyStart").attr("class","extension").attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 5,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id","dependencyEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L14,7 L9,1 Z")},czt=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:XRe,db:NK,renderer:{draw:function(i,a,f,p){const w=Tt().class;PK={},Fe.info("Rendering diagram "+i);const y=Tt().securityLevel;let b;y==="sandbox"&&(b=Cr("#i"+a));const E=Cr(y==="sandbox"?b.nodes()[0].contentDocument.body:"body"),S=E.select(`[id='${a}']`);ozt(S);const N=new zf({multigraph:!0});N.setGraph({isMultiGraph:!0}),N.setDefaultEdgeLabel(function(){return{}});const B=p.db.getClasses(),R=Object.keys(B);for(const se of R){const ge=B[se],ye=_0e.drawClass(S,ge,w,p);PK[ye.id]=ye,N.setNode(ye.id,ye),Fe.info("Org height: "+ye.height)}p.db.getRelations().forEach(function(se){Fe.info("tjoho"+OP(se.id1)+OP(se.id2)+JSON.stringify(se)),N.setEdge(OP(se.id1),OP(se.id2),{relation:se},se.title||"DEFAULT")}),p.db.getNotes().forEach(function(se){Fe.debug(`Adding note: ${JSON.stringify(se)}`);const ge=_0e.drawNote(S,se,w,p);PK[ge.id]=ge,N.setNode(ge.id,ge),se.class&&se.class in B&&N.setEdge(se.id,OP(se.class),{relation:{id1:se.id,id2:se.class,relation:{type1:"none",type2:"none",lineType:10}}},"DEFAULT")}),tL(N),N.nodes().forEach(function(se){se!==void 0&&N.node(se)!==void 0&&(Fe.debug("Node "+se+": "+JSON.stringify(N.node(se))),E.select("#"+(p.db.lookUpDomId(se)||se)).attr("transform","translate("+(N.node(se).x-N.node(se).width/2)+","+(N.node(se).y-N.node(se).height/2)+" )"))}),N.edges().forEach(function(se){se!==void 0&&N.edge(se)!==void 0&&(Fe.debug("Edge "+se.v+" -> "+se.w+": "+JSON.stringify(N.edge(se))),_0e.drawEdge(S,N.edge(se),N.edge(se).relation,w,p))});const V=S.node().getBBox(),Q=V.width+BK*2,oe=V.height+BK*2;Vw(S,oe,Q,w.useMaxWidth);const ce=`${V.x-BK} ${V.y-BK} ${Q} ${oe}`;Fe.debug(`viewBox ${ce}`),S.attr("viewBox",ce)}},styles:nFe,init:i=>{i.class||(i.class={}),i.class.arrowMarkerAbsolute=i.arrowMarkerAbsolute,NK.clear()}}},Symbol.toStringTag,{value:"Module"})),rFe=i=>Wa.sanitizeText(i,Tt());let fge={dividerMargin:10,padding:5,textHeight:10,curve:void 0};const uzt=function(i,a,f,p){const w=Object.keys(i);Fe.info("keys:",w),Fe.info(i),w.forEach(function(y){var $,V;const b=i[y];let E="";b.cssClasses.length>0&&(E=E+" "+b.cssClasses.join(" "));const S={labelStyle:"",style:""},N=b.label??b.id,B=0,R="class_box",j={labelStyle:S.labelStyle,shape:R,labelText:rFe(N),classData:b,rx:B,ry:B,class:E,style:S.style,id:b.id,domId:b.domId,tooltip:p.db.getTooltip(b.id)||"",haveCallback:b.haveCallback,link:b.link,width:b.type==="group"?500:void 0,type:b.type,padding:(($=Tt().flowchart)==null?void 0:$.padding)??((V=Tt().class)==null?void 0:V.padding)};a.setNode(b.id,j),Fe.info("setNode",j)})},lzt=function(i,a,f,p){Fe.info(i),i.forEach(function(w,y){var Q,oe;const b=w,E="",S={labelStyle:"",style:""},N=b.text,B=0,R="note",j={labelStyle:S.labelStyle,shape:R,labelText:rFe(N),noteData:b,rx:B,ry:B,class:E,style:S.style,id:b.id,domId:b.id,tooltip:"",type:"note",padding:((Q=Tt().flowchart)==null?void 0:Q.padding)??((oe=Tt().class)==null?void 0:oe.padding)};if(a.setNode(b.id,j),Fe.info("setNode",j),!b.class||!(b.class in p))return;const $=f+y,V={id:`edgeNote${$}`,classes:"relation",pattern:"dotted",arrowhead:"none",startLabelRight:"",endLabelLeft:"",arrowTypeStart:"none",arrowTypeEnd:"none",style:"fill:none",labelStyle:"",curve:Ub(fge.curve,ng)};a.setEdge(b.id,b.class,V,$)})},hzt=function(i,a){const f=Tt().flowchart;let p=0;i.forEach(function(w){var b;p++;const y={classes:"relation",pattern:w.relation.lineType==1?"dashed":"solid",id:"id"+p,arrowhead:w.type==="arrow_open"?"none":"normal",startLabelRight:w.relationTitle1==="none"?"":w.relationTitle1,endLabelLeft:w.relationTitle2==="none"?"":w.relationTitle2,arrowTypeStart:iFe(w.relation.type1),arrowTypeEnd:iFe(w.relation.type2),style:"fill:none",labelStyle:"",curve:Ub(f==null?void 0:f.curve,ng)};if(Fe.info(y,w),w.style!==void 0){const E=Yw(w.style);y.style=E.style,y.labelStyle=E.labelStyle}w.text=w.title,w.text===void 0?w.style!==void 0&&(y.arrowheadStyle="fill: #333"):(y.arrowheadStyle="fill: #333",y.labelpos="c",((b=Tt().flowchart)==null?void 0:b.htmlLabels)??Tt().htmlLabels?(y.labelType="html",y.label=''+w.text+""):(y.labelType="text",y.label=w.text.replace(Wa.lineBreakRegex,` +`),w.style===void 0&&(y.style=y.style||"stroke: #333; stroke-width: 1.5px;fill:none"),y.labelStyle=y.labelStyle.replace("color:","fill:"))),a.setEdge(w.id1,w.id2,y,p)})},fzt=function(i){fge={...fge,...i}},dzt=async function(i,a,f,p){Fe.info("Drawing class - ",a);const w=Tt().flowchart??Tt().class,y=Tt().securityLevel;Fe.info("config:",w);const b=(w==null?void 0:w.nodeSpacing)??50,E=(w==null?void 0:w.rankSpacing)??50,S=new zf({multigraph:!0,compound:!0}).setGraph({rankdir:p.db.getDirection(),nodesep:b,ranksep:E,marginx:8,marginy:8}).setDefaultEdgeLabel(function(){return{}}),N=p.db.getClasses(),B=p.db.getRelations(),R=p.db.getNotes();Fe.info(B),uzt(N,S,a,p),hzt(B,S),lzt(R,S,B.length+1,N);let j;y==="sandbox"&&(j=Cr("#i"+a));const $=Cr(y==="sandbox"?j.nodes()[0].contentDocument.body:"body"),V=$.select(`[id="${a}"]`),Q=$.select("#"+a+" g");if(await C0e(Q,S,["aggregation","extension","composition","dependency","lollipop"],"classDiagram",a),co.insertTitle(V,"classTitleText",(w==null?void 0:w.titleTopMargin)??5,p.db.getDiagramTitle()),YE(S,V,w==null?void 0:w.diagramPadding,w==null?void 0:w.useMaxWidth),!(w!=null&&w.htmlLabels)){const oe=y==="sandbox"?j.nodes()[0].contentDocument:document,ce=oe.querySelectorAll('[id="'+a+'"] .edgeLabel .label');for(const se of ce){const ge=se.getBBox(),ye=oe.createElementNS("http://www.w3.org/2000/svg","rect");ye.setAttribute("rx",0),ye.setAttribute("ry",0),ye.setAttribute("width",ge.width),ye.setAttribute("height",ge.height),se.insertBefore(ye,se.firstChild)}}};function iFe(i){let a;switch(i){case 0:a="aggregation";break;case 1:a="extension";break;case 2:a="composition";break;case 3:a="dependency";break;case 4:a="lollipop";break;default:a="none"}return a}const gzt=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:XRe,db:NK,renderer:{setConf:fzt,draw:dzt},styles:nFe,init:i=>{i.class||(i.class={}),i.class.arrowMarkerAbsolute=i.arrowMarkerAbsolute,NK.clear()}}},Symbol.toStringTag,{value:"Module"}));var dge=function(){var i=function(wt,jt,At,Bt){for(At=At||{},Bt=wt.length;Bt--;At[wt[Bt]]=jt);return At},a=[1,2],f=[1,3],p=[1,5],w=[1,7],y=[2,5],b=[1,15],E=[1,17],S=[1,21],N=[1,22],B=[1,23],R=[1,24],j=[1,37],$=[1,25],V=[1,26],Q=[1,27],oe=[1,28],ce=[1,29],se=[1,32],ge=[1,33],ye=[1,34],ke=[1,35],Ae=[1,36],de=[1,39],ve=[1,40],te=[1,41],xe=[1,42],De=[1,38],he=[1,45],Ie=[1,4,5,16,17,19,21,22,24,25,26,27,28,29,33,35,37,38,42,50,51,52,53,56,60],ee=[1,4,5,14,15,16,17,19,21,22,24,25,26,27,28,29,33,35,37,38,42,50,51,52,53,56,60],rt=[1,4,5,7,16,17,19,21,22,24,25,26,27,28,29,33,35,37,38,42,50,51,52,53,56,60],me=[4,5,16,17,19,21,22,24,25,26,27,28,29,33,35,37,38,42,50,51,52,53,56,60],gt={trace:function(){},yy:{},symbols_:{error:2,start:3,SPACE:4,NL:5,directive:6,SD:7,document:8,line:9,statement:10,classDefStatement:11,cssClassStatement:12,idStatement:13,DESCR:14,"-->":15,HIDE_EMPTY:16,scale:17,WIDTH:18,COMPOSIT_STATE:19,STRUCT_START:20,STRUCT_STOP:21,STATE_DESCR:22,AS:23,ID:24,FORK:25,JOIN:26,CHOICE:27,CONCURRENT:28,note:29,notePosition:30,NOTE_TEXT:31,direction:32,acc_title:33,acc_title_value:34,acc_descr:35,acc_descr_value:36,acc_descr_multiline_value:37,classDef:38,CLASSDEF_ID:39,CLASSDEF_STYLEOPTS:40,DEFAULT:41,class:42,CLASSENTITY_IDS:43,STYLECLASS:44,openDirective:45,typeDirective:46,closeDirective:47,":":48,argDirective:49,direction_tb:50,direction_bt:51,direction_rl:52,direction_lr:53,eol:54,";":55,EDGE_STATE:56,STYLE_SEPARATOR:57,left_of:58,right_of:59,open_directive:60,type_directive:61,arg_directive:62,close_directive:63,$accept:0,$end:1},terminals_:{2:"error",4:"SPACE",5:"NL",7:"SD",14:"DESCR",15:"-->",16:"HIDE_EMPTY",17:"scale",18:"WIDTH",19:"COMPOSIT_STATE",20:"STRUCT_START",21:"STRUCT_STOP",22:"STATE_DESCR",23:"AS",24:"ID",25:"FORK",26:"JOIN",27:"CHOICE",28:"CONCURRENT",29:"note",31:"NOTE_TEXT",33:"acc_title",34:"acc_title_value",35:"acc_descr",36:"acc_descr_value",37:"acc_descr_multiline_value",38:"classDef",39:"CLASSDEF_ID",40:"CLASSDEF_STYLEOPTS",41:"DEFAULT",42:"class",43:"CLASSENTITY_IDS",44:"STYLECLASS",48:":",50:"direction_tb",51:"direction_bt",52:"direction_rl",53:"direction_lr",55:";",56:"EDGE_STATE",57:"STYLE_SEPARATOR",58:"left_of",59:"right_of",60:"open_directive",61:"type_directive",62:"arg_directive",63:"close_directive"},productions_:[0,[3,2],[3,2],[3,2],[3,2],[8,0],[8,2],[9,2],[9,1],[9,1],[10,1],[10,1],[10,1],[10,2],[10,3],[10,4],[10,1],[10,2],[10,1],[10,4],[10,3],[10,6],[10,1],[10,1],[10,1],[10,1],[10,4],[10,4],[10,1],[10,1],[10,2],[10,2],[10,1],[11,3],[11,3],[12,3],[6,3],[6,5],[32,1],[32,1],[32,1],[32,1],[54,1],[54,1],[13,1],[13,1],[13,3],[13,3],[30,1],[30,1],[45,1],[46,1],[49,1],[47,1]],performAction:function(jt,At,Bt,cn,Nn,Ot,oi){var kt=Ot.length-1;switch(Nn){case 4:return cn.setRootDoc(Ot[kt]),Ot[kt];case 5:this.$=[];break;case 6:Ot[kt]!="nl"&&(Ot[kt-1].push(Ot[kt]),this.$=Ot[kt-1]);break;case 7:case 8:this.$=Ot[kt];break;case 9:this.$="nl";break;case 12:this.$=Ot[kt];break;case 13:const ze=Ot[kt-1];ze.description=cn.trimColon(Ot[kt]),this.$=ze;break;case 14:this.$={stmt:"relation",state1:Ot[kt-2],state2:Ot[kt]};break;case 15:const Xe=cn.trimColon(Ot[kt]);this.$={stmt:"relation",state1:Ot[kt-3],state2:Ot[kt-1],description:Xe};break;case 19:this.$={stmt:"state",id:Ot[kt-3],type:"default",description:"",doc:Ot[kt-1]};break;case 20:var Dt=Ot[kt],vt=Ot[kt-2].trim();if(Ot[kt].match(":")){var Nt=Ot[kt].split(":");Dt=Nt[0],vt=[vt,Nt[1]]}this.$={stmt:"state",id:Dt,type:"default",description:vt};break;case 21:this.$={stmt:"state",id:Ot[kt-3],type:"default",description:Ot[kt-5],doc:Ot[kt-1]};break;case 22:this.$={stmt:"state",id:Ot[kt],type:"fork"};break;case 23:this.$={stmt:"state",id:Ot[kt],type:"join"};break;case 24:this.$={stmt:"state",id:Ot[kt],type:"choice"};break;case 25:this.$={stmt:"state",id:cn.getDividerId(),type:"divider"};break;case 26:this.$={stmt:"state",id:Ot[kt-1].trim(),note:{position:Ot[kt-2].trim(),text:Ot[kt].trim()}};break;case 30:this.$=Ot[kt].trim(),cn.setAccTitle(this.$);break;case 31:case 32:this.$=Ot[kt].trim(),cn.setAccDescription(this.$);break;case 33:case 34:this.$={stmt:"classDef",id:Ot[kt-1].trim(),classes:Ot[kt].trim()};break;case 35:this.$={stmt:"applyClass",id:Ot[kt-1].trim(),styleClass:Ot[kt].trim()};break;case 38:cn.setDirection("TB"),this.$={stmt:"dir",value:"TB"};break;case 39:cn.setDirection("BT"),this.$={stmt:"dir",value:"BT"};break;case 40:cn.setDirection("RL"),this.$={stmt:"dir",value:"RL"};break;case 41:cn.setDirection("LR"),this.$={stmt:"dir",value:"LR"};break;case 44:case 45:this.$={stmt:"state",id:Ot[kt].trim(),type:"default",description:""};break;case 46:this.$={stmt:"state",id:Ot[kt-2].trim(),classes:[Ot[kt].trim()],type:"default",description:""};break;case 47:this.$={stmt:"state",id:Ot[kt-2].trim(),classes:[Ot[kt].trim()],type:"default",description:""};break;case 50:cn.parseDirective("%%{","open_directive");break;case 51:cn.parseDirective(Ot[kt],"type_directive");break;case 52:Ot[kt]=Ot[kt].trim().replace(/'/g,'"'),cn.parseDirective(Ot[kt],"arg_directive");break;case 53:cn.parseDirective("}%%","close_directive","state");break}},table:[{3:1,4:a,5:f,6:4,7:p,45:6,60:w},{1:[3]},{3:8,4:a,5:f,6:4,7:p,45:6,60:w},{3:9,4:a,5:f,6:4,7:p,45:6,60:w},{3:10,4:a,5:f,6:4,7:p,45:6,60:w},i([1,4,5,16,17,19,22,24,25,26,27,28,29,33,35,37,38,42,50,51,52,53,56,60],y,{8:11}),{46:12,61:[1,13]},{61:[2,50]},{1:[2,1]},{1:[2,2]},{1:[2,3]},{1:[2,4],4:b,5:E,6:30,9:14,10:16,11:18,12:19,13:20,16:S,17:N,19:B,22:R,24:j,25:$,26:V,27:Q,28:oe,29:ce,32:31,33:se,35:ge,37:ye,38:ke,42:Ae,45:6,50:de,51:ve,52:te,53:xe,56:De,60:w},{47:43,48:[1,44],63:he},i([48,63],[2,51]),i(Ie,[2,6]),{6:30,10:46,11:18,12:19,13:20,16:S,17:N,19:B,22:R,24:j,25:$,26:V,27:Q,28:oe,29:ce,32:31,33:se,35:ge,37:ye,38:ke,42:Ae,45:6,50:de,51:ve,52:te,53:xe,56:De,60:w},i(Ie,[2,8]),i(Ie,[2,9]),i(Ie,[2,10]),i(Ie,[2,11]),i(Ie,[2,12],{14:[1,47],15:[1,48]}),i(Ie,[2,16]),{18:[1,49]},i(Ie,[2,18],{20:[1,50]}),{23:[1,51]},i(Ie,[2,22]),i(Ie,[2,23]),i(Ie,[2,24]),i(Ie,[2,25]),{30:52,31:[1,53],58:[1,54],59:[1,55]},i(Ie,[2,28]),i(Ie,[2,29]),{34:[1,56]},{36:[1,57]},i(Ie,[2,32]),{39:[1,58],41:[1,59]},{43:[1,60]},i(ee,[2,44],{57:[1,61]}),i(ee,[2,45],{57:[1,62]}),i(Ie,[2,38]),i(Ie,[2,39]),i(Ie,[2,40]),i(Ie,[2,41]),i(rt,[2,36]),{49:63,62:[1,64]},i(rt,[2,53]),i(Ie,[2,7]),i(Ie,[2,13]),{13:65,24:j,56:De},i(Ie,[2,17]),i(me,y,{8:66}),{24:[1,67]},{24:[1,68]},{23:[1,69]},{24:[2,48]},{24:[2,49]},i(Ie,[2,30]),i(Ie,[2,31]),{40:[1,70]},{40:[1,71]},{44:[1,72]},{24:[1,73]},{24:[1,74]},{47:75,63:he},{63:[2,52]},i(Ie,[2,14],{14:[1,76]}),{4:b,5:E,6:30,9:14,10:16,11:18,12:19,13:20,16:S,17:N,19:B,21:[1,77],22:R,24:j,25:$,26:V,27:Q,28:oe,29:ce,32:31,33:se,35:ge,37:ye,38:ke,42:Ae,45:6,50:de,51:ve,52:te,53:xe,56:De,60:w},i(Ie,[2,20],{20:[1,78]}),{31:[1,79]},{24:[1,80]},i(Ie,[2,33]),i(Ie,[2,34]),i(Ie,[2,35]),i(ee,[2,46]),i(ee,[2,47]),i(rt,[2,37]),i(Ie,[2,15]),i(Ie,[2,19]),i(me,y,{8:81}),i(Ie,[2,26]),i(Ie,[2,27]),{4:b,5:E,6:30,9:14,10:16,11:18,12:19,13:20,16:S,17:N,19:B,21:[1,82],22:R,24:j,25:$,26:V,27:Q,28:oe,29:ce,32:31,33:se,35:ge,37:ye,38:ke,42:Ae,45:6,50:de,51:ve,52:te,53:xe,56:De,60:w},i(Ie,[2,21])],defaultActions:{7:[2,50],8:[2,1],9:[2,2],10:[2,3],54:[2,48],55:[2,49],64:[2,52]},parseError:function(jt,At){if(At.recoverable)this.trace(jt);else{var Bt=new Error(jt);throw Bt.hash=At,Bt}},parse:function(jt){var At=this,Bt=[0],cn=[],Nn=[null],Ot=[],oi=this.table,kt="",Dt=0,vt=0,Nt=2,ze=1,Xe=Ot.slice.call(arguments,1),Lt=Object.create(this.lexer),Ge={yy:{}};for(var Bn in this.yy)Object.prototype.hasOwnProperty.call(this.yy,Bn)&&(Ge.yy[Bn]=this.yy[Bn]);Lt.setInput(jt,Ge.yy),Ge.yy.lexer=Lt,Ge.yy.parser=this,typeof Lt.yylloc>"u"&&(Lt.yylloc={});var Oe=Lt.yylloc;Ot.push(Oe);var Ri=Lt.options&&Lt.options.ranges;typeof Ge.yy.parseError=="function"?this.parseError=Ge.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function tn(){var Hi;return Hi=cn.pop()||Lt.lex()||ze,typeof Hi!="number"&&(Hi instanceof Array&&(cn=Hi,Hi=cn.pop()),Hi=At.symbols_[Hi]||Hi),Hi}for(var hi,Sr,Zn,Xn,ir={},Hn,tr,ha,Zs;;){if(Sr=Bt[Bt.length-1],this.defaultActions[Sr]?Zn=this.defaultActions[Sr]:((hi===null||typeof hi>"u")&&(hi=tn()),Zn=oi[Sr]&&oi[Sr][hi]),typeof Zn>"u"||!Zn.length||!Zn[0]){var ns="";Zs=[];for(Hn in oi[Sr])this.terminals_[Hn]&&Hn>Nt&&Zs.push("'"+this.terminals_[Hn]+"'");Lt.showPosition?ns="Parse error on line "+(Dt+1)+`: +`+Lt.showPosition()+` +Expecting `+Zs.join(", ")+", got '"+(this.terminals_[hi]||hi)+"'":ns="Parse error on line "+(Dt+1)+": Unexpected "+(hi==ze?"end of input":"'"+(this.terminals_[hi]||hi)+"'"),this.parseError(ns,{text:Lt.match,token:this.terminals_[hi]||hi,line:Lt.yylineno,loc:Oe,expected:Zs})}if(Zn[0]instanceof Array&&Zn.length>1)throw new Error("Parse Error: multiple actions possible at state: "+Sr+", token: "+hi);switch(Zn[0]){case 1:Bt.push(hi),Nn.push(Lt.yytext),Ot.push(Lt.yylloc),Bt.push(Zn[1]),hi=null,vt=Lt.yyleng,kt=Lt.yytext,Dt=Lt.yylineno,Oe=Lt.yylloc;break;case 2:if(tr=this.productions_[Zn[1]][1],ir.$=Nn[Nn.length-tr],ir._$={first_line:Ot[Ot.length-(tr||1)].first_line,last_line:Ot[Ot.length-1].last_line,first_column:Ot[Ot.length-(tr||1)].first_column,last_column:Ot[Ot.length-1].last_column},Ri&&(ir._$.range=[Ot[Ot.length-(tr||1)].range[0],Ot[Ot.length-1].range[1]]),Xn=this.performAction.apply(ir,[kt,vt,Dt,Ge.yy,Zn[1],Nn,Ot].concat(Xe)),typeof Xn<"u")return Xn;tr&&(Bt=Bt.slice(0,-1*tr*2),Nn=Nn.slice(0,-1*tr),Ot=Ot.slice(0,-1*tr)),Bt.push(this.productions_[Zn[1]][0]),Nn.push(ir.$),Ot.push(ir._$),ha=oi[Bt[Bt.length-2]][Bt[Bt.length-1]],Bt.push(ha);break;case 3:return!0}}return!0}},pe=function(){var wt={EOF:1,parseError:function(At,Bt){if(this.yy.parser)this.yy.parser.parseError(At,Bt);else throw new Error(At)},setInput:function(jt,At){return this.yy=At||this.yy||{},this._input=jt,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var jt=this._input[0];this.yytext+=jt,this.yyleng++,this.offset++,this.match+=jt,this.matched+=jt;var At=jt.match(/(?:\r\n?|\n).*/g);return At?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),jt},unput:function(jt){var At=jt.length,Bt=jt.split(/(?:\r\n?|\n)/g);this._input=jt+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-At),this.offset-=At;var cn=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),Bt.length-1&&(this.yylineno-=Bt.length-1);var Nn=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:Bt?(Bt.length===cn.length?this.yylloc.first_column:0)+cn[cn.length-Bt.length].length-Bt[0].length:this.yylloc.first_column-At},this.options.ranges&&(this.yylloc.range=[Nn[0],Nn[0]+this.yyleng-At]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(jt){this.unput(this.match.slice(jt))},pastInput:function(){var jt=this.matched.substr(0,this.matched.length-this.match.length);return(jt.length>20?"...":"")+jt.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var jt=this.match;return jt.length<20&&(jt+=this._input.substr(0,20-jt.length)),(jt.substr(0,20)+(jt.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var jt=this.pastInput(),At=new Array(jt.length+1).join("-");return jt+this.upcomingInput()+` +`+At+"^"},test_match:function(jt,At){var Bt,cn,Nn;if(this.options.backtrack_lexer&&(Nn={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(Nn.yylloc.range=this.yylloc.range.slice(0))),cn=jt[0].match(/(?:\r\n?|\n).*/g),cn&&(this.yylineno+=cn.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:cn?cn[cn.length-1].length-cn[cn.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+jt[0].length},this.yytext+=jt[0],this.match+=jt[0],this.matches=jt,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(jt[0].length),this.matched+=jt[0],Bt=this.performAction.call(this,this.yy,this,At,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),Bt)return Bt;if(this._backtrack){for(var Ot in Nn)this[Ot]=Nn[Ot];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var jt,At,Bt,cn;this._more||(this.yytext="",this.match="");for(var Nn=this._currentRules(),Ot=0;OtAt[0].length)){if(At=Bt,cn=Ot,this.options.backtrack_lexer){if(jt=this.test_match(Bt,Nn[Ot]),jt!==!1)return jt;if(this._backtrack){At=!1;continue}else return!1}else if(!this.options.flex)break}return At?(jt=this.test_match(At,Nn[cn]),jt!==!1?jt:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var At=this.next();return At||this.lex()},begin:function(At){this.conditionStack.push(At)},popState:function(){var At=this.conditionStack.length-1;return At>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(At){return At=this.conditionStack.length-1-Math.abs(At||0),At>=0?this.conditionStack[At]:"INITIAL"},pushState:function(At){this.begin(At)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(At,Bt,cn,Nn){switch(cn){case 0:return 41;case 1:return 50;case 2:return 51;case 3:return 52;case 4:return 53;case 5:return this.begin("open_directive"),60;case 6:return this.begin("type_directive"),61;case 7:return this.popState(),this.begin("arg_directive"),48;case 8:return this.popState(),this.popState(),63;case 9:return 62;case 10:break;case 11:break;case 12:return 5;case 13:break;case 14:break;case 15:break;case 16:break;case 17:return this.pushState("SCALE"),17;case 18:return 18;case 19:this.popState();break;case 20:return this.begin("acc_title"),33;case 21:return this.popState(),"acc_title_value";case 22:return this.begin("acc_descr"),35;case 23:return this.popState(),"acc_descr_value";case 24:this.begin("acc_descr_multiline");break;case 25:this.popState();break;case 26:return"acc_descr_multiline_value";case 27:return this.pushState("CLASSDEF"),38;case 28:return this.popState(),this.pushState("CLASSDEFID"),"DEFAULT_CLASSDEF_ID";case 29:return this.popState(),this.pushState("CLASSDEFID"),39;case 30:return this.popState(),40;case 31:return this.pushState("CLASS"),42;case 32:return this.popState(),this.pushState("CLASS_STYLE"),43;case 33:return this.popState(),44;case 34:return this.pushState("SCALE"),17;case 35:return 18;case 36:this.popState();break;case 37:this.pushState("STATE");break;case 38:return this.popState(),Bt.yytext=Bt.yytext.slice(0,-8).trim(),25;case 39:return this.popState(),Bt.yytext=Bt.yytext.slice(0,-8).trim(),26;case 40:return this.popState(),Bt.yytext=Bt.yytext.slice(0,-10).trim(),27;case 41:return this.popState(),Bt.yytext=Bt.yytext.slice(0,-8).trim(),25;case 42:return this.popState(),Bt.yytext=Bt.yytext.slice(0,-8).trim(),26;case 43:return this.popState(),Bt.yytext=Bt.yytext.slice(0,-10).trim(),27;case 44:return 50;case 45:return 51;case 46:return 52;case 47:return 53;case 48:this.pushState("STATE_STRING");break;case 49:return this.pushState("STATE_ID"),"AS";case 50:return this.popState(),"ID";case 51:this.popState();break;case 52:return"STATE_DESCR";case 53:return 19;case 54:this.popState();break;case 55:return this.popState(),this.pushState("struct"),20;case 56:break;case 57:return this.popState(),21;case 58:break;case 59:return this.begin("NOTE"),29;case 60:return this.popState(),this.pushState("NOTE_ID"),58;case 61:return this.popState(),this.pushState("NOTE_ID"),59;case 62:this.popState(),this.pushState("FLOATING_NOTE");break;case 63:return this.popState(),this.pushState("FLOATING_NOTE_ID"),"AS";case 64:break;case 65:return"NOTE_TEXT";case 66:return this.popState(),"ID";case 67:return this.popState(),this.pushState("NOTE_TEXT"),24;case 68:return this.popState(),Bt.yytext=Bt.yytext.substr(2).trim(),31;case 69:return this.popState(),Bt.yytext=Bt.yytext.slice(0,-8).trim(),31;case 70:return 7;case 71:return 7;case 72:return 16;case 73:return 56;case 74:return 24;case 75:return Bt.yytext=Bt.yytext.trim(),14;case 76:return 15;case 77:return 28;case 78:return 57;case 79:return 5;case 80:return"INVALID"}},rules:[/^(?:default\b)/i,/^(?:.*direction\s+TB[^\n]*)/i,/^(?:.*direction\s+BT[^\n]*)/i,/^(?:.*direction\s+RL[^\n]*)/i,/^(?:.*direction\s+LR[^\n]*)/i,/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:%%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n]+)/i,/^(?:[\s]+)/i,/^(?:((?!\n)\s)+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:scale\s+)/i,/^(?:\d+)/i,/^(?:\s+width\b)/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:classDef\s+)/i,/^(?:DEFAULT\s+)/i,/^(?:\w+\s+)/i,/^(?:[^\n]*)/i,/^(?:class\s+)/i,/^(?:(\w+)+((,\s*\w+)*))/i,/^(?:[^\n]*)/i,/^(?:scale\s+)/i,/^(?:\d+)/i,/^(?:\s+width\b)/i,/^(?:state\s+)/i,/^(?:.*<>)/i,/^(?:.*<>)/i,/^(?:.*<>)/i,/^(?:.*\[\[fork\]\])/i,/^(?:.*\[\[join\]\])/i,/^(?:.*\[\[choice\]\])/i,/^(?:.*direction\s+TB[^\n]*)/i,/^(?:.*direction\s+BT[^\n]*)/i,/^(?:.*direction\s+RL[^\n]*)/i,/^(?:.*direction\s+LR[^\n]*)/i,/^(?:["])/i,/^(?:\s*as\s+)/i,/^(?:[^\n\{]*)/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[^\n\s\{]+)/i,/^(?:\n)/i,/^(?:\{)/i,/^(?:%%(?!\{)[^\n]*)/i,/^(?:\})/i,/^(?:[\n])/i,/^(?:note\s+)/i,/^(?:left of\b)/i,/^(?:right of\b)/i,/^(?:")/i,/^(?:\s*as\s*)/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[^\n]*)/i,/^(?:\s*[^:\n\s\-]+)/i,/^(?:\s*:[^:\n;]+)/i,/^(?:[\s\S]*?end note\b)/i,/^(?:stateDiagram\s+)/i,/^(?:stateDiagram-v2\s+)/i,/^(?:hide empty description\b)/i,/^(?:\[\*\])/i,/^(?:[^:\n\s\-\{]+)/i,/^(?:\s*:[^:\n;]+)/i,/^(?:-->)/i,/^(?:--)/i,/^(?::::)/i,/^(?:$)/i,/^(?:.)/i],conditions:{LINE:{rules:[14,15],inclusive:!1},close_directive:{rules:[14,15],inclusive:!1},arg_directive:{rules:[8,9,14,15],inclusive:!1},type_directive:{rules:[7,8,14,15],inclusive:!1},open_directive:{rules:[6,14,15],inclusive:!1},struct:{rules:[14,15,27,31,37,44,45,46,47,56,57,58,59,73,74,75,76,77],inclusive:!1},FLOATING_NOTE_ID:{rules:[66],inclusive:!1},FLOATING_NOTE:{rules:[63,64,65],inclusive:!1},NOTE_TEXT:{rules:[68,69],inclusive:!1},NOTE_ID:{rules:[67],inclusive:!1},NOTE:{rules:[60,61,62],inclusive:!1},CLASS_STYLE:{rules:[33],inclusive:!1},CLASS:{rules:[32],inclusive:!1},CLASSDEFID:{rules:[30],inclusive:!1},CLASSDEF:{rules:[28,29],inclusive:!1},acc_descr_multiline:{rules:[25,26],inclusive:!1},acc_descr:{rules:[23],inclusive:!1},acc_title:{rules:[21],inclusive:!1},SCALE:{rules:[18,19,35,36],inclusive:!1},ALIAS:{rules:[],inclusive:!1},STATE_ID:{rules:[50],inclusive:!1},STATE_STRING:{rules:[51,52],inclusive:!1},FORK_STATE:{rules:[],inclusive:!1},STATE:{rules:[14,15,38,39,40,41,42,43,48,49,53,54,55],inclusive:!1},ID:{rules:[14,15],inclusive:!1},INITIAL:{rules:[0,1,2,3,4,5,10,11,12,13,15,16,17,20,22,24,27,31,34,37,55,59,70,71,72,73,74,75,76,78,79,80],inclusive:!0}}};return wt}();gt.lexer=pe;function Et(){this.yy={}}return Et.prototype=gt,gt.Parser=Et,new Et}();dge.parser=dge;const sFe=dge,pzt="LR",bzt="TB",RK="state",gge="relation",vzt="classDef",wzt="applyClass",NP="default",aFe="divider",pge="[*]",oFe="start",cFe=pge,uFe="end",lFe="color",hFe="fill",mzt="bgFill",yzt=",";function fFe(){return{}}let dFe=pzt,FK=[],PP=fFe();const gFe=()=>({relations:[],states:{},documents:{}});let jK={root:gFe()},x0=jK.root,BP=0,pFe=0;const kzt={LINE:0,DOTTED_LINE:1},xzt={AGGREGATION:0,EXTENSION:1,COMPOSITION:2,DEPENDENCY:3},$K=i=>JSON.parse(JSON.stringify(i)),Ezt=function(i,a,f){rd.parseDirective(this,i,a,f)},Tzt=i=>{Fe.info("Setting root doc",i),FK=i},_zt=()=>FK,HK=(i,a,f)=>{if(a.stmt===gge)HK(i,a.state1,!0),HK(i,a.state2,!1);else if(a.stmt===RK&&(a.id==="[*]"?(a.id=f?i.id+"_start":i.id+"_end",a.start=f):a.id=a.id.trim()),a.doc){const p=[];let w=[],y;for(y=0;y0&&w.length>0){const b={stmt:RK,id:IIe(),type:"divider",doc:$K(w)};p.push($K(b)),a.doc=p}a.doc.forEach(b=>HK(a,b,!0))}},Czt=()=>(HK({id:"root"},{id:"root",doc:FK},!0),{id:"root",doc:FK}),Szt=i=>{let a;i.doc?a=i.doc:a=i,Fe.info(a),bFe(!0),Fe.info("Extract",a),a.forEach(f=>{switch(f.stmt){case RK:p9(f.id.trim(),f.type,f.doc,f.description,f.note,f.classes,f.styles,f.textStyles);break;case gge:vFe(f.state1,f.state2,f.description);break;case vzt:wFe(f.id.trim(),f.classes);break;case wzt:mge(f.id.trim(),f.styleClass);break}})},p9=function(i,a=NP,f=null,p=null,w=null,y=null,b=null,E=null){const S=i==null?void 0:i.trim();x0.states[S]===void 0?(Fe.info("Adding state ",S,p),x0.states[S]={id:S,descriptions:[],type:a,doc:f,note:w,classes:[],styles:[],textStyles:[]}):(x0.states[S].doc||(x0.states[S].doc=f),x0.states[S].type||(x0.states[S].type=a)),p&&(Fe.info("Setting state description",S,p),typeof p=="string"&&wge(S,p.trim()),typeof p=="object"&&p.forEach(N=>wge(S,N.trim()))),w&&(x0.states[S].note=w,x0.states[S].note.text=Wa.sanitizeText(x0.states[S].note.text,Tt())),y&&(Fe.info("Setting state classes",S,y),(typeof y=="string"?[y]:y).forEach(B=>mge(S,B.trim()))),b&&(Fe.info("Setting state styles",S,b),(typeof b=="string"?[b]:b).forEach(B=>Rzt(S,B.trim()))),E&&(Fe.info("Setting state styles",S,b),(typeof E=="string"?[E]:E).forEach(B=>Fzt(S,B.trim())))},bFe=function(i){jK={root:gFe()},x0=jK.root,BP=0,PP=fFe(),i||rp()},RP=function(i){return x0.states[i]},Azt=function(){return x0.states},Lzt=function(){Fe.info("Documents = ",jK)},Mzt=function(){return x0.relations};function bge(i=""){let a=i;return i===pge&&(BP++,a=`${oFe}${BP}`),a}function vge(i="",a=NP){return i===pge?oFe:a}function Dzt(i=""){let a=i;return i===cFe&&(BP++,a=`${uFe}${BP}`),a}function Izt(i="",a=NP){return i===cFe?uFe:a}function Ozt(i,a,f){let p=bge(i.id.trim()),w=vge(i.id.trim(),i.type),y=bge(a.id.trim()),b=vge(a.id.trim(),a.type);p9(p,w,i.doc,i.description,i.note,i.classes,i.styles,i.textStyles),p9(y,b,a.doc,a.description,a.note,a.classes,a.styles,a.textStyles),x0.relations.push({id1:p,id2:y,relationTitle:Wa.sanitizeText(f,Tt())})}const vFe=function(i,a,f){if(typeof i=="object")Ozt(i,a,f);else{const p=bge(i.trim()),w=vge(i),y=Dzt(a.trim()),b=Izt(a);p9(p,w),p9(y,b),x0.relations.push({id1:p,id2:y,title:Wa.sanitizeText(f,Tt())})}},wge=function(i,a){const f=x0.states[i],p=a.startsWith(":")?a.replace(":","").trim():a;f.descriptions.push(Wa.sanitizeText(p,Tt()))},Nzt=function(i){return i.substring(0,1)===":"?i.substr(2).trim():i.trim()},Pzt=()=>(pFe++,"divider-id-"+pFe),wFe=function(i,a=""){PP[i]===void 0&&(PP[i]={id:i,styles:[],textStyles:[]});const f=PP[i];a!=null&&a.split(yzt).forEach(p=>{const w=p.replace(/([^;]*);/,"$1").trim();if(p.match(lFe)){const b=w.replace(hFe,mzt).replace(lFe,hFe);f.textStyles.push(b)}f.styles.push(w)})},Bzt=function(){return PP},mge=function(i,a){i.split(",").forEach(function(f){let p=RP(f);if(p===void 0){const w=f.trim();p9(w),p=RP(w)}p.classes.push(a)})},Rzt=function(i,a){const f=RP(i);f!==void 0&&f.textStyles.push(a)},Fzt=function(i,a){const f=RP(i);f!==void 0&&f.textStyles.push(a)},D5={parseDirective:Ezt,getConfig:()=>Tt().state,addState:p9,clear:bFe,getState:RP,getStates:Azt,getRelations:Mzt,getClasses:Bzt,getDirection:()=>dFe,addRelation:vFe,getDividerId:Pzt,setDirection:i=>{dFe=i},cleanupLabel:Nzt,lineType:kzt,relationType:xzt,logDocuments:Lzt,getRootDoc:_zt,setRootDoc:Tzt,getRootDocV2:Czt,extract:Szt,trimColon:i=>i&&i[0]===":"?i.substr(1).trim():i.trim(),getAccTitle:L2,setAccTitle:ip,getAccDescription:D2,setAccDescription:M2,addStyleClass:wFe,setCssClass:mge,addDescription:wge,setDiagramTitle:Uw,getDiagramTitle:Ww},mFe=i=>` +defs #statediagram-barbEnd { + fill: ${i.transitionColor}; + stroke: ${i.transitionColor}; + } +g.stateGroup text { + fill: ${i.nodeBorder}; + stroke: none; + font-size: 10px; +} +g.stateGroup text { + fill: ${i.textColor}; + stroke: none; + font-size: 10px; + +} +g.stateGroup .state-title { + font-weight: bolder; + fill: ${i.stateLabelColor}; +} + +g.stateGroup rect { + fill: ${i.mainBkg}; + stroke: ${i.nodeBorder}; +} + +g.stateGroup line { + stroke: ${i.lineColor}; + stroke-width: 1; +} + +.transition { + stroke: ${i.transitionColor}; + stroke-width: 1; + fill: none; +} + +.stateGroup .composit { + fill: ${i.background}; + border-bottom: 1px +} + +.stateGroup .alt-composit { + fill: #e0e0e0; + border-bottom: 1px +} + +.state-note { + stroke: ${i.noteBorderColor}; + fill: ${i.noteBkgColor}; + + text { + fill: ${i.noteTextColor}; + stroke: none; + font-size: 10px; + } +} + +.stateLabel .box { + stroke: none; + stroke-width: 0; + fill: ${i.mainBkg}; + opacity: 0.5; +} + +.edgeLabel .label rect { + fill: ${i.labelBackgroundColor}; + opacity: 0.5; +} +.edgeLabel .label text { + fill: ${i.transitionLabelColor||i.tertiaryTextColor}; +} +.label div .edgeLabel { + color: ${i.transitionLabelColor||i.tertiaryTextColor}; +} + +.stateLabel text { + fill: ${i.stateLabelColor}; + font-size: 10px; + font-weight: bold; +} + +.node circle.state-start { + fill: ${i.specialStateColor}; + stroke: ${i.specialStateColor}; +} + +.node .fork-join { + fill: ${i.specialStateColor}; + stroke: ${i.specialStateColor}; +} + +.node circle.state-end { + fill: ${i.innerEndBackground}; + stroke: ${i.background}; + stroke-width: 1.5 +} +.end-state-inner { + fill: ${i.compositeBackground||i.background}; + // stroke: ${i.background}; + stroke-width: 1.5 +} + +.node rect { + fill: ${i.stateBkg||i.mainBkg}; + stroke: ${i.stateBorder||i.nodeBorder}; + stroke-width: 1px; +} +.node polygon { + fill: ${i.mainBkg}; + stroke: ${i.stateBorder||i.nodeBorder};; + stroke-width: 1px; +} +#statediagram-barbEnd { + fill: ${i.lineColor}; +} + +.statediagram-cluster rect { + fill: ${i.compositeTitleBackground}; + stroke: ${i.stateBorder||i.nodeBorder}; + stroke-width: 1px; +} + +.cluster-label, .nodeLabel { + color: ${i.stateLabelColor}; +} + +.statediagram-cluster rect.outer { + rx: 5px; + ry: 5px; +} +.statediagram-state .divider { + stroke: ${i.stateBorder||i.nodeBorder}; +} + +.statediagram-state .title-state { + rx: 5px; + ry: 5px; +} +.statediagram-cluster.statediagram-cluster .inner { + fill: ${i.compositeBackground||i.background}; +} +.statediagram-cluster.statediagram-cluster-alt .inner { + fill: ${i.altBackground?i.altBackground:"#efefef"}; +} + +.statediagram-cluster .inner { + rx:0; + ry:0; +} + +.statediagram-state rect.basic { + rx: 5px; + ry: 5px; +} +.statediagram-state rect.divider { + stroke-dasharray: 10,10; + fill: ${i.altBackground?i.altBackground:"#efefef"}; +} + +.note-edge { + stroke-dasharray: 5; +} + +.statediagram-note rect { + fill: ${i.noteBkgColor}; + stroke: ${i.noteBorderColor}; + stroke-width: 1px; + rx: 0; + ry: 0; +} +.statediagram-note rect { + fill: ${i.noteBkgColor}; + stroke: ${i.noteBorderColor}; + stroke-width: 1px; + rx: 0; + ry: 0; +} + +.statediagram-note text { + fill: ${i.noteTextColor}; +} + +.statediagram-note .nodeLabel { + color: ${i.noteTextColor}; +} +.statediagram .edgeLabel { + color: red; // ${i.noteTextColor}; +} + +#dependencyStart, #dependencyEnd { + fill: ${i.lineColor}; + stroke: ${i.lineColor}; + stroke-width: 1; +} + +.statediagramTitleText { + text-anchor: middle; + font-size: 18px; + fill: ${i.textColor}; +} +`,yge={},jzt=(i,a)=>{yge[i]=a},$zt=i=>yge[i],yFe=()=>Object.keys(yge),Hzt={get:$zt,set:jzt,keys:yFe,size:()=>yFe().length},zzt=i=>i.append("circle").attr("class","start-state").attr("r",Tt().state.sizeUnit).attr("cx",Tt().state.padding+Tt().state.sizeUnit).attr("cy",Tt().state.padding+Tt().state.sizeUnit),Gzt=i=>i.append("line").style("stroke","grey").style("stroke-dasharray","3").attr("x1",Tt().state.textHeight).attr("class","divider").attr("x2",Tt().state.textHeight*2).attr("y1",0).attr("y2",0),qzt=(i,a)=>{const f=i.append("text").attr("x",2*Tt().state.padding).attr("y",Tt().state.textHeight+2*Tt().state.padding).attr("font-size",Tt().state.fontSize).attr("class","state-title").text(a.id),p=f.node().getBBox();return i.insert("rect",":first-child").attr("x",Tt().state.padding).attr("y",Tt().state.padding).attr("width",p.width+2*Tt().state.padding).attr("height",p.height+2*Tt().state.padding).attr("rx",Tt().state.radius),f},Vzt=(i,a)=>{const f=function(j,$,V){const Q=j.append("tspan").attr("x",2*Tt().state.padding).text($);V||Q.attr("dy",Tt().state.textHeight)},w=i.append("text").attr("x",2*Tt().state.padding).attr("y",Tt().state.textHeight+1.3*Tt().state.padding).attr("font-size",Tt().state.fontSize).attr("class","state-title").text(a.descriptions[0]).node().getBBox(),y=w.height,b=i.append("text").attr("x",Tt().state.padding).attr("y",y+Tt().state.padding*.4+Tt().state.dividerMargin+Tt().state.textHeight).attr("class","state-description");let E=!0,S=!0;a.descriptions.forEach(function(j){E||(f(b,j,S),S=!1),E=!1});const N=i.append("line").attr("x1",Tt().state.padding).attr("y1",Tt().state.padding+y+Tt().state.dividerMargin/2).attr("y2",Tt().state.padding+y+Tt().state.dividerMargin/2).attr("class","descr-divider"),B=b.node().getBBox(),R=Math.max(B.width,w.width);return N.attr("x2",R+3*Tt().state.padding),i.insert("rect",":first-child").attr("x",Tt().state.padding).attr("y",Tt().state.padding).attr("width",R+2*Tt().state.padding).attr("height",B.height+y+2*Tt().state.padding).attr("rx",Tt().state.radius),i},Uzt=(i,a,f)=>{const p=Tt().state.padding,w=2*Tt().state.padding,y=i.node().getBBox(),b=y.width,E=y.x,S=i.append("text").attr("x",0).attr("y",Tt().state.titleShift).attr("font-size",Tt().state.fontSize).attr("class","state-title").text(a.id),B=S.node().getBBox().width+w;let R=Math.max(B,b);R===b&&(R=R+w);let j;const $=i.node().getBBox();a.doc,j=E-p,B>b&&(j=(b-R)/2+p),Math.abs(E-$.x)b&&(j=E-(B-b)/2);const V=1-Tt().state.textHeight;return i.insert("rect",":first-child").attr("x",j).attr("y",V).attr("class",f?"alt-composit":"composit").attr("width",R).attr("height",$.height+Tt().state.textHeight+Tt().state.titleShift+1).attr("rx","0"),S.attr("x",j+p),B<=b&&S.attr("x",E+(R-w)/2-B/2+p),i.insert("rect",":first-child").attr("x",j).attr("y",Tt().state.titleShift-Tt().state.textHeight-Tt().state.padding).attr("width",R).attr("height",Tt().state.textHeight*3).attr("rx",Tt().state.radius),i.insert("rect",":first-child").attr("x",j).attr("y",Tt().state.titleShift-Tt().state.textHeight-Tt().state.padding).attr("width",R).attr("height",$.height+3+2*Tt().state.textHeight).attr("rx",Tt().state.radius),i},Wzt=i=>(i.append("circle").attr("class","end-state-outer").attr("r",Tt().state.sizeUnit+Tt().state.miniPadding).attr("cx",Tt().state.padding+Tt().state.sizeUnit+Tt().state.miniPadding).attr("cy",Tt().state.padding+Tt().state.sizeUnit+Tt().state.miniPadding),i.append("circle").attr("class","end-state-inner").attr("r",Tt().state.sizeUnit).attr("cx",Tt().state.padding+Tt().state.sizeUnit+2).attr("cy",Tt().state.padding+Tt().state.sizeUnit+2)),Kzt=(i,a)=>{let f=Tt().state.forkWidth,p=Tt().state.forkHeight;if(a.parentId){let w=f;f=p,p=w}return i.append("rect").style("stroke","black").style("fill","black").attr("width",f).attr("height",p).attr("x",Tt().state.padding).attr("y",Tt().state.padding)},Yzt=(i,a,f,p)=>{let w=0;const y=p.append("text");y.style("text-anchor","start"),y.attr("class","noteText");let b=i.replace(/\r\n/g,"
");b=b.replace(/\n/g,"
");const E=b.split(Wa.lineBreakRegex);let S=1.25*Tt().state.noteMargin;for(const N of E){const B=N.trim();if(B.length>0){const R=y.append("tspan");if(R.text(B),S===0){const j=R.node().getBBox();S+=j.height}w+=S,R.attr("x",a+Tt().state.noteMargin),R.attr("y",f+w+1.25*Tt().state.noteMargin)}}return{textWidth:y.node().getBBox().width,textHeight:w}},Xzt=(i,a)=>{a.attr("class","state-note");const f=a.append("rect").attr("x",0).attr("y",Tt().state.padding),p=a.append("g"),{textWidth:w,textHeight:y}=Yzt(i,0,0,p);return f.attr("height",y+2*Tt().state.noteMargin),f.attr("width",w+Tt().state.noteMargin*2),f},kFe=function(i,a){const f=a.id,p={id:f,label:a.id,width:0,height:0},w=i.append("g").attr("id",f).attr("class","stateGroup");a.type==="start"&&zzt(w),a.type==="end"&&Wzt(w),(a.type==="fork"||a.type==="join")&&Kzt(w,a),a.type==="note"&&Xzt(a.note.text,w),a.type==="divider"&&Gzt(w),a.type==="default"&&a.descriptions.length===0&&qzt(w,a),a.type==="default"&&a.descriptions.length>0&&Vzt(w,a);const y=w.node().getBBox();return p.width=y.width+2*Tt().state.padding,p.height=y.height+2*Tt().state.padding,Hzt.set(f,p),p};let xFe=0;const Qzt=function(i,a,f){const p=function(S){switch(S){case D5.relationType.AGGREGATION:return"aggregation";case D5.relationType.EXTENSION:return"extension";case D5.relationType.COMPOSITION:return"composition";case D5.relationType.DEPENDENCY:return"dependency"}};a.points=a.points.filter(S=>!Number.isNaN(S.y));const w=a.points,y=WE().x(function(S){return S.x}).y(function(S){return S.y}).curve(SA),b=i.append("path").attr("d",y(w)).attr("id","edge"+xFe).attr("class","transition");let E="";if(Tt().state.arrowMarkerAbsolute&&(E=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search,E=E.replace(/\(/g,"\\("),E=E.replace(/\)/g,"\\)")),b.attr("marker-end","url("+E+"#"+p(D5.relationType.DEPENDENCY)+"End)"),f.title!==void 0){const S=i.append("g").attr("class","stateLabel"),{x:N,y:B}=co.calcLabelPosition(a.points),R=Wa.getRows(f.title);let j=0;const $=[];let V=0,Q=0;for(let se=0;se<=R.length;se++){const ge=S.append("text").attr("text-anchor","middle").text(R[se]).attr("x",N).attr("y",B+j),ye=ge.node().getBBox();V=Math.max(V,ye.width),Q=Math.min(Q,ye.x),Fe.info(ye.x,N,B+j),j===0&&(j=ge.node().getBBox().height,Fe.info("Title height",j,B)),$.push(ge)}let oe=j*R.length;if(R.length>1){const se=(R.length-1)*j*.5;$.forEach((ge,ye)=>ge.attr("y",B+ye*j-se)),oe=j*R.length}const ce=S.node().getBBox();S.insert("rect",":first-child").attr("class","box").attr("x",N-V/2-Tt().state.padding/2).attr("y",B-oe/2-Tt().state.padding/2-3.5).attr("width",V+Tt().state.padding).attr("height",oe+Tt().state.padding),Fe.info(ce)}xFe++};let B2;const kge={},Zzt=function(){},Jzt=function(i){i.append("defs").append("marker").attr("id","dependencyEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 19,7 L9,13 L14,7 L9,1 Z")},eGt=function(i,a,f,p){B2=Tt().state;const w=Tt().securityLevel;let y;w==="sandbox"&&(y=Cr("#i"+a));const b=Cr(w==="sandbox"?y.nodes()[0].contentDocument.body:"body"),E=w==="sandbox"?y.nodes()[0].contentDocument:document;Fe.debug("Rendering diagram "+i);const S=b.select(`[id='${a}']`);Jzt(S),new zf({multigraph:!0,compound:!0,rankdir:"RL"}).setDefaultEdgeLabel(function(){return{}});const B=p.db.getRootDoc();EFe(B,S,void 0,!1,b,E,p);const R=B2.padding,j=S.node().getBBox(),$=j.width+R*2,V=j.height+R*2,Q=$*1.75;Vw(S,V,Q,B2.useMaxWidth),S.attr("viewBox",`${j.x-B2.padding} ${j.y-B2.padding} `+$+" "+V)},tGt=i=>i?i.length*B2.fontSizeFactor:1,EFe=(i,a,f,p,w,y,b)=>{const E=new zf({compound:!0,multigraph:!0});let S,N=!0;for(S=0;S{const ye=ge.parentElement;let ke=0,Ae=0;ye&&(ye.parentElement&&(ke=ye.parentElement.getBBox().width),Ae=parseInt(ye.getAttribute("data-x-shift"),10),Number.isNaN(Ae)&&(Ae=0)),ge.setAttribute("x1",0-Ae+8),ge.setAttribute("x2",ke-Ae-8)})):Fe.debug("No Node "+ce+": "+JSON.stringify(E.node(ce)))});let Q=V.getBBox();E.edges().forEach(function(ce){ce!==void 0&&E.edge(ce)!==void 0&&(Fe.debug("Edge "+ce.v+" -> "+ce.w+": "+JSON.stringify(E.edge(ce))),Qzt(a,E.edge(ce),E.edge(ce).relation))}),Q=V.getBBox();const oe={id:f||"root",label:f||"root",width:0,height:0};return oe.width=Q.width+2*B2.padding,oe.height=Q.height+2*B2.padding,Fe.debug("Doc rendered",oe,E),oe},nGt=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:sFe,db:D5,renderer:{setConf:Zzt,draw:eGt},styles:mFe,init:i=>{i.state||(i.state={}),i.state.arrowMarkerAbsolute=i.arrowMarkerAbsolute,D5.clear()}}},Symbol.toStringTag,{value:"Module"})),zK="rect",xge="rectWithTitle",rGt="start",iGt="end",sGt="divider",aGt="roundedWithTitle",oGt="note",cGt="noteGroup",fL="statediagram",uGt=`${fL}-state`,TFe="transition",lGt="note",hGt=`${TFe} note-edge`,fGt=`${fL}-${lGt}`,dGt=`${fL}-cluster`,gGt=`${fL}-cluster-alt`,_Fe="parent",CFe="note",pGt="state",Ege="----",bGt=`${Ege}${CFe}`,SFe=`${Ege}${_Fe}`,AFe="fill:none",LFe="fill: #333",MFe="c",DFe="text",IFe="normal";let GK={},ux=0;const vGt=function(i){const a=Object.keys(i);for(const f of a)i[f]},wGt=function(i,a){Fe.trace("Extracting classes"),a.db.clear();try{return a.parser.parse(i),a.db.extract(a.db.getRootDocV2()),a.db.getClasses()}catch(f){return f}};function mGt(i){return i==null?"":i.classes?i.classes.join(" "):""}function Tge(i="",a=0,f="",p=Ege){const w=f!==null&&f.length>0?`${p}${f}`:"";return`${pGt}-${i}${w}-${a}`}const FP=(i,a,f,p,w,y)=>{const b=f.id,E=mGt(p[b]);if(b!=="root"){let S=zK;f.start===!0&&(S=rGt),f.start===!1&&(S=iGt),f.type!==NP&&(S=f.type),GK[b]||(GK[b]={id:b,shape:S,description:Wa.sanitizeText(b,Tt()),classes:`${E} ${uGt}`});const N=GK[b];f.description&&(Array.isArray(N.description)?(N.shape=xge,N.description.push(f.description)):N.description.length>0?(N.shape=xge,N.description===b?N.description=[f.description]:N.description=[N.description,f.description]):(N.shape=zK,N.description=f.description),N.description=Wa.sanitizeTextOrArray(N.description,Tt())),N.description.length===1&&N.shape===xge&&(N.shape=zK),!N.type&&f.doc&&(Fe.info("Setting cluster for ",b,_ge(f)),N.type="group",N.dir=_ge(f),N.shape=f.type===aFe?sGt:aGt,N.classes=N.classes+" "+dGt+" "+(y?gGt:""));const B={labelStyle:"",shape:N.shape,labelText:N.description,classes:N.classes,style:"",id:b,dir:N.dir,domId:Tge(b,ux),type:N.type,padding:15};if(B.centerLabel=!0,f.note){const R={labelStyle:"",shape:oGt,labelText:f.note.text,classes:fGt,style:"",id:b+bGt+"-"+ux,domId:Tge(b,ux,CFe),type:N.type,padding:15},j={labelStyle:"",shape:cGt,labelText:f.note.text,classes:N.classes,style:"",id:b+SFe,domId:Tge(b,ux,_Fe),type:"group",padding:0};ux++;const $=b+SFe;i.setNode($,j),i.setNode(R.id,R),i.setNode(b,B),i.setParent(b,$),i.setParent(R.id,$);let V=b,Q=R.id;f.note.position==="left of"&&(V=R.id,Q=b),i.setEdge(V,Q,{arrowhead:"none",arrowType:"",style:AFe,labelStyle:"",classes:hGt,arrowheadStyle:LFe,labelpos:MFe,labelType:DFe,thickness:IFe})}else i.setNode(b,B)}a&&a.id!=="root"&&(Fe.trace("Setting node ",b," to be child of its parent ",a.id),i.setParent(b,a.id)),f.doc&&(Fe.trace("Adding nodes children "),yGt(i,f,f.doc,p,w,!y))},yGt=(i,a,f,p,w,y)=>{Fe.trace("items",f),f.forEach(b=>{switch(b.stmt){case RK:FP(i,a,b,p,w,y);break;case NP:FP(i,a,b,p,w,y);break;case gge:{FP(i,a,b.state1,p,w,y),FP(i,a,b.state2,p,w,y);const E={id:"edge"+ux,arrowhead:"normal",arrowTypeEnd:"arrow_barb",style:AFe,labelStyle:"",label:Wa.sanitizeText(b.description,Tt()),arrowheadStyle:LFe,labelpos:MFe,labelType:DFe,thickness:IFe,classes:TFe};i.setEdge(b.state1.id,b.state2.id,E,ux),ux++}break}})},_ge=(i,a=bzt)=>{let f=a;if(i.doc)for(let p=0;p{i.state||(i.state={}),i.state.arrowMarkerAbsolute=i.arrowMarkerAbsolute,D5.clear()}}},Symbol.toStringTag,{value:"Module"}));var Cge=function(){var i=function(Q,oe,ce,se){for(ce=ce||{},se=Q.length;se--;ce[Q[se]]=oe);return ce},a=[1,2],f=[1,5],p=[6,9,11,17,18,20,22,23,24,26],w=[1,15],y=[1,16],b=[1,17],E=[1,18],S=[1,19],N=[1,20],B=[1,24],R=[4,6,9,11,17,18,20,22,23,24,26],j={trace:function(){},yy:{},symbols_:{error:2,start:3,journey:4,document:5,EOF:6,directive:7,line:8,SPACE:9,statement:10,NEWLINE:11,openDirective:12,typeDirective:13,closeDirective:14,":":15,argDirective:16,title:17,acc_title:18,acc_title_value:19,acc_descr:20,acc_descr_value:21,acc_descr_multiline_value:22,section:23,taskName:24,taskData:25,open_directive:26,type_directive:27,arg_directive:28,close_directive:29,$accept:0,$end:1},terminals_:{2:"error",4:"journey",6:"EOF",9:"SPACE",11:"NEWLINE",15:":",17:"title",18:"acc_title",19:"acc_title_value",20:"acc_descr",21:"acc_descr_value",22:"acc_descr_multiline_value",23:"section",24:"taskName",25:"taskData",26:"open_directive",27:"type_directive",28:"arg_directive",29:"close_directive"},productions_:[0,[3,3],[3,2],[5,0],[5,2],[8,2],[8,1],[8,1],[8,1],[7,4],[7,6],[10,1],[10,2],[10,2],[10,1],[10,1],[10,2],[10,1],[12,1],[13,1],[16,1],[14,1]],performAction:function(oe,ce,se,ge,ye,ke,Ae){var de=ke.length-1;switch(ye){case 1:return ke[de-1];case 3:this.$=[];break;case 4:ke[de-1].push(ke[de]),this.$=ke[de-1];break;case 5:case 6:this.$=ke[de];break;case 7:case 8:this.$=[];break;case 11:ge.setDiagramTitle(ke[de].substr(6)),this.$=ke[de].substr(6);break;case 12:this.$=ke[de].trim(),ge.setAccTitle(this.$);break;case 13:case 14:this.$=ke[de].trim(),ge.setAccDescription(this.$);break;case 15:ge.addSection(ke[de].substr(8)),this.$=ke[de].substr(8);break;case 16:ge.addTask(ke[de-1],ke[de]),this.$="task";break;case 18:ge.parseDirective("%%{","open_directive");break;case 19:ge.parseDirective(ke[de],"type_directive");break;case 20:ke[de]=ke[de].trim().replace(/'/g,'"'),ge.parseDirective(ke[de],"arg_directive");break;case 21:ge.parseDirective("}%%","close_directive","journey");break}},table:[{3:1,4:a,7:3,12:4,26:f},{1:[3]},i(p,[2,3],{5:6}),{3:7,4:a,7:3,12:4,26:f},{13:8,27:[1,9]},{27:[2,18]},{6:[1,10],7:21,8:11,9:[1,12],10:13,11:[1,14],12:4,17:w,18:y,20:b,22:E,23:S,24:N,26:f},{1:[2,2]},{14:22,15:[1,23],29:B},i([15,29],[2,19]),i(p,[2,8],{1:[2,1]}),i(p,[2,4]),{7:21,10:25,12:4,17:w,18:y,20:b,22:E,23:S,24:N,26:f},i(p,[2,6]),i(p,[2,7]),i(p,[2,11]),{19:[1,26]},{21:[1,27]},i(p,[2,14]),i(p,[2,15]),{25:[1,28]},i(p,[2,17]),{11:[1,29]},{16:30,28:[1,31]},{11:[2,21]},i(p,[2,5]),i(p,[2,12]),i(p,[2,13]),i(p,[2,16]),i(R,[2,9]),{14:32,29:B},{29:[2,20]},{11:[1,33]},i(R,[2,10])],defaultActions:{5:[2,18],7:[2,2],24:[2,21],31:[2,20]},parseError:function(oe,ce){if(ce.recoverable)this.trace(oe);else{var se=new Error(oe);throw se.hash=ce,se}},parse:function(oe){var ce=this,se=[0],ge=[],ye=[null],ke=[],Ae=this.table,de="",ve=0,te=0,xe=2,De=1,he=ke.slice.call(arguments,1),Ie=Object.create(this.lexer),ee={yy:{}};for(var rt in this.yy)Object.prototype.hasOwnProperty.call(this.yy,rt)&&(ee.yy[rt]=this.yy[rt]);Ie.setInput(oe,ee.yy),ee.yy.lexer=Ie,ee.yy.parser=this,typeof Ie.yylloc>"u"&&(Ie.yylloc={});var me=Ie.yylloc;ke.push(me);var gt=Ie.options&&Ie.options.ranges;typeof ee.yy.parseError=="function"?this.parseError=ee.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function pe(){var Dt;return Dt=ge.pop()||Ie.lex()||De,typeof Dt!="number"&&(Dt instanceof Array&&(ge=Dt,Dt=ge.pop()),Dt=ce.symbols_[Dt]||Dt),Dt}for(var Et,wt,jt,At,Bt={},cn,Nn,Ot,oi;;){if(wt=se[se.length-1],this.defaultActions[wt]?jt=this.defaultActions[wt]:((Et===null||typeof Et>"u")&&(Et=pe()),jt=Ae[wt]&&Ae[wt][Et]),typeof jt>"u"||!jt.length||!jt[0]){var kt="";oi=[];for(cn in Ae[wt])this.terminals_[cn]&&cn>xe&&oi.push("'"+this.terminals_[cn]+"'");Ie.showPosition?kt="Parse error on line "+(ve+1)+`: +`+Ie.showPosition()+` +Expecting `+oi.join(", ")+", got '"+(this.terminals_[Et]||Et)+"'":kt="Parse error on line "+(ve+1)+": Unexpected "+(Et==De?"end of input":"'"+(this.terminals_[Et]||Et)+"'"),this.parseError(kt,{text:Ie.match,token:this.terminals_[Et]||Et,line:Ie.yylineno,loc:me,expected:oi})}if(jt[0]instanceof Array&&jt.length>1)throw new Error("Parse Error: multiple actions possible at state: "+wt+", token: "+Et);switch(jt[0]){case 1:se.push(Et),ye.push(Ie.yytext),ke.push(Ie.yylloc),se.push(jt[1]),Et=null,te=Ie.yyleng,de=Ie.yytext,ve=Ie.yylineno,me=Ie.yylloc;break;case 2:if(Nn=this.productions_[jt[1]][1],Bt.$=ye[ye.length-Nn],Bt._$={first_line:ke[ke.length-(Nn||1)].first_line,last_line:ke[ke.length-1].last_line,first_column:ke[ke.length-(Nn||1)].first_column,last_column:ke[ke.length-1].last_column},gt&&(Bt._$.range=[ke[ke.length-(Nn||1)].range[0],ke[ke.length-1].range[1]]),At=this.performAction.apply(Bt,[de,te,ve,ee.yy,jt[1],ye,ke].concat(he)),typeof At<"u")return At;Nn&&(se=se.slice(0,-1*Nn*2),ye=ye.slice(0,-1*Nn),ke=ke.slice(0,-1*Nn)),se.push(this.productions_[jt[1]][0]),ye.push(Bt.$),ke.push(Bt._$),Ot=Ae[se[se.length-2]][se[se.length-1]],se.push(Ot);break;case 3:return!0}}return!0}},$=function(){var Q={EOF:1,parseError:function(ce,se){if(this.yy.parser)this.yy.parser.parseError(ce,se);else throw new Error(ce)},setInput:function(oe,ce){return this.yy=ce||this.yy||{},this._input=oe,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var oe=this._input[0];this.yytext+=oe,this.yyleng++,this.offset++,this.match+=oe,this.matched+=oe;var ce=oe.match(/(?:\r\n?|\n).*/g);return ce?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),oe},unput:function(oe){var ce=oe.length,se=oe.split(/(?:\r\n?|\n)/g);this._input=oe+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-ce),this.offset-=ce;var ge=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),se.length-1&&(this.yylineno-=se.length-1);var ye=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:se?(se.length===ge.length?this.yylloc.first_column:0)+ge[ge.length-se.length].length-se[0].length:this.yylloc.first_column-ce},this.options.ranges&&(this.yylloc.range=[ye[0],ye[0]+this.yyleng-ce]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(oe){this.unput(this.match.slice(oe))},pastInput:function(){var oe=this.matched.substr(0,this.matched.length-this.match.length);return(oe.length>20?"...":"")+oe.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var oe=this.match;return oe.length<20&&(oe+=this._input.substr(0,20-oe.length)),(oe.substr(0,20)+(oe.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var oe=this.pastInput(),ce=new Array(oe.length+1).join("-");return oe+this.upcomingInput()+` +`+ce+"^"},test_match:function(oe,ce){var se,ge,ye;if(this.options.backtrack_lexer&&(ye={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(ye.yylloc.range=this.yylloc.range.slice(0))),ge=oe[0].match(/(?:\r\n?|\n).*/g),ge&&(this.yylineno+=ge.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:ge?ge[ge.length-1].length-ge[ge.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+oe[0].length},this.yytext+=oe[0],this.match+=oe[0],this.matches=oe,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(oe[0].length),this.matched+=oe[0],se=this.performAction.call(this,this.yy,this,ce,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),se)return se;if(this._backtrack){for(var ke in ye)this[ke]=ye[ke];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var oe,ce,se,ge;this._more||(this.yytext="",this.match="");for(var ye=this._currentRules(),ke=0;kece[0].length)){if(ce=se,ge=ke,this.options.backtrack_lexer){if(oe=this.test_match(se,ye[ke]),oe!==!1)return oe;if(this._backtrack){ce=!1;continue}else return!1}else if(!this.options.flex)break}return ce?(oe=this.test_match(ce,ye[ge]),oe!==!1?oe:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var ce=this.next();return ce||this.lex()},begin:function(ce){this.conditionStack.push(ce)},popState:function(){var ce=this.conditionStack.length-1;return ce>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(ce){return ce=this.conditionStack.length-1-Math.abs(ce||0),ce>=0?this.conditionStack[ce]:"INITIAL"},pushState:function(ce){this.begin(ce)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(ce,se,ge,ye){switch(ge){case 0:return this.begin("open_directive"),26;case 1:return this.begin("type_directive"),27;case 2:return this.popState(),this.begin("arg_directive"),15;case 3:return this.popState(),this.popState(),29;case 4:return 28;case 5:break;case 6:break;case 7:return 11;case 8:break;case 9:break;case 10:return 4;case 11:return 17;case 12:return this.begin("acc_title"),18;case 13:return this.popState(),"acc_title_value";case 14:return this.begin("acc_descr"),20;case 15:return this.popState(),"acc_descr_value";case 16:this.begin("acc_descr_multiline");break;case 17:this.popState();break;case 18:return"acc_descr_multiline_value";case 19:return 23;case 20:return 24;case 21:return 25;case 22:return 15;case 23:return 6;case 24:return"INVALID"}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:journey\b)/i,/^(?:title\s[^#\n;]+)/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:section\s[^#:\n;]+)/i,/^(?:[^#:\n;]+)/i,/^(?::[^#\n;]+)/i,/^(?::)/i,/^(?:$)/i,/^(?:.)/i],conditions:{open_directive:{rules:[1],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},acc_descr_multiline:{rules:[17,18],inclusive:!1},acc_descr:{rules:[15],inclusive:!1},acc_title:{rules:[13],inclusive:!1},INITIAL:{rules:[0,5,6,7,8,9,10,11,12,14,16,19,20,21,22,23,24],inclusive:!0}}};return Q}();j.lexer=$;function V(){this.yy={}}return V.prototype=j,j.Parser=V,new V}();Cge.parser=Cge;const xGt=Cge;let dL="";const Sge=[],jP=[],$P=[],EGt=function(i,a,f){rd.parseDirective(this,i,a,f)},TGt=function(){Sge.length=0,jP.length=0,dL="",$P.length=0,rp()},_Gt=function(i){dL=i,Sge.push(i)},CGt=function(){return Sge},SGt=function(){let i=OFe();const a=100;let f=0;for(;!i&&f{f.people&&i.push(...f.people)}),[...new Set(i)].sort()},LGt=function(i,a){const f=a.substr(1).split(":");let p=0,w=[];f.length===1?(p=Number(f[0]),w=[]):(p=Number(f[0]),w=f[1].split(","));const y=w.map(E=>E.trim()),b={section:dL,type:dL,people:y,task:i,score:p};$P.push(b)},MGt=function(i){const a={section:dL,type:dL,description:i,task:i,classes:[]};jP.push(a)},OFe=function(){const i=function(f){return $P[f].processed};let a=!0;for(const[f,p]of $P.entries())i(f),a=a&&p.processed;return a},NFe={parseDirective:EGt,getConfig:()=>Tt().journey,clear:TGt,setDiagramTitle:Uw,getDiagramTitle:Ww,setAccTitle:ip,getAccTitle:L2,setAccDescription:M2,getAccDescription:D2,addSection:_Gt,getSections:CGt,getTasks:SGt,addTask:LGt,addTaskOrg:MGt,getActors:function(){return AGt()}},DGt=i=>`.label { + font-family: 'trebuchet ms', verdana, arial, sans-serif; + font-family: var(--mermaid-font-family); + color: ${i.textColor}; + } + .mouth { + stroke: #666; + } + + line { + stroke: ${i.textColor} + } + + .legend { + fill: ${i.textColor}; + } + + .label text { + fill: #333; + } + .label { + color: ${i.textColor} + } + + .face { + ${i.faceColor?`fill: ${i.faceColor}`:"fill: #FFF8DC"}; + stroke: #999; + } + + .node rect, + .node circle, + .node ellipse, + .node polygon, + .node path { + fill: ${i.mainBkg}; + stroke: ${i.nodeBorder}; + stroke-width: 1px; + } + + .node .label { + text-align: center; + } + .node.clickable { + cursor: pointer; + } + + .arrowheadPath { + fill: ${i.arrowheadColor}; + } + + .edgePath .path { + stroke: ${i.lineColor}; + stroke-width: 1.5px; + } + + .flowchart-link { + stroke: ${i.lineColor}; + fill: none; + } + + .edgeLabel { + background-color: ${i.edgeLabelBackground}; + rect { + opacity: 0.5; + } + text-align: center; + } + + .cluster rect { + } + + .cluster text { + fill: ${i.titleColor}; + } + + div.mermaidTooltip { + position: absolute; + text-align: center; + max-width: 200px; + padding: 2px; + font-family: 'trebuchet ms', verdana, arial, sans-serif; + font-family: var(--mermaid-font-family); + font-size: 12px; + background: ${i.tertiaryColor}; + border: 1px solid ${i.border2}; + border-radius: 2px; + pointer-events: none; + z-index: 100; + } + + .task-type-0, .section-type-0 { + ${i.fillType0?`fill: ${i.fillType0}`:""}; + } + .task-type-1, .section-type-1 { + ${i.fillType0?`fill: ${i.fillType1}`:""}; + } + .task-type-2, .section-type-2 { + ${i.fillType0?`fill: ${i.fillType2}`:""}; + } + .task-type-3, .section-type-3 { + ${i.fillType0?`fill: ${i.fillType3}`:""}; + } + .task-type-4, .section-type-4 { + ${i.fillType0?`fill: ${i.fillType4}`:""}; + } + .task-type-5, .section-type-5 { + ${i.fillType0?`fill: ${i.fillType5}`:""}; + } + .task-type-6, .section-type-6 { + ${i.fillType0?`fill: ${i.fillType6}`:""}; + } + .task-type-7, .section-type-7 { + ${i.fillType0?`fill: ${i.fillType7}`:""}; + } + + .actor-0 { + ${i.actor0?`fill: ${i.actor0}`:""}; + } + .actor-1 { + ${i.actor1?`fill: ${i.actor1}`:""}; + } + .actor-2 { + ${i.actor2?`fill: ${i.actor2}`:""}; + } + .actor-3 { + ${i.actor3?`fill: ${i.actor3}`:""}; + } + .actor-4 { + ${i.actor4?`fill: ${i.actor4}`:""}; + } + .actor-5 { + ${i.actor5?`fill: ${i.actor5}`:""}; + } +`,qK=function(i,a){const f=i.append("rect");return f.attr("x",a.x),f.attr("y",a.y),f.attr("fill",a.fill),f.attr("stroke",a.stroke),f.attr("width",a.width),f.attr("height",a.height),f.attr("rx",a.rx),f.attr("ry",a.ry),a.class!==void 0&&f.attr("class",a.class),f},IGt=function(i,a){const p=i.append("circle").attr("cx",a.cx).attr("cy",a.cy).attr("class","face").attr("r",15).attr("stroke-width",2).attr("overflow","visible"),w=i.append("g");w.append("circle").attr("cx",a.cx-15/3).attr("cy",a.cy-15/3).attr("r",1.5).attr("stroke-width",2).attr("fill","#666").attr("stroke","#666"),w.append("circle").attr("cx",a.cx+15/3).attr("cy",a.cy-15/3).attr("r",1.5).attr("stroke-width",2).attr("fill","#666").attr("stroke","#666");function y(S){const N=CA().startAngle(Math.PI/2).endAngle(3*(Math.PI/2)).innerRadius(7.5).outerRadius(6.8181818181818175);S.append("path").attr("class","mouth").attr("d",N).attr("transform","translate("+a.cx+","+(a.cy+2)+")")}function b(S){const N=CA().startAngle(3*Math.PI/2).endAngle(5*(Math.PI/2)).innerRadius(7.5).outerRadius(6.8181818181818175);S.append("path").attr("class","mouth").attr("d",N).attr("transform","translate("+a.cx+","+(a.cy+7)+")")}function E(S){S.append("line").attr("class","mouth").attr("stroke",2).attr("x1",a.cx-5).attr("y1",a.cy+7).attr("x2",a.cx+5).attr("y2",a.cy+7).attr("class","mouth").attr("stroke-width","1px").attr("stroke","#666")}return a.score>3?y(w):a.score<3?b(w):E(w),p},PFe=function(i,a){const f=i.append("circle");return f.attr("cx",a.cx),f.attr("cy",a.cy),f.attr("class","actor-"+a.pos),f.attr("fill",a.fill),f.attr("stroke",a.stroke),f.attr("r",a.r),f.class!==void 0&&f.attr("class",f.class),a.title!==void 0&&f.append("title").text(a.title),f},BFe=function(i,a){const f=a.text.replace(//gi," "),p=i.append("text");p.attr("x",a.x),p.attr("y",a.y),p.attr("class","legend"),p.style("text-anchor",a.anchor),a.class!==void 0&&p.attr("class",a.class);const w=p.append("tspan");return w.attr("x",a.x+a.textMargin*2),w.text(f),p},OGt=function(i,a){function f(w,y,b,E,S){return w+","+y+" "+(w+b)+","+y+" "+(w+b)+","+(y+E-S)+" "+(w+b-S*1.2)+","+(y+E)+" "+w+","+(y+E)}const p=i.append("polygon");p.attr("points",f(a.x,a.y,50,20,7)),p.attr("class","labelBox"),a.y=a.y+a.labelMargin,a.x=a.x+.5*a.labelMargin,BFe(i,a)},NGt=function(i,a,f){const p=i.append("g"),w=Age();w.x=a.x,w.y=a.y,w.fill=a.fill,w.width=f.width*a.taskCount+f.diagramMarginX*(a.taskCount-1),w.height=f.height,w.class="journey-section section-type-"+a.num,w.rx=3,w.ry=3,qK(p,w),FFe(f)(a.text,p,w.x,w.y,w.width,w.height,{class:"journey-section section-type-"+a.num},f,a.colour)};let RFe=-1;const PGt=function(i,a,f){const p=a.x+f.width/2,w=i.append("g");RFe++;const y=300+5*30;w.append("line").attr("id","task"+RFe).attr("x1",p).attr("y1",a.y).attr("x2",p).attr("y2",y).attr("class","task-line").attr("stroke-width","1px").attr("stroke-dasharray","4 2").attr("stroke","#666"),IGt(w,{cx:p,cy:300+(5-a.score)*30,score:a.score});const b=Age();b.x=a.x,b.y=a.y,b.fill=a.fill,b.width=f.width,b.height=f.height,b.class="task task-type-"+a.num,b.rx=3,b.ry=3,qK(w,b);let E=a.x+14;a.people.forEach(S=>{const N=a.actors[S].color,B={cx:E,cy:a.y,r:7,fill:N,stroke:"#000",title:S,pos:a.actors[S].position};PFe(w,B),E+=10}),FFe(f)(a.task,w,b.x,b.y,b.width,b.height,{class:"task"},f,a.colour)},BGt=function(i,a){qK(i,{x:a.startx,y:a.starty,width:a.stopx-a.startx,height:a.stopy-a.starty,fill:a.fill,class:"rect"}).lower()},RGt=function(){return{x:0,y:0,fill:void 0,"text-anchor":"start",width:100,height:100,textMargin:0,rx:0,ry:0}},Age=function(){return{x:0,y:0,width:100,anchor:"start",height:100,rx:0,ry:0}},FFe=function(){function i(w,y,b,E,S,N,B,R){const j=y.append("text").attr("x",b+S/2).attr("y",E+N/2+5).style("font-color",R).style("text-anchor","middle").text(w);p(j,B)}function a(w,y,b,E,S,N,B,R,j){const{taskFontSize:$,taskFontFamily:V}=R,Q=w.split(//gi);for(let oe=0;oe{const w=I5[p].color,y={cx:20,cy:f,r:7,fill:w,stroke:"#000",pos:I5[p].position};HP.drawCircle(i,y);const b={x:40,y:f+7,fill:"#666",text:p,textMargin:a.boxTextMargin|5};HP.drawText(i,b),f+=20})}const VK=Tt().journey,b9=VK.leftMargin,$Gt=function(i,a,f,p){const w=Tt().journey;p.db.clear(),p.parser.parse(i+` +`);const y=Tt().securityLevel;let b;y==="sandbox"&&(b=Cr("#i"+a));const E=Cr(y==="sandbox"?b.nodes()[0].contentDocument.body:"body");Qb.init();const S=E.select("#"+a);HP.initGraphics(S);const N=p.db.getTasks(),B=p.db.getDiagramTitle(),R=p.db.getActors();for(const ce in I5)delete I5[ce];let j=0;R.forEach(ce=>{I5[ce]={color:w.actorColours[j%w.actorColours.length],position:j},j++}),jGt(S),Qb.insert(0,0,b9,Object.keys(I5).length*50),HGt(S,N,0);const $=Qb.getBounds();B&&S.append("text").text(B).attr("x",b9).attr("font-size","4ex").attr("font-weight","bold").attr("y",25);const V=$.stopy-$.starty+2*w.diagramMarginY,Q=b9+$.stopx+2*w.diagramMarginX;Vw(S,V,Q,w.useMaxWidth),S.append("line").attr("x1",b9).attr("y1",w.height*4).attr("x2",Q-b9-4).attr("y2",w.height*4).attr("stroke-width",4).attr("stroke","black").attr("marker-end","url(#arrowhead)");const oe=B?70:0;S.attr("viewBox",`${$.startx} -25 ${Q} ${V+oe}`),S.attr("preserveAspectRatio","xMinYMin meet"),S.attr("height",V+oe+25)},Qb={data:{startx:void 0,stopx:void 0,starty:void 0,stopy:void 0},verticalPos:0,sequenceItems:[],init:function(){this.sequenceItems=[],this.data={startx:void 0,stopx:void 0,starty:void 0,stopy:void 0},this.verticalPos=0},updateVal:function(i,a,f,p){i[a]===void 0?i[a]=f:i[a]=p(f,i[a])},updateBounds:function(i,a,f,p){const w=Tt().journey,y=this;let b=0;function E(S){return function(B){b++;const R=y.sequenceItems.length-b+1;y.updateVal(B,"starty",a-R*w.boxMargin,Math.min),y.updateVal(B,"stopy",p+R*w.boxMargin,Math.max),y.updateVal(Qb.data,"startx",i-R*w.boxMargin,Math.min),y.updateVal(Qb.data,"stopx",f+R*w.boxMargin,Math.max),S!=="activation"&&(y.updateVal(B,"startx",i-R*w.boxMargin,Math.min),y.updateVal(B,"stopx",f+R*w.boxMargin,Math.max),y.updateVal(Qb.data,"starty",a-R*w.boxMargin,Math.min),y.updateVal(Qb.data,"stopy",p+R*w.boxMargin,Math.max))}}this.sequenceItems.forEach(E())},insert:function(i,a,f,p){const w=Math.min(i,f),y=Math.max(i,f),b=Math.min(a,p),E=Math.max(a,p);this.updateVal(Qb.data,"startx",w,Math.min),this.updateVal(Qb.data,"starty",b,Math.min),this.updateVal(Qb.data,"stopx",y,Math.max),this.updateVal(Qb.data,"stopy",E,Math.max),this.updateBounds(w,b,y,E)},bumpVerticalPos:function(i){this.verticalPos=this.verticalPos+i,this.data.stopy=this.verticalPos},getVerticalPos:function(){return this.verticalPos},getBounds:function(){return this.data}},Lge=VK.sectionFills,jFe=VK.sectionColours,HGt=function(i,a,f){const p=Tt().journey;let w="";const y=p.height*2+p.diagramMarginY,b=f+y;let E=0,S="#CCC",N="black",B=0;for(const[R,j]of a.entries()){if(w!==j.section){S=Lge[E%Lge.length],B=E%Lge.length,N=jFe[E%jFe.length];let V=0;const Q=j.section;for(let ce=R;ce(I5[Q]&&(V[Q]=I5[Q]),V),{});j.x=R*p.taskMargin+R*p.width+b9,j.y=b,j.width=p.diagramMarginX,j.height=p.diagramMarginY,j.colour=N,j.fill=S,j.num=B,j.actors=$,HP.drawTask(i,j,p),Qb.insert(j.x,j.y,j.x+j.width+p.taskMargin,300+5*30)}},$Fe={setConf:FGt,draw:$Gt},zGt=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:xGt,db:NFe,renderer:$Fe,styles:DGt,init:i=>{$Fe.setConf(i.journey),NFe.clear()}}},Symbol.toStringTag,{value:"Module"})),GGt=(i,a,f)=>{const{parentById:p}=f,w=new Set;let y=i;for(;y;){if(w.add(y),y===a)return y;y=p[y]}for(y=a;y;){if(w.has(y))return y;y=p[y]}return"root"};function UK(i){throw new Error('Could not dynamically require "'+i+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var Mge={},qGt={get exports(){return Mge},set exports(i){Mge=i}};(function(i,a){(function(f){i.exports=f()})(function(){return function(){function f(p,w,y){function b(N,B){if(!w[N]){if(!p[N]){var R=typeof UK=="function"&&UK;if(!B&&R)return R(N,!0);if(E)return E(N,!0);var j=new Error("Cannot find module '"+N+"'");throw j.code="MODULE_NOT_FOUND",j}var $=w[N]={exports:{}};p[N][0].call($.exports,function(V){var Q=p[N][1][V];return b(Q||V)},$,$.exports,f,p,w,y)}return w[N].exports}for(var E=typeof UK=="function"&&UK,S=0;S0&&arguments[0]!==void 0?arguments[0]:{},j=R.defaultLayoutOptions,$=j===void 0?{}:j,V=R.algorithms,Q=V===void 0?["layered","stress","mrtree","radial","force","disco","sporeOverlap","sporeCompaction","rectpacking"]:V,oe=R.workerFactory,ce=R.workerUrl;if(b(this,N),this.defaultLayoutOptions=$,this.initialized=!1,typeof ce>"u"&&typeof oe>"u")throw new Error("Cannot construct an ELK without both 'workerUrl' and 'workerFactory'.");var se=oe;typeof ce<"u"&&typeof oe>"u"&&(se=function(ke){return new Worker(ke)});var ge=se(ce);if(typeof ge.postMessage!="function")throw new TypeError("Created worker does not provide the required 'postMessage' function.");this.worker=new S(ge),this.worker.postMessage({cmd:"register",algorithms:Q}).then(function(ye){return B.initialized=!0}).catch(console.err)}return y(N,[{key:"layout",value:function(R){var j=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},$=j.layoutOptions,V=$===void 0?this.defaultLayoutOptions:$,Q=j.logging,oe=Q===void 0?!1:Q,ce=j.measureExecutionTime,se=ce===void 0?!1:ce;return R?this.worker.postMessage({cmd:"layout",graph:R,layoutOptions:V,options:{logging:oe,measureExecutionTime:se}}):Promise.reject(new Error("Missing mandatory parameter 'graph'."))}},{key:"knownLayoutAlgorithms",value:function(){return this.worker.postMessage({cmd:"algorithms"})}},{key:"knownLayoutOptions",value:function(){return this.worker.postMessage({cmd:"options"})}},{key:"knownLayoutCategories",value:function(){return this.worker.postMessage({cmd:"categories"})}},{key:"terminateWorker",value:function(){this.worker.terminate()}}]),N}();w.default=E;var S=function(){function N(B){var R=this;if(b(this,N),B===void 0)throw new Error("Missing mandatory parameter 'worker'.");this.resolvers={},this.worker=B,this.worker.onmessage=function(j){setTimeout(function(){R.receive(R,j)},0)}}return y(N,[{key:"postMessage",value:function(R){var j=this.id||0;this.id=j+1,R.id=j;var $=this;return new Promise(function(V,Q){$.resolvers[j]=function(oe,ce){oe?($.convertGwtStyleError(oe),Q(oe)):V(ce)},$.worker.postMessage(R)})}},{key:"receive",value:function(R,j){var $=j.data,V=R.resolvers[$.id];V&&(delete R.resolvers[$.id],$.error?V($.error):V(null,$.data))}},{key:"terminate",value:function(){this.worker.terminate&&this.worker.terminate()}},{key:"convertGwtStyleError",value:function(R){if(R){var j=R.__java$exception;j&&(j.cause&&j.cause.backingJsObject&&(R.cause=j.cause.backingJsObject,this.convertGwtStyleError(R.cause)),delete R.__java$exception)}}}]),N}()},{}],2:[function(f,p,w){(function(y){(function(){var b;typeof window<"u"?b=window:typeof y<"u"?b=y:typeof self<"u"&&(b=self);var E;function S(){}function N(){}function B(){}function R(){}function j(){}function $(){}function V(){}function Q(){}function oe(){}function ce(){}function se(){}function ge(){}function ye(){}function ke(){}function Ae(){}function de(){}function ve(){}function te(){}function xe(){}function De(){}function he(){}function Ie(){}function ee(){}function rt(){}function me(){}function gt(){}function pe(){}function Et(){}function wt(){}function jt(){}function At(){}function Bt(){}function cn(){}function Nn(){}function Ot(){}function oi(){}function kt(){}function Dt(){}function vt(){}function Nt(){}function ze(){}function Xe(){}function Lt(){}function Ge(){}function Bn(){}function Oe(){}function Ri(){}function tn(){}function hi(){}function Sr(){}function Zn(){}function Xn(){}function ir(){}function Hn(){}function tr(){}function ha(){}function Zs(){}function ns(){}function Hi(){}function Js(){}function Pc(){}function Ga(){}function ws(){}function Oi(){}function Er(){}function br(){}function Dr(){}function Vn(){}function qi(){}function yn(){}function Bc(){}function jn(){}function Ms(){}function Pa(){}function Ta(){}function _a(){}function ka(){}function Qi(){}function ea(){}function Ca(){}function Sa(){}function Ka(){}function cg(){}function Gc(){}function Dh(){}function Es(){}function lp(){}function sd(){}function sh(){}function Ai(){}function nn(){}function Tr(){}function ai(){}function Ns(){}function mc(){}function yu(){}function Mo(){}function ku(){}function Ih(){}function qf(){}function lx(){}function ad(){}function b3(){}function bL(){}function im(){}function ug(){}function rs(){}function Ps(){}function Aa(){}function pi(){}function Rc(){}function _t(){}function hp(){}function Gt(){}function ff(){}function sm(){}function m9(){}function fp(){}function N5(){}function ah(){}function od(){}function P5(){}function B5(){}function y9(){}function vL(){}function v1(){}function dp(){}function cd(){}function am(){}function ev(){}function om(){}function yc(){}function hx(){}function Vo(){}function fx(){}function oh(){}function QK(){}function k9(){}function ZK(){}function GP(){}function Vf(){}function cm(){}function wL(){}function qP(){}function gp(){}function um(){}function JK(){}function R2(){}function eY(){}function tY(){}function R5(){}function x9(){}function VP(){}function dx(){}function nY(){}function gx(){}function rY(){}function iY(){}function sY(){}function aY(){}function oY(){}function cY(){}function uY(){}function lY(){}function hY(){}function fY(){}function dY(){}function mL(){}function gY(){}function pY(){}function E9(){}function UP(){}function F5(){}function bY(){}function vY(){}function wY(){}function mY(){}function yY(){}function T9(){}function yL(){}function WP(){}function v3(){}function w3(){}function kY(){}function df(){}function j5(){}function xY(){}function px(){}function zd(){}function EY(){}function TY(){}function _Y(){}function CY(){}function _9(){}function kL(){}function KP(){}function xL(){}function $5(){}function SY(){}function YP(){}function XP(){}function AY(){}function LY(){}function MY(){}function DY(){}function IY(){}function OY(){}function Gd(){}function tv(){}function NY(){}function QP(){}function ZP(){}function PY(){}function m3(){}function bx(){}function EL(){}function lm(){}function vx(){}function BY(){}function C9(){}function ud(){}function JP(){}function TL(){}function wx(){}function _L(){}function eB(){}function RY(){}function CL(){}function FY(){}function jY(){}function tB(){}function H5(){}function nB(){}function z5(){}function $Y(){}function SL(){}function HY(){}function zY(){}function GY(){}function qY(){}function rB(){}function VY(){}function UY(){}function WY(){}function iB(){}function KY(){}function YY(){}function XY(){}function sB(){}function QY(){}function ZY(){}function aB(){}function oB(){}function cB(){}function JY(){}function eX(){}function mx(){}function G5(){}function S9(){}function tX(){}function AL(){}function A9(){}function LL(){}function uB(){}function lB(){}function nX(){}function rX(){}function iX(){}function hB(){}function fB(){}function sX(){}function aX(){}function oX(){}function cX(){}function uX(){}function dB(){}function lX(){}function hX(){}function fX(){}function dX(){}function gB(){}function L9(){}function gX(){}function pX(){}function pB(){}function bX(){}function vX(){}function wX(){}function mX(){}function yX(){}function kX(){}function bB(){}function xX(){}function vB(){}function EX(){}function TX(){}function _X(){}function M9(){}function CX(){}function D9(){}function SX(){}function wB(){}function mB(){}function yB(){}function kB(){}function nv(){}function xB(){}function EB(){}function TB(){}function _B(){}function AX(){}function q5(){}function I9(){}function y3(){}function LX(){}function MX(){}function O9(){}function DX(){}function IX(){}function OX(){}function NX(){}function PX(){}function BX(){}function RX(){}function FX(){}function jX(){}function $X(){}function HX(){}function ML(){}function CB(){}function zX(){}function GX(){}function qX(){}function SB(){}function VX(){}function UX(){}function WX(){}function KX(){}function YX(){}function XX(){}function AB(){}function LB(){}function QX(){}function MB(){}function DB(){}function ZX(){}function JX(){}function eQ(){}function DL(){}function tQ(){}function yx(){}function nQ(){}function rQ(){}function iQ(){}function IB(){}function sQ(){}function aQ(){}function oQ(){}function cQ(){}function uQ(){}function lQ(){}function hQ(){}function fQ(){}function dQ(){}function gQ(){}function pQ(){}function bQ(){}function V5(){}function OB(){}function vQ(){}function wQ(){}function mQ(){}function NB(){}function yQ(){}function N9(){}function kQ(){}function xQ(){}function EQ(){}function TQ(){}function _Q(){}function CQ(){}function SQ(){}function AQ(){}function LQ(){}function MQ(){}function U5(){}function DQ(){}function IQ(){}function OQ(){}function NQ(){}function PQ(){}function BQ(){}function RQ(){}function FQ(){}function P9(){}function jQ(){}function $Q(){}function HQ(){}function zQ(){}function GQ(){}function qQ(){}function VQ(){}function UQ(){}function W5(){}function PB(){}function WQ(){}function IL(){}function KQ(){}function YQ(){}function XQ(){}function QQ(){}function ZQ(){}function JQ(){}function eZ(){}function BB(){}function tZ(){}function RB(){}function nZ(){}function FB(){}function jB(){}function $B(){}function rZ(){}function iZ(){}function B9(){}function OL(){}function R9(){}function sZ(){}function aZ(){}function NL(){}function oZ(){}function cZ(){}function HB(){}function uZ(){}function lZ(){}function hZ(){}function fZ(){}function dZ(){}function gZ(){}function pZ(){}function bZ(){}function vZ(){}function wZ(){}function lg(){}function mZ(){}function hm(){}function zB(){}function yZ(){}function kZ(){}function xZ(){}function EZ(){}function TZ(){}function _Z(){}function CZ(){}function SZ(){}function AZ(){}function Fc(){}function LZ(){}function F9(){}function lc(){}function iu(){}function Ki(){}function PL(){}function MZ(){}function DZ(){}function IZ(){}function K5(){}function fm(){}function Ht(){}function OZ(){}function NZ(){}function PZ(){}function BZ(){}function RZ(){}function GB(){}function FZ(){}function jZ(){}function BL(){}function $Z(){}function rl(){}function Hu(){}function HZ(){}function zZ(){}function GZ(){}function dm(){}function rv(){}function pp(){}function ld(){}function Y5(){}function j9(){}function kx(){}function qB(){}function qZ(){}function xx(){}function VB(){}function VZ(){}function $9(){}function X5(){}function Q5(){}function bp(){}function UB(){}function Ex(){}function WB(){}function KB(){}function Z5(){}function F2(){}function E0(){}function vp(){}function k3(){}function Tx(){}function H9(){}function YB(){}function UZ(){}function XB(){}function QB(){}function ZB(){}function _x(){}function JB(){}function eR(){}function WZ(){}function Cx(){}function Sx(){}function gm(){}function RL(){}function KZ(){}function YZ(){}function XZ(){}function QZ(){}function ZZ(){}function JZ(){}function eJ(){}function tJ(){}function tR(){}function nJ(){}function rJ(){}function iJ(){}function nR(){}function Ax(){}function z9(){}function rR(){}function sJ(){}function iR(){}function sR(){}function aJ(){}function G9(){}function pm(){}function aR(){}function oR(){}function oJ(){}function cJ(){}function q9(){}function cR(){}function uR(){}function kc(){}function uJ(){}function lR(){}function V9(){}function lJ(){}function hJ(){}function U9(){}function hR(){}function W9(){}function K9(){}function Uf(){}function FL(){}function jL(){}function J5(){}function fJ(){}function dJ(){}function gJ(){}function pJ(){}function bm(){}function fR(){}function e6(){}function w1(){}function dR(){}function gR(){}function pR(){}function bR(){}function vR(){}function wR(){}function Wf(){}function xu(){}function bJ(){}function vJ(){}function wJ(){}function Eu(){}function Y9(){}function mR(){}function yR(){}function t6(){}function mJ(){}function Lx(){}function yJ(){}function kR(){}function kJ(){}function xJ(){}function X9(){}function xR(){}function $L(){}function Q9(){}function EJ(){}function TJ(){}function HL(){}function Z9(){}function m1(){}function Mx(){}function _J(){}function Dx(){}function zL(){}function j2(){}function J9(){}function GL(){}function Kf(){}function eT(){}function y1(){}function k1(){}function CJ(){}function SJ(){}function x3(){}function Ix(){}function Ox(){}function tT(){}function AJ(){}function n6(){}function qL(){}function ER(){}function LJ(){}function nT(){kT()}function MJ(){Tie()}function TR(){K_()}function VL(){GH()}function DJ(){m4e()}function rT(){a1()}function IJ(){M3e()}function OJ(){ZD()}function NJ(){vM()}function PJ(){bM()}function BJ(){GM()}function _R(){AGe()}function RJ(){U6()}function FJ(){TF()}function jJ(){jZe()}function CR(){ett()}function $J(){vJe()}function HJ(){NXe()}function iT(){X8()}function zJ(){Xp()}function GJ(){ttt()}function qJ(){SQe()}function VJ(){f6e()}function UJ(){zit()}function WJ(){PXe()}function SR(){pt()}function KJ(){OXe()}function AR(){ntt()}function YJ(){snt()}function UL(){RXe()}function XJ(){xJe()}function LR(){LGe()}function QJ(){e5e()}function MR(){Jm()}function ZJ(){Ltt()}function DR(){nI()}function IR(){Jse()}function OR(){ase()}function WL(){nw()}function E3(){Xme()}function sT(){BXe()}function hd(){Xct()}function NR(){Q4e()}function Nx(){Vse()}function KL(){A$()}function JJ(){XH()}function wp(){bi()}function PR(){hH()}function BR(){i3e()}function RR(){pz()}function ch(){EWe()}function YL(){cie()}function FR(){F5e()}function Px(e){Sn(e)}function aT(e){this.a=e}function Bx(e){this.a=e}function jR(e){this.a=e}function r6(e){this.a=e}function iv(e){this.a=e}function Rx(e){this.a=e}function $R(e){this.a=e}function eee(e){this.a=e}function XL(e){this.a=e}function T3(e){this.a=e}function QL(e){this.a=e}function oT(e){this.a=e}function tee(e){this.a=e}function cT(e){this.a=e}function uT(e){this.a=e}function i6(e){this.a=e}function ZL(e){this.a=e}function JL(e){this.a=e}function nee(e){this.a=e}function ree(e){this.a=e}function iee(e){this.a=e}function HR(e){this.b=e}function see(e){this.c=e}function aee(e){this.a=e}function oee(e){this.a=e}function cee(e){this.a=e}function uee(e){this.a=e}function lee(e){this.a=e}function hee(e){this.a=e}function fee(e){this.a=e}function dee(e){this.a=e}function s6(e){this.a=e}function gee(e){this.a=e}function Fx(e){this.a=e}function Oh(e){this.a=e}function pee(e){this.a=e}function a6(e){this.a=e}function jx(e){this.a=e}function lT(e){this.a=e}function $x(e){this.a=e}function hg(){this.a=[]}function bee(e,t){e.a=t}function jge(e,t){e.a=t}function $ge(e,t){e.b=t}function Hge(e,t){e.b=t}function zge(e,t){e.b=t}function eM(e,t){e.j=t}function Gge(e,t){e.g=t}function qge(e,t){e.i=t}function vee(e,t){e.c=t}function x1(e,t){e.d=t}function wee(e,t){e.d=t}function Vge(e,t){e.c=t}function T0(e,t){e.k=t}function mee(e,t){e.c=t}function zR(e,t){e.c=t}function GR(e,t){e.a=t}function yee(e,t){e.a=t}function Uge(e,t){e.f=t}function Wge(e,t){e.a=t}function sv(e,t){e.b=t}function tM(e,t){e.d=t}function hT(e,t){e.i=t}function qR(e,t){e.o=t}function Kge(e,t){e.r=t}function Yge(e,t){e.a=t}function VR(e,t){e.b=t}function av(e,t){e.e=t}function kee(e,t){e.f=t}function fT(e,t){e.g=t}function o6(e,t){e.e=t}function Xge(e,t){e.f=t}function Hx(e,t){e.f=t}function xee(e,t){e.n=t}function fg(e,t){e.a=t}function Qge(e,t){e.a=t}function _3(e,t){e.c=t}function Eee(e,t){e.c=t}function Tee(e,t){e.d=t}function UR(e,t){e.e=t}function WR(e,t){e.g=t}function _ee(e,t){e.a=t}function zx(e,t){e.c=t}function dT(e,t){e.d=t}function Zge(e,t){e.e=t}function Cee(e,t){e.f=t}function See(e,t){e.j=t}function Aee(e,t){e.a=t}function Jge(e,t){e.b=t}function Ac(e,t){e.a=t}function KR(e){e.b=e.a}function Lee(e){e.c=e.d.d}function c6(e){this.d=e}function dg(e){this.a=e}function vm(e){this.a=e}function nM(e){this.a=e}function E1(e){this.a=e}function u6(e){this.a=e}function Mee(e){this.a=e}function YR(e){this.a=e}function C3(e){this.a=e}function rM(e){this.a=e}function wm(e){this.a=e}function XR(e){this.a=e}function T1(e){this.a=e}function m(e){this.a=e}function g(e){this.a=e}function k(e){this.b=e}function T(e){this.b=e}function A(e){this.b=e}function D(e){this.a=e}function I(e){this.a=e}function F(e){this.a=e}function H(e){this.c=e}function C(e){this.c=e}function G(e){this.c=e}function U(e){this.a=e}function Z(e){this.a=e}function ne(e){this.a=e}function ae(e){this.a=e}function ue(e){this.a=e}function _e(e){this.a=e}function be(e){this.a=e}function Se(e){this.a=e}function Le(e){this.a=e}function Be(e){this.a=e}function Ke(e){this.a=e}function qe(e){this.a=e}function Re(e){this.a=e}function Ze(e){this.a=e}function $e(e){this.a=e}function ot(e){this.a=e}function ut(e){this.a=e}function Je(e){this.a=e}function Ct(e){this.a=e}function lt(e){this.a=e}function un(e){this.a=e}function Rt(e){this.a=e}function $t(e){this.a=e}function bn(e){this.a=e}function Cn(e){this.a=e}function Kn(e){this.a=e}function kn(e){this.a=e}function Wn(e){this.a=e}function sr(e){this.a=e}function yr(e){this.a=e}function hr(e){this.a=e}function nr(e){this.a=e}function fn(e){this.a=e}function vr(e){this.a=e}function gr(e){this.a=e}function ni(e){this.a=e}function Ti(e){this.a=e}function ia(e){this.a=e}function Ba(e){this.a=e}function Li(e){this.a=e}function wi(e){this.a=e}function Ts(e){this.a=e}function Yi(e){this.a=e}function Di(e){this.a=e}function es(e){this.a=e}function eo(e){this.e=e}function sa(e){this.a=e}function Ks(e){this.a=e}function Ar(e){this.a=e}function We(e){this.a=e}function On(e){this.a=e}function Ir(e){this.a=e}function ar(e){this.a=e}function or(e){this.a=e}function qa(e){this.a=e}function qr(e){this.a=e}function is(e){this.a=e}function Uo(e){this.a=e}function qc(e){this.a=e}function uo(e){this.a=e}function Lc(e){this.a=e}function Ra(e){this.a=e}function lo(e){this.a=e}function Sl(e){this.a=e}function Yf(e){this.a=e}function mp(e){this.a=e}function yp(e){this.a=e}function Xf(e){this.a=e}function gg(e){this.a=e}function fd(e){this.a=e}function ov(e){this.a=e}function mm(e){this.a=e}function l6(e){this.a=e}function S3(e){this.a=e}function h6(e){this.a=e}function gT(e){this.a=e}function A3(e){this.a=e}function qd(e){this.a=e}function _1(e){this.a=e}function Vd(e){this.a=e}function pT(e){this.a=e}function $2(e){this.a=e}function QR(e){this.a=e}function Dee(e){this.a=e}function Iee(e){this.a=e}function Oee(e){this.a=e}function Nee(e){this.a=e}function Pee(e){this.a=e}function Bee(e){this.a=e}function Ree(e){this.a=e}function Gx(e){this.a=e}function iM(e){this.a=e}function bT(e){this.a=e}function ZR(e){this.a=e}function JR(e){this.a=e}function Fee(e){this.a=e}function kp(e){this.a=e}function sM(e){this.a=e}function eF(e){this.a=e}function qx(e){this.c=e}function xp(e){this.b=e}function jee(e){this.a=e}function wje(e){this.a=e}function mje(e){this.a=e}function yje(e){this.a=e}function kje(e){this.a=e}function xje(e){this.a=e}function Eje(e){this.a=e}function Tje(e){this.a=e}function _je(e){this.a=e}function Cje(e){this.a=e}function Sje(e){this.a=e}function Aje(e){this.a=e}function Lje(e){this.a=e}function Mje(e){this.a=e}function Dje(e){this.a=e}function Ije(e){this.a=e}function Oje(e){this.a=e}function Nje(e){this.a=e}function Pje(e){this.a=e}function Bje(e){this.a=e}function Rje(e){this.a=e}function Fje(e){this.a=e}function jje(e){this.a=e}function $je(e){this.a=e}function Ep(e){this.a=e}function f6(e){this.a=e}function Hje(e){this.a=e}function zje(e){this.a=e}function Gje(e){this.a=e}function qje(e){this.a=e}function Vje(e){this.a=e}function Uje(e){this.a=e}function Wje(e){this.a=e}function Kje(e){this.a=e}function Yje(e){this.a=e}function Xje(e){this.a=e}function Qje(e){this.a=e}function Zje(e){this.a=e}function Jje(e){this.a=e}function e$e(e){this.a=e}function t$e(e){this.a=e}function n$e(e){this.a=e}function tF(e){this.a=e}function r$e(e){this.a=e}function i$e(e){this.a=e}function s$e(e){this.a=e}function a$e(e){this.a=e}function o$e(e){this.a=e}function c$e(e){this.a=e}function u$e(e){this.a=e}function l$e(e){this.a=e}function h$e(e){this.a=e}function f$e(e){this.a=e}function d$e(e){this.a=e}function g$e(e){this.a=e}function p$e(e){this.a=e}function b$e(e){this.a=e}function v$e(e){this.a=e}function w$e(e){this.a=e}function m$e(e){this.a=e}function y$e(e){this.a=e}function k$e(e){this.a=e}function x$e(e){this.a=e}function E$e(e){this.a=e}function T$e(e){this.a=e}function _$e(e){this.a=e}function C$e(e){this.a=e}function S$e(e){this.a=e}function A$e(e){this.a=e}function L$e(e){this.a=e}function M$e(e){this.a=e}function epe(e){this.a=e}function Zi(e){this.b=e}function D$e(e){this.f=e}function tpe(e){this.a=e}function I$e(e){this.a=e}function O$e(e){this.a=e}function N$e(e){this.a=e}function P$e(e){this.a=e}function B$e(e){this.a=e}function R$e(e){this.a=e}function F$e(e){this.a=e}function j$e(e){this.a=e}function aM(e){this.a=e}function $$e(e){this.a=e}function H$e(e){this.b=e}function npe(e){this.c=e}function nF(e){this.e=e}function z$e(e){this.a=e}function rF(e){this.a=e}function iF(e){this.a=e}function $ee(e){this.a=e}function G$e(e){this.a=e}function q$e(e){this.d=e}function rpe(e){this.a=e}function ipe(e){this.a=e}function cv(e){this.e=e}function nVt(){this.a=0}function L3(){EVe(this)}function st(){Ute(this)}function Mr(){sl(this)}function Hee(){SYe(this)}function V$e(){}function uv(){this.c=FAe}function rVt(e,t){t.Wb(e)}function U$e(e,t){e.b+=t}function W$e(e){e.b=new ite}function J(e){return e.e}function iVt(e){return e.a}function sVt(e){return e.a}function aVt(e){return e.a}function oVt(e){return e.a}function cVt(e){return e.a}function uVt(){return null}function lVt(){return null}function hVt(){qpe(),xyn()}function fVt(e){e.b.tf(e.e)}function vT(e,t){e.b=t-e.b}function wT(e,t){e.a=t-e.a}function K$e(e,t){t.ad(e.a)}function dVt(e,t){Vs(t,e)}function gVt(e,t,n){e.Od(n,t)}function oM(e,t){e.e=t,t.b=e}function spe(e){wd(),this.a=e}function Y$e(e){wd(),this.a=e}function X$e(e){wd(),this.a=e}function ape(e){Rm(),this.a=e}function Q$e(e){k8(),mue.be(e)}function H2(){aUe.call(this)}function ope(){aUe.call(this)}function cpe(){H2.call(this)}function zee(){H2.call(this)}function Z$e(){H2.call(this)}function cM(){H2.call(this)}function zu(){H2.call(this)}function mT(){H2.call(this)}function Fr(){H2.call(this)}function uh(){H2.call(this)}function J$e(){H2.call(this)}function xc(){H2.call(this)}function eHe(){H2.call(this)}function tHe(){this.a=this}function sF(){this.Bb|=256}function nHe(){this.b=new iVe}function upe(){upe=pe,new Mr}function lpe(){cpe.call(this)}function rHe(e,t){e.length=t}function aF(e,t){it(e.a,t)}function pVt(e,t){k4e(e.c,t)}function bVt(e,t){Gs(e.b,t)}function vVt(e,t){RH(e.a,t)}function wVt(e,t){Oie(e.a,t)}function Vx(e,t){_i(e.e,t)}function d6(e){JH(e.c,e.b)}function mVt(e,t){e.kc().Nb(t)}function hpe(e){this.a=von(e)}function Ys(){this.a=new Mr}function iHe(){this.a=new Mr}function oF(){this.a=new st}function Gee(){this.a=new st}function fpe(){this.a=new st}function Nh(){this.a=new Bc}function z2(){this.a=new PZe}function dpe(){this.a=new m9}function gpe(){this.a=new yGe}function sHe(){this.a=new cQe}function ppe(){this.a=new TXe}function bpe(){this.a=new KUe}function aHe(){this.a=new st}function vpe(){this.a=new st}function oHe(){this.a=new st}function cHe(){this.a=new st}function uHe(){this.d=new st}function lHe(){this.a=new Ys}function hHe(){this.a=new Mr}function fHe(){this.b=new Mr}function dHe(){this.b=new st}function wpe(){this.e=new st}function gHe(){this.d=new st}function pHe(){this.a=new zJ}function bHe(){st.call(this)}function mpe(){oF.call(this)}function vHe(){bj.call(this)}function wHe(){vpe.call(this)}function qee(){yT.call(this)}function yT(){V$e.call(this)}function g6(){V$e.call(this)}function ype(){g6.call(this)}function mHe(){tXe.call(this)}function yHe(){tXe.call(this)}function kHe(){Spe.call(this)}function xHe(){Spe.call(this)}function EHe(){Spe.call(this)}function THe(){Ape.call(this)}function Gu(){as.call(this)}function kpe(){dm.call(this)}function xpe(){dm.call(this)}function _He(){HHe.call(this)}function CHe(){HHe.call(this)}function SHe(){Mr.call(this)}function AHe(){Mr.call(this)}function LHe(){Mr.call(this)}function MHe(){Ys.call(this)}function Vee(){Qet.call(this)}function DHe(){sF.call(this)}function Uee(){Z2e.call(this)}function Wee(){Z2e.call(this)}function Epe(){Mr.call(this)}function Kee(){Mr.call(this)}function IHe(){Mr.call(this)}function Tpe(){Ex.call(this)}function OHe(){Ex.call(this)}function NHe(){Tpe.call(this)}function PHe(){qL.call(this)}function BHe(e){ket.call(this,e)}function RHe(e){ket.call(this,e)}function _pe(e){XL.call(this,e)}function Cpe(e){lGe.call(this,e)}function yVt(e){Cpe.call(this,e)}function kVt(e){lGe.call(this,e)}function Ux(){this.a=new as}function Spe(){this.a=new Ys}function Ape(){this.a=new Mr}function FHe(){this.a=new st}function jHe(){this.j=new st}function Lpe(){this.a=new $B}function $He(){this.a=new Pze}function HHe(){this.a=new UB}function Yee(){Yee=pe,due=new sze}function Xee(){Xee=pe,fue=new ize}function kT(){kT=pe,hue=new N}function cF(){cF=pe,bue=new iUe}function xVt(e){Cpe.call(this,e)}function EVt(e){Cpe.call(this,e)}function zHe(e){Cre.call(this,e)}function GHe(e){Cre.call(this,e)}function qHe(e){bWe.call(this,e)}function Qee(e){Gfn.call(this,e)}function lv(e){Em.call(this,e)}function xT(e){yF.call(this,e)}function Mpe(e){yF.call(this,e)}function VHe(e){yF.call(this,e)}function tc(e){MKe.call(this,e)}function UHe(e){tc.call(this,e)}function p6(){$x.call(this,{})}function uF(e){a8(),this.a=e}function ET(e){e.b=null,e.c=0}function TVt(e,t){e.e=t,Yot(e,t)}function _Vt(e,t){e.a=t,L1n(e)}function Zee(e,t,n){e.a[t.g]=n}function CVt(e,t,n){Vln(n,e,t)}function SVt(e,t){ZKt(t.i,e.n)}function WHe(e,t){Jsn(e).td(t)}function AVt(e,t){return e*e/t}function KHe(e,t){return e.g-t.g}function LVt(e){return new lT(e)}function MVt(e){return new Bm(e)}function lF(e){tc.call(this,e)}function Do(e){tc.call(this,e)}function YHe(e){tc.call(this,e)}function Jee(e){MKe.call(this,e)}function ete(e){Kme(),this.a=e}function XHe(e){xWe(),this.a=e}function ym(e){Mne(),this.f=e}function tte(e){Mne(),this.f=e}function Wx(e){tc.call(this,e)}function Ln(e){tc.call(this,e)}function Wo(e){tc.call(this,e)}function QHe(e){tc.call(this,e)}function b6(e){tc.call(this,e)}function It(e){return Sn(e),e}function Ue(e){return Sn(e),e}function uM(e){return Sn(e),e}function Dpe(e){return Sn(e),e}function DVt(e){return Sn(e),e}function TT(e){return e.b==e.c}function km(e){return!!e&&e.b}function IVt(e){return!!e&&e.k}function OVt(e){return!!e&&e.j}function Al(e){Sn(e),this.a=e}function Ipe(e){return ab(e),e}function _T(e){qve(e,e.length)}function pg(e){tc.call(this,e)}function dd(e){tc.call(this,e)}function nte(e){tc.call(this,e)}function M3(e){tc.call(this,e)}function CT(e){tc.call(this,e)}function $r(e){tc.call(this,e)}function rte(e){bbe.call(this,e,0)}function ite(){Twe.call(this,12,3)}function Ope(){Ope=pe,N8e=new xe}function ZHe(){ZHe=pe,O8e=new S}function hF(){hF=pe,YC=new ye}function JHe(){JHe=pe,M0t=new Ae}function eze(){throw J(new Fr)}function Npe(){throw J(new Fr)}function tze(){throw J(new Fr)}function NVt(){throw J(new Fr)}function PVt(){throw J(new Fr)}function BVt(){throw J(new Fr)}function ste(){this.a=Hr(Nr(io))}function v6(e){wd(),this.a=Nr(e)}function nze(e,t){e.Td(t),t.Sd(e)}function RVt(e,t){e.a.ec().Mc(t)}function FVt(e,t,n){e.c.lf(t,n)}function Ppe(e){Do.call(this,e)}function gd(e){Ln.call(this,e)}function bg(){u6.call(this,"")}function ST(){u6.call(this,"")}function Tp(){u6.call(this,"")}function xm(){u6.call(this,"")}function Bpe(e){Do.call(this,e)}function Kx(e){T.call(this,e)}function ate(e){oj.call(this,e)}function rze(e){Kx.call(this,e)}function ize(){cT.call(this,null)}function sze(){cT.call(this,null)}function fF(){fF=pe,k8()}function aze(){aze=pe,$0t=whn()}function oze(e){return e.a?e.b:0}function jVt(e){return e.a?e.b:0}function $Vt(e,t){return e.a-t.a}function HVt(e,t){return e.a-t.a}function zVt(e,t){return e.a-t.a}function dF(e,t){return gme(e,t)}function re(e,t){return SXe(e,t)}function GVt(e,t){return t in e.a}function cze(e,t){return e.f=t,e}function qVt(e,t){return e.b=t,e}function uze(e,t){return e.c=t,e}function VVt(e,t){return e.g=t,e}function Rpe(e,t){return e.a=t,e}function Fpe(e,t){return e.f=t,e}function UVt(e,t){return e.k=t,e}function jpe(e,t){return e.a=t,e}function WVt(e,t){return e.e=t,e}function $pe(e,t){return e.e=t,e}function KVt(e,t){return e.f=t,e}function YVt(e,t){e.b=!0,e.d=t}function XVt(e,t){e.b=new Io(t)}function QVt(e,t,n){t.td(e.a[n])}function ZVt(e,t,n){t.we(e.a[n])}function JVt(e,t){return e.b-t.b}function eUt(e,t){return e.g-t.g}function tUt(e,t){return e.s-t.s}function nUt(e,t){return e?0:t-1}function lze(e,t){return e?0:t-1}function rUt(e,t){return e?t-1:0}function iUt(e,t){return t.Yf(e)}function hv(e,t){return e.b=t,e}function gF(e,t){return e.a=t,e}function fv(e,t){return e.c=t,e}function dv(e,t){return e.d=t,e}function gv(e,t){return e.e=t,e}function Hpe(e,t){return e.f=t,e}function AT(e,t){return e.a=t,e}function Yx(e,t){return e.b=t,e}function Xx(e,t){return e.c=t,e}function Wt(e,t){return e.c=t,e}function pn(e,t){return e.b=t,e}function Kt(e,t){return e.d=t,e}function Yt(e,t){return e.e=t,e}function sUt(e,t){return e.f=t,e}function Xt(e,t){return e.g=t,e}function Qt(e,t){return e.a=t,e}function Zt(e,t){return e.i=t,e}function Jt(e,t){return e.j=t,e}function hze(e,t){return e.k=t,e}function aUt(e,t){return e.j=t,e}function oUt(e,t){Xp(),rc(t,e)}function cUt(e,t,n){nZt(e.a,t,n)}function fze(e){LYe.call(this,e)}function zpe(e){LYe.call(this,e)}function pF(e){dne.call(this,e)}function dze(e){_on.call(this,e)}function _p(e){jv.call(this,e)}function gze(e){tre.call(this,e)}function pze(e){tre.call(this,e)}function bze(){W2e.call(this,"")}function Fa(){this.a=0,this.b=0}function vze(){this.b=0,this.a=0}function wze(e,t){e.b=0,Wm(e,t)}function uUt(e,t){e.c=t,e.b=!0}function mze(e,t){return e.c._b(t)}function Qf(e){return e.e&&e.e()}function ote(e){return e?e.d:null}function yze(e,t){return Knt(e.b,t)}function lUt(e){return e?e.g:null}function hUt(e){return e?e.i:null}function Cp(e){return S0(e),e.o}function pv(){pv=pe,F3t=Lln()}function kze(){kze=pe,la=Hhn()}function Qx(){Qx=pe,RAe=Dln()}function xze(){xze=pe,x4t=Mln()}function Gpe(){Gpe=pe,Sc=C1n()}function qpe(){qpe=pe,x2=F8()}function Eze(){throw J(new Fr)}function Tze(){throw J(new Fr)}function _ze(){throw J(new Fr)}function Cze(){throw J(new Fr)}function Sze(){throw J(new Fr)}function Aze(){throw J(new Fr)}function bF(e){this.a=new w6(e)}function Vpe(e){_lt(),Pyn(this,e)}function Sp(e){this.a=new Nne(e)}function D3(e,t){for(;e.ye(t););}function Upe(e,t){for(;e.sd(t););}function I3(e,t){return e.a+=t,e}function cte(e,t){return e.a+=t,e}function vg(e,t){return e.a+=t,e}function bv(e,t){return e.a+=t,e}function LT(e){return Fp(e),e.a}function vF(e){return e.b!=e.d.c}function Lze(e){return e.l|e.m<<22}function Wpe(e,t){return e.d[t.p]}function Mze(e,t){return ppn(e,t)}function Kpe(e,t,n){e.splice(t,n)}function Dze(e){e.c?bct(e):vct(e)}function wF(e){this.a=0,this.b=e}function Ize(){this.a=new fI(X_e)}function Oze(){this.b=new fI(B_e)}function Nze(){this.b=new fI(Fhe)}function Pze(){this.b=new fI(Fhe)}function Bze(){throw J(new Fr)}function Rze(){throw J(new Fr)}function Fze(){throw J(new Fr)}function jze(){throw J(new Fr)}function $ze(){throw J(new Fr)}function Hze(){throw J(new Fr)}function zze(){throw J(new Fr)}function Gze(){throw J(new Fr)}function qze(){throw J(new Fr)}function Vze(){throw J(new Fr)}function fUt(){throw J(new xc)}function dUt(){throw J(new xc)}function lM(e){this.a=new Uze(e)}function Uze(e){Tin(this,e,Thn())}function hM(e){return!e||dYe(e)}function fM(e){return J1[e]!=-1}function gUt(){BG!=0&&(BG=0),RG=-1}function Wze(){lue==null&&(lue=[])}function pUt(e,t){$se(He(e.a),t)}function bUt(e,t){$se(He(e.a),t)}function dM(e,t){H3.call(this,e,t)}function Zx(e,t){dM.call(this,e,t)}function Ype(e,t){this.b=e,this.c=t}function Kze(e,t){this.b=e,this.a=t}function Yze(e,t){this.a=e,this.b=t}function Xze(e,t){this.a=e,this.b=t}function Qze(e,t){this.a=e,this.b=t}function Zze(e,t){this.a=e,this.b=t}function Jze(e,t){this.a=e,this.b=t}function eGe(e,t){this.a=e,this.b=t}function tGe(e,t){this.a=e,this.b=t}function nGe(e,t){this.a=e,this.b=t}function rGe(e,t){this.b=e,this.a=t}function iGe(e,t){this.b=e,this.a=t}function sGe(e,t){this.b=e,this.a=t}function aGe(e,t){this.b=e,this.a=t}function Kr(e,t){this.f=e,this.g=t}function Jx(e,t){this.e=e,this.d=t}function vv(e,t){this.g=e,this.i=t}function ute(e,t){this.a=e,this.b=t}function oGe(e,t){this.a=e,this.f=t}function cGe(e,t){this.b=e,this.c=t}function vUt(e,t){this.a=e,this.b=t}function uGe(e,t){this.a=e,this.b=t}function lte(e,t){this.a=e,this.b=t}function lGe(e){sbe(e.dc()),this.c=e}function mF(e){this.b=u(Nr(e),83)}function hGe(e){this.a=u(Nr(e),83)}function Em(e){this.a=u(Nr(e),15)}function fGe(e){this.a=u(Nr(e),15)}function yF(e){this.b=u(Nr(e),47)}function kF(){this.q=new b.Date}function Ud(){Ud=pe,Y8e=new Et}function e8(){e8=pe,Y7=new rt}function MT(e){return e.f.c+e.g.c}function gM(e,t){return e.b.Hc(t)}function dGe(e,t){return e.b.Ic(t)}function gGe(e,t){return e.b.Qc(t)}function pGe(e,t){return e.b.Hc(t)}function bGe(e,t){return e.c.uc(t)}function _0(e,t){return e.a._b(t)}function vGe(e,t){return Ci(e.c,t)}function wGe(e,t){return Il(e.b,t)}function mGe(e,t){return e>t&&t0}function fte(e,t){return Mc(e,t)<0}function BT(e,t){return e.a.get(t)}function MUt(e,t){return t.split(e)}function FGe(e,t){return Il(e.e,t)}function r2e(e){return Sn(e),!1}function DF(e){mn.call(this,e,21)}function DUt(e,t){pXe.call(this,e,t)}function IF(e,t){Kr.call(this,e,t)}function dte(e,t){Kr.call(this,e,t)}function i2e(e){Wne(),bWe.call(this,e)}function s2e(e,t){mKe(e,e.length,t)}function mM(e,t){KKe(e,e.length,t)}function IUt(e,t,n){t.ud(e.a.Ge(n))}function OUt(e,t,n){t.we(e.a.Fe(n))}function NUt(e,t,n){t.td(e.a.Kb(n))}function PUt(e,t,n){e.Mb(n)&&t.td(n)}function RT(e,t,n){e.splice(t,0,n)}function BUt(e,t){return Vu(e.e,t)}function OF(e,t){this.d=e,this.e=t}function jGe(e,t){this.b=e,this.a=t}function $Ge(e,t){this.b=e,this.a=t}function a2e(e,t){this.b=e,this.a=t}function HGe(e,t){this.a=e,this.b=t}function zGe(e,t){this.a=e,this.b=t}function GGe(e,t){this.a=e,this.b=t}function qGe(e,t){this.a=e,this.b=t}function y6(e,t){this.a=e,this.b=t}function o2e(e,t){this.b=e,this.a=t}function c2e(e,t){this.b=e,this.a=t}function NF(e,t){Kr.call(this,e,t)}function PF(e,t){Kr.call(this,e,t)}function u2e(e,t){Kr.call(this,e,t)}function l2e(e,t){Kr.call(this,e,t)}function O3(e,t){Kr.call(this,e,t)}function gte(e,t){Kr.call(this,e,t)}function pte(e,t){Kr.call(this,e,t)}function bte(e,t){Kr.call(this,e,t)}function BF(e,t){Kr.call(this,e,t)}function h2e(e,t){Kr.call(this,e,t)}function vte(e,t){Kr.call(this,e,t)}function yM(e,t){Kr.call(this,e,t)}function RF(e,t){Kr.call(this,e,t)}function wte(e,t){Kr.call(this,e,t)}function FT(e,t){Kr.call(this,e,t)}function f2e(e,t){Kr.call(this,e,t)}function Cs(e,t){Kr.call(this,e,t)}function FF(e,t){Kr.call(this,e,t)}function VGe(e,t){this.a=e,this.b=t}function UGe(e,t){this.a=e,this.b=t}function WGe(e,t){this.a=e,this.b=t}function KGe(e,t){this.a=e,this.b=t}function YGe(e,t){this.a=e,this.b=t}function XGe(e,t){this.a=e,this.b=t}function QGe(e,t){this.a=e,this.b=t}function ZGe(e,t){this.a=e,this.b=t}function JGe(e,t){this.a=e,this.b=t}function d2e(e,t){this.b=e,this.a=t}function eqe(e,t){this.b=e,this.a=t}function tqe(e,t){this.b=e,this.a=t}function nqe(e,t){this.b=e,this.a=t}function r8(e,t){this.c=e,this.d=t}function rqe(e,t){this.e=e,this.d=t}function iqe(e,t){this.a=e,this.b=t}function sqe(e,t){this.b=t,this.c=e}function jF(e,t){Kr.call(this,e,t)}function kM(e,t){Kr.call(this,e,t)}function mte(e,t){Kr.call(this,e,t)}function jT(e,t){Kr.call(this,e,t)}function g2e(e,t){Kr.call(this,e,t)}function yte(e,t){Kr.call(this,e,t)}function kte(e,t){Kr.call(this,e,t)}function xM(e,t){Kr.call(this,e,t)}function p2e(e,t){Kr.call(this,e,t)}function xte(e,t){Kr.call(this,e,t)}function $T(e,t){Kr.call(this,e,t)}function b2e(e,t){Kr.call(this,e,t)}function HT(e,t){Kr.call(this,e,t)}function zT(e,t){Kr.call(this,e,t)}function _m(e,t){Kr.call(this,e,t)}function Ete(e,t){Kr.call(this,e,t)}function Tte(e,t){Kr.call(this,e,t)}function v2e(e,t){Kr.call(this,e,t)}function GT(e,t){Kr.call(this,e,t)}function _te(e,t){Kr.call(this,e,t)}function $F(e,t){Kr.call(this,e,t)}function EM(e,t){Kr.call(this,e,t)}function TM(e,t){Kr.call(this,e,t)}function k6(e,t){Kr.call(this,e,t)}function Cte(e,t){Kr.call(this,e,t)}function w2e(e,t){Kr.call(this,e,t)}function Ste(e,t){Kr.call(this,e,t)}function Ate(e,t){Kr.call(this,e,t)}function m2e(e,t){Kr.call(this,e,t)}function Lte(e,t){Kr.call(this,e,t)}function Mte(e,t){Kr.call(this,e,t)}function Dte(e,t){Kr.call(this,e,t)}function Ite(e,t){Kr.call(this,e,t)}function y2e(e,t){Kr.call(this,e,t)}function aqe(e,t){this.b=e,this.a=t}function oqe(e,t){this.a=e,this.b=t}function cqe(e,t){this.a=e,this.b=t}function uqe(e,t){this.a=e,this.b=t}function lqe(e,t){this.a=e,this.b=t}function k2e(e,t){Kr.call(this,e,t)}function x2e(e,t){Kr.call(this,e,t)}function hqe(e,t){this.b=e,this.d=t}function E2e(e,t){Kr.call(this,e,t)}function T2e(e,t){Kr.call(this,e,t)}function fqe(e,t){this.a=e,this.b=t}function dqe(e,t){this.a=e,this.b=t}function HF(e,t){Kr.call(this,e,t)}function qT(e,t){Kr.call(this,e,t)}function _2e(e,t){Kr.call(this,e,t)}function C2e(e,t){Kr.call(this,e,t)}function S2e(e,t){Kr.call(this,e,t)}function Ote(e,t){Kr.call(this,e,t)}function A2e(e,t){Kr.call(this,e,t)}function Nte(e,t){Kr.call(this,e,t)}function zF(e,t){Kr.call(this,e,t)}function Pte(e,t){Kr.call(this,e,t)}function Bte(e,t){Kr.call(this,e,t)}function _M(e,t){Kr.call(this,e,t)}function Rte(e,t){Kr.call(this,e,t)}function L2e(e,t){Kr.call(this,e,t)}function CM(e,t){Kr.call(this,e,t)}function M2e(e,t){Kr.call(this,e,t)}function RUt(e,t){return Vu(e.c,t)}function FUt(e,t){return Vu(t.b,e)}function jUt(e,t){return-e.b.Je(t)}function D2e(e,t){return Vu(e.g,t)}function SM(e,t){Kr.call(this,e,t)}function x6(e,t){Kr.call(this,e,t)}function gqe(e,t){this.a=e,this.b=t}function pqe(e,t){this.a=e,this.b=t}function Pt(e,t){this.a=e,this.b=t}function VT(e,t){Kr.call(this,e,t)}function UT(e,t){Kr.call(this,e,t)}function AM(e,t){Kr.call(this,e,t)}function Fte(e,t){Kr.call(this,e,t)}function GF(e,t){Kr.call(this,e,t)}function WT(e,t){Kr.call(this,e,t)}function jte(e,t){Kr.call(this,e,t)}function qF(e,t){Kr.call(this,e,t)}function N3(e,t){Kr.call(this,e,t)}function LM(e,t){Kr.call(this,e,t)}function KT(e,t){Kr.call(this,e,t)}function YT(e,t){Kr.call(this,e,t)}function MM(e,t){Kr.call(this,e,t)}function VF(e,t){Kr.call(this,e,t)}function P3(e,t){Kr.call(this,e,t)}function UF(e,t){Kr.call(this,e,t)}function bqe(e,t){this.a=e,this.b=t}function vqe(e,t){this.a=e,this.b=t}function wqe(e,t){this.a=e,this.b=t}function mqe(e,t){this.a=e,this.b=t}function yqe(e,t){this.a=e,this.b=t}function kqe(e,t){this.a=e,this.b=t}function xa(e,t){this.a=e,this.b=t}function WF(e,t){Kr.call(this,e,t)}function xqe(e,t){this.a=e,this.b=t}function Eqe(e,t){this.a=e,this.b=t}function Tqe(e,t){this.a=e,this.b=t}function _qe(e,t){this.a=e,this.b=t}function Cqe(e,t){this.a=e,this.b=t}function Sqe(e,t){this.a=e,this.b=t}function Aqe(e,t){this.b=e,this.a=t}function Lqe(e,t){this.b=e,this.a=t}function Mqe(e,t){this.b=e,this.a=t}function Dqe(e,t){this.b=e,this.a=t}function Iqe(e,t){this.a=e,this.b=t}function Oqe(e,t){this.a=e,this.b=t}function $Ut(e,t){bgn(e.a,u(t,56))}function Nqe(e,t){Arn(e.a,u(t,11))}function HUt(e,t){return h8(),t!=e}function Pqe(){return aze(),new $0t}function Bqe(){fre(),this.b=new Ys}function Rqe(){az(),this.a=new Ys}function Fqe(){Ewe(),Ive.call(this)}function E6(e,t){Kr.call(this,e,t)}function jqe(e,t){this.a=e,this.b=t}function $qe(e,t){this.a=e,this.b=t}function KF(e,t){this.a=e,this.b=t}function Hqe(e,t){this.a=e,this.b=t}function zqe(e,t){this.a=e,this.b=t}function Gqe(e,t){this.a=e,this.b=t}function qqe(e,t){this.d=e,this.b=t}function I2e(e,t){this.d=e,this.e=t}function Vqe(e,t){this.f=e,this.c=t}function DM(e,t){this.b=e,this.c=t}function O2e(e,t){this.i=e,this.g=t}function Uqe(e,t){this.e=e,this.a=t}function Wqe(e,t){this.a=e,this.b=t}function N2e(e,t){e.i=null,X$(e,t)}function zUt(e,t){e&&Si(oN,e,t)}function Kqe(e,t){return qie(e.a,t)}function YF(e){return qD(e.c,e.b)}function hc(e){return e?e.dd():null}function je(e){return e??null}function Cm(e){return typeof e===sk}function Sm(e){return typeof e===d6e}function fa(e){return typeof e===Mae}function Mp(e,t){return e.Hd().Xb(t)}function XF(e,t){return isn(e.Kc(),t)}function mv(e,t){return Mc(e,t)==0}function GUt(e,t){return Mc(e,t)>=0}function XT(e,t){return Mc(e,t)!=0}function qUt(e){return""+(Sn(e),e)}function IM(e,t){return e.substr(t)}function Yqe(e){return bl(e),e.d.gc()}function $te(e){return $dn(e,e.c),e}function QF(e){return u_(e==null),e}function QT(e,t){return e.a+=""+t,e}function To(e,t){return e.a+=""+t,e}function ZT(e,t){return e.a+=""+t,e}function Ec(e,t){return e.a+=""+t,e}function Yr(e,t){return e.a+=""+t,e}function P2e(e,t){return e.a+=""+t,e}function Xqe(e,t){ks(e,t,e.a,e.a.a)}function q2(e,t){ks(e,t,e.c.b,e.c)}function VUt(e,t,n){ost(t,Ose(e,n))}function UUt(e,t,n){ost(t,Ose(e,n))}function WUt(e,t){jrn(new rr(e),t)}function Qqe(e,t){e.q.setTime(Bv(t))}function Zqe(e,t){Hve.call(this,e,t)}function Jqe(e,t){Hve.call(this,e,t)}function Hte(e,t){Hve.call(this,e,t)}function eVe(e){sl(this),P_(this,e)}function B2e(e){return xn(e,0),null}function Zf(e){return e.a=0,e.b=0,e}function tVe(e,t){return e.a=t.g+1,e}function KUt(e,t){return e.j[t.p]==2}function R2e(e){return MZt(u(e,79))}function nVe(){nVe=pe,Ngt=Qr(Xie())}function rVe(){rVe=pe,Qpt=Qr(Hot())}function iVe(){this.b=new w6(qm(12))}function sVe(){this.b=0,this.a=!1}function aVe(){this.b=0,this.a=!1}function JT(e){this.a=e,nT.call(this)}function oVe(e){this.a=e,nT.call(this)}function dn(e,t){zs.call(this,e,t)}function zte(e,t){Im.call(this,e,t)}function B3(e,t){O2e.call(this,e,t)}function Gte(e,t){G8.call(this,e,t)}function cVe(e,t){OM.call(this,e,t)}function ui(e,t){LF(),Si(QV,e,t)}function qte(e,t){return jl(e.a,0,t)}function uVe(e,t){return e.a.a.a.cc(t)}function lVe(e,t){return je(e)===je(t)}function YUt(e,t){return Fs(e.a,t.a)}function XUt(e,t){return Tu(e.a,t.a)}function QUt(e,t){return VKe(e.a,t.a)}function pd(e,t){return e.indexOf(t)}function yv(e,t){return e==t?0:e?1:-1}function ZF(e){return e<10?"0"+e:""+e}function ZUt(e){return Nr(e),new JT(e)}function hVe(e){return fu(e.l,e.m,e.h)}function i8(e){return _s((Sn(e),e))}function JUt(e){return _s((Sn(e),e))}function fVe(e,t){return Tu(e.g,t.g)}function Ko(e){return typeof e===d6e}function eWt(e){return e==vw||e==_y}function tWt(e){return e==vw||e==Ty}function F2e(e){return Yo(e.b.b,e,0)}function dVe(e){this.a=Pqe(),this.b=e}function gVe(e){this.a=Pqe(),this.b=e}function nWt(e,t){return it(e.a,t),t}function rWt(e,t){return it(e.c,t),e}function pVe(e,t){return Vl(e.a,t),e}function iWt(e,t){return mf(),t.a+=e}function sWt(e,t){return mf(),t.a+=e}function aWt(e,t){return mf(),t.c+=e}function j2e(e,t){L8(e,0,e.length,t)}function C0(){be.call(this,new Z2)}function bVe(){Dj.call(this,0,0,0,0)}function T6(){fh.call(this,0,0,0,0)}function Io(e){this.a=e.a,this.b=e.b}function Dp(e){return e==Xh||e==Df}function s8(e){return e==X0||e==Y0}function vVe(e){return e==K4||e==W4}function R3(e){return e!=X1&&e!=w2}function Ll(e){return e.Lg()&&e.Mg()}function wVe(e){return Wj(u(e,118))}function JF(e){return Vl(new Xs,e)}function mVe(e,t){return new G8(t,e)}function oWt(e,t){return new G8(t,e)}function $2e(e,t,n){z$(e,t),G$(e,n)}function ej(e,t,n){zv(e,t),Hv(e,n)}function C1(e,t,n){Du(e,t),Iu(e,n)}function tj(e,t,n){O8(e,t),P8(e,n)}function nj(e,t,n){N8(e,t),B8(e,n)}function Vte(e,t){Y8(e,t),R8(e,e.D)}function H2e(e){Vqe.call(this,e,!0)}function yVe(e,t,n){Mbe.call(this,e,t,n)}function Ip(e){Qp(),csn.call(this,e)}function kVe(){IF.call(this,"Head",1)}function xVe(){IF.call(this,"Tail",3)}function Ute(e){e.c=Me(Yn,yt,1,0,5,1)}function EVe(e){e.a=Me(Yn,yt,1,8,5,1)}function TVe(e){Mu(e.xf(),new hr(e))}function F3(e){return e!=null?Xi(e):0}function cWt(e,t){return Vm(t,L1(e))}function uWt(e,t){return Vm(t,L1(e))}function lWt(e,t){return e[e.length]=t}function hWt(e,t){return e[e.length]=t}function z2e(e){return lQt(e.b.Kc(),e.a)}function fWt(e,t){return Y$(Vne(e.d),t)}function dWt(e,t){return Y$(Vne(e.g),t)}function gWt(e,t){return Y$(Vne(e.j),t)}function fo(e,t){zs.call(this,e.b,t)}function kv(e){Dj.call(this,e,e,e,e)}function G2e(e){return e.b&&dae(e),e.a}function q2e(e){return e.b&&dae(e),e.c}function pWt(e,t){V1||(e.b=t)}function Wte(e,t,n){return cs(e,t,n),n}function _Ve(e,t,n){cs(e.c[t.g],t.g,n)}function bWt(e,t,n){u(e.c,69).Xh(t,n)}function vWt(e,t,n){C1(n,n.i+e,n.j+t)}function wWt(e,t){Br(jc(e.a),jXe(t))}function mWt(e,t){Br(gl(e.a),$Xe(t))}function e_(e){yi(),cv.call(this,e)}function yWt(e){return e==null?0:Xi(e)}function CVe(){CVe=pe,vhe=new V_(ffe)}function jr(){jr=pe,new SVe,new st}function SVe(){new Mr,new Mr,new Mr}function V2e(){V2e=pe,upe(),P8e=new Mr}function S1(){S1=pe,b.Math.log(2)}function lh(){lh=pe,b0=(OGe(),q3t)}function kWt(){throw J(new pg(p0t))}function xWt(){throw J(new pg(p0t))}function EWt(){throw J(new pg(b0t))}function TWt(){throw J(new pg(b0t))}function AVe(e){this.a=e,uve.call(this,e)}function Kte(e){this.a=e,mF.call(this,e)}function Yte(e){this.a=e,mF.call(this,e)}function aa(e,t){Cne(e.c,e.c.length,t)}function nc(e){return e.at?1:0}function MVe(e,t){return Mc(e,t)>0?e:t}function fu(e,t,n){return{l:e,m:t,h:n}}function _Wt(e,t){e.a!=null&&Nqe(t,e.a)}function DVe(e){e.a=new wt,e.c=new wt}function rj(e){this.b=e,this.a=new st}function IVe(e){this.b=new ug,this.a=e}function W2e(e){jbe.call(this),this.a=e}function OVe(){IF.call(this,"Range",2)}function NVe(){H3e(),this.a=new fI(uEe)}function CWt(e,t){Nr(t),G3(e).Jc(new ce)}function SWt(e,t){return $l(),t.n.b+=e}function AWt(e,t,n){return Si(e.g,n,t)}function LWt(e,t,n){return Si(e.k,n,t)}function MWt(e,t){return Si(e.a,t.a,t)}function j3(e,t,n){return o3e(t,n,e.c)}function K2e(e){return new Pt(e.c,e.d)}function DWt(e){return new Pt(e.c,e.d)}function fc(e){return new Pt(e.a,e.b)}function PVe(e,t){return emn(e.a,t,null)}function IWt(e){Va(e,null),ba(e,null)}function BVe(e){gre(e,null),pre(e,null)}function RVe(){OM.call(this,null,null)}function FVe(){hj.call(this,null,null)}function Y2e(e){this.a=e,Mr.call(this)}function OWt(e){this.b=(hn(),new H(e))}function ij(e){e.j=Me(K8e,Qe,310,0,0,1)}function NWt(e,t,n){e.c.Vc(t,u(n,133))}function PWt(e,t,n){e.c.ji(t,u(n,133))}function jVe(e,t){_r(e),e.Gc(u(t,15))}function t_(e,t){return bwn(e.c,e.b,t)}function BWt(e,t){return new oUe(e.Kc(),t)}function Xte(e,t){return Psn(e.Kc(),t)!=-1}function X2e(e,t){return e.a.Bc(t)!=null}function sj(e){return e.Ob()?e.Pb():null}function $Ve(e){return jh(e,0,e.length)}function we(e,t){return e!=null&&ese(e,t)}function RWt(e,t){e.q.setHours(t),lC(e,t)}function HVe(e,t){e.c&&(yve(t),dXe(t))}function FWt(e,t,n){u(e.Kb(n),164).Nb(t)}function jWt(e,t,n){return Wwn(e,t,n),n}function zVe(e,t,n){e.a=t^1502,e.b=n^uoe}function Qte(e,t,n){return e.a[t.g][n.g]}function A1(e,t){return e.a[t.c.p][t.p]}function $Wt(e,t){return e.e[t.c.p][t.p]}function HWt(e,t){return e.c[t.c.p][t.p]}function zWt(e,t){return e.j[t.p]=Q0n(t)}function GWt(e,t){return Jwe(e.f,t.tg())}function qWt(e,t){return Jwe(e.b,t.tg())}function VWt(e,t){return e.a0?t*t/e:t*t*100}function bKt(e,t){return e>0?t/(e*e):t*100}function vKt(e,t,n){return it(t,drt(e,n))}function wKt(e,t,n){A$(),e.Xe(t)&&n.td(e)}function c8(e,t,n){var r;r=e.Zc(t),r.Rb(n)}function Lm(e,t,n){return e.a+=t,e.b+=n,e}function mKt(e,t,n){return e.a*=t,e.b*=n,e}function BM(e,t,n){return e.a-=t,e.b-=n,e}function ybe(e,t){return e.a=t.a,e.b=t.b,e}function gj(e){return e.a=-e.a,e.b=-e.b,e}function mUe(e){this.c=e,this.a=1,this.b=1}function yUe(e){this.c=e,Du(e,0),Iu(e,0)}function kUe(e){as.call(this),D_(this,e)}function xUe(e){Aae(),W$e(this),this.mf(e)}function EUe(e,t){PT(),OM.call(this,e,t)}function kbe(e,t){wg(),hj.call(this,e,t)}function TUe(e,t){wg(),hj.call(this,e,t)}function _Ue(e,t){wg(),kbe.call(this,e,t)}function Ml(e,t,n){Nl.call(this,e,t,n,2)}function ine(e,t){lh(),Mj.call(this,e,t)}function CUe(e,t){lh(),ine.call(this,e,t)}function xbe(e,t){lh(),ine.call(this,e,t)}function SUe(e,t){lh(),xbe.call(this,e,t)}function Ebe(e,t){lh(),Mj.call(this,e,t)}function AUe(e,t){lh(),Ebe.call(this,e,t)}function LUe(e,t){lh(),Mj.call(this,e,t)}function yKt(e,t){return e.c.Fc(u(t,133))}function Tbe(e,t,n){return wz(wD(e,t),n)}function kKt(e,t,n){return t.Qk(e.e,e.c,n)}function xKt(e,t,n){return t.Rk(e.e,e.c,n)}function sne(e,t){return Up(e.e,u(t,49))}function EKt(e,t,n){G_(gl(e.a),t,$Xe(n))}function TKt(e,t,n){G_(jc(e.a),t,jXe(n))}function _be(e,t){t.$modCount=e.$modCount}function a_(){a_=pe,MS=new Zi("root")}function u8(){u8=pe,uN=new _He,new CHe}function MUe(){this.a=new Nv,this.b=new Nv}function Cbe(){Qet.call(this),this.Bb|=so}function DUe(){Kr.call(this,"GROW_TREE",0)}function _Kt(e){return e==null?null:Gmn(e)}function CKt(e){return e==null?null:Qfn(e)}function SKt(e){return e==null?null:Qo(e)}function AKt(e){return e==null?null:Qo(e)}function S0(e){e.o==null&&_0n(e)}function Mt(e){return u_(e==null||Cm(e)),e}function ft(e){return u_(e==null||Sm(e)),e}function Hr(e){return u_(e==null||fa(e)),e}function Sbe(e){this.q=new b.Date(Bv(e))}function RM(e,t){this.c=e,Jx.call(this,e,t)}function pj(e,t){this.a=e,RM.call(this,e,t)}function LKt(e,t){this.d=e,Lee(this),this.b=t}function Abe(e,t){Bre.call(this,e),this.a=t}function Lbe(e,t){Bre.call(this,e),this.a=t}function MKt(e){n3e.call(this,0,0),this.f=e}function Mbe(e,t,n){C$.call(this,e,t,n,null)}function IUe(e,t,n){C$.call(this,e,t,n,null)}function DKt(e,t,n){return e.ue(t,n)<=0?n:t}function IKt(e,t,n){return e.ue(t,n)<=0?t:n}function OKt(e,t){return u(Fv(e.b,t),149)}function NKt(e,t){return u(Fv(e.c,t),229)}function ane(e){return u(St(e.a,e.b),287)}function OUe(e){return new Pt(e.c,e.d+e.a)}function NUe(e){return $l(),vVe(u(e,197))}function Mm(){Mm=pe,F7e=rn((Bl(),Hb))}function PKt(e,t){t.a?ypn(e,t):Zte(e.a,t.b)}function PUe(e,t){V1||it(e.a,t)}function BKt(e,t){return bM(),z8(t.d.i,e)}function RKt(e,t){return U6(),new jct(t,e)}function vd(e,t){return JM(t,O6e),e.f=t,e}function Dbe(e,t,n){return n=Kl(e,t,3,n),n}function Ibe(e,t,n){return n=Kl(e,t,6,n),n}function Obe(e,t,n){return n=Kl(e,t,9,n),n}function FM(e,t,n){++e.j,e.Ki(),Nre(e,t,n)}function BUe(e,t,n){++e.j,e.Hi(t,e.oi(t,n))}function RUe(e,t,n){var r;r=e.Zc(t),r.Rb(n)}function FUe(e,t,n){return W5e(e.c,e.b,t,n)}function Nbe(e,t){return(t&Ei)%e.d.length}function zs(e,t){Zi.call(this,e),this.a=t}function Pbe(e,t){npe.call(this,e),this.a=t}function one(e,t){npe.call(this,e),this.a=t}function jUe(e,t){this.c=e,jv.call(this,t)}function $Ue(e,t){this.a=e,H$e.call(this,t)}function jM(e,t){this.a=e,H$e.call(this,t)}function HUe(e){this.a=(ql(e,fy),new su(e))}function zUe(e){this.a=(ql(e,fy),new su(e))}function $M(e){return!e.a&&(e.a=new se),e.a}function GUe(e){return e>8?0:e+1}function FKt(e,t){return Mn(),e==t?0:e?1:-1}function Bbe(e,t,n){return M6(e,u(t,22),n)}function jKt(e,t,n){return e.apply(t,n)}function qUe(e,t,n){return e.a+=jh(t,0,n),e}function Rbe(e,t){var n;return n=e.e,e.e=t,n}function $Kt(e,t){var n;n=e[coe],n.call(e,t)}function HKt(e,t){var n;n=e[coe],n.call(e,t)}function Dm(e,t){e.a.Vc(e.b,t),++e.b,e.c=-1}function VUe(e){sl(e.e),e.d.b=e.d,e.d.a=e.d}function HM(e){e.b?HM(e.b):e.f.c.zc(e.e,e.d)}function zKt(e,t,n){G2(),bee(e,t.Ce(e.a,n))}function GKt(e,t){return ote(Lrt(e.a,t,!0))}function qKt(e,t){return ote(Mrt(e.a,t,!0))}function wf(e,t){return dF(new Array(t),e)}function cne(e){return String.fromCharCode(e)}function VKt(e){return e==null?null:e.message}function UUe(){this.a=new st,this.b=new st}function WUe(){this.a=new m9,this.b=new nHe}function KUe(){this.b=new Fa,this.c=new st}function Fbe(){this.d=new Fa,this.e=new Fa}function jbe(){this.n=new Fa,this.o=new Fa}function bj(){this.n=new g6,this.i=new T6}function YUe(){this.a=new FJ,this.b=new $X}function XUe(){this.a=new st,this.d=new st}function QUe(){this.b=new Ys,this.a=new Ys}function ZUe(){this.b=new Mr,this.a=new Mr}function JUe(){this.b=new Oze,this.a=new OQ}function eWe(){bj.call(this),this.a=new Fa}function o_(e){bsn.call(this,e,(M$(),_ue))}function $be(e,t,n,r){Dj.call(this,e,t,n,r)}function UKt(e,t,n){n!=null&&W$(t,hse(e,n))}function WKt(e,t,n){n!=null&&K$(t,hse(e,n))}function Hbe(e,t,n){return n=Kl(e,t,11,n),n}function Ni(e,t){return e.a+=t.a,e.b+=t.b,e}function da(e,t){return e.a-=t.a,e.b-=t.b,e}function KKt(e,t){return e.n.a=(Sn(t),t+10)}function YKt(e,t){return e.n.a=(Sn(t),t+10)}function XKt(e,t){return t==e||u7(rz(t),e)}function tWe(e,t){return Si(e.a,t,"")==null}function QKt(e,t){return bM(),!z8(t.d.i,e)}function ZKt(e,t){Dp(e.f)?p0n(e,t):Jhn(e,t)}function JKt(e,t){var n;return n=t.Hh(e.a),n}function Im(e,t){Do.call(this,$C+e+Eb+t)}function S6(e,t,n,r){at.call(this,e,t,n,r)}function zbe(e,t,n,r){at.call(this,e,t,n,r)}function nWe(e,t,n,r){zbe.call(this,e,t,n,r)}function rWe(e,t,n,r){Hj.call(this,e,t,n,r)}function une(e,t,n,r){Hj.call(this,e,t,n,r)}function Gbe(e,t,n,r){Hj.call(this,e,t,n,r)}function iWe(e,t,n,r){une.call(this,e,t,n,r)}function qbe(e,t,n,r){une.call(this,e,t,n,r)}function wn(e,t,n,r){Gbe.call(this,e,t,n,r)}function sWe(e,t,n,r){qbe.call(this,e,t,n,r)}function aWe(e,t,n,r){zve.call(this,e,t,n,r)}function oWe(e,t,n){this.a=e,bbe.call(this,t,n)}function cWe(e,t,n){this.c=t,this.b=n,this.a=e}function eYt(e,t,n){return e.d=u(t.Kb(n),164)}function Vbe(e,t){return e.Aj().Nh().Kh(e,t)}function Ube(e,t){return e.Aj().Nh().Ih(e,t)}function uWe(e,t){return Sn(e),je(e)===je(t)}function an(e,t){return Sn(e),je(e)===je(t)}function lne(e,t){return ote(Lrt(e.a,t,!1))}function hne(e,t){return ote(Mrt(e.a,t,!1))}function tYt(e,t){return e.b.sd(new zGe(e,t))}function nYt(e,t){return e.b.sd(new GGe(e,t))}function lWe(e,t){return e.b.sd(new qGe(e,t))}function Wbe(e,t,n){return e.lastIndexOf(t,n)}function rYt(e,t,n){return Fs(e[t.b],e[n.b])}function iYt(e,t){return Ye(t,(pt(),_O),e)}function sYt(e,t){return Tu(t.a.d.p,e.a.d.p)}function aYt(e,t){return Tu(e.a.d.p,t.a.d.p)}function oYt(e,t){return Fs(e.c-e.s,t.c-t.s)}function hWe(e){return e.c?Yo(e.c.a,e,0):-1}function cYt(e){return e<100?null:new _p(e)}function A6(e){return e==$b||e==p0||e==tu}function fWe(e,t){return we(t,15)&&yct(e.c,t)}function uYt(e,t){V1||t&&(e.d=t)}function fne(e,t){var n;return n=t,!!bye(e,n)}function Kbe(e,t){this.c=e,jne.call(this,e,t)}function dWe(e){this.c=e,Hte.call(this,Cz,0)}function gWe(e,t){gQt.call(this,e,e.length,t)}function lYt(e,t,n){return u(e.c,69).lk(t,n)}function vj(e,t,n){return u(e.c,69).mk(t,n)}function hYt(e,t,n){return kKt(e,u(t,332),n)}function Ybe(e,t,n){return xKt(e,u(t,332),n)}function fYt(e,t,n){return gst(e,u(t,332),n)}function pWe(e,t,n){return lfn(e,u(t,332),n)}function c_(e,t){return t==null?null:Ym(e.b,t)}function Xbe(e){return Sm(e)?(Sn(e),e):e.ke()}function wj(e){return!isNaN(e)&&!isFinite(e)}function bWe(e){wd(),this.a=(hn(),new Kx(e))}function zM(e){h8(),this.d=e,this.a=new L3}function hh(e,t,n){this.a=e,this.b=t,this.c=n}function vWe(e,t,n){this.a=e,this.b=t,this.c=n}function wWe(e,t,n){this.d=e,this.b=n,this.a=t}function dne(e){DVe(this),Rh(this),no(this,e)}function Uu(e){Ute(this),hve(this.c,0,e.Pc())}function mWe(e){Ol(e.a),bJe(e.c,e.b),e.b=null}function yWe(e){this.a=e,Ud(),Ou(Date.now())}function kWe(){kWe=pe,p7e=new S,qG=new S}function gne(){gne=pe,a7e=new jt,H0t=new At}function xWe(){xWe=pe,Y3t=Me(Yn,yt,1,0,5,1)}function EWe(){EWe=pe,d4t=Me(Yn,yt,1,0,5,1)}function Qbe(){Qbe=pe,g4t=Me(Yn,yt,1,0,5,1)}function wd(){wd=pe,new spe((hn(),hn(),bo))}function dYt(e){return M$(),Xr((SJe(),q0t),e)}function gYt(e){return F1(),Xr((UZe(),X0t),e)}function pYt(e){return LH(),Xr((JQe(),ngt),e)}function bYt(e){return P$(),Xr((eZe(),rgt),e)}function vYt(e){return uz(),Xr((ztt(),igt),e)}function wYt(e){return n1(),Xr((GZe(),ogt),e)}function mYt(e){return al(),Xr((qZe(),ugt),e)}function yYt(e){return Lu(),Xr((VZe(),hgt),e)}function kYt(e){return Tz(),Xr((nVe(),Ngt),e)}function xYt(e){return Vv(),Xr((LJe(),Bgt),e)}function EYt(e){return Z6(),Xr((MJe(),Fgt),e)}function TYt(e){return Y_(),Xr((DJe(),Hgt),e)}function _Yt(e){return EF(),Xr((DQe(),zgt),e)}function CYt(e){return B$(),Xr((tZe(),spt),e)}function SYt(e){return L_(),Xr((WZe(),Cpt),e)}function AYt(e){return ro(),Xr((oet(),Mpt),e)}function LYt(e){return V8(),Xr((AJe(),Ppt),e)}function MYt(e){return Uv(),Xr((KZe(),Hpt),e)}function Zbe(e,t){if(!e)throw J(new Ln(t))}function DYt(e){return zn(),Xr((Met(),Vpt),e)}function Jbe(e){Dj.call(this,e.d,e.c,e.a,e.b)}function pne(e){Dj.call(this,e.d,e.c,e.a,e.b)}function eve(e,t,n){this.b=e,this.c=t,this.a=n}function mj(e,t,n){this.b=e,this.a=t,this.c=n}function TWe(e,t,n){this.a=e,this.b=t,this.c=n}function tve(e,t,n){this.a=e,this.b=t,this.c=n}function _We(e,t,n){this.a=e,this.b=t,this.c=n}function nve(e,t,n){this.a=e,this.b=t,this.c=n}function CWe(e,t,n){this.b=e,this.a=t,this.c=n}function yj(e,t,n){this.e=t,this.b=e,this.d=n}function IYt(e,t,n){return G2(),e.a.Od(t,n),t}function bne(e){var t;return t=new jn,t.e=e,t}function rve(e){var t;return t=new uHe,t.b=e,t}function GM(){GM=pe,rq=new _Y,iq=new CY}function mf(){mf=pe,s2t=new pX,a2t=new pB}function OYt(e){return cH(),Xr((OJe(),e2t),e)}function NYt(e){return R1(),Xr((PJe(),u2t),e)}function PYt(e){return oz(),Xr((Dtt(),v2t),e)}function BYt(e){return ek(),Xr((Oet(),w2t),e)}function RYt(e){return S$(),Xr((oZe(),m2t),e)}function FYt(e){return V6(),Xr((YZe(),y2t),e)}function jYt(e){return c4(),Xr((net(),h2t),e)}function $Yt(e){return qv(),Xr((ZZe(),b2t),e)}function HYt(e){return V$(),Xr((XZe(),k2t),e)}function zYt(e){return db(),Xr((eet(),x2t),e)}function GYt(e){return ED(),Xr((rZe(),E2t),e)}function qYt(e){return sb(),Xr((QZe(),_2t),e)}function VYt(e){return QH(),Xr((Ret(),C2t),e)}function UYt(e){return pD(),Xr((iZe(),S2t),e)}function WYt(e){return tI(),Xr((Pet(),A2t),e)}function KYt(e){return h7(),Xr((Net(),L2t),e)}function YYt(e){return mo(),Xr((rnt(),M2t),e)}function XYt(e){return q8(),Xr((eJe(),D2t),e)}function QYt(e){return P0(),Xr((JZe(),O2t),e)}function ZYt(e){return b$(),Xr((cZe(),N2t),e)}function JYt(e){return mh(),Xr((ret(),P2t),e)}function eXt(e){return WH(),Xr((Bet(),Xvt),e)}function tXt(e){return j_(),Xr((tJe(),Qvt),e)}function nXt(e){return Zm(),Xr((BJe(),Zvt),e)}function rXt(e){return vo(),Xr((iJe(),iwt),e)}function iXt(e){return f4(),Xr((Mtt(),ewt),e)}function sXt(e){return R0(),Xr((rJe(),twt),e)}function aXt(e){return mD(),Xr((aZe(),nwt),e)}function oXt(e){return iH(),Xr((nJe(),swt),e)}function cXt(e){return X_(),Xr((tet(),Jvt),e)}function uXt(e){return uD(),Xr((sZe(),awt),e)}function lXt(e){return Q8(),Xr((aJe(),owt),e)}function hXt(e){return nH(),Xr((oJe(),cwt),e)}function fXt(e){return uH(),Xr((sJe(),uwt),e)}function dXt(e){return Gv(),Xr((cJe(),xwt),e)}function gXt(e){return S_(),Xr((lZe(),Swt),e)}function pXt(e){return yd(),Xr((hZe(),Nwt),e)}function bXt(e){return M1(),Xr((fZe(),Bwt),e)}function vXt(e){return Jf(),Xr((uZe(),Qwt),e)}function wXt(e){return Ov(),Xr((dZe(),imt),e)}function mXt(e){return a7(),Xr((IJe(),smt),e)}function yXt(e){return nC(),Xr((Fet(),omt),e)}function kXt(e){return c$(),Xr((bZe(),kmt),e)}function xXt(e){return J$(),Xr((pZe(),Smt),e)}function EXt(e){return f$(),Xr((gZe(),xmt),e)}function TXt(e){return yH(),Xr((uJe(),Lmt),e)}function _Xt(e){return L$(),Xr((vZe(),Mmt),e)}function CXt(e){return RD(),Xr((lJe(),Dmt),e)}function SXt(e){return jH(),Xr((NJe(),Umt),e)}function AXt(e){return rH(),Xr((fJe(),Wmt),e)}function LXt(e){return mH(),Xr((hJe(),Kmt),e)}function MXt(e){return v7(),Xr((aet(),gyt),e)}function DXt(e){return GD(),Xr((dJe(),pyt),e)}function IXt(e){return _F(),Xr((LQe(),byt),e)}function OXt(e){return CF(),Xr((AQe(),wyt),e)}function NXt(e){return lD(),Xr((mZe(),myt),e)}function PXt(e){return rI(),Xr((iet(),yyt),e)}function BXt(e){return OT(),Xr((MQe(),Byt),e)}function RXt(e){return OD(),Xr((wZe(),Ryt),e)}function FXt(e){return i1(),Xr((set(),Gyt),e)}function jXt(e){return Ng(),Xr((Itt(),Vyt),e)}function $Xt(e){return t0(),Xr((Iet(),Uyt),e)}function HXt(e){return ty(),Xr((Det(),Zyt),e)}function zXt(e){return po(),Xr((rVe(),Qpt),e)}function GXt(e){return j8(),Xr((nZe(),Xpt),e)}function qXt(e){return wo(),Xr((cet(),d3t),e)}function VXt(e){return P1(),Xr((pJe(),g3t),e)}function UXt(e){return $0(),Xr((jJe(),p3t),e)}function WXt(e){return YH(),Xr(($et(),b3t),e)}function KXt(e){return F0(),Xr((gJe(),w3t),e)}function YXt(e){return Ul(),Xr((FJe(),y3t),e)}function XXt(e){return sy(),Xr((Htt(),k3t),e)}function QXt(e){return n4(),Xr((uet(),x3t),e)}function ZXt(e){return wa(),Xr((_et(),E3t),e)}function JXt(e){return ol(),Xr((jet(),T3t),e)}function eQt(e){return Bl(),Xr((HJe(),M3t),e)}function tQt(e){return wl(),Xr((int(),D3t),e)}function nQt(e){return ht(),Xr((het(),_3t),e)}function rQt(e){return EH(),Xr(($Je(),I3t),e)}function iQt(e){return Pl(),Xr((RJe(),P3t),e)}function sQt(e){return g7(),Xr((Ott(),K3t),e)}function aQt(e,t){return Sn(e),e+(Sn(t),t)}function oQt(e,t){return Ud(),Br(He(e.a),t)}function cQt(e,t){return Ud(),Br(He(e.a),t)}function vne(e,t){this.c=e,this.a=t,this.b=t-e}function SWe(e,t,n){this.a=e,this.b=t,this.c=n}function ive(e,t,n){this.a=e,this.b=t,this.c=n}function sve(e,t,n){this.a=e,this.b=t,this.c=n}function AWe(e,t,n){this.a=e,this.b=t,this.c=n}function LWe(e,t,n){this.a=e,this.b=t,this.c=n}function yg(e,t,n){this.e=e,this.a=t,this.c=n}function MWe(e,t,n){lh(),vwe.call(this,e,t,n)}function wne(e,t,n){lh(),twe.call(this,e,t,n)}function ave(e,t,n){lh(),twe.call(this,e,t,n)}function ove(e,t,n){lh(),twe.call(this,e,t,n)}function DWe(e,t,n){lh(),wne.call(this,e,t,n)}function cve(e,t,n){lh(),wne.call(this,e,t,n)}function IWe(e,t,n){lh(),cve.call(this,e,t,n)}function OWe(e,t,n){lh(),ave.call(this,e,t,n)}function NWe(e,t,n){lh(),ove.call(this,e,t,n)}function qM(e,t){return Nr(e),Nr(t),new tGe(e,t)}function L6(e,t){return Nr(e),Nr(t),new WWe(e,t)}function uQt(e,t){return Nr(e),Nr(t),new KWe(e,t)}function lQt(e,t){return Nr(e),Nr(t),new rGe(e,t)}function u(e,t){return u_(e==null||ese(e,t)),e}function l8(e){var t;return t=new st,Wre(t,e),t}function hQt(e){var t;return t=new Ys,Wre(t,e),t}function PWe(e){var t;return t=new gpe,oie(t,e),t}function VM(e){var t;return t=new as,oie(t,e),t}function fQt(e){return!e.e&&(e.e=new st),e.e}function dQt(e){return!e.c&&(e.c=new gm),e.c}function it(e,t){return e.c[e.c.length]=t,!0}function BWe(e,t){this.c=e,this.b=t,this.a=!1}function uve(e){this.d=e,Lee(this),this.b=sZt(e.d)}function RWe(){this.a=";,;",this.b="",this.c=""}function gQt(e,t,n){FKe.call(this,t,n),this.a=e}function FWe(e,t,n){this.b=e,Zqe.call(this,t,n)}function lve(e,t,n){this.c=e,OF.call(this,t,n)}function hve(e,t,n){O4e(n,0,e,t,n.length,!1)}function Kd(e,t,n,r,s){e.b=t,e.c=n,e.d=r,e.a=s}function pQt(e,t){t&&(e.b=t,e.a=(Fp(t),t.a))}function fve(e,t,n,r,s){e.d=t,e.c=n,e.a=r,e.b=s}function dve(e){var t,n;t=e.b,n=e.c,e.b=n,e.c=t}function gve(e){var t,n;n=e.d,t=e.a,e.d=t,e.a=n}function pve(e){return Gp(kZt(Ko(e)?Fh(e):e))}function bQt(e,t){return Tu(eKe(e.d),eKe(t.d))}function vQt(e,t){return t==(ht(),Dn)?e.c:e.d}function h8(){h8=pe,N_e=(ht(),Dn),uV=$n}function jWe(){this.b=Ue(ft(xt((a1(),zue))))}function $We(e){return G2(),Me(Yn,yt,1,e,5,1)}function wQt(e){return new Pt(e.c+e.b,e.d+e.a)}function mQt(e,t){return TF(),Tu(e.d.p,t.d.p)}function mne(e){return Qn(e.b!=0),bh(e,e.a.a)}function yQt(e){return Qn(e.b!=0),bh(e,e.c.b)}function bve(e,t){if(!e)throw J(new YHe(t))}function kj(e,t){if(!e)throw J(new Ln(t))}function vve(e,t,n){r8.call(this,e,t),this.b=n}function UM(e,t,n){I2e.call(this,e,t),this.c=n}function HWe(e,t,n){met.call(this,t,n),this.d=e}function wve(e){Qbe(),Ex.call(this),this.th(e)}function zWe(e,t,n){this.a=e,B3.call(this,t,n)}function GWe(e,t,n){this.a=e,B3.call(this,t,n)}function xj(e,t,n){I2e.call(this,e,t),this.c=n}function qWe(){C8(),jZt.call(this,(Ap(),rf))}function VWe(e){return e!=null&&!$ie(e,KS,YS)}function kQt(e,t){return(nrt(e)<<4|nrt(t))&Ss}function xQt(e,t){return Uj(),cse(e,t),new wYe(e,t)}function V2(e,t){var n;e.n&&(n=t,it(e.f,n))}function f8(e,t,n){var r;r=new Bm(n),t1(e,t,r)}function EQt(e,t){var n;return n=e.c,Bme(e,t),n}function mve(e,t){return t<0?e.g=-1:e.g=t,e}function Ej(e,t){return oin(e),e.a*=t,e.b*=t,e}function UWe(e,t,n,r,s){e.c=t,e.d=n,e.b=r,e.a=s}function ci(e,t){return ks(e,t,e.c.b,e.c),!0}function yve(e){e.a.b=e.b,e.b.a=e.a,e.a=e.b=null}function yne(e){this.b=e,this.a=Cv(this.b.a).Ed()}function WWe(e,t){this.b=e,this.a=t,nT.call(this)}function KWe(e,t){this.a=e,this.b=t,nT.call(this)}function YWe(e,t){FKe.call(this,t,1040),this.a=e}function WM(e){return e==0||isNaN(e)?e:e<0?-1:1}function TQt(e){return P6(),n0(e)==us(Kp(e))}function _Qt(e){return P6(),Kp(e)==us(n0(e))}function _v(e,t){return eC(e,new r8(t.a,t.b))}function CQt(e){return!to(e)&&e.c.i.c==e.d.i.c}function Tj(e){var t;return t=e.n,e.a.b+t.d+t.a}function XWe(e){var t;return t=e.n,e.e.b+t.d+t.a}function kve(e){var t;return t=e.n,e.e.a+t.b+t.c}function QWe(e){return yi(),new Yd(0,e)}function SQt(e){return e.a?e.a:ere(e)}function u_(e){if(!e)throw J(new Wx(null))}function ZWe(){ZWe=pe,Cfe=(hn(),new D(tue))}function _j(){_j=pe,new w3e((Yee(),due),(Xee(),fue))}function JWe(){JWe=pe,G8e=Me(Za,Qe,19,256,0,1)}function kne(e,t,n,r){Wye.call(this,e,t,n,r,0,0)}function AQt(e,t,n){return Si(e.b,u(n.b,17),t)}function LQt(e,t,n){return Si(e.b,u(n.b,17),t)}function MQt(e,t){return it(e,new Pt(t.a,t.b))}function DQt(e,t){return e.c=t)throw J(new lpe)}function dZt(e,t,n){return cs(t,0,_ve(t[0],n[0])),t}function gZt(e,t,n){t.Ye(n,Ue(ft(er(e.b,n)))*e.a)}function RKe(e,t,n){return g4(),$8(e,t)&&$8(e,n)}function g_(e){return ol(),!e.Hc(Z0)&&!e.Hc(m2)}function jj(e){return new Pt(e.c+e.b/2,e.d+e.a/2)}function One(e,t){return t.kh()?Up(e.b,u(t,49)):t}function Hve(e,t){this.e=e,this.d=t&64?t|Ed:t}function FKe(e,t){this.c=0,this.d=e,this.b=t|64|Ed}function $j(e){this.b=new su(11),this.a=(q3(),e)}function Nne(e){this.b=null,this.a=(q3(),e||r7e)}function jKe(e){this.a=lit(e.a),this.b=new Uu(e.b)}function $Ke(e){this.b=e,_6.call(this,e),GVe(this)}function HKe(e){this.b=e,NM.call(this,e),qVe(this)}function Pm(e,t,n){this.a=e,S6.call(this,t,n,5,6)}function zve(e,t,n,r){this.b=e,Bs.call(this,t,n,r)}function oa(e,t,n,r,s){jre.call(this,e,t,n,r,s,-1)}function p_(e,t,n,r,s){dD.call(this,e,t,n,r,s,-1)}function at(e,t,n,r){Bs.call(this,e,t,n),this.b=r}function Hj(e,t,n,r){UM.call(this,e,t,n),this.b=r}function zKe(e){Vqe.call(this,e,!1),this.a=!1}function GKe(e,t){this.b=e,see.call(this,e.b),this.a=t}function qKe(e,t){Rm(),vUt.call(this,e,pH(new Al(t)))}function zj(e,t){return yi(),new nwe(e,t,0)}function Pne(e,t){return yi(),new nwe(6,e,t)}function pZt(e,t){return an(e.substr(0,t.length),t)}function Il(e,t){return fa(t)?rre(e,t):!!$o(e.f,t)}function La(e,t){for(Sn(t);e.Ob();)t.td(e.Pb())}function z3(e,t,n){Qp(),this.e=e,this.d=t,this.a=n}function kg(e,t,n,r){var s;s=e.i,s.i=t,s.a=n,s.b=r}function Gve(e){var t;for(t=e;t.f;)t=t.f;return t}function I6(e){var t;return t=F_(e),Qn(t!=null),t}function bZt(e){var t;return t=ton(e),Qn(t!=null),t}function g8(e,t){var n;return n=e.a.gc(),eme(t,n),n-t}function qve(e,t){var n;for(n=0;n0?b.Math.log(e/t):-100}function VKe(e,t){return Mc(e,t)<0?-1:Mc(e,t)>0?1:0}function Yve(e,t,n){return Fut(e,u(t,46),u(n,167))}function UKe(e,t){return u(jve(Cv(e.a)).Xb(t),42).cd()}function _Zt(e,t){return Krn(t,e.length),new YWe(e,t)}function jne(e,t){this.d=e,rr.call(this,e),this.e=t}function Sv(e){this.d=(Sn(e),e),this.a=0,this.c=Cz}function Xve(e,t){cv.call(this,1),this.a=e,this.b=t}function WKe(e,t){return e.c?WKe(e.c,t):it(e.b,t),e}function CZt(e,t,n){var r;return r=Gm(e,t),Ere(e,t,n),r}function Qve(e,t){var n;return n=e.slice(0,t),gme(n,e)}function KKe(e,t,n){var r;for(r=0;r=e.g}function Kne(e,t,n){var r;return r=sie(e,t,n),_5e(e,r)}function O6(e,t){var n;n=e.a.length,Gm(e,n),Ere(e,n,t)}function uYe(e,t){var n;n=console[e],n.call(console,t)}function lYe(e,t){var n;++e.j,n=e.Vi(),e.Ii(e.oi(n,t))}function FZt(e,t,n){u(t.b,65),Mu(t.a,new ive(e,n,t))}function twe(e,t,n){nF.call(this,t),this.a=e,this.b=n}function nwe(e,t,n){cv.call(this,e),this.a=t,this.b=n}function rwe(e,t,n){this.a=e,npe.call(this,t),this.b=n}function hYe(e,t,n){this.a=e,Owe.call(this,8,t,null,n)}function jZt(e){this.a=(Sn(Zr),Zr),this.b=e,new Epe}function fYe(e){this.c=e,this.b=this.c.a,this.a=this.c.e}function iwe(e){this.c=e,this.b=e.a.d.a,_be(e.a.e,this)}function Ol(e){Am(e.c!=-1),e.d.$c(e.c),e.b=e.c,e.c=-1}function w_(e){return b.Math.sqrt(e.a*e.a+e.b*e.b)}function Lv(e,t){return d8(t,e.a.c.length),St(e.a,t)}function md(e,t){return je(e)===je(t)||e!=null&&Ci(e,t)}function $Zt(e){return 0>=e?new Xpe:Cin(e-1)}function HZt(e){return Yy?rre(Yy,e):!1}function dYe(e){return e?e.dc():!e.Kc().Ob()}function Ya(e){return!e.a&&e.c?e.c.b:e.a}function zZt(e){return!e.a&&(e.a=new Bs(y2,e,4)),e.a}function Mv(e){return!e.d&&(e.d=new Bs(Eo,e,1)),e.d}function Sn(e){if(e==null)throw J(new mT);return e}function m_(e){e.c?e.c.He():(e.d=!0,Wgn(e))}function Fp(e){e.c?Fp(e.c):(ub(e),e.d=!0)}function gYe(e){cwe(e.a),e.b=Me(Yn,yt,1,e.b.length,5,1)}function GZt(e,t){return Tu(t.j.c.length,e.j.c.length)}function qZt(e,t){e.c<0||e.b.b=0?e.Bh(n):P4e(e,t)}function pYe(e){var t,n;return t=e.c.i.c,n=e.d.i.c,t==n}function UZt(e){if(e.p!=4)throw J(new zu);return e.e}function WZt(e){if(e.p!=3)throw J(new zu);return e.e}function KZt(e){if(e.p!=6)throw J(new zu);return e.f}function YZt(e){if(e.p!=6)throw J(new zu);return e.k}function XZt(e){if(e.p!=3)throw J(new zu);return e.j}function QZt(e){if(e.p!=4)throw J(new zu);return e.j}function swe(e){return!e.b&&(e.b=new rF(new Kee)),e.b}function Dv(e){return e.c==-2&&zx(e,pfn(e.g,e.b)),e.c}function v8(e,t){var n;return n=Gne("",e),n.n=t,n.i=1,n}function ZZt(e,t){Ane(u(t.b,65),e),Mu(t.a,new ni(e))}function JZt(e,t){Br((!e.a&&(e.a=new jM(e,e)),e.a),t)}function bYe(e,t){this.b=e,jne.call(this,e,t),GVe(this)}function vYe(e,t){this.b=e,Kbe.call(this,e,t),qVe(this)}function awe(e,t,n,r){vv.call(this,e,t),this.d=n,this.a=r}function Vj(e,t,n,r){vv.call(this,e,n),this.a=t,this.f=r}function wYe(e,t){OWt.call(this,Sin(Nr(e),Nr(t))),this.a=t}function mYe(){d4e.call(this,_b,(xze(),x4t)),kwn(this)}function yYe(){d4e.call(this,Uh,(Qx(),RAe)),Mvn(this)}function kYe(){Kr.call(this,"DELAUNAY_TRIANGULATION",0)}function eJt(e){return String.fromCharCode.apply(null,e)}function Si(e,t,n){return fa(t)?Oo(e,t,n):gu(e.f,t,n)}function owe(e){return hn(),e?e.ve():(q3(),q3(),s7e)}function tJt(e,t,n){return W6(),n.pg(e,u(t.cd(),146))}function xYe(e,t){return _j(),new w3e(new rUe(e),new nUe(t))}function nJt(e){return ql(e,Nae),R$(Ua(Ua(5,e),e/10|0))}function Uj(){Uj=pe,k0t=new Qee(ie(re(Cb,1),Sz,42,0,[]))}function EYe(e){return!e.d&&(e.d=new T(e.c.Cc())),e.d}function w8(e){return!e.a&&(e.a=new rze(e.c.vc())),e.a}function TYe(e){return!e.b&&(e.b=new Kx(e.c.ec())),e.b}function Qd(e,t){for(;t-- >0;)e=e<<1|(e<0?1:0);return e}function Vc(e,t){return je(e)===je(t)||e!=null&&Ci(e,t)}function rJt(e,t){return Mn(),u(t.b,19).ar&&++r,r}function L0(e){var t,n;return n=(t=new uv,t),I8(n,e),n}function Jne(e){var t,n;return n=(t=new uv,t),b4e(n,e),n}function wJt(e,t){var n;return n=er(e.f,t),Wme(t,n),null}function ere(e){var t;return t=Lin(e),t||null}function NYe(e){return!e.b&&(e.b=new at(ra,e,12,3)),e.b}function mJt(e){return e!=null&&gM(ZV,e.toLowerCase())}function yJt(e,t){return Fs(Wu(e)*Dl(e),Wu(t)*Dl(t))}function kJt(e,t){return Fs(Wu(e)*Dl(e),Wu(t)*Dl(t))}function xJt(e,t){return Fs(e.d.c+e.d.b/2,t.d.c+t.d.b/2)}function EJt(e,t){return Fs(e.g.c+e.g.b/2,t.g.c+t.g.b/2)}function PYe(e,t,n){n.a?Iu(e,t.b-e.f/2):Du(e,t.a-e.g/2)}function BYe(e,t,n,r){this.a=e,this.b=t,this.c=n,this.d=r}function RYe(e,t,n,r){this.a=e,this.b=t,this.c=n,this.d=r}function K2(e,t,n,r){this.e=e,this.a=t,this.c=n,this.d=r}function FYe(e,t,n,r){this.a=e,this.c=t,this.d=n,this.b=r}function jYe(e,t,n,r){lh(),DZe.call(this,t,n,r),this.a=e}function $Ye(e,t,n,r){lh(),DZe.call(this,t,n,r),this.a=e}function HYe(e,t){this.a=e,LKt.call(this,e,u(e.d,15).Zc(t))}function tre(e){this.f=e,this.c=this.f.e,e.f>0&&tst(this)}function zYe(e,t,n,r){this.b=e,this.c=r,Hte.call(this,t,n)}function GYe(e){return Qn(e.b=0&&an(e.substr(n,t.length),t)}function jp(e,t,n,r,s,o,h){return new _re(e.e,t,n,r,s,o,h)}function aXe(e,t,n,r,s,o){this.a=e,Zre.call(this,t,n,r,s,o)}function oXe(e,t,n,r,s,o){this.a=e,Zre.call(this,t,n,r,s,o)}function cXe(e,t){this.g=e,this.d=ie(re(h0,1),Bg,10,0,[t])}function xg(e,t){this.e=e,this.a=Yn,this.b=Oct(t),this.c=t}function uXe(e,t){bj.call(this),xme(this),this.a=e,this.c=t}function eD(e,t,n,r){cs(e.c[t.g],n.g,r),cs(e.c[n.g],t.g,r)}function are(e,t,n,r){cs(e.c[t.g],t.g,n),cs(e.b[t.g],t.g,r)}function VJt(){return uD(),ie(re(__e,1),tt,376,0,[dhe,DO])}function UJt(){return pD(),ie(re(v9e,1),tt,479,0,[b9e,Dq])}function WJt(){return ED(),ie(re(g9e,1),tt,419,0,[Lq,d9e])}function KJt(){return S$(),ie(re(a9e,1),tt,422,0,[s9e,gle])}function YJt(){return b$(),ie(re(M9e,1),tt,420,0,[Lle,L9e])}function XJt(){return mD(),ie(re(k_e,1),tt,421,0,[lhe,hhe])}function QJt(){return S_(),ie(re(Cwt,1),tt,523,0,[TS,ES])}function ZJt(){return Jf(),ie(re(Xwt,1),tt,520,0,[jy,d2])}function JJt(){return yd(),ie(re(Owt,1),tt,516,0,[Lw,Gg])}function een(){return M1(),ie(re(Pwt,1),tt,515,0,[Pb,K1])}function ten(){return Ov(),ie(re(rmt,1),tt,455,0,[g2,Y4])}function nen(){return f$(),ie(re(Y_e,1),tt,425,0,[Ahe,K_e])}function ren(){return c$(),ie(re(W_e,1),tt,480,0,[She,U_e])}function ien(){return J$(),ie(re(X_e,1),tt,495,0,[mV,yE])}function sen(){return L$(),ie(re(Z_e,1),tt,426,0,[Q_e,Ihe])}function aen(){return OD(),ie(re(tSe,1),tt,429,0,[AV,eSe])}function oen(){return lD(),ie(re(OCe,1),tt,430,0,[Hhe,CV])}function cen(){return LH(),ie(re(w7e,1),tt,428,0,[Aue,v7e])}function uen(){return P$(),ie(re(y7e,1),tt,427,0,[m7e,Lue])}function len(){return B$(),ie(re(K7e,1),tt,424,0,[$ue,ZG])}function hen(){return j8(),ie(re(Ypt,1),tt,511,0,[gO,Jue])}function r$(e,t,n,r){return n>=0?e.jh(t,n,r):e.Sg(null,n,r)}function ore(e){return e.b.b==0?e.a.$e():mne(e.b)}function fen(e){if(e.p!=5)throw J(new zu);return Or(e.f)}function den(e){if(e.p!=5)throw J(new zu);return Or(e.k)}function bwe(e){return je(e.a)===je((cie(),Efe))&&gwn(e),e.a}function lXe(e){this.a=u(Nr(e),271),this.b=(hn(),new ube(e))}function hXe(e,t){Yge(this,new Pt(e.a,e.b)),VR(this,VM(t))}function Ov(){Ov=pe,g2=new T2e(uk,0),Y4=new T2e(lk,1)}function yd(){yd=pe,Lw=new x2e(lk,0),Gg=new x2e(uk,1)}function Nv(){EVt.call(this,new w6(qm(12))),sbe(!0),this.a=2}function cre(e,t,n){yi(),cv.call(this,e),this.b=t,this.a=n}function vwe(e,t,n){lh(),nF.call(this,t),this.a=e,this.b=n}function fXe(e){bj.call(this),xme(this),this.a=e,this.c=!0}function dXe(e){var t;t=e.c.d.b,e.b=t,e.a=e.c.d,t.a=e.c.d.b=e}function i$(e){var t;yin(e.a),TVe(e.a),t=new nr(e.a),Uye(t)}function gen(e,t){Tct(e,!0),Mu(e.e.wf(),new eve(e,!0,t))}function s$(e,t){return UQe(t),vin(e,Me(Lr,Jr,25,t,15,1),t)}function pen(e,t){return P6(),e==us(n0(t))||e==us(Kp(t))}function Uc(e,t){return t==null?hc($o(e.f,null)):BT(e.g,t)}function ben(e){return e.b==0?null:(Qn(e.b!=0),bh(e,e.a.a))}function _s(e){return Math.max(Math.min(e,Ei),-2147483648)|0}function ven(e,t){var n=wue[e.charCodeAt(0)];return n??e}function a$(e,t){return Zj(e,"set1"),Zj(t,"set2"),new uGe(e,t)}function wen(e,t){var n;return n=fin(e.f,t),Ni(gj(n),e.f.d)}function k_(e,t){var n,r;return n=t,r=new Nt,flt(e,n,r),r.d}function ure(e,t,n,r){var s;s=new eWe,t.a[n.g]=s,M6(e.b,r,s)}function wwe(e,t,n){var r;r=e.Yg(t),r>=0?e.sh(r,n):o5e(e,t,n)}function V3(e,t,n){u$(),e&&Si(yfe,e,t),e&&Si(oN,e,n)}function gXe(e,t,n){this.i=new st,this.b=e,this.g=t,this.a=n}function o$(e,t,n){this.c=new st,this.e=e,this.f=t,this.b=n}function mwe(e,t,n){this.a=new st,this.e=e,this.f=t,this.c=n}function pXe(e,t){ij(this),this.f=t,this.g=e,Qj(this),this._d()}function tD(e,t){var n;n=e.q.getHours(),e.q.setDate(t),lC(e,n)}function bXe(e,t){var n;for(Nr(t),n=e.a;n;n=n.c)t.Od(n.g,n.i)}function vXe(e){var t;return t=new bF(qm(e.length)),lye(t,e),t}function men(e){function t(){}return t.prototype=e||{},new t}function yen(e,t){return Ktt(e,t)?(Uet(e),!0):!1}function M0(e,t){if(t==null)throw J(new mT);return vcn(e,t)}function ken(e){if(e.qe())return null;var t=e.n;return PG[t]}function nD(e){return e.Db>>16!=3?null:u(e.Cb,33)}function L1(e){return e.Db>>16!=9?null:u(e.Cb,33)}function wXe(e){return e.Db>>16!=6?null:u(e.Cb,79)}function mXe(e){return e.Db>>16!=7?null:u(e.Cb,235)}function yXe(e){return e.Db>>16!=7?null:u(e.Cb,160)}function us(e){return e.Db>>16!=11?null:u(e.Cb,33)}function kXe(e,t){var n;return n=e.Yg(t),n>=0?e.lh(n):Fse(e,t)}function xXe(e,t){var n;return n=new Tve(t),_st(n,e),new Uu(n)}function ywe(e){var t;return t=e.d,t=e.si(e.f),Br(e,t),t.Ob()}function EXe(e,t){return e.b+=t.b,e.c+=t.c,e.d+=t.d,e.a+=t.a,e}function lre(e,t){return b.Math.abs(e)0}function TXe(){this.a=new C0,this.e=new Ys,this.g=0,this.i=0}function _Xe(e){this.a=e,this.b=Me(Ewt,Qe,1944,e.e.length,0,2)}function hre(e,t,n){var r;r=gnt(e,t,n),e.b=new Z$(r.c.length)}function M1(){M1=pe,Pb=new k2e(voe,0),K1=new k2e("UP",1)}function c$(){c$=pe,She=new _2e(Hft,0),U_e=new _2e("FAN",1)}function u$(){u$=pe,yfe=new Mr,oN=new Mr,zUt(j0t,new $9)}function Een(e){if(e.p!=0)throw J(new zu);return XT(e.f,0)}function Ten(e){if(e.p!=0)throw J(new zu);return XT(e.k,0)}function CXe(e){return e.Db>>16!=3?null:u(e.Cb,147)}function x8(e){return e.Db>>16!=6?null:u(e.Cb,235)}function Fm(e){return e.Db>>16!=17?null:u(e.Cb,26)}function SXe(e,t){var n=e.a=e.a||[];return n[t]||(n[t]=e.le(t))}function _en(e,t){var n;return n=e.a.get(t),n??new Array}function Cen(e,t){var n;n=e.q.getHours(),e.q.setMonth(t),lC(e,n)}function Oo(e,t,n){return t==null?gu(e.f,null,n):Wv(e.g,t,n)}function x_(e,t,n,r,s,o){return new N0(e.e,t,e.aj(),n,r,s,o)}function rD(e,t,n){return e.a=jl(e.a,0,t)+(""+n)+IM(e.a,t),e}function Sen(e,t,n){return it(e.a,(Uj(),cse(t,n),new vv(t,n))),e}function kwe(e){return obe(e.c),e.e=e.a=e.c,e.c=e.c.c,++e.d,e.a.f}function AXe(e){return obe(e.e),e.c=e.a=e.e,e.e=e.e.e,--e.d,e.a.f}function ba(e,t){e.d&&Au(e.d.e,e),e.d=t,e.d&&it(e.d.e,e)}function Va(e,t){e.c&&Au(e.c.g,e),e.c=t,e.c&&it(e.c.g,e)}function No(e,t){e.c&&Au(e.c.a,e),e.c=t,e.c&&it(e.c.a,e)}function rc(e,t){e.i&&Au(e.i.j,e),e.i=t,e.i&&it(e.i.j,e)}function LXe(e,t,n){this.a=t,this.c=e,this.b=(Nr(n),new Uu(n))}function MXe(e,t,n){this.a=t,this.c=e,this.b=(Nr(n),new Uu(n))}function DXe(e,t){this.a=e,this.c=fc(this.a),this.b=new n$(t)}function Aen(e){var t;return ub(e),t=new Ys,Vi(e,new $t(t))}function jm(e,t){if(e<0||e>t)throw J(new Do(C6e+e+S6e+t))}function xwe(e,t){return kKe(e.a,t)?Uve(e,u(t,22).g,null):null}function Len(e){return Aie(),Mn(),u(e.a,81).d.e!=0}function IXe(){IXe=pe,T0t=Qr((cF(),ie(re(E0t,1),tt,538,0,[bue])))}function OXe(){OXe=pe,lwt=il(new Xs,(ro(),Go),(po(),pO))}function Ewe(){Ewe=pe,hwt=il(new Xs,(ro(),Go),(po(),pO))}function NXe(){NXe=pe,dwt=il(new Xs,(ro(),Go),(po(),pO))}function PXe(){PXe=pe,Awt=xi(new Xs,(ro(),Go),(po(),nS))}function $l(){$l=pe,Dwt=xi(new Xs,(ro(),Go),(po(),nS))}function BXe(){BXe=pe,Iwt=xi(new Xs,(ro(),Go),(po(),nS))}function fre(){fre=pe,Rwt=xi(new Xs,(ro(),Go),(po(),nS))}function RXe(){RXe=pe,Emt=il(new Xs,(a7(),CS),(nC(),whe))}function X2(e,t,n,r){this.c=e,this.d=r,gre(this,t),pre(this,n)}function R6(e){this.c=new as,this.b=e.b,this.d=e.c,this.a=e.a}function dre(e){this.a=b.Math.cos(e),this.b=b.Math.sin(e)}function gre(e,t){e.a&&Au(e.a.k,e),e.a=t,e.a&&it(e.a.k,e)}function pre(e,t){e.b&&Au(e.b.f,e),e.b=t,e.b&&it(e.b.f,e)}function FXe(e,t){FZt(e,e.b,e.c),u(e.b.b,65),t&&u(t.b,65).b}function Men(e,t){jye(e,t),we(e.Cb,88)&&iy(dl(u(e.Cb,88)),2)}function bre(e,t){we(e.Cb,88)&&iy(dl(u(e.Cb,88)),4),au(e,t)}function l$(e,t){we(e.Cb,179)&&(u(e.Cb,179).tb=null),au(e,t)}function Wc(e,t){return ho(),Ure(t)?new Cj(t,e):new DM(t,e)}function Den(e,t){var n,r;n=t.c,r=n!=null,r&&O6(e,new Bm(t.c))}function jXe(e){var t,n;return n=(Qx(),t=new uv,t),I8(n,e),n}function $Xe(e){var t,n;return n=(Qx(),t=new uv,t),I8(n,e),n}function HXe(e,t){var n;return n=new Bh(e),t.c[t.c.length]=n,n}function zXe(e,t){var n;return n=u(Ym(B6(e.a),t),14),n?n.gc():0}function GXe(e){var t;return ub(e),t=(q3(),q3(),i7e),j$(e,t)}function qXe(e){for(var t;;)if(t=e.Pb(),!e.Ob())return t}function Twe(e,t){kVt.call(this,new w6(qm(e))),ql(t,sht),this.a=t}function Zd(e,t,n){Jnt(t,n,e.gc()),this.c=e,this.a=t,this.b=n-t}function VXe(e,t,n){var r;Jnt(t,n,e.c.length),r=n-t,Kpe(e.c,t,r)}function Ien(e,t){zVe(e,Or(qs(Np(t,24),Mz)),Or(qs(t,Mz)))}function xn(e,t){if(e<0||e>=t)throw J(new Do(C6e+e+S6e+t))}function zr(e,t){if(e<0||e>=t)throw J(new Bpe(C6e+e+S6e+t))}function mn(e,t){this.b=(Sn(e),e),this.a=t&dy?t:t|64|Ed}function UXe(e){EVe(this),rHe(this.a,cye(b.Math.max(8,e))<<1)}function D1(e){return sc(ie(re(na,1),Qe,8,0,[e.i.n,e.n,e.a]))}function Oen(){return F1(),ie(re(yl,1),tt,132,0,[g7e,Ql,xy])}function Nen(){return n1(),ie(re(Ey,1),tt,232,0,[pc,lu,bc])}function Pen(){return al(),ie(re(cgt,1),tt,461,0,[Nd,a2,Af])}function Ben(){return Lu(),ie(re(lgt,1),tt,462,0,[u1,o2,Lf])}function Ren(){return Uv(),ie(re(fEe,1),tt,423,0,[N4,hEe,Xue])}function Fen(){return L_(),ie(re(cEe,1),tt,379,0,[que,Gue,Vue])}function jen(){return j_(),ie(re(h_e,1),tt,378,0,[ihe,l_e,iV])}function $en(){return V6(),ie(re(c9e,1),tt,314,0,[Ek,vO,o9e])}function Hen(){return V$(),ie(re(l9e,1),tt,337,0,[u9e,Aq,ple])}function zen(){return sb(),ie(re(T2t,1),tt,450,0,[wle,aE,F4])}function Gen(){return qv(),ie(re(sle,1),tt,361,0,[mw,u2,ww])}function qen(){return P0(),ie(re(I2t,1),tt,303,0,[mO,$4,Tk])}function Ven(){return q8(),ie(re(Ale,1),tt,292,0,[Cle,Sle,wO])}function Uen(){return vo(),ie(re(rwt,1),tt,452,0,[yS,ul,hu])}function Wen(){return R0(),ie(re(y_e,1),tt,339,0,[f2,m_e,uhe])}function Ken(){return iH(),ie(re(T_e,1),tt,375,0,[x_e,fhe,E_e])}function Yen(){return uH(),ie(re(D_e,1),tt,377,0,[bhe,wE,Fy])}function Xen(){return Q8(),ie(re(S_e,1),tt,336,0,[ghe,C_e,kS])}function Qen(){return nH(),ie(re(M_e,1),tt,338,0,[L_e,phe,A_e])}function Zen(){return Gv(),ie(re(kwt,1),tt,454,0,[IO,xS,cV])}function Jen(){return yH(),ie(re(Amt,1),tt,442,0,[Dhe,Lhe,Mhe])}function etn(){return RD(),ie(re(tCe,1),tt,380,0,[yV,J_e,eCe])}function ttn(){return mH(),ie(re(mCe,1),tt,381,0,[wCe,Rhe,vCe])}function ntn(){return rH(),ie(re(pCe,1),tt,293,0,[Bhe,gCe,dCe])}function rtn(){return GD(),ie(re(Fhe,1),tt,437,0,[EV,TV,_V])}function itn(){return F0(),ie(re(cAe,1),tt,334,0,[FV,Wg,jS])}function stn(){return P1(),ie(re(XSe,1),tt,272,0,[EE,zy,TE])}function atn(e,t){return S0n(e,t,we(t,99)&&(u(t,18).Bb&so)!=0)}function otn(e,t,n){var r;return r=dC(e,t,!1),r.b<=t&&r.a<=n}function WXe(e,t,n){var r;r=new TQ,r.b=t,r.a=n,++t.b,it(e.d,r)}function ctn(e,t){var n;return n=(Sn(e),e).g,mbe(!!n),Sn(t),n(t)}function _we(e,t){var n,r;return r=g8(e,t),n=e.a.Zc(r),new cGe(e,n)}function utn(e){return e.Db>>16!=6?null:u(Hse(e),235)}function ltn(e){if(e.p!=2)throw J(new zu);return Or(e.f)&Ss}function htn(e){if(e.p!=2)throw J(new zu);return Or(e.k)&Ss}function ftn(e){return e.a==(C8(),nU)&&_ee(e,G0n(e.g,e.b)),e.a}function F6(e){return e.d==(C8(),nU)&&dT(e,B2n(e.g,e.b)),e.d}function Y(e){return Qn(e.ar?1:0}function KXe(e,t){var n,r;return n=Hre(t),r=n,u(er(e.c,r),19).a}function YXe(e,t){var n;for(n=e+"";n.length0&&e.a[--e.d]==0;);e.a[e.d++]==0&&(e.e=0)}function gQe(e){return e.a?e.e.length==0?e.a.a:e.a.a+(""+e.e):e.c}function Etn(e){return!!e.a&&gl(e.a.a).i!=0&&!(e.b&&sse(e.b))}function Ttn(e){return!!e.u&&jc(e.u.a).i!=0&&!(e.n&&ise(e.n))}function pQe(e){return Ene(e.e.Hd().gc()*e.c.Hd().gc(),16,new r6(e))}function _tn(e,t){return VKe(Ou(e.q.getTime()),Ou(t.q.getTime()))}function kd(e){return u(j1(e,Me(Que,Ooe,17,e.c.length,0,1)),474)}function iD(e){return u(j1(e,Me(h0,Bg,10,e.c.length,0,1)),193)}function Ctn(e){return $l(),!to(e)&&!(!to(e)&&e.c.i.c==e.d.i.c)}function bQe(e,t,n){var r;r=(Nr(e),new Uu(e)),nln(new LXe(r,t,n))}function sD(e,t,n){var r;r=(Nr(e),new Uu(e)),rln(new MXe(r,t,n))}function vQe(e,t){var n;return n=1-t,e.a[n]=Q$(e.a[n],n),Q$(e,t)}function wQe(e,t){var n;e.e=new Lpe,n=oy(t),aa(n,e.c),dct(e,n,0)}function va(e,t,n,r){var s;s=new zB,s.a=t,s.b=n,s.c=r,ci(e.a,s)}function dt(e,t,n,r){var s;s=new zB,s.a=t,s.b=n,s.c=r,ci(e.b,s)}function kf(e){var t,n,r;return t=new ZKe,n=aae(t,e),hmn(t),r=n,r}function Dwe(){var e,t,n;return t=(n=(e=new uv,e),n),it(WAe,t),t}function d$(e){return e.j.c=Me(Yn,yt,1,0,5,1),cwe(e.c),aJt(e.a),e}function U3(e){return IT(),we(e.g,10)?u(e.g,10):null}function Stn(e){return G3(e).dc()?!1:(CWt(e,new de),!0)}function Atn(e){if(!("stack"in e))try{throw e}catch{}return e}function aD(e,t){if(e<0||e>=t)throw J(new Do(H1n(e,t)));return e}function mQe(e,t,n){if(e<0||tn)throw J(new Do(f1n(e,t,n)))}function yre(e,t){if(Gs(e.a,t),t.d)throw J(new tc(Sht));t.d=e}function kre(e,t){if(t.$modCount!=e.$modCount)throw J(new uh)}function yQe(e,t){return we(t,42)?lse(e.a,u(t,42)):!1}function kQe(e,t){return we(t,42)?lse(e.a,u(t,42)):!1}function xQe(e,t){return we(t,42)?lse(e.a,u(t,42)):!1}function Ltn(e,t){return e.a<=e.b?(t.ud(e.a++),!0):!1}function Bv(e){var t;return Ko(e)?(t=e,t==-0?0:t):Frn(e)}function g$(e){var t;return Fp(e),t=new kt,D3(e.a,new un(t)),t}function EQe(e){var t;return Fp(e),t=new oi,D3(e.a,new lt(t)),t}function Ea(e,t){this.a=e,c6.call(this,e),jm(t,e.gc()),this.b=t}function Iwe(e){this.e=e,this.b=this.e.a.entries(),this.a=new Array}function Mtn(e){return Ene(e.e.Hd().gc()*e.c.Hd().gc(),273,new jR(e))}function p$(e){return new su((ql(e,Nae),R$(Ua(Ua(5,e),e/10|0))))}function TQe(e){return u(j1(e,Me(Upt,ift,11,e.c.length,0,1)),1943)}function Dtn(e,t,n){return n.f.c.length>0?Yve(e.a,t,n):Yve(e.b,t,n)}function Itn(e,t,n){e.d&&Au(e.d.e,e),e.d=t,e.d&&Om(e.d.e,n,e)}function xre(e,t){_yn(t,e),gve(e.d),gve(u(K(e,(pt(),Qq)),207))}function T_(e,t){Tyn(t,e),dve(e.d),dve(u(K(e,(pt(),Qq)),207))}function Rv(e,t){var n,r;return n=M0(e,t),r=null,n&&(r=n.fe()),r}function E8(e,t){var n,r;return n=Gm(e,t),r=null,n&&(r=n.ie()),r}function __(e,t){var n,r;return n=M0(e,t),r=null,n&&(r=n.ie()),r}function D0(e,t){var n,r;return n=M0(e,t),r=null,n&&(r=E4e(n)),r}function Otn(e,t,n){var r;return r=i7(n),fz(e.g,r,t),fz(e.i,t,n),t}function Ntn(e,t,n){var r;r=ccn();try{return jKt(e,t,n)}finally{Vtn(r)}}function _Qe(e){var t;t=e.Wg(),this.a=we(t,69)?u(t,69).Zh():t.Kc()}function Xs(){jHe.call(this),this.j.c=Me(Yn,yt,1,0,5,1),this.a=-1}function Owe(e,t,n,r){this.d=e,this.n=t,this.g=n,this.o=r,this.p=-1}function CQe(e,t,n,r){this.e=r,this.d=null,this.c=e,this.a=t,this.b=n}function Nwe(e,t,n){this.d=new eF(this),this.e=e,this.i=t,this.f=n}function b$(){b$=pe,Lle=new v2e(D7,0),L9e=new v2e("TOP_LEFT",1)}function SQe(){SQe=pe,O_e=xYe(ct(1),ct(4)),I_e=xYe(ct(1),ct(2))}function AQe(){AQe=pe,wyt=Qr((CF(),ie(re(vyt,1),tt,551,0,[$he])))}function LQe(){LQe=pe,byt=Qr((_F(),ie(re(ICe,1),tt,482,0,[jhe])))}function MQe(){MQe=pe,Byt=Qr((OT(),ie(re(JCe,1),tt,530,0,[FO])))}function DQe(){DQe=pe,zgt=Qr((EF(),ie(re(H7e,1),tt,481,0,[Pue])))}function Ptn(){return Vv(),ie(re(Pgt,1),tt,406,0,[sO,iO,Oue,Nue])}function Btn(){return M$(),ie(re(GG,1),tt,297,0,[_ue,l7e,h7e,f7e])}function Rtn(){return Y_(),ie(re($gt,1),tt,394,0,[lO,KG,YG,hO])}function Ftn(){return Z6(),ie(re(Rgt,1),tt,323,0,[oO,aO,cO,uO])}function jtn(){return V8(),ie(re(Npt,1),tt,405,0,[vw,_y,Ty,O4])}function $tn(){return cH(),ie(re(Jpt,1),tt,360,0,[rle,kq,xq,bO])}function IQe(e,t,n,r){return we(n,54)?new wUe(e,t,n,r):new Fve(e,t,n,r)}function Htn(){return R1(),ie(re(c2t,1),tt,411,0,[xk,tE,nE,ile])}function ztn(e){var t;return e.j==(ht(),xr)&&(t=not(e),Vu(t,$n))}function Gtn(e,t){var n;n=t.a,Va(n,t.c.d),ba(n,t.d.d),Um(n.a,e.n)}function OQe(e,t){return u(Tv(Rj(u(Ii(e.k,t),15).Oc(),P4)),113)}function NQe(e,t){return u(Tv(Fj(u(Ii(e.k,t),15).Oc(),P4)),113)}function qtn(e){return new mn(Hin(u(e.a.dd(),14).gc(),e.a.cd()),16)}function T8(e){return we(e,14)?u(e,14).dc():!e.Kc().Ob()}function j6(e){return IT(),we(e.g,145)?u(e.g,145):null}function PQe(e){if(e.e.g!=e.b)throw J(new uh);return!!e.c&&e.d>0}function ri(e){return Qn(e.b!=e.d.c),e.c=e.b,e.b=e.b.a,++e.a,e.c.c}function Pwe(e,t){Sn(t),cs(e.a,e.c,t),e.c=e.c+1&e.a.length-1,Fit(e)}function $p(e,t){Sn(t),e.b=e.b-1&e.a.length-1,cs(e.a,e.b,t),Fit(e)}function BQe(e,t){var n;for(n=e.j.c.length;n0&&Hc(e.g,0,t,0,e.i),t}function $Qe(e,t){LF();var n;return n=u(er(QV,e),55),!n||n.wj(t)}function rnn(e){if(e.p!=1)throw J(new zu);return Or(e.f)<<24>>24}function inn(e){if(e.p!=1)throw J(new zu);return Or(e.k)<<24>>24}function snn(e){if(e.p!=7)throw J(new zu);return Or(e.k)<<16>>16}function ann(e){if(e.p!=7)throw J(new zu);return Or(e.f)<<16>>16}function I0(e){var t;for(t=0;e.Ob();)e.Pb(),t=Ua(t,1);return R$(t)}function HQe(e,t){var n;return n=new xm,e.xd(n),n.a+="..",t.yd(n),n.a}function onn(e,t,n){var r;r=u(er(e.g,n),57),it(e.a.c,new xa(t,r))}function cnn(e,t,n){return Ine(ft(hc($o(e.f,t))),ft(hc($o(e.f,n))))}function v$(e,t,n){return gz(e,t,n,we(t,99)&&(u(t,18).Bb&so)!=0)}function unn(e,t,n){return y7(e,t,n,we(t,99)&&(u(t,18).Bb&so)!=0)}function lnn(e,t,n){return O0n(e,t,n,we(t,99)&&(u(t,18).Bb&so)!=0)}function Fwe(e,t){return e==(zn(),Hs)&&t==Hs?4:e==Hs||t==Hs?8:32}function zQe(e,t){return je(t)===je(e)?"(this Map)":t==null?Pu:Qo(t)}function hnn(e,t){return u(t==null?hc($o(e.f,null)):BT(e.g,t),281)}function GQe(e,t,n){var r;return r=i7(n),Si(e.b,r,t),Si(e.c,t,n),t}function qQe(e,t){var n;for(n=t;n;)Lm(e,n.i,n.j),n=us(n);return e}function jwe(e,t){var n;return n=ZM(l8(new zre(e,t))),Aj(new zre(e,t)),n}function Jd(e,t){ho();var n;return n=u(e,66).Mj(),Vfn(n,t),n.Ok(t)}function fnn(e,t,n,r,s){var o;o=F0n(s,n,r),it(t,B1n(s,o)),Sfn(e,s,t)}function VQe(e,t,n){e.i=0,e.e=0,t!=n&&(wnt(e,t,n),vnt(e,t,n))}function $we(e,t){var n;n=e.q.getHours(),e.q.setFullYear(t+e2),lC(e,n)}function dnn(e,t,n){if(n){var r=n.ee();e.a[t]=r(n)}else delete e.a[t]}function Ere(e,t,n){if(n){var r=n.ee();n=r(n)}else n=void 0;e.a[t]=n}function UQe(e){if(e<0)throw J(new QHe("Negative array size: "+e))}function jc(e){return e.n||(dl(e),e.n=new _Ke(e,Eo,e),jo(e)),e.n}function C_(e){return Qn(e.a=0&&e.a[n]===t[n];n--);return n<0}function QQe(e,t){X8();var n;return n=e.j.g-t.j.g,n!=0?n:0}function ZQe(e,t){return Sn(t),e.a!=null?ZQt(t.Kb(e.a)):zG}function w$(e){var t;return e?new Tve(e):(t=new C0,oie(t,e),t)}function zl(e,t){var n;return t.b.Kb(qJe(e,t.c.Ee(),(n=new Cn(t),n)))}function m$(e){o4e(),zVe(this,Or(qs(Np(e,24),Mz)),Or(qs(e,Mz)))}function JQe(){JQe=pe,ngt=Qr((LH(),ie(re(w7e,1),tt,428,0,[Aue,v7e])))}function eZe(){eZe=pe,rgt=Qr((P$(),ie(re(y7e,1),tt,427,0,[m7e,Lue])))}function tZe(){tZe=pe,spt=Qr((B$(),ie(re(K7e,1),tt,424,0,[$ue,ZG])))}function nZe(){nZe=pe,Xpt=Qr((j8(),ie(re(Ypt,1),tt,511,0,[gO,Jue])))}function rZe(){rZe=pe,E2t=Qr((ED(),ie(re(g9e,1),tt,419,0,[Lq,d9e])))}function iZe(){iZe=pe,S2t=Qr((pD(),ie(re(v9e,1),tt,479,0,[b9e,Dq])))}function sZe(){sZe=pe,awt=Qr((uD(),ie(re(__e,1),tt,376,0,[dhe,DO])))}function aZe(){aZe=pe,nwt=Qr((mD(),ie(re(k_e,1),tt,421,0,[lhe,hhe])))}function oZe(){oZe=pe,m2t=Qr((S$(),ie(re(a9e,1),tt,422,0,[s9e,gle])))}function cZe(){cZe=pe,N2t=Qr((b$(),ie(re(M9e,1),tt,420,0,[Lle,L9e])))}function uZe(){uZe=pe,Qwt=Qr((Jf(),ie(re(Xwt,1),tt,520,0,[jy,d2])))}function lZe(){lZe=pe,Swt=Qr((S_(),ie(re(Cwt,1),tt,523,0,[TS,ES])))}function hZe(){hZe=pe,Nwt=Qr((yd(),ie(re(Owt,1),tt,516,0,[Lw,Gg])))}function fZe(){fZe=pe,Bwt=Qr((M1(),ie(re(Pwt,1),tt,515,0,[Pb,K1])))}function dZe(){dZe=pe,imt=Qr((Ov(),ie(re(rmt,1),tt,455,0,[g2,Y4])))}function gZe(){gZe=pe,xmt=Qr((f$(),ie(re(Y_e,1),tt,425,0,[Ahe,K_e])))}function pZe(){pZe=pe,Smt=Qr((J$(),ie(re(X_e,1),tt,495,0,[mV,yE])))}function bZe(){bZe=pe,kmt=Qr((c$(),ie(re(W_e,1),tt,480,0,[She,U_e])))}function vZe(){vZe=pe,Mmt=Qr((L$(),ie(re(Z_e,1),tt,426,0,[Q_e,Ihe])))}function wZe(){wZe=pe,Ryt=Qr((OD(),ie(re(tSe,1),tt,429,0,[AV,eSe])))}function mZe(){mZe=pe,myt=Qr((lD(),ie(re(OCe,1),tt,430,0,[Hhe,CV])))}function S_(){S_=pe,TS=new y2e("UPPER",0),ES=new y2e("LOWER",1)}function vnn(e,t){var n;n=new p6,Y2(n,"x",t.a),Y2(n,"y",t.b),O6(e,n)}function wnn(e,t){var n;n=new p6,Y2(n,"x",t.a),Y2(n,"y",t.b),O6(e,n)}function mnn(e,t){var n,r;r=!1;do n=unt(e,t),r=r|n;while(n);return r}function Gwe(e,t){var n,r;for(n=t,r=0;n>0;)r+=e.a[n],n-=n&-n;return r}function yZe(e,t){var n;for(n=t;n;)Lm(e,-n.i,-n.j),n=us(n);return e}function Da(e,t){var n,r;for(Sn(t),r=e.Kc();r.Ob();)n=r.Pb(),t.td(n)}function kZe(e,t){var n;return n=t.cd(),new vv(n,e.e.pc(n,u(t.dd(),14)))}function ks(e,t,n,r){var s;s=new wt,s.c=t,s.b=n,s.a=r,r.b=n.a=s,++e.b}function gh(e,t,n){var r;return r=(xn(t,e.c.length),e.c[t]),e.c[t]=n,r}function ynn(e,t,n){return u(t==null?gu(e.f,null,n):Wv(e.g,t,n),281)}function Sre(e){return e.c&&e.d?Cwe(e.c)+"->"+Cwe(e.d):"e_"+xv(e)}function _8(e,t){return(ub(e),LT(new vn(e,new dme(t,e.a)))).sd(X7)}function knn(){return ro(),ie(re(uEe,1),tt,356,0,[Pd,c2,bu,Zc,Go])}function xnn(){return ht(),ie(re(ao,1),Dc,61,0,[uc,An,$n,xr,Dn])}function Enn(e){return fF(),function(){return Ntn(e,this,arguments)}}function Tnn(){return Date.now?Date.now():new Date().getTime()}function to(e){return!e.c||!e.d?!1:!!e.c.i&&e.c.i==e.d.i}function xZe(e){if(!e.c.Sb())throw J(new xc);return e.a=!0,e.c.Ub()}function oD(e){e.i=0,mM(e.b,null),mM(e.c,null),e.a=null,e.e=null,++e.g}function qwe(e){DUt.call(this,e==null?Pu:Qo(e),we(e,78)?u(e,78):null)}function EZe(e){Xlt(),W$e(this),this.a=new as,vye(this,e),ci(this.a,e)}function TZe(){Ute(this),this.b=new Pt(gs,gs),this.a=new Pt(Ds,Ds)}function _Ze(e,t){this.c=0,this.b=t,Jqe.call(this,e,17493),this.a=this.c}function Are(e){y$(),!V1&&(this.c=e,this.e=!0,this.a=new st)}function y$(){y$=pe,V1=!0,U0t=!1,W0t=!1,Y0t=!1,K0t=!1}function Vwe(e,t){return we(t,149)?an(e.c,u(t,149).c):!1}function Uwe(e,t){var n;return n=0,e&&(n+=e.f.a/2),t&&(n+=t.f.a/2),n}function Lre(e,t){var n;return n=u(Fv(e.d,t),23),n||u(Fv(e.e,t),23)}function CZe(e){this.b=e,rr.call(this,e),this.a=u(_n(this.b.a,4),126)}function SZe(e){this.b=e,C6.call(this,e),this.a=u(_n(this.b.a,4),126)}function dl(e){return e.t||(e.t=new R$e(e),G_(new XHe(e),0,e.t)),e.t}function _nn(){return wo(),ie(re(RS,1),tt,103,0,[f0,Df,Xh,Y0,X0])}function Cnn(){return n4(),ie(re(HS,1),tt,249,0,[v2,ZO,uAe,$S,lAe])}function Snn(){return i1(),ie(re(Ug,1),tt,175,0,[Fn,ua,Fd,Bb,Vg])}function Ann(){return rI(),ie(re(RCe,1),tt,316,0,[NCe,zhe,BCe,Ghe,PCe])}function Lnn(){return X_(),ie(re(d_e,1),tt,315,0,[f_e,ohe,che,wS,mS])}function Mnn(){return db(),ie(re(f9e,1),tt,335,0,[ble,h9e,vle,sS,iS])}function Dnn(){return v7(),ie(re(dyt,1),tt,355,0,[X4,Nk,IS,DS,OS])}function Inn(){return c4(),ie(re(l2t,1),tt,363,0,[Tq,Cq,Sq,_q,Eq])}function Onn(){return mh(),ie(re(G9e,1),tt,163,0,[TO,lS,l2,hS,Ly])}function C8(){C8=pe;var e,t;tU=(Qx(),t=new sF,t),nU=(e=new Vee,e)}function AZe(e){var t;return e.c||(t=e.r,we(t,88)&&(e.c=u(t,26))),e.c}function Nnn(e){return e.e=3,e.d=e.Yb(),e.e!=2?(e.e=0,!0):!1}function Mre(e){var t,n,r;return t=e&ml,n=e>>22&ml,r=e<0?V0:0,fu(t,n,r)}function Pnn(e){var t,n,r,s;for(n=e,r=0,s=n.length;r0?Art(e,t):Xot(e,-t)}function Wwe(e,t){return t==0||e.e==0?e:t>0?Xot(e,t):Art(e,-t)}function Pr(e){if(Vr(e))return e.c=e.a,e.a.Pb();throw J(new xc)}function MZe(e){var t,n;return t=e.c.i,n=e.d.i,t.k==(zn(),Ls)&&n.k==Ls}function Dre(e){var t;return t=new Iv,Ho(t,e),Ye(t,(pt(),Fo),null),t}function Ire(e,t,n){var r;return r=e.Yg(t),r>=0?e._g(r,n,!0):tw(e,t,n)}function Kwe(e,t,n,r){var s;for(s=0;st)throw J(new Do(M4e(e,t,"index")));return e}function Ore(e,t,n,r){var s;return s=Me(Lr,Jr,25,t,15,1),Khn(s,e,t,n,r),s}function Rnn(e,t){var n;n=e.q.getHours()+(t/60|0),e.q.setMinutes(t),lC(e,n)}function Fnn(e,t){return b.Math.min(Hp(t.a,e.d.d.c),Hp(t.b,e.d.d.c))}function z6(e,t){return fa(t)?t==null?W4e(e.f,null):Vtt(e.g,t):W4e(e.f,t)}function N1(e){this.c=e,this.a=new C(this.c.a),this.b=new C(this.c.b)}function k$(){this.e=new st,this.c=new st,this.d=new st,this.b=new st}function PZe(){this.g=new fpe,this.b=new fpe,this.a=new st,this.k=new st}function BZe(e,t,n){this.a=e,this.c=t,this.d=n,it(t.e,this),it(n.b,this)}function RZe(e,t){Zqe.call(this,t.rd(),t.qd()&-6),Sn(e),this.a=e,this.b=t}function FZe(e,t){Jqe.call(this,t.rd(),t.qd()&-6),Sn(e),this.a=e,this.b=t}function tme(e,t){Hte.call(this,t.rd(),t.qd()&-6),Sn(e),this.a=e,this.b=t}function x$(e,t,n){this.a=e,this.b=t,this.c=n,it(e.t,this),it(t.i,this)}function E$(){this.b=new as,this.a=new as,this.b=new as,this.a=new as}function T$(){T$=pe,NS=new Zi("org.eclipse.elk.labels.labelManager")}function jZe(){jZe=pe,e9e=new zs("separateLayerConnections",(cH(),rle))}function Jf(){Jf=pe,jy=new E2e("REGULAR",0),d2=new E2e("CRITICAL",1)}function uD(){uD=pe,dhe=new m2e("STACKED",0),DO=new m2e("SEQUENCED",1)}function lD(){lD=pe,Hhe=new L2e("FIXED",0),CV=new L2e("CENTER_NODE",1)}function jnn(e,t){var n;return n=Gwn(e,t),e.b=new Z$(n.c.length),twn(e,n)}function $nn(e,t,n){var r;return++e.e,--e.f,r=u(e.d[t].$c(n),133),r.dd()}function $Ze(e){var t;return e.a||(t=e.r,we(t,148)&&(e.a=u(t,148))),e.a}function nme(e){if(e.a){if(e.e)return nme(e.e)}else return e;return null}function Hnn(e,t){return e.pt.p?-1:0}function _$(e,t){return Sn(t),e.c=0,"Initial capacity must not be negative")}function GZe(){GZe=pe,ogt=Qr((n1(),ie(re(Ey,1),tt,232,0,[pc,lu,bc])))}function qZe(){qZe=pe,ugt=Qr((al(),ie(re(cgt,1),tt,461,0,[Nd,a2,Af])))}function VZe(){VZe=pe,hgt=Qr((Lu(),ie(re(lgt,1),tt,462,0,[u1,o2,Lf])))}function UZe(){UZe=pe,X0t=Qr((F1(),ie(re(yl,1),tt,132,0,[g7e,Ql,xy])))}function WZe(){WZe=pe,Cpt=Qr((L_(),ie(re(cEe,1),tt,379,0,[que,Gue,Vue])))}function KZe(){KZe=pe,Hpt=Qr((Uv(),ie(re(fEe,1),tt,423,0,[N4,hEe,Xue])))}function YZe(){YZe=pe,y2t=Qr((V6(),ie(re(c9e,1),tt,314,0,[Ek,vO,o9e])))}function XZe(){XZe=pe,k2t=Qr((V$(),ie(re(l9e,1),tt,337,0,[u9e,Aq,ple])))}function QZe(){QZe=pe,_2t=Qr((sb(),ie(re(T2t,1),tt,450,0,[wle,aE,F4])))}function ZZe(){ZZe=pe,b2t=Qr((qv(),ie(re(sle,1),tt,361,0,[mw,u2,ww])))}function JZe(){JZe=pe,O2t=Qr((P0(),ie(re(I2t,1),tt,303,0,[mO,$4,Tk])))}function eJe(){eJe=pe,D2t=Qr((q8(),ie(re(Ale,1),tt,292,0,[Cle,Sle,wO])))}function tJe(){tJe=pe,Qvt=Qr((j_(),ie(re(h_e,1),tt,378,0,[ihe,l_e,iV])))}function nJe(){nJe=pe,swt=Qr((iH(),ie(re(T_e,1),tt,375,0,[x_e,fhe,E_e])))}function rJe(){rJe=pe,twt=Qr((R0(),ie(re(y_e,1),tt,339,0,[f2,m_e,uhe])))}function iJe(){iJe=pe,iwt=Qr((vo(),ie(re(rwt,1),tt,452,0,[yS,ul,hu])))}function sJe(){sJe=pe,uwt=Qr((uH(),ie(re(D_e,1),tt,377,0,[bhe,wE,Fy])))}function aJe(){aJe=pe,owt=Qr((Q8(),ie(re(S_e,1),tt,336,0,[ghe,C_e,kS])))}function oJe(){oJe=pe,cwt=Qr((nH(),ie(re(M_e,1),tt,338,0,[L_e,phe,A_e])))}function cJe(){cJe=pe,xwt=Qr((Gv(),ie(re(kwt,1),tt,454,0,[IO,xS,cV])))}function uJe(){uJe=pe,Lmt=Qr((yH(),ie(re(Amt,1),tt,442,0,[Dhe,Lhe,Mhe])))}function lJe(){lJe=pe,Dmt=Qr((RD(),ie(re(tCe,1),tt,380,0,[yV,J_e,eCe])))}function hJe(){hJe=pe,Kmt=Qr((mH(),ie(re(mCe,1),tt,381,0,[wCe,Rhe,vCe])))}function fJe(){fJe=pe,Wmt=Qr((rH(),ie(re(pCe,1),tt,293,0,[Bhe,gCe,dCe])))}function dJe(){dJe=pe,pyt=Qr((GD(),ie(re(Fhe,1),tt,437,0,[EV,TV,_V])))}function gJe(){gJe=pe,w3t=Qr((F0(),ie(re(cAe,1),tt,334,0,[FV,Wg,jS])))}function pJe(){pJe=pe,g3t=Qr((P1(),ie(re(XSe,1),tt,272,0,[EE,zy,TE])))}function Knn(){return wa(),ie(re(hAe,1),tt,98,0,[w2,X1,CE,$b,p0,tu])}function J2(e,t){return!e.o&&(e.o=new Nl((cu(),k2),Dw,e,0)),qie(e.o,t)}function Ynn(e){return!e.g&&(e.g=new kx),!e.g.d&&(e.g.d=new N$e(e)),e.g.d}function Xnn(e){return!e.g&&(e.g=new kx),!e.g.a&&(e.g.a=new P$e(e)),e.g.a}function Qnn(e){return!e.g&&(e.g=new kx),!e.g.b&&(e.g.b=new O$e(e)),e.g.b}function hD(e){return!e.g&&(e.g=new kx),!e.g.c&&(e.g.c=new B$e(e)),e.g.c}function Znn(e,t,n){var r,s;for(s=new G8(t,e),r=0;rn||t=0?e._g(n,!0,!0):tw(e,t,!0)}function prn(e,t){return Fs(Ue(ft(K(e,(et(),Ew)))),Ue(ft(K(t,Ew))))}function xJe(){xJe=pe,Tmt=Qv(Qv(AF(new Xs,(a7(),_S)),(nC(),dV)),mhe)}function brn(e,t,n){var r;return r=gnt(e,t,n),e.b=new Z$(r.c.length),w5e(e,r)}function vrn(e){if(e.b<=0)throw J(new xc);return--e.b,e.a-=e.c.c,ct(e.a)}function wrn(e){var t;if(!e.a)throw J(new CYe);return t=e.a,e.a=us(e.a),t}function mrn(e){for(;!e.a;)if(!lWe(e.c,new Rt(e)))return!1;return!0}function q6(e){var t;return Nr(e),we(e,198)?(t=u(e,198),t):new iee(e)}function yrn(e){A$(),u(e.We((bi(),Hy)),174).Fc((ol(),JO)),e.Ye(cfe,null)}function A$(){A$=pe,$yt=new vZ,zyt=new wZ,Hyt=ian((bi(),cfe),$yt,p2,zyt)}function L$(){L$=pe,Q_e=new A2e("LEAF_NUMBER",0),Ihe=new A2e("NODE_SIZE",1)}function krn(e,t,n){e.a=t,e.c=n,e.b.a.$b(),Rh(e.d),e.e.a.c=Me(Yn,yt,1,0,5,1)}function $re(e){e.a=Me(Lr,Jr,25,e.b+1,15,1),e.c=Me(Lr,Jr,25,e.b,15,1),e.d=0}function xrn(e,t){e.a.ue(t.d,e.b)>0&&(it(e.c,new vve(t.c,t.d,e.d)),e.b=t.d)}function fme(e,t){if(e.g==null||t>=e.i)throw J(new zte(t,e.i));return e.g[t]}function EJe(e,t,n){if(K8(e,n),n!=null&&!e.wj(n))throw J(new zee);return n}function TJe(e){var t;if(e.Ek())for(t=e.i-1;t>=0;--t)Te(e,t);return Rwe(e)}function Ern(e){var t,n;if(!e.b)return null;for(n=e.b;t=n.a[0];)n=t;return n}function Trn(e,t){var n,r;return UQe(t),n=(r=e.slice(0,t),gme(r,e)),n.length=t,n}function L8(e,t,n,r){var s;r=(q3(),r||r7e),s=e.slice(t,n),D4e(s,e,t,n,-t,r)}function ph(e,t,n,r,s){return t<0?tw(e,n,r):u(n,66).Nj().Pj(e,e.yh(),t,r,s)}function _rn(e){return we(e,172)?""+u(e,172).a:e==null?null:Qo(e)}function Crn(e){return we(e,172)?""+u(e,172).a:e==null?null:Qo(e)}function _Je(e,t){if(t.a)throw J(new tc(Sht));Gs(e.a,t),t.a=e,!e.j&&(e.j=t)}function dme(e,t){Hte.call(this,t.rd(),t.qd()&-16449),Sn(e),this.a=e,this.c=t}function CJe(e,t){var n,r;return r=t/e.c.Hd().gc()|0,n=t%e.c.Hd().gc(),G6(e,r,n)}function al(){al=pe,Nd=new pte(uk,0),a2=new pte(D7,1),Af=new pte(lk,2)}function M$(){M$=pe,_ue=new IF("All",0),l7e=new kVe,h7e=new OVe,f7e=new xVe}function SJe(){SJe=pe,q0t=Qr((M$(),ie(re(GG,1),tt,297,0,[_ue,l7e,h7e,f7e])))}function AJe(){AJe=pe,Ppt=Qr((V8(),ie(re(Npt,1),tt,405,0,[vw,_y,Ty,O4])))}function LJe(){LJe=pe,Bgt=Qr((Vv(),ie(re(Pgt,1),tt,406,0,[sO,iO,Oue,Nue])))}function MJe(){MJe=pe,Fgt=Qr((Z6(),ie(re(Rgt,1),tt,323,0,[oO,aO,cO,uO])))}function DJe(){DJe=pe,Hgt=Qr((Y_(),ie(re($gt,1),tt,394,0,[lO,KG,YG,hO])))}function IJe(){IJe=pe,smt=Qr((a7(),ie(re(B_e,1),tt,393,0,[fV,_S,NO,CS])))}function OJe(){OJe=pe,e2t=Qr((cH(),ie(re(Jpt,1),tt,360,0,[rle,kq,xq,bO])))}function NJe(){NJe=pe,Umt=Qr((jH(),ie(re(fCe,1),tt,340,0,[Phe,lCe,hCe,uCe])))}function PJe(){PJe=pe,u2t=Qr((R1(),ie(re(c2t,1),tt,411,0,[xk,tE,nE,ile])))}function BJe(){BJe=pe,Zvt=Qr((Zm(),ie(re(ahe,1),tt,197,0,[sV,she,K4,W4])))}function RJe(){RJe=pe,P3t=Qr((Pl(),ie(re(N3t,1),tt,396,0,[nh,mAe,wAe,yAe])))}function FJe(){FJe=pe,y3t=Qr((Ul(),ie(re(m3t,1),tt,285,0,[QO,d0,b2,XO])))}function jJe(){jJe=pe,p3t=Qr(($0(),ie(re(ffe,1),tt,218,0,[hfe,YO,_E,jk])))}function $Je(){$Je=pe,I3t=Qr((EH(),ie(re(vAe,1),tt,311,0,[pfe,gAe,bAe,pAe])))}function HJe(){HJe=pe,M3t=Qr((Bl(),ie(re(qS,1),tt,374,0,[tN,Hb,eN,Gy])))}function zJe(){zJe=pe,pz(),tLe=gs,R4t=Ds,nLe=new C3(gs),F4t=new C3(Ds)}function pD(){pD=pe,b9e=new b2e(U0,0),Dq=new b2e("IMPROVE_STRAIGHTNESS",1)}function Srn(e,t){return h8(),it(e,new xa(t,ct(t.e.c.length+t.g.c.length)))}function Arn(e,t){return h8(),it(e,new xa(t,ct(t.e.c.length+t.g.c.length)))}function gme(e,t){return yD(t)!=10&&ie(pl(t),t.hm,t.__elementTypeId$,yD(t),e),e}function Au(e,t){var n;return n=Yo(e,t,0),n==-1?!1:(Eg(e,n),!0)}function GJe(e,t){var n;return n=u(z6(e.e,t),387),n?(yve(n),n.e):null}function M8(e){var t;return Ko(e)&&(t=0-e,!isNaN(t))?t:Gp(U8(e))}function Yo(e,t,n){for(;n=0?NH(e,n,!0,!0):tw(e,t,!0)}function mme(e,t){IT();var n,r;return n=j6(e),r=j6(t),!!n&&!!r&&!oit(n.k,r.k)}function Drn(e,t){Du(e,t==null||wj((Sn(t),t))||isNaN((Sn(t),t))?0:(Sn(t),t))}function Irn(e,t){Iu(e,t==null||wj((Sn(t),t))||isNaN((Sn(t),t))?0:(Sn(t),t))}function Orn(e,t){zv(e,t==null||wj((Sn(t),t))||isNaN((Sn(t),t))?0:(Sn(t),t))}function Nrn(e,t){Hv(e,t==null||wj((Sn(t),t))||isNaN((Sn(t),t))?0:(Sn(t),t))}function KJe(e){(this.q?this.q:(hn(),hn(),l0)).Ac(e.q?e.q:(hn(),hn(),l0))}function Prn(e,t){return we(t,99)&&u(t,18).Bb&so?new Gte(t,e):new G8(t,e)}function Brn(e,t){return we(t,99)&&u(t,18).Bb&so?new Gte(t,e):new G8(t,e)}function YJe(e,t){j7e=new rs,jgt=t,ZC=e,u(ZC.b,65),sme(ZC,j7e,null),qut(ZC)}function Vre(e,t,n){var r;return r=e.g[t],n_(e,t,e.oi(t,n)),e.gi(t,n,r),e.ci(),r}function N$(e,t){var n;return n=e.Xc(t),n>=0?(e.$c(n),!0):!1}function Ure(e){var t;return e.d!=e.r&&(t=$h(e),e.e=!!t&&t.Cj()==Idt,e.d=t),e.e}function Wre(e,t){var n;for(Nr(e),Nr(t),n=!1;t.Ob();)n=n|e.Fc(t.Pb());return n}function Fv(e,t){var n;return n=u(er(e.e,t),387),n?(HVe(e,n),n.e):null}function XJe(e){var t,n;return t=e/60|0,n=e%60,n==0?""+t:""+t+":"+(""+n)}function ic(e,t){var n,r;return ub(e),r=new tme(t,e.a),n=new dWe(r),new vn(e,n)}function Gm(e,t){var n=e.a[t],r=(fie(),yue)[typeof n];return r?r(n):Eye(typeof n)}function Rrn(e){switch(e.g){case 0:return Ei;case 1:return-1;default:return 0}}function Frn(e){return $3e(e,(D8(),F8e))<0?-eKt(U8(e)):e.l+e.m*ck+e.h*vb}function yD(e){return e.__elementTypeCategory$==null?10:e.__elementTypeCategory$}function Kre(e){var t;return t=e.b.c.length==0?null:St(e.b,0),t!=null&&iie(e,0),t}function QJe(e,t){for(;t[0]=0;)++t[0]}function kD(e,t){this.e=t,this.a=Utt(e),this.a<54?this.f=Bv(e):this.c=WD(e)}function ZJe(e,t,n,r){yi(),cv.call(this,26),this.c=e,this.a=t,this.d=n,this.b=r}function e0(e,t,n){var r,s;for(r=10,s=0;se.a[r]&&(r=n);return r}function qrn(e,t){var n;return n=Kv(e.e.c,t.e.c),n==0?Fs(e.e.d,t.e.d):n}function W3(e,t){return t.e==0||e.e==0?K7:(d7(),Yse(e,t))}function Vrn(e,t){if(!e)throw J(new Ln(Kgn("Enum constant undefined: %s",t)))}function M_(){M_=pe,Fpt=new ev,jpt=new cd,Bpt=new fx,Rpt=new oh,$pt=new QK}function P$(){P$=pe,m7e=new l2e("BY_SIZE",0),Lue=new l2e("BY_SIZE_AND_SHAPE",1)}function B$(){B$=pe,$ue=new h2e("EADES",0),ZG=new h2e("FRUCHTERMAN_REINGOLD",1)}function ED(){ED=pe,Lq=new p2e("READING_DIRECTION",0),d9e=new p2e("ROTATION",1)}function eet(){eet=pe,x2t=Qr((db(),ie(re(f9e,1),tt,335,0,[ble,h9e,vle,sS,iS])))}function tet(){tet=pe,Jvt=Qr((X_(),ie(re(d_e,1),tt,315,0,[f_e,ohe,che,wS,mS])))}function net(){net=pe,h2t=Qr((c4(),ie(re(l2t,1),tt,363,0,[Tq,Cq,Sq,_q,Eq])))}function ret(){ret=pe,P2t=Qr((mh(),ie(re(G9e,1),tt,163,0,[TO,lS,l2,hS,Ly])))}function iet(){iet=pe,yyt=Qr((rI(),ie(re(RCe,1),tt,316,0,[NCe,zhe,BCe,Ghe,PCe])))}function set(){set=pe,Gyt=Qr((i1(),ie(re(Ug,1),tt,175,0,[Fn,ua,Fd,Bb,Vg])))}function aet(){aet=pe,gyt=Qr((v7(),ie(re(dyt,1),tt,355,0,[X4,Nk,IS,DS,OS])))}function oet(){oet=pe,Mpt=Qr((ro(),ie(re(uEe,1),tt,356,0,[Pd,c2,bu,Zc,Go])))}function cet(){cet=pe,d3t=Qr((wo(),ie(re(RS,1),tt,103,0,[f0,Df,Xh,Y0,X0])))}function uet(){uet=pe,x3t=Qr((n4(),ie(re(HS,1),tt,249,0,[v2,ZO,uAe,$S,lAe])))}function het(){het=pe,_3t=Qr((ht(),ie(re(ao,1),Dc,61,0,[uc,An,$n,xr,Dn])))}function Yre(e,t){var n;return n=u(er(e.a,t),134),n||(n=new b3,Si(e.a,t,n)),n}function fet(e){var t;return t=u(K(e,(et(),yw)),305),t?t.a==e:!1}function det(e){var t;return t=u(K(e,(et(),yw)),305),t?t.i==e:!1}function get(e,t){return Sn(t),$ve(e),e.d.Ob()?(t.td(e.d.Pb()),!0):!1}function R$(e){return Mc(e,Ei)>0?Ei:Mc(e,$a)<0?$a:Or(e)}function qm(e){return e<3?(ql(e,uht),e+1):e=0&&t=-.01&&e.a<=z1&&(e.a=0),e.b>=-.01&&e.b<=z1&&(e.b=0),e}function bet(e,t){return t==(gne(),gne(),H0t)?e.toLocaleLowerCase():e.toLowerCase()}function kme(e){return(e.i&2?"interface ":e.i&1?"":"class ")+(S0(e),e.o)}function Bo(e){var t,n;n=(t=new Uee,t),Br((!e.q&&(e.q=new at(nf,e,11,10)),e.q),n)}function Urn(e,t){var n;return n=t>0?t-1:t,hze(aUt(zet(mve(new Ux,n),e.n),e.j),e.k)}function Wrn(e,t,n,r){var s;e.j=-1,q4e(e,T4e(e,t,n),(ho(),s=u(t,66).Mj(),s.Ok(r)))}function vet(e){this.g=e,this.f=new st,this.a=b.Math.min(this.g.c.c,this.g.d.c)}function wet(e){this.b=new st,this.a=new st,this.c=new st,this.d=new st,this.e=e}function met(e,t){this.a=new Mr,this.e=new Mr,this.b=(j_(),iV),this.c=e,this.b=t}function yet(e,t,n){bj.call(this),xme(this),this.a=e,this.c=n,this.b=t.d,this.f=t.e}function ket(e){this.d=e,this.c=e.c.vc().Kc(),this.b=null,this.a=null,this.e=(cF(),bue)}function jv(e){if(e<0)throw J(new Ln("Illegal Capacity: "+e));this.g=this.ri(e)}function Krn(e,t){if(0>e||e>t)throw J(new Ppe("fromIndex: 0, toIndex: "+e+E6e+t))}function Yrn(e){var t;if(e.a==e.b.a)throw J(new xc);return t=e.a,e.c=t,e.a=e.a.e,t}function F$(e){var t;Am(!!e.c),t=e.c.a,bh(e.d,e.c),e.b==e.c?e.b=t:--e.a,e.c=null}function j$(e,t){var n;return ub(e),n=new zYe(e,e.a.rd(),e.a.qd()|4,t),new vn(e,n)}function Xrn(e,t){var n,r;return n=u(Ym(e.d,t),14),n?(r=t,e.e.pc(r,n)):null}function $$(e,t){var n,r;for(r=e.Kc();r.Ob();)n=u(r.Pb(),70),Ye(n,(et(),Ak),t)}function Qrn(e){var t;return t=Ue(ft(K(e,(pt(),Hg)))),t<0&&(t=0,Ye(e,Hg,t)),t}function Zrn(e,t,n){var r;r=b.Math.max(0,e.b/2-.5),Z_(n,r,1),it(t,new UGe(n,r))}function Jrn(e,t,n){var r;return r=e.a.e[u(t.a,10).p]-e.a.e[u(n.a,10).p],_s(WM(r))}function xet(e,t,n,r,s,o){var h;h=Dre(r),Va(h,s),ba(h,o),sn(e.a,r,new mj(h,t,n.f))}function Eet(e,t){var n;if(n=dI(e.Tg(),t),!n)throw J(new Ln(i2+t+Oce));return n}function Vm(e,t){var n;for(n=e;us(n);)if(n=us(n),n==t)return!0;return!1}function ein(e,t){var n,r,s;for(r=t.a.cd(),n=u(t.a.dd(),14).gc(),s=0;s0&&(e.a/=t,e.b/=t),e}function Gl(e){var t;return e.w?e.w:(t=utn(e),t&&!t.kh()&&(e.w=t),t)}function cin(e){var t;return e==null?null:(t=u(e,190),ufn(t,t.length))}function Te(e,t){if(e.g==null||t>=e.i)throw J(new zte(t,e.i));return e.li(t,e.g[t])}function uin(e){var t,n;for(t=e.a.d.j,n=e.c.d.j;t!=n;)Tf(e.b,t),t=vH(t);Tf(e.b,t)}function lin(e){var t;for(t=0;t=14&&t<=16))),e}function Aet(e,t,n){var r=function(){return e.apply(r,arguments)};return t.apply(r,n),r}function Let(e,t,n){var r,s;r=t;do s=Ue(e.p[r.p])+n,e.p[r.p]=s,r=e.a[r.p];while(r!=t)}function I8(e,t){var n,r;r=e.a,n=qan(e,t,null),r!=t&&!e.e&&(n=E7(e,t,n)),n&&n.Fi()}function Eme(e,t){return S1(),Ef(Jp),b.Math.abs(e-t)<=Jp||e==t||isNaN(e)&&isNaN(t)}function Tme(e,t){return S1(),Ef(Jp),b.Math.abs(e-t)<=Jp||e==t||isNaN(e)&&isNaN(t)}function din(e,t){return Xp(),Tu(e.b.c.length-e.e.c.length,t.b.c.length-t.e.c.length)}function K3(e,t){return hUt(O_(e,t,Or(ja(s0,Qd(Or(ja(t==null?0:Xi(t),a0)),15)))))}function Met(){Met=pe,Vpt=Qr((zn(),ie(re(Zue,1),tt,267,0,[Hs,ca,Ls,Jc,Rl,U1])))}function Det(){Det=pe,Zyt=Qr((ty(),ie(re(Jhe,1),tt,291,0,[Zhe,qO,GO,Qhe,HO,zO])))}function Iet(){Iet=pe,Uyt=Qr((t0(),ie(re(aSe,1),tt,248,0,[Yhe,jO,$O,DV,LV,MV])))}function Oet(){Oet=pe,w2t=Qr((ek(),ie(re(sE,1),tt,227,0,[iE,rS,rE,Cy,R4,B4])))}function Net(){Net=pe,L2t=Qr((h7(),ie(re(A9e,1),tt,275,0,[aS,T9e,S9e,C9e,_9e,E9e])))}function Pet(){Pet=pe,A2t=Qr((tI(),ie(re(x9e,1),tt,274,0,[Iq,m9e,k9e,w9e,y9e,Tle])))}function Bet(){Bet=pe,Xvt=Qr((WH(),ie(re(u_e,1),tt,313,0,[rhe,o_e,nhe,a_e,c_e,rV])))}function Ret(){Ret=pe,C2t=Qr((QH(),ie(re(p9e,1),tt,276,0,[yle,mle,xle,kle,Ele,Mq])))}function Fet(){Fet=pe,omt=Qr((nC(),ie(re(amt,1),tt,327,0,[dV,mhe,khe,yhe,xhe,whe])))}function jet(){jet=pe,T3t=Qr((ol(),ie(re(jV,1),tt,273,0,[m2,Z0,JO,GS,zS,$k])))}function $et(){$et=pe,b3t=Qr((YH(),ie(re(nAe,1),tt,312,0,[dfe,JSe,tAe,QSe,eAe,ZSe])))}function gin(){return sy(),ie(re(xo,1),tt,93,0,[If,Q0,Of,Pf,g0,Zh,Jl,Nf,Qh])}function z$(e,t){var n;n=e.a,e.a=t,e.Db&4&&!(e.Db&1)&&_i(e,new Hm(e,0,n,e.a))}function G$(e,t){var n;n=e.b,e.b=t,e.Db&4&&!(e.Db&1)&&_i(e,new Hm(e,1,n,e.b))}function O8(e,t){var n;n=e.b,e.b=t,e.Db&4&&!(e.Db&1)&&_i(e,new Hm(e,3,n,e.b))}function Hv(e,t){var n;n=e.f,e.f=t,e.Db&4&&!(e.Db&1)&&_i(e,new Hm(e,3,n,e.f))}function zv(e,t){var n;n=e.g,e.g=t,e.Db&4&&!(e.Db&1)&&_i(e,new Hm(e,4,n,e.g))}function Du(e,t){var n;n=e.i,e.i=t,e.Db&4&&!(e.Db&1)&&_i(e,new Hm(e,5,n,e.i))}function Iu(e,t){var n;n=e.j,e.j=t,e.Db&4&&!(e.Db&1)&&_i(e,new Hm(e,6,n,e.j))}function N8(e,t){var n;n=e.j,e.j=t,e.Db&4&&!(e.Db&1)&&_i(e,new Hm(e,1,n,e.j))}function P8(e,t){var n;n=e.c,e.c=t,e.Db&4&&!(e.Db&1)&&_i(e,new Hm(e,4,n,e.c))}function B8(e,t){var n;n=e.k,e.k=t,e.Db&4&&!(e.Db&1)&&_i(e,new Hm(e,2,n,e.k))}function Qre(e,t){var n;n=e.d,e.d=t,e.Db&4&&!(e.Db&1)&&_i(e,new Tre(e,2,n,e.d))}function Cg(e,t){var n;n=e.s,e.s=t,e.Db&4&&!(e.Db&1)&&_i(e,new Tre(e,4,n,e.s))}function Wm(e,t){var n;n=e.t,e.t=t,e.Db&4&&!(e.Db&1)&&_i(e,new Tre(e,5,n,e.t))}function R8(e,t){var n;n=e.F,e.F=t,e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,5,n,t))}function TD(e,t){var n;return n=u(er((LF(),QV),e),55),n?n.xj(t):Me(Yn,yt,1,t,5,1)}function B0(e,t){var n,r;return n=t in e.a,n&&(r=M0(e,t).he(),r)?r.a:null}function pin(e,t){var n,r,s;return n=(r=(pv(),s=new j9,s),t&&f5e(r,t),r),Ome(n,e),n}function Het(e,t,n){if(K8(e,n),!e.Bk()&&n!=null&&!e.wj(n))throw J(new zee);return n}function zet(e,t){return e.n=t,e.n?(e.f=new st,e.e=new st):(e.f=null,e.e=null),e}function Gr(e,t,n,r,s,o){var h;return h=Gne(e,t),qet(n,h),h.i=s?8:0,h.f=r,h.e=s,h.g=o,h}function _me(e,t,n,r,s){this.d=t,this.k=r,this.f=s,this.o=-1,this.p=1,this.c=e,this.a=n}function Cme(e,t,n,r,s){this.d=t,this.k=r,this.f=s,this.o=-1,this.p=2,this.c=e,this.a=n}function Sme(e,t,n,r,s){this.d=t,this.k=r,this.f=s,this.o=-1,this.p=6,this.c=e,this.a=n}function Ame(e,t,n,r,s){this.d=t,this.k=r,this.f=s,this.o=-1,this.p=7,this.c=e,this.a=n}function Lme(e,t,n,r,s){this.d=t,this.j=r,this.e=s,this.o=-1,this.p=4,this.c=e,this.a=n}function Get(e,t){var n,r,s,o;for(r=t,s=0,o=r.length;s=0),pcn(e.d,e.c)<0&&(e.a=e.a-1&e.d.a.length-1,e.b=e.d.c),e.c=-1}function Mme(e){return e.a<54?e.f<0?-1:e.f>0?1:0:(!e.c&&(e.c=FD(e.f)),e.c).e}function Ef(e){if(!(e>=0))throw J(new Ln("tolerance ("+e+") must be >= 0"));return e}function F8(){return Whe||(Whe=new Ict,J3(Whe,ie(re(I4,1),yt,130,0,[new wp]))),Whe}function vo(){vo=pe,yS=new Ste(EC,0),ul=new Ste("INPUT",1),hu=new Ste("OUTPUT",2)}function V$(){V$=pe,u9e=new kte("ARD",0),Aq=new kte("MSD",1),ple=new kte("MANUAL",2)}function Gv(){Gv=pe,IO=new Ite("BARYCENTER",0),xS=new Ite(bft,1),cV=new Ite(vft,2)}function _D(e,t){var n;if(n=e.gc(),t<0||t>n)throw J(new Im(t,n));return new Kbe(e,t)}function Wet(e,t){var n;return we(t,42)?e.c.Mc(t):(n=qie(e,t),CH(e,t),n)}function Co(e,t,n){return cb(e,t),au(e,n),Cg(e,0),Wm(e,1),Mg(e,!0),Lg(e,!0),e}function ql(e,t){if(e<0)throw J(new Ln(t+" cannot be negative but was: "+e));return e}function Ket(e,t){var n,r;for(n=0,r=e.gc();n0?u(St(n.a,r-1),10):null}function I_(e,t){var n;n=e.k,e.k=t,e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,2,n,e.k))}function W$(e,t){var n;n=e.f,e.f=t,e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,8,n,e.f))}function K$(e,t){var n;n=e.i,e.i=t,e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,7,n,e.i))}function Ome(e,t){var n;n=e.a,e.a=t,e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,8,n,e.a))}function Nme(e,t){var n;n=e.b,e.b=t,e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,0,n,e.b))}function Pme(e,t){var n;n=e.b,e.b=t,e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,0,n,e.b))}function Bme(e,t){var n;n=e.c,e.c=t,e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,1,n,e.c))}function Rme(e,t){var n;n=e.c,e.c=t,e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,1,n,e.c))}function Jre(e,t){var n;n=e.c,e.c=t,e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,4,n,e.c))}function Fme(e,t){var n;n=e.d,e.d=t,e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,1,n,e.d))}function eie(e,t){var n;n=e.D,e.D=t,e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,2,n,e.D))}function tie(e,t){e.r>0&&e.c0&&e.g!=0&&tie(e.i,t/e.r*e.i.d))}function Tin(e,t,n){var r;e.b=t,e.a=n,r=(e.a&512)==512?new PHe:new qL,e.c=$pn(r,e.b,e.a)}function rtt(e,t){return G0(e.e,t)?(ho(),Ure(t)?new Cj(t,e):new DM(t,e)):new Wqe(t,e)}function Y$(e,t){return lUt(N_(e.a,t,Or(ja(s0,Qd(Or(ja(t==null?0:Xi(t),a0)),15)))))}function _in(e,t,n){return zm(e,new ot(t),new Zs,new ut(n),ie(re(yl,1),tt,132,0,[]))}function Cin(e){var t,n;return 0>e?new Xpe:(t=e+1,n=new _Ze(t,e),new Lbe(null,n))}function Sin(e,t){hn();var n;return n=new w6(1),fa(e)?Oo(n,e,t):gu(n.f,e,t),new H(n)}function Ain(e,t){var n,r;return n=e.o+e.p,r=t.o+t.p,nt?(t<<=1,t>0?t:wC):t}function nie(e){switch(abe(e.e!=3),e.e){case 2:return!1;case 0:return!0}return Nnn(e)}function stt(e,t){var n;return we(t,8)?(n=u(t,8),e.a==n.a&&e.b==n.b):!1}function rie(e,t,n){var r,s,o;return o=t>>5,s=t&31,r=qs(Nm(e.n[n][o],Or(A0(s,1))),3),r}function Min(e,t){var n,r;for(r=t.vc().Kc();r.Ob();)n=u(r.Pb(),42),qH(e,n.cd(),n.dd())}function Din(e,t){var n;n=new rs,u(t.b,65),u(t.b,65),u(t.b,65),Mu(t.a,new sve(e,n,t))}function jme(e,t){var n;n=e.b,e.b=t,e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,21,n,e.b))}function $me(e,t){var n;n=e.d,e.d=t,e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,11,n,e.d))}function X$(e,t){var n;n=e.j,e.j=t,e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,13,n,e.j))}function att(e,t,n){var r,s,o;for(o=e.a.length-1,s=e.b,r=0;r>>31;r!=0&&(e[n]=r)}function Hin(e,t){hn();var n,r;for(r=new st,n=0;n0&&(this.g=this.ri(this.i+(this.i/8|0)+1),e.Qc(this.g))}function ds(e,t){xj.call(this,b4t,e,t),this.b=this,this.a=pu(e.Tg(),gn(this.e.Tg(),this.c))}function P_(e,t){var n,r;for(Sn(t),r=t.vc().Kc();r.Ob();)n=u(r.Pb(),42),e.zc(n.cd(),n.dd())}function Qin(e,t,n){var r;for(r=n.Kc();r.Ob();)if(!v$(e,t,r.Pb()))return!1;return!0}function Zin(e,t,n,r,s){var o;return n&&(o=Ji(t.Tg(),e.c),s=n.gh(t,-1-(o==-1?r:o),null,s)),s}function Jin(e,t,n,r,s){var o;return n&&(o=Ji(t.Tg(),e.c),s=n.ih(t,-1-(o==-1?r:o),null,s)),s}function _tt(e){var t;if(e.b==-2){if(e.e==0)t=-1;else for(t=0;e.a[t]==0;t++);e.b=t}return e.b}function Ctt(e){switch(e.g){case 2:return ht(),Dn;case 4:return ht(),$n;default:return e}}function Stt(e){switch(e.g){case 1:return ht(),xr;case 3:return ht(),An;default:return e}}function esn(e){var t,n,r;return e.j==(ht(),An)&&(t=not(e),n=Vu(t,$n),r=Vu(t,Dn),r||r&&n)}function tsn(e){var t,n;return t=u(e.e&&e.e(),9),n=u(Qve(t,t.length),9),new hh(t,n,t.length)}function nsn(e,t){kr(t,pft,1),Uye(xUt(new nr((DT(),new Qne(e,!1,!1,new qP))))),ur(t)}function CD(e,t){return Mn(),fa(e)?Jwe(e,Hr(t)):Sm(e)?Ine(e,ft(t)):Cm(e)?aZt(e,Mt(t)):e.wd(t)}function Ume(e,t){t.q=e,e.d=b.Math.max(e.d,t.r),e.b+=t.d+(e.a.c.length==0?0:e.c),it(e.a,t)}function $8(e,t){var n,r,s,o;return s=e.c,n=e.c+e.b,o=e.d,r=e.d+e.a,t.a>s&&t.ao&&t.b1||e.Ob())return++e.a,e.g=0,t=e.i,e.Ob(),t;throw J(new xc)}function gsn(e){CVe();var t;return BGe(vhe,e)||(t=new CQ,t.a=e,Bbe(vhe,e,t)),u(_o(vhe,e),635)}function Fh(e){var t,n,r,s;return s=e,r=0,s<0&&(s+=vb,r=V0),n=_s(s/ck),t=_s(s-n*ck),fu(t,n,r)}function SD(e){var t,n,r;for(r=0,n=new m6(e.a);n.a>22),s=e.h+t.h+(r>>22),fu(n&ml,r&ml,s&V0)}function Wtt(e,t){var n,r,s;return n=e.l-t.l,r=e.m-t.m+(n>>22),s=e.h-t.h+(r>>22),fu(n&ml,r&ml,s&V0)}function DD(e){var t;return e<128?(t=(aKe(),z8e)[e],!t&&(t=z8e[e]=new YR(e)),t):new YR(e)}function ts(e){var t;return we(e,78)?e:(t=e&&e.__java$exception,t||(t=new Bnt(e),Q$e(t)),t)}function ID(e){if(we(e,186))return u(e,118);if(e)return null;throw J(new b6(z1t))}function Ktt(e,t){if(t==null)return!1;for(;e.a!=e.b;)if(Ci(t,gH(e)))return!0;return!1}function Zme(e){return e.a.Ob()?!0:e.a!=e.d?!1:(e.a=new Iwe(e.e.f),e.a.Ob())}function Rs(e,t){var n,r;return n=t.Pc(),r=n.length,r==0?!1:(hve(e.c,e.c.length,n),!0)}function Lsn(e,t,n){var r,s;for(s=t.vc().Kc();s.Ob();)r=u(s.Pb(),42),e.yc(r.cd(),r.dd(),n);return e}function Ytt(e,t){var n,r;for(r=new C(e.b);r.a=0,"Negative initial capacity"),kj(t>=0,"Non-positive load factor"),sl(this)}function die(e,t,n){return e>=128?!1:e<64?XT(qs(A0(1,e),n),0):XT(qs(A0(1,e-64),t),0)}function Fsn(e,t){return!e||!t||e==t?!1:Kv(e.b.c,t.b.c+t.b.b)<0&&Kv(t.b.c,e.b.c+e.b.b)<0}function ont(e){var t,n,r;return n=e.n,r=e.o,t=e.d,new fh(n.a-t.b,n.b-t.d,r.a+(t.b+t.c),r.b+(t.d+t.a))}function jsn(e){var t,n,r,s;for(n=e.a,r=0,s=n.length;rr)throw J(new Im(t,r));return e.hi()&&(n=xXe(e,n)),e.Vh(t,n)}function PD(e,t,n){return n==null?(!e.q&&(e.q=new Mr),z6(e.q,t)):(!e.q&&(e.q=new Mr),Si(e.q,t,n)),e}function Ye(e,t,n){return n==null?(!e.q&&(e.q=new Mr),z6(e.q,t)):(!e.q&&(e.q=new Mr),Si(e.q,t,n)),e}function cnt(e){var t,n;return n=new k$,Ho(n,e),Ye(n,(zp(),kk),e),t=new Mr,Gbn(e,n,t),pmn(e,n,t),n}function zsn(e){g4();var t,n,r;for(n=Me(na,Qe,8,2,0,1),r=0,t=0;t<2;t++)r+=.5,n[t]=Eun(r,e);return n}function unt(e,t){var n,r,s,o;for(n=!1,r=e.a[t].length,o=0;o>=1);return t}function hnt(e){var t,n;return n=uI(e.h),n==32?(t=uI(e.m),t==32?uI(e.l)+32:t+20-10):n-12}function F_(e){var t;return t=e.a[e.b],t==null?null:(cs(e.a,e.b,null),e.b=e.b+1&e.a.length-1,t)}function fnt(e){var t,n;return t=e.t-e.k[e.o.p]*e.d+e.j[e.o.p]>e.f,n=e.u+e.e[e.o.p]*e.d>e.f*e.s*e.d,t||n}function lH(e,t,n){var r,s;return r=new Rre(t,n),s=new Nt,e.b=rct(e,e.b,r,s),s.b||++e.c,e.b.b=!1,s.d}function dnt(e,t,n){var r,s,o,h;for(h=H_(t,n),o=0,s=h.Kc();s.Ob();)r=u(s.Pb(),11),Si(e.c,r,ct(o++))}function qp(e){var t,n;for(n=new C(e.a.b);n.an&&(n=e[t]);return n}function gnt(e,t,n){var r;return r=new st,p5e(e,t,r,(ht(),$n),!0,!1),p5e(e,n,r,Dn,!1,!1),r}function pie(e,t,n){var r,s,o,h;return o=null,h=t,s=Rv(h,"labels"),r=new Iqe(e,n),o=(o0n(r.a,r.b,s),s),o}function qsn(e,t,n,r){var s;return s=n5e(e,t,n,r),!s&&(s=Van(e,n,r),s&&!v4(e,t,s))?null:s}function Vsn(e,t,n,r){var s;return s=r5e(e,t,n,r),!s&&(s=Iie(e,n,r),s&&!v4(e,t,s))?null:s}function pnt(e,t){var n;for(n=0;n1||t>=0&&e.b<3)}function BD(e){var t,n,r;for(t=new Gu,r=ii(e,0);r.b!=r.d.c;)n=u(ri(r),8),c8(t,0,new Io(n));return t}function ab(e){var t,n;for(n=new C(e.a.b);n.ar?1:0}function vye(e,t){return jot(e,t)?(sn(e.b,u(K(t,(et(),Sy)),21),t),ci(e.a,t),!0):!1}function ran(e){var t,n;t=u(K(e,(et(),cl)),10),t&&(n=t.c,Au(n.a,t),n.a.c.length==0&&Au(Ya(t).b,n))}function knt(e){return V1?Me(V0t,Eht,572,0,0,1):u(j1(e.a,Me(V0t,Eht,572,e.a.c.length,0,1)),842)}function ian(e,t,n,r){return Uj(),new Qee(ie(re(Cb,1),Sz,42,0,[(cse(e,t),new vv(e,t)),(cse(n,r),new vv(n,r))]))}function Z3(e,t,n){var r,s;return s=(r=new Uee,r),Co(s,t,n),Br((!e.q&&(e.q=new at(nf,e,11,10)),e.q),s),s}function mie(e){var t,n,r,s;for(s=MUt(V3t,e),n=s.length,r=Me(mt,Qe,2,n,6,1),t=0;t=e.b.c.length||(wye(e,2*t+1),n=2*t+2,n=0&&e[r]===t[r];r--);return r<0?0:fte(qs(e[r],yo),qs(t[r],yo))?-1:1}function san(e,t){var n,r;for(r=ii(e,0);r.b!=r.d.c;)n=u(ri(r),214),n.e.length>0&&(t.td(n),n.i&&Jan(n))}function kie(e,t){var n,r;return r=u(_n(e.a,4),126),n=Me(kfe,Xce,415,t,0,1),r!=null&&Hc(r,0,n,0,r.length),n}function Ent(e,t){var n;return n=new Zse((e.f&256)!=0,e.i,e.a,e.d,(e.f&16)!=0,e.j,e.g,t),e.e!=null||(n.c=e),n}function aan(e,t){var n,r;for(r=e.Zb().Cc().Kc();r.Ob();)if(n=u(r.Pb(),14),n.Hc(t))return!0;return!1}function xie(e,t,n,r,s){var o,h;for(h=n;h<=s;h++)for(o=t;o<=r;o++)if(i4(e,o,h))return!0;return!1}function Tnt(e,t,n){var r,s,o,h;for(Sn(n),h=!1,o=e.Zc(t),s=n.Kc();s.Ob();)r=s.Pb(),o.Rb(r),h=!0;return h}function oan(e,t){var n;return e===t?!0:we(t,83)?(n=u(t,83),y4e(Cv(e),n.vc())):!1}function _nt(e,t,n){var r,s;for(s=n.Kc();s.Ob();)if(r=u(s.Pb(),42),e.re(t,r.dd()))return!0;return!1}function Cnt(e,t,n){return e.d[t.p][n.p]||(run(e,t,n),e.d[t.p][n.p]=!0,e.d[n.p][t.p]=!0),e.a[t.p][n.p]}function K8(e,t){if(!e.ai()&&t==null)throw J(new Ln("The 'no null' constraint is violated"));return t}function Y8(e,t){e.D==null&&e.B!=null&&(e.D=e.B,e.B=null),eie(e,t==null?null:(Sn(t),t)),e.C&&e.yk(null)}function can(e,t){var n;return!e||e==t||!ta(t,(et(),xw))?!1:(n=u(K(t,(et(),xw)),10),n!=e)}function Eie(e){switch(e.i){case 2:return!0;case 1:return!1;case-1:++e.c;default:return e.pl()}}function Snt(e){switch(e.i){case-2:return!0;case-1:return!1;case 1:--e.c;default:return e.ql()}}function Ant(e){pXe.call(this,"The given string does not match the expected format for individual spacings.",e)}function Pl(){Pl=pe,nh=new WF("ELK",0),mAe=new WF("JSON",1),wAe=new WF("DOT",2),yAe=new WF("SVG",3)}function RD(){RD=pe,yV=new Nte(U0,0),J_e=new Nte("RADIAL_COMPACTION",1),eCe=new Nte("WEDGE_COMPACTION",2)}function F1(){F1=pe,g7e=new dte("CONCURRENT",0),Ql=new dte("IDENTITY_FINISH",1),xy=new dte("UNORDERED",2)}function Tie(){Tie=pe,G7e=(EF(),Pue),z7e=new dn(F6e,G7e),Ggt=new Zi(j6e),qgt=new Zi($6e),Vgt=new Zi(H6e)}function X8(){X8=pe,n9e=new z5,r9e=new $Y,r2t=new SL,n2t=new HY,t2t=new zY,t9e=(Sn(t2t),new cn)}function Q8(){Q8=pe,ghe=new Lte("CONSERVATIVE",0),C_e=new Lte("CONSERVATIVE_SOFT",1),kS=new Lte("SLOPPY",2)}function hH(){hH=pe,oAe=new kv(15),v3t=new fo((bi(),Fb),oAe),FS=Rk,rAe=e3t,iAe=Rb,aAe=e5,sAe=NV}function _ie(e,t,n){var r,s,o;for(r=new as,o=ii(n,0);o.b!=o.d.c;)s=u(ri(o),8),ci(r,new Io(s));Tnt(e,t,r)}function uan(e){var t,n,r;for(t=0,r=Me(na,Qe,8,e.b,0,1),n=ii(e,0);n.b!=n.d.c;)r[t++]=u(ri(n),8);return r}function yye(e){var t;return t=(!e.a&&(e.a=new at(J0,e,9,5)),e.a),t.i!=0?SUt(u(Te(t,0),678)):null}function lan(e,t){var n;return n=Ua(e,t),fte(vre(e,t),0)|GUt(vre(e,n),0)?n:Ua(Cz,vre(Nm(n,63),1))}function han(e,t){var n;n=xt((zie(),nV))!=null&&t.wg()!=null?Ue(ft(t.wg()))/Ue(ft(xt(nV))):1,Si(e.b,t,n)}function fan(e,t){var n,r;return n=u(e.d.Bc(t),14),n?(r=e.e.hc(),r.Gc(n),e.e.d-=n.gc(),n.$b(),r):null}function kye(e,t){var n,r;if(r=e.c[t],r!=0)for(e.c[t]=0,e.d-=r,n=t+1;n0)return d8(t-1,e.a.c.length),Eg(e.a,t-1);throw J(new J$e)}function dan(e,t,n){if(t<0)throw J(new Do(Zft+t));tt)throw J(new Ln(Dz+e+Tht+t));if(e<0||t>n)throw J(new Ppe(Dz+e+_6e+t+E6e+n))}function Dnt(e){if(!e.a||!(e.a.i&8))throw J(new Wo("Enumeration class expected for layout option "+e.f))}function Km(e){var t;++e.j,e.i==0?e.g=null:e.iaG?e-n>aG:n-e>aG}function Sie(e,t){return!e||t&&!e.j||we(e,124)&&u(e,124).a.b==0?0:e.Re()}function dH(e,t){return!e||t&&!e.k||we(e,124)&&u(e,124).a.a==0?0:e.Se()}function FD(e){return Qp(),e<0?e!=-1?new b3e(-1,-e):Eue:e<=10?n7e[_s(e)]:new b3e(1,e)}function Eye(e){throw fie(),J(new UHe("Unexpected typeof result '"+e+"'; please report this bug to the GWT team"))}function Bnt(e){ZHe(),ij(this),Qj(this),this.e=e,Yot(this,e),this.g=e==null?Pu:Qo(e),this.a="",this.b=e,this.a=""}function Tye(){this.a=new aZ,this.f=new Hje(this),this.b=new zje(this),this.i=new Gje(this),this.e=new qje(this)}function Rnt(){xVt.call(this,new ome(qm(16))),ql(2,sht),this.b=2,this.a=new awe(null,null,0,null),oM(this.a,this.a)}function j_(){j_=pe,ihe=new _te("DUMMY_NODE_OVER",0),l_e=new _te("DUMMY_NODE_UNDER",1),iV=new _te("EQUAL",2)}function Aie(){Aie=pe,Wue=vXe(ie(re(RS,1),tt,103,0,[(wo(),Xh),Df])),Kue=vXe(ie(re(RS,1),tt,103,0,[X0,Y0]))}function Lie(e){return(ht(),Ru).Hc(e.j)?Ue(ft(K(e,(et(),hE)))):sc(ie(re(na,1),Qe,8,0,[e.i.n,e.n,e.a])).b}function wan(e){var t,n,r,s;for(r=e.b.a,n=r.a.ec().Kc();n.Ob();)t=u(n.Pb(),561),s=new Lot(t,e.e,e.f),it(e.g,s)}function cb(e,t){var n,r,s;r=e.nk(t,null),s=null,t&&(s=(Qx(),n=new uv,n),I8(s,e.r)),r=$1(e,s,r),r&&r.Fi()}function man(e,t){var n,r;for(r=vl(e.d,1)!=0,n=!0;n;)n=!1,n=t.c.Tf(t.e,r),n=n|gI(e,t,r,!1),r=!r;zme(e)}function _ye(e,t){var n,r,s;return r=!1,n=t.q.d,t.ds&&(ust(t.q,s),r=n!=t.q.d)),r}function Fnt(e,t){var n,r,s,o,h,d,v,x;return v=t.i,x=t.j,r=e.f,s=r.i,o=r.j,h=v-s,d=x-o,n=b.Math.sqrt(h*h+d*d),n}function Cye(e,t){var n,r;return r=SH(e),r||(n=(kae(),lat(t)),r=new q$e(n),Br(r.Vk(),e)),r}function jD(e,t){var n,r;return n=u(e.c.Bc(t),14),n?(r=e.hc(),r.Gc(n),e.d-=n.gc(),n.$b(),e.mc(r)):e.jc()}function jnt(e,t){var n;for(n=0;n=e.c.b:e.a<=e.c.b))throw J(new xc);return t=e.a,e.a+=e.c.c,++e.b,ct(t)}function xan(e){var t;return t=new vet(e),sD(e.a,$pt,new Al(ie(re(dO,1),yt,369,0,[t]))),t.d&&it(t.f,t.d),t.f}function Mie(e){var t;return t=new W2e(e.a),Ho(t,e),Ye(t,(et(),Mi),e),t.o.a=e.g,t.o.b=e.f,t.n.a=e.i,t.n.b=e.j,t}function Ean(e,t,n,r){var s,o;for(o=e.Kc();o.Ob();)s=u(o.Pb(),70),s.n.a=t.a+(r.a-s.o.a)/2,s.n.b=t.b,t.b+=s.o.b+n}function Tan(e,t,n){var r,s;for(s=t.a.a.ec().Kc();s.Ob();)if(r=u(s.Pb(),57),XYe(e,r,n))return!0;return!1}function _an(e){var t,n;for(n=new C(e.r);n.a=0?t:-t;r>0;)r%2==0?(n*=n,r=r/2|0):(s*=n,r-=1);return t<0?1/s:s}function Lan(e,t){var n,r,s;for(s=1,n=e,r=t>=0?t:-t;r>0;)r%2==0?(n*=n,r=r/2|0):(s*=n,r-=1);return t<0?1/s:s}function Unt(e){var t,n;if(e!=null)for(n=0;n0&&(n=u(St(e.a,e.a.c.length-1),570),vye(n,t))||it(e.a,new EZe(t))}function Nan(e){mf();var t,n;t=e.d.c-e.e.c,n=u(e.g,145),Mu(n.b,new pT(t)),Mu(n.c,new $2(t)),Da(n.i,new QR(t))}function Xnt(e){var t;return t=new Tp,t.a+="VerticalSegment ",Ec(t,e.e),t.a+=" ",Yr(t,rbe(new ste,new C(e.k))),t.a}function Pan(e){var t;return t=u(Fv(e.c.c,""),229),t||(t=new R6(Xx(Yx(new hm,""),"Other")),hb(e.c.c,"",t)),t}function $_(e){var t;return e.Db&64?_f(e):(t=new Ph(_f(e)),t.a+=" (name: ",To(t,e.zb),t.a+=")",t.a)}function Dye(e,t,n){var r,s;return s=e.sb,e.sb=t,e.Db&4&&!(e.Db&1)&&(r=new oa(e,1,4,s,t),n?n.Ei(r):n=r),n}function Die(e,t){var n,r,s;for(n=0,s=ac(e,t).Kc();s.Ob();)r=u(s.Pb(),11),n+=K(r,(et(),cl))!=null?1:0;return n}function e4(e,t,n){var r,s,o;for(r=0,o=ii(e,0);o.b!=o.d.c&&(s=Ue(ft(ri(o))),!(s>n));)s>=t&&++r;return r}function Ban(e,t,n){var r,s;return r=new N0(e.e,3,13,null,(s=t.c,s||(on(),Z1)),Dg(e,t),!1),n?n.Ei(r):n=r,n}function Ran(e,t,n){var r,s;return r=new N0(e.e,4,13,(s=t.c,s||(on(),Z1)),null,Dg(e,t),!1),n?n.Ei(r):n=r,n}function Iye(e,t,n){var r,s;return s=e.r,e.r=t,e.Db&4&&!(e.Db&1)&&(r=new oa(e,1,8,s,e.r),n?n.Ei(r):n=r),n}function Ag(e,t){var n,r;return n=u(t,676),r=n.vk(),!r&&n.wk(r=we(t,88)?new qqe(e,u(t,26)):new hQe(e,u(t,148))),r}function $D(e,t,n){var r;e.qi(e.i+1),r=e.oi(t,n),t!=e.i&&Hc(e.g,t,e.g,t+1,e.i-t),cs(e.g,t,r),++e.i,e.bi(t,n),e.ci()}function Fan(e,t){var n;return t.a&&(n=t.a.a.length,e.a?Yr(e.a,e.b):e.a=new Fl(e.d),dQe(e.a,t.a,t.d.length,n)),e}function jan(e,t){var n,r,s,o;if(t.vi(e.a),o=u(_n(e.a,8),1936),o!=null)for(n=o,r=0,s=n.length;rn)throw J(new Do(Dz+e+_6e+t+", size: "+n));if(e>t)throw J(new Ln(Dz+e+Tht+t))}function wh(e,t,n){if(t<0)P4e(e,n);else{if(!n.Ij())throw J(new Ln(i2+n.ne()+RC));u(n,66).Nj().Vj(e,e.yh(),t)}}function zan(e,t,n,r,s,o,h,d){var v;for(v=n;o=r||t=65&&e<=70?e-65+10:e>=97&&e<=102?e-97+10:e>=48&&e<=57?e-48:0}function rrt(e){var t;return e.Db&64?_f(e):(t=new Ph(_f(e)),t.a+=" (source: ",To(t,e.d),t.a+=")",t.a)}function qan(e,t,n){var r,s;return s=e.a,e.a=t,e.Db&4&&!(e.Db&1)&&(r=new oa(e,1,5,s,e.a),n?t4e(n,r):n=r),n}function Lg(e,t){var n;n=(e.Bb&256)!=0,t?e.Bb|=256:e.Bb&=-257,e.Db&4&&!(e.Db&1)&&_i(e,new xf(e,1,2,n,t))}function Nye(e,t){var n;n=(e.Bb&256)!=0,t?e.Bb|=256:e.Bb&=-257,e.Db&4&&!(e.Db&1)&&_i(e,new xf(e,1,8,n,t))}function bH(e,t){var n;n=(e.Bb&256)!=0,t?e.Bb|=256:e.Bb&=-257,e.Db&4&&!(e.Db&1)&&_i(e,new xf(e,1,8,n,t))}function Mg(e,t){var n;n=(e.Bb&512)!=0,t?e.Bb|=512:e.Bb&=-513,e.Db&4&&!(e.Db&1)&&_i(e,new xf(e,1,3,n,t))}function Pye(e,t){var n;n=(e.Bb&512)!=0,t?e.Bb|=512:e.Bb&=-513,e.Db&4&&!(e.Db&1)&&_i(e,new xf(e,1,9,n,t))}function z_(e,t){var n;return e.b==-1&&e.a&&(n=e.a.Gj(),e.b=n?e.c.Xg(e.a.aj(),n):Ji(e.c.Tg(),e.a)),e.c.Og(e.b,t)}function ct(e){var t,n;return e>-129&&e<128?(t=e+128,n=(JWe(),G8e)[t],!n&&(n=G8e[t]=new rM(e)),n):new rM(e)}function Z8(e){var t,n;return e>-129&&e<128?(t=e+128,n=(sKe(),W8e)[t],!n&&(n=W8e[t]=new XR(e)),n):new XR(e)}function Bye(e){var t,n;return t=e.k,t==(zn(),Ls)?(n=u(K(e,(et(),vc)),61),n==(ht(),An)||n==xr):!1}function Van(e,t,n){var r,s,o;return o=(s=p7(e.b,t),s),o&&(r=u(wz(wD(e,o),""),26),r)?n5e(e,r,t,n):null}function Iie(e,t,n){var r,s,o;return o=(s=p7(e.b,t),s),o&&(r=u(wz(wD(e,o),""),26),r)?r5e(e,r,t,n):null}function irt(e,t){var n,r;for(r=new rr(e);r.e!=r.i.gc();)if(n=u(pr(r),138),je(t)===je(n))return!0;return!1}function G_(e,t,n){var r;if(r=e.gc(),t>r)throw J(new Im(t,r));if(e.hi()&&e.Hc(n))throw J(new Ln(YI));e.Xh(t,n)}function Uan(e,t){var n;if(n=K3(e.i,t),n==null)throw J(new dd("Node did not exist in input."));return Wme(t,n),null}function Wan(e,t){var n;if(n=dI(e,t),we(n,322))return u(n,34);throw J(new Ln(i2+t+"' is not a valid attribute"))}function Kan(e,t,n){var r,s;for(s=we(t,99)&&u(t,18).Bb&so?new Gte(t,e):new G8(t,e),r=0;rt?1:e==t?e==0?Fs(1/e,1/t):0:isNaN(e)?isNaN(t)?0:1:-1}function ron(e,t){kr(t,"Sort end labels",1),ms(Vi(ic(new vn(null,new mn(e.b,16)),new UP),new F5),new bY),ur(t)}function q_(e,t,n){var r,s;return e.ej()?(s=e.fj(),r=jse(e,t,n),e.$i(e.Zi(7,ct(n),r,t,s)),r):jse(e,t,n)}function Oie(e,t){var n,r,s;e.d==null?(++e.e,--e.f):(s=t.cd(),n=t.Sh(),r=(n&Ei)%e.d.length,$nn(e,r,xot(e,r,n,s)))}function J8(e,t){var n;n=(e.Bb&Sf)!=0,t?e.Bb|=Sf:e.Bb&=-1025,e.Db&4&&!(e.Db&1)&&_i(e,new xf(e,1,10,n,t))}function e7(e,t){var n;n=(e.Bb&dy)!=0,t?e.Bb|=dy:e.Bb&=-4097,e.Db&4&&!(e.Db&1)&&_i(e,new xf(e,1,12,n,t))}function t7(e,t){var n;n=(e.Bb&Zu)!=0,t?e.Bb|=Zu:e.Bb&=-8193,e.Db&4&&!(e.Db&1)&&_i(e,new xf(e,1,15,n,t))}function n7(e,t){var n;n=(e.Bb&ky)!=0,t?e.Bb|=ky:e.Bb&=-2049,e.Db&4&&!(e.Db&1)&&_i(e,new xf(e,1,11,n,t))}function ion(e,t){var n;return n=Fs(e.b.c,t.b.c),n!=0||(n=Fs(e.a.a,t.a.a),n!=0)?n:Fs(e.a.b,t.a.b)}function son(e,t){var n;if(n=er(e.k,t),n==null)throw J(new dd("Port did not exist in input."));return Wme(t,n),null}function aon(e){var t,n;for(n=Sot(Gl(e)).Kc();n.Ob();)if(t=Hr(n.Pb()),uC(e,t))return gnn((NGe(),r4t),t);return null}function oon(e,t){var n,r,s,o,h;for(h=pu(e.e.Tg(),t),o=0,n=u(e.g,119),s=0;s>10)+II&Ss,t[1]=(e&1023)+56320&Ss,jh(t,0,t.length)}function wH(e){var t,n;return n=u(K(e,(pt(),Zl)),103),n==(wo(),f0)?(t=Ue(ft(K(e,Hq))),t>=1?Df:Y0):n}function lon(e){switch(u(K(e,(pt(),K0)),218).g){case 1:return new BX;case 3:return new HX;default:return new PX}}function ub(e){if(e.c)ub(e.c);else if(e.d)throw J(new Wo("Stream already terminated, can't be modified or used"))}function Bie(e){var t;return e.Db&64?_f(e):(t=new Ph(_f(e)),t.a+=" (identifier: ",To(t,e.k),t.a+=")",t.a)}function crt(e,t,n){var r,s;return r=(pv(),s=new pp,s),z$(r,t),G$(r,n),e&&Br((!e.a&&(e.a=new Bs(ef,e,5)),e.a),r),r}function Rie(e,t,n,r){var s,o;return Sn(r),Sn(n),s=e.xc(t),o=s==null?n:kGe(u(s,15),u(n,14)),o==null?e.Bc(t):e.zc(t,o),o}function rn(e){var t,n,r,s;return n=(t=u(Qf((r=e.gm,s=r.f,s==Wr?r:s)),9),new hh(t,u(wf(t,t.length),9),0)),Tf(n,e),n}function hon(e,t,n){var r,s;for(s=e.a.ec().Kc();s.Ob();)if(r=u(s.Pb(),10),MD(n,u(St(t,r.p),14)))return r;return null}function fon(e,t,n){var r;try{Usn(e,t,n)}catch(s){throw s=ts(s),we(s,597)?(r=s,J(new qwe(r))):J(s)}return t}function Wp(e,t){var n;return Ko(e)&&Ko(t)&&(n=e-t,DI>1,e.k=n-1>>1}function Fie(){o4e();var e,t,n;n=c3n+++Date.now(),e=_s(b.Math.floor(n*NI))&Mz,t=_s(n-e*x6e),this.a=e^1502,this.b=t^uoe}function j0(e){var t,n,r;for(t=new st,r=new C(e.j);r.a34028234663852886e22?gs:t<-34028234663852886e22?Ds:t}function urt(e){return e-=e>>1&1431655765,e=(e>>2&858993459)+(e&858993459),e=(e>>4)+e&252645135,e+=e>>8,e+=e>>16,e&63}function lrt(e){var t,n,r,s;for(t=new zUe(e.Hd().gc()),s=0,r=q6(e.Hd().Kc());r.Ob();)n=r.Pb(),Sen(t,n,ct(s++));return Zfn(t.a)}function won(e,t){var n,r,s;for(s=new Mr,r=t.vc().Kc();r.Ob();)n=u(r.Pb(),42),Si(s,n.cd(),usn(e,u(n.dd(),15)));return s}function zye(e,t){e.n.c.length==0&&it(e.n,new o$(e.s,e.t,e.i)),it(e.b,t),T3e(u(St(e.n,e.n.c.length-1),211),t),yut(e,t)}function t4(e){return(e.c!=e.b.b||e.i!=e.g.b)&&(e.a.c=Me(Yn,yt,1,0,5,1),Rs(e.a,e.b),Rs(e.a,e.g),e.c=e.b.b,e.i=e.g.b),e.a}function jie(e,t){var n,r,s;for(s=0,r=u(t.Kb(e),20).Kc();r.Ob();)n=u(r.Pb(),17),It(Mt(K(n,(et(),W1))))||++s;return s}function mon(e,t){var n,r,s;r=U3(t),s=Ue(ft(Qm(r,(pt(),Mf)))),n=b.Math.max(0,s/2-.5),Z_(t,n,1),it(e,new eqe(t,n))}function mh(){mh=pe,TO=new TM(U0,0),lS=new TM("FIRST",1),l2=new TM(wft,2),hS=new TM("LAST",3),Ly=new TM(mft,4)}function $0(){$0=pe,hfe=new GF(EC,0),YO=new GF("POLYLINE",1),_E=new GF("ORTHOGONAL",2),jk=new GF("SPLINES",3)}function mH(){mH=pe,wCe=new Bte("ASPECT_RATIO_DRIVEN",0),Rhe=new Bte("MAX_SCALE_DRIVEN",1),vCe=new Bte("AREA_DRIVEN",2)}function GD(){GD=pe,EV=new Rte("P1_STRUCTURE",0),TV=new Rte("P2_PROCESSING_ORDER",1),_V=new Rte("P3_EXECUTION",2)}function yH(){yH=pe,Dhe=new Ote("OVERLAP_REMOVAL",0),Lhe=new Ote("COMPACTION",1),Mhe=new Ote("GRAPH_SIZE_CALCULATION",2)}function Kv(e,t){return S1(),Ef(Jp),b.Math.abs(e-t)<=Jp||e==t||isNaN(e)&&isNaN(t)?0:et?1:yv(isNaN(e),isNaN(t))}function hrt(e,t){var n,r;for(n=ii(e,0);n.b!=n.d.c;){if(r=uM(ft(ri(n))),r==t)return;if(r>t){mre(n);break}}YM(n,t)}function en(e,t){var n,r,s,o,h;if(n=t.f,hb(e.c.d,n,t),t.g!=null)for(s=t.g,o=0,h=s.length;ot&&r.ue(e[o-1],e[o])>0;--o)h=e[o],cs(e,o,e[o-1]),cs(e,o-1,h)}function yh(e,t,n,r){if(t<0)o5e(e,n,r);else{if(!n.Ij())throw J(new Ln(i2+n.ne()+RC));u(n,66).Nj().Tj(e,e.yh(),t,r)}}function kH(e,t){if(t==e.d)return e.e;if(t==e.e)return e.d;throw J(new Ln("Node "+t+" not part of edge "+e))}function kon(e,t){switch(t.g){case 2:return e.b;case 1:return e.c;case 4:return e.d;case 3:return e.a;default:return!1}}function frt(e,t){switch(t.g){case 2:return e.b;case 1:return e.c;case 4:return e.d;case 3:return e.a;default:return!1}}function Gye(e,t,n,r){switch(t){case 3:return e.f;case 4:return e.g;case 5:return e.i;case 6:return e.j}return Oye(e,t,n,r)}function xon(e){return e.k!=(zn(),Hs)?!1:_8(new vn(null,new Sv(new cr(fr(js(e).a.Kc(),new V)))),new TB)}function Eon(e){return e.e==null?e:(!e.c&&(e.c=new Zse((e.f&256)!=0,e.i,e.a,e.d,(e.f&16)!=0,e.j,e.g,null)),e.c)}function Ton(e,t){return e.h==MI&&e.m==0&&e.l==0?(t&&(s2=fu(0,0,0)),hVe((D8(),R8e))):(t&&(s2=fu(e.l,e.m,e.h)),fu(0,0,0))}function Qo(e){var t;return Array.isArray(e)&&e.im===gt?Cp(pl(e))+"@"+(t=Xi(e)>>>0,t.toString(16)):e.toString()}function V_(e){var t;this.a=(t=u(e.e&&e.e(),9),new hh(t,u(wf(t,t.length),9),0)),this.b=Me(Yn,yt,1,this.a.a.length,5,1)}function _on(e){var t,n,r;for(this.a=new C0,r=new C(e);r.a0&&(zr(t-1,e.length),e.charCodeAt(t-1)==58)&&!$ie(e,KS,YS))}function $ie(e,t,n){var r,s;for(r=0,s=e.length;r=s)return t.c+n;return t.c+t.b.gc()}function Mon(e,t){u8();var n,r,s,o;for(r=TJe(e),s=t,L8(r,0,r.length,s),n=0;n0&&(r+=s,++n);return n>1&&(r+=e.d*(n-1)),r}function Vye(e){var t,n,r;for(r=new bg,r.a+="[",t=0,n=e.gc();t0&&this.b>0&&Cve(this.c,this.b,this.a)}function Kye(e){zie(),this.c=O1(ie(re(C3n,1),yt,831,0,[Kvt])),this.b=new Mr,this.a=e,Si(this.b,nV,1),Mu(Yvt,new Jje(this))}function drt(e,t){var n;return e.d?Il(e.b,t)?u(er(e.b,t),51):(n=t.Kf(),Si(e.b,t,n),n):t.Kf()}function Yye(e,t){var n;return je(e)===je(t)?!0:we(t,91)?(n=u(t,91),e.e==n.e&&e.d==n.d&&bnn(e,n.a)):!1}function Y6(e){switch(ht(),e.g){case 4:return An;case 1:return $n;case 3:return xr;case 2:return Dn;default:return uc}}function Xye(e,t){switch(t){case 3:return e.f!=0;case 4:return e.g!=0;case 5:return e.i!=0;case 6:return e.j!=0}return Yme(e,t)}function Bon(e){switch(e.g){case 0:return new nZ;case 1:return new FB;default:throw J(new Ln(wce+(e.f!=null?e.f:""+e.g)))}}function grt(e){switch(e.g){case 0:return new RB;case 1:return new jB;default:throw J(new Ln(Noe+(e.f!=null?e.f:""+e.g)))}}function prt(e){switch(e.g){case 0:return new Ape;case 1:return new THe;default:throw J(new Ln(lG+(e.f!=null?e.f:""+e.g)))}}function Ron(e){switch(e.g){case 1:return new QQ;case 2:return new MUe;default:throw J(new Ln(wce+(e.f!=null?e.f:""+e.g)))}}function Fon(e){var t,n;if(e.b)return e.b;for(n=V1?null:e.d;n;){if(t=V1?null:n.b,t)return t;n=V1?null:n.d}return n8(),d7e}function jon(e){var t,n,r;return e.e==0?0:(t=e.d<<5,n=e.a[e.d-1],e.e<0&&(r=_tt(e),r==e.d-1&&(--n,n=n|0)),t-=uI(n),t)}function $on(e){var t,n,r;return e<$G.length?$G[e]:(n=e>>5,t=e&31,r=Me(Lr,Jr,25,n+1,15,1),r[n]=1<3;)s*=10,--o;e=(e+(s>>1))/s|0}return r.i=e,!0}function zon(e){return Aie(),Mn(),!!(frt(u(e.a,81).j,u(e.b,103))||u(e.a,81).d.e!=0&&frt(u(e.a,81).j,u(e.b,103)))}function Gon(e){A$(),u(e.We((bi(),p2)),174).Hc((wl(),zV))&&(u(e.We(Hy),174).Fc((ol(),$k)),u(e.We(p2),174).Mc(zV))}function vrt(e,t){var n,r;if(t){for(n=0;n=0;--r)for(t=n[r],s=0;s>1,this.k=t-1>>1}function Yon(e,t){kr(t,"End label post-processing",1),ms(Vi(ic(new vn(null,new mn(e.b,16)),new lY),new hY),new fY),ur(t)}function Xon(e,t,n){var r,s;return r=Ue(e.p[t.i.p])+Ue(e.d[t.i.p])+t.n.b+t.a.b,s=Ue(e.p[n.i.p])+Ue(e.d[n.i.p])+n.n.b+n.a.b,s-r}function Qon(e,t,n){var r,s;for(r=qs(n,yo),s=0;Mc(r,0)!=0&&s0&&(zr(0,t.length),t.charCodeAt(0)==43)?t.substr(1):t))}function Jon(e){var t;return e==null?null:new Ip((t=Xc(e,!0),t.length>0&&(zr(0,t.length),t.charCodeAt(0)==43)?t.substr(1):t))}function r3e(e,t){var n;return e.i>0&&(t.lengthe.i&&cs(t,e.i,null),t}function ou(e,t,n){var r,s,o;return e.ej()?(r=e.i,o=e.fj(),$D(e,r,t),s=e.Zi(3,null,t,r,o),n?n.Ei(s):n=s):$D(e,e.i,t),n}function ecn(e,t,n){var r,s;return r=new N0(e.e,4,10,(s=t.c,we(s,88)?u(s,26):(on(),sf)),null,Dg(e,t),!1),n?n.Ei(r):n=r,n}function tcn(e,t,n){var r,s;return r=new N0(e.e,3,10,null,(s=t.c,we(s,88)?u(s,26):(on(),sf)),Dg(e,t),!1),n?n.Ei(r):n=r,n}function yrt(e){Mm();var t;return t=new Io(u(e.e.We((bi(),e5)),8)),e.B.Hc((wl(),SE))&&(t.a<=0&&(t.a=20),t.b<=0&&(t.b=20)),t}function krt(e){Zm();var t;return(e.q?e.q:(hn(),hn(),l0))._b((pt(),_w))?t=u(K(e,_w),197):t=u(K(Ya(e),pS),197),t}function Qm(e,t){var n,r;return r=null,ta(e,(pt(),eV))&&(n=u(K(e,eV),94),n.Xe(t)&&(r=n.We(t))),r==null&&(r=K(Ya(e),t)),r}function xrt(e,t){var n,r,s;return we(t,42)?(n=u(t,42),r=n.cd(),s=Ym(e.Rc(),r),md(s,n.dd())&&(s!=null||e.Rc()._b(r))):!1}function qie(e,t){var n,r,s;return e.f>0?(e.qj(),r=t==null?0:Xi(t),s=(r&Ei)%e.d.length,n=xot(e,s,r,t),n!=-1):!1}function r1(e,t){var n,r,s;return e.f>0&&(e.qj(),r=t==null?0:Xi(t),s=(r&Ei)%e.d.length,n=H4e(e,s,r,t),n)?n.dd():null}function qD(e,t){var n,r,s,o;for(o=pu(e.e.Tg(),t),n=u(e.g,119),s=0;s1?I1(A0(t.a[1],32),qs(t.a[0],yo)):qs(t.a[0],yo),Bv(ja(t.e,n))))}function VD(e,t){var n;return Ko(e)&&Ko(t)&&(n=e%t,DI>5,t&=31,s=e.d+n+(t==0?0:1),r=Me(Lr,Jr,25,s,15,1),nfn(r,e.a,n,t),o=new z3(e.e,s,r),E_(o),o}function s3e(e,t,n){var r,s;r=u(Uc(ME,t),117),s=u(Uc(tA,t),117),n?(Oo(ME,e,r),Oo(tA,e,s)):(Oo(tA,e,r),Oo(ME,e,s))}function Lrt(e,t,n){var r,s,o;for(s=null,o=e.b;o;){if(r=e.a.ue(t,o.d),n&&r==0)return o;r>=0?o=o.a[1]:(s=o,o=o.a[0])}return s}function Mrt(e,t,n){var r,s,o;for(s=null,o=e.b;o;){if(r=e.a.ue(t,o.d),n&&r==0)return o;r<=0?o=o.a[0]:(s=o,o=o.a[1])}return s}function acn(e,t,n,r){var s,o,h;return s=!1,Hwn(e.f,n,r)&&(Dcn(e.f,e.a[t][n],e.a[t][r]),o=e.a[t],h=o[r],o[r]=o[n],o[n]=h,s=!0),s}function a3e(e,t,n,r,s){var o,h,d;for(h=s;t.b!=t.c;)o=u(I6(t),10),d=u(ac(o,r).Xb(0),11),e.d[d.p]=h++,n.c[n.c.length]=d;return h}function o3e(e,t,n){var r,s,o,h,d;return h=e.k,d=t.k,r=n[h.g][d.g],s=ft(Qm(e,r)),o=ft(Qm(t,r)),b.Math.max((Sn(s),s),(Sn(o),o))}function ocn(e,t,n){var r,s,o,h;for(r=n/e.c.length,s=0,h=new C(e);h.a2e3&&(S0t=e,RG=b.setTimeout(gUt,10))),BG++==0?(zrn((Ope(),N8e)),!0):!1}function ucn(e,t){var n,r,s;for(r=new cr(fr(js(e).a.Kc(),new V));Vr(r);)if(n=u(Pr(r),17),s=n.d.i,s.c==t)return!1;return!0}function c3e(e,t){var n,r;if(we(t,245)){r=u(t,245);try{return n=e.vd(r),n==0}catch(s){if(s=ts(s),!we(s,205))throw J(s)}}return!1}function lcn(){return Error.stackTraceLimit>0?(b.Error.stackTraceLimit=Error.stackTraceLimit=64,!0):"stack"in new Error}function hcn(e,t){return S1(),S1(),Ef(Jp),(b.Math.abs(e-t)<=Jp||e==t||isNaN(e)&&isNaN(t)?0:et?1:yv(isNaN(e),isNaN(t)))>0}function u3e(e,t){return S1(),S1(),Ef(Jp),(b.Math.abs(e-t)<=Jp||e==t||isNaN(e)&&isNaN(t)?0:et?1:yv(isNaN(e),isNaN(t)))<0}function Ort(e,t){return S1(),S1(),Ef(Jp),(b.Math.abs(e-t)<=Jp||e==t||isNaN(e)&&isNaN(t)?0:et?1:yv(isNaN(e),isNaN(t)))<=0}function Uie(e,t){for(var n=0;!t[n]||t[n]=="";)n++;for(var r=t[n++];nioe)return n.fh();if(r=n.Zg(),r||n==e)break}return r}function l3e(e){return u$(),we(e,156)?u(er(oN,j0t),288).vg(e):Il(oN,pl(e))?u(er(oN,pl(e)),288).vg(e):null}function dcn(e){if(AH(j7,e))return Mn(),U7;if(AH(Mce,e))return Mn(),Sb;throw J(new Ln("Expecting true or false"))}function gcn(e,t){if(t.c==e)return t.d;if(t.d==e)return t.c;throw J(new Ln("Input edge is not connected to the input port."))}function jrt(e,t){return e.e>t.e?1:e.et.d?e.e:e.d=48&&e<48+b.Math.min(10,10)?e-48:e>=97&&e<97?e-97+10:e>=65&&e<65?e-65+10:-1}function Hrt(e,t){var n;return je(t)===je(e)?!0:!we(t,21)||(n=u(t,21),n.gc()!=e.gc())?!1:e.Ic(n)}function pcn(e,t){var n,r,s,o;return r=e.a.length-1,n=t-e.b&r,o=e.c-t&r,s=e.c-e.b&r,pUe(n=o?(gan(e,t),-1):(pan(e,t),1)}function bcn(e,t){var n,r;for(n=(zr(t,e.length),e.charCodeAt(t)),r=t+1;rt.e?1:e.ft.f?1:Xi(e)-Xi(t)}function AH(e,t){return Sn(e),t==null?!1:an(e,t)?!0:e.length==t.length&&an(e.toLowerCase(),t.toLowerCase())}function _cn(e,t){var n,r,s,o;for(r=0,s=t.gc();r0&&Mc(e,128)<0?(t=Or(e)+128,n=(iKe(),q8e)[t],!n&&(n=q8e[t]=new wm(e)),n):new wm(e)}function Grt(e,t){var n,r;return n=t.Hh(e.a),n&&(r=Hr(r1((!n.b&&(n.b=new Ml((on(),oo),wc,n)),n.b),gi)),r!=null)?r:t.ne()}function Ccn(e,t){var n,r;return n=t.Hh(e.a),n&&(r=Hr(r1((!n.b&&(n.b=new Ml((on(),oo),wc,n)),n.b),gi)),r!=null)?r:t.ne()}function Scn(e,t){fre();var n,r;for(r=new cr(fr(j0(e).a.Kc(),new V));Vr(r);)if(n=u(Pr(r),17),n.d.i==t||n.c.i==t)return n;return null}function d3e(e,t,n){this.c=e,this.f=new st,this.e=new Fa,this.j=new xve,this.n=new xve,this.b=t,this.g=new fh(t.c,t.d,t.b,t.a),this.a=n}function Wie(e){var t,n,r,s;for(this.a=new C0,this.d=new Ys,this.e=0,n=e,r=0,s=n.length;r0):!1}function Urt(e){var t;je(Ft(e,(bi(),Q4)))===je((F0(),FV))&&(us(e)?(t=u(Ft(us(e),Q4),334),So(e,Q4,t)):So(e,Q4,jS))}function Dcn(e,t,n){var r,s;Ase(e.e,t,n,(ht(),Dn)),Ase(e.i,t,n,$n),e.a&&(s=u(K(t,(et(),Mi)),11),r=u(K(n,Mi),11),wre(e.g,s,r))}function Wrt(e,t,n){var r,s,o;r=t.c.p,o=t.p,e.b[r][o]=new cXe(e,t),n&&(e.a[r][o]=new qx(t),s=u(K(t,(et(),xw)),10),s&&sn(e.d,s,t))}function Krt(e,t){var n,r,s;if(it(QG,e),t.Fc(e),n=u(er(jue,e),21),n)for(s=n.Kc();s.Ob();)r=u(s.Pb(),33),Yo(QG,r,0)!=-1||Krt(r,t)}function Icn(e,t,n){var r;(U0t?(Fon(e),!0):W0t||Y0t?(n8(),!0):K0t&&(n8(),!1))&&(r=new yWe(t),r.b=n,Pfn(e,r))}function Kie(e,t){var n;n=!e.A.Hc((Bl(),Hb))||e.q==(wa(),tu),e.u.Hc((ol(),Z0))?n?eyn(e,t):Tlt(e,t):e.u.Hc(m2)&&(n?mmn(e,t):Flt(e,t))}function s7(e,t){var n,r;if(++e.j,t!=null&&(n=(r=e.a.Cb,we(r,97)?u(r,97).Jg():null),Sdn(t,n))){X6(e.a,4,n);return}X6(e.a,4,u(t,126))}function Yrt(e,t,n){return new fh(b.Math.min(e.a,t.a)-n/2,b.Math.min(e.b,t.b)-n/2,b.Math.abs(e.a-t.a)+n,b.Math.abs(e.b-t.b)+n)}function Ocn(e,t){var n,r;return n=Tu(e.a.c.p,t.a.c.p),n!=0?n:(r=Tu(e.a.d.i.p,t.a.d.i.p),r!=0?r:Tu(t.a.d.p,e.a.d.p))}function Ncn(e,t,n){var r,s,o,h;return o=t.j,h=n.j,o!=h?o.g-h.g:(r=e.f[t.p],s=e.f[n.p],r==0&&s==0?0:r==0?-1:s==0?1:Fs(r,s))}function Xrt(e,t,n){var r,s,o;if(!n[t.d])for(n[t.d]=!0,s=new C(t4(t));s.a=s)return s;for(t=t>0?t:0;tr&&cs(t,r,null),t}function Zrt(e,t){var n,r;for(r=e.a.length,t.lengthr&&cs(t,r,null),t}function hb(e,t,n){var r,s,o;return s=u(er(e.e,t),387),s?(o=Rbe(s,n),HVe(e,s),o):(r=new lve(e,t,n),Si(e.e,t,r),dXe(r),null)}function Rcn(e){var t;if(e==null)return null;if(t=D0n(Xc(e,!0)),t==null)throw J(new nte("Invalid hexBinary value: '"+e+"'"));return t}function WD(e){return Qp(),Mc(e,0)<0?Mc(e,-1)!=0?new Z3e(-1,M8(e)):Eue:Mc(e,10)<=0?n7e[Or(e)]:new Z3e(1,e)}function Xie(){return Tz(),ie(re(Ogt,1),tt,159,0,[Dgt,Mgt,Igt,xgt,kgt,Egt,Cgt,_gt,Tgt,Lgt,Agt,Sgt,mgt,wgt,ygt,bgt,pgt,vgt,dgt,fgt,ggt,Iue])}function Jrt(e){var t;this.d=new st,this.j=new Fa,this.g=new Fa,t=e.g.b,this.f=u(K(Ya(t),(pt(),Zl)),103),this.e=Ue(ft(DH(t,Ry)))}function eit(e){this.b=new st,this.e=new st,this.d=e,this.a=!LT(Vi(new vn(null,new Sv(new N1(e.b))),new Ke(new _B))).sd((G2(),X7))}function i1(){i1=pe,Fn=new SM("PARENTS",0),ua=new SM("NODES",1),Fd=new SM("EDGES",2),Bb=new SM("PORTS",3),Vg=new SM("LABELS",4)}function n4(){n4=pe,v2=new LM("DISTRIBUTED",0),ZO=new LM("JUSTIFIED",1),uAe=new LM("BEGIN",2),$S=new LM(D7,3),lAe=new LM("END",4)}function Fcn(e){var t;switch(t=e.yi(null),t){case 10:return 0;case 15:return 1;case 14:return 2;case 11:return 3;case 21:return 4}return-1}function Qie(e){switch(e.g){case 1:return wo(),X0;case 4:return wo(),Xh;case 2:return wo(),Df;case 3:return wo(),Y0}return wo(),f0}function jcn(e,t,n){var r;switch(r=n.q.getFullYear()-e2+e2,r<0&&(r=-r),t){case 1:e.a+=r;break;case 2:e0(e,r%100,2);break;default:e0(e,r,t)}}function ii(e,t){var n,r;if(jm(t,e.b),t>=e.b>>1)for(r=e.c,n=e.b;n>t;--n)r=r.b;else for(r=e.a.a,n=0;n=64&&t<128&&(s=I1(s,A0(1,t-64)));return s}function DH(e,t){var n,r;return r=null,ta(e,(bi(),Fk))&&(n=u(K(e,Fk),94),n.Xe(t)&&(r=n.We(t))),r==null&&Ya(e)&&(r=K(Ya(e),t)),r}function rit(e,t){var n,r,s;s=t.d.i,r=s.k,!(r==(zn(),Hs)||r==U1)&&(n=new cr(fr(js(s).a.Kc(),new V)),Vr(n)&&Si(e.k,t,u(Pr(n),17)))}function Zie(e,t){var n,r,s;return r=gn(e.Tg(),t),n=t-e.Ah(),n<0?(s=e.Yg(r),s>=0?e.lh(s):Fse(e,r)):n<0?Fse(e,r):u(r,66).Nj().Sj(e,e.yh(),n)}function xt(e){var t;if(we(e.a,4)){if(t=l3e(e.a),t==null)throw J(new Wo(e1t+e.b+"'. "+Jft+(S0(cN),cN.k)+qxe));return t}else return e.a}function zcn(e){var t;if(e==null)return null;if(t=cyn(Xc(e,!0)),t==null)throw J(new nte("Invalid base64Binary value: '"+e+"'"));return t}function pr(e){var t;try{return t=e.i.Xb(e.e),e.mj(),e.g=e.e++,t}catch(n){throw n=ts(n),we(n,73)?(e.mj(),J(new xc)):J(n)}}function Jie(e){var t;try{return t=e.c.ki(e.e),e.mj(),e.g=e.e++,t}catch(n){throw n=ts(n),we(n,73)?(e.mj(),J(new xc)):J(n)}}function K_(){K_=pe,U7e=(bi(),zSe),Rue=ySe,Ugt=Bk,V7e=Fb,Xgt=(GH(),T7e),Ygt=x7e,Qgt=C7e,Kgt=k7e,Wgt=(Tie(),z7e),Bue=Ggt,q7e=qgt,XG=Vgt}function IH(e){switch(Jpe(),this.c=new st,this.d=e,e.g){case 0:case 2:this.a=owe(lEe),this.b=gs;break;case 3:case 1:this.a=lEe,this.b=Ds}}function iit(e,t,n){var r,s;if(e.c)Du(e.c,e.c.i+t),Iu(e.c,e.c.j+n);else for(s=new C(e.b);s.a0&&(it(e.b,new BWe(t.a,n)),r=t.a.length,0r&&(t.a+=$Ve(Me(Sh,Td,25,-r,15,1))))}function sit(e,t){var n,r,s;for(n=e.o,s=u(u(Ii(e.r,t),21),84).Kc();s.Ob();)r=u(s.Pb(),111),r.e.a=Vun(r,n.a),r.e.b=n.b*Ue(ft(r.b.We(WG)))}function qcn(e,t){var n,r,s,o;return s=e.k,n=Ue(ft(K(e,(et(),Ew)))),o=t.k,r=Ue(ft(K(t,Ew))),o!=(zn(),Ls)?-1:s!=Ls?1:n==r?0:n=0?e.hh(t,n,r):(e.eh()&&(r=(s=e.Vg(),s>=0?e.Qg(r):e.eh().ih(e,-1-s,null,r))),e.Sg(t,n,r))}function p3e(e,t){switch(t){case 7:!e.e&&(e.e=new wn(ra,e,7,4)),_r(e.e);return;case 8:!e.d&&(e.d=new wn(ra,e,8,5)),_r(e.d);return}t3e(e,t)}function s1(e,t){var n;n=e.Zc(t);try{return n.Pb()}catch(r){throw r=ts(r),we(r,109)?J(new Do("Can't get element "+t)):J(r)}}function b3e(e,t){this.e=e,t=0&&(n.d=e.t);break;case 3:e.t>=0&&(n.a=e.t)}e.C&&(n.b=e.C.b,n.c=e.C.c)}function Z6(){Z6=pe,oO=new PF(Oz,0),aO=new PF(woe,1),cO=new PF(moe,2),uO=new PF(yoe,3),oO.a=!1,aO.a=!0,cO.a=!1,uO.a=!0}function Y_(){Y_=pe,lO=new NF(Oz,0),KG=new NF(woe,1),YG=new NF(moe,2),hO=new NF(yoe,3),lO.a=!1,KG.a=!0,YG.a=!1,hO.a=!0}function Ycn(e){var t;t=e.a;do t=u(Pr(new cr(fr(Xo(t).a.Kc(),new V))),17).c.i,t.k==(zn(),ca)&&e.b.Fc(t);while(t.k==(zn(),ca));e.b=nb(e.b)}function Xcn(e){var t,n,r;for(r=e.c.a,e.p=(Nr(r),new Uu(r)),n=new C(r);n.an.b)return!0}return!1}function ese(e,t){return fa(e)?!!y0t[t]:e.hm?!!e.hm[t]:Sm(e)?!!m0t[t]:Cm(e)?!!w0t[t]:!1}function So(e,t,n){return n==null?(!e.o&&(e.o=new Nl((cu(),k2),Dw,e,0)),CH(e.o,t)):(!e.o&&(e.o=new Nl((cu(),k2),Dw,e,0)),qH(e.o,t,n)),e}function eun(e,t,n,r){var s,o;o=t.Xe((bi(),J4))?u(t.We(J4),21):e.j,s=Gan(o),s!=(Tz(),Iue)&&(n&&!h3e(s)||k4e(I0n(e,s,r),t))}function NH(e,t,n,r){var s,o,h;return o=gn(e.Tg(),t),s=t-e.Ah(),s<0?(h=e.Yg(o),h>=0?e._g(h,n,!0):tw(e,o,n)):u(o,66).Nj().Pj(e,e.yh(),s,n,r)}function tun(e,t,n,r){var s,o,h;n.mh(t)&&(ho(),Ure(t)?(s=u(n.ah(t),153),_cn(e,s)):(o=(h=t,h?u(r,49).xh(h):null),o&&rVt(n.ah(t),o)))}function nun(e){switch(e.g){case 1:return Vv(),sO;case 3:return Vv(),iO;case 2:return Vv(),Nue;case 4:return Vv(),Oue;default:return null}}function v3e(e){switch(typeof e){case Mae:return Ig(e);case d6e:return _s(e);case sk:return Mn(),e?1231:1237;default:return e==null?0:xv(e)}}function run(e,t,n){if(e.e)switch(e.b){case 1:IJt(e.c,t,n);break;case 0:OJt(e.c,t,n)}else VQe(e.c,t,n);e.a[t.p][n.p]=e.c.i,e.a[n.p][t.p]=e.c.e}function lit(e){var t,n;if(e==null)return null;for(n=Me(h0,Qe,193,e.length,0,2),t=0;t=0)return s;if(e.Fk()){for(r=0;r=s)throw J(new Im(t,s));if(e.hi()&&(r=e.Xc(n),r>=0&&r!=t))throw J(new Ln(YI));return e.mi(t,n)}function w3e(e,t){if(this.a=u(Nr(e),245),this.b=u(Nr(t),245),e.vd(t)>0||e==(Xee(),fue)||t==(Yee(),due))throw J(new Ln("Invalid range: "+HQe(e,t)))}function hit(e){var t,n;for(this.b=new st,this.c=e,this.a=!1,n=new C(e.a);n.a0),(t&-t)==t)return _s(t*vl(e,31)*4656612873077393e-25);do n=vl(e,31),r=n%t;while(n-r+(t-1)<0);return _s(r)}function Ig(e){kWe();var t,n,r;return n=":"+e,r=qG[n],r!=null?_s((Sn(r),r)):(r=p7e[n],t=r==null?Ygn(e):_s((Sn(r),r)),TJt(),qG[n]=t,t)}function dit(e,t,n){kr(n,"Compound graph preprocessor",1),e.a=new Nv,mlt(e,t,null),Bvn(e,t),wgn(e),Ye(t,(et(),N9e),e.a),e.a=null,sl(e.b),ur(n)}function aun(e,t,n){switch(n.g){case 1:e.a=t.a/2,e.b=0;break;case 2:e.a=t.a,e.b=t.b/2;break;case 3:e.a=t.a/2,e.b=t.b;break;case 4:e.a=0,e.b=t.b/2}}function oun(e){var t,n,r;for(r=u(Ii(e.a,(c4(),Cq)),15).Kc();r.Ob();)n=u(r.Pb(),101),t=D3e(n),p8(e,n,t[0],(qv(),ww),0),p8(e,n,t[1],mw,1)}function cun(e){var t,n,r;for(r=u(Ii(e.a,(c4(),Sq)),15).Kc();r.Ob();)n=u(r.Pb(),101),t=D3e(n),p8(e,n,t[0],(qv(),ww),0),p8(e,n,t[1],mw,1)}function tse(e){switch(e.g){case 0:return null;case 1:return new dtt;case 2:return new Lpe;default:throw J(new Ln(wce+(e.f!=null?e.f:""+e.g)))}}function KD(e,t,n){var r,s;for(Msn(e,t-e.s,n-e.t),s=new C(e.n);s.a1&&(o=sun(e,t)),o}function nse(e){var t;return e.f&&e.f.kh()&&(t=u(e.f,49),e.f=u(Up(e,t),82),e.f!=t&&e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,9,8,t,e.f))),e.f}function rse(e){var t;return e.i&&e.i.kh()&&(t=u(e.i,49),e.i=u(Up(e,t),82),e.i!=t&&e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,9,7,t,e.i))),e.i}function go(e){var t;return e.b&&e.b.Db&64&&(t=e.b,e.b=u(Up(e,t),18),e.b!=t&&e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,9,21,t,e.b))),e.b}function RH(e,t){var n,r,s;e.d==null?(++e.e,++e.f):(r=t.Sh(),_gn(e,e.f+1),s=(r&Ei)%e.d.length,n=e.d[s],!n&&(n=e.d[s]=e.uj()),n.Fc(t),++e.f)}function k3e(e,t,n){var r;return t.Kj()?!1:t.Zj()!=-2?(r=t.zj(),r==null?n==null:Ci(r,n)):t.Hj()==e.e.Tg()&&n==null}function FH(){var e;ql(16,uht),e=itt(16),this.b=Me(pue,AI,317,e,0,1),this.c=Me(pue,AI,317,e,0,1),this.a=null,this.e=null,this.i=0,this.f=e-1,this.g=0}function H0(e){jbe.call(this),this.k=(zn(),Hs),this.j=(ql(6,fy),new su(6)),this.b=(ql(2,fy),new su(2)),this.d=new qee,this.f=new ype,this.a=e}function lun(e){var t,n;e.c.length<=1||(t=hct(e,(ht(),xr)),Jst(e,u(t.a,19).a,u(t.b,19).a),n=hct(e,Dn),Jst(e,u(n.a,19).a,u(n.b,19).a))}function X_(){X_=pe,f_e=new EM("SIMPLE",0),ohe=new EM(Boe,1),che=new EM("LINEAR_SEGMENTS",2),wS=new EM("BRANDES_KOEPF",3),mS=new EM(Pft,4)}function x3e(e,t,n){A6(u(K(t,(pt(),bs)),98))||(bme(e,t,Og(t,n)),bme(e,t,Og(t,(ht(),xr))),bme(e,t,Og(t,An)),hn(),aa(t.j,new sM(e)))}function git(e,t,n,r){var s,o,h;for(s=u(Ii(r?e.a:e.b,t),21),h=s.Kc();h.Ob();)if(o=u(h.Pb(),33),cz(e,n,o))return!0;return!1}function ise(e){var t,n;for(n=new rr(e);n.e!=n.i.gc();)if(t=u(pr(n),87),t.e||(!t.d&&(t.d=new Bs(Eo,t,1)),t.d).i!=0)return!0;return!1}function sse(e){var t,n;for(n=new rr(e);n.e!=n.i.gc();)if(t=u(pr(n),87),t.e||(!t.d&&(t.d=new Bs(Eo,t,1)),t.d).i!=0)return!0;return!1}function hun(e){var t,n,r;for(t=0,r=new C(e.c.a);r.a102?-1:e<=57?e-48:e<65?-1:e<=70?e-65+10:e<97?-1:e-97+10}function cse(e,t){if(e==null)throw J(new b6("null key in entry: null="+t));if(t==null)throw J(new b6("null value in entry: "+e+"=null"))}function fun(e,t){for(var n,r;e.Ob();)if(!t.Ob()||(n=e.Pb(),r=t.Pb(),!(je(n)===je(r)||n!=null&&Ci(n,r))))return!1;return!t.Ob()}function bit(e,t){var n;return n=ie(re(pa,1),Ao,25,15,[Sie(e.a[0],t),Sie(e.a[1],t),Sie(e.a[2],t)]),e.d&&(n[0]=b.Math.max(n[0],n[2]),n[2]=n[0]),n}function vit(e,t){var n;return n=ie(re(pa,1),Ao,25,15,[dH(e.a[0],t),dH(e.a[1],t),dH(e.a[2],t)]),e.d&&(n[0]=b.Math.max(n[0],n[2]),n[2]=n[0]),n}function db(){db=pe,ble=new xM("GREEDY",0),h9e=new xM(kft,1),vle=new xM(Boe,2),sS=new xM("MODEL_ORDER",3),iS=new xM("GREEDY_MODEL_ORDER",4)}function wit(e,t){var n,r,s;for(e.b[t.g]=1,r=ii(t.d,0);r.b!=r.d.c;)n=u(ri(r),188),s=n.c,e.b[s.g]==1?ci(e.a,n):e.b[s.g]==2?e.b[s.g]=1:wit(e,s)}function dun(e,t){var n,r,s;for(s=new su(t.gc()),r=t.Kc();r.Ob();)n=u(r.Pb(),286),n.c==n.f?f7(e,n,n.c):h1n(e,n)||(s.c[s.c.length]=n);return s}function gun(e,t,n){var r,s,o,h,d;for(d=e.r+t,e.r+=t,e.d+=n,r=n/e.n.c.length,s=0,h=new C(e.n);h.ao&&cs(t,o,null),t}function Aun(e,t){var n,r;if(r=e.gc(),t==null){for(n=0;n0&&(v+=s),x[_]=h,h+=d*(v+r)}function Cit(e){var t,n,r;for(r=e.f,e.n=Me(pa,Ao,25,r,15,1),e.d=Me(pa,Ao,25,r,15,1),t=0;t0?e.c:0),++s;e.b=r,e.d=o}function Pun(e,t){var n,r,s,o,h;for(r=0,s=0,n=0,h=new C(t);h.a0?e.g:0),++n;e.c=s,e.d=r}function Dit(e,t){var n;return n=ie(re(pa,1),Ao,25,15,[y3e(e,(n1(),pc),t),y3e(e,lu,t),y3e(e,bc,t)]),e.f&&(n[0]=b.Math.max(n[0],n[2]),n[2]=n[0]),n}function Bun(e,t,n){var r;try{hz(e,t+e.j,n+e.k,!1,!0)}catch(s){throw s=ts(s),we(s,73)?(r=s,J(new Do(r.g+Pz+t+io+n+")."))):J(s)}}function Run(e,t,n){var r;try{hz(e,t+e.j,n+e.k,!0,!1)}catch(s){throw s=ts(s),we(s,73)?(r=s,J(new Do(r.g+Pz+t+io+n+")."))):J(s)}}function Iit(e){var t;ta(e,(pt(),Tw))&&(t=u(K(e,Tw),21),t.Hc((sy(),If))?(t.Mc(If),t.Fc(Of)):t.Hc(Of)&&(t.Mc(Of),t.Fc(If)))}function Oit(e){var t;ta(e,(pt(),Tw))&&(t=u(K(e,Tw),21),t.Hc((sy(),Pf))?(t.Mc(Pf),t.Fc(Zh)):t.Hc(Zh)&&(t.Mc(Zh),t.Fc(Pf)))}function Fun(e,t,n){kr(n,"Self-Loop ordering",1),ms(Cu(Vi(Vi(ic(new vn(null,new mn(t.b,16)),new rB),new VY),new UY),new WY),new mm(e)),ur(n)}function XD(e,t,n,r){var s,o;for(s=t;s0&&(s.b+=t),s}function HH(e,t){var n,r,s;for(s=new Fa,r=e.Kc();r.Ob();)n=u(r.Pb(),37),cC(n,0,s.b),s.b+=n.f.b+t,s.a=b.Math.max(s.a,n.f.a);return s.a>0&&(s.a+=t),s}function Pit(e){var t,n,r;for(r=Ei,n=new C(e.a);n.a>16==6?e.Cb.ih(e,5,h1,t):(r=go(u(gn((n=u(_n(e,16),26),n||e.zh()),e.Db>>16),18)),e.Cb.ih(e,r.n,r.f,t))}function Gun(e){k8();var t=e.e;if(t&&t.stack){var n=t.stack,r=t+` +`;return n.substring(0,r.length)==r&&(n=n.substring(r.length)),n.split(` +`)}return[]}function qun(e){var t;return t=(Zet(),I0t),t[e>>>28]|t[e>>24&15]<<4|t[e>>20&15]<<8|t[e>>16&15]<<12|t[e>>12&15]<<16|t[e>>8&15]<<20|t[e>>4&15]<<24|t[e&15]<<28}function Fit(e){var t,n,r;e.b==e.c&&(r=e.a.length,n=cye(b.Math.max(8,r))<<1,e.b!=0?(t=wf(e.a,n),att(e,t,r),e.a=t,e.b=0):rHe(e.a,n),e.c=r)}function Vun(e,t){var n;return n=e.b,n.Xe((bi(),kl))?n.Hf()==(ht(),Dn)?-n.rf().a-Ue(ft(n.We(kl))):t+Ue(ft(n.We(kl))):n.Hf()==(ht(),Dn)?-n.rf().a:t}function QD(e){var t;return e.b.c.length!=0&&u(St(e.b,0),70).a?u(St(e.b,0),70).a:(t=ere(e),t??""+(e.c?Yo(e.c.a,e,0):-1))}function zH(e){var t;return e.f.c.length!=0&&u(St(e.f,0),70).a?u(St(e.f,0),70).a:(t=ere(e),t??""+(e.i?Yo(e.i.j,e,0):-1))}function Uun(e,t){var n,r;if(t<0||t>=e.gc())return null;for(n=t;n0?e.c:0),s=b.Math.max(s,t.d),++r;e.e=o,e.b=s}function Kun(e){var t,n;if(!e.b)for(e.b=p$(u(e.f,118).Ag().i),n=new rr(u(e.f,118).Ag());n.e!=n.i.gc();)t=u(pr(n),137),it(e.b,new tte(t));return e.b}function Yun(e,t){var n,r,s;if(t.dc())return u8(),u8(),uN;for(n=new jUe(e,t.gc()),s=new rr(e);s.e!=s.i.gc();)r=pr(s),t.Hc(r)&&Br(n,r);return n}function L3e(e,t,n,r){return t==0?r?(!e.o&&(e.o=new Nl((cu(),k2),Dw,e,0)),e.o):(!e.o&&(e.o=new Nl((cu(),k2),Dw,e,0)),hD(e.o)):NH(e,t,n,r)}function bse(e){var t,n;if(e.rb)for(t=0,n=e.rb.i;t>22),s+=r>>22,s<0)?!1:(e.l=n&ml,e.m=r&ml,e.h=s&V0,!0)}function Jun(e,t,n,r,s,o,h){var d,v;return!(t.Ae()&&(v=e.a.ue(n,r),v<0||!s&&v==0)||t.Be()&&(d=e.a.ue(n,o),d>0||!h&&d==0))}function eln(e,t){X8();var n;if(n=e.j.g-t.j.g,n!=0)return 0;switch(e.j.g){case 2:return jie(t,r9e)-jie(e,r9e);case 4:return jie(e,n9e)-jie(t,n9e)}return 0}function tln(e){switch(e.g){case 0:return mle;case 1:return yle;case 2:return kle;case 3:return xle;case 4:return Mq;case 5:return Ele;default:return null}}function Ro(e,t,n){var r,s;return r=(s=new Wee,cb(s,t),au(s,n),Br((!e.c&&(e.c=new at(Iw,e,12,10)),e.c),s),s),Cg(r,0),Wm(r,1),Mg(r,!0),Lg(r,!0),r}function J6(e,t){var n,r;if(t>=e.i)throw J(new zte(t,e.i));return++e.j,n=e.g[t],r=e.i-t-1,r>0&&Hc(e.g,t+1,e.g,t,r),cs(e.g,--e.i,null),e.fi(t,n),e.ci(),n}function jit(e,t){var n,r;return e.Db>>16==17?e.Cb.ih(e,21,tf,t):(r=go(u(gn((n=u(_n(e,16),26),n||e.zh()),e.Db>>16),18)),e.Cb.ih(e,r.n,r.f,t))}function nln(e){var t,n,r,s;for(hn(),aa(e.c,e.a),s=new C(e.c);s.an.a.c.length))throw J(new Ln("index must be >= 0 and <= layer node count"));e.c&&Au(e.c.a,e),e.c=n,n&&Om(n.a,t,e)}function qit(e,t){var n,r,s;for(r=new cr(fr(j0(e).a.Kc(),new V));Vr(r);)return n=u(Pr(r),17),s=u(t.Kb(n),10),new Bx(Nr(s.n.b+s.o.b/2));return kT(),kT(),hue}function Vit(e,t){this.c=new Mr,this.a=e,this.b=t,this.d=u(K(e,(et(),G4)),304),je(K(e,(pt(),zTe)))===je((pD(),Dq))?this.e=new yHe:this.e=new mHe}function cln(e,t){var n,r,s,o;for(o=0,r=new C(e);r.a>16==6?e.Cb.ih(e,6,ra,t):(r=go(u(gn((n=u(_n(e,16),26),n||(cu(),qV)),e.Db>>16),18)),e.Cb.ih(e,r.n,r.f,t))}function P3e(e,t){var n,r;return e.Db>>16==7?e.Cb.ih(e,1,iN,t):(r=go(u(gn((n=u(_n(e,16),26),n||(cu(),xAe)),e.Db>>16),18)),e.Cb.ih(e,r.n,r.f,t))}function B3e(e,t){var n,r;return e.Db>>16==9?e.Cb.ih(e,9,hs,t):(r=go(u(gn((n=u(_n(e,16),26),n||(cu(),TAe)),e.Db>>16),18)),e.Cb.ih(e,r.n,r.f,t))}function Wit(e,t){var n,r;return e.Db>>16==5?e.Cb.ih(e,9,JV,t):(r=go(u(gn((n=u(_n(e,16),26),n||(on(),Yg)),e.Db>>16),18)),e.Cb.ih(e,r.n,r.f,t))}function R3e(e,t){var n,r;return e.Db>>16==3?e.Cb.ih(e,0,aN,t):(r=go(u(gn((n=u(_n(e,16),26),n||(on(),Kg)),e.Db>>16),18)),e.Cb.ih(e,r.n,r.f,t))}function Kit(e,t){var n,r;return e.Db>>16==7?e.Cb.ih(e,6,h1,t):(r=go(u(gn((n=u(_n(e,16),26),n||(on(),Qg)),e.Db>>16),18)),e.Cb.ih(e,r.n,r.f,t))}function Yit(){this.a=new VB,this.g=new FH,this.j=new FH,this.b=new Mr,this.d=new FH,this.i=new FH,this.k=new Mr,this.c=new Mr,this.e=new Mr,this.f=new Mr}function fln(e,t,n){var r,s,o;for(n<0&&(n=0),o=e.i,s=n;sioe)return o7(e,r);if(r==e)return!0}}return!1}function gln(e){switch(uj(),e.q.g){case 5:Oat(e,(ht(),An)),Oat(e,xr);break;case 4:Aot(e,(ht(),An)),Aot(e,xr);break;default:Alt(e,(ht(),An)),Alt(e,xr)}}function pln(e){switch(uj(),e.q.g){case 5:Kat(e,(ht(),$n)),Kat(e,Dn);break;case 4:sit(e,(ht(),$n)),sit(e,Dn);break;default:Llt(e,(ht(),$n)),Llt(e,Dn)}}function bln(e){var t,n;t=u(K(e,(a1(),dpt)),19),t?(n=t.a,n==0?Ye(e,(zp(),tq),new Fie):Ye(e,(zp(),tq),new m$(n))):Ye(e,(zp(),tq),new m$(1))}function vln(e,t){var n;switch(n=e.i,t.g){case 1:return-(e.n.b+e.o.b);case 2:return e.n.a-n.o.a;case 3:return e.n.b-n.o.b;case 4:return-(e.n.a+e.o.a)}return 0}function wln(e,t){switch(e.g){case 0:return t==(mh(),l2)?kq:xq;case 1:return t==(mh(),l2)?kq:bO;case 2:return t==(mh(),l2)?bO:xq;default:return bO}}function JD(e,t){var n,r,s;for(Au(e.a,t),e.e-=t.r+(e.a.c.length==0?0:e.c),s=Exe,r=new C(e.a);r.a>16==3?e.Cb.ih(e,12,hs,t):(r=go(u(gn((n=u(_n(e,16),26),n||(cu(),kAe)),e.Db>>16),18)),e.Cb.ih(e,r.n,r.f,t))}function j3e(e,t){var n,r;return e.Db>>16==11?e.Cb.ih(e,10,hs,t):(r=go(u(gn((n=u(_n(e,16),26),n||(cu(),EAe)),e.Db>>16),18)),e.Cb.ih(e,r.n,r.f,t))}function Xit(e,t){var n,r;return e.Db>>16==10?e.Cb.ih(e,11,tf,t):(r=go(u(gn((n=u(_n(e,16),26),n||(on(),Xg)),e.Db>>16),18)),e.Cb.ih(e,r.n,r.f,t))}function Qit(e,t){var n,r;return e.Db>>16==10?e.Cb.ih(e,12,nf,t):(r=go(u(gn((n=u(_n(e,16),26),n||(on(),Ky)),e.Db>>16),18)),e.Cb.ih(e,r.n,r.f,t))}function $h(e){var t;return!(e.Bb&1)&&e.r&&e.r.kh()&&(t=u(e.r,49),e.r=u(Up(e,t),138),e.r!=t&&e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,9,8,t,e.r))),e.r}function wse(e,t,n){var r;return r=ie(re(pa,1),Ao,25,15,[l4e(e,(n1(),pc),t,n),l4e(e,lu,t,n),l4e(e,bc,t,n)]),e.f&&(r[0]=b.Math.max(r[0],r[2]),r[2]=r[0]),r}function mln(e,t){var n,r,s;if(s=dun(e,t),s.c.length!=0)for(aa(s,new PY),n=s.c.length,r=0;r>19,x=t.h>>19,v!=x?x-v:(s=e.h,d=t.h,s!=d?s-d:(r=e.m,h=t.m,r!=h?r-h:(n=e.l,o=t.l,n-o)))}function GH(){GH=pe,S7e=(uz(),Mue),C7e=new dn(A6e,S7e),_7e=(P$(),Lue),T7e=new dn(L6e,_7e),E7e=(LH(),Aue),x7e=new dn(M6e,E7e),k7e=new dn(D6e,(Mn(),!0))}function Z_(e,t,n){var r,s;r=t*n,we(e.g,145)?(s=j6(e),s.f.d?s.f.a||(e.d.a+=r+z1):(e.d.d-=r+z1,e.d.a+=r+z1)):we(e.g,10)&&(e.d.d-=r,e.d.a+=2*r)}function Zit(e,t,n){var r,s,o,h,d;for(s=e[n.g],d=new C(t.d);d.a0?e.g:0),++n;t.b=r,t.e=s}function Jit(e){var t,n,r;if(r=e.b,mGe(e.i,r.length)){for(n=r.length*2,e.b=Me(pue,AI,317,n,0,1),e.c=Me(pue,AI,317,n,0,1),e.f=n-1,e.i=0,t=e.a;t;t=t.c)aI(e,t,t);++e.g}}function Sln(e,t,n,r){var s,o,h,d;for(s=0;sh&&(d=h/r),s>o&&(v=o/s),bd(e,b.Math.min(d,v)),e}function Lln(){pz();var e,t;try{if(t=u(X3e((Ap(),rf),H7),2014),t)return t}catch(n){if(n=ts(n),we(n,102))e=n,Rve((jr(),e));else throw J(n)}return new Y5}function Mln(){zJe();var e,t;try{if(t=u(X3e((Ap(),rf),_b),2024),t)return t}catch(n){if(n=ts(n),we(n,102))e=n,Rve((jr(),e));else throw J(n)}return new bm}function Dln(){pz();var e,t;try{if(t=u(X3e((Ap(),rf),Uh),1941),t)return t}catch(n){if(n=ts(n),we(n,102))e=n,Rve((jr(),e));else throw J(n)}return new KZ}function Iln(e,t,n){var r,s;return s=e.e,e.e=t,e.Db&4&&!(e.Db&1)&&(r=new oa(e,1,4,s,t),n?n.Ei(r):n=r),s!=t&&(t?n=E7(e,nz(e,t),n):n=E7(e,e.a,n)),n}function est(){kF.call(this),this.e=-1,this.a=!1,this.p=$a,this.k=-1,this.c=-1,this.b=-1,this.g=!1,this.f=-1,this.j=-1,this.n=-1,this.i=-1,this.d=-1,this.o=$a}function Oln(e,t){var n,r,s;if(r=e.b.d.d,e.a||(r+=e.b.d.a),s=t.b.d.d,t.a||(s+=t.b.d.a),n=Fs(r,s),n==0){if(!e.a&&t.a)return-1;if(!t.a&&e.a)return 1}return n}function Nln(e,t){var n,r,s;if(r=e.b.b.d,e.a||(r+=e.b.b.a),s=t.b.b.d,t.a||(s+=t.b.b.a),n=Fs(r,s),n==0){if(!e.a&&t.a)return-1;if(!t.a&&e.a)return 1}return n}function Pln(e,t){var n,r,s;if(r=e.b.g.d,e.a||(r+=e.b.g.a),s=t.b.g.d,t.a||(s+=t.b.g.a),n=Fs(r,s),n==0){if(!e.a&&t.a)return-1;if(!t.a&&e.a)return 1}return n}function H3e(){H3e=pe,Spt=il(xi(xi(xi(new Xs,(ro(),Zc),(po(),zEe)),Zc,GEe),Go,qEe),Go,DEe),Lpt=xi(xi(new Xs,Zc,TEe),Zc,IEe),Apt=il(new Xs,Go,NEe)}function Bln(e){var t,n,r,s,o;for(t=u(K(e,(et(),uS)),83),o=e.n,r=t.Cc().Kc();r.Ob();)n=u(r.Pb(),306),s=n.i,s.c+=o.a,s.d+=o.b,n.c?bct(n):vct(n);Ye(e,uS,null)}function Rln(e,t,n){var r,s;switch(s=e.b,r=s.d,t.g){case 1:return-r.d-n;case 2:return s.o.a+r.c+n;case 3:return s.o.b+r.a+n;case 4:return-r.b-n;default:return-1}}function Fln(e){var t,n,r,s,o;if(r=0,s=O7,e.b)for(t=0;t<360;t++)n=t*.017453292519943295,D5e(e,e.d,0,0,_4,n),o=e.b.ig(e.d),o0&&(h=(o&Ei)%e.d.length,s=H4e(e,h,o,t),s)?(d=s.ed(n),d):(r=e.tj(o,t,n),e.c.Fc(r),null)}function q3e(e,t){var n,r,s,o;switch(Ag(e,t)._k()){case 3:case 2:{for(n=b4(t),s=0,o=n.i;s=0;r--)if(an(e[r].d,t)||an(e[r].d,n)){e.length>=r+1&&e.splice(0,r+1);break}return e}function eI(e,t){var n;return Ko(e)&&Ko(t)&&(n=e/t,DI0&&(e.b+=2,e.a+=r):(e.b+=1,e.a+=b.Math.min(r,s))}function ost(e,t){var n,r;if(r=!1,fa(t)&&(r=!0,O6(e,new Bm(Hr(t)))),r||we(t,236)&&(r=!0,O6(e,(n=Xbe(u(t,236)),new lT(n)))),!r)throw J(new Jee(s8e))}function nhn(e,t,n,r){var s,o,h;return s=new N0(e.e,1,10,(h=t.c,we(h,88)?u(h,26):(on(),sf)),(o=n.c,we(o,88)?u(o,26):(on(),sf)),Dg(e,t),!1),r?r.Ei(s):r=s,r}function W3e(e){var t,n;switch(u(K(Ya(e),(pt(),NTe)),420).g){case 0:return t=e.n,n=e.o,new Pt(t.a+n.a/2,t.b+n.b/2);case 1:return new Io(e.n);default:return null}}function tI(){tI=pe,Iq=new HT(U0,0),m9e=new HT("LEFTUP",1),k9e=new HT("RIGHTUP",2),w9e=new HT("LEFTDOWN",3),y9e=new HT("RIGHTDOWN",4),Tle=new HT("BALANCED",5)}function rhn(e,t,n){var r,s,o;if(r=Fs(e.a[t.p],e.a[n.p]),r==0){if(s=u(K(t,(et(),Sk)),15),o=u(K(n,Sk),15),s.Hc(n))return-1;if(o.Hc(t))return 1}return r}function ihn(e){switch(e.g){case 1:return new JQ;case 2:return new eZ;case 3:return new ZQ;case 0:return null;default:throw J(new Ln(wce+(e.f!=null?e.f:""+e.g)))}}function K3e(e,t,n){switch(t){case 1:!e.n&&(e.n=new at(Jo,e,1,7)),_r(e.n),!e.n&&(e.n=new at(Jo,e,1,7)),fs(e.n,u(n,14));return;case 2:I_(e,Hr(n));return}gye(e,t,n)}function Y3e(e,t,n){switch(t){case 3:Hv(e,Ue(ft(n)));return;case 4:zv(e,Ue(ft(n)));return;case 5:Du(e,Ue(ft(n)));return;case 6:Iu(e,Ue(ft(n)));return}K3e(e,t,n)}function VH(e,t,n){var r,s,o;o=(r=new Wee,r),s=$1(o,t,null),s&&s.Fi(),au(o,n),Br((!e.c&&(e.c=new at(Iw,e,12,10)),e.c),o),Cg(o,0),Wm(o,1),Mg(o,!0),Lg(o,!0)}function X3e(e,t){var n,r,s;return n=BT(e.g,t),we(n,235)?(s=u(n,235),s.Qh()==null,s.Nh()):we(n,498)?(r=u(n,1938),s=r.b,s):null}function shn(e,t,n,r){var s,o;return Nr(t),Nr(n),o=u(c_(e.d,t),19),WJe(!!o,"Row %s not in %s",t,e.e),s=u(c_(e.b,n),19),WJe(!!s,"Column %s not in %s",n,e.c),ent(e,o.a,s.a,r)}function cst(e,t,n,r,s,o,h){var d,v,x,_,L;if(_=s[o],x=o==h-1,d=x?r:0,L=Lit(d,_),r!=10&&ie(re(e,h-o),t[o],n[o],d,L),!x)for(++o,v=0;v<_;++v)L[v]=cst(e,t,n,r,s,o,h);return L}function J_(e){if(e.g==-1)throw J(new zu);e.mj();try{e.i.$c(e.g),e.f=e.i.j,e.g1||d==-1?(o=u(v,15),s.Wb(fcn(e,o))):s.Wb(aae(e,u(v,56)))))}function fhn(e,t,n,r){Wze();var s=lue;function o(){for(var h=0;hpce)return n;s>-1e-6&&++n}return n}function J3e(e,t){var n;t!=e.b?(n=null,e.b&&(n=r$(e.b,e,-4,n)),t&&(n=Q6(t,e,-4,n)),n=qnt(e,t,n),n&&n.Fi()):e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,3,t,t))}function hst(e,t){var n;t!=e.f?(n=null,e.f&&(n=r$(e.f,e,-1,n)),t&&(n=Q6(t,e,-1,n)),n=Vnt(e,t,n),n&&n.Fi()):e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,0,t,t))}function fst(e){var t,n,r;if(e==null)return null;if(n=u(e,15),n.dc())return"";for(r=new bg,t=n.Kc();t.Ob();)To(r,(Fi(),Hr(t.Pb()))),r.a+=" ";return qte(r,r.a.length-1)}function dst(e){var t,n,r;if(e==null)return null;if(n=u(e,15),n.dc())return"";for(r=new bg,t=n.Kc();t.Ob();)To(r,(Fi(),Hr(t.Pb()))),r.a+=" ";return qte(r,r.a.length-1)}function yhn(e,t,n){var r,s;return r=e.c[t.c.p][t.p],s=e.c[n.c.p][n.p],r.a!=null&&s.a!=null?Ine(r.a,s.a):r.a!=null?-1:s.a!=null?1:0}function khn(e,t){var n,r,s,o,h,d;if(t)for(o=t.a.length,n=new W2(o),d=(n.b-n.a)*n.c<0?(Lp(),C2):new Op(n);d.Ob();)h=u(d.Pb(),19),s=E8(t,h.a),r=new f$e(e),lJt(r.a,s)}function xhn(e,t){var n,r,s,o,h,d;if(t)for(o=t.a.length,n=new W2(o),d=(n.b-n.a)*n.c<0?(Lp(),C2):new Op(n);d.Ob();)h=u(d.Pb(),19),s=E8(t,h.a),r=new r$e(e),uJt(r.a,s)}function Ehn(e){var t;if(e!=null&&e.length>0&&Ma(e,e.length-1)==33)try{return t=lat(jl(e,0,e.length-1)),t.e==null}catch(n){if(n=ts(n),!we(n,32))throw J(n)}return!1}function gst(e,t,n){var r,s,o;return r=t.ak(),o=t.dd(),s=r.$j()?jp(e,3,r,null,o,y7(e,r,o,we(r,99)&&(u(r,18).Bb&so)!=0),!0):jp(e,1,r,r.zj(),o,-1,!0),n?n.Ei(s):n=s,n}function Thn(){var e,t,n;for(t=0,e=0;e<1;e++){if(n=V4e((zr(e,1),"X".charCodeAt(e))),n==0)throw J(new $r("Unknown Option: "+"X".substr(e)));t|=n}return t}function _hn(e,t,n){var r,s,o;switch(r=Ya(t),s=wH(r),o=new $c,rc(o,t),n.g){case 1:Vs(o,zD(Y6(s)));break;case 2:Vs(o,Y6(s))}return Ye(o,(pt(),Ny),ft(K(e,Ny))),o}function e4e(e){var t,n;return t=u(Pr(new cr(fr(Xo(e.a).a.Kc(),new V))),17),n=u(Pr(new cr(fr(js(e.a).a.Kc(),new V))),17),It(Mt(K(t,(et(),W1))))||It(Mt(K(n,W1)))}function c4(){c4=pe,Tq=new kM("ONE_SIDE",0),Cq=new kM("TWO_SIDES_CORNER",1),Sq=new kM("TWO_SIDES_OPPOSING",2),_q=new kM("THREE_SIDES",3),Eq=new kM("FOUR_SIDES",4)}function xse(e,t,n,r,s){var o,h;o=u(zl(Vi(t.Oc(),new IX),eb(new vt,new Dt,new Hn,ie(re(yl,1),tt,132,0,[(F1(),Ql)]))),15),h=u(rb(e.b,n,r),15),s==0?h.Wc(0,o):h.Gc(o)}function Chn(e,t){var n,r,s,o,h;for(o=new C(t.a);o.a0&&$it(this,this.c-1,(ht(),$n)),this.c0&&e[0].length>0&&(this.c=It(Mt(K(Ya(e[0][0]),(et(),B9e))))),this.a=Me(vwt,Qe,2018,e.length,0,2),this.b=Me(wwt,Qe,2019,e.length,0,2),this.d=new Rnt}function Dhn(e){return e.c.length==0?!1:(xn(0,e.c.length),u(e.c[0],17)).c.i.k==(zn(),ca)?!0:_8(Cu(new vn(null,new mn(e,16)),new oQ),new cQ)}function Ihn(e,t,n){return kr(n,"Tree layout",1),d$(e.b),Xd(e.b,(a7(),fV),fV),Xd(e.b,_S,_S),Xd(e.b,NO,NO),Xd(e.b,CS,CS),e.a=mz(e.b,t),opn(e,t,Kc(n,1)),ur(n),t}function bst(e,t){var n,r,s,o,h,d,v;for(d=oy(t),o=t.f,v=t.g,h=b.Math.sqrt(o*o+v*v),s=0,r=new C(d);r.a=0?(n=eI(e,Lz),r=VD(e,Lz)):(t=Nm(e,1),n=eI(t,5e8),r=VD(t,5e8),r=Ua(A0(r,1),qs(e,1))),I1(A0(r,32),qs(n,yo))}function mst(e,t,n){var r,s;switch(r=(Qn(t.b!=0),u(bh(t,t.a.a),8)),n.g){case 0:r.b=0;break;case 2:r.b=e.f;break;case 3:r.a=0;break;default:r.a=e.g}return s=ii(t,0),YM(s,r),t}function yst(e,t,n,r){var s,o,h,d,v;switch(v=e.b,o=t.d,h=o.j,d=g3e(h,v.d[h.g],n),s=Ni(fc(o.n),o.a),o.j.g){case 1:case 3:d.a+=s.a;break;case 2:case 4:d.b+=s.b}ks(r,d,r.c.b,r.c)}function qhn(e,t,n){var r,s,o,h;for(h=Yo(e.e,t,0),o=new wpe,o.b=n,r=new Ea(e.e,h);r.b1;t>>=1)t&1&&(r=W3(r,n)),n.d==1?n=W3(n,n):n=new qrt(Jct(n.a,n.d,Me(Lr,Jr,25,n.d<<1,15,1)));return r=W3(r,n),r}function o4e(){o4e=pe;var e,t,n,r;for(c7e=Me(pa,Ao,25,25,15,1),u7e=Me(pa,Ao,25,33,15,1),r=152587890625e-16,t=32;t>=0;t--)u7e[t]=r,r*=.5;for(n=1,e=24;e>=0;e--)c7e[e]=n,n*=.5}function Xhn(e){var t,n;if(It(Mt(Ft(e,(pt(),Oy))))){for(n=new cr(fr(z0(e).a.Kc(),new V));Vr(n);)if(t=u(Pr(n),79),ew(t)&&It(Mt(Ft(t,Db))))return!0}return!1}function kst(e,t){var n,r,s;Gs(e.f,t)&&(t.b=e,r=t.c,Yo(e.j,r,0)!=-1||it(e.j,r),s=t.d,Yo(e.j,s,0)!=-1||it(e.j,s),n=t.a.b,n.c.length!=0&&(!e.i&&(e.i=new Jrt(e)),fsn(e.i,n)))}function Qhn(e){var t,n,r,s,o;return n=e.c.d,r=n.j,s=e.d.d,o=s.j,r==o?n.p=0&&an(e.substr(t,3),"GMT")||t>=0&&an(e.substr(t,3),"UTC"))&&(n[0]=t+3),N5e(e,n,r)}function Jhn(e,t){var n,r,s,o,h;for(o=e.g.a,h=e.g.b,r=new C(e.d);r.an;o--)e[o]|=t[o-n-1]>>>h,e[o-1]=t[o-n-1]<=e.f)break;o.c[o.c.length]=n}return o}function u4e(e){var t,n,r,s;for(t=null,s=new C(e.wf());s.a0&&Hc(e.g,t,e.g,t+r,d),h=n.Kc(),e.i+=r,s=0;so&&pZt(x,bet(n[d],a7e))&&(s=d,o=v);return s>=0&&(r[0]=t+o),s}function afn(e,t){var n;if(n=fVe(e.b.Hf(),t.b.Hf()),n!=0)return n;switch(e.b.Hf().g){case 1:case 2:return Tu(e.b.sf(),t.b.sf());case 3:case 4:return Tu(t.b.sf(),e.b.sf())}return 0}function ofn(e){var t,n,r;for(r=e.e.c.length,e.a=U2(Lr,[Qe,Jr],[48,25],15,[r,r],2),n=new C(e.c);n.a>4&15,o=e[r]&15,h[s++]=_Ae[n],h[s++]=_Ae[o];return jh(h,0,h.length)}function lfn(e,t,n){var r,s,o;return r=t.ak(),o=t.dd(),s=r.$j()?jp(e,4,r,o,null,y7(e,r,o,we(r,99)&&(u(r,18).Bb&so)!=0),!0):jp(e,r.Kj()?2:1,r,o,r.zj(),-1,!0),n?n.Ei(s):n=s,n}function Nu(e){var t,n;return e>=so?(t=II+(e-so>>10&1023)&Ss,n=56320+(e-so&1023)&Ss,String.fromCharCode(t)+(""+String.fromCharCode(n))):String.fromCharCode(e&Ss)}function hfn(e,t){Mm();var n,r,s,o;return s=u(u(Ii(e.r,t),21),84),s.gc()>=2?(r=u(s.Kc().Pb(),111),n=e.u.Hc((ol(),GS)),o=e.u.Hc($k),!r.a&&!n&&(s.gc()==2||o)):!1}function Tst(e,t,n,r,s){var o,h,d;for(o=oct(e,t,n,r,s),d=!1;!o;)ez(e,s,!0),d=!0,o=oct(e,t,n,r,s);d&&ez(e,s,!1),h=hie(s),h.c.length!=0&&(e.d&&e.d.lg(h),Tst(e,s,n,r,h))}function YH(){YH=pe,dfe=new WT(U0,0),JSe=new WT("DIRECTED",1),tAe=new WT("UNDIRECTED",2),QSe=new WT("ASSOCIATION",3),eAe=new WT("GENERALIZATION",4),ZSe=new WT("DEPENDENCY",5)}function ffn(e,t){var n;if(!L1(e))throw J(new Wo(m1t));switch(n=L1(e),t.g){case 1:return-(e.j+e.f);case 2:return e.i-n.g;case 3:return e.j-n.f;case 4:return-(e.i+e.g)}return 0}function l7(e,t){var n,r;for(Sn(t),r=e.b.c.length,it(e.b,t);r>0;){if(n=r,r=(r-1)/2|0,e.a.ue(St(e.b,r),t)<=0)return gh(e.b,n,t),!0;gh(e.b,n,St(e.b,r))}return gh(e.b,r,t),!0}function l4e(e,t,n,r){var s,o;if(s=0,n)s=dH(e.a[n.g][t.g],r);else for(o=0;o=d)}function h4e(e,t,n,r){var s;if(s=!1,fa(r)&&(s=!0,f8(t,n,Hr(r))),s||Cm(r)&&(s=!0,h4e(e,t,n,r)),s||we(r,236)&&(s=!0,Y2(t,n,u(r,236))),!s)throw J(new Jee(s8e))}function gfn(e,t){var n,r,s;if(n=t.Hh(e.a),n&&(s=r1((!n.b&&(n.b=new Ml((on(),oo),wc,n)),n.b),Vh),s!=null)){for(r=1;r<(Yu(),YAe).length;++r)if(an(YAe[r],s))return r}return 0}function pfn(e,t){var n,r,s;if(n=t.Hh(e.a),n&&(s=r1((!n.b&&(n.b=new Ml((on(),oo),wc,n)),n.b),Vh),s!=null)){for(r=1;r<(Yu(),XAe).length;++r)if(an(XAe[r],s))return r}return 0}function _st(e,t){var n,r,s,o;if(Sn(t),o=e.a.gc(),o0?1:0;o.a[s]!=n;)o=o.a[s],s=e.a.ue(n.d,o.d)>0?1:0;o.a[s]=r,r.b=n.b,r.a[0]=n.a[0],r.a[1]=n.a[1],n.a[0]=null,n.a[1]=null}function wfn(e){ol();var t,n;return t=Ui(Z0,ie(re(jV,1),tt,273,0,[m2])),!(SD(a$(t,e))>1||(n=Ui(GS,ie(re(jV,1),tt,273,0,[zS,$k])),SD(a$(n,e))>1))}function d4e(e,t){var n;n=Uc((Ap(),rf),e),we(n,498)?Oo(rf,e,new zqe(this,t)):Oo(rf,e,this),Lse(this,t),t==(Qx(),RAe)?(this.wb=u(this,1939),u(t,1941)):this.wb=(Rp(),En)}function mfn(e){var t,n,r;if(e==null)return null;for(t=null,n=0;n=Pg?"error":r>=900?"warn":r>=800?"info":"log"),uYe(n,e.a),e.b&&d5e(t,n,e.b,"Exception: ",!0))}function K(e,t){var n,r;return r=(!e.q&&(e.q=new Mr),er(e.q,t)),r??(n=t.wg(),we(n,4)&&(n==null?(!e.q&&(e.q=new Mr),z6(e.q,t)):(!e.q&&(e.q=new Mr),Si(e.q,t,n))),n)}function ro(){ro=pe,Pd=new yM("P1_CYCLE_BREAKING",0),c2=new yM("P2_LAYERING",1),bu=new yM("P3_NODE_ORDERING",2),Zc=new yM("P4_NODE_PLACEMENT",3),Go=new yM("P5_EDGE_ROUTING",4)}function Lst(e,t){var n,r,s,o,h;for(s=t==1?Kue:Wue,r=s.a.ec().Kc();r.Ob();)for(n=u(r.Pb(),103),h=u(Ii(e.f.c,n),21).Kc();h.Ob();)o=u(h.Pb(),46),Au(e.b.b,o.b),Au(e.b.a,u(o.b,81).d)}function yfn(e,t){M_();var n;if(e.c==t.c){if(e.b==t.b||Vin(e.b,t.b)){if(n=eWt(e.b)?1:-1,e.a&&!t.a)return n;if(!e.a&&t.a)return-n}return Tu(e.b.g,t.b.g)}else return Fs(e.c,t.c)}function kfn(e,t){var n;kr(t,"Hierarchical port position processing",1),n=e.b,n.c.length>0&&Kct((xn(0,n.c.length),u(n.c[0],29)),e),n.c.length>1&&Kct(u(St(n,n.c.length-1),29),e),ur(t)}function Mst(e,t){var n,r,s;if(p4e(e,t))return!0;for(r=new C(t);r.a=s||t<0)throw J(new Do(qce+t+Eb+s));if(n>=s||n<0)throw J(new Do(Vce+n+Eb+s));return t!=n?r=(o=e.Ti(n),e.Hi(t,o),o):r=e.Oi(n),r}function Ost(e){var t,n,r;if(r=e,e)for(t=0,n=e.Ug();n;n=n.Ug()){if(++t>ioe)return Ost(n);if(r=n,n==e)throw J(new Wo("There is a cycle in the containment hierarchy of "+e))}return r}function Yp(e){var t,n,r;for(r=new ib(io,"[","]"),n=e.Kc();n.Ob();)t=n.Pb(),O0(r,je(t)===je(e)?"(this Collection)":t==null?Pu:Qo(t));return r.a?r.e.length==0?r.a.a:r.a.a+(""+r.e):r.c}function p4e(e,t){var n,r;if(r=!1,t.gc()<2)return!1;for(n=0;nr&&(zr(t-1,e.length),e.charCodeAt(t-1)<=32);)--t;return r>0||t1&&(e.j.b+=e.e)):(e.j.a+=n.a,e.j.b=b.Math.max(e.j.b,n.b),e.d.c.length>1&&(e.j.a+=e.e))}function Xp(){Xp=pe,d2t=ie(re(ao,1),Dc,61,0,[(ht(),An),$n,xr]),f2t=ie(re(ao,1),Dc,61,0,[$n,xr,Dn]),g2t=ie(re(ao,1),Dc,61,0,[xr,Dn,An]),p2t=ie(re(ao,1),Dc,61,0,[Dn,An,$n])}function Efn(e,t,n,r){var s,o,h,d,v,x,_;if(h=e.c.d,d=e.d.d,h.j!=d.j)for(_=e.b,s=h.j,v=null;s!=d.j;)v=t==0?vH(s):Fye(s),o=g3e(s,_.d[s.g],n),x=g3e(v,_.d[v.g],n),ci(r,Ni(o,x)),s=v}function Tfn(e,t,n,r){var s,o,h,d,v;return h=Hit(e.a,t,n),d=u(h.a,19).a,o=u(h.b,19).a,r&&(v=u(K(t,(et(),cl)),10),s=u(K(n,cl),10),v&&s&&(VQe(e.b,v,s),d+=e.b.i,o+=e.b.e)),d>o}function Pst(e){var t,n,r,s,o,h,d,v,x;for(this.a=lit(e),this.b=new st,n=e,r=0,s=n.length;rane(e.d).c?(e.i+=e.g.c,Vie(e.d)):ane(e.d).c>ane(e.g).c?(e.e+=e.d.c,Vie(e.g)):(e.i+=lKe(e.g),e.e+=lKe(e.d),Vie(e.g),Vie(e.d))}function Sfn(e,t,n){var r,s,o,h;for(o=t.q,h=t.r,new X2((Jf(),d2),t,o,1),new X2(d2,o,h,1),s=new C(n);s.ad&&(v=d/r),s>o&&(x=o/s),h=b.Math.min(v,x),e.a+=h*(t.a-e.a),e.b+=h*(t.b-e.b)}function Dfn(e,t,n,r,s){var o,h;for(h=!1,o=u(St(n.b,0),33);Ubn(e,t,o,r,s)&&(h=!0,lhn(n,o),n.b.c.length!=0);)o=u(St(n.b,0),33);return n.b.c.length==0&&JD(n.j,n),h&&$H(t.q),h}function Ifn(e,t){g4();var n,r,s,o;if(t.b<2)return!1;for(o=ii(t,0),n=u(ri(o),8),r=n;o.b!=o.d.c;){if(s=u(ri(o),8),Kse(e,r,s))return!0;r=s}return!!Kse(e,r,n)}function v4e(e,t,n,r){var s,o;return n==0?(!e.o&&(e.o=new Nl((cu(),k2),Dw,e,0)),vj(e.o,t,r)):(o=u(gn((s=u(_n(e,16),26),s||e.zh()),n),66),o.Nj().Rj(e,du(e),n-Jn(e.zh()),t,r))}function Lse(e,t){var n;t!=e.sb?(n=null,e.sb&&(n=u(e.sb,49).ih(e,1,US,n)),t&&(n=u(t,49).gh(e,1,US,n)),n=Dye(e,t,n),n&&n.Fi()):e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,4,t,t))}function Ofn(e,t){var n,r,s,o;if(t)s=B0(t,"x"),n=new u$e(e),O8(n.a,(Sn(s),s)),o=B0(t,"y"),r=new l$e(e),P8(r.a,(Sn(o),o));else throw J(new dd("All edge sections need an end point."))}function Nfn(e,t){var n,r,s,o;if(t)s=B0(t,"x"),n=new a$e(e),N8(n.a,(Sn(s),s)),o=B0(t,"y"),r=new o$e(e),B8(r.a,(Sn(o),o));else throw J(new dd("All edge sections need a start point."))}function Pfn(e,t){var n,r,s,o,h,d,v;for(r=knt(e),o=0,d=r.length;o>22-t,s=e.h<>22-t):t<44?(n=0,r=e.l<>44-t):(n=0,r=0,s=e.l<e)throw J(new Ln("k must be smaller than n"));return t==0||t==e?1:e==0?0:V3e(e)/(V3e(t)*V3e(e-t))}function w4e(e,t){var n,r,s,o;for(n=new H2e(e);n.g==null&&!n.c?ywe(n):n.g==null||n.i!=0&&u(n.g[n.i-1],47).Ob();)if(o=u(tz(n),56),we(o,160))for(r=u(o,160),s=0;s>4],t[n*2+1]=iU[o&15];return jh(t,0,t.length)}function Zfn(e){Uj();var t,n,r;switch(r=e.c.length,r){case 0:return k0t;case 1:return t=u(_at(new C(e)),42),xQt(t.cd(),t.dd());default:return n=u(j1(e,Me(Cb,Sz,42,e.c.length,0,1)),165),new Qee(n)}}function Jfn(e){var t,n,r,s,o,h;for(t=new L3,n=new L3,$p(t,e),$p(n,e);n.b!=n.c;)for(s=u(I6(n),37),h=new C(s.a);h.a0&&bI(e,n,t),s):Pdn(e,t,n)}function Gst(e,t,n){var r,s,o,h;if(t.b!=0){for(r=new as,h=ii(t,0);h.b!=h.d.c;)o=u(ri(h),86),no(r,eye(o)),s=o.e,s.a=u(K(o,(Tc(),Che)),19).a,s.b=u(K(o,F_e),19).a;Gst(e,r,Kc(n,r.b/e.a|0))}}function qst(e,t){var n,r,s,o,h;if(e.e<=t||otn(e,e.g,t))return e.g;for(o=e.r,r=e.g,h=e.r,s=(o-r)/2+r;r+11&&(e.e.b+=e.a)):(e.e.a+=n.a,e.e.b=b.Math.max(e.e.b,n.b),e.d.c.length>1&&(e.e.a+=e.a))}function i1n(e){var t,n,r,s;switch(s=e.i,t=s.b,r=s.j,n=s.g,s.a.g){case 0:n.a=(e.g.b.o.a-r.a)/2;break;case 1:n.a=t.d.n.a+t.d.a.a;break;case 2:n.a=t.d.n.a+t.d.a.a-r.a;break;case 3:n.b=t.d.n.b+t.d.a.b}}function Vst(e,t,n,r,s){if(rr&&(e.a=r),e.bs&&(e.b=s),e}function s1n(e){if(we(e,149))return Ngn(u(e,149));if(we(e,229))return Don(u(e,229));if(we(e,23))return Ffn(u(e,23));throw J(new Ln(a8e+Yp(new Al(ie(re(Yn,1),yt,1,5,[e])))))}function a1n(e,t,n,r,s){var o,h,d;for(o=!0,h=0;h>>s|n[h+r+1]<>>s,++h}return o}function x4e(e,t,n,r){var s,o,h;if(t.k==(zn(),ca)){for(o=new cr(fr(Xo(t).a.Kc(),new V));Vr(o);)if(s=u(Pr(o),17),h=s.c.i.k,h==ca&&e.c.a[s.c.i.c.p]==r&&e.c.a[t.c.p]==n)return!0}return!1}function o1n(e,t){var n,r,s,o;return t&=63,n=e.h&V0,t<22?(o=n>>>t,s=e.m>>t|n<<22-t,r=e.l>>t|e.m<<22-t):t<44?(o=0,s=n>>>t-22,r=e.m>>t-22|e.h<<44-t):(o=0,s=0,r=n>>>t-44),fu(r&ml,s&ml,o&V0)}function Ust(e,t,n,r){var s;this.b=r,this.e=e==(Gv(),xS),s=t[n],this.d=U2(El,[Qe,c0],[177,25],16,[s.length,s.length],2),this.a=U2(Lr,[Qe,Jr],[48,25],15,[s.length,s.length],2),this.c=new i4e(t,n)}function c1n(e){var t,n,r;for(e.k=new Twe((ht(),ie(re(ao,1),Dc,61,0,[uc,An,$n,xr,Dn])).length,e.j.c.length),r=new C(e.j);r.a=n)return f7(e,t,r.p),!0;return!1}function Kst(e){var t;return e.Db&64?Mse(e):(t=new Fl(Yxe),!e.a||Yr(Yr((t.a+=' "',t),e.a),'"'),Yr(bv(Yr(bv(Yr(bv(Yr(bv((t.a+=" (",t),e.i),","),e.j)," | "),e.g),","),e.f),")"),t.a)}function Yst(e,t,n){var r,s,o,h,d;for(d=pu(e.e.Tg(),t),s=u(e.g,119),r=0,h=0;hn?M4e(e,n,"start index"):t<0||t>n?M4e(t,n,"end index"):oC("end index (%s) must not be less than start index (%s)",ie(re(Yn,1),yt,1,5,[ct(t),ct(e)]))}function Qst(e,t){var n,r,s,o;for(r=0,s=e.length;r0&&Zst(e,o,n));t.p=0}function Vt(e){var t;this.c=new as,this.f=e.e,this.e=e.d,this.i=e.g,this.d=e.c,this.b=e.b,this.k=e.j,this.a=e.a,e.i?this.j=e.i:this.j=(t=u(Qf(Ug),9),new hh(t,u(wf(t,t.length),9),0)),this.g=e.f}function g1n(e){var t,n,r,s;for(t=Bp(Yr(new Fl("Predicates."),"and"),40),n=!0,s=new c6(e);s.b0?d[h-1]:Me(h0,Bg,10,0,0,1),s=d[h],x=h=0?e.Bh(s):P4e(e,r);else throw J(new Ln(i2+r.ne()+RC));else throw J(new Ln(M1t+t+D1t));else wh(e,n,r)}function E4e(e){var t,n;if(n=null,t=!1,we(e,204)&&(t=!0,n=u(e,204).a),t||we(e,258)&&(t=!0,n=""+u(e,258).a),t||we(e,483)&&(t=!0,n=""+u(e,483).a),!t)throw J(new Jee(s8e));return n}function nat(e,t){var n,r;if(e.f){for(;t.Ob();)if(n=u(t.Pb(),72),r=n.ak(),we(r,99)&&u(r,18).Bb&_c&&(!e.e||r.Gj()!=AE||r.aj()!=0)&&n.dd()!=null)return t.Ub(),!0;return!1}else return t.Ob()}function rat(e,t){var n,r;if(e.f){for(;t.Sb();)if(n=u(t.Ub(),72),r=n.ak(),we(r,99)&&u(r,18).Bb&_c&&(!e.e||r.Gj()!=AE||r.aj()!=0)&&n.dd()!=null)return t.Pb(),!0;return!1}else return t.Sb()}function T4e(e,t,n){var r,s,o,h,d,v;for(v=pu(e.e.Tg(),t),r=0,d=e.i,s=u(e.g,119),h=0;h1&&(t.c[t.c.length]=o))}function w1n(e){var t,n,r,s;for(n=new as,no(n,e.o),r=new mpe;n.b!=0;)t=u(n.b==0?null:(Qn(n.b!=0),bh(n,n.a.a)),508),s=Blt(e,t,!0),s&&it(r.a,t);for(;r.a.c.length!=0;)t=u(Lnt(r),508),Blt(e,t,!1)}function Ng(){Ng=pe,rSe=new x6(EC,0),za=new x6("BOOLEAN",1),Cc=new x6("INT",2),kE=new x6("STRING",3),qo=new x6("DOUBLE",4),vs=new x6("ENUM",5),Pk=new x6("ENUMSET",6),Y1=new x6("OBJECT",7)}function tC(e,t){var n,r,s,o,h;r=b.Math.min(e.c,t.c),o=b.Math.min(e.d,t.d),s=b.Math.max(e.c+e.b,t.c+t.b),h=b.Math.max(e.d+e.a,t.d+t.a),s=(s/2|0))for(this.e=r?r.c:null,this.d=s;n++0;)kwe(this);this.b=t,this.a=null}function k1n(e,t){var n,r;t.a?qgn(e,t):(n=u(hne(e.b,t.b),57),n&&n==e.a[t.b.f]&&n.a&&n.a!=t.b.a&&n.c.Fc(t.b),r=u(lne(e.b,t.b),57),r&&e.a[r.f]==t.b&&r.a&&r.a!=t.b.a&&t.b.c.Fc(r),Zte(e.b,t.b))}function sat(e,t){var n,r;if(n=u(_o(e.b,t),124),u(u(Ii(e.r,t),21),84).dc()){n.n.b=0,n.n.c=0;return}n.n.b=e.C.b,n.n.c=e.C.c,e.A.Hc((Bl(),Hb))&&Lct(e,t),r=Qcn(e,t),Xse(e,t)==(n4(),v2)&&(r+=2*e.w),n.a.a=r}function aat(e,t){var n,r;if(n=u(_o(e.b,t),124),u(u(Ii(e.r,t),21),84).dc()){n.n.d=0,n.n.a=0;return}n.n.d=e.C.d,n.n.a=e.C.a,e.A.Hc((Bl(),Hb))&&Mct(e,t),r=Zcn(e,t),Xse(e,t)==(n4(),v2)&&(r+=2*e.w),n.a.b=r}function x1n(e,t){var n,r,s,o;for(o=new st,r=new C(t);r.an.a&&(r.Hc((ty(),HO))?s=(t.a-n.a)/2:r.Hc(zO)&&(s=t.a-n.a)),t.b>n.b&&(r.Hc((ty(),qO))?o=(t.b-n.b)/2:r.Hc(GO)&&(o=t.b-n.b)),f4e(e,s,o)}function gat(e,t,n,r,s,o,h,d,v,x,_,L,P){we(e.Cb,88)&&iy(dl(u(e.Cb,88)),4),au(e,n),e.f=h,e7(e,d),n7(e,v),J8(e,x),t7(e,_),Mg(e,L),r7(e,P),Lg(e,!0),Cg(e,s),e.ok(o),cb(e,t),r!=null&&(e.i=null,X$(e,r))}function pat(e){var t,n;if(e.f){for(;e.n>0;){if(t=u(e.k.Xb(e.n-1),72),n=t.ak(),we(n,99)&&u(n,18).Bb&_c&&(!e.e||n.Gj()!=AE||n.aj()!=0)&&t.dd()!=null)return!0;--e.n}return!1}else return e.n>0}function M4e(e,t,n){if(e<0)return oC(Jlt,ie(re(Yn,1),yt,1,5,[n,ct(e)]));if(t<0)throw J(new Ln(eht+t));return oC("%s (%s) must not be greater than size (%s)",ie(re(Yn,1),yt,1,5,[n,ct(e),ct(t)]))}function D4e(e,t,n,r,s,o){var h,d,v,x;if(h=r-n,h<7){yon(t,n,r,o);return}if(v=n+s,d=r+s,x=v+(d-v>>1),D4e(t,e,v,x,-s,o),D4e(t,e,x,d,-s,o),o.ue(e[x-1],e[x])<=0){for(;n=0?e.sh(o,n):o5e(e,s,n);else throw J(new Ln(i2+s.ne()+RC));else throw J(new Ln(M1t+t+D1t));else yh(e,r,s,n)}function bat(e){var t,n,r,s;if(n=u(e,49).qh(),n)try{if(r=null,t=p7((Ap(),rf),Zct(Eon(n))),t&&(s=t.rh(),s&&(r=s.Wk(DVt(n.e)))),r&&r!=e)return bat(r)}catch(o){if(o=ts(o),!we(o,60))throw J(o)}return e}function gu(e,t,n){var r,s,o,h;if(h=t==null?0:e.b.se(t),s=(r=e.a.get(h),r??new Array),s.length==0)e.a.set(h,s);else if(o=Int(e,t,s),o)return o.ed(n);return cs(s,s.length,new OF(t,n)),++e.c,t$(e.b),null}function vat(e,t){var n,r;return d$(e.a),Xd(e.a,(J$(),mV),mV),Xd(e.a,yE,yE),r=new Xs,xi(r,yE,(yH(),Dhe)),je(Ft(t,(Jm(),Nhe)))!==je((RD(),yV))&&xi(r,yE,Lhe),xi(r,yE,Mhe),pVe(e.a,r),n=mz(e.a,t),n}function wat(e){if(!e)return JHe(),M0t;var t=e.valueOf?e.valueOf():e;if(t!==e){var n=yue[typeof t];return n?n(t):Eye(typeof t)}else return e instanceof Array||e instanceof b.Array?new a6(e):new $x(e)}function mat(e,t,n){var r,s,o;switch(o=e.o,r=u(_o(e.p,n),244),s=r.i,s.b=cI(r),s.a=oI(r),s.b=b.Math.max(s.b,o.a),s.b>o.a&&!t&&(s.b=o.a),s.c=-(s.b-o.a)/2,n.g){case 1:s.d=-s.a;break;case 3:s.d=o.b}uae(r),lae(r)}function yat(e,t,n){var r,s,o;switch(o=e.o,r=u(_o(e.p,n),244),s=r.i,s.b=cI(r),s.a=oI(r),s.a=b.Math.max(s.a,o.b),s.a>o.b&&!t&&(s.a=o.b),s.d=-(s.a-o.b)/2,n.g){case 4:s.c=-s.b;break;case 2:s.c=o.a}uae(r),lae(r)}function R1n(e,t){var n,r,s,o,h;if(!t.dc()){if(s=u(t.Xb(0),128),t.gc()==1){Wot(e,s,s,1,0,t);return}for(n=1;n0)try{s=Wl(t,$a,Ei)}catch(o){throw o=ts(o),we(o,127)?(r=o,J(new D$(r))):J(o)}return n=(!e.a&&(e.a=new $ee(e)),e.a),s=0?u(Te(n,s),56):null}function H1n(e,t){if(e<0)return oC(Jlt,ie(re(Yn,1),yt,1,5,["index",ct(e)]));if(t<0)throw J(new Ln(eht+t));return oC("%s (%s) must be less than size (%s)",ie(re(Yn,1),yt,1,5,["index",ct(e),ct(t)]))}function z1n(e){var t,n,r,s,o;if(e==null)return Pu;for(o=new ib(io,"[","]"),n=e,r=0,s=n.length;r0)for(h=e.c.d,d=e.d.d,s=bd(da(new Pt(d.a,d.b),h),1/(r+1)),o=new Pt(h.a,h.b),n=new C(e.a);n.a=0?e._g(n,!0,!0):tw(e,s,!0),153)),u(r,215).ol(t);else throw J(new Ln(i2+t.ne()+RC))}function B4e(e){var t,n;return e>-0x800000000000&&e<0x800000000000?e==0?0:(t=e<0,t&&(e=-e),n=_s(b.Math.floor(b.Math.log(e)/.6931471805599453)),(!t||e!=b.Math.pow(2,n))&&++n,n):Utt(Ou(e))}function tdn(e){var t,n,r,s,o,h,d;for(o=new C0,n=new C(e);n.a2&&d.e.b+d.j.b<=2&&(s=d,r=h),o.a.zc(s,o),s.q=r);return o}function Aat(e,t){var n,r,s;return r=new H0(e),Ho(r,t),Ye(r,(et(),jq),t),Ye(r,(pt(),bs),(wa(),tu)),Ye(r,Bd,(t0(),MV)),T0(r,(zn(),Ls)),n=new $c,rc(n,r),Vs(n,(ht(),Dn)),s=new $c,rc(s,r),Vs(s,$n),r}function Lat(e){switch(e.g){case 0:return new ete((Gv(),IO));case 1:return new AR;case 2:return new ZJ;default:throw J(new Ln("No implementation is available for the crossing minimizer "+(e.f!=null?e.f:""+e.g)))}}function Mat(e,t){var n,r,s,o,h;for(e.c[t.p]=!0,it(e.a,t),h=new C(t.j);h.a=o)h.$b();else for(s=h.Kc(),r=0;r0?Npe():h<0&&Nat(e,t,-h),!0):!1}function oI(e){var t,n,r,s,o,h,d;if(d=0,e.b==0){for(h=bit(e,!0),t=0,r=h,s=0,o=r.length;s0&&(d+=n,++t);t>1&&(d+=e.c*(t-1))}else d=oze(ytt(Kj(Vi(Rne(e.a),new Ta),new _a)));return d>0?d+e.n.d+e.n.a:0}function cI(e){var t,n,r,s,o,h,d;if(d=0,e.b==0)d=oze(ytt(Kj(Vi(Rne(e.a),new Ms),new Pa)));else{for(h=vit(e,!0),t=0,r=h,s=0,o=r.length;s0&&(d+=n,++t);t>1&&(d+=e.c*(t-1))}return d>0?d+e.n.b+e.n.c:0}function udn(e,t){var n,r,s,o;for(o=u(_o(e.b,t),124),n=o.a,s=u(u(Ii(e.r,t),21),84).Kc();s.Ob();)r=u(s.Pb(),111),r.c&&(n.a=b.Math.max(n.a,kve(r.c)));if(n.a>0)switch(t.g){case 2:o.n.c=e.s;break;case 4:o.n.b=e.s}}function ldn(e,t){var n,r,s;return n=u(K(t,(a1(),Q7)),19).a-u(K(e,Q7),19).a,n==0?(r=da(fc(u(K(e,(zp(),fO)),8)),u(K(e,eS),8)),s=da(fc(u(K(t,fO),8)),u(K(t,eS),8)),Fs(r.a*r.b,s.a*s.b)):n}function hdn(e,t){var n,r,s;return n=u(K(t,(nw(),wV)),19).a-u(K(e,wV),19).a,n==0?(r=da(fc(u(K(e,(Tc(),PO)),8)),u(K(e,SS),8)),s=da(fc(u(K(t,PO),8)),u(K(t,SS),8)),Fs(r.a*r.b,s.a*s.b)):n}function Pat(e){var t,n;return n=new Tp,n.a+="e_",t=ysn(e),t!=null&&(n.a+=""+t),e.c&&e.d&&(Yr((n.a+=" ",n),zH(e.c)),Yr(Ec((n.a+="[",n),e.c.i),"]"),Yr((n.a+=Ioe,n),zH(e.d)),Yr(Ec((n.a+="[",n),e.d.i),"]")),n.a}function Bat(e){switch(e.g){case 0:return new UL;case 1:return new XJ;case 2:return new YJ;case 3:return new LR;default:throw J(new Ln("No implementation is available for the layout phase "+(e.f!=null?e.f:""+e.g)))}}function F4e(e,t,n,r,s){var o;switch(o=0,s.g){case 1:o=b.Math.max(0,t.b+e.b-(n.b+r));break;case 3:o=b.Math.max(0,-e.b-r);break;case 2:o=b.Math.max(0,-e.a-r);break;case 4:o=b.Math.max(0,t.a+e.a-(n.a+r))}return o}function fdn(e,t,n){var r,s,o,h,d;if(n)for(s=n.a.length,r=new W2(s),d=(r.b-r.a)*r.c<0?(Lp(),C2):new Op(r);d.Ob();)h=u(d.Pb(),19),o=E8(n,h.a),Jxe in o.a||zce in o.a?E2n(e,o,t):Lyn(e,o,t),XWt(u(er(e.b,i7(o)),79))}function j4e(e){var t,n;switch(e.b){case-1:return!0;case 0:return n=e.t,n>1||n==-1?(e.b=-1,!0):(t=$h(e),t&&(ho(),t.Cj()==Idt)?(e.b=-1,!0):(e.b=1,!1));default:case 1:return!1}}function ddn(e,t){var n,r,s,o,h;for(r=(!t.s&&(t.s=new at(ju,t,21,17)),t.s),o=null,s=0,h=r.i;s=0&&r=0?e._g(n,!0,!0):tw(e,s,!0),153)),u(r,215).ll(t);throw J(new Ln(i2+t.ne()+Oce))}function wdn(){t2e();var e;return v4t?u(p7((Ap(),rf),Uh),1939):(ui(Cb,new Uf),Jwn(),e=u(we(Uc((Ap(),rf),Uh),547)?Uc(rf,Uh):new yYe,547),v4t=!0,Yyn(e),e3n(e),Si((e2e(),BAe),e,new YZ),Oo(rf,Uh,e),e)}function mdn(e,t){var n,r,s,o;e.j=-1,Ll(e.e)?(n=e.i,o=e.i!=0,cD(e,t),r=new N0(e.e,3,e.c,null,t,n,o),s=t.Qk(e.e,e.c,null),s=gst(e,t,s),s?(s.Ei(r),s.Fi()):_i(e.e,r)):(cD(e,t),s=t.Qk(e.e,e.c,null),s&&s.Fi())}function ZH(e,t){var n,r,s;if(s=0,r=t[0],r>=e.length)return-1;for(n=(zr(r,e.length),e.charCodeAt(r));n>=48&&n<=57&&(s=s*10+(n-48),++r,!(r>=e.length));)n=(zr(r,e.length),e.charCodeAt(r));return r>t[0]?t[0]=r:s=-1,s}function ydn(e){var t,n,r,s,o;return s=u(e.a,19).a,o=u(e.b,19).a,n=s,r=o,t=b.Math.max(b.Math.abs(s),b.Math.abs(o)),s<=0&&s==o?(n=0,r=o-1):s==-t&&o!=t?(n=o,r=s,o>=0&&++n):(n=-o,r=s),new xa(ct(n),ct(r))}function kdn(e,t,n,r){var s,o,h,d,v,x;for(s=0;s=0&&x>=0&&v=e.i)throw J(new Do(qce+t+Eb+e.i));if(n>=e.i)throw J(new Do(Vce+n+Eb+e.i));return r=e.g[n],t!=n&&(t>16),t=r>>16&16,n=16-t,e=e>>t,r=e-256,t=r>>16&8,n+=t,e<<=t,r=e-dy,t=r>>16&4,n+=t,e<<=t,r=e-Ed,t=r>>16&2,n+=t,e<<=t,r=e>>14,t=r&~(r>>1),n+2-t)}function Edn(e){P6();var t,n,r,s;for(QG=new st,jue=new Mr,Fue=new st,t=(!e.a&&(e.a=new at(hs,e,10,11)),e.a),tyn(t),s=new rr(t);s.e!=s.i.gc();)r=u(pr(s),33),Yo(QG,r,0)==-1&&(n=new st,it(Fue,n),Krt(r,n));return Fue}function Tdn(e,t,n){var r,s,o,h;e.a=n.b.d,we(t,352)?(s=d4(u(t,79),!1,!1),o=iI(s),r=new Ba(e),Da(o,r),mI(o,s),t.We((bi(),Z4))!=null&&Da(u(t.We(Z4),74),r)):(h=u(t,470),h.Hg(h.Dg()+e.a.a),h.Ig(h.Eg()+e.a.b))}function Fat(e,t){var n,r,s,o,h,d,v,x;for(x=Ue(ft(K(t,(pt(),bS)))),v=e[0].n.a+e[0].o.a+e[0].d.c+x,d=1;d=0?n:(d=w_(da(new Pt(h.c+h.b/2,h.d+h.a/2),new Pt(o.c+o.b/2,o.d+o.a/2))),-(aut(o,h)-1)*d)}function Cdn(e,t,n){var r;ms(new vn(null,(!n.a&&(n.a=new at(os,n,6,6)),new mn(n.a,16))),new yqe(e,t)),ms(new vn(null,(!n.n&&(n.n=new at(Jo,n,1,7)),new mn(n.n,16))),new kqe(e,t)),r=u(Ft(n,(bi(),Z4)),74),r&&qme(r,e,t)}function tw(e,t,n){var r,s,o;if(o=v4((Yu(),Oa),e.Tg(),t),o)return ho(),u(o,66).Oj()||(o=F6(Po(Oa,o))),s=(r=e.Yg(o),u(r>=0?e._g(r,!0,!0):tw(e,o,!0),153)),u(s,215).hl(t,n);throw J(new Ln(i2+t.ne()+Oce))}function H4e(e,t,n,r){var s,o,h,d,v;if(s=e.d[t],s){if(o=s.g,v=s.i,r!=null){for(d=0;d=n&&(r=t,x=(v.c+v.a)/2,h=x-n,v.c<=x-n&&(s=new vne(v.c,h),Om(e,r++,s)),d=x+n,d<=v.a&&(o=new vne(d,v.a),jm(r,e.c.length),RT(e.c,r,o)))}function z4e(e){var t;if(!e.c&&e.g==null)e.d=e.si(e.f),Br(e,e.d),t=e.d;else{if(e.g==null)return!0;if(e.i==0)return!1;t=u(e.g[e.i-1],47)}return t==e.b&&null.km>=null.jm()?(tz(e),z4e(e)):t.Ob()}function Mdn(e,t,n){var r,s,o,h,d;if(d=n,!d&&(d=mve(new Ux,0)),kr(d,tft,1),alt(e.c,t),h=qwn(e.a,t),h.gc()==1)zut(u(h.Xb(0),37),d);else for(o=1/h.gc(),s=h.Kc();s.Ob();)r=u(s.Pb(),37),zut(r,Kc(d,o));FVt(e.a,h,t),qpn(t),ur(d)}function Hat(e){if(this.a=e,e.c.i.k==(zn(),Ls))this.c=e.c,this.d=u(K(e.c.i,(et(),vc)),61);else if(e.d.i.k==Ls)this.c=e.d,this.d=u(K(e.d.i,(et(),vc)),61);else throw J(new Ln("Edge "+e+" is not an external edge."))}function zat(e,t){var n,r,s;s=e.b,e.b=t,e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,3,s,e.b)),t?t!=e&&(au(e,t.zb),Qre(e,t.d),n=(r=t.c,r??t.zb),Jre(e,n==null||an(n,t.zb)?null:n)):(au(e,null),Qre(e,0),Jre(e,null))}function Gat(e){var t,n;if(e.f){for(;e.n=h)throw J(new Im(t,h));return s=n[t],h==1?r=null:(r=Me(kfe,Xce,415,h-1,0,1),Hc(n,0,r,0,t),o=h-t-1,o>0&&Hc(n,t+1,r,t,o)),s7(e,r),fat(e,t,s),s}function nk(){nk=pe,Gk=u(Te(He((Gpe(),Sc).qb),6),34),zk=u(Te(He(Sc.qb),3),34),Sfe=u(Te(He(Sc.qb),4),34),Afe=u(Te(He(Sc.qb),5),18),UH(Gk),UH(zk),UH(Sfe),UH(Afe),k4t=new Al(ie(re(ju,1),L4,170,0,[Gk,zk]))}function Wat(e,t){var n;this.d=new yT,this.b=t,this.e=new Io(t.qf()),n=e.u.Hc((ol(),JO)),e.u.Hc(Z0)?e.D?this.a=n&&!t.If():this.a=!0:e.u.Hc(m2)?n?this.a=!(t.zf().Kc().Ob()||t.Bf().Kc().Ob()):this.a=!1:this.a=!1}function Kat(e,t){var n,r,s,o;for(n=e.o.a,o=u(u(Ii(e.r,t),21),84).Kc();o.Ob();)s=u(o.Pb(),111),s.e.a=(r=s.b,r.Xe((bi(),kl))?r.Hf()==(ht(),Dn)?-r.rf().a-Ue(ft(r.We(kl))):n+Ue(ft(r.We(kl))):r.Hf()==(ht(),Dn)?-r.rf().a:n)}function Yat(e,t){var n,r,s,o;n=u(K(e,(pt(),Zl)),103),o=u(Ft(t,gE),61),s=u(K(e,bs),98),s!=(wa(),X1)&&s!=w2?o==(ht(),uc)&&(o=$5e(t,n),o==uc&&(o=Y6(n))):(r=Hut(t),r>0?o=Y6(n):o=zD(Y6(n))),So(t,gE,o)}function Ndn(e,t){var n,r,s,o,h;for(h=e.j,t.a!=t.b&&aa(h,new q5),s=h.c.length/2|0,r=0;r0&&bI(e,n,t),o):r.a!=null?(bI(e,t,n),-1):s.a!=null?(bI(e,n,t),1):0}function Xat(e,t){var n,r,s,o;e.ej()?(n=e.Vi(),o=e.fj(),++e.j,e.Hi(n,e.oi(n,t)),r=e.Zi(3,null,t,n,o),e.bj()?(s=e.cj(t,null),s?(s.Ei(r),s.Fi()):e.$i(r)):e.$i(r)):(lYe(e,t),e.bj()&&(s=e.cj(t,null),s&&s.Fi()))}function JH(e,t){var n,r,s,o,h;for(h=pu(e.e.Tg(),t),s=new X5,n=u(e.g,119),o=e.i;--o>=0;)r=n[o],h.rl(r.ak())&&Br(s,r);!jlt(e,s)&&Ll(e.e)&&Vx(e,t.$j()?jp(e,6,t,(hn(),bo),null,-1,!1):jp(e,t.Kj()?2:1,t,null,null,-1,!1))}function d7(){d7=pe;var e,t;for(yk=Me(D4,Qe,91,32,0,1),QC=Me(D4,Qe,91,32,0,1),e=1,t=0;t<=18;t++)yk[t]=WD(e),QC[t]=WD(A0(e,t)),e=ja(e,5);for(;th)||t.q&&(r=t.C,h=r.c.c.a-r.o.a/2,s=r.n.a-n,s>h)))}function Rdn(e,t){var n;kr(t,"Partition preprocessing",1),n=u(zl(Vi(ic(Vi(new vn(null,new mn(e.a,16)),new jY),new tB),new H5),eb(new vt,new Dt,new Hn,ie(re(yl,1),tt,132,0,[(F1(),Ql)]))),15),ms(n.Oc(),new nB),ur(t)}function Qat(e){fre();var t,n,r,s,o,h,d;for(n=new Z2,s=new C(e.e.b);s.a1?e.e*=Ue(e.a):e.f/=Ue(e.a),wan(e),Ecn(e),s2n(e),Ye(e.b,(K_(),XG),e.g)}function tot(e,t,n){var r,s,o,h,d,v;for(r=0,v=n,t||(r=n*(e.c.length-1),v*=-1),o=new C(e);o.a=0?(t||(t=new ST,r>0&&To(t,e.substr(0,r))),t.a+="\\",b8(t,n&Ss)):t&&b8(t,n&Ss);return t?t.a:e}function Udn(e){var t;if(!e.a)throw J(new Wo("IDataType class expected for layout option "+e.f));if(t=enn(e.a),t==null)throw J(new Wo("Couldn't create new instance of property '"+e.f+"'. "+Jft+(S0(cN),cN.k)+qxe));return u(t,414)}function Hse(e){var t,n,r,s,o;return o=e.eh(),o&&o.kh()&&(s=Up(e,o),s!=o)?(n=e.Vg(),r=(t=e.Vg(),t>=0?e.Qg(null):e.eh().ih(e,-1-t,null,null)),e.Rg(u(s,49),n),r&&r.Fi(),e.Lg()&&e.Mg()&&n>-1&&_i(e,new oa(e,9,n,o,s)),s):o}function aot(e){var t,n,r,s,o,h,d,v;for(h=0,o=e.f.e,r=0;r>5,s>=e.d)return e.e<0;if(n=e.a[s],t=1<<(t&31),e.e<0){if(r=_tt(e),s>16)),15).Xc(o),d0&&(!(Dp(e.a.c)&&t.n.d)&&!(s8(e.a.c)&&t.n.b)&&(t.g.d+=b.Math.max(0,r/2-.5)),!(Dp(e.a.c)&&t.n.a)&&!(s8(e.a.c)&&t.n.c)&&(t.g.a-=r-1))}function uot(e){var t,n,r,s,o;if(s=new st,o=nut(e,s),t=u(K(e,(et(),cl)),10),t)for(r=new C(t.j);r.a>t,o=e.m>>t|n<<22-t,s=e.l>>t|e.m<<22-t):t<44?(h=r?V0:0,o=n>>t-22,s=e.m>>t-22|n<<44-t):(h=r?V0:0,o=r?ml:0,s=n>>t-44),fu(s&ml,o&ml,h&V0)}function zse(e){var t,n,r,s,o,h;for(this.c=new st,this.d=e,r=gs,s=gs,t=Ds,n=Ds,h=ii(e,0);h.b!=h.d.c;)o=u(ri(h),8),r=b.Math.min(r,o.a),s=b.Math.min(s,o.b),t=b.Math.max(t,o.a),n=b.Math.max(n,o.b);this.a=new fh(r,s,t-r,n-s)}function fot(e,t){var n,r,s,o,h,d;for(o=new C(e.b);o.a0&&we(t,42)&&(e.a.qj(),x=u(t,42),v=x.cd(),o=v==null?0:Xi(v),h=Nbe(e.a,o),n=e.a.d[h],n)){for(r=u(n.g,367),_=n.i,d=0;d<_;++d)if(s=r[d],s.Sh()==o&&s.Fb(x))return dot(e,x),!0}return!1}function Jdn(e){var t,n,r,s;for(s=u(Ii(e.a,(c4(),_q)),15).Kc();s.Ob();)r=u(s.Pb(),101),n=(t=D6(r.k),t.Hc((ht(),An))?t.Hc($n)?t.Hc(xr)?t.Hc(Dn)?null:d2t:p2t:g2t:f2t),p8(e,r,n[0],(qv(),ww),0),p8(e,r,n[1],u2,1),p8(e,r,n[2],mw,1)}function e0n(e,t){var n,r;n=A2n(t),Cpn(e,t,n),wst(e.a,u(K(Ya(t.b),(et(),Lk)),230)),J2n(e),Shn(e,t),r=Me(Lr,Jr,25,t.b.j.c.length,15,1),Tae(e,t,(ht(),An),r,n),Tae(e,t,$n,r,n),Tae(e,t,xr,r,n),Tae(e,t,Dn,r,n),e.a=null,e.c=null,e.b=null}function Q4e(){Q4e=pe,yCe=(mH(),Rhe),eyt=new dn(Dxe,yCe),Zmt=new dn(Ixe,(Mn(),!0)),ct(-1),Ymt=new dn(Oxe,ct(-1)),ct(-1),Xmt=new dn(Nxe,ct(-1)),Jmt=new dn(Pxe,!1),tyt=new dn(Bxe,!0),Qmt=new dn(xce,!1),nyt=new dn(Rxe,-1)}function Z4e(e,t,n){switch(t){case 7:!e.e&&(e.e=new wn(ra,e,7,4)),_r(e.e),!e.e&&(e.e=new wn(ra,e,7,4)),fs(e.e,u(n,14));return;case 8:!e.d&&(e.d=new wn(ra,e,8,5)),_r(e.d),!e.d&&(e.d=new wn(ra,e,8,5)),fs(e.d,u(n,14));return}Y3e(e,t,n)}function J4e(e,t){var n,r,s,o,h;if(je(t)===je(e))return!0;if(!we(t,15)||(h=u(t,15),e.gc()!=h.gc()))return!1;for(o=h.Kc(),r=e.Kc();r.Ob();)if(n=r.Pb(),s=o.Pb(),!(je(n)===je(s)||n!=null&&Ci(n,s)))return!1;return!0}function t0n(e,t){var n,r,s,o;for(o=u(zl(ic(ic(new vn(null,new mn(t.b,16)),new kL),new KP),eb(new vt,new Dt,new Hn,ie(re(yl,1),tt,132,0,[(F1(),Ql)]))),15),o.Jc(new xL),n=0,s=o.Kc();s.Ob();)r=u(s.Pb(),11),r.p==-1&&t5e(e,r,n++)}function got(e){switch(e.g){case 0:return new sT;case 1:return new WJ;case 2:return new UJ;case 3:return new Bqe;case 4:return new EKe;default:throw J(new Ln("No implementation is available for the node placer "+(e.f!=null?e.f:""+e.g)))}}function pot(e){switch(e.g){case 0:return new Ive;case 1:return new KJ;case 2:return new $J;case 3:return new HJ;case 4:return new Fqe;default:throw J(new Ln("No implementation is available for the cycle breaker "+(e.f!=null?e.f:""+e.g)))}}function e5e(){e5e=pe,Pmt=new dn(_xe,ct(0)),Bmt=new dn(Cxe,0),nCe=(RD(),yV),Omt=new dn(mce,nCe),ct(0),Imt=new dn(yce,ct(1)),iCe=(rH(),Bhe),Rmt=new dn(Sxe,iCe),sCe=(L$(),Ihe),Fmt=new dn(Axe,sCe),rCe=(jH(),Phe),Nmt=new dn(Lxe,rCe)}function n0n(e,t,n){var r;r=null,t&&(r=t.d),eC(e,new r8(t.n.a-r.b+n.a,t.n.b-r.d+n.b)),eC(e,new r8(t.n.a-r.b+n.a,t.n.b+t.o.b+r.a+n.b)),eC(e,new r8(t.n.a+t.o.a+r.c+n.a,t.n.b-r.d+n.b)),eC(e,new r8(t.n.a+t.o.a+r.c+n.a,t.n.b+t.o.b+r.a+n.b))}function t5e(e,t,n){var r,s,o;for(t.p=n,o=Pp(B1(ie(re(q1,1),yt,20,0,[new sa(t),new Ar(t)])));Vr(o);)r=u(Pr(o),11),r.p==-1&&t5e(e,r,n);if(t.i.k==(zn(),ca))for(s=new C(t.i.j);s.a=2)for(n=s.Kc(),t=ft(n.Pb());n.Ob();)o=t,t=ft(n.Pb()),r=b.Math.min(r,(Sn(t),t-(Sn(o),o)));return r}function r0n(e,t){var n,r,s,o,h;r=new as,ks(r,t,r.c.b,r.c);do for(n=(Qn(r.b!=0),u(bh(r,r.a.a),86)),e.b[n.g]=1,o=ii(n.d,0);o.b!=o.d.c;)s=u(ri(o),188),h=s.c,e.b[h.g]==1?ci(e.a,s):e.b[h.g]==2?e.b[h.g]=1:ks(r,h,r.c.b,r.c);while(r.b!=0)}function i0n(e,t){var n,r,s;if(je(t)===je(Nr(e)))return!0;if(!we(t,15)||(r=u(t,15),s=e.gc(),s!=r.gc()))return!1;if(we(r,54)){for(n=0;n0&&(s=n),h=new C(e.f.e);h.a0?(t-=1,n-=1):r>=0&&s<0?(t+=1,n+=1):r>0&&s>=0?(t-=1,n+=1):(t+=1,n-=1),new xa(ct(t),ct(n))}function x0n(e,t){return e.ct.c?1:e.bt.b?1:e.a!=t.a?Xi(e.a)-Xi(t.a):e.d==(S_(),TS)&&t.d==ES?-1:e.d==ES&&t.d==TS?1:0}function mot(e,t){var n,r,s,o,h;return o=t.a,o.c.i==t.b?h=o.d:h=o.c,o.c.i==t.b?r=o.c:r=o.d,s=Xon(e.a,h,r),s>0&&s0):s<0&&-s0):!1}function E0n(e,t,n,r){var s,o,h,d,v,x,_,L;for(s=(t-e.d)/e.c.c.length,o=0,e.a+=n,e.d=t,L=new C(e.c);L.a>24;return h}function _0n(e){if(e.pe()){var t=e.c;t.qe()?e.o="["+t.n:t.pe()?e.o="["+t.ne():e.o="[L"+t.ne()+";",e.b=t.me()+"[]",e.k=t.oe()+"[]";return}var n=e.j,r=e.d;r=r.split("/"),e.o=Uie(".",[n,Uie("$",r)]),e.b=Uie(".",[n,Uie(".",r)]),e.k=r[r.length-1]}function C0n(e,t){var n,r,s,o,h;for(h=null,o=new C(e.e.a);o.a=0;t-=2)for(n=0;n<=t;n+=2)(e.b[n]>e.b[n+2]||e.b[n]===e.b[n+2]&&e.b[n+1]>e.b[n+3])&&(r=e.b[n+2],e.b[n+2]=e.b[n],e.b[n]=r,r=e.b[n+3],e.b[n+3]=e.b[n+1],e.b[n+1]=r);e.c=!0}}function yot(e,t){var n,r,s,o,h,d,v,x;for(h=t==1?Kue:Wue,o=h.a.ec().Kc();o.Ob();)for(s=u(o.Pb(),103),v=u(Ii(e.f.c,s),21).Kc();v.Ob();)switch(d=u(v.Pb(),46),r=u(d.b,81),x=u(d.a,189),n=x.c,s.g){case 2:case 1:r.g.d+=n;break;case 4:case 3:r.g.c+=n}}function L0n(e,t){var n,r,s,o,h,d,v,x,_;for(x=-1,_=0,h=e,d=0,v=h.length;d0&&++_;++x}return _}function _f(e){var t,n;return n=new Fl(Cp(e.gm)),n.a+="@",Yr(n,(t=Xi(e)>>>0,t.toString(16))),e.kh()?(n.a+=" (eProxyURI: ",Ec(n,e.qh()),e.$g()&&(n.a+=" eClass: ",Ec(n,e.$g())),n.a+=")"):e.$g()&&(n.a+=" (eClass: ",Ec(n,e.$g()),n.a+=")"),n.a}function sC(e){var t,n,r,s;if(e.e)throw J(new Wo((S0(Sue),doe+Sue.k+goe)));for(e.d==(wo(),f0)&&kz(e,Xh),n=new C(e.a.a);n.a>24}return n}function I0n(e,t,n){var r,s,o;if(s=u(_o(e.i,t),306),!s)if(s=new yet(e.d,t,n),M6(e.i,t,s),h3e(t))KWt(e.a,t.c,t.b,s);else switch(o=m1n(t),r=u(_o(e.p,o),244),o.g){case 1:case 3:s.j=!0,Zee(r,t.b,s);break;case 4:case 2:s.k=!0,Zee(r,t.c,s)}return s}function O0n(e,t,n,r){var s,o,h,d,v,x;if(d=new X5,v=pu(e.e.Tg(),t),s=u(e.g,119),ho(),u(t,66).Oj())for(h=0;h=0)return s;for(o=1,d=new C(t.j);d.a0&&t.ue((xn(s-1,e.c.length),u(e.c[s-1],10)),o)>0;)gh(e,s,(xn(s-1,e.c.length),u(e.c[s-1],10))),--s;xn(s,e.c.length),e.c[s]=o}n.a=new Mr,n.b=new Mr}function N0n(e,t,n){var r,s,o,h,d,v,x,_;for(_=(r=u(t.e&&t.e(),9),new hh(r,u(wf(r,r.length),9),0)),v=cy(n,"[\\[\\]\\s,]+"),o=v,h=0,d=o.length;h0&&(!(Dp(e.a.c)&&t.n.d)&&!(s8(e.a.c)&&t.n.b)&&(t.g.d-=b.Math.max(0,r/2-.5)),!(Dp(e.a.c)&&t.n.a)&&!(s8(e.a.c)&&t.n.c)&&(t.g.a+=b.Math.max(0,r-1)))}function _ot(e,t,n){var r,s;if((e.c-e.b&e.a.length-1)==2)t==(ht(),An)||t==$n?($$(u(F_(e),15),(Ul(),d0)),$$(u(F_(e),15),b2)):($$(u(F_(e),15),(Ul(),b2)),$$(u(F_(e),15),d0));else for(s=new y_(e);s.a!=s.b;)r=u(gH(s),15),$$(r,n)}function B0n(e,t){var n,r,s,o,h,d,v;for(s=l8(new tpe(e)),d=new Ea(s,s.c.length),o=l8(new tpe(t)),v=new Ea(o,o.c.length),h=null;d.b>0&&v.b>0&&(n=(Qn(d.b>0),u(d.a.Xb(d.c=--d.b),33)),r=(Qn(v.b>0),u(v.a.Xb(v.c=--v.b),33)),n==r);)h=n;return h}function vl(e,t){var n,r,s,o,h,d;return o=e.a*uoe+e.b*1502,d=e.b*uoe+11,n=b.Math.floor(d*NI),o+=n,d-=n*x6e,o%=x6e,e.a=o,e.b=d,t<=24?b.Math.floor(e.a*c7e[t]):(s=e.a*(1<=2147483648&&(r-=soe),r)}function Cot(e,t,n){var r,s,o,h;KXe(e,t)>KXe(e,n)?(r=ac(n,(ht(),$n)),e.d=r.dc()?0:xne(u(r.Xb(0),11)),h=ac(t,Dn),e.b=h.dc()?0:xne(u(h.Xb(0),11))):(s=ac(n,(ht(),Dn)),e.d=s.dc()?0:xne(u(s.Xb(0),11)),o=ac(t,$n),e.b=o.dc()?0:xne(u(o.Xb(0),11)))}function Sot(e){var t,n,r,s,o,h,d;if(e&&(t=e.Hh(Uh),t&&(h=Hr(r1((!t.b&&(t.b=new Ml((on(),oo),wc,t)),t.b),"conversionDelegates")),h!=null))){for(d=new st,r=cy(h,"\\w+"),s=0,o=r.length;se.c));h++)s.a>=e.s&&(o<0&&(o=h),d=h);return v=(e.s+e.c)/2,o>=0&&(r=m2n(e,t,o,d),v=AUt((xn(r,t.c.length),u(t.c[r],329))),Ldn(t,r,n)),v}function Vse(){Vse=pe,ryt=new fo((bi(),Bk),1.3),xCe=xSe,LCe=new kv(15),lyt=new fo(Fb,LCe),fyt=new fo(jb,15),iyt=IV,oyt=Rb,cyt=e5,uyt=p2,ayt=J4,CCe=KO,hyt=Hy,ACe=(Q4e(),eyt),_Ce=Zmt,SCe=Jmt,MCe=tyt,ECe=Qmt,TCe=OV,syt=TSe,RO=Xmt,kCe=Ymt,DCe=nyt}function Rr(e,t,n){var r,s,o,h,d,v,x;for(h=(o=new KB,o),Fme(h,(Sn(t),t)),x=(!h.b&&(h.b=new Ml((on(),oo),wc,h)),h.b),v=1;v0&&fwn(this,s)}function i5e(e,t,n,r,s,o){var h,d,v;if(!s[t.b]){for(s[t.b]=!0,h=r,!h&&(h=new k$),it(h.e,t),v=o[t.b].Kc();v.Ob();)d=u(v.Pb(),282),!(d.d==n||d.c==n)&&(d.c!=t&&i5e(e,d.c,t,h,s,o),d.d!=t&&i5e(e,d.d,t,h,s,o),it(h.c,d),Rs(h.d,d.b));return h}return null}function j0n(e){var t,n,r,s,o,h,d;for(t=0,s=new C(e.e);s.a=2}function $0n(e,t){var n,r,s,o;for(kr(t,"Self-Loop pre-processing",1),r=new C(e.a);r.a1||(t=Ui(If,ie(re(xo,1),tt,93,0,[Q0,Of])),SD(a$(t,e))>1)||(r=Ui(Pf,ie(re(xo,1),tt,93,0,[g0,Zh])),SD(a$(r,e))>1))}function G0n(e,t){var n,r,s;return n=t.Hh(e.a),n&&(s=Hr(r1((!n.b&&(n.b=new Ml((on(),oo),wc,n)),n.b),"affiliation")),s!=null)?(r=cj(s,Nu(35)),r==-1?Iie(e,f_(e,Gl(t.Hj())),s):r==0?Iie(e,null,s.substr(1)):Iie(e,s.substr(0,r),s.substr(r+1))):null}function q0n(e){var t,n,r;try{return e==null?Pu:Qo(e)}catch(s){if(s=ts(s),we(s,102))return t=s,r=Cp(pl(e))+"@"+(n=(Ud(),v3e(e)>>>0),n.toString(16)),Icn(Dsn(),(n8(),"Exception during lenientFormat for "+r),t),"<"+r+" threw "+Cp(t.gm)+">";throw J(s)}}function Mot(e){switch(e.g){case 0:return new GJ;case 1:return new CR;case 2:return new MGe;case 3:return new DL;case 4:return new QUe;case 5:return new qJ;default:throw J(new Ln("No implementation is available for the layerer "+(e.f!=null?e.f:""+e.g)))}}function s5e(e,t,n){var r,s,o;for(o=new C(e.t);o.a0&&(r.b.n-=r.c,r.b.n<=0&&r.b.u>0&&ci(t,r.b));for(s=new C(e.i);s.a0&&(r.a.u-=r.c,r.a.u<=0&&r.a.n>0&&ci(n,r.a))}function tz(e){var t,n,r,s,o;if(e.g==null&&(e.d=e.si(e.f),Br(e,e.d),e.c))return o=e.f,o;if(t=u(e.g[e.i-1],47),s=t.Pb(),e.e=t,n=e.si(s),n.Ob())e.d=n,Br(e,n);else for(e.d=null;!t.Ob()&&(cs(e.g,--e.i,null),e.i!=0);)r=u(e.g[e.i-1],47),t=r;return s}function V0n(e,t){var n,r,s,o,h,d;if(r=t,s=r.ak(),G0(e.e,s)){if(s.hi()&&v$(e,s,r.dd()))return!1}else for(d=pu(e.e.Tg(),s),n=u(e.g,119),o=0;o1||n>1)return 2;return t+n==1?2:0}function Iot(e,t,n){var r,s,o,h,d;for(kr(n,"ELK Force",1),It(Mt(Ft(t,(a1(),Q7e))))||i$((r=new sr((Tm(),new ym(t))),r)),d=cnt(t),bln(d),Ysn(e,u(K(d,X7e),424)),h=kut(e.a,d),o=h.Kc();o.Ob();)s=u(o.Pb(),231),D2n(e.b,s,Kc(n,1/h.gc()));d=Nlt(h),Dlt(d),ur(n)}function Z0n(e,t){var n,r,s,o,h;if(kr(t,"Breaking Point Processor",1),wmn(e),It(Mt(K(e,(pt(),i_e))))){for(s=new C(e.b);s.a=0?e._g(r,!0,!0):tw(e,o,!0),153)),u(s,215).ml(t,n)}else throw J(new Ln(i2+t.ne()+RC))}function ngn(e,t){var n,r,s,o,h;for(n=new st,s=ic(new vn(null,new mn(e,16)),new $Q),o=ic(new vn(null,new mn(e,16)),new HQ),h=Lrn(qnn(Kj(Pgn(ie(re(h3n,1),yt,833,0,[s,o])),new zQ))),r=1;r=2*t&&it(n,new vne(h[r-1]+t,h[r]-t));return n}function rgn(e,t,n){kr(n,"Eades radial",1),n.n&&t&&yf(n,kf(t),(Pl(),nh)),e.d=u(Ft(t,(a_(),MS)),33),e.c=Ue(ft(Ft(t,(Jm(),xV)))),e.e=tse(u(Ft(t,BO),293)),e.a=Bon(u(Ft(t,cCe),426)),e.b=ihn(u(Ft(t,oCe),340)),Fln(e),n.n&&t&&yf(n,kf(t),(Pl(),nh))}function ign(e,t,n){var r,s,o,h,d,v,x,_;if(n)for(o=n.a.length,r=new W2(o),d=(r.b-r.a)*r.c<0?(Lp(),C2):new Op(r);d.Ob();)h=u(d.Pb(),19),s=E8(n,h.a),s&&(v=nnn(e,(x=(pv(),_=new xpe,_),t&&c5e(x,t),x),s),I_(v,D0(s,Id)),KH(s,v),I4e(s,v),pie(e,s,v))}function rz(e){var t,n,r,s,o,h;if(!e.j){if(h=new H9,t=XS,o=t.a.zc(e,t),o==null){for(r=new rr(jo(e));r.e!=r.i.gc();)n=u(pr(r),26),s=rz(n),fs(h,s),Br(h,n);t.a.Bc(e)!=null}Km(h),e.j=new B3((u(Te(He((Rp(),En).o),11),18),h.i),h.g),dl(e).b&=-33}return e.j}function sgn(e){var t,n,r,s;if(e==null)return null;if(r=Xc(e,!0),s=tO.length,an(r.substr(r.length-s,s),tO)){if(n=r.length,n==4){if(t=(zr(0,r.length),r.charCodeAt(0)),t==43)return nLe;if(t==45)return F4t}else if(n==3)return nLe}return new hpe(r)}function agn(e){var t,n,r;return n=e.l,n&n-1||(r=e.m,r&r-1)||(t=e.h,t&t-1)||t==0&&r==0&&n==0?-1:t==0&&r==0&&n!=0?Dme(n):t==0&&r!=0&&n==0?Dme(r)+22:t!=0&&r==0&&n==0?Dme(t)+44:-1}function ogn(e,t){var n,r,s,o,h;for(kr(t,"Edge joining",1),n=It(Mt(K(e,(pt(),Jle)))),s=new C(e.b);s.a1)for(s=new C(e.a);s.a0),o.a.Xb(o.c=--o.b),Dm(o,s),Qn(o.b3&&e0(e,0,t-3))}function hgn(e){var t,n,r,s;return je(K(e,(pt(),Iy)))===je((F0(),Wg))?!e.e&&je(K(e,_O))!==je((q8(),wO)):(r=u(K(e,Hle),292),s=It(Mt(K(e,zle)))||je(K(e,dS))===je((V6(),vO)),t=u(K(e,kTe),19).a,n=e.a.c.length,!s&&r!=(q8(),wO)&&(t==0||t>n))}function fgn(e){var t,n;for(n=0;n0);n++);if(n>0&&n0);t++);return t>0&&n>16!=6&&t){if(o7(e,t))throw J(new Ln(FC+Zat(e)));r=null,e.Cb&&(r=(n=e.Db>>16,n>=0?N3e(e,r):e.Cb.ih(e,-1-n,null,r))),t&&(r=Q6(t,e,6,r)),r=Ibe(e,t,r),r&&r.Fi()}else e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,6,t,t))}function c5e(e,t){var n,r;if(t!=e.Cb||e.Db>>16!=9&&t){if(o7(e,t))throw J(new Ln(FC+Nct(e)));r=null,e.Cb&&(r=(n=e.Db>>16,n>=0?B3e(e,r):e.Cb.ih(e,-1-n,null,r))),t&&(r=Q6(t,e,9,r)),r=Obe(e,t,r),r&&r.Fi()}else e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,9,t,t))}function Wse(e,t){var n,r;if(t!=e.Cb||e.Db>>16!=3&&t){if(o7(e,t))throw J(new Ln(FC+Out(e)));r=null,e.Cb&&(r=(n=e.Db>>16,n>=0?F3e(e,r):e.Cb.ih(e,-1-n,null,r))),t&&(r=Q6(t,e,12,r)),r=Dbe(e,t,r),r&&r.Fi()}else e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,3,t,t))}function b7(e){var t,n,r,s,o;if(r=$h(e),o=e.j,o==null&&r)return e.$j()?null:r.zj();if(we(r,148)){if(n=r.Aj(),n&&(s=n.Nh(),s!=e.i)){if(t=u(r,148),t.Ej())try{e.g=s.Kh(t,o)}catch(h){if(h=ts(h),we(h,78))e.g=null;else throw J(h)}e.i=s}return e.g}return null}function Pot(e){var t;return t=new st,it(t,new y6(new Pt(e.c,e.d),new Pt(e.c+e.b,e.d))),it(t,new y6(new Pt(e.c,e.d),new Pt(e.c,e.d+e.a))),it(t,new y6(new Pt(e.c+e.b,e.d+e.a),new Pt(e.c+e.b,e.d))),it(t,new y6(new Pt(e.c+e.b,e.d+e.a),new Pt(e.c,e.d+e.a))),t}function Bot(e,t,n,r){var s,o,h;if(h=U3e(t,n),r.c[r.c.length]=t,e.j[h.p]==-1||e.j[h.p]==2||e.a[t.p])return r;for(e.j[h.p]=-1,o=new cr(fr(j0(h).a.Kc(),new V));Vr(o);)if(s=u(Pr(o),17),!(!(!to(s)&&!(!to(s)&&s.c.i.c==s.d.i.c))||s==t))return Bot(e,s,h,r);return r}function dgn(e,t,n){var r,s,o;for(o=t.a.ec().Kc();o.Ob();)s=u(o.Pb(),79),r=u(er(e.b,s),266),!r&&(us(n0(s))==us(Kp(s))?Apn(e,s,n):n0(s)==us(Kp(s))?er(e.c,s)==null&&er(e.b,Kp(s))!=null&&plt(e,s,n,!1):er(e.d,s)==null&&er(e.b,n0(s))!=null&&plt(e,s,n,!0))}function ggn(e,t){var n,r,s,o,h,d,v;for(s=e.Kc();s.Ob();)for(r=u(s.Pb(),10),d=new $c,rc(d,r),Vs(d,(ht(),$n)),Ye(d,(et(),$q),(Mn(),!0)),h=t.Kc();h.Ob();)o=u(h.Pb(),10),v=new $c,rc(v,o),Vs(v,Dn),Ye(v,$q,!0),n=new Iv,Ye(n,$q,!0),Va(n,d),ba(n,v)}function pgn(e,t,n,r){var s,o,h,d;s=Drt(e,t,n),o=Drt(e,n,t),h=u(er(e.c,t),112),d=u(er(e.c,n),112),sr.b.g&&(o.c[o.c.length]=r);return o}function v7(){v7=pe,X4=new _M("CANDIDATE_POSITION_LAST_PLACED_RIGHT",0),Nk=new _M("CANDIDATE_POSITION_LAST_PLACED_BELOW",1),IS=new _M("CANDIDATE_POSITION_WHOLE_DRAWING_RIGHT",2),DS=new _M("CANDIDATE_POSITION_WHOLE_DRAWING_BELOW",3),OS=new _M("WHOLE_DRAWING",4)}function bgn(e,t){if(we(t,239))return Uan(e,u(t,33));if(we(t,186))return son(e,u(t,118));if(we(t,354))return wJt(e,u(t,137));if(we(t,352))return zbn(e,u(t,79));if(t)return null;throw J(new Ln(a8e+Yp(new Al(ie(re(Yn,1),yt,1,5,[t])))))}function vgn(e){var t,n,r,s,o,h,d;for(o=new as,s=new C(e.d.a);s.a1)for(t=Ev((n=new z2,++e.b,n),e.d),d=ii(o,0);d.b!=d.d.c;)h=u(ri(d),121),Cf(bf(pf(vf(gf(new Nh,1),0),t),h))}function u5e(e,t){var n,r;if(t!=e.Cb||e.Db>>16!=11&&t){if(o7(e,t))throw J(new Ln(FC+S5e(e)));r=null,e.Cb&&(r=(n=e.Db>>16,n>=0?j3e(e,r):e.Cb.ih(e,-1-n,null,r))),t&&(r=Q6(t,e,10,r)),r=Hbe(e,t,r),r&&r.Fi()}else e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,11,t,t))}function wgn(e){var t,n,r,s;for(r=new ob(new dg(e.b).a);r.b;)n=$v(r),s=u(n.cd(),11),t=u(n.dd(),10),Ye(t,(et(),Mi),s),Ye(s,cl,t),Ye(s,kO,(Mn(),!0)),Vs(s,u(K(t,vc),61)),K(t,vc),Ye(s.i,(pt(),bs),(wa(),CE)),u(K(Ya(s.i),eu),21).Fc((mo(),uE))}function mgn(e,t,n){var r,s,o,h,d,v;if(o=0,h=0,e.c)for(v=new C(e.d.i.j);v.ao.a?-1:s.av){for(_=e.d,e.d=Me(SAe,p8e,63,2*v+4,0,1),o=0;o=9223372036854776e3?(D8(),B8e):(s=!1,e<0&&(s=!0,e=-e),r=0,e>=vb&&(r=_s(e/vb),e-=r*vb),n=0,e>=ck&&(n=_s(e/ck),e-=n*ck),t=_s(e),o=fu(t,n,r),s&&gie(o),o)}function Lgn(e,t){var n,r,s,o;for(n=!t||!e.u.Hc((ol(),Z0)),o=0,s=new C(e.e.Cf());s.a=-t&&r==t?new xa(ct(n-1),ct(r)):new xa(ct(n),ct(r-1))}function Hot(){return po(),ie(re(m3n,1),tt,77,0,[MEe,SEe,tS,ele,YEe,uq,mq,eE,WEe,FEe,VEe,J7,KEe,PEe,XEe,kEe,dq,tle,oq,bq,ZEe,pq,xEe,UEe,JEe,vq,QEe,cq,IEe,GEe,zEe,yq,_Ee,aq,hq,TEe,Z7,$Ee,BEe,qEe,nS,AEe,CEe,HEe,REe,fq,wq,EEe,gq,jEe,lq,OEe,DEe,pO,sq,NEe,LEe])}function Ogn(e,t,n){e.d=0,e.b=0,t.k==(zn(),Jc)&&n.k==Jc&&u(K(t,(et(),Mi)),10)==u(K(n,Mi),10)&&(Hre(t).j==(ht(),An)?Cot(e,t,n):Cot(e,n,t)),t.k==Jc&&n.k==ca?Hre(t).j==(ht(),An)?e.d=1:e.b=1:n.k==Jc&&t.k==ca&&(Hre(n).j==(ht(),An)?e.b=1:e.d=1),yun(e,t,n)}function Ngn(e){var t,n,r,s,o,h,d,v,x,_,L;return L=c4e(e),t=e.a,v=t!=null,v&&f8(L,"category",e.a),s=hM(new vm(e.d)),h=!s,h&&(x=new hg,t1(L,"knownOptions",x),n=new S$e(x),Da(new vm(e.d),n)),o=hM(e.g),d=!o,d&&(_=new hg,t1(L,"supportedFeatures",_),r=new A$e(_),Da(e.g,r)),L}function Pgn(e){var t,n,r,s,o,h,d,v,x;for(r=!1,t=336,n=0,o=new HUe(e.length),d=e,v=0,x=d.length;v>16!=7&&t){if(o7(e,t))throw J(new Ln(FC+Kst(e)));r=null,e.Cb&&(r=(n=e.Db>>16,n>=0?P3e(e,r):e.Cb.ih(e,-1-n,null,r))),t&&(r=u(t,49).gh(e,1,iN,r)),r=Ove(e,t,r),r&&r.Fi()}else e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,7,t,t))}function zot(e,t){var n,r;if(t!=e.Cb||e.Db>>16!=3&&t){if(o7(e,t))throw J(new Ln(FC+rrt(e)));r=null,e.Cb&&(r=(n=e.Db>>16,n>=0?R3e(e,r):e.Cb.ih(e,-1-n,null,r))),t&&(r=u(t,49).gh(e,0,aN,r)),r=Nve(e,t,r),r&&r.Fi()}else e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,3,t,t))}function Yse(e,t){d7();var n,r,s,o,h,d,v,x,_;return t.d>e.d&&(d=e,e=t,t=d),t.d<63?_pn(e,t):(h=(e.d&-2)<<4,x=Wwe(e,h),_=Wwe(t,h),r=hae(e,$6(x,h)),s=hae(t,$6(_,h)),v=Yse(x,_),n=Yse(r,s),o=Yse(hae(x,r),hae(s,_)),o=mae(mae(o,v),n),o=$6(o,h),v=$6(v,h<<1),mae(mae(v,o),n))}function Rgn(e,t,n){var r,s,o,h,d;for(h=H_(e,n),d=Me(h0,Bg,10,t.length,0,1),r=0,o=h.Kc();o.Ob();)s=u(o.Pb(),11),It(Mt(K(s,(et(),kO))))&&(d[r++]=u(K(s,cl),10));if(r=0;o+=n?1:-1)h=h|t.c.Sf(v,o,n,r&&!It(Mt(K(t.j,(et(),kw))))&&!It(Mt(K(t.j,(et(),z4))))),h=h|t.q._f(v,o,n),h=h|Sct(e,v[o],n,r);return Gs(e.c,t),h}function sz(e,t,n){var r,s,o,h,d,v,x,_,L,P;for(_=TQe(e.j),L=0,P=_.length;L1&&(e.a=!0),JQt(u(n.b,65),Ni(fc(u(t.b,65).c),bd(da(fc(u(n.b,65).a),u(t.b,65).a),s))),FXe(e,t),Got(e,n)}function qot(e){var t,n,r,s,o,h,d;for(o=new C(e.a.a);o.a0&&o>0?h.p=t++:r>0?h.p=n++:o>0?h.p=s++:h.p=n++}hn(),aa(e.j,new _L)}function zgn(e){var t,n;n=null,t=u(St(e.g,0),17);do{if(n=t.d.i,ta(n,(et(),Yh)))return u(K(n,Yh),11).i;if(n.k!=(zn(),Hs)&&Vr(new cr(fr(js(n).a.Kc(),new V))))t=u(Pr(new cr(fr(js(n).a.Kc(),new V))),17);else if(n.k!=Hs)return null}while(n&&n.k!=(zn(),Hs));return n}function Ggn(e,t){var n,r,s,o,h,d,v,x,_;for(d=t.j,h=t.g,v=u(St(d,d.c.length-1),113),_=(xn(0,d.c.length),u(d.c[0],113)),x=gse(e,h,v,_),o=1;ox&&(v=n,_=s,x=r);t.a=_,t.c=v}function qgn(e,t){var n,r;if(r=KM(e.b,t.b),!r)throw J(new Wo("Invalid hitboxes for scanline constraint calculation."));(Qtt(t.b,u(qKt(e.b,t.b),57))||Qtt(t.b,u(GKt(e.b,t.b),57)))&&(Ud(),t.b+""),e.a[t.b.f]=u(hne(e.b,t.b),57),n=u(lne(e.b,t.b),57),n&&(e.a[n.f]=t.b)}function Cf(e){if(!e.a.d||!e.a.e)throw J(new Wo((S0(sgt),sgt.k+" must have a source and target "+(S0(R7e),R7e.k)+" specified.")));if(e.a.d==e.a.e)throw J(new Wo("Network simplex does not support self-loops: "+e.a+" "+e.a.d+" "+e.a.e));return lj(e.a.d.g,e.a),lj(e.a.e.b,e.a),e.a}function Vgn(e,t,n){var r,s,o,h,d,v,x;for(x=new Sp(new Cje(e)),h=ie(re(Upt,1),ift,11,0,[t,n]),d=0,v=h.length;dv-e.b&&dv-e.a&&d0&&++z;++P}return z}function tpn(e,t){var n,r,s,o,h;for(h=u(K(t,(nw(),q_e)),425),o=ii(t.b,0);o.b!=o.d.c;)if(s=u(ri(o),86),e.b[s.g]==0){switch(h.g){case 0:wit(e,s);break;case 1:r0n(e,s)}e.b[s.g]=2}for(r=ii(e.a,0);r.b!=r.d.c;)n=u(ri(r),188),Xm(n.b.d,n,!0),Xm(n.c.b,n,!0);Ye(t,(Tc(),R_e),e.a)}function pu(e,t){ho();var n,r,s,o;return t?t==(Fi(),B4t)||(t==T4t||t==zb||t==E4t)&&e!=eLe?new s6e(e,t):(r=u(t,677),n=r.pk(),n||(m8(Po((Yu(),Oa),t)),n=r.pk()),o=(!n.i&&(n.i=new Mr),n.i),s=u(hc($o(o.f,e)),1942),!s&&Si(o,e,s=new s6e(e,t)),s):y4t}function npn(e,t){var n,r,s,o,h,d,v,x,_;for(v=u(K(e,(et(),Mi)),11),x=sc(ie(re(na,1),Qe,8,0,[v.i.n,v.n,v.a])).a,_=e.i.n.b,n=kd(e.e),s=n,o=0,h=s.length;o0?o.a?(d=o.b.rf().a,n>d&&(s=(n-d)/2,o.d.b=s,o.d.c=s)):o.d.c=e.s+n:g_(e.u)&&(r=u4e(o.b),r.c<0&&(o.d.b=-r.c),r.c+r.b>o.b.rf().a&&(o.d.c=r.c+r.b-o.b.rf().a))}function apn(e,t){var n,r,s,o;for(kr(t,"Semi-Interactive Crossing Minimization Processor",1),n=!1,s=new C(e.b);s.a=0){if(t==n)return new xa(ct(-t-1),ct(-t-1));if(t==-n)return new xa(ct(-t),ct(n+1))}return b.Math.abs(t)>b.Math.abs(n)?t<0?new xa(ct(-t),ct(n)):new xa(ct(-t),ct(n+1)):new xa(ct(t+1),ct(n))}function upn(e){var t,n;n=u(K(e,(pt(),vu)),163),t=u(K(e,(et(),Lb)),303),n==(mh(),l2)?(Ye(e,vu,TO),Ye(e,Lb,(P0(),$4))):n==Ly?(Ye(e,vu,TO),Ye(e,Lb,(P0(),Tk))):t==(P0(),$4)?(Ye(e,vu,l2),Ye(e,Lb,mO)):t==Tk&&(Ye(e,vu,Ly),Ye(e,Lb,mO))}function az(){az=pe,OO=new SQ,Vwt=xi(new Xs,(ro(),bu),(po(),oq)),Kwt=il(xi(new Xs,bu,pq),Go,gq),Ywt=Qv(Qv(AF(il(xi(new Xs,Pd,mq),Go,wq),Zc),vq),yq),Uwt=il(xi(xi(xi(new Xs,c2,uq),Zc,hq),Zc,Z7),Go,lq),Wwt=il(xi(xi(new Xs,Zc,Z7),Zc,aq),Go,sq)}function aC(){aC=pe,Zwt=xi(il(new Xs,(ro(),Go),(po(),OEe)),bu,oq),nmt=Qv(Qv(AF(il(xi(new Xs,Pd,mq),Go,wq),Zc),vq),yq),Jwt=il(xi(xi(xi(new Xs,c2,uq),Zc,hq),Zc,Z7),Go,lq),tmt=xi(xi(new Xs,bu,pq),Go,gq),emt=il(xi(xi(new Xs,Zc,Z7),Zc,aq),Go,sq)}function lpn(e,t,n,r,s){var o,h;(!to(t)&&t.c.i.c==t.d.i.c||!stt(sc(ie(re(na,1),Qe,8,0,[s.i.n,s.n,s.a])),n))&&!to(t)&&(t.c==s?c8(t.a,0,new Io(n)):ci(t.a,new Io(n)),r&&!_0(e.a,n)&&(h=u(K(t,(pt(),Fo)),74),h||(h=new Gu,Ye(t,Fo,h)),o=new Io(n),ks(h,o,h.c.b,h.c),Gs(e.a,o)))}function hpn(e){var t,n;for(n=new cr(fr(Xo(e).a.Kc(),new V));Vr(n);)if(t=u(Pr(n),17),t.c.i.k!=(zn(),Rl))throw J(new M3(Poe+QD(e)+"' has its layer constraint set to FIRST, but has at least one incoming edge that does not come from a FIRST_SEPARATE node. That must not happen."))}function fpn(e,t,n){var r,s,o,h,d,v,x;if(s=urt(e.Db&254),s==0)e.Eb=n;else{if(s==1)d=Me(Yn,yt,1,2,5,1),o=dse(e,t),o==0?(d[0]=n,d[1]=e.Eb):(d[0]=e.Eb,d[1]=n);else for(d=Me(Yn,yt,1,s+1,5,1),h=tb(e.Eb),r=2,v=0,x=0;r<=128;r<<=1)r==t?d[x++]=n:e.Db&r&&(d[x++]=h[v++]);e.Eb=d}e.Db|=t}function Uot(e,t,n){var r,s,o,h;for(this.b=new st,s=0,r=0,h=new C(e);h.a0&&(o=u(St(this.b,0),167),s+=o.o,r+=o.p),s*=2,r*=2,t>1?s=_s(b.Math.ceil(s*t)):r=_s(b.Math.ceil(r/t)),this.a=new n3e(s,r)}function Wot(e,t,n,r,s,o){var h,d,v,x,_,L,P,z,q,W,X,le;for(_=r,t.j&&t.o?(z=u(er(e.f,t.A),57),W=z.d.c+z.d.b,--_):W=t.a.c+t.a.b,L=s,n.q&&n.o?(z=u(er(e.f,n.C),57),x=z.d.c,++L):x=n.a.c,X=x-W,v=b.Math.max(2,L-_),d=X/v,q=W+d,P=_;P=0;h+=s?1:-1){for(d=t[h],v=r==(ht(),$n)?s?ac(d,r):nb(ac(d,r)):s?nb(ac(d,r)):ac(d,r),o&&(e.c[d.p]=v.gc()),L=v.Kc();L.Ob();)_=u(L.Pb(),11),e.d[_.p]=x++;Rs(n,v)}}function Kot(e,t,n){var r,s,o,h,d,v,x,_;for(o=Ue(ft(e.b.Kc().Pb())),x=Ue(ft(ksn(t.b))),r=bd(fc(e.a),x-n),s=bd(fc(t.a),n-o),_=Ni(r,s),bd(_,1/(x-o)),this.a=_,this.b=new st,d=!0,h=e.b.Kc(),h.Pb();h.Ob();)v=Ue(ft(h.Pb())),d&&v-n>pce&&(this.b.Fc(n),d=!1),this.b.Fc(v);d&&this.b.Fc(n)}function dpn(e){var t,n,r,s;if(T2n(e,e.n),e.d.c.length>0){for(_T(e.c);K4e(e,u(Y(new C(e.e.a)),121))>5,t&=31,r>=e.d)return e.e<0?(Qp(),Eue):(Qp(),K7);if(o=e.d-r,s=Me(Lr,Jr,25,o+1,15,1),a1n(s,o,e.a,r,t),e.e<0){for(n=0;n0&&e.a[n]<<32-t){for(n=0;n=0?!1:(n=v4((Yu(),Oa),s,t),n?(r=n.Zj(),(r>1||r==-1)&&Dv(Po(Oa,n))!=3):!0)):!1}function vpn(e,t,n,r){var s,o,h,d,v;return d=zo(u(Te((!t.b&&(t.b=new wn(mr,t,4,7)),t.b),0),82)),v=zo(u(Te((!t.c&&(t.c=new wn(mr,t,5,8)),t.c),0),82)),us(d)==us(v)||Vm(v,d)?null:(h=nD(t),h==n?r:(o=u(er(e.a,h),10),o&&(s=o.e,s)?s:null))}function wpn(e,t){var n;switch(n=u(K(e,(pt(),Wq)),276),kr(t,"Label side selection ("+n+")",1),n.g){case 0:fot(e,(Ul(),d0));break;case 1:fot(e,(Ul(),b2));break;case 2:Sut(e,(Ul(),d0));break;case 3:Sut(e,(Ul(),b2));break;case 4:cct(e,(Ul(),d0));break;case 5:cct(e,(Ul(),b2))}ur(t)}function b5e(e,t,n){var r,s,o,h,d,v;if(r=rUt(n,e.length),h=e[r],h[0].k==(zn(),Ls))for(o=lze(n,h.length),v=t.j,s=0;s0&&(n[0]+=e.d,h-=n[0]),n[2]>0&&(n[2]+=e.d,h-=n[2]),o=b.Math.max(0,h),n[1]=b.Math.max(n[1],h),Ywe(e,lu,s.c+r.b+n[0]-(n[1]-h)/2,n),t==lu&&(e.c.b=o,e.c.c=s.c+r.b+(o-h)/2)}function sct(){this.c=Me(pa,Ao,25,(ht(),ie(re(ao,1),Dc,61,0,[uc,An,$n,xr,Dn])).length,15,1),this.b=Me(pa,Ao,25,ie(re(ao,1),Dc,61,0,[uc,An,$n,xr,Dn]).length,15,1),this.a=Me(pa,Ao,25,ie(re(ao,1),Dc,61,0,[uc,An,$n,xr,Dn]).length,15,1),s2e(this.c,gs),s2e(this.b,Ds),s2e(this.a,Ds)}function Yc(e,t,n){var r,s,o,h;if(t<=n?(s=t,o=n):(s=n,o=t),r=0,e.b==null)e.b=Me(Lr,Jr,25,2,15,1),e.b[0]=s,e.b[1]=o,e.c=!0;else{if(r=e.b.length,e.b[r-1]+1==s){e.b[r-1]=o;return}h=Me(Lr,Jr,25,r+2,15,1),Hc(e.b,0,h,0,r),e.b=h,e.b[r-1]>=s&&(e.c=!1,e.a=!1),e.b[r++]=s,e.b[r]=o,e.c||l4(e)}}function Cpn(e,t,n){var r,s,o,h,d,v,x;for(x=t.d,e.a=new su(x.c.length),e.c=new Mr,d=new C(x);d.a=0?e._g(x,!1,!0):tw(e,n,!1),58));e:for(o=L.Kc();o.Ob();){for(s=u(o.Pb(),56),_=0;_1;)ay(s,s.i-1);return r}function Dpn(e,t){var n,r,s,o,h,d,v;for(kr(t,"Comment post-processing",1),o=new C(e.b);o.ae.d[h.p]&&(n+=Gwe(e.b,o),$p(e.a,ct(o)));for(;!TT(e.a);)yme(e.b,u(I6(e.a),19).a)}return n}function uct(e,t,n){var r,s,o,h;for(o=(!t.a&&(t.a=new at(hs,t,10,11)),t.a).i,s=new rr((!t.a&&(t.a=new at(hs,t,10,11)),t.a));s.e!=s.i.gc();)r=u(pr(s),33),(!r.a&&(r.a=new at(hs,r,10,11)),r.a).i==0||(o+=uct(e,r,!1));if(n)for(h=us(t);h;)o+=(!h.a&&(h.a=new at(hs,h,10,11)),h.a).i,h=us(h);return o}function ay(e,t){var n,r,s,o;return e.ej()?(r=null,s=e.fj(),e.ij()&&(r=e.kj(e.pi(t),null)),n=e.Zi(4,o=J6(e,t),null,t,s),e.bj()&&o!=null&&(r=e.dj(o,r)),r?(r.Ei(n),r.Fi()):e.$i(n),o):(o=J6(e,t),e.bj()&&o!=null&&(r=e.dj(o,null),r&&r.Fi()),o)}function Opn(e){var t,n,r,s,o,h,d,v,x,_;for(x=e.a,t=new Ys,v=0,r=new C(e.d);r.ad.d&&(_=d.d+d.a+x));n.c.d=_,t.a.zc(n,t),v=b.Math.max(v,n.c.d+n.c.a)}return v}function mo(){mo=pe,Oq=new _m("COMMENTS",0),Th=new _m("EXTERNAL_PORTS",1),oS=new _m("HYPEREDGES",2),Nq=new _m("HYPERNODES",3),uE=new _m("NON_FREE_PORTS",4),j4=new _m("NORTH_SOUTH_PORTS",5),cS=new _m(Eft,6),oE=new _m("CENTER_LABELS",7),cE=new _m("END_LABELS",8),Pq=new _m("PARTITIONS",9)}function oy(e){var t,n,r,s,o;for(s=new st,t=new l_((!e.a&&(e.a=new at(hs,e,10,11)),e.a)),r=new cr(fr(z0(e).a.Kc(),new V));Vr(r);)n=u(Pr(r),79),we(Te((!n.b&&(n.b=new wn(mr,n,4,7)),n.b),0),186)||(o=zo(u(Te((!n.c&&(n.c=new wn(mr,n,5,8)),n.c),0),82)),t.a._b(o)||(s.c[s.c.length]=o));return s}function Npn(e){var t,n,r,s,o,h;for(o=new Ys,t=new l_((!e.a&&(e.a=new at(hs,e,10,11)),e.a)),s=new cr(fr(z0(e).a.Kc(),new V));Vr(s);)r=u(Pr(s),79),we(Te((!r.b&&(r.b=new wn(mr,r,4,7)),r.b),0),186)||(h=zo(u(Te((!r.c&&(r.c=new wn(mr,r,5,8)),r.c),0),82)),t.a._b(h)||(n=o.a.zc(h,o),n==null));return o}function Ppn(e,t,n,r,s){return r<0?(r=u4(e,s,ie(re(mt,1),Qe,2,6,[Rae,Fae,jae,$ae,ak,Hae,zae,Gae,qae,Vae,Uae,Wae]),t),r<0&&(r=u4(e,s,ie(re(mt,1),Qe,2,6,["Jan","Feb","Mar","Apr",ak,"Jun","Jul","Aug","Sep","Oct","Nov","Dec"]),t)),r<0?!1:(n.k=r,!0)):r>0?(n.k=r-1,!0):!1}function Bpn(e,t,n,r,s){return r<0?(r=u4(e,s,ie(re(mt,1),Qe,2,6,[Rae,Fae,jae,$ae,ak,Hae,zae,Gae,qae,Vae,Uae,Wae]),t),r<0&&(r=u4(e,s,ie(re(mt,1),Qe,2,6,["Jan","Feb","Mar","Apr",ak,"Jun","Jul","Aug","Sep","Oct","Nov","Dec"]),t)),r<0?!1:(n.k=r,!0)):r>0?(n.k=r-1,!0):!1}function Rpn(e,t,n,r,s,o){var h,d,v,x;if(d=32,r<0){if(t[0]>=e.length||(d=Ma(e,t[0]),d!=43&&d!=45)||(++t[0],r=ZH(e,t),r<0))return!1;d==45&&(r=-r)}return d==32&&t[0]-n==2&&s.b==2&&(v=new kF,x=v.q.getFullYear()-e2+e2-80,h=x%100,o.a=r==h,r+=(x/100|0)*100+(r=x&&(v=r);v&&(_=b.Math.max(_,v.a.o.a)),_>P&&(L=x,P=_)}return L}function $pn(e,t,n){var r,s,o;if(e.e=n,e.d=0,e.b=0,e.f=1,e.i=t,(e.e&16)==16&&(e.i=C2n(e.i)),e.j=e.i.length,mi(e),o=Xv(e),e.d!=e.j)throw J(new $r(Ur((jr(),V1t))));if(e.g){for(r=0;rUft?aa(v,e.b):r<=Uft&&r>Wft?aa(v,e.d):r<=Wft&&r>Kft?aa(v,e.c):r<=Kft&&aa(v,e.a),o=dct(e,v,o);return s}function Qp(){Qp=pe;var e;for(jG=new Tg(1,1),Tue=new Tg(1,10),K7=new Tg(0,0),Eue=new Tg(-1,1),n7e=ie(re(D4,1),Qe,91,0,[K7,jG,new Tg(1,2),new Tg(1,3),new Tg(1,4),new Tg(1,5),new Tg(1,6),new Tg(1,7),new Tg(1,8),new Tg(1,9),Tue]),$G=Me(D4,Qe,91,32,0,1),e=0;e<$G.length;e++)$G[e]=WD(A0(1,e))}function zpn(e,t,n,r,s,o){var h,d,v,x;for(d=!LT(Vi(e.Oc(),new Ke(new NY))).sd((G2(),X7)),h=e,o==(wo(),X0)&&(h=we(h,152)?H6(u(h,152)):we(h,131)?u(h,131).a:we(h,54)?new lv(h):new Em(h)),x=h.Kc();x.Ob();)v=u(x.Pb(),70),v.n.a=t.a,d?v.n.b=t.b+(r.b-v.o.b)/2:s?v.n.b=t.b:v.n.b=t.b+r.b-v.o.b,t.a+=v.o.a+n}function gct(e,t,n,r){var s,o,h,d,v,x;for(s=(r.c+r.a)/2,Rh(t.j),ci(t.j,s),Rh(n.e),ci(n.e,s),x=new vze,d=new C(e.f);d.a1,d&&(r=new Pt(s,n.b),ci(t.a,r)),D_(t.a,ie(re(na,1),Qe,8,0,[P,L]))}function wct(e){wv(e,new gb(gv(hv(dv(fv(new lg,fG),"ELK Randomizer"),'Distributes the nodes randomly on the plane, leading to very obfuscating layouts. Can be useful to demonstrate the power of "real" layout algorithms.'),new $Z))),dt(e,fG,uw,fAe),dt(e,fG,py,15),dt(e,fG,Fz,ct(0)),dt(e,fG,fk,N7)}function m5e(){m5e=pe;var e,t,n,r,s,o;for(eA=Me(el,A4,25,255,15,1),iU=Me(Sh,Td,25,16,15,1),t=0;t<255;t++)eA[t]=-1;for(n=57;n>=48;n--)eA[n]=n-48<<24>>24;for(r=70;r>=65;r--)eA[r]=r-65+10<<24>>24;for(s=102;s>=97;s--)eA[s]=s-97+10<<24>>24;for(o=0;o<10;o++)iU[o]=48+o&Ss;for(e=10;e<=15;e++)iU[e]=65+e-10&Ss}function cz(e,t,n){var r,s,o,h,d,v,x,_;return d=t.i-e.g/2,v=n.i-e.g/2,x=t.j-e.g/2,_=n.j-e.g/2,o=t.g+e.g/2,h=n.g+e.g/2,r=t.f+e.g/2,s=n.f+e.g/2,d>19)return"-"+mct(U8(e));for(n=e,r="";!(n.l==0&&n.m==0&&n.h==0);){if(s=Mre(Lz),n=Q5e(n,s,!0),t=""+Lze(s2),!(n.l==0&&n.m==0&&n.h==0))for(o=9-t.length;o>0;o--)t="0"+t;r=t+r}return r}function Upn(){if(!Object.create||!Object.getOwnPropertyNames)return!1;var e="__proto__",t=Object.create(null);if(t[e]!==void 0)return!1;var n=Object.getOwnPropertyNames(t);return!(n.length!=0||(t[e]=42,t[e]!==42)||Object.getOwnPropertyNames(t).length==0)}function Wpn(e){var t,n,r,s,o,h,d;for(t=!1,n=0,s=new C(e.d.b);s.a=e.a||!a4e(t,n))return-1;if(T8(u(r.Kb(t),20)))return 1;for(s=0,h=u(r.Kb(t),20).Kc();h.Ob();)if(o=u(h.Pb(),17),v=o.c.i==t?o.d.i:o.c.i,d=k5e(e,v,n,r),d==-1||(s=b.Math.max(s,d),s>e.c-1))return-1;return s+1}function yct(e,t){var n,r,s,o,h,d;if(je(t)===je(e))return!0;if(!we(t,15)||(r=u(t,15),d=e.gc(),r.gc()!=d))return!1;if(h=r.Kc(),e.ni()){for(n=0;n0){if(e.qj(),t!=null){for(o=0;o>24;case 97:case 98:case 99:case 100:case 101:case 102:return e-97+10<<24>>24;case 65:case 66:case 67:case 68:case 69:case 70:return e-65+10<<24>>24;default:throw J(new gd("Invalid hexadecimal"))}}function Qpn(e,t,n){var r,s,o,h;for(kr(n,"Processor order nodes",2),e.a=Ue(ft(K(t,(nw(),V_e)))),s=new as,h=ii(t.b,0);h.b!=h.d.c;)o=u(ri(h),86),It(Mt(K(o,(Tc(),$y))))&&ks(s,o,s.c.b,s.c);r=(Qn(s.b!=0),u(s.a.a.c,86)),$ut(e,r),!n.b&&tie(n,1),C5e(e,r,0-Ue(ft(K(r,(Tc(),bV))))/2,0),!n.b&&tie(n,1),ur(n)}function uz(){uz=pe,P7e=new O3("SPIRAL",0),D7e=new O3("LINE_BY_LINE",1),I7e=new O3("MANHATTAN",2),M7e=new O3("JITTER",3),Mue=new O3("QUADRANTS_LINE_BY_LINE",4),N7e=new O3("QUADRANTS_MANHATTAN",5),O7e=new O3("QUADRANTS_JITTER",6),L7e=new O3("COMBINE_LINE_BY_LINE_MANHATTAN",7),A7e=new O3("COMBINE_JITTER_MANHATTAN",8)}function xct(e,t,n,r){var s,o,h,d,v,x;for(v=mse(e,n),x=mse(t,n),s=!1;v&&x&&(r||Wun(v,x,n));)h=mse(v,n),d=mse(x,n),bD(t),bD(e),o=v.c,Eae(v,!1),Eae(x,!1),n?(ey(t,x.p,o),t.p=x.p,ey(e,v.p+1,o),e.p=v.p):(ey(e,v.p,o),e.p=v.p,ey(t,x.p+1,o),t.p=x.p),No(v,null),No(x,null),v=h,x=d,s=!0;return s}function Zpn(e,t,n,r){var s,o,h,d,v;for(s=!1,o=!1,d=new C(r.j);d.a=t.length)throw J(new Do("Greedy SwitchDecider: Free layer not in graph."));this.c=t[e],this.e=new zM(r),sie(this.e,this.c,(ht(),Dn)),this.i=new zM(r),sie(this.i,this.c,$n),this.f=new wKe(this.c),this.a=!o&&s.i&&!s.s&&this.c[0].k==(zn(),Ls),this.a&&p1n(this,e,t.length)}function Tct(e,t){var n,r,s,o,h,d;o=!e.B.Hc((wl(),nN)),h=e.B.Hc(gfe),e.a=new mrt(h,o,e.c),e.n&&hwe(e.a.n,e.n),Zee(e.g,(n1(),lu),e.a),t||(r=new W_(1,o,e.c),r.n.a=e.k,M6(e.p,(ht(),An),r),s=new W_(1,o,e.c),s.n.d=e.k,M6(e.p,xr,s),d=new W_(0,o,e.c),d.n.c=e.k,M6(e.p,Dn,d),n=new W_(0,o,e.c),n.n.b=e.k,M6(e.p,$n,n))}function e2n(e){var t,n,r;switch(t=u(K(e.d,(pt(),K0)),218),t.g){case 2:n=Myn(e);break;case 3:n=(r=new st,ms(Vi(Cu(ic(ic(new vn(null,new mn(e.d.b,16)),new TX),new _X),new M9),new gX),new Nee(r)),r);break;default:throw J(new Wo("Compaction not supported for "+t+" edges."))}Zvn(e,n),Da(new vm(e.g),new Iee(e))}function t2n(e,t){var n;return n=new b3,t&&Ho(n,u(er(e.a,iN),94)),we(t,470)&&Ho(n,u(er(e.a,sN),94)),we(t,354)?(Ho(n,u(er(e.a,Jo),94)),n):(we(t,82)&&Ho(n,u(er(e.a,mr),94)),we(t,239)?(Ho(n,u(er(e.a,hs),94)),n):we(t,186)?(Ho(n,u(er(e.a,xl),94)),n):(we(t,352)&&Ho(n,u(er(e.a,ra),94)),n))}function a1(){a1=pe,Q7=new fo((bi(),BV),ct(1)),eq=new fo(jb,80),ppt=new fo(GSe,5),apt=new fo(Bk,N7),dpt=new fo(ufe,ct(1)),gpt=new fo(lfe,(Mn(),!0)),Z7e=new kv(50),hpt=new fo(Fb,Z7e),Y7e=OV,J7e=BS,opt=new fo(efe,!1),Q7e=KO,lpt=p2,upt=Rb,cpt=J4,fpt=Hy,X7e=(m4e(),Jgt),zue=rpt,JG=Zgt,Hue=ept,eEe=npt}function n2n(e){var t,n,r,s,o,h,d,v;for(v=new TZe,d=new C(e.a);d.a0&&t=0)return!1;if(t.p=n.b,it(n.e,t),s==(zn(),ca)||s==Jc){for(h=new C(t.j);h.a1||h==-1)&&(o|=16),s.Bb&_c&&(o|=64)),n.Bb&so&&(o|=ky),o|=Sf):we(t,457)?o|=512:(r=t.Bj(),r&&r.i&1&&(o|=256)),e.Bb&512&&(o|=128),o}function oC(e,t){var n,r,s,o,h;for(e=e==null?Pu:(Sn(e),e),s=0;se.d[d.p]&&(n+=Gwe(e.b,o),$p(e.a,ct(o)))):++h;for(n+=e.b.d*h;!TT(e.a);)yme(e.b,u(I6(e.a),19).a)}return n}function h2n(e,t){var n;return e.f==Cfe?(n=Dv(Po((Yu(),Oa),t)),e.e?n==4&&t!=(nk(),Gk)&&t!=(nk(),zk)&&t!=(nk(),Sfe)&&t!=(nk(),Afe):n==2):e.d&&(e.d.Hc(t)||e.d.Hc(F6(Po((Yu(),Oa),t)))||e.d.Hc(v4((Yu(),Oa),e.b,t)))?!0:e.f&&l5e((Yu(),e.f),QM(Po(Oa,t)))?(n=Dv(Po(Oa,t)),e.e?n==4:n==2):!1}function f2n(e,t,n,r){var s,o,h,d,v,x,_,L;return h=u(Ft(n,(bi(),Rk)),8),v=h.a,_=h.b+e,s=b.Math.atan2(_,v),s<0&&(s+=_4),s+=t,s>_4&&(s-=_4),d=u(Ft(r,Rk),8),x=d.a,L=d.b+e,o=b.Math.atan2(L,x),o<0&&(o+=_4),o+=t,o>_4&&(o-=_4),S1(),Ef(1e-10),b.Math.abs(s-o)<=1e-10||s==o||isNaN(s)&&isNaN(o)?0:so?1:yv(isNaN(s),isNaN(o))}function eae(e){var t,n,r,s,o,h,d;for(d=new Mr,r=new C(e.a.b);r.a=e.o)throw J(new lpe);d=t>>5,h=t&31,o=A0(1,Or(A0(h,1))),s?e.n[n][d]=I1(e.n[n][d],o):e.n[n][d]=qs(e.n[n][d],pve(o)),o=A0(o,1),r?e.n[n][d]=I1(e.n[n][d],o):e.n[n][d]=qs(e.n[n][d],pve(o))}catch(v){throw v=ts(v),we(v,320)?J(new Do(koe+e.o+"*"+e.p+xoe+t+io+n+Eoe)):J(v)}}function C5e(e,t,n,r){var s,o,h;t&&(o=Ue(ft(K(t,(Tc(),qg))))+r,h=n+Ue(ft(K(t,bV)))/2,Ye(t,Che,ct(Or(Ou(b.Math.round(o))))),Ye(t,F_e,ct(Or(Ou(b.Math.round(h))))),t.d.b==0||C5e(e,u(sj((s=ii(new Ep(t).a.d,0),new f6(s))),86),n+Ue(ft(K(t,bV)))+e.a,r+Ue(ft(K(t,mE)))),K(t,_he)!=null&&C5e(e,u(K(t,_he),86),n,r))}function g2n(e,t){var n,r,s,o,h,d,v,x,_,L,P;for(v=Ya(t.a),s=Ue(ft(K(v,(pt(),Nb))))*2,_=Ue(ft(K(v,U4))),x=b.Math.max(s,_),o=Me(pa,Ao,25,t.f-t.c+1,15,1),r=-x,n=0,d=t.b.Kc();d.Ob();)h=u(d.Pb(),10),r+=e.a[h.c.p]+x,o[n++]=r;for(r+=e.a[t.a.c.p]+x,o[n++]=r,P=new C(t.e);P.a0&&(r=(!e.n&&(e.n=new at(Jo,e,1,7)),u(Te(e.n,0),137)).a,!r||Yr(Yr((t.a+=' "',t),r),'"'))),Yr(bv(Yr(bv(Yr(bv(Yr(bv((t.a+=" (",t),e.i),","),e.j)," | "),e.g),","),e.f),")"),t.a)}function Nct(e){var t,n,r;return e.Db&64?Mse(e):(t=new Fl(Qxe),n=e.k,n?Yr(Yr((t.a+=' "',t),n),'"'):(!e.n&&(e.n=new at(Jo,e,1,7)),e.n.i>0&&(r=(!e.n&&(e.n=new at(Jo,e,1,7)),u(Te(e.n,0),137)).a,!r||Yr(Yr((t.a+=' "',t),r),'"'))),Yr(bv(Yr(bv(Yr(bv(Yr(bv((t.a+=" (",t),e.i),","),e.j)," | "),e.g),","),e.f),")"),t.a)}function nae(e,t){var n,r,s,o,h,d,v;if(t==null||t.length==0)return null;if(s=u(Uc(e.a,t),149),!s){for(r=(d=new E1(e.b).a.vc().Kc(),new T1(d));r.a.Ob();)if(n=(o=u(r.a.Pb(),42),u(o.dd(),149)),h=n.c,v=t.length,an(h.substr(h.length-v,v),t)&&(t.length==h.length||Ma(h,h.length-t.length-1)==46)){if(s)return null;s=n}s&&Oo(e.a,t,s)}return s}function v2n(e,t){var n,r,s,o;return n=new Dh,r=u(zl(Cu(new vn(null,new mn(e.f,16)),n),zm(new Ri,new tn,new tr,new ha,ie(re(yl,1),tt,132,0,[(F1(),xy),Ql]))),21),s=r.gc(),r=u(zl(Cu(new vn(null,new mn(t.f,16)),n),zm(new Ri,new tn,new tr,new ha,ie(re(yl,1),tt,132,0,[xy,Ql]))),21),o=r.gc(),ss.p?(Vs(o,xr),o.d&&(d=o.o.b,t=o.a.b,o.a.b=d-t)):o.j==xr&&s.p>e.p&&(Vs(o,An),o.d&&(d=o.o.b,t=o.a.b,o.a.b=-(d-t)));break}return s}function m2n(e,t,n,r){var s,o,h,d,v,x,_,L,P,z,q;if(o=n,n1,d&&(r=new Pt(s,n.b),ci(t.a,r)),D_(t.a,ie(re(na,1),Qe,8,0,[P,L]))}function rae(e,t,n){var r,s,o,h,d,v;if(t)if(n<=-1){if(r=gn(t.Tg(),-1-n),we(r,99))return u(r,18);for(h=u(t.ah(r),153),d=0,v=h.gc();d0){for(s=v.length;s>0&&v[s-1]=="";)--s;s=40,h&&Mbn(e),Nvn(e),dpn(e),n=srt(e),r=0;n&&r0&&ci(e.f,o)):(e.c[h]-=x+1,e.c[h]<=0&&e.a[h]>0&&ci(e.e,o))))}function V2n(e){var t,n,r,s,o,h,d,v,x;for(d=new Sp(u(Nr(new lp),62)),x=Ds,n=new C(e.d);n.a=0&&vn?t:n;x<=L;++x)x==n?d=r++:(o=s[x],_=q.rl(o.ak()),x==t&&(v=x==L&&!_?r-1:r),_&&++r);return P=u(q_(e,t,n),72),d!=v&&Vx(e,new dD(e.e,7,h,ct(d),z.dd(),v)),P}}else return u(jse(e,t,n),72);return u(q_(e,t,n),72)}function Y2n(e,t){var n,r,s,o,h,d,v;for(kr(t,"Port order processing",1),v=u(K(e,(pt(),YTe)),421),r=new C(e.b);r.a=0&&(d=Zun(e,h),!(d&&(x<22?v.l|=1<>>1,h.m=_>>>1|(L&1)<<21,h.l=P>>>1|(_&1)<<21,--x;return n&&gie(v),o&&(r?(s2=U8(e),s&&(s2=Wtt(s2,(D8(),R8e)))):s2=fu(e.l,e.m,e.h)),v}function Z2n(e,t){var n,r,s,o,h,d,v,x,_,L;for(x=e.e[t.c.p][t.p]+1,v=t.c.a.c.length+1,d=new C(e.a);d.a0&&(zr(0,e.length),e.charCodeAt(0)==45||(zr(0,e.length),e.charCodeAt(0)==43))?1:0,r=h;rn)throw J(new gd(cw+e+'"'));return d}function J2n(e){var t,n,r,s,o,h,d;for(h=new as,o=new C(e.a);o.a1)&&t==1&&u(e.a[e.b],10).k==(zn(),Rl)?ik(u(e.a[e.b],10),(Ul(),d0)):r&&(!n||(e.c-e.b&e.a.length-1)>1)&&t==1&&u(e.a[e.c-1&e.a.length-1],10).k==(zn(),Rl)?ik(u(e.a[e.c-1&e.a.length-1],10),(Ul(),b2)):(e.c-e.b&e.a.length-1)==2?(ik(u(F_(e),10),(Ul(),d0)),ik(u(F_(e),10),b2)):W0n(e,s),Hwe(e)}function nbn(e,t,n){var r,s,o,h,d;for(o=0,s=new rr((!e.a&&(e.a=new at(hs,e,10,11)),e.a));s.e!=s.i.gc();)r=u(pr(s),33),h="",(!r.n&&(r.n=new at(Jo,r,1,7)),r.n).i==0||(h=u(Te((!r.n&&(r.n=new at(Jo,r,1,7)),r.n),0),137).a),d=new vie(o++,t,h),Ho(d,r),Ye(d,(Tc(),LS),r),d.e.b=r.j+r.f/2,d.f.a=b.Math.max(r.g,1),d.e.a=r.i+r.g/2,d.f.b=b.Math.max(r.f,1),ci(t.b,d),gu(n.f,r,d)}function rbn(e){var t,n,r,s,o;r=u(K(e,(et(),Mi)),33),o=u(Ft(r,(pt(),Ib)),174).Hc((Bl(),Hb)),e.e||(s=u(K(e,eu),21),t=new Pt(e.f.a+e.d.b+e.d.c,e.f.b+e.d.d+e.d.a),s.Hc((mo(),Th))?(So(r,bs,(wa(),tu)),sw(r,t.a,t.b,!1,!0)):It(Mt(Ft(r,Yle)))||sw(r,t.a,t.b,!0,!0)),o?So(r,Ib,rn(Hb)):So(r,Ib,(n=u(Qf(qS),9),new hh(n,u(wf(n,n.length),9),0)))}function N5e(e,t,n){var r,s,o,h;if(t[0]>=e.length)return n.o=0,!0;switch(Ma(e,t[0])){case 43:s=1;break;case 45:s=-1;break;default:return n.o=0,!0}if(++t[0],o=t[0],h=ZH(e,t),h==0&&t[0]==o)return!1;if(t[0]=0&&d!=n&&(o=new oa(e,1,d,h,null),r?r.Ei(o):r=o),n>=0&&(o=new oa(e,1,n,d==n?h:null,t),r?r.Ei(o):r=o)),r}function Zct(e){var t,n,r;if(e.b==null){if(r=new bg,e.i!=null&&(To(r,e.i),r.a+=":"),e.f&256){for(e.f&256&&e.a!=null&&(mJt(e.i)||(r.a+="//"),To(r,e.a)),e.d!=null&&(r.a+="/",To(r,e.d)),e.f&16&&(r.a+="/"),t=0,n=e.j.length;tP?!1:(L=(v=dC(r,P,!1),v.a),_+d+L<=t.b&&(fD(n,o-n.s),n.c=!0,fD(r,o-n.s),KD(r,n.s,n.t+n.d+d),r.k=!0,Ume(n.q,r),z=!0,s&&(q$(t,r),r.j=t,e.c.length>h&&(JD((xn(h,e.c.length),u(e.c[h],200)),r),(xn(h,e.c.length),u(e.c[h],200)).a.c.length==0&&Eg(e,h)))),z)}function hbn(e,t){var n,r,s,o,h,d;if(kr(t,"Partition midprocessing",1),s=new Nv,ms(Vi(new vn(null,new mn(e.a,16)),new RY),new ov(s)),s.d!=0){for(d=u(zl(GXe((o=s.i,new vn(null,(o||(s.i=new H3(s,s.c))).Nc()))),eb(new vt,new Dt,new Hn,ie(re(yl,1),tt,132,0,[(F1(),Ql)]))),15),r=d.Kc(),n=u(r.Pb(),19);r.Ob();)h=u(r.Pb(),19),ggn(u(Ii(s,n),21),u(Ii(s,h),21)),n=h;ur(t)}}function tut(e,t,n){var r,s,o,h,d,v,x,_;if(t.p==0){for(t.p=1,h=n,h||(s=new st,o=(r=u(Qf(ao),9),new hh(r,u(wf(r,r.length),9),0)),h=new xa(s,o)),u(h.a,15).Fc(t),t.k==(zn(),Ls)&&u(h.b,21).Fc(u(K(t,(et(),vc)),61)),v=new C(t.j);v.a0){if(s=u(e.Ab.g,1934),t==null){for(o=0;o1)for(r=new C(s);r.an.s&&dd&&(d=s,_.c=Me(Yn,yt,1,0,5,1)),s==d&&it(_,new xa(n.c.i,n)));hn(),aa(_,e.c),Om(e.b,v.p,_)}}function vbn(e,t){var n,r,s,o,h,d,v,x,_;for(h=new C(t.b);h.ad&&(d=s,_.c=Me(Yn,yt,1,0,5,1)),s==d&&it(_,new xa(n.d.i,n)));hn(),aa(_,e.c),Om(e.f,v.p,_)}}function rut(e){wv(e,new gb(gv(hv(dv(fv(new lg,fw),"ELK Box"),"Algorithm for packing of unconnected boxes, i.e. graphs without edges."),new MZ))),dt(e,fw,uw,hSe),dt(e,fw,py,15),dt(e,fw,FI,ct(0)),dt(e,fw,uG,xt(cSe)),dt(e,fw,E4,xt(Kyt)),dt(e,fw,dk,xt(Yyt)),dt(e,fw,fk,t1t),dt(e,fw,jI,xt(uSe)),dt(e,fw,gk,xt(lSe)),dt(e,fw,Vxe,xt(Xhe)),dt(e,fw,rG,xt(Wyt))}function iut(e,t){var n,r,s,o,h,d,v,x,_;if(s=e.i,h=s.o.a,o=s.o.b,h<=0&&o<=0)return ht(),uc;switch(x=e.n.a,_=e.n.b,d=e.o.a,n=e.o.b,t.g){case 2:case 1:if(x<0)return ht(),Dn;if(x+d>h)return ht(),$n;break;case 4:case 3:if(_<0)return ht(),An;if(_+n>o)return ht(),xr}return v=(x+d/2)/h,r=(_+n/2)/o,v+r<=1&&v-r<=0?(ht(),Dn):v+r>=1&&v-r>=0?(ht(),$n):r<.5?(ht(),An):(ht(),xr)}function wbn(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W;for(n=!1,_=Ue(ft(K(t,(pt(),Aw)))),q=Jp*_,s=new C(t.b);s.av+q&&(W=L.g+P.g,P.a=(P.g*P.a+L.g*L.a)/W,P.g=W,L.f=P,n=!0)),o=d,L=P;return n}function sut(e,t,n,r,s,o,h){var d,v,x,_,L,P;for(P=new T6,x=t.Kc();x.Ob();)for(d=u(x.Pb(),839),L=new C(d.wf());L.a0?d.a?(x=d.b.rf().b,s>x&&(e.v||d.c.d.c.length==1?(h=(s-x)/2,d.d.d=h,d.d.a=h):(n=u(St(d.c.d,0),181).rf().b,r=(n-x)/2,d.d.d=b.Math.max(0,r),d.d.a=s-r-x))):d.d.a=e.t+s:g_(e.u)&&(o=u4e(d.b),o.d<0&&(d.d.d=-o.d),o.d+o.a>d.b.rf().b&&(d.d.a=o.d+o.a-d.b.rf().b))}function kbn(e,t){var n;switch(yD(e)){case 6:return fa(t);case 7:return Sm(t);case 8:return Cm(t);case 3:return Array.isArray(t)&&(n=yD(t),!(n>=14&&n<=16));case 11:return t!=null&&typeof t===Dae;case 12:return t!=null&&(typeof t===TI||typeof t==Dae);case 0:return ese(t,e.__elementTypeId$);case 2:return Fne(t)&&t.im!==gt;case 1:return Fne(t)&&t.im!==gt||ese(t,e.__elementTypeId$);default:return!0}}function aut(e,t){var n,r,s,o;return r=b.Math.min(b.Math.abs(e.c-(t.c+t.b)),b.Math.abs(e.c+e.b-t.c)),o=b.Math.min(b.Math.abs(e.d-(t.d+t.a)),b.Math.abs(e.d+e.a-t.d)),n=b.Math.abs(e.c+e.b/2-(t.c+t.b/2)),n>e.b/2+t.b/2||(s=b.Math.abs(e.d+e.a/2-(t.d+t.a/2)),s>e.a/2+t.a/2)?1:n==0&&s==0?0:n==0?o/s+1:s==0?r/n+1:b.Math.min(r/n,o/s)+1}function out(e,t){var n,r,s,o,h,d;return s=Mme(e),d=Mme(t),s==d?e.e==t.e&&e.a<54&&t.a<54?e.ft.f?1:0:(r=e.e-t.e,n=(e.d>0?e.d:b.Math.floor((e.a-1)*wht)+1)-(t.d>0?t.d:b.Math.floor((t.a-1)*wht)+1),n>r+1?s:n0&&(h=W3(h,Lut(r))),jrt(o,h))):s0&&e.d!=(L_(),Vue)&&(d+=h*(r.d.a+e.a[t.b][r.b]*(t.d.a-r.d.a)/n)),n>0&&e.d!=(L_(),Gue)&&(v+=h*(r.d.b+e.a[t.b][r.b]*(t.d.b-r.d.b)/n)));switch(e.d.g){case 1:return new Pt(d/o,t.d.b);case 2:return new Pt(t.d.a,v/o);default:return new Pt(d/o,v/o)}}function cut(e,t){X8();var n,r,s,o,h;if(h=u(K(e.i,(pt(),bs)),98),o=e.j.g-t.j.g,o!=0||!(h==(wa(),$b)||h==p0||h==tu))return 0;if(h==(wa(),$b)&&(n=u(K(e,zg),19),r=u(K(t,zg),19),n&&r&&(s=n.a-r.a,s!=0)))return s;switch(e.j.g){case 1:return Fs(e.n.a,t.n.a);case 2:return Fs(e.n.b,t.n.b);case 3:return Fs(t.n.a,e.n.a);case 4:return Fs(t.n.b,e.n.b);default:throw J(new Wo(eke))}}function uut(e){var t,n,r,s,o,h;for(n=(!e.a&&(e.a=new Bs(ef,e,5)),e.a).i+2,h=new su(n),it(h,new Pt(e.j,e.k)),ms(new vn(null,(!e.a&&(e.a=new Bs(ef,e,5)),new mn(e.a,16))),new t$e(h)),it(h,new Pt(e.b,e.c)),t=1;t0&&(ND(v,!1,(wo(),Xh)),ND(v,!0,Df)),Mu(t.g,new ZGe(e,n)),Si(e.g,t,n)}function hut(){hut=pe;var e;for(V8e=ie(re(Lr,1),Jr,25,15,[-1,-1,30,19,15,13,11,11,10,9,9,8,8,8,8,7,7,7,7,7,7,7,6,6,6,6,6,6,6,6,6,6,6,6,6,6,5]),kue=Me(Lr,Jr,25,37,15,1),O0t=ie(re(Lr,1),Jr,25,15,[-1,-1,63,40,32,28,25,23,21,20,19,19,18,18,17,17,16,16,16,15,15,15,15,14,14,14,14,14,14,13,13,13,13,13,13,13,13]),U8e=Me(S2,roe,25,37,14,1),e=2;e<=36;e++)kue[e]=_s(b.Math.pow(e,V8e[e])),U8e[e]=eI(Cz,kue[e])}function Ebn(e){var t;if((!e.a&&(e.a=new at(os,e,6,6)),e.a).i!=1)throw J(new Ln(y1t+(!e.a&&(e.a=new at(os,e,6,6)),e.a).i));return t=new Gu,ID(u(Te((!e.b&&(e.b=new wn(mr,e,4,7)),e.b),0),82))&&no(t,Wlt(e,ID(u(Te((!e.b&&(e.b=new wn(mr,e,4,7)),e.b),0),82)),!1)),ID(u(Te((!e.c&&(e.c=new wn(mr,e,5,8)),e.c),0),82))&&no(t,Wlt(e,ID(u(Te((!e.c&&(e.c=new wn(mr,e,5,8)),e.c),0),82)),!0)),t}function fut(e,t){var n,r,s,o,h;for(t.d?s=e.a.c==(yd(),Lw)?Xo(t.b):js(t.b):s=e.a.c==(yd(),Gg)?Xo(t.b):js(t.b),o=!1,r=new cr(fr(s.a.Kc(),new V));Vr(r);)if(n=u(Pr(r),17),h=It(e.a.f[e.a.g[t.b.p].p]),!(!h&&!to(n)&&n.c.i.c==n.d.i.c)&&!(It(e.a.n[e.a.g[t.b.p].p])||It(e.a.n[e.a.g[t.b.p].p]))&&(o=!0,_0(e.b,e.a.g[Oun(n,t.b).p])))return t.c=!0,t.a=n,t;return t.c=o,t.a=null,t}function Tbn(e,t,n,r,s){var o,h,d,v,x,_,L;for(hn(),aa(e,new FZ),d=new Ea(e,0),L=new st,o=0;d.bo*2?(_=new H$(L),x=Wu(h)/Dl(h),v=Sae(_,t,new g6,n,r,s,x),Ni(Zf(_.e),v),L.c=Me(Yn,yt,1,0,5,1),o=0,L.c[L.c.length]=_,L.c[L.c.length]=h,o=Wu(_)*Dl(_)+Wu(h)*Dl(h)):(L.c[L.c.length]=h,o+=Wu(h)*Dl(h));return L}function B5e(e,t,n){var r,s,o,h,d,v,x;if(r=n.gc(),r==0)return!1;if(e.ej())if(v=e.fj(),Qye(e,t,n),h=r==1?e.Zi(3,null,n.Kc().Pb(),t,v):e.Zi(5,null,n,t,v),e.bj()){for(d=r<100?null:new _p(r),o=t+r,s=t;s0){for(h=0;h>16==-15&&e.Cb.nh()&&Gre(new jre(e.Cb,9,13,n,e.c,Dg(gl(u(e.Cb,59)),e))):we(e.Cb,88)&&e.Db>>16==-23&&e.Cb.nh()&&(t=e.c,we(t,88)||(t=(on(),sf)),we(n,88)||(n=(on(),sf)),Gre(new jre(e.Cb,9,10,n,t,Dg(jc(u(e.Cb,26)),e)))))),e.c}function _bn(e,t){var n,r,s,o,h,d,v,x,_,L;for(kr(t,"Hypernodes processing",1),s=new C(e.b);s.an);return s}function gut(e,t){var n,r,s;r=vl(e.d,1)!=0,!It(Mt(K(t.j,(et(),kw))))&&!It(Mt(K(t.j,z4)))||je(K(t.j,(pt(),h2)))===je((R0(),f2))?t.c.Tf(t.e,r):r=It(Mt(K(t.j,kw))),gI(e,t,r,!0),It(Mt(K(t.j,z4)))&&Ye(t.j,z4,(Mn(),!1)),It(Mt(K(t.j,kw)))&&(Ye(t.j,kw,(Mn(),!1)),Ye(t.j,z4,!0)),n=Pse(e,t);do{if(zme(e),n==0)return 0;r=!r,s=n,gI(e,t,r,!1),n=Pse(e,t)}while(s>n);return s}function put(e,t,n){var r,s,o,h,d,v,x,_,L,P,z,q;if(t==n)return!0;if(t=U4e(e,t),n=U4e(e,n),r=ose(t),r){if(_=ose(n),_!=r)return _?(v=r.Dj(),q=_.Dj(),v==q&&v!=null):!1;if(h=(!t.d&&(t.d=new Bs(Eo,t,1)),t.d),o=h.i,P=(!n.d&&(n.d=new Bs(Eo,n,1)),n.d),o==P.i){for(x=0;x0,d=kH(t,o),dbe(n?d.b:d.g,t),t4(d).c.length==1&&ks(r,d,r.c.b,r.c),s=new xa(o,t),$p(e.o,s),Au(e.e.a,o))}function mut(e,t){var n,r,s,o,h,d,v;return r=b.Math.abs(jj(e.b).a-jj(t.b).a),d=b.Math.abs(jj(e.b).b-jj(t.b).b),s=0,v=0,n=1,h=1,r>e.b.b/2+t.b.b/2&&(s=b.Math.min(b.Math.abs(e.b.c-(t.b.c+t.b.b)),b.Math.abs(e.b.c+e.b.b-t.b.c)),n=1-s/r),d>e.b.a/2+t.b.a/2&&(v=b.Math.min(b.Math.abs(e.b.d-(t.b.d+t.b.a)),b.Math.abs(e.b.d+e.b.a-t.b.d)),h=1-v/d),o=b.Math.min(n,h),(1-o)*b.Math.sqrt(r*r+d*d)}function Dbn(e){var t,n,r,s;for(Cae(e,e.e,e.f,(Ov(),g2),!0,e.c,e.i),Cae(e,e.e,e.f,g2,!1,e.c,e.i),Cae(e,e.e,e.f,Y4,!0,e.c,e.i),Cae(e,e.e,e.f,Y4,!1,e.c,e.i),Obn(e,e.c,e.e,e.f,e.i),r=new Ea(e.i,0);r.b=65;n--)J1[n]=n-65<<24>>24;for(r=122;r>=97;r--)J1[r]=r-97+26<<24>>24;for(s=57;s>=48;s--)J1[s]=s-48+52<<24>>24;for(J1[43]=62,J1[47]=63,o=0;o<=25;o++)Zg[o]=65+o&Ss;for(h=26,v=0;h<=51;++h,v++)Zg[h]=97+v&Ss;for(e=52,d=0;e<=61;++e,d++)Zg[e]=48+d&Ss;Zg[62]=43,Zg[63]=47}function Ibn(e,t){var n,r,s,o,h,d,v,x,_,L,P,z;if(e.dc())return new Fa;for(x=0,L=0,s=e.Kc();s.Ob();)r=u(s.Pb(),37),o=r.f,x=b.Math.max(x,o.a),L+=o.a*o.b;for(x=b.Math.max(x,b.Math.sqrt(L)*Ue(ft(K(u(e.Kc().Pb(),37),(pt(),Hq))))),P=0,z=0,v=0,n=t,d=e.Kc();d.Ob();)h=u(d.Pb(),37),_=h.f,P+_.a>x&&(P=0,z+=v+t,v=0),cC(h,P,z),n=b.Math.max(n,P+_.a),v=b.Math.max(v,_.b),P+=_.a+t;return new Pt(n+t,z+v+t)}function Obn(e,t,n,r,s){var o,h,d,v,x,_,L;for(h=new C(t);h.ao)return ht(),$n;break;case 4:case 3:if(v<0)return ht(),An;if(v+e.f>s)return ht(),xr}return h=(d+e.g/2)/o,n=(v+e.f/2)/s,h+n<=1&&h-n<=0?(ht(),Dn):h+n>=1&&h-n>=0?(ht(),$n):n<.5?(ht(),An):(ht(),xr)}function Nbn(e,t,n,r,s){var o,h;if(o=Ua(qs(t[0],yo),qs(r[0],yo)),e[0]=Or(o),o=Np(o,32),n>=s){for(h=1;h0&&(s.b[h++]=0,s.b[h++]=o.b[0]-1),t=1;t0&&(tM(v,v.d-s.d),s.c==(Jf(),d2)&&Wge(v,v.a-s.d),v.d<=0&&v.i>0&&ks(t,v,t.c.b,t.c)));for(o=new C(e.f);o.a0&&(hT(d,d.i-s.d),s.c==(Jf(),d2)&&sv(d,d.b-s.d),d.i<=0&&d.d>0&&ks(n,d,n.c.b,n.c)))}function Pbn(e,t,n){var r,s,o,h,d,v,x,_;for(kr(n,"Processor compute fanout",1),sl(e.b),sl(e.a),d=null,o=ii(t.b,0);!d&&o.b!=o.d.c;)x=u(ri(o),86),It(Mt(K(x,(Tc(),$y))))&&(d=x);for(v=new as,ks(v,d,v.c.b,v.c),Mlt(e,v),_=ii(t.b,0);_.b!=_.d.c;)x=u(ri(_),86),h=Hr(K(x,(Tc(),AS))),s=Uc(e.b,h)!=null?u(Uc(e.b,h),19).a:0,Ye(x,gV,ct(s)),r=1+(Uc(e.a,h)!=null?u(Uc(e.a,h),19).a:0),Ye(x,cmt,ct(r));ur(n)}function Bbn(e,t,n,r,s){var o,h,d,v,x,_,L,P,z,q;for(P=mhn(e,n),v=0;v0),r.a.Xb(r.c=--r.b),L>P+v&&Ol(r);for(h=new C(z);h.a0),r.a.Xb(r.c=--r.b)}}function Rbn(){yi();var e,t,n,r,s,o;if(Mfe)return Mfe;for(e=new Hl(4),ly(e,Zp(cue,!0)),bC(e,Zp("M",!0)),bC(e,Zp("C",!0)),o=new Hl(4),r=0;r<11;r++)Yc(o,r,r);return t=new Hl(4),ly(t,Zp("M",!0)),Yc(t,4448,4607),Yc(t,65438,65439),s=new e_(2),pb(s,e),pb(s,nA),n=new e_(2),n.$l(Ij(o,Zp("L",!0))),n.$l(t),n=new $m(3,n),n=new Xve(s,n),Mfe=n,Mfe}function Fbn(e){var t,n;if(t=Hr(Ft(e,(bi(),PS))),!Ptt(t,e)&&!J2(e,xE)&&((!e.a&&(e.a=new at(hs,e,10,11)),e.a).i!=0||It(Mt(Ft(e,UO)))))if(t==null||ny(t).length==0){if(!Ptt(qn,e))throw n=Yr(Yr(new Fl("Unable to load default layout algorithm "),qn)," for unconfigured node "),yz(e,n),J(new M3(n.a))}else throw n=Yr(Yr(new Fl("Layout algorithm '"),t),"' not found for "),yz(e,n),J(new M3(n.a))}function uae(e){var t,n,r,s,o,h,d,v,x,_,L,P,z;if(n=e.i,t=e.n,e.b==0)for(z=n.c+t.b,P=n.b-t.b-t.c,h=e.a,v=0,_=h.length;v<_;++v)s=h[v],Nj(s,z,P);else r=vit(e,!1),Nj(e.a[0],n.c+t.b,r[0]),Nj(e.a[2],n.c+n.b-t.c-r[2],r[2]),L=n.b-t.b-t.c,r[0]>0&&(L-=r[0]+e.c,r[0]+=e.c),r[2]>0&&(L-=r[2]+e.c),r[1]=b.Math.max(r[1],L),Nj(e.a[1],n.c+t.b+r[0]-(r[1]-L)/2,r[1]);for(o=e.a,d=0,x=o.length;d0?(e.n.c.length-1)*e.i:0,r=new C(e.n);r.a1)for(r=ii(s,0);r.b!=r.d.c;)for(n=u(ri(r),231),o=0,v=new C(n.e);v.a0&&(t[0]+=e.c,L-=t[0]),t[2]>0&&(L-=t[2]+e.c),t[1]=b.Math.max(t[1],L),Pj(e.a[1],r.d+n.d+t[0]-(t[1]-L)/2,t[1]);else for(q=r.d+n.d,z=r.a-n.d-n.a,h=e.a,v=0,_=h.length;v<_;++v)s=h[v],Pj(s,q,z);for(o=e.a,d=0,x=o.length;d=0&&o!=n))throw J(new Ln(YI));for(s=0,v=0;v0||Kv(s.b.d,e.b.d+e.b.a)==0&&r.b<0||Kv(s.b.d+s.b.a,e.b.d)==0&&r.b>0){d=0;break}}else d=b.Math.min(d,Eat(e,s,r));d=b.Math.min(d,Eut(e,o,d,r))}return d}function mI(e,t){var n,r,s,o,h,d,v;if(e.b<2)throw J(new Ln("The vector chain must contain at least a source and a target point."));for(s=(Qn(e.b!=0),u(e.a.a.c,8)),nj(t,s.a,s.b),v=new _6((!t.a&&(t.a=new Bs(ef,t,5)),t.a)),h=ii(e,1);h.aUe(A1(h.g,h.d[0]).a)?(Qn(v.b>0),v.a.Xb(v.c=--v.b),Dm(v,h),s=!0):d.e&&d.e.gc()>0&&(o=(!d.e&&(d.e=new st),d.e).Mc(t),x=(!d.e&&(d.e=new st),d.e).Mc(n),(o||x)&&((!d.e&&(d.e=new st),d.e).Fc(h),++h.c));s||(r.c[r.c.length]=h)}function Cut(e){var t,n,r;if(R3(u(K(e,(pt(),bs)),98)))for(n=new C(e.j);n.a>>0,"0"+t.toString(16)),r="\\x"+jl(n,n.length-2,n.length)):e>=so?(n=(t=e>>>0,"0"+t.toString(16)),r="\\v"+jl(n,n.length-6,n.length)):r=""+String.fromCharCode(e&Ss)}return r}function hae(e,t){var n,r,s,o,h,d,v,x,_,L;if(h=e.e,v=t.e,v==0)return e;if(h==0)return t.e==0?t:new z3(-t.e,t.d,t.a);if(o=e.d,d=t.d,o+d==2)return n=qs(e.a[0],yo),r=qs(t.a[0],yo),h<0&&(n=M8(n)),v<0&&(r=M8(r)),WD(Wp(n,r));if(s=o!=d?o>d?1:-1:mye(e.a,t.a,o),s==-1)L=-v,_=h==v?Ore(t.a,d,e.a,o):Pre(t.a,d,e.a,o);else if(L=h,h==v){if(s==0)return Qp(),K7;_=Ore(e.a,o,t.a,d)}else _=Pre(e.a,o,t.a,d);return x=new z3(L,_.length,_),E_(x),x}function G5e(e){var t,n,r,s,o,h;for(this.e=new st,this.a=new st,n=e.b-1;n<3;n++)c8(e,0,u(s1(e,0),8));if(e.b<4)throw J(new Ln("At (least dimension + 1) control points are necessary!"));for(this.b=3,this.d=!0,this.c=!1,M0n(this,e.b+this.b-1),h=new st,o=new C(this.e),t=0;t=t.o&&n.f<=t.f||t.a*.5<=n.f&&t.a*1.5>=n.f){if(h=u(St(t.n,t.n.c.length-1),211),h.e+h.d+n.g+s<=r&&(o=u(St(t.n,t.n.c.length-1),211),o.f-e.f+n.f<=e.b||e.a.c.length==1))return zye(t,n),!0;if(t.s+n.g<=r&&(t.t+t.d+n.f+s<=e.b||e.a.c.length==1))return it(t.b,n),d=u(St(t.n,t.n.c.length-1),211),it(t.n,new o$(t.s,d.f+d.a+t.i,t.i)),T3e(u(St(t.n,t.n.c.length-1),211),n),yut(t,n),!0}return!1}function Aut(e,t,n){var r,s,o,h;return e.ej()?(s=null,o=e.fj(),r=e.Zi(1,h=Vre(e,t,n),n,t,o),e.bj()&&!(e.ni()&&h!=null?Ci(h,n):je(h)===je(n))?(h!=null&&(s=e.dj(h,s)),s=e.cj(n,s),e.ij()&&(s=e.lj(h,n,s)),s?(s.Ei(r),s.Fi()):e.$i(r)):(e.ij()&&(s=e.lj(h,n,s)),s?(s.Ei(r),s.Fi()):e.$i(r)),h):(h=Vre(e,t,n),e.bj()&&!(e.ni()&&h!=null?Ci(h,n):je(h)===je(n))&&(s=null,h!=null&&(s=e.dj(h,null)),s=e.cj(n,s),s&&s.Fi()),h)}function lC(e,t){var n,r,s,o,h,d,v,x;t%=24,e.q.getHours()!=t&&(r=new b.Date(e.q.getTime()),r.setDate(r.getDate()+1),d=e.q.getTimezoneOffset()-r.getTimezoneOffset(),d>0&&(v=d/60|0,x=d%60,s=e.q.getDate(),n=e.q.getHours(),n+v>=24&&++s,o=new b.Date(e.q.getFullYear(),e.q.getMonth(),s,t+v,e.q.getMinutes()+x,e.q.getSeconds(),e.q.getMilliseconds()),e.q.setTime(o.getTime()))),h=e.q.getTime(),e.q.setTime(h+36e5),e.q.getHours()!=t&&e.q.setTime(h)}function Wbn(e,t){var n,r,s,o,h;if(kr(t,"Path-Like Graph Wrapping",1),e.b.c.length==0){ur(t);return}if(s=new X4e(e),h=(s.i==null&&(s.i=Gme(s,new AB)),Ue(s.i)*s.f),n=h/(s.i==null&&(s.i=Gme(s,new AB)),Ue(s.i)),s.b>n){ur(t);return}switch(u(K(e,(pt(),ehe)),337).g){case 2:o=new MB;break;case 0:o=new SB;break;default:o=new DB}if(r=o.Vf(e,s),!o.Wf())switch(u(K(e,tV),338).g){case 2:r=Tat(s,r);break;case 1:r=Est(s,r)}qvn(e,s,r),ur(t)}function Kbn(e,t){var n,r,s,o;if(Ien(e.d,e.e),e.c.a.$b(),Ue(ft(K(t.j,(pt(),qq))))!=0||Ue(ft(K(t.j,qq)))!=0)for(n=O7,je(K(t.j,h2))!==je((R0(),f2))&&Ye(t.j,(et(),kw),(Mn(),!0)),o=u(K(t.j,vS),19).a,s=0;ss&&++x,it(h,(xn(d+x,t.c.length),u(t.c[d+x],19))),v+=(xn(d+x,t.c.length),u(t.c[d+x],19)).a-r,++n;n1&&(v>Wu(d)*Dl(d)/2||h.b==0)&&(L=new H$(P),_=Wu(d)/Dl(d),x=Sae(L,t,new g6,n,r,s,_),Ni(Zf(L.e),x),d=L,z.c[z.c.length]=L,v=0,P.c=Me(Yn,yt,1,0,5,1)));return Rs(z,P),z}function Qbn(e,t,n,r){var s,o,h,d,v,x,_,L,P,z,q,W;if(n.mh(t)&&(_=(z=t,z?u(r,49).xh(z):null),_))if(W=n.bh(t,e.a),q=t.t,q>1||q==-1)if(L=u(W,69),P=u(_,69),L.dc())P.$b();else for(h=!!go(t),o=0,d=e.a?L.Kc():L.Zh();d.Ob();)x=u(d.Pb(),56),s=u(Fv(e,x),56),s?(h?(v=P.Xc(s),v==-1?P.Xh(o,s):o!=v&&P.ji(o,s)):P.Xh(o,s),++o):e.b&&!h&&(P.Xh(o,x),++o);else W==null?_.Wb(null):(s=Fv(e,W),s==null?e.b&&!go(t)&&_.Wb(W):_.Wb(s))}function Zbn(e,t){var n,r,s,o,h,d,v,x;for(n=new TY,s=new cr(fr(Xo(t).a.Kc(),new V));Vr(s);)if(r=u(Pr(s),17),!to(r)&&(d=r.c.i,a4e(d,iq))){if(x=k5e(e,d,iq,rq),x==-1)continue;n.b=b.Math.max(n.b,x),!n.a&&(n.a=new st),it(n.a,d)}for(h=new cr(fr(js(t).a.Kc(),new V));Vr(h);)if(o=u(Pr(h),17),!to(o)&&(v=o.d.i,a4e(v,rq))){if(x=k5e(e,v,rq,iq),x==-1)continue;n.d=b.Math.max(n.d,x),!n.c&&(n.c=new st),it(n.c,v)}return n}function Lut(e){d7();var t,n,r,s;if(t=_s(e),e1e6)throw J(new lF("power of ten too big"));if(e<=Ei)return $6(lI(yk[1],t),t);for(r=lI(yk[1],Ei),s=r,n=Ou(e-Ei),t=_s(e%Ei);Mc(n,Ei)>0;)s=W3(s,r),n=Wp(n,Ei);for(s=W3(s,lI(yk[1],t)),s=$6(s,Ei),n=Ou(e-Ei);Mc(n,Ei)>0;)s=$6(s,Ei),n=Wp(n,Ei);return s=$6(s,t),s}function Jbn(e,t){var n,r,s,o,h,d,v,x,_;for(kr(t,"Hierarchical port dummy size processing",1),v=new st,_=new st,r=Ue(ft(K(e,(pt(),V4)))),n=r*2,o=new C(e.b);o.ax&&r>x)_=d,x=Ue(t.p[d.p])+Ue(t.d[d.p])+d.o.b+d.d.a;else{s=!1,n.n&&V2(n,"bk node placement breaks on "+d+" which should have been after "+_);break}if(!s)break}return n.n&&V2(n,t+" is feasible: "+s),s}function ivn(e,t,n,r){var s,o,h,d,v,x,_;for(d=-1,_=new C(e);_.a<_.c.c.length;)x=u(Y(_),112),x.g=d--,s=Or(g$(Yj(Vi(new vn(null,new mn(x.f,16)),new AQ),new LQ)).d),o=Or(g$(Yj(Vi(new vn(null,new mn(x.k,16)),new MQ),new U5)).d),h=s,v=o,r||(h=Or(g$(Yj(new vn(null,new mn(x.f,16)),new DQ)).d),v=Or(g$(Yj(new vn(null,new mn(x.k,16)),new IQ)).d)),x.d=h,x.a=s,x.i=v,x.b=o,v==0?ks(n,x,n.c.b,n.c):h==0&&ks(t,x,t.c.b,t.c)}function svn(e,t,n,r){var s,o,h,d,v,x,_;if(n.d.i!=t.i){for(s=new H0(e),T0(s,(zn(),ca)),Ye(s,(et(),Mi),n),Ye(s,(pt(),bs),(wa(),tu)),r.c[r.c.length]=s,h=new $c,rc(h,s),Vs(h,(ht(),Dn)),d=new $c,rc(d,s),Vs(d,$n),_=n.d,ba(n,h),o=new Iv,Ho(o,n),Ye(o,Fo,null),Va(o,d),ba(o,_),x=new Ea(n.b,0);x.b=X&&e.e[v.p]>q*e.b||Ee>=n*X)&&(P.c[P.c.length]=d,d=new st,no(h,o),o.a.$b(),x-=_,z=b.Math.max(z,x*e.b+W),x+=Ee,Ce=Ee,Ee=0,_=0,W=0);return new xa(z,P)}function cvn(e){var t,n,r,s,o,h,d,v,x,_,L,P,z;for(n=(x=new E1(e.c.b).a.vc().Kc(),new T1(x));n.a.Ob();)t=(d=u(n.a.Pb(),42),u(d.dd(),149)),s=t.a,s==null&&(s=""),r=NKt(e.c,s),!r&&s.length==0&&(r=Pan(e)),r&&!Xm(r.c,t,!1)&&ci(r.c,t);for(h=ii(e.a,0);h.b!=h.d.c;)o=u(ri(h),478),_=Lre(e.c,o.a),z=Lre(e.c,o.b),_&&z&&ci(_.c,new xa(z,o.c));for(Rh(e.a),P=ii(e.b,0);P.b!=P.d.c;)L=u(ri(P),478),t=OKt(e.c,L.a),v=Lre(e.c,L.b),t&&v&&EUt(t,v,L.c);Rh(e.b)}function uvn(e,t,n){var r,s,o,h,d,v,x,_,L,P,z;o=new $x(e),h=new Yit,s=(oD(h.g),oD(h.j),sl(h.b),oD(h.d),oD(h.i),sl(h.k),sl(h.c),sl(h.e),z=Iat(h,o,null),kot(h,o),z),t&&(x=new $x(t),d=mvn(x),w4e(s,ie(re(nSe,1),yt,527,0,[d]))),P=!1,L=!1,n&&(x=new $x(n),bG in x.a&&(P=M0(x,bG).ge().a),q1t in x.a&&(L=M0(x,q1t).ge().a)),_=hze(zet(new Ux,P),L),n1n(new dZ,s,_),bG in o.a&&t1(o,bG,null),(P||L)&&(v=new p6,_ut(_,v,P,L),t1(o,bG,v)),r=new w$e(h),Xsn(new H2e(s),r)}function lvn(e,t,n){var r,s,o,h,d,v,x,_,L;for(h=new est,x=ie(re(Lr,1),Jr,25,15,[0]),s=-1,o=0,r=0,v=0;v0){if(s<0&&_.a&&(s=v,o=x[0],r=0),s>=0){if(d=_.b,v==s&&(d-=r++,d==0))return 0;if(!Ilt(t,x,_,d,h)){v=s-1,x[0]=o;continue}}else if(s=-1,!Ilt(t,x,_,0,h))return 0}else{if(s=-1,Ma(_.c,0)==32){if(L=x[0],QJe(t,x),x[0]>L)continue}else if(qJt(t,_.c,x[0])){x[0]+=_.c.length;continue}return 0}return qmn(h,n)?x[0]:0}function fC(e){var t,n,r,s,o,h,d,v;if(!e.f){if(v=new E0,d=new E0,t=XS,h=t.a.zc(e,t),h==null){for(o=new rr(jo(e));o.e!=o.i.gc();)s=u(pr(o),26),fs(v,fC(s));t.a.Bc(e)!=null,t.a.gc()==0}for(r=(!e.s&&(e.s=new at(ju,e,21,17)),new rr(e.s));r.e!=r.i.gc();)n=u(pr(r),170),we(n,99)&&Br(d,u(n,18));Km(d),e.r=new GWe(e,(u(Te(He((Rp(),En).o),6),18),d.i),d.g),fs(v,e.r),Km(v),e.f=new B3((u(Te(He(En.o),5),18),v.i),v.g),dl(e).b&=-3}return e.f}function hvn(e){var t,n,r,s,o,h,d,v,x,_,L,P,z,q;for(h=e.o,r=Me(Lr,Jr,25,h,15,1),s=Me(Lr,Jr,25,h,15,1),n=e.p,t=Me(Lr,Jr,25,n,15,1),o=Me(Lr,Jr,25,n,15,1),x=0;x=0&&!i4(e,_,L);)--L;s[_]=L}for(z=0;z=0&&!i4(e,d,q);)--d;o[q]=d}for(v=0;vt[P]&&Pr[v]&&hz(e,v,P,!1,!0)}function q5e(e){var t,n,r,s,o,h,d,v;n=It(Mt(K(e,(a1(),opt)))),o=e.a.c.d,d=e.a.d.d,n?(h=bd(da(new Pt(d.a,d.b),o),.5),v=bd(fc(e.e),.5),t=da(Ni(new Pt(o.a,o.b),h),v),ybe(e.d,t)):(s=Ue(ft(K(e.a,ppt))),r=e.d,o.a>=d.a?o.b>=d.b?(r.a=d.a+(o.a-d.a)/2+s,r.b=d.b+(o.b-d.b)/2-s-e.e.b):(r.a=d.a+(o.a-d.a)/2+s,r.b=o.b+(d.b-o.b)/2+s):o.b>=d.b?(r.a=o.a+(d.a-o.a)/2+s,r.b=d.b+(o.b-d.b)/2+s):(r.a=o.a+(d.a-o.a)/2+s,r.b=o.b+(d.b-o.b)/2-s-e.e.b))}function Xc(e,t){var n,r,s,o,h,d,v;if(e==null)return null;if(o=e.length,o==0)return"";for(v=Me(Sh,Td,25,o,15,1),ame(0,o,e.length),ame(0,o,v.length),YKe(e,0,o,v,0),n=null,d=t,s=0,h=0;s0?jl(n.a,0,o-1):""):e.substr(0,o-1):n?n.a:e}function Iut(e){wv(e,new gb(gv(hv(dv(fv(new lg,yb),"ELK DisCo"),"Layouter for arranging unconnected subgraphs. The subgraphs themselves are, by default, not laid out."),new pi))),dt(e,yb,_oe,xt(U7e)),dt(e,yb,Coe,xt(Rue)),dt(e,yb,fk,xt(Ugt)),dt(e,yb,uw,xt(V7e)),dt(e,yb,L6e,xt(Xgt)),dt(e,yb,M6e,xt(Ygt)),dt(e,yb,A6e,xt(Qgt)),dt(e,yb,D6e,xt(Kgt)),dt(e,yb,F6e,xt(Wgt)),dt(e,yb,j6e,xt(Bue)),dt(e,yb,$6e,xt(q7e)),dt(e,yb,H6e,xt(XG))}function V5e(e,t,n,r){var s,o,h,d,v,x,_,L,P;if(o=new H0(e),T0(o,(zn(),Jc)),Ye(o,(pt(),bs),(wa(),tu)),s=0,t){for(h=new $c,Ye(h,(et(),Mi),t),Ye(o,Mi,t.i),Vs(h,(ht(),Dn)),rc(h,o),P=kd(t.e),x=P,_=0,L=x.length;_0)if(n-=r.length-t,n>=0){for(s.a+="0.";n>Ab.length;n-=Ab.length)cKe(s,Ab);qUe(s,Ab,_s(n)),Yr(s,r.substr(t))}else n=t-n,Yr(s,jl(r,t,_s(n))),s.a+=".",Yr(s,IM(r,_s(n)));else{for(Yr(s,r.substr(t));n<-Ab.length;n+=Ab.length)cKe(s,Ab);qUe(s,Ab,_s(-n))}return s.a}function U5e(e,t,n,r){var s,o,h,d,v,x,_,L,P;return v=da(new Pt(n.a,n.b),e),x=v.a*t.b-v.b*t.a,_=t.a*r.b-t.b*r.a,L=(v.a*r.b-v.b*r.a)/_,P=x/_,_==0?x==0?(s=Ni(new Pt(n.a,n.b),bd(new Pt(r.a,r.b),.5)),o=Hp(e,s),h=Hp(Ni(new Pt(e.a,e.b),t),s),d=b.Math.sqrt(r.a*r.a+r.b*r.b)*.5,o=0&&L<=1&&P>=0&&P<=1?Ni(new Pt(e.a,e.b),bd(new Pt(t.a,t.b),L)):null}function dvn(e,t,n){var r,s,o,h,d;if(r=u(K(e,(pt(),$le)),21),n.a>t.a&&(r.Hc((ty(),HO))?e.c.a+=(n.a-t.a)/2:r.Hc(zO)&&(e.c.a+=n.a-t.a)),n.b>t.b&&(r.Hc((ty(),qO))?e.c.b+=(n.b-t.b)/2:r.Hc(GO)&&(e.c.b+=n.b-t.b)),u(K(e,(et(),eu)),21).Hc((mo(),Th))&&(n.a>t.a||n.b>t.b))for(d=new C(e.a);d.at.a&&(r.Hc((ty(),HO))?e.c.a+=(n.a-t.a)/2:r.Hc(zO)&&(e.c.a+=n.a-t.a)),n.b>t.b&&(r.Hc((ty(),qO))?e.c.b+=(n.b-t.b)/2:r.Hc(GO)&&(e.c.b+=n.b-t.b)),u(K(e,(et(),eu)),21).Hc((mo(),Th))&&(n.a>t.a||n.b>t.b))for(h=new C(e.a);h.at&&(s=0,o+=_.b+n,L.c[L.c.length]=_,_=new Lwe(o,n),r=new wie(0,_.f,_,n),q$(_,r),s=0),r.b.c.length==0||v.f>=r.o&&v.f<=r.f||r.a*.5<=v.f&&r.a*1.5>=v.f?zye(r,v):(h=new wie(r.s+r.r+n,_.f,_,n),q$(_,h),zye(h,v)),s=v.i+v.g;return L.c[L.c.length]=_,L}function b4(e){var t,n,r,s,o,h,d,v;if(!e.a){if(e.o=null,v=new F$e(e),t=new vp,n=XS,d=n.a.zc(e,n),d==null){for(h=new rr(jo(e));h.e!=h.i.gc();)o=u(pr(h),26),fs(v,b4(o));n.a.Bc(e)!=null,n.a.gc()==0}for(s=(!e.s&&(e.s=new at(ju,e,21,17)),new rr(e.s));s.e!=s.i.gc();)r=u(pr(s),170),we(r,322)&&Br(t,u(r,34));Km(t),e.k=new zWe(e,(u(Te(He((Rp(),En).o),7),18),t.i),t.g),fs(v,e.k),Km(v),e.a=new B3((u(Te(He(En.o),4),18),v.i),v.g),dl(e).b&=-2}return e.a}function vvn(e,t,n,r,s,o,h){var d,v,x,_,L,P;return L=!1,v=$ot(n.q,t.f+t.b-n.q.f),P=s-(n.q.e+v-h),P=(xn(o,e.c.length),u(e.c[o],200)).e,_=(d=dC(r,P,!1),d.a),_>t.b&&!x)?!1:((x||_<=t.b)&&(x&&_>t.b?(n.d=_,fD(n,qst(n,_))):(ust(n.q,v),n.c=!0),fD(r,s-(n.s+n.r)),KD(r,n.q.e+n.q.d,t.f),q$(t,r),e.c.length>o&&(JD((xn(o,e.c.length),u(e.c[o],200)),r),(xn(o,e.c.length),u(e.c[o],200)).a.c.length==0&&Eg(e,o)),L=!0),L)}function W5e(e,t,n,r){var s,o,h,d,v,x,_;if(_=pu(e.e.Tg(),t),s=0,o=u(e.g,119),v=null,ho(),u(t,66).Oj()){for(d=0;de.o.a&&(_=(v-e.o.a)/2,d.b=b.Math.max(d.b,_),d.c=b.Math.max(d.c,_))}}function mvn(e){var t,n,r,s,o,h,d,v;for(o=new uQe,rWt(o,(W6(),Fyt)),r=(s=aie(e,Me(mt,Qe,2,0,6,1)),new c6(new Al(new lte(e,s).b)));r.b0?e.i:0)>t&&v>0&&(o=0,h+=v+e.i,s=b.Math.max(s,P),r+=v+e.i,v=0,P=0,n&&(++L,it(e.n,new o$(e.s,h,e.i))),d=0),P+=x.g+(d>0?e.i:0),v=b.Math.max(v,x.f),n&&T3e(u(St(e.n,L),211),x),o+=x.g+(d>0?e.i:0),++d;return s=b.Math.max(s,P),r+=v,n&&(e.r=s,e.d=r,A3e(e.j)),new fh(e.s,e.t,s,r)}function Hc(e,t,n,r,s){Ud();var o,h,d,v,x,_,L,P,z;if(Wve(e,"src"),Wve(n,"dest"),P=pl(e),v=pl(n),bve((P.i&4)!=0,"srcType is not an array"),bve((v.i&4)!=0,"destType is not an array"),L=P.c,h=v.c,bve(L.i&1?L==h:(h.i&1)==0,"Array types don't match"),z=e.length,x=n.length,t<0||r<0||s<0||t+s>z||r+s>x)throw J(new cpe);if(!(L.i&1)&&P!=v)if(_=tb(e),o=tb(n),je(e)===je(n)&&tr;)cs(o,d,_[--t]);else for(d=r+s;r0&&O4e(e,t,n,r,s,!0)}function pae(){pae=pe,P0t=ie(re(Lr,1),Jr,25,15,[$a,1162261467,wC,1220703125,362797056,1977326743,wC,387420489,Lz,214358881,429981696,815730721,1475789056,170859375,268435456,410338673,612220032,893871739,128e7,1801088541,113379904,148035889,191102976,244140625,308915776,387420489,481890304,594823321,729e6,887503681,wC,1291467969,1544804416,1838265625,60466176]),B0t=ie(re(Lr,1),Jr,25,15,[-1,-1,31,19,15,13,11,11,10,9,9,8,8,8,8,7,7,7,7,7,7,7,6,6,6,6,6,6,6,6,6,6,6,6,6,6,5])}function yvn(e){var t,n,r,s,o,h,d,v;for(s=new C(e.b);s.a=e.b.length?(o[s++]=h.b[r++],o[s++]=h.b[r++]):r>=h.b.length?(o[s++]=e.b[n++],o[s++]=e.b[n++]):h.b[r]0?e.i:0)),++t;for(Ion(e.n,v),e.d=n,e.r=r,e.g=0,e.f=0,e.e=0,e.o=gs,e.p=gs,o=new C(e.b);o.a0&&(s=(!e.n&&(e.n=new at(Jo,e,1,7)),u(Te(e.n,0),137)).a,!s||Yr(Yr((t.a+=' "',t),s),'"'))),n=(!e.b&&(e.b=new wn(mr,e,4,7)),!(e.b.i<=1&&(!e.c&&(e.c=new wn(mr,e,5,8)),e.c.i<=1))),n?t.a+=" [":t.a+=" ",Yr(t,rbe(new ste,new rr(e.b))),n&&(t.a+="]"),t.a+=Ioe,n&&(t.a+="["),Yr(t,rbe(new ste,new rr(e.c))),n&&(t.a+="]"),t.a)}function bae(e,t){var n,r,s,o,h,d,v;if(e.a){if(d=e.a.ne(),v=null,d!=null?t.a+=""+d:(h=e.a.Dj(),h!=null&&(o=pd(h,Nu(91)),o!=-1?(v=h.substr(o),t.a+=""+jl(h==null?Pu:(Sn(h),h),0,o)):t.a+=""+h)),e.d&&e.d.i!=0){for(s=!0,t.a+="<",r=new rr(e.d);r.e!=r.i.gc();)n=u(pr(r),87),s?s=!1:t.a+=io,bae(n,t);t.a+=">"}v!=null&&(t.a+=""+v)}else e.e?(d=e.e.zb,d!=null&&(t.a+=""+d)):(t.a+="?",e.b?(t.a+=" super ",bae(e.b,t)):e.f&&(t.a+=" extends ",bae(e.f,t)))}function Evn(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt,bt,zt,Ut,In;for(Ve=e.c,nt=t.c,n=Yo(Ve.a,e,0),r=Yo(nt.a,t,0),Ee=u(Yv(e,(vo(),ul)).Kc().Pb(),11),Ut=u(Yv(e,hu).Kc().Pb(),11),Ne=u(Yv(t,ul).Kc().Pb(),11),In=u(Yv(t,hu).Kc().Pb(),11),le=kd(Ee.e),bt=kd(Ut.g),Ce=kd(Ne.e),zt=kd(In.g),ey(e,r,nt),h=Ce,_=0,q=h.length;__?new X2((Jf(),jy),n,t,x-_):x>0&&_>0&&(new X2((Jf(),jy),t,n,0),new X2(jy,n,t,0))),h)}function Put(e,t){var n,r,s,o,h,d;for(h=new ob(new dg(e.f.b).a);h.b;){if(o=$v(h),s=u(o.cd(),594),t==1){if(s.gf()!=(wo(),X0)&&s.gf()!=Y0)continue}else if(s.gf()!=(wo(),Xh)&&s.gf()!=Df)continue;switch(r=u(u(o.dd(),46).b,81),d=u(u(o.dd(),46).a,189),n=d.c,s.gf().g){case 2:r.g.c=e.e.a,r.g.b=b.Math.max(1,r.g.b+n);break;case 1:r.g.c=r.g.c+n,r.g.b=b.Math.max(1,r.g.b-n);break;case 4:r.g.d=e.e.b,r.g.a=b.Math.max(1,r.g.a+n);break;case 3:r.g.d=r.g.d+n,r.g.a=b.Math.max(1,r.g.a-n)}}}function Tvn(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W;for(d=Me(Lr,Jr,25,t.b.c.length,15,1),x=Me(Zue,tt,267,t.b.c.length,0,1),v=Me(h0,Bg,10,t.b.c.length,0,1),L=e.a,P=0,z=L.length;P0&&v[r]&&(q=j3(e.b,v[r],s)),W=b.Math.max(W,s.c.c.b+q);for(o=new C(_.e);o.a1)throw J(new Ln(eO));v||(o=Jd(t,r.Kc().Pb()),h.Fc(o))}return iye(e,T4e(e,t,n),h)}function Svn(e,t){var n,r,s,o;for(lin(t.b.j),ms(Cu(new vn(null,new mn(t.d,16)),new FX),new jX),o=new C(t.d);o.ae.o.b||(n=ac(e,$n),d=t.d+t.a+(n.gc()-1)*h,d>e.o.b)))}function mae(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q;if(h=e.e,v=t.e,h==0)return t;if(v==0)return e;if(o=e.d,d=t.d,o+d==2)return n=qs(e.a[0],yo),r=qs(t.a[0],yo),h==v?(_=Ua(n,r),q=Or(_),z=Or(Nm(_,32)),z==0?new Tg(h,q):new z3(h,2,ie(re(Lr,1),Jr,25,15,[q,z]))):WD(h<0?Wp(r,n):Wp(n,r));if(h==v)P=h,L=o>=d?Pre(e.a,o,t.a,d):Pre(t.a,d,e.a,o);else{if(s=o!=d?o>d?1:-1:mye(e.a,t.a,o),s==0)return Qp(),K7;s==1?(P=h,L=Ore(e.a,o,t.a,d)):(P=v,L=Ore(t.a,d,e.a,o))}return x=new z3(P,L.length,L),E_(x),x}function yae(e,t,n,r,s,o,h){var d,v,x,_,L,P,z;return L=It(Mt(K(t,(pt(),HTe)))),P=null,o==(vo(),ul)&&r.c.i==n?P=r.c:o==hu&&r.d.i==n&&(P=r.d),x=h,!x||!L||P?(_=(ht(),uc),P?_=P.j:R3(u(K(n,bs),98))&&(_=o==ul?Dn:$n),v=Dvn(e,t,n,o,_,r),d=Dre((Ya(n),r)),o==ul?(Va(d,u(St(v.j,0),11)),ba(d,s)):(Va(d,s),ba(d,u(St(v.j,0),11))),x=new ert(r,d,v,u(K(v,(et(),Mi)),11),o,!P)):(it(x.e,r),z=b.Math.max(Ue(ft(K(x.d,Hg))),Ue(ft(K(r,Hg)))),Ye(x.d,Hg,z)),sn(e.a,r,new mj(x.d,t,o)),x}function wz(e,t){var n,r,s,o,h,d,v,x,_,L;if(_=null,e.d&&(_=u(Uc(e.d,t),138)),!_){if(o=e.a.Mh(),L=o.i,!e.d||MT(e.d)!=L){for(v=new Mr,e.d&&P_(v,e.d),x=v.f.c+v.g.c,d=x;d0?(z=(q-1)*n,d&&(z+=r),_&&(z+=r),z=e.b[s+1])s+=2;else if(n0)for(r=new Uu(u(Ii(e.a,o),21)),hn(),aa(r,new Di(t)),s=new Ea(o.b,0);s.bVe)?(v=2,h=Ei):v==0?(v=1,h=bt):(v=0,h=bt)):(z=bt>=h||h-bt0?1:yv(isNaN(r),isNaN(0)))>=0^(Ef(Md),(b.Math.abs(d)<=Md||d==0||isNaN(d)&&isNaN(0)?0:d<0?-1:d>0?1:yv(isNaN(d),isNaN(0)))>=0)?b.Math.max(d,r):(Ef(Md),(b.Math.abs(r)<=Md||r==0||isNaN(r)&&isNaN(0)?0:r<0?-1:r>0?1:yv(isNaN(r),isNaN(0)))>0?b.Math.sqrt(d*d+r*r):-b.Math.sqrt(d*d+r*r))}function pb(e,t){var n,r,s,o,h,d;if(t){if(!e.a&&(e.a=new oF),e.e==2){aF(e.a,t);return}if(t.e==1){for(s=0;s=so?To(n,Hye(r)):b8(n,r&Ss),h=new cre(10,null,0),wZt(e.a,h,d-1)):(n=(h.bm().length+o,new ST),To(n,h.bm())),t.e==0?(r=t._l(),r>=so?To(n,Hye(r)):b8(n,r&Ss)):To(n,t.bm()),u(h,521).b=n.a}}function Gut(e){var t,n,r,s,o;return e.g!=null?e.g:e.a<32?(e.g=nyn(Ou(e.f),_s(e.e)),e.g):(s=Lae((!e.c&&(e.c=FD(e.f)),e.c),0),e.e==0?s:(t=(!e.c&&(e.c=FD(e.f)),e.c).e<0?2:1,n=s.length,r=-e.e+n-t,o=new Tp,o.a+=""+s,e.e>0&&r>=-6?r>=0?rD(o,n-_s(e.e),String.fromCharCode(46)):(o.a=jl(o.a,0,t-1)+"0."+IM(o.a,t-1),rD(o,t+1,jh(Ab,0,-_s(r)-1))):(n-t>=1&&(rD(o,t,String.fromCharCode(46)),++n),rD(o,n,String.fromCharCode(69)),r>0&&rD(o,++n,String.fromCharCode(43)),rD(o,++n,""+d_(Ou(r)))),e.g=o.a,e.g))}function qvn(e,t,n){var r,s,o,h,d,v,x,_,L,P,z,q,W,X;if(!n.dc()){for(d=0,P=0,r=n.Kc(),q=u(r.Pb(),19).a;d1&&(v=x.mg(v,e.a,d));return v.c.length==1?u(St(v,v.c.length-1),220):v.c.length==2?Ovn((xn(0,v.c.length),u(v.c[0],220)),(xn(1,v.c.length),u(v.c[1],220)),h,o):null}function qut(e){var t,n,r,s,o,h;for(Mu(e.a,new bL),n=new C(e.a);n.a=b.Math.abs(r.b)?(r.b=0,o.d+o.a>h.d&&o.dh.c&&o.c0){if(t=new O2e(e.i,e.g),n=e.i,o=n<100?null:new _p(n),e.ij())for(r=0;r0){for(d=e.g,x=e.i,A_(e),o=x<100?null:new _p(x),r=0;r>13|(e.m&15)<<9,s=e.m>>4&8191,o=e.m>>17|(e.h&255)<<5,h=(e.h&1048320)>>8,d=t.l&8191,v=t.l>>13|(t.m&15)<<9,x=t.m>>4&8191,_=t.m>>17|(t.h&255)<<5,L=(t.h&1048320)>>8,zt=n*d,Ut=r*d,In=s*d,Rn=o*d,dr=h*d,v!=0&&(Ut+=n*v,In+=r*v,Rn+=s*v,dr+=o*v),x!=0&&(In+=n*x,Rn+=r*x,dr+=s*x),_!=0&&(Rn+=n*_,dr+=r*_),L!=0&&(dr+=n*L),z=zt&ml,q=(Ut&511)<<13,P=z+q,X=zt>>22,le=Ut>>9,Ce=(In&262143)<<4,Ee=(Rn&31)<<17,W=X+le+Ce+Ee,Ve=In>>18,nt=Rn>>5,bt=(dr&4095)<<8,Ne=Ve+nt+bt,W+=P>>22,P&=ml,Ne+=W>>22,W&=ml,Ne&=V0,fu(P,W,Ne)}function Vut(e){var t,n,r,s,o,h,d;if(d=u(St(e.j,0),11),d.g.c.length!=0&&d.e.c.length!=0)throw J(new Wo("Interactive layout does not support NORTH/SOUTH ports with incoming _and_ outgoing edges."));if(d.g.c.length!=0){for(o=gs,n=new C(d.g);n.a4)if(e.wj(t)){if(e.rk()){if(s=u(t,49),r=s.Ug(),v=r==e.e&&(e.Dk()?s.Og(s.Vg(),e.zk())==e.Ak():-1-s.Vg()==e.aj()),e.Ek()&&!v&&!r&&s.Zg()){for(o=0;o0&&(x=e.n.a/o);break;case 2:case 4:s=e.i.o.b,s>0&&(x=e.n.b/s)}Ye(e,(et(),Ew),x)}if(v=e.o,h=e.a,r)h.a=r.a,h.b=r.b,e.d=!0;else if(t!=X1&&t!=w2&&d!=uc)switch(d.g){case 1:h.a=v.a/2;break;case 2:h.a=v.a,h.b=v.b/2;break;case 3:h.a=v.a/2,h.b=v.b;break;case 4:h.b=v.b/2}else h.a=v.a/2,h.b=v.b/2}function pC(e){var t,n,r,s,o,h,d,v,x,_;if(e.ej())if(_=e.Vi(),v=e.fj(),_>0)if(t=new Vme(e.Gi()),n=_,o=n<100?null:new _p(n),FM(e,n,t.g),s=n==1?e.Zi(4,Te(t,0),null,0,v):e.Zi(6,t,null,-1,v),e.bj()){for(r=new rr(t);r.e!=r.i.gc();)o=e.dj(pr(r),o);o?(o.Ei(s),o.Fi()):e.$i(s)}else o?(o.Ei(s),o.Fi()):e.$i(s);else FM(e,e.Vi(),e.Wi()),e.$i(e.Zi(6,(hn(),bo),null,-1,v));else if(e.bj())if(_=e.Vi(),_>0){for(d=e.Wi(),x=_,FM(e,_,d),o=x<100?null:new _p(x),r=0;re.d[h.p]&&(n+=Gwe(e.b,o)*u(v.b,19).a,$p(e.a,ct(o)));for(;!TT(e.a);)yme(e.b,u(I6(e.a),19).a)}return n}function nwn(e,t,n,r){var s,o,h,d,v,x,_,L,P,z,q,W,X;for(L=new Io(u(Ft(e,(XH(),lSe)),8)),L.a=b.Math.max(L.a-n.b-n.c,0),L.b=b.Math.max(L.b-n.d-n.a,0),s=ft(Ft(e,oSe)),(s==null||(Sn(s),s<=0))&&(s=1.3),d=new st,q=new rr((!e.a&&(e.a=new at(hs,e,10,11)),e.a));q.e!=q.i.gc();)z=u(pr(q),33),h=new yUe(z),d.c[d.c.length]=h;switch(P=u(Ft(e,Xhe),311),P.g){case 3:X=Tbn(d,t,L.a,L.b,(x=r,Sn(s),x));break;case 1:X=Xbn(d,t,L.a,L.b,(_=r,Sn(s),_));break;default:X=swn(d,t,L.a,L.b,(v=r,Sn(s),v))}o=new H$(X),W=Sae(o,t,n,L.a,L.b,r,(Sn(s),s)),sw(e,W.a,W.b,!1,!0)}function rwn(e,t){var n,r,s,o;n=t.b,o=new Uu(n.j),s=0,r=n.j,r.c=Me(Yn,yt,1,0,5,1),Av(u(rb(e.b,(ht(),An),(qv(),mw)),15),n),s=XD(o,s,new SX,r),Av(u(rb(e.b,An,u2),15),n),s=XD(o,s,new D9,r),Av(u(rb(e.b,An,ww),15),n),Av(u(rb(e.b,$n,mw),15),n),Av(u(rb(e.b,$n,u2),15),n),s=XD(o,s,new wB,r),Av(u(rb(e.b,$n,ww),15),n),Av(u(rb(e.b,xr,mw),15),n),s=XD(o,s,new mB,r),Av(u(rb(e.b,xr,u2),15),n),s=XD(o,s,new yB,r),Av(u(rb(e.b,xr,ww),15),n),Av(u(rb(e.b,Dn,mw),15),n),s=XD(o,s,new MX,r),Av(u(rb(e.b,Dn,u2),15),n),Av(u(rb(e.b,Dn,ww),15),n)}function iwn(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W;for(kr(t,"Layer size calculation",1),_=gs,x=Ds,s=!1,d=new C(e.b);d.a.5?le-=h*2*(q-.5):q<.5&&(le+=o*2*(.5-q)),s=d.d.b,leX.a-W-_&&(le=X.a-W-_),d.n.a=t+le}}function swn(e,t,n,r,s){var o,h,d,v,x,_,L,P,z,q,W,X;for(d=Me(pa,Ao,25,e.c.length,15,1),P=new $j(new GB),I3e(P,e),x=0,W=new st;P.b.c.length!=0;)if(h=u(P.b.c.length==0?null:St(P.b,0),157),x>1&&Wu(h)*Dl(h)/2>d[0]){for(o=0;od[o];)++o;q=new Zd(W,0,o+1),L=new H$(q),_=Wu(h)/Dl(h),v=Sae(L,t,new g6,n,r,s,_),Ni(Zf(L.e),v),S8(l7(P,L)),z=new Zd(W,o+1,W.c.length),I3e(P,z),W.c=Me(Yn,yt,1,0,5,1),x=0,mKe(d,d.length,0)}else X=P.b.c.length==0?null:St(P.b,0),X!=null&&iie(P,0),x>0&&(d[x]=d[x-1]),d[x]+=Wu(h)*Dl(h),++x,W.c[W.c.length]=h;return W}function awn(e){var t,n,r,s,o;if(r=u(K(e,(pt(),vu)),163),r==(mh(),l2)){for(n=new cr(fr(Xo(e).a.Kc(),new V));Vr(n);)if(t=u(Pr(n),17),!MZe(t))throw J(new M3(Poe+QD(e)+"' has its layer constraint set to FIRST_SEPARATE, but has at least one incoming edge. FIRST_SEPARATE nodes must not have incoming edges."))}else if(r==Ly){for(o=new cr(fr(js(e).a.Kc(),new V));Vr(o);)if(s=u(Pr(o),17),!MZe(s))throw J(new M3(Poe+QD(e)+"' has its layer constraint set to LAST_SEPARATE, but has at least one outgoing edge. LAST_SEPARATE nodes must not have outgoing edges."))}}function own(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q;for(kr(t,"Label dummy removal",1),r=Ue(ft(K(e,(pt(),Ok)))),s=Ue(ft(K(e,Ry))),x=u(K(e,Zl),103),v=new C(e.b);v.a0&&Zst(e,d,L);for(s=new C(L);s.a>19&&(t=U8(t),v=!v),h=agn(t),o=!1,s=!1,r=!1,e.h==MI&&e.m==0&&e.l==0)if(s=!0,o=!0,h==-1)e=hVe((D8(),B8e)),r=!0,v=!v;else return d=Y4e(e,h),v&&gie(d),n&&(s2=fu(0,0,0)),d;else e.h>>19&&(o=!0,e=U8(e),r=!0,v=!v);return h!=-1?Wsn(e,h,v,o,n):$3e(e,t)<0?(n&&(o?s2=U8(e):s2=fu(e.l,e.m,e.h)),fu(0,0,0)):Q2n(r?e:fu(e.l,e.m,e.h),t,v,o,s,n)}function mz(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q;if(e.e&&e.c.ct.f||t.g>e.f)){for(n=0,r=0,h=e.w.a.ec().Kc();h.Ob();)s=u(h.Pb(),11),Cie(sc(ie(re(na,1),Qe,8,0,[s.i.n,s.n,s.a])).b,t.g,t.f)&&++n;for(d=e.r.a.ec().Kc();d.Ob();)s=u(d.Pb(),11),Cie(sc(ie(re(na,1),Qe,8,0,[s.i.n,s.n,s.a])).b,t.g,t.f)&&--n;for(v=t.w.a.ec().Kc();v.Ob();)s=u(v.Pb(),11),Cie(sc(ie(re(na,1),Qe,8,0,[s.i.n,s.n,s.a])).b,e.g,e.f)&&++r;for(o=t.r.a.ec().Kc();o.Ob();)s=u(o.Pb(),11),Cie(sc(ie(re(na,1),Qe,8,0,[s.i.n,s.n,s.a])).b,e.g,e.f)&&--r;n=0)return s=bon(e,t.substr(1,h-1)),_=t.substr(h+1,v-(h+1)),hyn(e,_,s)}else{if(n=-1,H8e==null&&(H8e=new RegExp("\\d")),H8e.test(String.fromCharCode(d))&&(n=Wbe(t,Nu(46),v-1),n>=0)){r=u(Ire(e,Eet(e,t.substr(1,n-1)),!1),58),x=0;try{x=Wl(t.substr(n+1),$a,Ei)}catch(P){throw P=ts(P),we(P,127)?(o=P,J(new D$(o))):J(P)}if(x=0)return n;switch(Dv(Po(e,n))){case 2:{if(an("",Ag(e,n.Hj()).ne())){if(v=QM(Po(e,n)),d=m8(Po(e,n)),_=n5e(e,t,v,d),_)return _;for(s=L5e(e,t),h=0,L=s.gc();h1)throw J(new Ln(eO));for(_=pu(e.e.Tg(),t),r=u(e.g,119),h=0;h1,x=new N1(P.b);nc(x.a)||nc(x.b);)v=u(nc(x.a)?Y(x.a):Y(x.b),17),L=v.c==P?v.d:v.c,b.Math.abs(sc(ie(re(na,1),Qe,8,0,[L.i.n,L.n,L.a])).b-h.b)>1&&lpn(e,v,h,o,P)}}function mwn(e){var t,n,r,s,o,h;if(s=new Ea(e.e,0),r=new Ea(e.a,0),e.d)for(n=0;npce;){for(o=t,h=0;b.Math.abs(t-o)0),s.a.Xb(s.c=--s.b),Bbn(e,e.b-h,o,r,s),Qn(s.b0),r.a.Xb(r.c=--r.b)}if(!e.d)for(n=0;n0?(e.f[_.p]=z/(_.e.c.length+_.g.c.length),e.c=b.Math.min(e.c,e.f[_.p]),e.b=b.Math.max(e.b,e.f[_.p])):d&&(e.f[_.p]=z)}}function kwn(e){e.b=null,e.bb=null,e.fb=null,e.qb=null,e.a=null,e.c=null,e.d=null,e.e=null,e.f=null,e.n=null,e.M=null,e.L=null,e.Q=null,e.R=null,e.K=null,e.db=null,e.eb=null,e.g=null,e.i=null,e.j=null,e.k=null,e.gb=null,e.o=null,e.p=null,e.q=null,e.r=null,e.$=null,e.ib=null,e.S=null,e.T=null,e.t=null,e.s=null,e.u=null,e.v=null,e.w=null,e.B=null,e.A=null,e.C=null,e.D=null,e.F=null,e.G=null,e.H=null,e.I=null,e.J=null,e.P=null,e.Z=null,e.U=null,e.V=null,e.W=null,e.X=null,e.Y=null,e._=null,e.ab=null,e.cb=null,e.hb=null,e.nb=null,e.lb=null,e.mb=null,e.ob=null,e.pb=null,e.jb=null,e.kb=null,e.N=!1,e.O=!1}function xwn(e,t,n){var r,s,o,h;for(kr(n,"Graph transformation ("+e.a+")",1),h=Pv(t.a),o=new C(t.b);o.a0&&(e.a=v+(z-1)*o,t.c.b+=e.a,t.f.b+=e.a)),q.a.gc()!=0&&(P=new Hne(1,o),z=t6e(P,t,q,W,t.f.b+v-t.c.b),z>0&&(t.f.b+=v+(z-1)*o))}function x7(e,t){var n,r,s,o;o=e.F,t==null?(e.F=null,Y8(e,null)):(e.F=(Sn(t),t),r=pd(t,Nu(60)),r!=-1?(s=t.substr(0,r),pd(t,Nu(46))==-1&&!an(s,sk)&&!an(s,HC)&&!an(s,mG)&&!an(s,zC)&&!an(s,GC)&&!an(s,qC)&&!an(s,VC)&&!an(s,UC)&&(s=Odt),n=cj(t,Nu(62)),n!=-1&&(s+=""+t.substr(n+1)),Y8(e,s)):(s=t,pd(t,Nu(46))==-1&&(r=pd(t,Nu(91)),r!=-1&&(s=t.substr(0,r)),!an(s,sk)&&!an(s,HC)&&!an(s,mG)&&!an(s,zC)&&!an(s,GC)&&!an(s,qC)&&!an(s,VC)&&!an(s,UC)?(s=Odt,r!=-1&&(s+=""+t.substr(r))):s=t),Y8(e,s),s==t&&(e.F=e.D))),e.Db&4&&!(e.Db&1)&&_i(e,new oa(e,1,5,o,t))}function Twn(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee;if(W=t.b.c.length,!(W<3)){for(z=Me(Lr,Jr,25,W,15,1),L=0,_=new C(t.b);_.a<_.c.c.length;)x=u(Y(_),29),z[L++]=x.a.c.length;for(P=new Ea(t.b,2),r=1;rh)&&Gs(e.b,u(X.b,17));++d}o=h}}}function Z5e(e,t){var n;if(t==null||an(t,Pu)||t.length==0&&e.k!=(Ng(),Pk))return null;switch(e.k.g){case 1:return AH(t,j7)?(Mn(),U7):AH(t,Mce)?(Mn(),Sb):null;case 2:try{return ct(Wl(t,$a,Ei))}catch(r){if(r=ts(r),we(r,127))return null;throw J(r)}case 4:try{return ry(t)}catch(r){if(r=ts(r),we(r,127))return null;throw J(r)}case 3:return t;case 5:return Dnt(e),Rat(e,t);case 6:return Dnt(e),N0n(e,e.a,t);case 7:try{return n=Udn(e),n.Jf(t),n}catch(r){if(r=ts(r),we(r,32))return null;throw J(r)}default:throw J(new Wo("Invalid type set for this layout option."))}}function _wn(e){M_();var t,n,r,s,o,h,d;for(d=new aHe,n=new C(e);n.a=d.b.c)&&(d.b=t),(!d.c||t.c<=d.c.c)&&(d.d=d.c,d.c=t),(!d.e||t.d>=d.e.d)&&(d.e=t),(!d.f||t.d<=d.f.d)&&(d.f=t);return r=new IH((V8(),vw)),sD(e,jpt,new Al(ie(re(dO,1),yt,369,0,[r]))),h=new IH(_y),sD(e,Fpt,new Al(ie(re(dO,1),yt,369,0,[h]))),s=new IH(Ty),sD(e,Rpt,new Al(ie(re(dO,1),yt,369,0,[s]))),o=new IH(O4),sD(e,Bpt,new Al(ie(re(dO,1),yt,369,0,[o]))),Use(r.c,vw),Use(s.c,Ty),Use(o.c,O4),Use(h.c,_y),d.a.c=Me(Yn,yt,1,0,5,1),Rs(d.a,r.c),Rs(d.a,nb(s.c)),Rs(d.a,o.c),Rs(d.a,nb(h.c)),d}function J5e(e){var t;switch(e.d){case 1:{if(e.hj())return e.o!=-2;break}case 2:{if(e.hj())return e.o==-2;break}case 3:case 5:case 4:case 6:case 7:return e.o>-2;default:return!1}switch(t=e.gj(),e.p){case 0:return t!=null&&It(Mt(t))!=XT(e.k,0);case 1:return t!=null&&u(t,217).a!=Or(e.k)<<24>>24;case 2:return t!=null&&u(t,172).a!=(Or(e.k)&Ss);case 6:return t!=null&&XT(u(t,162).a,e.k);case 5:return t!=null&&u(t,19).a!=Or(e.k);case 7:return t!=null&&u(t,184).a!=Or(e.k)<<16>>16;case 3:return t!=null&&Ue(ft(t))!=e.j;case 4:return t!=null&&u(t,155).a!=e.j;default:return t==null?e.n!=null:!Ci(t,e.n)}}function xI(e,t,n){var r,s,o,h;return e.Fk()&&e.Ek()&&(h=One(e,u(n,56)),je(h)!==je(n))?(e.Oi(t),e.Ui(t,EJe(e,t,h)),e.rk()&&(o=(s=u(n,49),e.Dk()?e.Bk()?s.ih(e.b,go(u(gn(Su(e.b),e.aj()),18)).n,u(gn(Su(e.b),e.aj()).Yj(),26).Bj(),null):s.ih(e.b,Ji(s.Tg(),go(u(gn(Su(e.b),e.aj()),18))),null,null):s.ih(e.b,-1-e.aj(),null,null)),!u(h,49).eh()&&(o=(r=u(h,49),e.Dk()?e.Bk()?r.gh(e.b,go(u(gn(Su(e.b),e.aj()),18)).n,u(gn(Su(e.b),e.aj()).Yj(),26).Bj(),o):r.gh(e.b,Ji(r.Tg(),go(u(gn(Su(e.b),e.aj()),18))),null,o):r.gh(e.b,-1-e.aj(),null,o))),o&&o.Fi()),Ll(e.b)&&e.$i(e.Zi(9,n,h,t,!1)),h):n}function Yut(e,t,n){var r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne;for(_=Ue(ft(K(e,(pt(),Sw)))),r=Ue(ft(K(e,ZTe))),P=new rl,Ye(P,Sw,_+r),x=t,le=x.d,W=x.c.i,Ce=x.d.i,X=F2e(W.c),Ee=F2e(Ce.c),s=new st,L=X;L<=Ee;L++)d=new H0(e),T0(d,(zn(),ca)),Ye(d,(et(),Mi),x),Ye(d,bs,(wa(),tu)),Ye(d,eV,P),z=u(St(e.b,L),29),L==X?ey(d,z.a.c.length-n,z):No(d,z),Ne=Ue(ft(K(x,Hg))),Ne<0&&(Ne=0,Ye(x,Hg,Ne)),d.o.b=Ne,q=b.Math.floor(Ne/2),h=new $c,Vs(h,(ht(),Dn)),rc(h,d),h.n.b=q,v=new $c,Vs(v,$n),rc(v,d),v.n.b=q,ba(x,h),o=new Iv,Ho(o,x),Ye(o,Fo,null),Va(o,v),ba(o,le),Aln(d,x,o),s.c[s.c.length]=o,x=o;return s}function Eae(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee;for(v=u(Og(e,(ht(),Dn)).Kc().Pb(),11).e,z=u(Og(e,$n).Kc().Pb(),11).g,d=v.c.length,Ee=D1(u(St(e.j,0),11));d-- >0;){for(W=(xn(0,v.c.length),u(v.c[0],17)),s=(xn(0,z.c.length),u(z.c[0],17)),Ce=s.d.e,o=Yo(Ce,s,0),Itn(W,s.d,o),Va(s,null),ba(s,null),q=W.a,t&&ci(q,new Io(Ee)),r=ii(s.a,0);r.b!=r.d.c;)n=u(ri(r),8),ci(q,new Io(n));for(le=W.b,P=new C(s.b);P.a0&&(h=b.Math.max(h,Ett(e.C.b+r.d.b,s))),_=r,L=s,P=o;e.C&&e.C.c>0&&(z=P+e.C.c,x&&(z+=_.d.c),h=b.Math.max(h,(S1(),Ef(z1),b.Math.abs(L-1)<=z1||L==1||isNaN(L)&&isNaN(1)?0:z/(1-L)))),n.n.b=0,n.a.a=h}function Qut(e,t){var n,r,s,o,h,d,v,x,_,L,P,z;if(n=u(_o(e.b,t),124),v=u(u(Ii(e.r,t),21),84),v.dc()){n.n.d=0,n.n.a=0;return}for(x=e.u.Hc((ol(),Z0)),h=0,e.A.Hc((Bl(),Hb))&&Mct(e,t),d=v.Kc(),_=null,P=0,L=0;d.Ob();)r=u(d.Pb(),111),o=Ue(ft(r.b.We((uj(),WG)))),s=r.b.rf().b,_?(z=L+_.d.a+e.w+r.d.d,h=b.Math.max(h,(S1(),Ef(z1),b.Math.abs(P-o)<=z1||P==o||isNaN(P)&&isNaN(o)?0:z/(o-P)))):e.C&&e.C.d>0&&(h=b.Math.max(h,Ett(e.C.d+r.d.d,o))),_=r,P=o,L=s;e.C&&e.C.a>0&&(z=L+e.C.a,x&&(z+=_.d.a),h=b.Math.max(h,(S1(),Ef(z1),b.Math.abs(P-1)<=z1||P==1||isNaN(P)&&isNaN(1)?0:z/(1-P)))),n.n.d=0,n.a.b=h}function Zut(e,t,n){var r,s,o,h,d,v;for(this.g=e,d=t.d.length,v=n.d.length,this.d=Me(h0,Bg,10,d+v,0,1),h=0;h0?Xre(this,this.f/this.a):A1(t.g,t.d[0]).a!=null&&A1(n.g,n.d[0]).a!=null?Xre(this,(Ue(A1(t.g,t.d[0]).a)+Ue(A1(n.g,n.d[0]).a))/2):A1(t.g,t.d[0]).a!=null?Xre(this,A1(t.g,t.d[0]).a):A1(n.g,n.d[0]).a!=null&&Xre(this,A1(n.g,n.d[0]).a)}function Cwn(e,t){var n,r,s,o,h,d,v,x,_,L;for(e.a=new iYe(tsn(RS)),r=new C(t.a);r.a=1&&(X-h>0&&L>=0?(v.n.a+=W,v.n.b+=o*h):X-h<0&&_>=0&&(v.n.a+=W*X,v.n.b+=o));e.o.a=t.a,e.o.b=t.b,Ye(e,(pt(),Ib),(Bl(),r=u(Qf(qS),9),new hh(r,u(wf(r,r.length),9),0)))}function Mwn(e,t,n,r,s,o){var h;if(!(t==null||!$ie(t,OAe,NAe)))throw J(new Ln("invalid scheme: "+t));if(!e&&!(n!=null&&pd(n,Nu(35))==-1&&n.length>0&&(zr(0,n.length),n.charCodeAt(0)!=47)))throw J(new Ln("invalid opaquePart: "+n));if(e&&!(t!=null&&gM(ZV,t.toLowerCase()))&&!(n==null||!$ie(n,KS,YS)))throw J(new Ln(ydt+n));if(e&&t!=null&&gM(ZV,t.toLowerCase())&&!Ehn(n))throw J(new Ln(ydt+n));if(!Son(r))throw J(new Ln("invalid device: "+r));if(!yan(s))throw h=s==null?"invalid segments: null":"invalid segment: "+ban(s),J(new Ln(h));if(!(o==null||pd(o,Nu(35))==-1))throw J(new Ln("invalid query: "+o))}function Dwn(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le;for(kr(t,"Calculate Graph Size",1),t.n&&e&&yf(t,kf(e),(Pl(),nh)),d=O7,v=O7,o=Exe,h=Exe,L=new rr((!e.a&&(e.a=new at(hs,e,10,11)),e.a));L.e!=L.i.gc();)x=u(pr(L),33),q=x.i,W=x.j,le=x.g,r=x.f,s=u(Ft(x,(bi(),WO)),142),d=b.Math.min(d,q-s.b),v=b.Math.min(v,W-s.d),o=b.Math.max(o,q+le+s.c),h=b.Math.max(h,W+r+s.a);for(z=u(Ft(e,(bi(),Fb)),116),P=new Pt(d-z.b,v-z.d),_=new rr((!e.a&&(e.a=new at(hs,e,10,11)),e.a));_.e!=_.i.gc();)x=u(pr(_),33),Du(x,x.i-P.a),Iu(x,x.j-P.b);X=o-d+(z.b+z.c),n=h-v+(z.d+z.a),zv(e,X),Hv(e,n),t.n&&e&&yf(t,kf(e),(Pl(),nh))}function tlt(e){var t,n,r,s,o,h,d,v,x,_;for(r=new st,h=new C(e.e.a);h.a0){OH(e,n,0),n.a+=String.fromCharCode(r),s=bcn(t,o),OH(e,n,s),o+=s-1;continue}r==39?o+11)for(W=Me(Lr,Jr,25,e.b.b.c.length,15,1),L=0,x=new C(e.b.b);x.a=d&&s<=v)d<=s&&o<=v?(n[_++]=s,n[_++]=o,r+=2):d<=s?(n[_++]=s,n[_++]=v,e.b[r]=v+1,h+=2):o<=v?(n[_++]=d,n[_++]=o,r+=2):(n[_++]=d,n[_++]=v,e.b[r]=v+1);else if(vJp)&&d<10);$pe(e.c,new dp),nlt(e),yZt(e.c),Awn(e.f)}function Pwn(e,t,n){var r,s,o,h,d,v,x,_,L,P,z,q,W,X;if(It(Mt(K(n,(pt(),Oy)))))for(d=new C(n.j);d.a=2){for(v=ii(n,0),h=u(ri(v),8),d=u(ri(v),8);d.a0&&ND(x,!0,(wo(),Df)),d.k==(zn(),Ls)&&SYe(x),Si(e.f,d,t)}}function jwn(e,t,n){var r,s,o,h,d,v,x,_,L,P;switch(kr(n,"Node promotion heuristic",1),e.g=t,Vmn(e),e.q=u(K(t,(pt(),Wle)),260),_=u(K(e.g,FTe),19).a,o=new JP,e.q.g){case 2:case 1:k7(e,o);break;case 3:for(e.q=(f4(),oV),k7(e,o),v=0,d=new C(e.a);d.ae.j&&(e.q=LO,k7(e,o));break;case 4:for(e.q=(f4(),oV),k7(e,o),x=0,s=new C(e.b);s.ae.k&&(e.q=MO,k7(e,o));break;case 6:P=_s(b.Math.ceil(e.f.length*_/100)),k7(e,new yp(P));break;case 5:L=_s(b.Math.ceil(e.d*_/100)),k7(e,new Xf(L));break;default:k7(e,o)}Ipn(e,t),ur(n)}function ilt(e,t,n){var r,s,o,h;this.j=e,this.e=r4e(e),this.o=this.j.e,this.i=!!this.o,this.p=this.i?u(St(n,Ya(this.o).p),214):null,s=u(K(e,(et(),eu)),21),this.g=s.Hc((mo(),Th)),this.b=new st,this.d=new Crt(this.e),h=u(K(this.j,Lk),230),this.q=vsn(t,h,this.e),this.k=new _Xe(this),o=O1(ie(re(o2t,1),yt,225,0,[this,this.d,this.k,this.q])),t==(Gv(),IO)&&!It(Mt(K(e,(pt(),My))))?(r=new s4e(this.e),o.c[o.c.length]=r,this.c=new Nwe(r,h,u(this.q,402))):t==IO&&It(Mt(K(e,(pt(),My))))?(r=new s4e(this.e),o.c[o.c.length]=r,this.c=new utt(r,h,u(this.q,402))):this.c=new sqe(t,this),it(o,this.c),jut(o,this.e),this.s=kyn(this.k)}function $wn(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne;for(L=u(sj((h=ii(new Ep(t).a.d,0),new f6(h))),86),q=L?u(K(L,(Tc(),The)),86):null,s=1;L&&q;){for(v=0,Ne=0,n=L,r=q,d=0;d=e.i?(++e.i,it(e.a,ct(1)),it(e.b,_)):(r=e.c[t.p][1],gh(e.a,x,ct(u(St(e.a,x),19).a+1-r)),gh(e.b,x,Ue(ft(St(e.b,x)))+_-r*e.e)),(e.q==(f4(),LO)&&(u(St(e.a,x),19).a>e.j||u(St(e.a,x-1),19).a>e.j)||e.q==MO&&(Ue(ft(St(e.b,x)))>e.k||Ue(ft(St(e.b,x-1)))>e.k))&&(v=!1),h=new cr(fr(Xo(t).a.Kc(),new V));Vr(h);)o=u(Pr(h),17),d=o.c.i,e.f[d.p]==x&&(L=slt(e,d),s=s+u(L.a,19).a,v=v&&It(Mt(L.b)));return e.f[t.p]=x,s=s+e.c[t.p][0],new xa(ct(s),(Mn(),!!v))}function t6e(e,t,n,r,s){var o,h,d,v,x,_,L,P,z,q,W,X,le;for(L=new Mr,h=new st,Sat(e,n,e.d.fg(),h,L),Sat(e,r,e.d.gg(),h,L),e.b=.2*(W=bot(ic(new vn(null,new mn(h,16)),new GQ)),X=bot(ic(new vn(null,new mn(h,16)),new qQ)),b.Math.min(W,X)),o=0,d=0;d=2&&(le=Fot(h,!0,P),!e.e&&(e.e=new $je(e)),wcn(e.e,le,h,e.b)),wst(h,P),nmn(h),z=-1,_=new C(h);_.a<_.c.c.length;)x=u(Y(_),112),!(b.Math.abs(x.s-x.c)d)}function zwn(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W;for(n=u(K(e,(pt(),bs)),98),h=e.f,o=e.d,d=h.a+o.b+o.c,v=0-o.d-e.c.b,_=h.b+o.d+o.a-e.c.b,x=new st,L=new st,s=new C(t);s.a0),u(_.a.Xb(_.c=--_.b),17));o!=r&&_.b>0;)e.a[o.p]=!0,e.a[r.p]=!0,o=(Qn(_.b>0),u(_.a.Xb(_.c=--_.b),17));_.b>0&&Ol(_)}}function ult(e,t,n){var r,s,o,h,d,v,x,_,L;if(e.a!=t.Aj())throw J(new Ln($7+t.ne()+dw));if(r=Ag((Yu(),Oa),t).$k(),r)return r.Aj().Nh().Ih(r,n);if(h=Ag(Oa,t).al(),h){if(n==null)return null;if(d=u(n,15),d.dc())return"";for(L=new bg,o=d.Kc();o.Ob();)s=o.Pb(),To(L,h.Aj().Nh().Ih(h,s)),L.a+=" ";return qte(L,L.a.length-1)}if(_=Ag(Oa,t).bl(),!_.dc()){for(x=_.Kc();x.Ob();)if(v=u(x.Pb(),148),v.wj(n))try{if(L=v.Aj().Nh().Ih(v,n),L!=null)return L}catch(P){if(P=ts(P),!we(P,102))throw J(P)}throw J(new Ln("Invalid value: '"+n+"' for datatype :"+t.ne()))}return u(t,834).Fj(),n==null?null:we(n,172)?""+u(n,172).a:pl(n)==FG?PVe(WS[0],u(n,199)):Qo(n)}function Kwn(e){var t,n,r,s,o,h,d,v,x,_;for(x=new as,d=new as,o=new C(e);o.a-1){for(s=ii(d,0);s.b!=s.d.c;)r=u(ri(s),128),r.v=h;for(;d.b!=0;)for(r=u(vse(d,0),128),n=new C(r.i);n.a0&&(n+=v.n.a+v.o.a/2,++L),q=new C(v.j);q.a0&&(n/=L),le=Me(pa,Ao,25,r.a.c.length,15,1),d=0,x=new C(r.a);x.a=d&&s<=v)d<=s&&o<=v?r+=2:d<=s?(e.b[r]=v+1,h+=2):o<=v?(n[_++]=s,n[_++]=d-1,r+=2):(n[_++]=s,n[_++]=d-1,e.b[r]=v+1,h+=2);else if(v0?s-=864e5:s+=864e5,v=new Sbe(Ua(Ou(t.q.getTime()),s))),_=new xm,x=e.a.length,o=0;o=97&&r<=122||r>=65&&r<=90){for(h=o+1;h=x)throw J(new Ln("Missing trailing '"));h+10&&n.c==0&&(!t&&(t=new st),t.c[t.c.length]=n);if(t)for(;t.c.length!=0;){if(n=u(Eg(t,0),233),n.b&&n.b.c.length>0){for(o=(!n.b&&(n.b=new st),new C(n.b));o.aYo(e,n,0))return new xa(s,n)}else if(Ue(A1(s.g,s.d[0]).a)>Ue(A1(n.g,n.d[0]).a))return new xa(s,n)}for(d=(!n.e&&(n.e=new st),n.e).Kc();d.Ob();)h=u(d.Pb(),233),v=(!h.b&&(h.b=new st),h.b),jm(0,v.c.length),RT(v.c,0,n),h.c==v.c.length&&(t.c[t.c.length]=h)}return null}function glt(e,t){var n,r,s,o,h,d,v,x,_;if(e==null)return Pu;if(v=t.a.zc(e,t),v!=null)return"[...]";for(n=new ib(io,"[","]"),s=e,o=0,h=s.length;o=14&&_<=16))?t.a._b(r)?(n.a?Yr(n.a,n.b):n.a=new Fl(n.d),ZT(n.a,"[...]")):(d=tb(r),x=new l_(t),O0(n,glt(d,x))):we(r,177)?O0(n,V1n(u(r,177))):we(r,190)?O0(n,Nhn(u(r,190))):we(r,195)?O0(n,qfn(u(r,195))):we(r,2012)?O0(n,Phn(u(r,2012))):we(r,48)?O0(n,q1n(u(r,48))):we(r,364)?O0(n,idn(u(r,364))):we(r,832)?O0(n,G1n(u(r,832))):we(r,104)&&O0(n,z1n(u(r,104))):O0(n,r==null?Pu:Qo(r));return n.a?n.e.length==0?n.a.a:n.a.a+(""+n.e):n.c}function plt(e,t,n,r){var s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee;for(d=d4(t,!1,!1),le=iI(d),r&&(le=BD(le)),Ee=Ue(ft(Ft(t,(K_(),Rue)))),X=(Qn(le.b!=0),u(le.a.a.c,8)),L=u(s1(le,1),8),le.b>2?(_=new st,Rs(_,new Zd(le,1,le.b)),o=Klt(_,Ee+e.a),Ce=new zse(o),Ho(Ce,t),n.c[n.c.length]=Ce):r?Ce=u(er(e.b,n0(t)),266):Ce=u(er(e.b,Kp(t)),266),v=n0(t),r&&(v=Kp(t)),h=l1n(X,v),x=Ee+e.a,h.a?(x+=b.Math.abs(X.b-L.b),W=new Pt(L.a,(L.b+X.b)/2)):(x+=b.Math.abs(X.a-L.a),W=new Pt((L.a+X.a)/2,L.b)),r?Si(e.d,t,new C3e(Ce,h,W,x)):Si(e.c,t,new C3e(Ce,h,W,x)),Si(e.b,t,Ce),q=(!t.n&&(t.n=new at(Jo,t,1,7)),t.n),z=new rr(q);z.e!=z.i.gc();)P=u(pr(z),137),s=pI(e,P,!0,0,0),n.c[n.c.length]=s}function nmn(e){var t,n,r,s,o,h,d,v,x,_;for(x=new st,d=new st,h=new C(e);h.a-1){for(o=new C(d);o.a0)&&(qR(v,b.Math.min(v.o,s.o-1)),hT(v,v.i-1),v.i==0&&(d.c[d.c.length]=v))}}function E7(e,t,n){var r,s,o,h,d,v,x;if(x=e.c,!t&&(t=FAe),e.c=t,e.Db&4&&!(e.Db&1)&&(v=new oa(e,1,2,x,e.c),n?n.Ei(v):n=v),x!=t){if(we(e.Cb,284))e.Db>>16==-10?n=u(e.Cb,284).nk(t,n):e.Db>>16==-15&&(!t&&(t=(on(),Z1)),!x&&(x=(on(),Z1)),e.Cb.nh()&&(v=new N0(e.Cb,1,13,x,t,Dg(gl(u(e.Cb,59)),e),!1),n?n.Ei(v):n=v));else if(we(e.Cb,88))e.Db>>16==-23&&(we(t,88)||(t=(on(),sf)),we(x,88)||(x=(on(),sf)),e.Cb.nh()&&(v=new N0(e.Cb,1,10,x,t,Dg(jc(u(e.Cb,26)),e),!1),n?n.Ei(v):n=v));else if(we(e.Cb,444))for(d=u(e.Cb,836),h=(!d.b&&(d.b=new rF(new Kee)),d.b),o=(r=new ob(new dg(h.a).a),new iF(r));o.a.b;)s=u($v(o.a).cd(),87),n=E7(s,nz(s,d),n)}return n}function rmn(e,t){var n,r,s,o,h,d,v,x,_,L,P;for(h=It(Mt(Ft(e,(pt(),Oy)))),P=u(Ft(e,Py),21),v=!1,x=!1,L=new rr((!e.c&&(e.c=new at(xl,e,9,9)),e.c));L.e!=L.i.gc()&&(!v||!x);){for(o=u(pr(L),118),d=0,s=Pp(B1(ie(re(q1,1),yt,20,0,[(!o.d&&(o.d=new wn(ra,o,8,5)),o.d),(!o.e&&(o.e=new wn(ra,o,7,4)),o.e)])));Vr(s)&&(r=u(Pr(s),79),_=h&&ew(r)&&It(Mt(Ft(r,Db))),n=Uut((!r.b&&(r.b=new wn(mr,r,4,7)),r.b),o)?e==us(zo(u(Te((!r.c&&(r.c=new wn(mr,r,5,8)),r.c),0),82))):e==us(zo(u(Te((!r.b&&(r.b=new wn(mr,r,4,7)),r.b),0),82))),!((_||n)&&(++d,d>1))););(d>0||P.Hc((ol(),Z0))&&(!o.n&&(o.n=new at(Jo,o,1,7)),o.n).i>0)&&(v=!0),d>1&&(x=!0)}v&&t.Fc((mo(),Th)),x&&t.Fc((mo(),oS))}function blt(e){var t,n,r,s,o,h,d,v,x,_,L,P;if(P=u(Ft(e,(bi(),Rb)),21),P.dc())return null;if(d=0,h=0,P.Hc((Bl(),tN))){for(_=u(Ft(e,BS),98),r=2,n=2,s=2,o=2,t=us(e)?u(Ft(us(e),Mw),103):u(Ft(e,Mw),103),x=new rr((!e.c&&(e.c=new at(xl,e,9,9)),e.c));x.e!=x.i.gc();)if(v=u(pr(x),118),L=u(Ft(v,t5),61),L==(ht(),uc)&&(L=$5e(v,t),So(v,t5,L)),_==(wa(),tu))switch(L.g){case 1:r=b.Math.max(r,v.i+v.g);break;case 2:n=b.Math.max(n,v.j+v.f);break;case 3:s=b.Math.max(s,v.i+v.g);break;case 4:o=b.Math.max(o,v.j+v.f)}else switch(L.g){case 1:r+=v.g+2;break;case 2:n+=v.f+2;break;case 3:s+=v.g+2;break;case 4:o+=v.f+2}d=b.Math.max(r,s),h=b.Math.max(n,o)}return sw(e,d,h,!0,!0)}function Tae(e,t,n,r,s){var o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne;for(Ce=u(zl(j$(Vi(new vn(null,new mn(t.d,16)),new Gx(n)),new iM(n)),eb(new vt,new Dt,new Hn,ie(re(yl,1),tt,132,0,[(F1(),Ql)]))),15),L=Ei,_=$a,v=new C(t.b.j);v.a0,x?x&&(P=le.p,h?++P:--P,L=u(St(le.c.a,P),10),r=ont(L),z=!(Kse(r,nt,n[0])||RKe(r,nt,n[0]))):z=!0),q=!1,Ve=t.D.i,Ve&&Ve.c&&d.e&&(_=h&&Ve.p>0||!h&&Ve.p0&&(t.a+=io),yz(u(pr(d),160),t);for(t.a+=Ioe,v=new _6((!r.c&&(r.c=new wn(mr,r,5,8)),r.c));v.e!=v.i.gc();)v.e>0&&(t.a+=io),yz(u(pr(v),160),t);t.a+=")"}}function umn(e,t,n){var r,s,o,h,d,v,x,_,L,P,z;if(o=u(K(e,(et(),Mi)),79),!!o){for(r=e.a,s=new Io(n),Ni(s,Jln(e)),z8(e.d.i,e.c.i)?(P=e.c,L=sc(ie(re(na,1),Qe,8,0,[P.n,P.a])),da(L,n)):L=D1(e.c),ks(r,L,r.a,r.a.a),z=D1(e.d),K(e,Rle)!=null&&Ni(z,u(K(e,Rle),8)),ks(r,z,r.c.b,r.c),Um(r,s),h=d4(o,!0,!0),W$(h,u(Te((!o.b&&(o.b=new wn(mr,o,4,7)),o.b),0),82)),K$(h,u(Te((!o.c&&(o.c=new wn(mr,o,5,8)),o.c),0),82)),mI(r,h),_=new C(e.b);_.a<_.c.c.length;)x=u(Y(_),70),d=u(K(x,Mi),137),zv(d,x.o.a),Hv(d,x.o.b),C1(d,x.n.a+s.a,x.n.b+s.b),So(d,(U6(),nle),Mt(K(x,nle)));v=u(K(e,(pt(),Fo)),74),v?(Um(v,s),So(o,Fo,v)):So(o,Fo,null),t==($0(),jk)?So(o,K0,jk):So(o,K0,null)}}function lmn(e,t,n,r){var s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce;for(z=t.c.length,P=0,L=new C(e.b);L.a=0){for(v=null,d=new Ea(_.a,x+1);d.bh?1:yv(isNaN(0),isNaN(h)))<0&&(Ef(Md),(b.Math.abs(h-1)<=Md||h==1||isNaN(h)&&isNaN(1)?0:h<1?-1:h>1?1:yv(isNaN(h),isNaN(1)))<0)&&(Ef(Md),(b.Math.abs(0-d)<=Md||d==0||isNaN(0)&&isNaN(d)?0:0d?1:yv(isNaN(0),isNaN(d)))<0)&&(Ef(Md),(b.Math.abs(d-1)<=Md||d==1||isNaN(d)&&isNaN(1)?0:d<1?-1:d>1?1:yv(isNaN(d),isNaN(1)))<0)),o)}function hmn(e){var t,n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt;for(L=new iwe(new Se(e));L.b!=L.c.a.d;)for(_=mJe(L),d=u(_.d,56),t=u(_.e,56),h=d.Tg(),W=0,Ne=(h.i==null&&xd(h),h.i).length;W=0&&W=x.c.c.length?_=Fwe((zn(),Hs),ca):_=Fwe((zn(),ca),ca),_*=2,o=n.a.g,n.a.g=b.Math.max(o,o+(_-o)),h=n.b.g,n.b.g=b.Math.max(h,h+(_-h)),s=t}}function gmn(e,t,n,r,s){var o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve;for(Ve=PWe(e),_=new st,d=e.c.length,L=d-1,P=d+1;Ve.a.c!=0;){for(;n.b!=0;)Ee=(Qn(n.b!=0),u(bh(n,n.a.a),112)),k_(Ve.a,Ee)!=null,Ee.g=L--,H5e(Ee,t,n,r);for(;t.b!=0;)Ne=(Qn(t.b!=0),u(bh(t,t.a.a),112)),k_(Ve.a,Ne)!=null,Ne.g=P++,H5e(Ne,t,n,r);for(x=$a,le=(h=new o_(new i_(new m(Ve.a).a).b),new g(h));wM(le.a.a);){if(X=(o=dj(le.a),u(o.cd(),112)),!r&&X.b>0&&X.a<=0){_.c=Me(Yn,yt,1,0,5,1),_.c[_.c.length]=X;break}W=X.i-X.d,W>=x&&(W>x&&(_.c=Me(Yn,yt,1,0,5,1),x=W),_.c[_.c.length]=X)}_.c.length!=0&&(v=u(St(_,BH(s,_.c.length)),112),k_(Ve.a,v)!=null,v.g=P++,H5e(v,t,n,r),_.c=Me(Yn,yt,1,0,5,1))}for(Ce=e.c.length+1,q=new C(e);q.a0&&(P.d+=_.n.d,P.d+=_.d),P.a>0&&(P.a+=_.n.a,P.a+=_.d),P.b>0&&(P.b+=_.n.b,P.b+=_.d),P.c>0&&(P.c+=_.n.c,P.c+=_.d),P}function wlt(e,t,n){var r,s,o,h,d,v,x,_,L,P,z,q;for(P=n.d,L=n.c,o=new Pt(n.f.a+n.d.b+n.d.c,n.f.b+n.d.d+n.d.a),h=o.b,x=new C(e.a);x.a0&&(e.c[t.c.p][t.p].d+=vl(e.i,24)*NI*.07000000029802322-.03500000014901161,e.c[t.c.p][t.p].a=e.c[t.c.p][t.p].d/e.c[t.c.p][t.p].b)}}function xmn(e){var t,n,r,s,o,h,d,v,x,_,L,P,z,q,W,X;for(q=new C(e);q.ar.d,r.d=b.Math.max(r.d,t),d&&n&&(r.d=b.Math.max(r.d,r.a),r.a=r.d+s);break;case 3:n=t>r.a,r.a=b.Math.max(r.a,t),d&&n&&(r.a=b.Math.max(r.a,r.d),r.d=r.a+s);break;case 2:n=t>r.c,r.c=b.Math.max(r.c,t),d&&n&&(r.c=b.Math.max(r.b,r.c),r.b=r.c+s);break;case 4:n=t>r.b,r.b=b.Math.max(r.b,t),d&&n&&(r.b=b.Math.max(r.b,r.c),r.c=r.b+s)}}}function Cmn(e){var t,n,r,s,o,h,d,v,x,_,L;for(x=new C(e);x.a0||_.j==Dn&&_.e.c.length-_.g.c.length<0)){t=!1;break}for(s=new C(_.g);s.a=x&&Ve>=X&&(P+=q.n.b+W.n.b+W.a.b-Ne,++d));if(n)for(h=new C(Ce.e);h.a=x&&Ve>=X&&(P+=q.n.b+W.n.b+W.a.b-Ne,++d))}d>0&&(nt+=P/d,++z)}z>0?(t.a=s*nt/z,t.g=z):(t.a=0,t.g=0)}function Amn(e,t){var n,r,s,o,h,d,v,x,_,L,P;for(s=new C(e.a.b);s.aDs||t.o==Pb&&_0&&Du(le,Ne*nt),Ve>0&&Iu(le,Ve*bt);for(B_(e.b,new sm),t=new st,d=new ob(new dg(e.c).a);d.b;)h=$v(d),r=u(h.cd(),79),n=u(h.dd(),395).a,s=d4(r,!1,!1),L=mst(n0(r),iI(s),n),mI(L,s),Ee=Dst(r),Ee&&Yo(t,Ee,0)==-1&&(t.c[t.c.length]=Ee,PYe(Ee,(Qn(L.b!=0),u(L.a.a.c,8)),n));for(X=new ob(new dg(e.d).a);X.b;)W=$v(X),r=u(W.cd(),79),n=u(W.dd(),395).a,s=d4(r,!1,!1),L=mst(Kp(r),BD(iI(s)),n),L=BD(L),mI(L,s),Ee=Ist(r),Ee&&Yo(t,Ee,0)==-1&&(t.c[t.c.length]=Ee,PYe(Ee,(Qn(L.b!=0),u(L.c.b.c,8)),n))}function klt(e,t,n,r){var s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt,bt;if(n.c.length!=0){for(z=new st,P=new C(n);P.a1)for(z=new Y5e(q,Ee,r),Da(Ee,new fqe(e,z)),h.c[h.c.length]=z,L=Ee.a.ec().Kc();L.Ob();)_=u(L.Pb(),46),Au(o,_.b);if(d.a.gc()>1)for(z=new Y5e(q,d,r),Da(d,new dqe(e,z)),h.c[h.c.length]=z,L=d.a.ec().Kc();L.Ob();)_=u(L.Pb(),46),Au(o,_.b)}}function Elt(e){wv(e,new gb(gF(gv(hv(dv(fv(new lg,Dd),"ELK Radial"),'A radial layout provider which is based on the algorithm of Peter Eades published in "Drawing free trees.", published by International Institute for Advanced Study of Social Information Science, Fujitsu Limited in 1991. The radial layouter takes a tree and places the nodes in radial order around the root. The nodes of the same tree level are placed on the same radius.'),new tZ),Dd))),dt(e,Dd,iG,xt(qmt)),dt(e,Dd,py,xt(Vmt)),dt(e,Dd,E4,xt($mt)),dt(e,Dd,gk,xt(Hmt)),dt(e,Dd,dk,xt(zmt)),dt(e,Dd,P7,xt(jmt)),dt(e,Dd,CC,xt(aCe)),dt(e,Dd,B7,xt(Gmt)),dt(e,Dd,yce,xt(Ohe)),dt(e,Dd,mce,xt(Nhe)),dt(e,Dd,Lxe,xt(oCe)),dt(e,Dd,_xe,xt(kV)),dt(e,Dd,Cxe,xt(xV)),dt(e,Dd,Sxe,xt(BO)),dt(e,Dd,Axe,xt(cCe))}function i6e(e){var t;if(this.r=hJt(new ka,new Qi),this.b=new V_(u(Nr(ao),290)),this.p=new V_(u(Nr(ao),290)),this.i=new V_(u(Nr(Ogt),290)),this.e=e,this.o=new Io(e.rf()),this.D=e.Df()||It(Mt(e.We((bi(),UO)))),this.A=u(e.We((bi(),Rb)),21),this.B=u(e.We(p2),21),this.q=u(e.We(BS),98),this.u=u(e.We(Hy),21),!wfn(this.u))throw J(new M3("Invalid port label placement: "+this.u));if(this.v=It(Mt(e.We($Se))),this.j=u(e.We(J4),21),!z0n(this.j))throw J(new M3("Invalid node label placement: "+this.j));this.n=u(Q_(e,SSe),116),this.k=Ue(ft(Q_(e,RV))),this.d=Ue(ft(Q_(e,qSe))),this.w=Ue(ft(Q_(e,YSe))),this.s=Ue(ft(Q_(e,VSe))),this.t=Ue(ft(Q_(e,USe))),this.C=u(Q_(e,WSe),142),this.c=2*this.d,t=!this.B.Hc((wl(),nN)),this.f=new W_(0,t,0),this.g=new W_(1,t,0),Zee(this.f,(n1(),lu),this.g)}function Rmn(e,t,n,r,s){var o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt,bt,zt,Ut,In;for(Ee=0,q=0,z=0,P=1,Ce=new rr((!e.a&&(e.a=new at(hs,e,10,11)),e.a));Ce.e!=Ce.i.gc();)X=u(pr(Ce),33),P+=I0(new cr(fr(z0(X).a.Kc(),new V))),zt=X.g,q=b.Math.max(q,zt),L=X.f,z=b.Math.max(z,L),Ee+=zt*L;for(W=(!e.a&&(e.a=new at(hs,e,10,11)),e.a).i,h=Ee+2*r*r*P*W,o=b.Math.sqrt(h),v=b.Math.max(o*n,q),d=b.Math.max(o/n,z),le=new rr((!e.a&&(e.a=new at(hs,e,10,11)),e.a));le.e!=le.i.gc();)X=u(pr(le),33),Ut=s.b+(vl(t,26)*mC+vl(t,27)*yC)*(v-X.g),In=s.b+(vl(t,26)*mC+vl(t,27)*yC)*(d-X.f),Du(X,Ut),Iu(X,In);for(bt=v+(s.b+s.c),nt=d+(s.d+s.a),Ve=new rr((!e.a&&(e.a=new at(hs,e,10,11)),e.a));Ve.e!=Ve.i.gc();)for(Ne=u(pr(Ve),33),_=new cr(fr(z0(Ne).a.Kc(),new V));Vr(_);)x=u(Pr(_),79),iC(x)||Fyn(x,t,bt,nt);bt+=s.b+s.c,nt+=s.d+s.a,sw(e,bt,nt,!1,!0)}function xz(e){var t,n,r,s,o,h,d,v,x,_,L;if(e==null)throw J(new gd(Pu));if(x=e,o=e.length,v=!1,o>0&&(t=(zr(0,e.length),e.charCodeAt(0)),(t==45||t==43)&&(e=e.substr(1),--o,v=t==45)),o==0)throw J(new gd(cw+x+'"'));for(;e.length>0&&(zr(0,e.length),e.charCodeAt(0)==48);)e=e.substr(1),--o;if(o>(hut(),O0t)[10])throw J(new gd(cw+x+'"'));for(s=0;s0&&(L=-parseInt(e.substr(0,r),10),e=e.substr(r),o-=r,n=!1);o>=h;){if(r=parseInt(e.substr(0,h),10),e=e.substr(h),o-=h,n)n=!1;else{if(Mc(L,d)<0)throw J(new gd(cw+x+'"'));L=ja(L,_)}L=Wp(L,r)}if(Mc(L,0)>0)throw J(new gd(cw+x+'"'));if(!v&&(L=M8(L),Mc(L,0)<0))throw J(new gd(cw+x+'"'));return L}function s6e(e,t){ZWe();var n,r,s,o,h,d,v;if(this.a=new Y2e(this),this.b=e,this.c=t,this.f=Bne(Po((Yu(),Oa),t)),this.f.dc())if((d=q3e(Oa,e))==t)for(this.e=!0,this.d=new st,this.f=new xx,this.f.Fc(_b),u(wz(wD(Oa,Gl(e)),""),26)==e&&this.f.Fc(f_(Oa,Gl(e))),s=iae(Oa,e).Kc();s.Ob();)switch(r=u(s.Pb(),170),Dv(Po(Oa,r))){case 4:{this.d.Fc(r);break}case 5:{this.f.Gc(Bne(Po(Oa,r)));break}}else if(ho(),u(t,66).Oj())for(this.e=!0,this.f=null,this.d=new st,h=0,v=(e.i==null&&xd(e),e.i).length;h=0&&h0&&(u(_o(e.b,t),124).a.b=n)}function Fmn(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le;for(kr(t,"Comment pre-processing",1),n=0,v=new C(e.a);v.a0&&(v=(zr(0,t.length),t.charCodeAt(0)),v!=64)){if(v==37&&(L=t.lastIndexOf("%"),x=!1,L!=0&&(L==P-1||(x=(zr(L+1,t.length),t.charCodeAt(L+1)==46))))){if(h=t.substr(1,L-1),Ee=an("%",h)?null:o6e(h),r=0,x)try{r=Wl(t.substr(L+2),$a,Ei)}catch(Ne){throw Ne=ts(Ne),we(Ne,127)?(d=Ne,J(new D$(d))):J(Ne)}for(X=Hme(e.Wg());X.Ob();)if(q=aH(X),we(q,510)&&(s=u(q,590),Ce=s.d,(Ee==null?Ce==null:an(Ee,Ce))&&r--==0))return s;return null}if(_=t.lastIndexOf("."),z=_==-1?t:t.substr(0,_),n=0,_!=-1)try{n=Wl(t.substr(_+1),$a,Ei)}catch(Ne){if(Ne=ts(Ne),we(Ne,127))z=t;else throw J(Ne)}for(z=an("%",z)?null:o6e(z),W=Hme(e.Wg());W.Ob();)if(q=aH(W),we(q,191)&&(o=u(q,191),le=o.ne(),(z==null?le==null:an(z,le))&&n--==0))return o;return null}return Kut(e,t)}function Hmn(e){var t,n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt,bt,zt,Ut,In,Rn;for(nt=new st,q=new C(e.b);q.a=t.length)return{done:!0};var s=t[r++];return{value:[s,n.get(s)],done:!1}}}},Upn()||(e.prototype.createObject=function(){return{}},e.prototype.get=function(t){return this.obj[":"+t]},e.prototype.set=function(t,n){this.obj[":"+t]=n},e.prototype[coe]=function(t){delete this.obj[":"+t]},e.prototype.keys=function(){var t=[];for(var n in this.obj)n.charCodeAt(0)==58&&t.push(n.substring(1));return t}),e}function Gmn(e){j5e();var t,n,r,s,o,h,d,v,x,_,L,P,z,q,W,X;if(e==null)return null;if(L=e.length*8,L==0)return"";for(d=L%24,z=L/24|0,P=d!=0?z+1:z,o=null,o=Me(Sh,Td,25,P*4,15,1),x=0,_=0,t=0,n=0,r=0,h=0,s=0,v=0;v>24,x=(t&3)<<24>>24,q=t&-128?(t>>2^192)<<24>>24:t>>2<<24>>24,W=n&-128?(n>>4^240)<<24>>24:n>>4<<24>>24,X=r&-128?(r>>6^252)<<24>>24:r>>6<<24>>24,o[h++]=Zg[q],o[h++]=Zg[W|x<<4],o[h++]=Zg[_<<2|X],o[h++]=Zg[r&63];return d==8?(t=e[s],x=(t&3)<<24>>24,q=t&-128?(t>>2^192)<<24>>24:t>>2<<24>>24,o[h++]=Zg[q],o[h++]=Zg[x<<4],o[h++]=61,o[h++]=61):d==16&&(t=e[s],n=e[s+1],_=(n&15)<<24>>24,x=(t&3)<<24>>24,q=t&-128?(t>>2^192)<<24>>24:t>>2<<24>>24,W=n&-128?(n>>4^240)<<24>>24:n>>4<<24>>24,o[h++]=Zg[q],o[h++]=Zg[W|x<<4],o[h++]=Zg[_<<2],o[h++]=61),jh(o,0,o.length)}function qmn(e,t){var n,r,s,o,h,d,v;if(e.e==0&&e.p>0&&(e.p=-(e.p-1)),e.p>$a&&$we(t,e.p-e2),h=t.q.getDate(),tD(t,1),e.k>=0&&Cen(t,e.k),e.c>=0?tD(t,e.c):e.k>=0?(v=new oye(t.q.getFullYear()-e2,t.q.getMonth(),35),r=35-v.q.getDate(),tD(t,b.Math.min(r,h))):tD(t,h),e.f<0&&(e.f=t.q.getHours()),e.b>0&&e.f<12&&(e.f+=12),RWt(t,e.f==24&&e.g?0:e.f),e.j>=0&&Rnn(t,e.j),e.n>=0&&trn(t,e.n),e.i>=0&&Qqe(t,Ua(ja(eI(Ou(t.q.getTime()),Pg),Pg),e.i)),e.a&&(s=new kF,$we(s,s.q.getFullYear()-e2-80),fte(Ou(t.q.getTime()),Ou(s.q.getTime()))&&$we(t,s.q.getFullYear()-e2+100)),e.d>=0){if(e.c==-1)n=(7+e.d-t.q.getDay())%7,n>3&&(n-=7),d=t.q.getMonth(),tD(t,t.q.getDate()+n),t.q.getMonth()!=d&&tD(t,t.q.getDate()+(n>0?-7:7));else if(t.q.getDay()!=e.d)return!1}return e.o>$a&&(o=t.q.getTimezoneOffset(),Qqe(t,Ua(Ou(t.q.getTime()),(e.o-o)*60*Pg))),!0}function Clt(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne;if(s=K(t,(et(),Mi)),!!we(s,239)){for(q=u(s,33),W=t.e,P=new Io(t.c),o=t.d,P.a+=o.b,P.b+=o.d,Ne=u(Ft(q,(pt(),Jq)),174),Vu(Ne,(wl(),$V))&&(z=u(Ft(q,qTe),116),jge(z,o.a),wee(z,o.d),$ge(z,o.b),Vge(z,o.c)),n=new st,_=new C(t.a);_.a<_.c.c.length;)for(v=u(Y(_),10),we(K(v,Mi),239)?Xmn(v,P):we(K(v,Mi),186)&&!W&&(r=u(K(v,Mi),118),Ce=vut(t,v,r.g,r.f),C1(r,Ce.a,Ce.b)),le=new C(v.j);le.a0&&it(e.p,_),it(e.o,_);t-=r,z=v+t,x+=t*e.e,gh(e.a,d,ct(z)),gh(e.b,d,x),e.j=b.Math.max(e.j,z),e.k=b.Math.max(e.k,x),e.d+=t,t+=W}}function ht(){ht=pe;var e;uc=new MM(EC,0),An=new MM(Oz,1),$n=new MM(woe,2),xr=new MM(moe,3),Dn=new MM(yoe,4),Q1=(hn(),new Kx((e=u(Qf(ao),9),new hh(e,u(wf(e,e.length),9),0)))),Bf=Sg(Ui(An,ie(re(ao,1),Dc,61,0,[]))),_h=Sg(Ui($n,ie(re(ao,1),Dc,61,0,[]))),eh=Sg(Ui(xr,ie(re(ao,1),Dc,61,0,[]))),Jh=Sg(Ui(Dn,ie(re(ao,1),Dc,61,0,[]))),Ru=Sg(Ui(An,ie(re(ao,1),Dc,61,0,[xr]))),wu=Sg(Ui($n,ie(re(ao,1),Dc,61,0,[Dn]))),Rf=Sg(Ui(An,ie(re(ao,1),Dc,61,0,[Dn]))),ll=Sg(Ui(An,ie(re(ao,1),Dc,61,0,[$n]))),th=Sg(Ui(xr,ie(re(ao,1),Dc,61,0,[Dn]))),Ch=Sg(Ui($n,ie(re(ao,1),Dc,61,0,[xr]))),hl=Sg(Ui(An,ie(re(ao,1),Dc,61,0,[$n,Dn]))),Bu=Sg(Ui($n,ie(re(ao,1),Dc,61,0,[xr,Dn]))),Fu=Sg(Ui(An,ie(re(ao,1),Dc,61,0,[xr,Dn]))),Ju=Sg(Ui(An,ie(re(ao,1),Dc,61,0,[$n,xr]))),nu=Sg(Ui(An,ie(re(ao,1),Dc,61,0,[$n,xr,Dn])))}function Mlt(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee;if(t.b!=0){for(z=new as,d=null,q=null,r=_s(b.Math.floor(b.Math.log(t.b)*b.Math.LOG10E)+1),v=0,Ee=ii(t,0);Ee.b!=Ee.d.c;)for(le=u(ri(Ee),86),je(q)!==je(K(le,(Tc(),AS)))&&(q=Hr(K(le,AS)),v=0),q!=null?d=q+YXe(v++,r):d=YXe(v++,r),Ye(le,AS,d),X=(s=ii(new Ep(le).a.d,0),new f6(s));vF(X.a);)W=u(ri(X.a),188).c,ks(z,W,z.c.b,z.c),Ye(W,AS,d);for(P=new Mr,h=0;h=v){Qn(le.b>0),le.a.Xb(le.c=--le.b);break}else W.a>x&&(s?(Rs(s.b,W.b),s.a=b.Math.max(s.a,W.a),Ol(le)):(it(W.b,L),W.c=b.Math.min(W.c,x),W.a=b.Math.max(W.a,v),s=W));s||(s=new dHe,s.c=x,s.a=v,Dm(le,s),it(s.b,L))}for(d=t.b,_=0,X=new C(r);X.ad?1:0:(e.b&&(e.b._b(o)&&(s=u(e.b.xc(o),19).a),e.b._b(v)&&(d=u(e.b.xc(v),19).a)),sd?1:0)):t.e.c.length!=0&&n.g.c.length!=0?1:-1}function Kmn(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt,bt;for(kr(t,yft,1),W=new st,nt=new st,x=new C(e.b);x.a0&&(Ee-=z),X5e(h,Ee),_=0,P=new C(h.a);P.a0),d.a.Xb(d.c=--d.b)),v=.4*r*_,!o&&d.bt.d.c){if(z=e.c[t.a.d],X=e.c[L.a.d],z==X)continue;Cf(bf(pf(vf(gf(new Nh,1),100),z),X))}}}}}function o6e(e){kae();var t,n,r,s,o,h,d,v;if(e==null)return null;if(s=pd(e,Nu(37)),s<0)return e;for(v=new Fl(e.substr(0,s)),t=Me(el,A4,25,4,15,1),d=0,r=0,h=e.length;ss+2&&die((zr(s+1,e.length),e.charCodeAt(s+1)),DAe,IAe)&&die((zr(s+2,e.length),e.charCodeAt(s+2)),DAe,IAe))if(n=kQt((zr(s+1,e.length),e.charCodeAt(s+1)),(zr(s+2,e.length),e.charCodeAt(s+2))),s+=2,r>0?(n&192)==128?t[d++]=n<<24>>24:r=0:n>=128&&((n&224)==192?(t[d++]=n<<24>>24,r=2):(n&240)==224?(t[d++]=n<<24>>24,r=3):(n&248)==240&&(t[d++]=n<<24>>24,r=4)),r>0){if(d==r){switch(d){case 2:{Bp(v,((t[0]&31)<<6|t[1]&63)&Ss);break}case 3:{Bp(v,((t[0]&15)<<12|(t[1]&63)<<6|t[2]&63)&Ss);break}}d=0,r=0}}else{for(o=0;o0){if(h+r>e.length)return!1;d=ZH(e.substr(0,h+r),t)}else d=ZH(e,t);switch(o){case 71:return d=u4(e,h,ie(re(mt,1),Qe,2,6,[fht,dht]),t),s.e=d,!0;case 77:return Ppn(e,t,s,d,h);case 76:return Bpn(e,t,s,d,h);case 69:return S1n(e,t,h,s);case 99:return A1n(e,t,h,s);case 97:return d=u4(e,h,ie(re(mt,1),Qe,2,6,["AM","PM"]),t),s.b=d,!0;case 121:return Rpn(e,t,h,d,n,s);case 100:return d<=0?!1:(s.c=d,!0);case 83:return d<0?!1:Hon(d,h,t[0],s);case 104:d==12&&(d=0);case 75:case 72:return d<0?!1:(s.f=d,s.g=!1,!0);case 107:return d<0?!1:(s.f=d,s.g=!0,!0);case 109:return d<0?!1:(s.j=d,!0);case 115:return d<0?!1:(s.n=d,!0);case 90:if(hnt&&(q.c=nt-q.b),it(h.d,new Lne(q,Rye(h,q))),Ce=t==An?b.Math.max(Ce,W.b+x.b.rf().b):b.Math.min(Ce,W.b));for(Ce+=t==An?e.t:-e.t,Ee=Jye((h.e=Ce,h)),Ee>0&&(u(_o(e.b,t),124).a.b=Ee),_=P.Kc();_.Ob();)x=u(_.Pb(),111),!(!x.c||x.c.d.c.length<=0)&&(q=x.c.i,q.c-=x.e.a,q.d-=x.e.b)}function tyn(e){var t,n,r,s,o,h,d,v,x,_,L,P,z;for(t=new Mr,v=new rr(e);v.e!=v.i.gc();){for(d=u(pr(v),33),n=new Ys,Si(jue,d,n),z=new Rc,s=u(zl(new vn(null,new Sv(new cr(fr(hI(d).a.Kc(),new V)))),yKe(z,eb(new vt,new Dt,new Hn,ie(re(yl,1),tt,132,0,[(F1(),Ql)])))),83),Vet(n,u(s.xc((Mn(),!0)),14),new _t),r=u(zl(Vi(u(s.xc(!1),15).Lc(),new hp),eb(new vt,new Dt,new Hn,ie(re(yl,1),tt,132,0,[Ql]))),15),h=r.Kc();h.Ob();)o=u(h.Pb(),79),P=Dst(o),P&&(x=u(hc($o(t.f,P)),21),x||(x=Qot(P),gu(t.f,P,x)),no(n,x));for(s=u(zl(new vn(null,new Sv(new cr(fr(z0(d).a.Kc(),new V)))),yKe(z,eb(new vt,new Dt,new Hn,ie(re(yl,1),tt,132,0,[Ql])))),83),Vet(n,u(s.xc(!0),14),new Gt),r=u(zl(Vi(u(s.xc(!1),15).Lc(),new ff),eb(new vt,new Dt,new Hn,ie(re(yl,1),tt,132,0,[Ql]))),15),L=r.Kc();L.Ob();)_=u(L.Pb(),79),P=Ist(_),P&&(x=u(hc($o(t.f,P)),21),x||(x=Qot(P),gu(t.f,P,x)),no(n,x))}}function nyn(e,t){pae();var n,r,s,o,h,d,v,x,_,L,P,z,q,W;if(v=Mc(e,0)<0,v&&(e=M8(e)),Mc(e,0)==0)switch(t){case 0:return"0";case 1:return L7;case 2:return"0.00";case 3:return"0.000";case 4:return"0.0000";case 5:return"0.00000";case 6:return"0.000000";default:return z=new Tp,t<0?z.a+="0E+":z.a+="0E",z.a+=t==$a?"2147483648":""+-t,z.a}_=18,L=Me(Sh,Td,25,_+1,15,1),n=_,W=e;do x=W,W=eI(W,10),L[--n]=Or(Ua(48,Wp(x,ja(W,10))))&Ss;while(Mc(W,0)!=0);if(s=Wp(Wp(Wp(_,n),t),1),t==0)return v&&(L[--n]=45),jh(L,n,_-n);if(t>0&&Mc(s,-6)>=0){if(Mc(s,0)>=0){for(o=n+Or(s),d=_-1;d>=o;d--)L[d+1]=L[d];return L[++o]=46,v&&(L[--n]=45),jh(L,n,_-n+1)}for(h=2;fte(h,Ua(M8(s),1));h++)L[--n]=48;return L[--n]=46,L[--n]=48,v&&(L[--n]=45),jh(L,n,_-n)}return q=n+1,r=_,P=new xm,v&&(P.a+="-"),r-q>=1?(Bp(P,L[n]),P.a+=".",P.a+=jh(L,n+1,_-n-1)):P.a+=jh(L,n,_-n),P.a+="E",Mc(s,0)>0&&(P.a+="+"),P.a+=""+d_(s),P.a}function ryn(e,t,n){var r,s,o,h,d,v,x,_,L,P,z;if(e.e.a.$b(),e.f.a.$b(),e.c.c=Me(Yn,yt,1,0,5,1),e.i.c=Me(Yn,yt,1,0,5,1),e.g.a.$b(),t)for(h=new C(t.a);h.a=1&&(Ve-x>0&&q>=0?(Du(L,L.i+Ne),Iu(L,L.j+v*x)):Ve-x<0&&z>=0&&(Du(L,L.i+Ne*Ve),Iu(L,L.j+v)));return So(e,(bi(),Rb),(Bl(),o=u(Qf(qS),9),new hh(o,u(wf(o,o.length),9),0))),new Pt(nt,_)}function Olt(e){var t,n,r,s,o,h,d,v,x,_,L,P,z,q;if(z=us(zo(u(Te((!e.b&&(e.b=new wn(mr,e,4,7)),e.b),0),82))),q=us(zo(u(Te((!e.c&&(e.c=new wn(mr,e,5,8)),e.c),0),82))),L=z==q,d=new Fa,t=u(Ft(e,(hH(),rAe)),74),t&&t.b>=2){if((!e.a&&(e.a=new at(os,e,6,6)),e.a).i==0)n=(pv(),s=new ld,s),Br((!e.a&&(e.a=new at(os,e,6,6)),e.a),n);else if((!e.a&&(e.a=new at(os,e,6,6)),e.a).i>1)for(P=new _6((!e.a&&(e.a=new at(os,e,6,6)),e.a));P.e!=P.i.gc();)J_(P);mI(t,u(Te((!e.a&&(e.a=new at(os,e,6,6)),e.a),0),202))}if(L)for(r=new rr((!e.a&&(e.a=new at(os,e,6,6)),e.a));r.e!=r.i.gc();)for(n=u(pr(r),202),x=new rr((!n.a&&(n.a=new Bs(ef,n,5)),n.a));x.e!=x.i.gc();)v=u(pr(x),469),d.a=b.Math.max(d.a,v.a),d.b=b.Math.max(d.b,v.b);for(h=new rr((!e.n&&(e.n=new at(Jo,e,1,7)),e.n));h.e!=h.i.gc();)o=u(pr(h),137),_=u(Ft(o,FS),8),_&&C1(o,_.a,_.b),L&&(d.a=b.Math.max(d.a,o.i+o.g),d.b=b.Math.max(d.b,o.j+o.f));return d}function iyn(e,t,n){var r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt,bt,zt;for(Ee=t.c.length,s=new p4(e.a,n,null,null),zt=Me(pa,Ao,25,Ee,15,1),W=Me(pa,Ao,25,Ee,15,1),q=Me(pa,Ao,25,Ee,15,1),X=0,d=0;dzt[v]&&(X=v),L=new C(e.a.b);L.az&&(o&&(q2(nt,P),q2(zt,ct(x.b-1))),ki=n.b,Ws+=P+t,P=0,_=b.Math.max(_,n.b+n.c+dr)),Du(d,ki),Iu(d,Ws),_=b.Math.max(_,ki+dr+n.c),P=b.Math.max(P,L),ki+=dr+t;if(_=b.Math.max(_,r),Rn=Ws+P+n.a,RnSd,Ut=b.Math.abs(P.b-q.b)>Sd,(!n&&zt&&Ut||n&&(zt||Ut))&&ci(X.a,Ne)),no(X.a,r),r.b==0?P=Ne:P=(Qn(r.b!=0),u(r.c.b.c,8)),xsn(z,L,W),xtt(s)==bt&&(Ya(bt.i)!=s.a&&(W=new Fa,_4e(W,Ya(bt.i),Ce)),Ye(X,Rle,W)),Ufn(z,X,Ce),_.a.zc(z,_);Va(X,Ve),ba(X,bt)}for(x=_.a.ec().Kc();x.Ob();)v=u(x.Pb(),17),Va(v,null),ba(v,null);ur(t)}function Nlt(e){var t,n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne;if(e.gc()==1)return u(e.Xb(0),231);if(e.gc()<=0)return new k$;for(s=e.Kc();s.Ob();){for(n=u(s.Pb(),231),q=0,_=Ei,L=Ei,v=$a,x=$a,z=new C(n.e);z.ad&&(Ee=0,Ne+=h+le,h=0),q2n(W,n,Ee,Ne),t=b.Math.max(t,Ee+X.a),h=b.Math.max(h,X.b),Ee+=X.a+le;return W}function Plt(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q;switch(_=new Gu,e.a.g){case 3:P=u(K(t.e,(et(),Mb)),15),z=u(K(t.j,Mb),15),q=u(K(t.f,Mb),15),n=u(K(t.e,q4),15),r=u(K(t.j,q4),15),s=u(K(t.f,q4),15),h=new st,Rs(h,P),z.Jc(new XX),Rs(h,we(z,152)?H6(u(z,152)):we(z,131)?u(z,131).a:we(z,54)?new lv(z):new Em(z)),Rs(h,q),o=new st,Rs(o,n),Rs(o,we(r,152)?H6(u(r,152)):we(r,131)?u(r,131).a:we(r,54)?new lv(r):new Em(r)),Rs(o,s),Ye(t.f,Mb,h),Ye(t.f,q4,o),Ye(t.f,z9e,t.f),Ye(t.e,Mb,null),Ye(t.e,q4,null),Ye(t.j,Mb,null),Ye(t.j,q4,null);break;case 1:no(_,t.e.a),ci(_,t.i.n),no(_,nb(t.j.a)),ci(_,t.a.n),no(_,t.f.a);break;default:no(_,t.e.a),no(_,nb(t.j.a)),no(_,t.f.a)}Rh(t.f.a),no(t.f.a,_),Va(t.f,t.e.c),d=u(K(t.e,(pt(),Fo)),74),x=u(K(t.j,Fo),74),v=u(K(t.f,Fo),74),(d||x||v)&&(L=new Gu,Kve(L,v),Kve(L,x),Kve(L,d),Ye(t.f,Fo,L)),Va(t.j,null),ba(t.j,null),Va(t.e,null),ba(t.e,null),No(t.a,null),No(t.i,null),t.g&&Plt(e,t.g)}function cyn(e){j5e();var t,n,r,s,o,h,d,v,x,_,L,P,z,q,W,X;if(e==null||(o=O$(e),q=Yan(o),q%4!=0))return null;if(W=q/4|0,W==0)return Me(el,A4,25,0,15,1);for(L=null,t=0,n=0,r=0,s=0,h=0,d=0,v=0,x=0,z=0,P=0,_=0,L=Me(el,A4,25,W*3,15,1);z>4)<<24>>24,L[P++]=((n&15)<<4|r>>2&15)<<24>>24,L[P++]=(r<<6|s)<<24>>24}return!fM(h=o[_++])||!fM(d=o[_++])?null:(t=J1[h],n=J1[d],v=o[_++],x=o[_++],J1[v]==-1||J1[x]==-1?v==61&&x==61?n&15?null:(X=Me(el,A4,25,z*3+1,15,1),Hc(L,0,X,0,z*3),X[P]=(t<<2|n>>4)<<24>>24,X):v!=61&&x==61?(r=J1[v],r&3?null:(X=Me(el,A4,25,z*3+2,15,1),Hc(L,0,X,0,z*3),X[P++]=(t<<2|n>>4)<<24>>24,X[P]=((n&15)<<4|r>>2&15)<<24>>24,X)):null:(r=J1[v],s=J1[x],L[P++]=(t<<2|n>>4)<<24>>24,L[P++]=((n&15)<<4|r>>2&15)<<24>>24,L[P++]=(r<<6|s)<<24>>24,L))}function uyn(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve;for(kr(t,yft,1),q=u(K(e,(pt(),K0)),218),s=new C(e.b);s.a=2){for(W=!0,P=new C(o.j),n=u(Y(P),11),z=null;P.a0&&(s=u(St(X.c.a,nt-1),10),h=e.i[s.p],zt=b.Math.ceil(j3(e.n,s,X)),o=Ve.a.e-X.d.d-(h.a.e+s.o.b+s.d.a)-zt),x=gs,nt0&&bt.a.e.e-bt.a.a-(bt.b.e.e-bt.b.a)<0,q=Ee.a.e.e-Ee.a.a-(Ee.b.e.e-Ee.b.a)<0&&bt.a.e.e-bt.a.a-(bt.b.e.e-bt.b.a)>0,z=Ee.a.e.e+Ee.b.abt.b.e.e+bt.a.a,Ne=0,!W&&!q&&(P?o+L>0?Ne=L:x-r>0&&(Ne=r):z&&(o+d>0?Ne=d:x-Ce>0&&(Ne=Ce))),Ve.a.e+=Ne,Ve.b&&(Ve.d.e+=Ne),!1))}function Rlt(e,t,n){var r,s,o,h,d,v,x,_,L,P;if(r=new fh(t.qf().a,t.qf().b,t.rf().a,t.rf().b),s=new T6,e.c)for(h=new C(t.wf());h.ax&&(r.a+=$Ve(Me(Sh,Td,25,-x,15,1))),r.a+="Is",pd(v,Nu(32))>=0)for(s=0;s=r.o.b/2}else Ce=!L;Ce?(le=u(K(r,(et(),Mk)),15),le?P?o=le:(s=u(K(r,_k),15),s?le.gc()<=s.gc()?o=le:o=s:(o=new st,Ye(r,_k,o))):(o=new st,Ye(r,Mk,o))):(s=u(K(r,(et(),_k)),15),s?L?o=s:(le=u(K(r,Mk),15),le?s.gc()<=le.gc()?o=s:o=le:(o=new st,Ye(r,Mk,o))):(o=new st,Ye(r,_k,o))),o.Fc(e),Ye(e,(et(),Bq),n),t.d==n?(ba(t,null),n.e.c.length+n.g.c.length==0&&rc(n,null),ran(n)):(Va(t,null),n.e.c.length+n.g.c.length==0&&rc(n,null)),Rh(t.a)}function dyn(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt,bt,zt,Ut,In,Rn,dr,ki;for(Ce=new Ea(e.b,0),_=t.Kc(),q=0,x=u(_.Pb(),19).a,Ve=0,n=new Ys,bt=new C0;Ce.b=e.a&&(r=Zbn(e,Ce),_=b.Math.max(_,r.b),Ne=b.Math.max(Ne,r.d),it(d,new xa(Ce,r)));for(zt=new st,x=0;x<_;++x)Om(zt,0,(Qn(X.b>0),X.a.Xb(X.c=--X.b),Ut=new Bh(e.b),Dm(X,Ut),Qn(X.b0?(x=0,X&&(x+=d),x+=(Ut-1)*h,Ee&&(x+=d),zt&&Ee&&(x=b.Math.max(x,Qgn(Ee,h,Ce,bt))),x0){for(P=_<100?null:new _p(_),x=new Vme(t),q=x.g,le=Me(Lr,Jr,25,_,15,1),r=0,Ne=new jv(_),s=0;s=0;)if(z!=null?Ci(z,q[v]):je(z)===je(q[v])){le.length<=r&&(X=le,le=Me(Lr,Jr,25,2*le.length,15,1),Hc(X,0,le,0,r)),le[r++]=s,Br(Ne,q[v]);break e}if(z=z,je(z)===je(d))break}}if(x=Ne,q=Ne.g,_=r,r>le.length&&(X=le,le=Me(Lr,Jr,25,r,15,1),Hc(X,0,le,0,r)),r>0){for(Ee=!0,o=0;o=0;)J6(e,le[h]);if(r!=_){for(s=_;--s>=r;)J6(x,s);X=le,le=Me(Lr,Jr,25,r,15,1),Hc(X,0,le,0,r)}t=x}}}else for(t=Yun(e,t),s=e.i;--s>=0;)t.Hc(e.g[s])&&(J6(e,s),Ee=!0);if(Ee){if(le!=null){for(n=t.gc(),L=n==1?x_(e,4,t.Kc().Pb(),null,le[0],W):x_(e,6,t,le,le[0],W),P=n<100?null:new _p(n),s=t.Kc();s.Ob();)z=s.Pb(),P=Ybe(e,u(z,72),P);P?(P.Ei(L),P.Fi()):_i(e.e,L)}else{for(P=cYt(t.gc()),s=t.Kc();s.Ob();)z=s.Pb(),P=Ybe(e,u(z,72),P);P&&P.Fi()}return!0}else return!1}function wyn(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee;for(n=new hit(t),n.a||tbn(t),x=n2n(t),v=new Nv,X=new sct,W=new C(t.a);W.a0||n.o==K1&&s0?(L=u(St(P.c.a,h-1),10),zt=j3(e.b,P,L),X=P.n.b-P.d.d-(L.n.b+L.o.b+L.d.a+zt)):X=P.n.b-P.d.d,x=b.Math.min(X,x),hh?w7(e,t,n):w7(e,n,t),sh?1:0}return r=u(K(t,(et(),Nc)),19).a,o=u(K(n,Nc),19).a,r>o?w7(e,t,n):w7(e,n,t),ro?1:0}function c6e(e,t,n,r){var s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce;if(It(Mt(Ft(t,(bi(),PV)))))return hn(),hn(),bo;if(x=(!t.a&&(t.a=new at(hs,t,10,11)),t.a).i!=0,L=adn(t),_=!L.dc(),x||_){if(s=u(Ft(t,xE),149),!s)throw J(new M3("Resolved algorithm is not set; apply a LayoutAlgorithmResolver before computing layout."));if(Ce=D2e(s,(g7(),KV)),Urt(t),!x&&_&&!Ce)return hn(),hn(),bo;if(v=new st,je(Ft(t,Q4))===je((F0(),Wg))&&(D2e(s,UV)||D2e(s,VV)))for(z=Act(e,t),q=new as,no(q,(!t.a&&(t.a=new at(hs,t,10,11)),t.a));q.b!=0;)P=u(q.b==0?null:(Qn(q.b!=0),bh(q,q.a.a)),33),Urt(P),le=je(Ft(P,Q4))===je(jS),le||J2(P,PS)&&!Vwe(s,Ft(P,xE))?(d=c6e(e,P,n,r),Rs(v,d),So(P,Q4,jS),Vct(P)):no(q,(!P.a&&(P.a=new at(hs,P,10,11)),P.a));else for(z=(!t.a&&(t.a=new at(hs,t,10,11)),t.a).i,h=new rr((!t.a&&(t.a=new at(hs,t,10,11)),t.a));h.e!=h.i.gc();)o=u(pr(h),33),d=c6e(e,o,n,r),Rs(v,d),Vct(o);for(X=new C(v);X.a=0?z=Y6(d):z=zD(Y6(d)),e.Ye(gE,z)),x=new Fa,P=!1,e.Xe(Cw)?(ybe(x,u(e.We(Cw),8)),P=!0):WWt(x,h.a/2,h.b/2),z.g){case 4:Ye(_,vu,(mh(),l2)),Ye(_,Fq,(sb(),F4)),_.o.b=h.b,W<0&&(_.o.a=-W),Vs(L,(ht(),$n)),P||(x.a=h.a),x.a-=h.a;break;case 2:Ye(_,vu,(mh(),Ly)),Ye(_,Fq,(sb(),aE)),_.o.b=h.b,W<0&&(_.o.a=-W),Vs(L,(ht(),Dn)),P||(x.a=0);break;case 1:Ye(_,Lb,(P0(),$4)),_.o.a=h.a,W<0&&(_.o.b=-W),Vs(L,(ht(),xr)),P||(x.b=h.b),x.b-=h.b;break;case 3:Ye(_,Lb,(P0(),Tk)),_.o.a=h.a,W<0&&(_.o.b=-W),Vs(L,(ht(),An)),P||(x.b=0)}if(ybe(L.n,x),Ye(_,Cw,x),t==$b||t==p0||t==tu){if(q=0,t==$b&&e.Xe(zg))switch(z.g){case 1:case 2:q=u(e.We(zg),19).a;break;case 3:case 4:q=-u(e.We(zg),19).a}else switch(z.g){case 4:case 2:q=o.b,t==p0&&(q/=s.b);break;case 1:case 3:q=o.a,t==p0&&(q/=s.a)}Ye(_,Ew,q)}return Ye(_,vc,z),_}function kyn(e){var t,n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt,bt,zt,Ut;if(n=Ue(ft(K(e.a.j,(pt(),xTe)))),n<-1||!e.a.i||A6(u(K(e.a.o,bs),98))||ac(e.a.o,(ht(),$n)).gc()<2&&ac(e.a.o,Dn).gc()<2)return!0;if(e.a.c.Rf())return!1;for(Ve=0,Ne=0,Ee=new st,v=e.a.e,x=0,_=v.length;x<_;++x){for(d=v[x],P=d,z=0,W=P.length;z=n}function xyn(){qpe();function e(r){var s=this;this.dispatch=function(o){var h=o.data;switch(h.cmd){case"algorithms":var d=Zye((hn(),new T(new E1(x2.b))));r.postMessage({id:h.id,data:d});break;case"categories":var v=Zye((hn(),new T(new E1(x2.c))));r.postMessage({id:h.id,data:v});break;case"options":var x=Zye((hn(),new T(new E1(x2.d))));r.postMessage({id:h.id,data:x});break;case"register":Lwn(h.algorithms),r.postMessage({id:h.id});break;case"layout":uvn(h.graph,h.layoutOptions||{},h.options||{}),r.postMessage({id:h.id,data:h.graph});break}},this.saveDispatch=function(o){try{s.dispatch(o)}catch(h){r.postMessage({id:o.data.id,error:h})}}}function t(r){var s=this;this.dispatcher=new e({postMessage:function(o){s.onmessage({data:o})}}),this.postMessage=function(o){setTimeout(function(){s.dispatcher.saveDispatch({data:o})},0)}}if(typeof document===foe&&typeof self!==foe){var n=new e(self);self.onmessage=n.saveDispatch}else typeof p!==foe&&p.exports&&(Object.defineProperty(w,"__esModule",{value:!0}),p.exports={default:t,Worker:t})}function Eyn(e){e.N||(e.N=!0,e.b=gc(e,0),ls(e.b,0),ls(e.b,1),ls(e.b,2),e.bb=gc(e,1),ls(e.bb,0),ls(e.bb,1),e.fb=gc(e,2),ls(e.fb,3),ls(e.fb,4),zi(e.fb,5),e.qb=gc(e,3),ls(e.qb,0),zi(e.qb,1),zi(e.qb,2),ls(e.qb,3),ls(e.qb,4),zi(e.qb,5),ls(e.qb,6),e.a=di(e,4),e.c=di(e,5),e.d=di(e,6),e.e=di(e,7),e.f=di(e,8),e.g=di(e,9),e.i=di(e,10),e.j=di(e,11),e.k=di(e,12),e.n=di(e,13),e.o=di(e,14),e.p=di(e,15),e.q=di(e,16),e.s=di(e,17),e.r=di(e,18),e.t=di(e,19),e.u=di(e,20),e.v=di(e,21),e.w=di(e,22),e.B=di(e,23),e.A=di(e,24),e.C=di(e,25),e.D=di(e,26),e.F=di(e,27),e.G=di(e,28),e.H=di(e,29),e.J=di(e,30),e.I=di(e,31),e.K=di(e,32),e.M=di(e,33),e.L=di(e,34),e.P=di(e,35),e.Q=di(e,36),e.R=di(e,37),e.S=di(e,38),e.T=di(e,39),e.U=di(e,40),e.V=di(e,41),e.X=di(e,42),e.W=di(e,43),e.Y=di(e,44),e.Z=di(e,45),e.$=di(e,46),e._=di(e,47),e.ab=di(e,48),e.cb=di(e,49),e.db=di(e,50),e.eb=di(e,51),e.gb=di(e,52),e.hb=di(e,53),e.ib=di(e,54),e.jb=di(e,55),e.kb=di(e,56),e.lb=di(e,57),e.mb=di(e,58),e.nb=di(e,59),e.ob=di(e,60),e.pb=di(e,61))}function Tyn(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne;if(Ce=0,t.f.a==0)for(X=new C(e);X.ax&&(xn(x,t.c.length),u(t.c[x],200)).a.c.length==0;)Au(t,(xn(x,t.c.length),t.c[x]));if(!v){--o;continue}if(lbn(t,_,s,v,P,n,x,r)){L=!0;continue}if(P){if(vvn(t,_,s,v,n,x,r)){L=!0;continue}else if(_ye(_,s)){s.c=!0,L=!0;continue}}else if(_ye(_,s)){s.c=!0,L=!0;continue}if(L)continue}if(_ye(_,s)){s.c=!0,L=!0,v&&(v.k=!1);continue}else $H(s.q)}return L}function Sae(e,t,n,r,s,o,h){var d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt,bt,zt,Ut,In,Rn,dr,ki,Ws;for(W=0,In=0,x=new C(e.b);x.aW&&(o&&(q2(nt,z),q2(zt,ct(_.b-1)),it(e.d,q),d.c=Me(Yn,yt,1,0,5,1)),ki=n.b,Ws+=z+t,z=0,L=b.Math.max(L,n.b+n.c+dr)),d.c[d.c.length]=v,iit(v,ki,Ws),L=b.Math.max(L,ki+dr+n.c),z=b.Math.max(z,P),ki+=dr+t,q=v;if(Rs(e.a,d),it(e.d,u(St(d,d.c.length-1),157)),L=b.Math.max(L,r),Rn=Ws+z+n.a,Rn1&&(h=b.Math.min(h,b.Math.abs(u(s1(d.a,1),8).b-_.b)))));else for(W=new C(t.j);W.as&&(o=P.a-s,h=Ei,r.c=Me(Yn,yt,1,0,5,1),s=P.a),P.a>=s&&(r.c[r.c.length]=d,d.a.b>1&&(h=b.Math.min(h,b.Math.abs(u(s1(d.a,d.a.b-2),8).b-P.b)))));if(r.c.length!=0&&o>t.o.a/2&&h>t.o.b/2){for(z=new $c,rc(z,t),Vs(z,(ht(),An)),z.n.a=t.o.a/2,le=new $c,rc(le,t),Vs(le,xr),le.n.a=t.o.a/2,le.n.b=t.o.b,v=new C(r);v.a=x.b?Va(d,le):Va(d,z)):(x=u(yQt(d.a),8),X=d.a.b==0?D1(d.c):u(fj(d.a),8),X.b>=x.b?ba(d,le):ba(d,z)),L=u(K(d,(pt(),Fo)),74),L&&Xm(L,x,!0);t.n.a=s-t.o.a/2}}function Lyn(e,t,n){var r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt,bt,zt,Ut,In,Rn,dr,ki,Ws,rh,af;if(In=null,dr=t,Rn=GQe(e,jQe(n),dr),I_(Rn,D0(dr,Id)),ki=u(K3(e.g,tk(M0(dr,Bce))),33),P=M0(dr,"sourcePort"),r=null,P&&(r=tk(P)),Ws=u(K3(e.j,r),118),!ki)throw d=i7(dr),q="An edge must have a source node (edge id: '"+d,W=q+z7,J(new dd(W));if(Ws&&!md(L1(Ws),ki))throw v=D0(dr,Id),X="The source port of an edge must be a port of the edge's source node (edge id: '"+v,le=X+z7,J(new dd(le));if(zt=(!Rn.b&&(Rn.b=new wn(mr,Rn,4,7)),Rn.b),o=null,Ws?o=Ws:o=ki,Br(zt,o),rh=u(K3(e.g,tk(M0(dr,o8e))),33),z=M0(dr,"targetPort"),s=null,z&&(s=tk(z)),af=u(K3(e.j,s),118),!rh)throw L=i7(dr),Ce="An edge must have a target node (edge id: '"+L,Ee=Ce+z7,J(new dd(Ee));if(af&&!md(L1(af),rh))throw x=D0(dr,Id),Ne="The target port of an edge must be a port of the edge's target node (edge id: '"+x,Ve=Ne+z7,J(new dd(Ve));if(Ut=(!Rn.c&&(Rn.c=new wn(mr,Rn,5,8)),Rn.c),h=null,af?h=af:h=rh,Br(Ut,h),(!Rn.b&&(Rn.b=new wn(mr,Rn,4,7)),Rn.b).i==0||(!Rn.c&&(Rn.c=new wn(mr,Rn,5,8)),Rn.c).i==0)throw _=D0(dr,Id),nt=R1t+_,bt=nt+z7,J(new dd(bt));return KH(dr,Rn),m0n(dr,Rn),In=pie(e,dr,Rn),In}function zlt(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt,bt,zt,Ut,In;return L=Ibn(_u(e,(ht(),Q1)),t),q=s4(_u(e,Bf),t),Ne=s4(_u(e,eh),t),zt=HH(_u(e,Jh),t),P=HH(_u(e,_h),t),Ce=s4(_u(e,Rf),t),W=s4(_u(e,ll),t),nt=s4(_u(e,th),t),Ve=s4(_u(e,Ch),t),Ut=HH(_u(e,wu),t),le=s4(_u(e,Ru),t),Ee=s4(_u(e,hl),t),bt=s4(_u(e,Bu),t),In=HH(_u(e,Fu),t),z=HH(_u(e,Ju),t),X=s4(_u(e,nu),t),n=Q3(ie(re(pa,1),Ao,25,15,[Ce.a,zt.a,nt.a,In.a])),r=Q3(ie(re(pa,1),Ao,25,15,[q.a,L.a,Ne.a,X.a])),s=le.a,o=Q3(ie(re(pa,1),Ao,25,15,[W.a,P.a,Ve.a,z.a])),x=Q3(ie(re(pa,1),Ao,25,15,[Ce.b,q.b,W.b,Ee.b])),v=Q3(ie(re(pa,1),Ao,25,15,[zt.b,L.b,P.b,X.b])),_=Ut.b,d=Q3(ie(re(pa,1),Ao,25,15,[nt.b,Ne.b,Ve.b,bt.b])),_g(_u(e,Q1),n+s,x+_),_g(_u(e,nu),n+s,x+_),_g(_u(e,Bf),n+s,0),_g(_u(e,eh),n+s,x+_+v),_g(_u(e,Jh),0,x+_),_g(_u(e,_h),n+s+r,x+_),_g(_u(e,ll),n+s+r,0),_g(_u(e,th),0,x+_+v),_g(_u(e,Ch),n+s+r,x+_+v),_g(_u(e,wu),0,x),_g(_u(e,Ru),n,0),_g(_u(e,Bu),0,x+_+v),_g(_u(e,Ju),n+s+r,0),h=new Fa,h.a=Q3(ie(re(pa,1),Ao,25,15,[n+r+s+o,Ut.a,Ee.a,bt.a])),h.b=Q3(ie(re(pa,1),Ao,25,15,[x+v+_+d,le.b,In.b,z.b])),h}function Myn(e){var t,n,r,s,o,h,d,v,x,_,L,P,z,q,W,X;for(W=new st,P=new C(e.d.b);P.as.d.d+s.d.a?_.f.d=!0:(_.f.d=!0,_.f.a=!0))),r.b!=r.d.c&&(t=n);_&&(o=u(er(e.f,h.d.i),57),t.bo.d.d+o.d.a?_.f.d=!0:(_.f.d=!0,_.f.a=!0))}for(d=new cr(fr(Xo(z).a.Kc(),new V));Vr(d);)h=u(Pr(d),17),h.a.b!=0&&(t=u(fj(h.a),8),h.d.j==(ht(),An)&&(X=new hC(t,new Pt(t.a,s.d.d),s,h),X.f.a=!0,X.a=h.d,W.c[W.c.length]=X),h.d.j==xr&&(X=new hC(t,new Pt(t.a,s.d.d+s.d.a),s,h),X.f.d=!0,X.a=h.d,W.c[W.c.length]=X))}return W}function Dyn(e,t,n){var r,s,o,h,d,v,x,_,L;if(kr(n,"Network simplex node placement",1),e.e=t,e.n=u(K(t,(et(),G4)),304),Kvn(e),Ahn(e),ms(ic(new vn(null,new mn(e.e.b,16)),new hQ),new Oje(e)),ms(Vi(ic(Vi(ic(new vn(null,new mn(e.e.b,16)),new N9),new kQ),new xQ),new EQ),new Ije(e)),It(Mt(K(e.e,(pt(),gS))))&&(h=Kc(n,1),kr(h,"Straight Edges Pre-Processing",1),dmn(e),ur(h)),uun(e.f),o=u(K(t,vS),19).a*e.f.a.c.length,sae(Rpe(Fpe(bne(e.f),o),!1),Kc(n,1)),e.d.a.gc()!=0){for(h=Kc(n,1),kr(h,"Flexible Where Space Processing",1),d=u(Tv(Fj(Cu(new vn(null,new mn(e.f.a,16)),new fQ),new sQ)),19).a,v=u(Tv(Rj(Cu(new vn(null,new mn(e.f.a,16)),new dQ),new aQ)),19).a,x=v-d,_=Ev(new z2,e.f),L=Ev(new z2,e.f),Cf(bf(pf(gf(vf(new Nh,2e4),x),_),L)),ms(Vi(Vi(Rne(e.i),new gQ),new pQ),new MYe(d,_,x,L)),s=e.d.a.ec().Kc();s.Ob();)r=u(s.Pb(),213),r.g=1;sae(Rpe(Fpe(bne(e.f),o),!1),Kc(h,1)),ur(h)}It(Mt(K(t,gS)))&&(h=Kc(n,1),kr(h,"Straight Edges Post-Processing",1),w1n(e),ur(h)),Qwn(e),e.e=null,e.f=null,e.i=null,e.c=null,sl(e.k),e.j=null,e.a=null,e.o=null,e.d.a.$b(),ur(n)}function Iyn(e,t,n){var r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve;for(d=new C(e.a.b);d.a0)if(r=L.gc(),x=_s(b.Math.floor((r+1)/2))-1,s=_s(b.Math.ceil((r+1)/2))-1,t.o==K1)for(_=s;_>=x;_--)t.a[Ne.p]==Ne&&(W=u(L.Xb(_),46),q=u(W.a,10),!_0(n,W.b)&&z>e.b.e[q.p]&&(t.a[q.p]=Ne,t.g[Ne.p]=t.g[q.p],t.a[Ne.p]=t.g[Ne.p],t.f[t.g[Ne.p].p]=(Mn(),!!(It(t.f[t.g[Ne.p].p])&Ne.k==(zn(),ca))),z=e.b.e[q.p]));else for(_=x;_<=s;_++)t.a[Ne.p]==Ne&&(le=u(L.Xb(_),46),X=u(le.a,10),!_0(n,le.b)&&z=q&&(Ce>q&&(z.c=Me(Yn,yt,1,0,5,1),q=Ce),z.c[z.c.length]=h);z.c.length!=0&&(P=u(St(z,BH(t,z.c.length)),128),Rn.a.Bc(P)!=null,P.s=W++,s5e(P,Ut,nt),z.c=Me(Yn,yt,1,0,5,1))}for(Ne=e.c.length+1,d=new C(e);d.aIn.s&&(Ol(n),Au(In.i,r),r.c>0&&(r.a=In,it(In.t,r),r.b=bt,it(bt.i,r)))}function u6e(e){var t,n,r,s,o;switch(t=e.c,t){case 11:return e.Ml();case 12:return e.Ol();case 14:return e.Ql();case 15:return e.Tl();case 16:return e.Rl();case 17:return e.Ul();case 21:return mi(e),yi(),yi(),nA;case 10:switch(e.a){case 65:return e.yl();case 90:return e.Dl();case 122:return e.Kl();case 98:return e.El();case 66:return e.zl();case 60:return e.Jl();case 62:return e.Hl()}}switch(o=Syn(e),t=e.c,t){case 3:return e.Zl(o);case 4:return e.Xl(o);case 5:return e.Yl(o);case 0:if(e.a==123&&e.d=48&&t<=57){for(r=t-48;s=48&&t<=57;)if(r=r*10+t-48,r<0)throw J(new $r(Ur((jr(),d8e))))}else throw J(new $r(Ur((jr(),hdt))));if(n=r,t==44){if(s>=e.j)throw J(new $r(Ur((jr(),ddt))));if((t=Ma(e.i,s++))>=48&&t<=57){for(n=t-48;s=48&&t<=57;)if(n=n*10+t-48,n<0)throw J(new $r(Ur((jr(),d8e))));if(r>n)throw J(new $r(Ur((jr(),gdt))))}else n=-1}if(t!=125)throw J(new $r(Ur((jr(),fdt))));e.sl(s)?(o=(yi(),yi(),new $m(9,o)),e.d=s+1):(o=(yi(),yi(),new $m(3,o)),e.d=s),o.dm(r),o.cm(n),mi(e)}}return o}function Glt(e,t,n,r,s){var o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt,bt,zt,Ut,In,Rn;for(W=new su(t.b),Ne=new su(t.b),P=new su(t.b),zt=new su(t.b),X=new su(t.b),bt=ii(t,0);bt.b!=bt.d.c;)for(Ve=u(ri(bt),11),d=new C(Ve.g);d.a0,le=Ve.g.c.length>0,x&&le?P.c[P.c.length]=Ve:x?W.c[W.c.length]=Ve:le&&(Ne.c[Ne.c.length]=Ve);for(q=new C(W);q.a1)for(q=new _6((!e.a&&(e.a=new at(os,e,6,6)),e.a));q.e!=q.i.gc();)J_(q);for(h=u(Te((!e.a&&(e.a=new at(os,e,6,6)),e.a),0),202),X=ki,ki>Ve+Ne?X=Ve+Ne:kint+W?le=nt+W:WsVe-Ne&&Xnt-W&&leki+dr?zt=ki+dr:VeWs+bt?Ut=Ws+bt:ntki-dr&&ztWs-bt&&Utn&&(P=n-1),z=pN+vl(t,24)*NI*L-L/2,z<0?z=1:z>r&&(z=r-1),s=(pv(),v=new pp,v),z$(s,P),G$(s,z),Br((!h.a&&(h.a=new Bs(ef,h,5)),h.a),s)}function pt(){pt=pe,Xle=(bi(),c3t),QTe=u3t,SO=zSe,Mf=l3t,Ok=GSe,Sw=h3t,Ry=qSe,bE=VSe,vE=USe,Qle=RV,Aw=jb,Zle=f3t,bS=YSe,eV=Fk,CO=(f6e(),svt),V4=avt,Nb=ovt,U4=cvt,Vvt=new fo(BV,ct(0)),pE=nvt,XTe=rvt,Ik=ivt,s_e=Mvt,ZTe=hvt,JTe=gvt,ehe=kvt,e_e=vvt,t_e=mvt,tV=Nvt,the=Dvt,r_e=Cvt,n_e=Tvt,i_e=Avt,_w=Xbt,pS=Qbt,Vle=gbt,ATe=bbt,VTe=new kv(12),qTe=new fo(Fb,VTe),_Te=($0(),_E),K0=new fo(wSe,_Te),Ny=new fo(kl,0),Uvt=new fo(ufe,ct(1)),Hq=new fo(Bk,N7),Ob=PV,bs=BS,gE=t5,Fvt=VO,Bd=Jyt,Iy=Q4,Wvt=new fo(lfe,(Mn(),!0)),Oy=UO,Db=nfe,Ib=Rb,Jq=p2,Yle=NV,TTe=(wo(),f0),Zl=new fo(Mw,TTe),Tw=J4,Qq=SSe,Py=Hy,qvt=cfe,KTe=$Se,WTe=(n4(),ZO),new fo(PSe,WTe),Hvt=ife,zvt=sfe,Gvt=afe,$vt=rfe,Jle=lvt,jTe=Fbt,Wle=Rbt,vS=uvt,vu=Mbt,Dy=abt,dS=sbt,My=U2t,kTe=W2t,Hle=Q2t,_O=K2t,zle=rbt,$Te=jbt,HTe=$bt,NTe=Tbt,Zq=evt,Kle=Gbt,Ule=mbt,GTe=Kbt,STe=fbt,qle=dbt,$le=IV,zTe=Hbt,Gq=j2t,wTe=F2t,zq=R2t,DTe=xbt,MTe=kbt,ITe=Ebt,fE=e5,Fo=Z4,Hg=ySe,Rd=tfe,Gle=efe,xTe=J2t,zg=ofe,fS=n3t,Kq=r3t,Cw=RSe,UTe=i3t,dE=s3t,BTe=Ibt,RTe=Nbt,By=Rk,Fle=B2t,FTe=Bbt,Wq=ubt,Uq=cbt,Xq=WO,PTe=Sbt,gS=Vbt,AO=WSe,ETe=obt,YTe=tvt,CTe=lbt,jvt=Lbt,Rvt=tbt,OTe=TSe,Yq=Dbt,Vq=nbt,h2=V2t,yTe=G2t,qq=H2t,mTe=z2t,jle=q2t,Dk=$2t,LTe=ybt}function Lae(e,t){pae();var n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt,bt,zt,Ut,In,Rn,dr,ki;if(zt=e.e,q=e.d,s=e.a,zt==0)switch(t){case 0:return"0";case 1:return L7;case 2:return"0.00";case 3:return"0.000";case 4:return"0.0000";case 5:return"0.00000";case 6:return"0.000000";default:return nt=new Tp,t<0?nt.a+="0E+":nt.a+="0E",nt.a+=-t,nt.a}if(Ee=q*10+1+7,Ne=Me(Sh,Td,25,Ee+1,15,1),n=Ee,q==1)if(d=s[0],d<0){ki=qs(d,yo);do W=ki,ki=eI(ki,10),Ne[--n]=48+Or(Wp(W,ja(ki,10)))&Ss;while(Mc(ki,0)!=0)}else{ki=d;do W=ki,ki=ki/10|0,Ne[--n]=48+(W-ki*10)&Ss;while(ki!=0)}else{In=Me(Lr,Jr,25,q,15,1),dr=q,Hc(s,0,In,0,dr);e:for(;;){for(bt=0,x=dr-1;x>=0;x--)Rn=Ua(A0(bt,32),qs(In[x],yo)),le=Ghn(Rn),In[x]=Or(le),bt=Or(Np(le,32));Ce=Or(bt),X=n;do Ne[--n]=48+Ce%10&Ss;while((Ce=Ce/10|0)!=0&&n!=0);for(r=9-X+n,v=0;v0;v++)Ne[--n]=48;for(L=dr-1;In[L]==0;L--)if(L==0)break e;dr=L+1}for(;Ne[n]==48;)++n}if(z=zt<0,h=Ee-n-t-1,t==0)return z&&(Ne[--n]=45),jh(Ne,n,Ee-n);if(t>0&&h>=-6){if(h>=0){for(_=n+h,P=Ee-1;P>=_;P--)Ne[P+1]=Ne[P];return Ne[++_]=46,z&&(Ne[--n]=45),jh(Ne,n,Ee-n+1)}for(L=2;L<-h+1;L++)Ne[--n]=48;return Ne[--n]=46,Ne[--n]=48,z&&(Ne[--n]=45),jh(Ne,n,Ee-n)}return Ut=n+1,o=Ee,Ve=new xm,z&&(Ve.a+="-"),o-Ut>=1?(Bp(Ve,Ne[n]),Ve.a+=".",Ve.a+=jh(Ne,n+1,Ee-n-1)):Ve.a+=jh(Ne,n,Ee-n),Ve.a+="E",h>0&&(Ve.a+="+"),Ve.a+=""+h,Ve.a}function Ult(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt;switch(e.c=t,e.g=new Mr,n=(Tm(),new ym(e.c)),r=new nr(n),Uye(r),Ee=Hr(Ft(e.c,(nI(),HCe))),v=u(Ft(e.c,Vhe),316),Ve=u(Ft(e.c,Uhe),429),h=u(Ft(e.c,FCe),482),Ne=u(Ft(e.c,qhe),430),e.j=Ue(ft(Ft(e.c,Eyt))),d=e.a,v.g){case 0:d=e.a;break;case 1:d=e.b;break;case 2:d=e.i;break;case 3:d=e.e;break;case 4:d=e.f;break;default:throw J(new Ln(lG+(v.f!=null?v.f:""+v.g)))}if(e.d=new gXe(d,Ve,h),Ye(e.d,(H8(),JC),Mt(Ft(e.c,kyt))),e.d.c=It(Mt(Ft(e.c,jCe))),Jj(e.c).i==0)return e.d;for(L=new rr(Jj(e.c));L.e!=L.i.gc();){for(_=u(pr(L),33),z=_.g/2,P=_.f/2,nt=new Pt(_.i+z,_.j+P);Il(e.g,nt);)Lm(nt,(b.Math.random()-.5)*Sd,(b.Math.random()-.5)*Sd);W=u(Ft(_,(bi(),WO)),142),X=new DXe(nt,new fh(nt.a-z-e.j/2-W.b,nt.b-P-e.j/2-W.d,_.g+e.j+(W.b+W.c),_.f+e.j+(W.d+W.a))),it(e.d.i,X),Si(e.g,nt,new xa(X,_))}switch(Ne.g){case 0:if(Ee==null)e.d.d=u(St(e.d.i,0),65);else for(Ce=new C(e.d.i);Ce.a1&&ks(_,le,_.c.b,_.c),F$(s)));le=Ce}return _}function jyn(e,t,n){var r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt,bt,zt,Ut,In,Rn,dr,ki,Ws,rh,af,ed;for(kr(n,"Greedy cycle removal",1),Ee=t.a,ed=Ee.c.length,e.a=Me(Lr,Jr,25,ed,15,1),e.c=Me(Lr,Jr,25,ed,15,1),e.b=Me(Lr,Jr,25,ed,15,1),x=0,le=new C(Ee);le.a0?dr+1:1);for(h=new C(nt.g);h.a0?dr+1:1)}e.c[x]==0?ci(e.e,W):e.a[x]==0&&ci(e.f,W),++x}for(q=-1,z=1,L=new st,e.d=u(K(t,(et(),Lk)),230);ed>0;){for(;e.e.b!=0;)Ws=u(mne(e.e),10),e.b[Ws.p]=q--,I5e(e,Ws),--ed;for(;e.f.b!=0;)rh=u(mne(e.f),10),e.b[rh.p]=z++,I5e(e,rh),--ed;if(ed>0){for(P=$a,Ce=new C(Ee);Ce.a=P&&(Ne>P&&(L.c=Me(Yn,yt,1,0,5,1),P=Ne),L.c[L.c.length]=W));_=e.Zf(L),e.b[_.p]=z++,I5e(e,_),--ed}}for(ki=Ee.c.length+1,x=0;xe.b[af]&&(iw(r,!0),Ye(t,yO,(Mn(),!0)));e.a=null,e.c=null,e.b=null,Rh(e.f),Rh(e.e),ur(n)}function Klt(e,t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le;for(r=new st,d=new st,X=t/2,z=e.gc(),s=u(e.Xb(0),8),le=u(e.Xb(1),8),q=Gse(s.a,s.b,le.a,le.b,X),it(r,(xn(0,q.c.length),u(q.c[0],8))),it(d,(xn(1,q.c.length),u(q.c[1],8))),x=2;x=0;v--)ci(n,(xn(v,h.c.length),u(h.c[v],8)));return n}function $yn(e){var t,n,r,s,o,h,d,v,x,_,L,P,z;if(h=!0,L=null,r=null,s=null,t=!1,z=e4t,x=null,o=null,d=0,v=Yie(e,d,OAe,NAe),v=0&&an(e.substr(d,2),"//")?(d+=2,v=Yie(e,d,KS,YS),r=e.substr(d,v-d),d=v):L!=null&&(d==e.length||(zr(d,e.length),e.charCodeAt(d)!=47))&&(h=!1,v=lbe(e,Nu(35),d),v==-1&&(v=e.length),r=e.substr(d,v-d),d=v);if(!n&&d0&&Ma(_,_.length-1)==58&&(s=_,d=v)),d=e.j){e.a=-1,e.c=1;return}if(t=Ma(e.i,e.d++),e.a=t,e.b==1){switch(t){case 92:if(r=10,e.d>=e.j)throw J(new $r(Ur((jr(),vG))));e.a=Ma(e.i,e.d++);break;case 45:(e.e&512)==512&&e.d=e.j||Ma(e.i,e.d)!=63)break;if(++e.d>=e.j)throw J(new $r(Ur((jr(),Wce))));switch(t=Ma(e.i,e.d++),t){case 58:r=13;break;case 61:r=14;break;case 33:r=15;break;case 91:r=19;break;case 62:r=18;break;case 60:if(e.d>=e.j)throw J(new $r(Ur((jr(),Wce))));if(t=Ma(e.i,e.d++),t==61)r=16;else if(t==33)r=17;else throw J(new $r(Ur((jr(),W1t))));break;case 35:for(;e.d=e.j)throw J(new $r(Ur((jr(),vG))));e.a=Ma(e.i,e.d++);break;default:r=0}e.c=r}function zyn(e){var t,n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt,bt,zt,Ut,In,Rn,dr;if(bt=u(K(e,(pt(),bs)),98),bt!=(wa(),X1)&&bt!=w2){for(q=e.b,z=q.c.length,_=new su((ql(z+2,Nae),R$(Ua(Ua(5,z+2),(z+2)/10|0)))),W=new su((ql(z+2,Nae),R$(Ua(Ua(5,z+2),(z+2)/10|0)))),it(_,new Mr),it(_,new Mr),it(W,new st),it(W,new st),nt=new st,t=0;t=Ve||!ucn(le,r))&&(r=HXe(t,_)),No(le,r),o=new cr(fr(Xo(le).a.Kc(),new V));Vr(o);)s=u(Pr(o),17),!e.a[s.p]&&(W=s.c.i,--e.e[W.p],e.e[W.p]==0&&S8(l7(z,W)));for(x=_.c.length-1;x>=0;--x)it(t.b,(xn(x,_.c.length),u(_.c[x],29)));t.a.c=Me(Yn,yt,1,0,5,1),ur(n)}function Ylt(e){var t,n,r,s,o,h,d,v,x;for(e.b=1,mi(e),t=null,e.c==0&&e.a==94?(mi(e),t=(yi(),yi(),new Hl(4)),Yc(t,0,q7),d=new Hl(4)):d=(yi(),yi(),new Hl(4)),s=!0;(x=e.c)!=1;){if(x==0&&e.a==93&&!s){t&&(bC(t,d),d=t);break}if(n=e.a,r=!1,x==10)switch(n){case 100:case 68:case 119:case 87:case 115:case 83:ly(d,m7(n)),r=!0;break;case 105:case 73:case 99:case 67:n=(ly(d,m7(n)),-1),n<0&&(r=!0);break;case 112:case 80:if(v=$4e(e,n),!v)throw J(new $r(Ur((jr(),Kce))));ly(d,v),r=!0;break;default:n=y5e(e)}else if(x==24&&!s){if(t&&(bC(t,d),d=t),o=Ylt(e),bC(d,o),e.c!=0||e.a!=93)throw J(new $r(Ur((jr(),rdt))));break}if(mi(e),!r){if(x==0){if(n==91)throw J(new $r(Ur((jr(),h8e))));if(n==93)throw J(new $r(Ur((jr(),f8e))));if(n==45&&!s&&e.a!=93)throw J(new $r(Ur((jr(),Yce))))}if(e.c!=0||e.a!=45||n==45&&s)Yc(d,n,n);else{if(mi(e),(x=e.c)==1)throw J(new $r(Ur((jr(),wG))));if(x==0&&e.a==93)Yc(d,n,n),Yc(d,45,45);else{if(x==0&&e.a==93||x==24)throw J(new $r(Ur((jr(),Yce))));if(h=e.a,x==0){if(h==91)throw J(new $r(Ur((jr(),h8e))));if(h==93)throw J(new $r(Ur((jr(),f8e))));if(h==45)throw J(new $r(Ur((jr(),Yce))))}else x==10&&(h=y5e(e));if(mi(e),n>h)throw J(new $r(Ur((jr(),adt))));Yc(d,n,h)}}}s=!1}if(e.c==1)throw J(new $r(Ur((jr(),wG))));return l4(d),gC(d),e.b=0,mi(e),d}function qyn(e){Rr(e.c,Zr,ie(re(mt,1),Qe,2,6,[Ha,"http://www.w3.org/2001/XMLSchema#decimal"])),Rr(e.d,Zr,ie(re(mt,1),Qe,2,6,[Ha,"http://www.w3.org/2001/XMLSchema#integer"])),Rr(e.e,Zr,ie(re(mt,1),Qe,2,6,[Ha,"http://www.w3.org/2001/XMLSchema#boolean"])),Rr(e.f,Zr,ie(re(mt,1),Qe,2,6,[Ha,"EBoolean",gi,"EBoolean:Object"])),Rr(e.i,Zr,ie(re(mt,1),Qe,2,6,[Ha,"http://www.w3.org/2001/XMLSchema#byte"])),Rr(e.g,Zr,ie(re(mt,1),Qe,2,6,[Ha,"http://www.w3.org/2001/XMLSchema#hexBinary"])),Rr(e.j,Zr,ie(re(mt,1),Qe,2,6,[Ha,"EByte",gi,"EByte:Object"])),Rr(e.n,Zr,ie(re(mt,1),Qe,2,6,[Ha,"EChar",gi,"EChar:Object"])),Rr(e.t,Zr,ie(re(mt,1),Qe,2,6,[Ha,"http://www.w3.org/2001/XMLSchema#double"])),Rr(e.u,Zr,ie(re(mt,1),Qe,2,6,[Ha,"EDouble",gi,"EDouble:Object"])),Rr(e.F,Zr,ie(re(mt,1),Qe,2,6,[Ha,"http://www.w3.org/2001/XMLSchema#float"])),Rr(e.G,Zr,ie(re(mt,1),Qe,2,6,[Ha,"EFloat",gi,"EFloat:Object"])),Rr(e.I,Zr,ie(re(mt,1),Qe,2,6,[Ha,"http://www.w3.org/2001/XMLSchema#int"])),Rr(e.J,Zr,ie(re(mt,1),Qe,2,6,[Ha,"EInt",gi,"EInt:Object"])),Rr(e.N,Zr,ie(re(mt,1),Qe,2,6,[Ha,"http://www.w3.org/2001/XMLSchema#long"])),Rr(e.O,Zr,ie(re(mt,1),Qe,2,6,[Ha,"ELong",gi,"ELong:Object"])),Rr(e.Z,Zr,ie(re(mt,1),Qe,2,6,[Ha,"http://www.w3.org/2001/XMLSchema#short"])),Rr(e.$,Zr,ie(re(mt,1),Qe,2,6,[Ha,"EShort",gi,"EShort:Object"])),Rr(e._,Zr,ie(re(mt,1),Qe,2,6,[Ha,"http://www.w3.org/2001/XMLSchema#string"]))}function Vyn(e){var t,n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt,bt,zt,Ut,In,Rn,dr;if(e.c.length==1)return xn(0,e.c.length),u(e.c[0],135);if(e.c.length<=0)return new E$;for(v=new C(e);v.aL&&(Rn=0,dr+=_+bt,_=0),tgn(Ve,h,Rn,dr),t=b.Math.max(t,Rn+nt.a),_=b.Math.max(_,nt.b),Rn+=nt.a+bt;for(Ne=new Mr,n=new Mr,Ut=new C(e);Ut.aqse(o))&&(L=o);for(!L&&(L=(xn(0,X.c.length),u(X.c[0],180))),W=new C(t.b);W.a=-1900?1:0,n>=4?Yr(e,ie(re(mt,1),Qe,2,6,[fht,dht])[d]):Yr(e,ie(re(mt,1),Qe,2,6,["BC","AD"])[d]);break;case 121:jcn(e,n,r);break;case 77:G2n(e,n,r);break;case 107:v=s.q.getHours(),v==0?e0(e,24,n):e0(e,v,n);break;case 83:lgn(e,n,s);break;case 69:_=r.q.getDay(),n==5?Yr(e,ie(re(mt,1),Qe,2,6,["S","M","T","W","T","F","S"])[_]):n==4?Yr(e,ie(re(mt,1),Qe,2,6,[Kae,Yae,Xae,Qae,Zae,Jae,eoe])[_]):Yr(e,ie(re(mt,1),Qe,2,6,["Sun","Mon","Tue","Wed","Thu","Fri","Sat"])[_]);break;case 97:s.q.getHours()>=12&&s.q.getHours()<24?Yr(e,ie(re(mt,1),Qe,2,6,["AM","PM"])[1]):Yr(e,ie(re(mt,1),Qe,2,6,["AM","PM"])[0]);break;case 104:L=s.q.getHours()%12,L==0?e0(e,12,n):e0(e,L,n);break;case 75:P=s.q.getHours()%12,e0(e,P,n);break;case 72:z=s.q.getHours(),e0(e,z,n);break;case 99:q=r.q.getDay(),n==5?Yr(e,ie(re(mt,1),Qe,2,6,["S","M","T","W","T","F","S"])[q]):n==4?Yr(e,ie(re(mt,1),Qe,2,6,[Kae,Yae,Xae,Qae,Zae,Jae,eoe])[q]):n==3?Yr(e,ie(re(mt,1),Qe,2,6,["Sun","Mon","Tue","Wed","Thu","Fri","Sat"])[q]):e0(e,q,1);break;case 76:W=r.q.getMonth(),n==5?Yr(e,ie(re(mt,1),Qe,2,6,["J","F","M","A","M","J","J","A","S","O","N","D"])[W]):n==4?Yr(e,ie(re(mt,1),Qe,2,6,[Rae,Fae,jae,$ae,ak,Hae,zae,Gae,qae,Vae,Uae,Wae])[W]):n==3?Yr(e,ie(re(mt,1),Qe,2,6,["Jan","Feb","Mar","Apr",ak,"Jun","Jul","Aug","Sep","Oct","Nov","Dec"])[W]):e0(e,W+1,n);break;case 81:X=r.q.getMonth()/3|0,n<4?Yr(e,ie(re(mt,1),Qe,2,6,["Q1","Q2","Q3","Q4"])[X]):Yr(e,ie(re(mt,1),Qe,2,6,["1st quarter","2nd quarter","3rd quarter","4th quarter"])[X]);break;case 100:le=r.q.getDate(),e0(e,le,n);break;case 109:x=s.q.getMinutes(),e0(e,x,n);break;case 115:h=s.q.getSeconds(),e0(e,h,n);break;case 122:n<4?Yr(e,o.c[0]):Yr(e,o.c[1]);break;case 118:Yr(e,o.b);break;case 90:n<3?Yr(e,J1n(o)):n==3?Yr(e,ndn(o)):Yr(e,rdn(o.a));break;default:return!1}return!0}function h6e(e,t,n,r){var s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt,bt,zt,Ut,In,Rn,dr,ki;if(Bct(t),v=u(Te((!t.b&&(t.b=new wn(mr,t,4,7)),t.b),0),82),_=u(Te((!t.c&&(t.c=new wn(mr,t,5,8)),t.c),0),82),d=zo(v),x=zo(_),h=(!t.a&&(t.a=new at(os,t,6,6)),t.a).i==0?null:u(Te((!t.a&&(t.a=new at(os,t,6,6)),t.a),0),202),bt=u(er(e.a,d),10),Rn=u(er(e.a,x),10),zt=null,dr=null,we(v,186)&&(nt=u(er(e.a,v),299),we(nt,11)?zt=u(nt,11):we(nt,10)&&(bt=u(nt,10),zt=u(St(bt.j,0),11))),we(_,186)&&(In=u(er(e.a,_),299),we(In,11)?dr=u(In,11):we(In,10)&&(Rn=u(In,10),dr=u(St(Rn.j,0),11))),!bt||!Rn)throw J(new CT("The source or the target of edge "+t+" could not be found. This usually happens when an edge connects a node laid out by ELK Layered to a node in another level of hierarchy laid out by either another instance of ELK Layered or another layout algorithm alltogether. The former can be solved by setting the hierarchyHandling option to INCLUDE_CHILDREN."));for(W=new Iv,Ho(W,t),Ye(W,(et(),Mi),t),Ye(W,(pt(),Fo),null),z=u(K(r,eu),21),bt==Rn&&z.Fc((mo(),cS)),zt||(Ve=(vo(),hu),Ut=null,h&&R3(u(K(bt,bs),98))&&(Ut=new Pt(h.j,h.k),qQe(Ut,nD(t)),yZe(Ut,n),Vm(x,d)&&(Ve=ul,Ni(Ut,bt.n))),zt=Nut(bt,Ut,Ve,r)),dr||(Ve=(vo(),ul),ki=null,h&&R3(u(K(Rn,bs),98))&&(ki=new Pt(h.b,h.c),qQe(ki,nD(t)),yZe(ki,n)),dr=Nut(Rn,ki,Ve,Ya(Rn))),Va(W,zt),ba(W,dr),(zt.e.c.length>1||zt.g.c.length>1||dr.e.c.length>1||dr.g.c.length>1)&&z.Fc((mo(),oS)),P=new rr((!t.n&&(t.n=new at(Jo,t,1,7)),t.n));P.e!=P.i.gc();)if(L=u(pr(P),137),!It(Mt(Ft(L,Ob)))&&L.a)switch(X=Mie(L),it(W.b,X),u(K(X,Rd),272).g){case 1:case 2:z.Fc((mo(),cE));break;case 0:z.Fc((mo(),oE)),Ye(X,Rd,(P1(),EE))}if(o=u(K(r,dS),314),le=u(K(r,Zq),315),s=o==(V6(),vO)||le==(X_(),ohe),h&&(!h.a&&(h.a=new Bs(ef,h,5)),h.a).i!=0&&s){for(Ce=iI(h),q=new Gu,Ne=ii(Ce,0);Ne.b!=Ne.d.c;)Ee=u(ri(Ne),8),ci(q,new Io(Ee));Ye(W,R9e,q)}return W}function Yyn(e){e.gb||(e.gb=!0,e.b=gc(e,0),ls(e.b,18),zi(e.b,19),e.a=gc(e,1),ls(e.a,1),zi(e.a,2),zi(e.a,3),zi(e.a,4),zi(e.a,5),e.o=gc(e,2),ls(e.o,8),ls(e.o,9),zi(e.o,10),zi(e.o,11),zi(e.o,12),zi(e.o,13),zi(e.o,14),zi(e.o,15),zi(e.o,16),zi(e.o,17),zi(e.o,18),zi(e.o,19),zi(e.o,20),zi(e.o,21),zi(e.o,22),zi(e.o,23),Bo(e.o),Bo(e.o),Bo(e.o),Bo(e.o),Bo(e.o),Bo(e.o),Bo(e.o),Bo(e.o),Bo(e.o),Bo(e.o),e.p=gc(e,3),ls(e.p,2),ls(e.p,3),ls(e.p,4),ls(e.p,5),zi(e.p,6),zi(e.p,7),Bo(e.p),Bo(e.p),e.q=gc(e,4),ls(e.q,8),e.v=gc(e,5),zi(e.v,9),Bo(e.v),Bo(e.v),Bo(e.v),e.w=gc(e,6),ls(e.w,2),ls(e.w,3),ls(e.w,4),zi(e.w,5),e.B=gc(e,7),zi(e.B,1),Bo(e.B),Bo(e.B),Bo(e.B),e.Q=gc(e,8),zi(e.Q,0),Bo(e.Q),e.R=gc(e,9),ls(e.R,1),e.S=gc(e,10),Bo(e.S),Bo(e.S),Bo(e.S),Bo(e.S),Bo(e.S),Bo(e.S),Bo(e.S),Bo(e.S),Bo(e.S),Bo(e.S),Bo(e.S),Bo(e.S),Bo(e.S),Bo(e.S),Bo(e.S),e.T=gc(e,11),zi(e.T,10),zi(e.T,11),zi(e.T,12),zi(e.T,13),zi(e.T,14),Bo(e.T),Bo(e.T),e.U=gc(e,12),ls(e.U,2),ls(e.U,3),zi(e.U,4),zi(e.U,5),zi(e.U,6),zi(e.U,7),Bo(e.U),e.V=gc(e,13),zi(e.V,10),e.W=gc(e,14),ls(e.W,18),ls(e.W,19),ls(e.W,20),zi(e.W,21),zi(e.W,22),zi(e.W,23),e.bb=gc(e,15),ls(e.bb,10),ls(e.bb,11),ls(e.bb,12),ls(e.bb,13),ls(e.bb,14),ls(e.bb,15),ls(e.bb,16),zi(e.bb,17),Bo(e.bb),Bo(e.bb),e.eb=gc(e,16),ls(e.eb,2),ls(e.eb,3),ls(e.eb,4),ls(e.eb,5),ls(e.eb,6),ls(e.eb,7),zi(e.eb,8),zi(e.eb,9),e.ab=gc(e,17),ls(e.ab,0),ls(e.ab,1),e.H=gc(e,18),zi(e.H,0),zi(e.H,1),zi(e.H,2),zi(e.H,3),zi(e.H,4),zi(e.H,5),Bo(e.H),e.db=gc(e,19),zi(e.db,2),e.c=di(e,20),e.d=di(e,21),e.e=di(e,22),e.f=di(e,23),e.i=di(e,24),e.g=di(e,25),e.j=di(e,26),e.k=di(e,27),e.n=di(e,28),e.r=di(e,29),e.s=di(e,30),e.t=di(e,31),e.u=di(e,32),e.fb=di(e,33),e.A=di(e,34),e.C=di(e,35),e.D=di(e,36),e.F=di(e,37),e.G=di(e,38),e.I=di(e,39),e.J=di(e,40),e.L=di(e,41),e.M=di(e,42),e.N=di(e,43),e.O=di(e,44),e.P=di(e,45),e.X=di(e,46),e.Y=di(e,47),e.Z=di(e,48),e.$=di(e,49),e._=di(e,50),e.cb=di(e,51),e.K=di(e,52))}function bi(){bi=pe;var e,t;PS=new Zi(n1t),xE=new Zi(r1t),dSe=(t0(),Yhe),Jyt=new dn(Zke,dSe),Bk=new dn(fk,null),e3t=new Zi(Uxe),pSe=(ty(),Ui(Zhe,ie(re(Jhe,1),tt,291,0,[Qhe]))),IV=new dn(rG,pSe),VO=new dn(WI,(Mn(),!1)),bSe=(wo(),f0),Mw=new dn(txe,bSe),mSe=($0(),hfe),wSe=new dn(VI,mSe),xSe=new dn(uG,!1),ESe=(F0(),FV),Q4=new dn(nG,ESe),OSe=new kv(12),Fb=new dn(uw,OSe),OV=new dn(jI,!1),TSe=new dn(fce,!1),KO=new dn(CC,!1),FSe=(wa(),w2),BS=new dn(Doe,FSe),Rk=new Zi(iG),BV=new Zi(FI),ufe=new Zi(Fz),lfe=new Zi(_C),_Se=new Gu,Z4=new dn(lxe,_Se),n3t=new dn(dxe,!1),r3t=new dn(gxe,!1),CSe=new yT,WO=new dn(bxe,CSe),PV=new dn(Xke,!1),o3t=new dn(i1t,1),new dn(s1t,!0),ct(0),new dn(a1t,ct(100)),new dn(o1t,!1),ct(0),new dn(c1t,ct(4e3)),ct(0),new dn(u1t,ct(400)),new dn(l1t,!1),new dn(h1t,!1),new dn(f1t,!0),new dn(d1t,!1),gSe=(EH(),pfe),t3t=new dn(Vxe,gSe),c3t=new dn(Fke,10),u3t=new dn(jke,10),zSe=new dn(_oe,20),l3t=new dn($ke,10),GSe=new dn(Moe,2),h3t=new dn(Hke,10),qSe=new dn(zke,0),RV=new dn(Vke,5),VSe=new dn(Gke,1),USe=new dn(qke,1),jb=new dn(py,20),f3t=new dn(Uke,10),YSe=new dn(Wke,10),Fk=new Zi(Kke),KSe=new bVe,WSe=new dn(vxe,KSe),s3t=new Zi(hce),NSe=!1,i3t=new dn(lce,NSe),ASe=new kv(5),SSe=new dn(nxe,ASe),LSe=(sy(),t=u(Qf(xo),9),new hh(t,u(wf(t,t.length),9),0)),J4=new dn(P7,LSe),BSe=(n4(),v2),PSe=new dn(sxe,BSe),ife=new Zi(axe),sfe=new Zi(oxe),afe=new Zi(cxe),rfe=new Zi(uxe),MSe=(e=u(Qf(qS),9),new hh(e,u(wf(e,e.length),9),0)),Rb=new dn(E4,MSe),ISe=rn((wl(),SE)),p2=new dn(dk,ISe),DSe=new Pt(0,0),e5=new dn(gk,DSe),NV=new dn(uce,!1),vSe=(P1(),EE),tfe=new dn(hxe,vSe),efe=new dn(jz,!1),ct(1),new dn(g1t,null),RSe=new Zi(pxe),ofe=new Zi(fxe),HSe=(ht(),uc),t5=new dn(Qke,HSe),kl=new Zi(Yke),jSe=(ol(),rn(m2)),Hy=new dn(B7,jSe),cfe=new dn(rxe,!1),$Se=new dn(ixe,!0),UO=new dn(Jke,!1),nfe=new dn(exe,!1),ySe=new dn(Coe,1),kSe=(YH(),dfe),new dn(p1t,kSe),a3t=!0}function et(){et=pe;var e,t;Mi=new Zi(K6e),O9e=new Zi("coordinateOrigin"),Ple=new Zi("processors"),I9e=new zs("compoundNode",(Mn(),!1)),kO=new zs("insideConnections",!1),R9e=new Zi("originalBendpoints"),F9e=new Zi("originalDummyNodePosition"),j9e=new Zi("originalLabelEdge"),EO=new Zi("representedLabels"),uS=new Zi("endLabels"),Ck=new Zi("endLabel.origin"),Ak=new zs("labelSide",(Ul(),QO)),H4=new zs("maxEdgeThickness",0),W1=new zs("reversed",!1),Lk=new Zi(Qht),l1=new zs("longEdgeSource",null),Yh=new zs("longEdgeTarget",null),Ay=new zs("longEdgeHasLabelDummies",!1),xO=new zs("longEdgeBeforeLabelDummy",!1),Fq=new zs("edgeConstraint",(sb(),wle)),xw=new Zi("inLayerLayoutUnit"),Lb=new zs("inLayerConstraint",(P0(),mO)),Sk=new zs("inLayerSuccessorConstraint",new st),B9e=new zs("inLayerSuccessorConstraintBetweenNonDummies",!1),cl=new Zi("portDummy"),Rq=new zs("crossingHint",ct(0)),eu=new zs("graphProperties",(t=u(Qf(_le),9),new hh(t,u(wf(t,t.length),9),0))),vc=new zs("externalPortSide",(ht(),uc)),P9e=new zs("externalPortSize",new Fa),Mle=new Zi("externalPortReplacedDummies"),jq=new Zi("externalPortReplacedDummy"),Sy=new zs("externalPortConnections",(e=u(Qf(ao),9),new hh(e,u(wf(e,e.length),9),0))),Ew=new zs(Ght,0),D9e=new Zi("barycenterAssociates"),Mk=new Zi("TopSideComments"),_k=new Zi("BottomSideComments"),Bq=new Zi("CommentConnectionPort"),Ile=new zs("inputCollect",!1),Nle=new zs("outputCollect",!1),yO=new zs("cyclic",!1),N9e=new Zi("crossHierarchyMap"),Rle=new Zi("targetOffset"),new zs("splineLabelSize",new Fa),G4=new Zi("spacings"),$q=new zs("partitionConstraint",!1),yw=new Zi("breakingPoint.info"),z9e=new Zi("splines.survivingEdge"),Mb=new Zi("splines.route.start"),q4=new Zi("splines.edgeChain"),H9e=new Zi("originalPortConstraints"),lE=new Zi("selfLoopHolder"),hE=new Zi("splines.nsPortY"),Nc=new Zi("modelOrder"),Ole=new Zi("longEdgeTargetNode"),kw=new zs(Tft,!1),z4=new zs(Tft,!1),Dle=new Zi("layerConstraints.hiddenNodes"),$9e=new Zi("layerConstraints.opposidePort"),Ble=new Zi("targetNode.modelOrder")}function f6e(){f6e=pe,J9e=(ED(),Lq),obt=new dn(nke,J9e),mbt=new dn(rke,(Mn(),!1)),sTe=(b$(),Lle),Tbt=new dn(Gz,sTe),jbt=new dn(ike,!1),$bt=new dn(ske,!0),B2t=new dn(ake,!1),dTe=(mD(),lhe),tvt=new dn(oke,dTe),ct(1),uvt=new dn(cke,ct(7)),lvt=new dn(uke,!1),ybt=new dn(lke,!1),Z9e=(db(),ble),abt=new dn(Roe,Z9e),cTe=(WH(),rhe),Fbt=new dn(GI,cTe),aTe=(mh(),TO),Mbt=new dn(hke,aTe),ct(-1),Lbt=new dn(fke,ct(-1)),ct(-1),Dbt=new dn(dke,ct(-1)),ct(-1),Ibt=new dn(Foe,ct(4)),ct(-1),Nbt=new dn(joe,ct(2)),oTe=(f4(),aV),Rbt=new dn($oe,oTe),ct(0),Bbt=new dn(Hoe,ct(0)),Sbt=new dn(zoe,ct(Ei)),Q9e=(V6(),Ek),sbt=new dn(MC,Q9e),U2t=new dn(gke,!1),J2t=new dn(Goe,.1),rbt=new dn(qoe,!1),ct(-1),tbt=new dn(pke,ct(-1)),ct(-1),nbt=new dn(bke,ct(-1)),ct(0),W2t=new dn(vke,ct(40)),X9e=(q8(),Sle),Q2t=new dn(Voe,X9e),Y9e=wO,K2t=new dn(qz,Y9e),fTe=(X_(),wS),evt=new dn(T4,fTe),Vbt=new Zi(Vz),uTe=(pD(),Dq),Hbt=new dn(Uoe,uTe),lTe=(tI(),Iq),Gbt=new dn(Woe,lTe),Kbt=new dn(Koe,.3),Xbt=new Zi(Yoe),hTe=(Zm(),sV),Qbt=new dn(Xoe,hTe),nTe=(iH(),fhe),fbt=new dn(wke,nTe),rTe=(uD(),dhe),dbt=new dn(mke,rTe),iTe=(Q8(),kS),gbt=new dn(Uz,iTe),bbt=new dn(Wz,.2),lbt=new dn(Qoe,2),svt=new dn(yke,null),ovt=new dn(kke,10),avt=new dn(xke,10),cvt=new dn(Eke,20),ct(0),nvt=new dn(Tke,ct(0)),ct(0),rvt=new dn(_ke,ct(0)),ct(0),ivt=new dn(Cke,ct(0)),R2t=new dn(Zoe,!1),V9e=(h7(),aS),j2t=new dn(Ske,V9e),q9e=(S$(),gle),F2t=new dn(Ake,q9e),xbt=new dn(Kz,!1),ct(0),kbt=new dn(Joe,ct(16)),ct(0),Ebt=new dn(ece,ct(5)),bTe=(uH(),bhe),Mvt=new dn(W0,bTe),hvt=new dn(Yz,10),gvt=new dn(Xz,1),pTe=(V$(),Aq),kvt=new dn(DC,pTe),vvt=new Zi(tce),gTe=ct(1),ct(0),mvt=new dn(nce,gTe),vTe=(nH(),phe),Nvt=new dn(Qz,vTe),Dvt=new Zi(Zz),Cvt=new dn(Jz,!0),Tvt=new dn(eG,2),Avt=new dn(rce,!0),tTe=(QH(),Mq),ubt=new dn(Lke,tTe),eTe=(ek(),iE),cbt=new dn(Mke,eTe),K9e=(R0(),f2),V2t=new dn(tG,K9e),q2t=new dn(Dke,!1),U9e=(Uv(),N4),$2t=new dn(ice,U9e),W9e=(j_(),ihe),G2t=new dn(Ike,W9e),H2t=new dn(sce,0),z2t=new dn(ace,0),Cbt=vle,_bt=vO,Obt=rV,Pbt=rV,Abt=nhe,ebt=(F0(),Wg),ibt=Ek,Z2t=Ek,Y2t=Ek,X2t=Wg,Ubt=mS,Wbt=wS,zbt=wS,qbt=wS,Ybt=che,Jbt=mS,Zbt=mS,pbt=($0(),jk),vbt=jk,wbt=kS,hbt=YO,fvt=wE,dvt=Fy,pvt=wE,bvt=Fy,xvt=wE,Evt=Fy,wvt=ple,yvt=Aq,Pvt=wE,Bvt=Fy,Ivt=wE,Ovt=Fy,Svt=Fy,_vt=Fy,Lvt=Fy}function po(){po=pe,MEe=new Cs("DIRECTION_PREPROCESSOR",0),SEe=new Cs("COMMENT_PREPROCESSOR",1),tS=new Cs("EDGE_AND_LAYER_CONSTRAINT_EDGE_REVERSER",2),ele=new Cs("INTERACTIVE_EXTERNAL_PORT_POSITIONER",3),YEe=new Cs("PARTITION_PREPROCESSOR",4),uq=new Cs("LABEL_DUMMY_INSERTER",5),mq=new Cs("SELF_LOOP_PREPROCESSOR",6),eE=new Cs("LAYER_CONSTRAINT_PREPROCESSOR",7),WEe=new Cs("PARTITION_MIDPROCESSOR",8),FEe=new Cs("HIGH_DEGREE_NODE_LAYER_PROCESSOR",9),VEe=new Cs("NODE_PROMOTION",10),J7=new Cs("LAYER_CONSTRAINT_POSTPROCESSOR",11),KEe=new Cs("PARTITION_POSTPROCESSOR",12),PEe=new Cs("HIERARCHICAL_PORT_CONSTRAINT_PROCESSOR",13),XEe=new Cs("SEMI_INTERACTIVE_CROSSMIN_PROCESSOR",14),kEe=new Cs("BREAKING_POINT_INSERTER",15),dq=new Cs("LONG_EDGE_SPLITTER",16),tle=new Cs("PORT_SIDE_PROCESSOR",17),oq=new Cs("INVERTED_PORT_PROCESSOR",18),bq=new Cs("PORT_LIST_SORTER",19),ZEe=new Cs("SORT_BY_INPUT_ORDER_OF_MODEL",20),pq=new Cs("NORTH_SOUTH_PORT_PREPROCESSOR",21),xEe=new Cs("BREAKING_POINT_PROCESSOR",22),UEe=new Cs(bft,23),JEe=new Cs(vft,24),vq=new Cs("SELF_LOOP_PORT_RESTORER",25),QEe=new Cs("SINGLE_EDGE_GRAPH_WRAPPER",26),cq=new Cs("IN_LAYER_CONSTRAINT_PROCESSOR",27),IEe=new Cs("END_NODE_PORT_LABEL_MANAGEMENT_PROCESSOR",28),GEe=new Cs("LABEL_AND_NODE_SIZE_PROCESSOR",29),zEe=new Cs("INNERMOST_NODE_MARGIN_CALCULATOR",30),yq=new Cs("SELF_LOOP_ROUTER",31),_Ee=new Cs("COMMENT_NODE_MARGIN_CALCULATOR",32),aq=new Cs("END_LABEL_PREPROCESSOR",33),hq=new Cs("LABEL_DUMMY_SWITCHER",34),TEe=new Cs("CENTER_LABEL_MANAGEMENT_PROCESSOR",35),Z7=new Cs("LABEL_SIDE_SELECTOR",36),$Ee=new Cs("HYPEREDGE_DUMMY_MERGER",37),BEe=new Cs("HIERARCHICAL_PORT_DUMMY_SIZE_PROCESSOR",38),qEe=new Cs("LAYER_SIZE_AND_GRAPH_HEIGHT_CALCULATOR",39),nS=new Cs("HIERARCHICAL_PORT_POSITION_PROCESSOR",40),AEe=new Cs("CONSTRAINTS_POSTPROCESSOR",41),CEe=new Cs("COMMENT_POSTPROCESSOR",42),HEe=new Cs("HYPERNODE_PROCESSOR",43),REe=new Cs("HIERARCHICAL_PORT_ORTHOGONAL_EDGE_ROUTER",44),fq=new Cs("LONG_EDGE_JOINER",45),wq=new Cs("SELF_LOOP_POSTPROCESSOR",46),EEe=new Cs("BREAKING_POINT_REMOVER",47),gq=new Cs("NORTH_SOUTH_PORT_POSTPROCESSOR",48),jEe=new Cs("HORIZONTAL_COMPACTOR",49),lq=new Cs("LABEL_DUMMY_REMOVER",50),OEe=new Cs("FINAL_SPLINE_BENDPOINTS_CALCULATOR",51),DEe=new Cs("END_LABEL_SORTER",52),pO=new Cs("REVERSED_EDGE_RESTORER",53),sq=new Cs("END_LABEL_POSTPROCESSOR",54),NEe=new Cs("HIERARCHICAL_NODE_RESIZER",55),LEe=new Cs("DIRECTION_POSTPROCESSOR",56)}function Xyn(e,t,n){var r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt,bt,zt,Ut,In,Rn,dr,ki,Ws,rh,af,ed,aU,pN,rA,bN,IE,Dfe,Q4t,Ife,Jg,Bw,OE,vN,wN,Vk,Ofe,iA,Z4t,gLe,Rw,sA,Nfe,Uk,aA,Qy,oA,Pfe,J4t;for(gLe=0,ki=t,af=0,pN=ki.length;af0&&(e.a[Jg.p]=gLe++)}for(aA=0,Ws=n,ed=0,rA=Ws.length;ed0;){for(Jg=(Qn(wN.b>0),u(wN.a.Xb(wN.c=--wN.b),11)),vN=0,d=new C(Jg.e);d.a0&&(Jg.j==(ht(),An)?(e.a[Jg.p]=aA,++aA):(e.a[Jg.p]=aA+bN+Dfe,++Dfe))}aA+=Dfe}for(OE=new Mr,q=new C0,dr=t,rh=0,aU=dr.length;rhx.b&&(x.b=Vk)):Jg.i.c==Z4t&&(Vkx.c&&(x.c=Vk));for(L8(W,0,W.length,null),Uk=Me(Lr,Jr,25,W.length,15,1),r=Me(Lr,Jr,25,aA+1,15,1),le=0;le0;)bt%2>0&&(s+=Pfe[bt+1]),bt=(bt-1)/2|0,++Pfe[bt];for(Ut=Me(_wt,yt,362,W.length*2,0,1),Ne=0;Ne'?":an(W1t,e)?"'(?<' or '(? toIndex: ",_6e=", toIndex: ",C6e="Index: ",S6e=", Size: ",M7="org.eclipse.elk.alg.common",ji={62:1},_ht="org.eclipse.elk.alg.common.compaction",Cht="Scanline/EventHandler",o0="org.eclipse.elk.alg.common.compaction.oned",Sht="CNode belongs to another CGroup.",Aht="ISpacingsHandler/1",doe="The ",goe=" instance has been finished already.",Lht="The direction ",Mht=" is not supported by the CGraph instance.",Dht="OneDimensionalCompactor",Iht="OneDimensionalCompactor/lambda$0$Type",Oht="Quadruplet",Nht="ScanlineConstraintCalculator",Pht="ScanlineConstraintCalculator/ConstraintsScanlineHandler",Bht="ScanlineConstraintCalculator/ConstraintsScanlineHandler/lambda$0$Type",Rht="ScanlineConstraintCalculator/Timestamp",Fht="ScanlineConstraintCalculator/lambda$0$Type",_d={169:1,45:1},poe="org.eclipse.elk.alg.common.compaction.options",cc="org.eclipse.elk.core.data",A6e="org.eclipse.elk.polyomino.traversalStrategy",L6e="org.eclipse.elk.polyomino.lowLevelSort",M6e="org.eclipse.elk.polyomino.highLevelSort",D6e="org.eclipse.elk.polyomino.fill",zh={130:1},boe="polyomino",xC="org.eclipse.elk.alg.common.networksimplex",c0={177:1,3:1,4:1},jht="org.eclipse.elk.alg.common.nodespacing",wb="org.eclipse.elk.alg.common.nodespacing.cellsystem",D7="CENTER",$ht={212:1,326:1},I6e={3:1,4:1,5:1,595:1},uk="LEFT",lk="RIGHT",O6e="Vertical alignment cannot be null",N6e="BOTTOM",Iz="org.eclipse.elk.alg.common.nodespacing.internal",EC="UNDEFINED",z1=.01,PI="org.eclipse.elk.alg.common.nodespacing.internal.algorithm",Hht="LabelPlacer/lambda$0$Type",zht="LabelPlacer/lambda$1$Type",Ght="portRatioOrPosition",I7="org.eclipse.elk.alg.common.overlaps",voe="DOWN",Cd="org.eclipse.elk.alg.common.polyomino",Oz="NORTH",woe="EAST",moe="SOUTH",yoe="WEST",Nz="org.eclipse.elk.alg.common.polyomino.structures",P6e="Direction",koe="Grid is only of size ",xoe=". Requested point (",Eoe=") is out of bounds.",Pz=" Given center based coordinates were (",BI="org.eclipse.elk.graph.properties",qht="IPropertyHolder",B6e={3:1,94:1,134:1},hk="org.eclipse.elk.alg.common.spore",Vht="org.eclipse.elk.alg.common.utils",mb={209:1},k4="org.eclipse.elk.core",Uht="Connected Components Compaction",Wht="org.eclipse.elk.alg.disco",Bz="org.eclipse.elk.alg.disco.graph",Toe="org.eclipse.elk.alg.disco.options",R6e="CompactionStrategy",F6e="org.eclipse.elk.disco.componentCompaction.strategy",j6e="org.eclipse.elk.disco.componentCompaction.componentLayoutAlgorithm",$6e="org.eclipse.elk.disco.debug.discoGraph",H6e="org.eclipse.elk.disco.debug.discoPolys",Kht="componentCompaction",yb="org.eclipse.elk.disco",_oe="org.eclipse.elk.spacing.componentComponent",Coe="org.eclipse.elk.edge.thickness",fk="org.eclipse.elk.aspectRatio",uw="org.eclipse.elk.padding",x4="org.eclipse.elk.alg.disco.transform",Soe=1.5707963267948966,O7=17976931348623157e292,gy={3:1,4:1,5:1,192:1},z6e={3:1,6:1,4:1,5:1,106:1,120:1},G6e="org.eclipse.elk.alg.force",q6e="ComponentsProcessor",Yht="ComponentsProcessor/1",RI="org.eclipse.elk.alg.force.graph",Xht="Component Layout",V6e="org.eclipse.elk.alg.force.model",Rz="org.eclipse.elk.force.model",U6e="org.eclipse.elk.force.iterations",W6e="org.eclipse.elk.force.repulsivePower",Aoe="org.eclipse.elk.force.temperature",Sd=.001,Loe="org.eclipse.elk.force.repulsion",TC="org.eclipse.elk.alg.force.options",N7=1.600000023841858,Yl="org.eclipse.elk.force",FI="org.eclipse.elk.priority",py="org.eclipse.elk.spacing.nodeNode",Moe="org.eclipse.elk.spacing.edgeLabel",Fz="org.eclipse.elk.randomSeed",_C="org.eclipse.elk.separateConnectedComponents",jI="org.eclipse.elk.interactive",Doe="org.eclipse.elk.portConstraints",jz="org.eclipse.elk.edgeLabels.inline",CC="org.eclipse.elk.omitNodeMicroLayout",dk="org.eclipse.elk.nodeSize.options",E4="org.eclipse.elk.nodeSize.constraints",P7="org.eclipse.elk.nodeLabels.placement",B7="org.eclipse.elk.portLabels.placement",K6e="origin",Qht="random",Zht="boundingBox.upLeft",Jht="boundingBox.lowRight",Y6e="org.eclipse.elk.stress.fixed",X6e="org.eclipse.elk.stress.desiredEdgeLength",Q6e="org.eclipse.elk.stress.dimension",Z6e="org.eclipse.elk.stress.epsilon",J6e="org.eclipse.elk.stress.iterationLimit",t2="org.eclipse.elk.stress",eft="ELK Stress",gk="org.eclipse.elk.nodeSize.minimum",$z="org.eclipse.elk.alg.force.stress",tft="Layered layout",pk="org.eclipse.elk.alg.layered",$I="org.eclipse.elk.alg.layered.compaction.components",SC="org.eclipse.elk.alg.layered.compaction.oned",Hz="org.eclipse.elk.alg.layered.compaction.oned.algs",kb="org.eclipse.elk.alg.layered.compaction.recthull",Ad="org.eclipse.elk.alg.layered.components",U0="NONE",Dc={3:1,6:1,4:1,9:1,5:1,122:1},nft={3:1,6:1,4:1,5:1,141:1,106:1,120:1},zz="org.eclipse.elk.alg.layered.compound",ps={51:1},uu="org.eclipse.elk.alg.layered.graph",Ioe=" -> ",rft="Not supported by LGraph",eke="Port side is undefined",Ooe={3:1,6:1,4:1,5:1,474:1,141:1,106:1,120:1},Bg={3:1,6:1,4:1,5:1,141:1,193:1,203:1,106:1,120:1},ift={3:1,6:1,4:1,5:1,141:1,1943:1,203:1,106:1,120:1},sft=`([{"' \r +`,aft=`)]}"' \r +`,oft="The given string contains parts that cannot be parsed as numbers.",HI="org.eclipse.elk.core.math",cft={3:1,4:1,142:1,207:1,414:1},uft={3:1,4:1,116:1,207:1,414:1},qn="org.eclipse.elk.layered",Rg="org.eclipse.elk.alg.layered.graph.transform",lft="ElkGraphImporter",hft="ElkGraphImporter/lambda$0$Type",fft="ElkGraphImporter/lambda$1$Type",dft="ElkGraphImporter/lambda$2$Type",gft="ElkGraphImporter/lambda$4$Type",pft="Node margin calculation",Pn="org.eclipse.elk.alg.layered.intermediate",bft="ONE_SIDED_GREEDY_SWITCH",vft="TWO_SIDED_GREEDY_SWITCH",Noe="No implementation is available for the layout processor ",tke="IntermediateProcessorStrategy",Poe="Node '",wft="FIRST_SEPARATE",mft="LAST_SEPARATE",yft="Odd port side processing",Is="org.eclipse.elk.alg.layered.intermediate.compaction",AC="org.eclipse.elk.alg.layered.intermediate.greedyswitch",u0="org.eclipse.elk.alg.layered.p3order.counting",zI={225:1},bk="org.eclipse.elk.alg.layered.intermediate.loops",Xl="org.eclipse.elk.alg.layered.intermediate.loops.ordering",n2="org.eclipse.elk.alg.layered.intermediate.loops.routing",LC="org.eclipse.elk.alg.layered.intermediate.preserveorder",Ld="org.eclipse.elk.alg.layered.intermediate.wrapping",Ic="org.eclipse.elk.alg.layered.options",Boe="INTERACTIVE",kft="DEPTH_FIRST",xft="EDGE_LENGTH",Eft="SELF_LOOPS",Tft="firstTryWithInitialOrder",nke="org.eclipse.elk.layered.directionCongruency",rke="org.eclipse.elk.layered.feedbackEdges",Gz="org.eclipse.elk.layered.interactiveReferencePoint",ike="org.eclipse.elk.layered.mergeEdges",ske="org.eclipse.elk.layered.mergeHierarchyEdges",ake="org.eclipse.elk.layered.allowNonFlowPortsToSwitchSides",oke="org.eclipse.elk.layered.portSortingStrategy",cke="org.eclipse.elk.layered.thoroughness",uke="org.eclipse.elk.layered.unnecessaryBendpoints",lke="org.eclipse.elk.layered.generatePositionAndLayerIds",Roe="org.eclipse.elk.layered.cycleBreaking.strategy",GI="org.eclipse.elk.layered.layering.strategy",hke="org.eclipse.elk.layered.layering.layerConstraint",fke="org.eclipse.elk.layered.layering.layerChoiceConstraint",dke="org.eclipse.elk.layered.layering.layerId",Foe="org.eclipse.elk.layered.layering.minWidth.upperBoundOnWidth",joe="org.eclipse.elk.layered.layering.minWidth.upperLayerEstimationScalingFactor",$oe="org.eclipse.elk.layered.layering.nodePromotion.strategy",Hoe="org.eclipse.elk.layered.layering.nodePromotion.maxIterations",zoe="org.eclipse.elk.layered.layering.coffmanGraham.layerBound",MC="org.eclipse.elk.layered.crossingMinimization.strategy",gke="org.eclipse.elk.layered.crossingMinimization.forceNodeModelOrder",Goe="org.eclipse.elk.layered.crossingMinimization.hierarchicalSweepiness",qoe="org.eclipse.elk.layered.crossingMinimization.semiInteractive",pke="org.eclipse.elk.layered.crossingMinimization.positionChoiceConstraint",bke="org.eclipse.elk.layered.crossingMinimization.positionId",vke="org.eclipse.elk.layered.crossingMinimization.greedySwitch.activationThreshold",Voe="org.eclipse.elk.layered.crossingMinimization.greedySwitch.type",qz="org.eclipse.elk.layered.crossingMinimization.greedySwitchHierarchical.type",T4="org.eclipse.elk.layered.nodePlacement.strategy",Vz="org.eclipse.elk.layered.nodePlacement.favorStraightEdges",Uoe="org.eclipse.elk.layered.nodePlacement.bk.edgeStraightening",Woe="org.eclipse.elk.layered.nodePlacement.bk.fixedAlignment",Koe="org.eclipse.elk.layered.nodePlacement.linearSegments.deflectionDampening",Yoe="org.eclipse.elk.layered.nodePlacement.networkSimplex.nodeFlexibility",Xoe="org.eclipse.elk.layered.nodePlacement.networkSimplex.nodeFlexibility.default",wke="org.eclipse.elk.layered.edgeRouting.selfLoopDistribution",mke="org.eclipse.elk.layered.edgeRouting.selfLoopOrdering",Uz="org.eclipse.elk.layered.edgeRouting.splines.mode",Wz="org.eclipse.elk.layered.edgeRouting.splines.sloppy.layerSpacingFactor",Qoe="org.eclipse.elk.layered.edgeRouting.polyline.slopedEdgeZoneWidth",yke="org.eclipse.elk.layered.spacing.baseValue",kke="org.eclipse.elk.layered.spacing.edgeNodeBetweenLayers",xke="org.eclipse.elk.layered.spacing.edgeEdgeBetweenLayers",Eke="org.eclipse.elk.layered.spacing.nodeNodeBetweenLayers",Tke="org.eclipse.elk.layered.priority.direction",_ke="org.eclipse.elk.layered.priority.shortness",Cke="org.eclipse.elk.layered.priority.straightness",Zoe="org.eclipse.elk.layered.compaction.connectedComponents",Ske="org.eclipse.elk.layered.compaction.postCompaction.strategy",Ake="org.eclipse.elk.layered.compaction.postCompaction.constraints",Kz="org.eclipse.elk.layered.highDegreeNodes.treatment",Joe="org.eclipse.elk.layered.highDegreeNodes.threshold",ece="org.eclipse.elk.layered.highDegreeNodes.treeHeight",W0="org.eclipse.elk.layered.wrapping.strategy",Yz="org.eclipse.elk.layered.wrapping.additionalEdgeSpacing",Xz="org.eclipse.elk.layered.wrapping.correctionFactor",DC="org.eclipse.elk.layered.wrapping.cutting.strategy",tce="org.eclipse.elk.layered.wrapping.cutting.cuts",nce="org.eclipse.elk.layered.wrapping.cutting.msd.freedom",Qz="org.eclipse.elk.layered.wrapping.validify.strategy",Zz="org.eclipse.elk.layered.wrapping.validify.forbiddenIndices",Jz="org.eclipse.elk.layered.wrapping.multiEdge.improveCuts",eG="org.eclipse.elk.layered.wrapping.multiEdge.distancePenalty",rce="org.eclipse.elk.layered.wrapping.multiEdge.improveWrappedEdges",Lke="org.eclipse.elk.layered.edgeLabels.sideSelection",Mke="org.eclipse.elk.layered.edgeLabels.centerLabelPlacementStrategy",tG="org.eclipse.elk.layered.considerModelOrder.strategy",Dke="org.eclipse.elk.layered.considerModelOrder.noModelOrder",ice="org.eclipse.elk.layered.considerModelOrder.components",Ike="org.eclipse.elk.layered.considerModelOrder.longEdgeStrategy",sce="org.eclipse.elk.layered.considerModelOrder.crossingCounterNodeInfluence",ace="org.eclipse.elk.layered.considerModelOrder.crossingCounterPortInfluence",oce="layering",_ft="layering.minWidth",Cft="layering.nodePromotion",qI="crossingMinimization",nG="org.eclipse.elk.hierarchyHandling",Sft="crossingMinimization.greedySwitch",Aft="nodePlacement",Lft="nodePlacement.bk",Mft="edgeRouting",VI="org.eclipse.elk.edgeRouting",G1="spacing",Oke="priority",Nke="compaction",Dft="compaction.postCompaction",Ift="Specifies whether and how post-process compaction is applied.",Pke="highDegreeNodes",Bke="wrapping",Oft="wrapping.cutting",Nft="wrapping.validify",Rke="wrapping.multiEdge",cce="edgeLabels",UI="considerModelOrder",Fke="org.eclipse.elk.spacing.commentComment",jke="org.eclipse.elk.spacing.commentNode",$ke="org.eclipse.elk.spacing.edgeEdge",Hke="org.eclipse.elk.spacing.edgeNode",zke="org.eclipse.elk.spacing.labelLabel",Gke="org.eclipse.elk.spacing.labelPortHorizontal",qke="org.eclipse.elk.spacing.labelPortVertical",Vke="org.eclipse.elk.spacing.labelNode",Uke="org.eclipse.elk.spacing.nodeSelfLoop",Wke="org.eclipse.elk.spacing.portPort",Kke="org.eclipse.elk.spacing.individual",Yke="org.eclipse.elk.port.borderOffset",Xke="org.eclipse.elk.noLayout",Qke="org.eclipse.elk.port.side",WI="org.eclipse.elk.debugMode",Zke="org.eclipse.elk.alignment",Jke="org.eclipse.elk.insideSelfLoops.activate",exe="org.eclipse.elk.insideSelfLoops.yo",uce="org.eclipse.elk.nodeSize.fixedGraphSize",txe="org.eclipse.elk.direction",nxe="org.eclipse.elk.nodeLabels.padding",rxe="org.eclipse.elk.portLabels.nextToPortIfPossible",ixe="org.eclipse.elk.portLabels.treatAsGroup",sxe="org.eclipse.elk.portAlignment.default",axe="org.eclipse.elk.portAlignment.north",oxe="org.eclipse.elk.portAlignment.south",cxe="org.eclipse.elk.portAlignment.west",uxe="org.eclipse.elk.portAlignment.east",rG="org.eclipse.elk.contentAlignment",lxe="org.eclipse.elk.junctionPoints",hxe="org.eclipse.elk.edgeLabels.placement",fxe="org.eclipse.elk.port.index",dxe="org.eclipse.elk.commentBox",gxe="org.eclipse.elk.hypernode",pxe="org.eclipse.elk.port.anchor",lce="org.eclipse.elk.partitioning.activate",hce="org.eclipse.elk.partitioning.partition",iG="org.eclipse.elk.position",bxe="org.eclipse.elk.margins",vxe="org.eclipse.elk.spacing.portsSurrounding",fce="org.eclipse.elk.interactiveLayout",Oc="org.eclipse.elk.core.util",wxe={3:1,4:1,5:1,593:1},Pft="NETWORK_SIMPLEX",Qc={123:1,51:1},sG="org.eclipse.elk.alg.layered.p1cycles",by="org.eclipse.elk.alg.layered.p2layers",mxe={402:1,225:1},Bft={832:1,3:1,4:1},Qu="org.eclipse.elk.alg.layered.p3order",ko="org.eclipse.elk.alg.layered.p4nodes",Rft={3:1,4:1,5:1,840:1},Md=1e-5,r2="org.eclipse.elk.alg.layered.p4nodes.bk",dce="org.eclipse.elk.alg.layered.p5edges",o1="org.eclipse.elk.alg.layered.p5edges.orthogonal",gce="org.eclipse.elk.alg.layered.p5edges.orthogonal.direction",pce=1e-6,vy="org.eclipse.elk.alg.layered.p5edges.splines",bce=.09999999999999998,aG=1e-8,Fft=4.71238898038469,jft=3.141592653589793,IC="org.eclipse.elk.alg.mrtree",OC="org.eclipse.elk.alg.mrtree.graph",vk="org.eclipse.elk.alg.mrtree.intermediate",$ft="Set neighbors in level",Hft="DESCENDANTS",yxe="org.eclipse.elk.mrtree.weighting",kxe="org.eclipse.elk.mrtree.searchOrder",oG="org.eclipse.elk.alg.mrtree.options",Fg="org.eclipse.elk.mrtree",zft="org.eclipse.elk.tree",xxe="org.eclipse.elk.alg.radial",_4=6.283185307179586,Exe=5e-324,Gft="org.eclipse.elk.alg.radial.intermediate",vce="org.eclipse.elk.alg.radial.intermediate.compaction",qft={3:1,4:1,5:1,106:1},Txe="org.eclipse.elk.alg.radial.intermediate.optimization",wce="No implementation is available for the layout option ",NC="org.eclipse.elk.alg.radial.options",_xe="org.eclipse.elk.radial.orderId",Cxe="org.eclipse.elk.radial.radius",mce="org.eclipse.elk.radial.compactor",yce="org.eclipse.elk.radial.compactionStepSize",Sxe="org.eclipse.elk.radial.sorter",Axe="org.eclipse.elk.radial.wedgeCriteria",Lxe="org.eclipse.elk.radial.optimizationCriteria",Dd="org.eclipse.elk.radial",Vft="org.eclipse.elk.alg.radial.p1position.wedge",Mxe="org.eclipse.elk.alg.radial.sorting",Uft=5.497787143782138,Wft=3.9269908169872414,Kft=2.356194490192345,Yft="org.eclipse.elk.alg.rectpacking",cG="org.eclipse.elk.alg.rectpacking.firstiteration",kce="org.eclipse.elk.alg.rectpacking.options",Dxe="org.eclipse.elk.rectpacking.optimizationGoal",Ixe="org.eclipse.elk.rectpacking.lastPlaceShift",Oxe="org.eclipse.elk.rectpacking.currentPosition",Nxe="org.eclipse.elk.rectpacking.desiredPosition",Pxe="org.eclipse.elk.rectpacking.onlyFirstIteration",Bxe="org.eclipse.elk.rectpacking.rowCompaction",xce="org.eclipse.elk.rectpacking.expandToAspectRatio",Rxe="org.eclipse.elk.rectpacking.targetWidth",uG="org.eclipse.elk.expandNodes",Gh="org.eclipse.elk.rectpacking",KI="org.eclipse.elk.alg.rectpacking.util",lG="No implementation available for ",wy="org.eclipse.elk.alg.spore",my="org.eclipse.elk.alg.spore.options",lw="org.eclipse.elk.sporeCompaction",Ece="org.eclipse.elk.underlyingLayoutAlgorithm",Fxe="org.eclipse.elk.processingOrder.treeConstruction",jxe="org.eclipse.elk.processingOrder.spanningTreeCostFunction",Tce="org.eclipse.elk.processingOrder.preferredRoot",_ce="org.eclipse.elk.processingOrder.rootSelection",Cce="org.eclipse.elk.structure.structureExtractionStrategy",$xe="org.eclipse.elk.compaction.compactionStrategy",Hxe="org.eclipse.elk.compaction.orthogonal",zxe="org.eclipse.elk.overlapRemoval.maxIterations",Gxe="org.eclipse.elk.overlapRemoval.runScanline",Sce="processingOrder",Xft="overlapRemoval",R7="org.eclipse.elk.sporeOverlap",Qft="org.eclipse.elk.alg.spore.p1structure",Ace="org.eclipse.elk.alg.spore.p2processingorder",Lce="org.eclipse.elk.alg.spore.p3execution",Zft="Invalid index: ",F7="org.eclipse.elk.core.alg",C4={331:1},yy={288:1},Jft="Make sure its type is registered with the ",qxe=" utility class.",j7="true",Mce="false",e1t="Couldn't clone property '",hw=.05,qh="org.eclipse.elk.core.options",t1t=1.2999999523162842,fw="org.eclipse.elk.box",Vxe="org.eclipse.elk.box.packingMode",n1t="org.eclipse.elk.algorithm",r1t="org.eclipse.elk.resolvedAlgorithm",Uxe="org.eclipse.elk.bendPoints",t3n="org.eclipse.elk.labelManager",i1t="org.eclipse.elk.scaleFactor",s1t="org.eclipse.elk.animate",a1t="org.eclipse.elk.animTimeFactor",o1t="org.eclipse.elk.layoutAncestors",c1t="org.eclipse.elk.maxAnimTime",u1t="org.eclipse.elk.minAnimTime",l1t="org.eclipse.elk.progressBar",h1t="org.eclipse.elk.validateGraph",f1t="org.eclipse.elk.validateOptions",d1t="org.eclipse.elk.zoomToFit",n3n="org.eclipse.elk.font.name",g1t="org.eclipse.elk.font.size",p1t="org.eclipse.elk.edge.type",b1t="partitioning",v1t="nodeLabels",hG="portAlignment",Dce="nodeSize",Ice="port",Wxe="portLabels",w1t="insideSelfLoops",PC="org.eclipse.elk.fixed",fG="org.eclipse.elk.random",m1t="port must have a parent node to calculate the port side",y1t="The edge needs to have exactly one edge section. Found: ",BC="org.eclipse.elk.core.util.adapters",kh="org.eclipse.emf.ecore",S4="org.eclipse.elk.graph",k1t="EMapPropertyHolder",x1t="ElkBendPoint",E1t="ElkGraphElement",T1t="ElkConnectableShape",Kxe="ElkEdge",_1t="ElkEdgeSection",C1t="EModelElement",S1t="ENamedElement",Yxe="ElkLabel",Xxe="ElkNode",Qxe="ElkPort",A1t={92:1,90:1},wk="org.eclipse.emf.common.notify.impl",i2="The feature '",RC="' is not a valid changeable feature",L1t="Expecting null",Oce="' is not a valid feature",M1t="The feature ID",D1t=" is not a valid feature ID",_c=32768,I1t={105:1,92:1,90:1,56:1,49:1,97:1},Tn="org.eclipse.emf.ecore.impl",xb="org.eclipse.elk.graph.impl",FC="Recursive containment not allowed for ",$7="The datatype '",dw="' is not a valid classifier",Nce="The value '",A4={190:1,3:1,4:1},Pce="The class '",H7="http://www.eclipse.org/elk/ElkGraph",Sf=1024,Zxe="property",jC="value",Bce="source",O1t="properties",N1t="identifier",Rce="height",Fce="width",jce="parent",$ce="text",Hce="children",P1t="hierarchical",Jxe="sources",zce="targets",e8e="sections",dG="bendPoints",t8e="outgoingShape",n8e="incomingShape",r8e="outgoingSections",i8e="incomingSections",Qa="org.eclipse.emf.common.util",s8e="Severe implementation error in the Json to ElkGraph importer.",Id="id",Ia="org.eclipse.elk.graph.json",a8e="Unhandled parameter types: ",B1t="startPoint",R1t="An edge must have at least one source and one target (edge id: '",z7="').",F1t="Referenced edge section does not exist: ",j1t=" (edge id: '",o8e="target",$1t="sourcePoint",H1t="targetPoint",gG="group",gi="name",z1t="connectableShape cannot be null",G1t="edge cannot be null",Gce="Passed edge is not 'simple'.",pG="org.eclipse.elk.graph.util",YI="The 'no duplicates' constraint is violated",qce="targetIndex=",Eb=", size=",Vce="sourceIndex=",Od={3:1,4:1,20:1,28:1,52:1,14:1,15:1,54:1,67:1,63:1,58:1},Uce={3:1,4:1,20:1,28:1,52:1,14:1,47:1,15:1,54:1,67:1,63:1,58:1,588:1},bG="logging",q1t="measureExecutionTime",V1t="parser.parse.1",U1t="parser.parse.2",vG="parser.next.1",Wce="parser.next.2",W1t="parser.next.3",K1t="parser.next.4",Tb="parser.factor.1",c8e="parser.factor.2",Y1t="parser.factor.3",X1t="parser.factor.4",Q1t="parser.factor.5",Z1t="parser.factor.6",J1t="parser.atom.1",edt="parser.atom.2",tdt="parser.atom.3",u8e="parser.atom.4",Kce="parser.atom.5",l8e="parser.cc.1",wG="parser.cc.2",ndt="parser.cc.3",rdt="parser.cc.5",h8e="parser.cc.6",f8e="parser.cc.7",Yce="parser.cc.8",idt="parser.ope.1",sdt="parser.ope.2",adt="parser.ope.3",jg="parser.descape.1",odt="parser.descape.2",cdt="parser.descape.3",udt="parser.descape.4",ldt="parser.descape.5",xh="parser.process.1",hdt="parser.quantifier.1",fdt="parser.quantifier.2",ddt="parser.quantifier.3",gdt="parser.quantifier.4",d8e="parser.quantifier.5",pdt="org.eclipse.emf.common.notify",g8e={415:1,672:1},bdt={3:1,4:1,20:1,28:1,52:1,14:1,15:1,67:1,58:1},XI={366:1,143:1},$C="index=",Xce={3:1,4:1,5:1,126:1},vdt={3:1,4:1,20:1,28:1,52:1,14:1,15:1,54:1,67:1,58:1},p8e={3:1,6:1,4:1,5:1,192:1},wdt={3:1,4:1,5:1,165:1,367:1},mdt=";/?:@&=+$,",ydt="invalid authority: ",kdt="EAnnotation",xdt="ETypedElement",Edt="EStructuralFeature",Tdt="EAttribute",_dt="EClassifier",Cdt="EEnumLiteral",Sdt="EGenericType",Adt="EOperation",Ldt="EParameter",Mdt="EReference",Ddt="ETypeParameter",Wi="org.eclipse.emf.ecore.util",Qce={76:1},b8e={3:1,20:1,14:1,15:1,58:1,589:1,76:1,69:1,95:1},Idt="org.eclipse.emf.ecore.util.FeatureMap$Entry",Zu=8192,ky=2048,HC="byte",mG="char",zC="double",GC="float",qC="int",VC="long",UC="short",Odt="java.lang.Object",L4={3:1,4:1,5:1,247:1},v8e={3:1,4:1,5:1,673:1},Ndt={3:1,4:1,20:1,28:1,52:1,14:1,15:1,54:1,67:1,63:1,58:1,69:1},Zo={3:1,4:1,20:1,28:1,52:1,14:1,15:1,54:1,67:1,63:1,58:1,76:1,69:1,95:1},QI="mixed",Zr="http:///org/eclipse/emf/ecore/util/ExtendedMetaData",Vh="kind",Pdt={3:1,4:1,5:1,674:1},w8e={3:1,4:1,20:1,28:1,52:1,14:1,15:1,67:1,58:1,76:1,69:1,95:1},yG={20:1,28:1,52:1,14:1,15:1,58:1,69:1},kG={47:1,125:1,279:1},xG={72:1,332:1},EG="The value of type '",TG="' must be of type '",M4=1316,Uh="http://www.eclipse.org/emf/2002/Ecore",_G=-32768,gw="constraints",Ha="baseType",Bdt="getEStructuralFeature",Rdt="getFeatureID",WC="feature",Fdt="getOperationID",m8e="operation",jdt="defaultValue",$dt="eTypeParameters",Hdt="isInstance",zdt="getEEnumLiteral",Gdt="eContainingClass",li={55:1},qdt={3:1,4:1,5:1,119:1},Vdt="org.eclipse.emf.ecore.resource",Udt={92:1,90:1,591:1,1935:1},Zce="org.eclipse.emf.ecore.resource.impl",y8e="unspecified",ZI="simple",CG="attribute",Wdt="attributeWildcard",SG="element",Jce="elementWildcard",c1="collapse",eue="itemType",AG="namespace",JI="##targetNamespace",Wh="whiteSpace",k8e="wildcards",_b="http://www.eclipse.org/emf/2003/XMLType",tue="##any",G7="uninitialized",eO="The multiplicity constraint is violated",LG="org.eclipse.emf.ecore.xml.type",Kdt="ProcessingInstruction",Ydt="SimpleAnyType",Xdt="XMLTypeDocumentRoot",As="org.eclipse.emf.ecore.xml.type.impl",tO="INF",Qdt="processing",Zdt="ENTITIES_._base",x8e="minLength",E8e="ENTITY",MG="NCName",Jdt="IDREFS_._base",T8e="integer",nue="token",rue="pattern",e0t="[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*",_8e="\\i\\c*",t0t="[\\i-[:]][\\c-[:]]*",n0t="nonPositiveInteger",nO="maxInclusive",C8e="NMTOKEN",r0t="NMTOKENS_._base",S8e="nonNegativeInteger",rO="minInclusive",i0t="normalizedString",s0t="unsignedByte",a0t="unsignedInt",o0t="18446744073709551615",c0t="unsignedShort",u0t="processingInstruction",$g="org.eclipse.emf.ecore.xml.type.internal",q7=1114111,l0t="Internal Error: shorthands: \\u",KC="xml:isDigit",iue="xml:isWord",sue="xml:isSpace",aue="xml:isNameChar",oue="xml:isInitialNameChar",h0t="09٠٩۰۹०९০৯੦੯૦૯୦୯௧௯౦౯೦೯൦൯๐๙໐໙༠༩",f0t="AZazÀÖØöøıĴľŁňŊžƀǃǍǰǴǵǺȗɐʨʻˁΆΆΈΊΌΌΎΡΣώϐϖϚϚϜϜϞϞϠϠϢϳЁЌЎяёќўҁҐӄӇӈӋӌӐӫӮӵӸӹԱՖՙՙաֆאתװײءغفيٱڷںھۀێېۓەەۥۦअहऽऽक़ॡঅঌএঐওনপরললশহড়ঢ়য়ৡৰৱਅਊਏਐਓਨਪਰਲਲ਼ਵਸ਼ਸਹਖ਼ੜਫ਼ਫ਼ੲੴઅઋઍઍએઑઓનપરલળવહઽઽૠૠଅଌଏଐଓନପରଲଳଶହଽଽଡ଼ଢ଼ୟୡஅஊஎஐஒகஙசஜஜஞடணதநபமவஷஹఅఌఎఐఒనపళవహౠౡಅಌಎಐಒನಪಳವಹೞೞೠೡഅഌഎഐഒനപഹൠൡกฮะะาำเๅກຂຄຄງຈຊຊຍຍດທນຟມຣລລວວສຫອຮະະາຳຽຽເໄཀཇཉཀྵႠჅაჶᄀᄀᄂᄃᄅᄇᄉᄉᄋᄌᄎᄒᄼᄼᄾᄾᅀᅀᅌᅌᅎᅎᅐᅐᅔᅕᅙᅙᅟᅡᅣᅣᅥᅥᅧᅧᅩᅩᅭᅮᅲᅳᅵᅵᆞᆞᆨᆨᆫᆫᆮᆯᆷᆸᆺᆺᆼᇂᇫᇫᇰᇰᇹᇹḀẛẠỹἀἕἘἝἠὅὈὍὐὗὙὙὛὛὝὝὟώᾀᾴᾶᾼιιῂῄῆῌῐΐῖΊῠῬῲῴῶῼΩΩKÅ℮℮ↀↂ〇〇〡〩ぁゔァヺㄅㄬ一龥가힣",d0t="Private Use",cue="ASSIGNED",uue="\0€ÿĀſƀɏɐʯʰ˿̀ͯͰϿЀӿ԰֏֐׿؀ۿ܀ݏހ޿ऀॿঀ৿਀੿઀૿଀୿஀௿ఀ౿ಀ೿ഀൿ඀෿฀๿຀໿ༀ࿿က႟Ⴀჿᄀᇿሀ፿Ꭰ᏿᐀ᙿ ᚟ᚠ᛿ក៿᠀᢯Ḁỿἀ῿ ⁰₟₠⃏⃐⃿℀⅏⅐↏←⇿∀⋿⌀⏿␀␿⑀⑟①⓿─╿▀▟■◿☀⛿✀➿⠀⣿⺀⻿⼀⿟⿰⿿ 〿぀ゟ゠ヿ㄀ㄯ㄰㆏㆐㆟ㆠㆿ㈀㋿㌀㏿㐀䶵一鿿ꀀ꒏꒐꓏가힣豈﫿ffﭏﭐ﷿︠︯︰﹏﹐﹯ﹰ﻾\uFEFF\uFEFF＀￯",A8e="UNASSIGNED",V7={3:1,117:1},g0t="org.eclipse.emf.ecore.xml.type.util",DG={3:1,4:1,5:1,368:1},L8e="org.eclipse.xtext.xbase.lib",p0t="Cannot add elements to a Range",b0t="Cannot set elements in a Range",v0t="Cannot remove elements from a Range",IG="locale",OG="default",NG="user.agent",l,PG,lue;b.goog=b.goog||{},b.goog.global=b.goog.global||b,Afn(),M(1,null,{},S),l.Fb=function(t){return lVe(this,t)},l.Gb=function(){return this.gm},l.Hb=function(){return xv(this)},l.Ib=function(){var t;return Cp(pl(this))+"@"+(t=Xi(this)>>>0,t.toString(16))},l.equals=function(e){return this.Fb(e)},l.hashCode=function(){return this.Hb()},l.toString=function(){return this.Ib()};var w0t,m0t,y0t;M(290,1,{290:1,2026:1},aye),l.le=function(t){var n;return n=new aye,n.i=4,t>1?n.c=SXe(this,t-1):n.c=this,n},l.me=function(){return S0(this),this.b},l.ne=function(){return Cp(this)},l.oe=function(){return S0(this),this.k},l.pe=function(){return(this.i&4)!=0},l.qe=function(){return(this.i&1)!=0},l.Ib=function(){return kme(this)},l.i=0;var Yn=O(oc,"Object",1),M8e=O(oc,"Class",290);M(1998,1,_I),O(CI,"Optional",1998),M(1170,1998,_I,N),l.Fb=function(t){return t===this},l.Hb=function(){return 2040732332},l.Ib=function(){return"Optional.absent()"},l.Jb=function(t){return Nr(t),kT(),hue};var hue;O(CI,"Absent",1170),M(628,1,{},ste),O(CI,"Joiner",628);var r3n=ss(CI,"Predicate");M(582,1,{169:1,582:1,3:1,45:1},aT),l.Mb=function(t){return pnt(this,t)},l.Lb=function(t){return pnt(this,t)},l.Fb=function(t){var n;return we(t,582)?(n=u(t,582),J4e(this.a,n.a)):!1},l.Hb=function(){return hye(this.a)+306654252},l.Ib=function(){return g1n(this.a)},O(CI,"Predicates/AndPredicate",582),M(408,1998,{408:1,3:1},Bx),l.Fb=function(t){var n;return we(t,408)?(n=u(t,408),Ci(this.a,n.a)):!1},l.Hb=function(){return 1502476572+Xi(this.a)},l.Ib=function(){return tht+this.a+")"},l.Jb=function(t){return new Bx(Zj(t.Kb(this.a),"the Function passed to Optional.transform() must not return null."))},O(CI,"Present",408),M(198,1,T7),l.Nb=function(t){La(this,t)},l.Qb=function(){eze()},O(qt,"UnmodifiableIterator",198),M(1978,198,_7),l.Qb=function(){eze()},l.Rb=function(t){throw J(new Fr)},l.Wb=function(t){throw J(new Fr)},O(qt,"UnmodifiableListIterator",1978),M(386,1978,_7),l.Ob=function(){return this.c0},l.Pb=function(){if(this.c>=this.d)throw J(new xc);return this.Xb(this.c++)},l.Tb=function(){return this.c},l.Ub=function(){if(this.c<=0)throw J(new xc);return this.Xb(--this.c)},l.Vb=function(){return this.c-1},l.c=0,l.d=0,O(qt,"AbstractIndexedListIterator",386),M(699,198,T7),l.Ob=function(){return nie(this)},l.Pb=function(){return pme(this)},l.e=1,O(qt,"AbstractIterator",699),M(1986,1,{224:1}),l.Zb=function(){var t;return t=this.f,t||(this.f=this.ac())},l.Fb=function(t){return yie(this,t)},l.Hb=function(){return Xi(this.Zb())},l.dc=function(){return this.gc()==0},l.ec=function(){return D6(this)},l.Ib=function(){return Qo(this.Zb())},O(qt,"AbstractMultimap",1986),M(726,1986,bb),l.$b=function(){U$(this)},l._b=function(t){return mze(this,t)},l.ac=function(){return new Jx(this,this.c)},l.ic=function(t){return this.hc()},l.bc=function(){return new H3(this,this.c)},l.jc=function(){return this.mc(this.hc())},l.kc=function(){return new RHe(this)},l.lc=function(){return Sse(this.c.vc().Nc(),new R,64,this.d)},l.cc=function(t){return Ii(this,t)},l.fc=function(t){return jD(this,t)},l.gc=function(){return this.d},l.mc=function(t){return hn(),new T(t)},l.nc=function(){return new BHe(this)},l.oc=function(){return Sse(this.c.Cc().Nc(),new B,64,this.d)},l.pc=function(t,n){return new C$(this,t,n,null)},l.d=0,O(qt,"AbstractMapBasedMultimap",726),M(1631,726,bb),l.hc=function(){return new su(this.a)},l.jc=function(){return hn(),hn(),bo},l.cc=function(t){return u(Ii(this,t),15)},l.fc=function(t){return u(jD(this,t),15)},l.Zb=function(){return B6(this)},l.Fb=function(t){return yie(this,t)},l.qc=function(t){return u(Ii(this,t),15)},l.rc=function(t){return u(jD(this,t),15)},l.mc=function(t){return ZM(u(t,15))},l.pc=function(t,n){return IQe(this,t,u(n,15),null)},O(qt,"AbstractListMultimap",1631),M(732,1,ga),l.Nb=function(t){La(this,t)},l.Ob=function(){return this.c.Ob()||this.e.Ob()},l.Pb=function(){var t;return this.e.Ob()||(t=u(this.c.Pb(),42),this.b=t.cd(),this.a=u(t.dd(),14),this.e=this.a.Kc()),this.sc(this.b,this.e.Pb())},l.Qb=function(){this.e.Qb(),this.a.dc()&&this.c.Qb(),--this.d.d},O(qt,"AbstractMapBasedMultimap/Itr",732),M(1099,732,ga,BHe),l.sc=function(t,n){return n},O(qt,"AbstractMapBasedMultimap/1",1099),M(1100,1,{},B),l.Kb=function(t){return u(t,14).Nc()},O(qt,"AbstractMapBasedMultimap/1methodref$spliterator$Type",1100),M(1101,732,ga,RHe),l.sc=function(t,n){return new vv(t,n)},O(qt,"AbstractMapBasedMultimap/2",1101);var D8e=ss(wr,"Map");M(1967,1,ow),l.wc=function(t){B_(this,t)},l.yc=function(t,n,r){return Rie(this,t,n,r)},l.$b=function(){this.vc().$b()},l.tc=function(t){return lse(this,t)},l._b=function(t){return!!n4e(this,t,!1)},l.uc=function(t){var n,r,s;for(r=this.vc().Kc();r.Ob();)if(n=u(r.Pb(),42),s=n.dd(),je(t)===je(s)||t!=null&&Ci(t,s))return!0;return!1},l.Fb=function(t){var n,r,s;if(t===this)return!0;if(!we(t,83)||(s=u(t,83),this.gc()!=s.gc()))return!1;for(r=s.vc().Kc();r.Ob();)if(n=u(r.Pb(),42),!this.tc(n))return!1;return!0},l.xc=function(t){return hc(n4e(this,t,!1))},l.Hb=function(){return tye(this.vc())},l.dc=function(){return this.gc()==0},l.ec=function(){return new vm(this)},l.zc=function(t,n){throw J(new pg("Put not supported on this map"))},l.Ac=function(t){P_(this,t)},l.Bc=function(t){return hc(n4e(this,t,!0))},l.gc=function(){return this.vc().gc()},l.Ib=function(){return vst(this)},l.Cc=function(){return new E1(this)},O(wr,"AbstractMap",1967),M(1987,1967,ow),l.bc=function(){return new mF(this)},l.vc=function(){return DKe(this)},l.ec=function(){var t;return t=this.g,t||(this.g=this.bc())},l.Cc=function(){var t;return t=this.i,t||(this.i=new hGe(this))},O(qt,"Maps/ViewCachingAbstractMap",1987),M(389,1987,ow,Jx),l.xc=function(t){return Xrn(this,t)},l.Bc=function(t){return fan(this,t)},l.$b=function(){this.d==this.e.c?this.e.$b():Aj(new Eve(this))},l._b=function(t){return Knt(this.d,t)},l.Ec=function(){return new Rx(this)},l.Dc=function(){return this.Ec()},l.Fb=function(t){return this===t||Ci(this.d,t)},l.Hb=function(){return Xi(this.d)},l.ec=function(){return this.e.ec()},l.gc=function(){return this.d.gc()},l.Ib=function(){return Qo(this.d)},O(qt,"AbstractMapBasedMultimap/AsMap",389);var q1=ss(oc,"Iterable");M(28,1,hy),l.Jc=function(t){Da(this,t)},l.Lc=function(){return this.Oc()},l.Nc=function(){return new mn(this,0)},l.Oc=function(){return new vn(null,this.Nc())},l.Fc=function(t){throw J(new pg("Add not supported on this collection"))},l.Gc=function(t){return no(this,t)},l.$b=function(){cwe(this)},l.Hc=function(t){return Xm(this,t,!1)},l.Ic=function(t){return MD(this,t)},l.dc=function(){return this.gc()==0},l.Mc=function(t){return Xm(this,t,!0)},l.Pc=function(){return Bve(this)},l.Qc=function(t){return YD(this,t)},l.Ib=function(){return Yp(this)},O(wr,"AbstractCollection",28);var Kh=ss(wr,"Set");M(H1,28,Xu),l.Nc=function(){return new mn(this,1)},l.Fb=function(t){return Hrt(this,t)},l.Hb=function(){return tye(this)},O(wr,"AbstractSet",H1),M(1970,H1,Xu),O(qt,"Sets/ImprovedAbstractSet",1970),M(1971,1970,Xu),l.$b=function(){this.Rc().$b()},l.Hc=function(t){return xrt(this,t)},l.dc=function(){return this.Rc().dc()},l.Mc=function(t){var n;return this.Hc(t)?(n=u(t,42),this.Rc().ec().Mc(n.cd())):!1},l.gc=function(){return this.Rc().gc()},O(qt,"Maps/EntrySet",1971),M(1097,1971,Xu,Rx),l.Hc=function(t){return Mye(this.a.d.vc(),t)},l.Kc=function(){return new Eve(this.a)},l.Rc=function(){return this.a},l.Mc=function(t){var n;return Mye(this.a.d.vc(),t)?(n=u(t,42),Bnn(this.a.e,n.cd()),!0):!1},l.Nc=function(){return qM(this.a.d.vc().Nc(),new $R(this.a))},O(qt,"AbstractMapBasedMultimap/AsMap/AsMapEntries",1097),M(1098,1,{},$R),l.Kb=function(t){return kZe(this.a,u(t,42))},O(qt,"AbstractMapBasedMultimap/AsMap/AsMapEntries/0methodref$wrapEntry$Type",1098),M(730,1,ga,Eve),l.Nb=function(t){La(this,t)},l.Pb=function(){var t;return t=u(this.b.Pb(),42),this.a=u(t.dd(),14),kZe(this.c,t)},l.Ob=function(){return this.b.Ob()},l.Qb=function(){X3(!!this.a),this.b.Qb(),this.c.e.d-=this.a.gc(),this.a.$b(),this.a=null},O(qt,"AbstractMapBasedMultimap/AsMap/AsMapIterator",730),M(532,1970,Xu,mF),l.$b=function(){this.b.$b()},l.Hc=function(t){return this.b._b(t)},l.Jc=function(t){Nr(t),this.b.wc(new dee(t))},l.dc=function(){return this.b.dc()},l.Kc=function(){return new xT(this.b.vc().Kc())},l.Mc=function(t){return this.b._b(t)?(this.b.Bc(t),!0):!1},l.gc=function(){return this.b.gc()},O(qt,"Maps/KeySet",532),M(318,532,Xu,H3),l.$b=function(){var t;Aj((t=this.b.vc().Kc(),new Ype(this,t)))},l.Ic=function(t){return this.b.ec().Ic(t)},l.Fb=function(t){return this===t||Ci(this.b.ec(),t)},l.Hb=function(){return Xi(this.b.ec())},l.Kc=function(){var t;return t=this.b.vc().Kc(),new Ype(this,t)},l.Mc=function(t){var n,r;return r=0,n=u(this.b.Bc(t),14),n&&(r=n.gc(),n.$b(),this.a.d-=r),r>0},l.Nc=function(){return this.b.ec().Nc()},O(qt,"AbstractMapBasedMultimap/KeySet",318),M(731,1,ga,Ype),l.Nb=function(t){La(this,t)},l.Ob=function(){return this.c.Ob()},l.Pb=function(){return this.a=u(this.c.Pb(),42),this.a.cd()},l.Qb=function(){var t;X3(!!this.a),t=u(this.a.dd(),14),this.c.Qb(),this.b.a.d-=t.gc(),t.$b(),this.a=null},O(qt,"AbstractMapBasedMultimap/KeySet/1",731),M(491,389,{83:1,161:1},RM),l.bc=function(){return this.Sc()},l.ec=function(){return this.Tc()},l.Sc=function(){return new dM(this.c,this.Uc())},l.Tc=function(){var t;return t=this.b,t||(this.b=this.Sc())},l.Uc=function(){return u(this.d,161)},O(qt,"AbstractMapBasedMultimap/SortedAsMap",491),M(542,491,nht,pj),l.bc=function(){return new Zx(this.a,u(u(this.d,161),171))},l.Sc=function(){return new Zx(this.a,u(u(this.d,161),171))},l.ec=function(){var t;return t=this.b,u(t||(this.b=new Zx(this.a,u(u(this.d,161),171))),271)},l.Tc=function(){var t;return t=this.b,u(t||(this.b=new Zx(this.a,u(u(this.d,161),171))),271)},l.Uc=function(){return u(u(this.d,161),171)},O(qt,"AbstractMapBasedMultimap/NavigableAsMap",542),M(490,318,rht,dM),l.Nc=function(){return this.b.ec().Nc()},O(qt,"AbstractMapBasedMultimap/SortedKeySet",490),M(388,490,g6e,Zx),O(qt,"AbstractMapBasedMultimap/NavigableKeySet",388),M(541,28,hy,C$),l.Fc=function(t){var n,r;return bl(this),r=this.d.dc(),n=this.d.Fc(t),n&&(++this.f.d,r&&HM(this)),n},l.Gc=function(t){var n,r,s;return t.dc()?!1:(s=(bl(this),this.d.gc()),n=this.d.Gc(t),n&&(r=this.d.gc(),this.f.d+=r-s,s==0&&HM(this)),n)},l.$b=function(){var t;t=(bl(this),this.d.gc()),t!=0&&(this.d.$b(),this.f.d-=t,Oj(this))},l.Hc=function(t){return bl(this),this.d.Hc(t)},l.Ic=function(t){return bl(this),this.d.Ic(t)},l.Fb=function(t){return t===this?!0:(bl(this),Ci(this.d,t))},l.Hb=function(){return bl(this),Xi(this.d)},l.Kc=function(){return bl(this),new uve(this)},l.Mc=function(t){var n;return bl(this),n=this.d.Mc(t),n&&(--this.f.d,Oj(this)),n},l.gc=function(){return Yqe(this)},l.Nc=function(){return bl(this),this.d.Nc()},l.Ib=function(){return bl(this),Qo(this.d)},O(qt,"AbstractMapBasedMultimap/WrappedCollection",541);var Eh=ss(wr,"List");M(728,541,{20:1,28:1,14:1,15:1},Fve),l.ad=function(t){Y3(this,t)},l.Nc=function(){return bl(this),this.d.Nc()},l.Vc=function(t,n){var r;bl(this),r=this.d.dc(),u(this.d,15).Vc(t,n),++this.a.d,r&&HM(this)},l.Wc=function(t,n){var r,s,o;return n.dc()?!1:(o=(bl(this),this.d.gc()),r=u(this.d,15).Wc(t,n),r&&(s=this.d.gc(),this.a.d+=s-o,o==0&&HM(this)),r)},l.Xb=function(t){return bl(this),u(this.d,15).Xb(t)},l.Xc=function(t){return bl(this),u(this.d,15).Xc(t)},l.Yc=function(){return bl(this),new AVe(this)},l.Zc=function(t){return bl(this),new HYe(this,t)},l.$c=function(t){var n;return bl(this),n=u(this.d,15).$c(t),--this.a.d,Oj(this),n},l._c=function(t,n){return bl(this),u(this.d,15)._c(t,n)},l.bd=function(t,n){return bl(this),IQe(this.a,this.e,u(this.d,15).bd(t,n),this.b?this.b:this)},O(qt,"AbstractMapBasedMultimap/WrappedList",728),M(1096,728,{20:1,28:1,14:1,15:1,54:1},wUe),O(qt,"AbstractMapBasedMultimap/RandomAccessWrappedList",1096),M(620,1,ga,uve),l.Nb=function(t){La(this,t)},l.Ob=function(){return y8(this),this.b.Ob()},l.Pb=function(){return y8(this),this.b.Pb()},l.Qb=function(){tUe(this)},O(qt,"AbstractMapBasedMultimap/WrappedCollection/WrappedIterator",620),M(729,620,r0,AVe,HYe),l.Qb=function(){tUe(this)},l.Rb=function(t){var n;n=Yqe(this.a)==0,(y8(this),u(this.b,125)).Rb(t),++this.a.a.d,n&&HM(this.a)},l.Sb=function(){return(y8(this),u(this.b,125)).Sb()},l.Tb=function(){return(y8(this),u(this.b,125)).Tb()},l.Ub=function(){return(y8(this),u(this.b,125)).Ub()},l.Vb=function(){return(y8(this),u(this.b,125)).Vb()},l.Wb=function(t){(y8(this),u(this.b,125)).Wb(t)},O(qt,"AbstractMapBasedMultimap/WrappedList/WrappedListIterator",729),M(727,541,rht,Mbe),l.Nc=function(){return bl(this),this.d.Nc()},O(qt,"AbstractMapBasedMultimap/WrappedSortedSet",727),M(1095,727,g6e,yVe),O(qt,"AbstractMapBasedMultimap/WrappedNavigableSet",1095),M(1094,541,Xu,IUe),l.Nc=function(){return bl(this),this.d.Nc()},O(qt,"AbstractMapBasedMultimap/WrappedSet",1094),M(1103,1,{},R),l.Kb=function(t){return znn(u(t,42))},O(qt,"AbstractMapBasedMultimap/lambda$1$Type",1103),M(1102,1,{},eee),l.Kb=function(t){return new vv(this.a,t)},O(qt,"AbstractMapBasedMultimap/lambda$2$Type",1102);var Cb=ss(wr,"Map/Entry");M(345,1,_z),l.Fb=function(t){var n;return we(t,42)?(n=u(t,42),md(this.cd(),n.cd())&&md(this.dd(),n.dd())):!1},l.Hb=function(){var t,n;return t=this.cd(),n=this.dd(),(t==null?0:Xi(t))^(n==null?0:Xi(n))},l.ed=function(t){throw J(new Fr)},l.Ib=function(){return this.cd()+"="+this.dd()},O(qt,iht,345),M(1988,28,hy),l.$b=function(){this.fd().$b()},l.Hc=function(t){var n;return we(t,42)?(n=u(t,42),xtn(this.fd(),n.cd(),n.dd())):!1},l.Mc=function(t){var n;return we(t,42)?(n=u(t,42),fQe(this.fd(),n.cd(),n.dd())):!1},l.gc=function(){return this.fd().d},O(qt,"Multimaps/Entries",1988),M(733,1988,hy,XL),l.Kc=function(){return this.a.kc()},l.fd=function(){return this.a},l.Nc=function(){return this.a.lc()},O(qt,"AbstractMultimap/Entries",733),M(734,733,Xu,_pe),l.Nc=function(){return this.a.lc()},l.Fb=function(t){return y4e(this,t)},l.Hb=function(){return ptt(this)},O(qt,"AbstractMultimap/EntrySet",734),M(735,28,hy,T3),l.$b=function(){this.a.$b()},l.Hc=function(t){return aan(this.a,t)},l.Kc=function(){return this.a.nc()},l.gc=function(){return this.a.d},l.Nc=function(){return this.a.oc()},O(qt,"AbstractMultimap/Values",735),M(1989,28,{835:1,20:1,28:1,14:1}),l.Jc=function(t){Nr(t),G3(this).Jc(new fee(t))},l.Nc=function(){var t;return t=G3(this).Nc(),Sse(t,new ve,64|t.qd()&1296,this.a.d)},l.Fc=function(t){return Npe(),!0},l.Gc=function(t){return Nr(this),Nr(t),we(t,543)?Stn(u(t,835)):!t.dc()&&Wre(this,t.Kc())},l.Hc=function(t){var n;return n=u(Ym(B6(this.a),t),14),(n?n.gc():0)>0},l.Fb=function(t){return y0n(this,t)},l.Hb=function(){return Xi(G3(this))},l.dc=function(){return G3(this).dc()},l.Mc=function(t){return Nat(this,t,1)>0},l.Ib=function(){return Qo(G3(this))},O(qt,"AbstractMultiset",1989),M(1991,1970,Xu),l.$b=function(){U$(this.a.a)},l.Hc=function(t){var n,r;return we(t,492)?(r=u(t,416),u(r.a.dd(),14).gc()<=0?!1:(n=zXe(this.a,r.a.cd()),n==u(r.a.dd(),14).gc())):!1},l.Mc=function(t){var n,r,s,o;return we(t,492)&&(r=u(t,416),n=r.a.cd(),s=u(r.a.dd(),14).gc(),s!=0)?(o=this.a,cdn(o,n,s)):!1},O(qt,"Multisets/EntrySet",1991),M(1109,1991,Xu,QL),l.Kc=function(){return new VHe(DKe(B6(this.a.a)).Kc())},l.gc=function(){return B6(this.a.a).gc()},O(qt,"AbstractMultiset/EntrySet",1109),M(619,726,bb),l.hc=function(){return this.gd()},l.jc=function(){return this.hd()},l.cc=function(t){return this.jd(t)},l.fc=function(t){return this.kd(t)},l.Zb=function(){var t;return t=this.f,t||(this.f=this.ac())},l.hd=function(){return hn(),hn(),HG},l.Fb=function(t){return yie(this,t)},l.jd=function(t){return u(Ii(this,t),21)},l.kd=function(t){return u(jD(this,t),21)},l.mc=function(t){return hn(),new Kx(u(t,21))},l.pc=function(t,n){return new IUe(this,t,u(n,21))},O(qt,"AbstractSetMultimap",619),M(1657,619,bb),l.hc=function(){return new Sp(this.b)},l.gd=function(){return new Sp(this.b)},l.jc=function(){return Jve(new Sp(this.b))},l.hd=function(){return Jve(new Sp(this.b))},l.cc=function(t){return u(u(Ii(this,t),21),84)},l.jd=function(t){return u(u(Ii(this,t),21),84)},l.fc=function(t){return u(u(jD(this,t),21),84)},l.kd=function(t){return u(u(jD(this,t),21),84)},l.mc=function(t){return we(t,271)?Jve(u(t,271)):(hn(),new ube(u(t,84)))},l.Zb=function(){var t;return t=this.f,t||(this.f=we(this.c,171)?new pj(this,u(this.c,171)):we(this.c,161)?new RM(this,u(this.c,161)):new Jx(this,this.c))},l.pc=function(t,n){return we(n,271)?new yVe(this,t,u(n,271)):new Mbe(this,t,u(n,84))},O(qt,"AbstractSortedSetMultimap",1657),M(1658,1657,bb),l.Zb=function(){var t;return t=this.f,u(u(t||(this.f=we(this.c,171)?new pj(this,u(this.c,171)):we(this.c,161)?new RM(this,u(this.c,161)):new Jx(this,this.c)),161),171)},l.ec=function(){var t;return t=this.i,u(u(t||(this.i=we(this.c,171)?new Zx(this,u(this.c,171)):we(this.c,161)?new dM(this,u(this.c,161)):new H3(this,this.c)),84),271)},l.bc=function(){return we(this.c,171)?new Zx(this,u(this.c,171)):we(this.c,161)?new dM(this,u(this.c,161)):new H3(this,this.c)},O(qt,"AbstractSortedKeySortedSetMultimap",1658),M(2010,1,{1947:1}),l.Fb=function(t){return Qln(this,t)},l.Hb=function(){var t;return tye((t=this.g,t||(this.g=new oT(this))))},l.Ib=function(){var t;return vst((t=this.f,t||(this.f=new tbe(this))))},O(qt,"AbstractTable",2010),M(665,H1,Xu,oT),l.$b=function(){tze()},l.Hc=function(t){var n,r;return we(t,468)?(n=u(t,682),r=u(Ym(eYe(this.a),Mp(n.c.e,n.b)),83),!!r&&Mye(r.vc(),new vv(Mp(n.c.c,n.a),G6(n.c,n.b,n.a)))):!1},l.Kc=function(){return PJt(this.a)},l.Mc=function(t){var n,r;return we(t,468)?(n=u(t,682),r=u(Ym(eYe(this.a),Mp(n.c.e,n.b)),83),!!r&&Oan(r.vc(),new vv(Mp(n.c.c,n.a),G6(n.c,n.b,n.a)))):!1},l.gc=function(){return fKe(this.a)},l.Nc=function(){return Mtn(this.a)},O(qt,"AbstractTable/CellSet",665),M(1928,28,hy,tee),l.$b=function(){tze()},l.Hc=function(t){return zhn(this.a,t)},l.Kc=function(){return BJt(this.a)},l.gc=function(){return fKe(this.a)},l.Nc=function(){return pQe(this.a)},O(qt,"AbstractTable/Values",1928),M(1632,1631,bb),O(qt,"ArrayListMultimapGwtSerializationDependencies",1632),M(513,1632,bb,ite,Twe),l.hc=function(){return new su(this.a)},l.a=0,O(qt,"ArrayListMultimap",513),M(664,2010,{664:1,1947:1,3:1},qat),O(qt,"ArrayTable",664),M(1924,386,_7,YVe),l.Xb=function(t){return new sye(this.a,t)},O(qt,"ArrayTable/1",1924),M(1925,1,{},jR),l.ld=function(t){return new sye(this.a,t)},O(qt,"ArrayTable/1methodref$getCell$Type",1925),M(2011,1,{682:1}),l.Fb=function(t){var n;return t===this?!0:we(t,468)?(n=u(t,682),md(Mp(this.c.e,this.b),Mp(n.c.e,n.b))&&md(Mp(this.c.c,this.a),Mp(n.c.c,n.a))&&md(G6(this.c,this.b,this.a),G6(n.c,n.b,n.a))):!1},l.Hb=function(){return fH(ie(re(Yn,1),yt,1,5,[Mp(this.c.e,this.b),Mp(this.c.c,this.a),G6(this.c,this.b,this.a)]))},l.Ib=function(){return"("+Mp(this.c.e,this.b)+","+Mp(this.c.c,this.a)+")="+G6(this.c,this.b,this.a)},O(qt,"Tables/AbstractCell",2011),M(468,2011,{468:1,682:1},sye),l.a=0,l.b=0,l.d=0,O(qt,"ArrayTable/2",468),M(1927,1,{},r6),l.ld=function(t){return CJe(this.a,t)},O(qt,"ArrayTable/2methodref$getValue$Type",1927),M(1926,386,_7,XVe),l.Xb=function(t){return CJe(this.a,t)},O(qt,"ArrayTable/3",1926),M(1979,1967,ow),l.$b=function(){Aj(this.kc())},l.vc=function(){return new s6(this)},l.lc=function(){return new AYe(this.kc(),this.gc())},O(qt,"Maps/IteratorBasedAbstractMap",1979),M(828,1979,ow),l.$b=function(){throw J(new Fr)},l._b=function(t){return yze(this.c,t)},l.kc=function(){return new QVe(this,this.c.b.c.gc())},l.lc=function(){return Ene(this.c.b.c.gc(),16,new iv(this))},l.xc=function(t){var n;return n=u(c_(this.c,t),19),n?this.nd(n.a):null},l.dc=function(){return this.c.b.c.dc()},l.ec=function(){return Dne(this.c)},l.zc=function(t,n){var r;if(r=u(c_(this.c,t),19),!r)throw J(new Ln(this.md()+" "+t+" not in "+Dne(this.c)));return this.od(r.a,n)},l.Bc=function(t){throw J(new Fr)},l.gc=function(){return this.c.b.c.gc()},O(qt,"ArrayTable/ArrayMap",828),M(1923,1,{},iv),l.ld=function(t){return nYe(this.a,t)},O(qt,"ArrayTable/ArrayMap/0methodref$getEntry$Type",1923),M(1921,345,_z,eGe),l.cd=function(){return QWt(this.a,this.b)},l.dd=function(){return this.a.nd(this.b)},l.ed=function(t){return this.a.od(this.b,t)},l.b=0,O(qt,"ArrayTable/ArrayMap/1",1921),M(1922,386,_7,QVe),l.Xb=function(t){return nYe(this.a,t)},O(qt,"ArrayTable/ArrayMap/2",1922),M(1920,828,ow,GKe),l.md=function(){return"Column"},l.nd=function(t){return G6(this.b,this.a,t)},l.od=function(t,n){return ent(this.b,this.a,t,n)},l.a=0,O(qt,"ArrayTable/Row",1920),M(829,828,ow,tbe),l.nd=function(t){return new GKe(this.a,t)},l.zc=function(t,n){return u(n,83),NVt()},l.od=function(t,n){return u(n,83),PVt()},l.md=function(){return"Row"},O(qt,"ArrayTable/RowMap",829),M(1120,1,Hh,tGe),l.qd=function(){return this.a.qd()&-262},l.rd=function(){return this.a.rd()},l.Nb=function(t){this.a.Nb(new Xze(t,this.b))},l.sd=function(t){return this.a.sd(new Yze(t,this.b))},O(qt,"CollectSpliterators/1",1120),M(1121,1,Un,Yze),l.td=function(t){this.a.td(this.b.Kb(t))},O(qt,"CollectSpliterators/1/lambda$0$Type",1121),M(1122,1,Un,Xze),l.td=function(t){this.a.td(this.b.Kb(t))},O(qt,"CollectSpliterators/1/lambda$1$Type",1122),M(1123,1,Hh,CQe),l.qd=function(){return this.a},l.rd=function(){return this.d&&(this.b=MVe(this.b,this.d.rd())),MVe(this.b,0)},l.Nb=function(t){this.d&&(this.d.Nb(t),this.d=null),this.c.Nb(new Kze(this.e,t)),this.b=0},l.sd=function(t){for(;;){if(this.d&&this.d.sd(t))return XT(this.b,Cz)&&(this.b=Wp(this.b,1)),!0;if(this.d=null,!this.c.sd(new Qze(this,this.e)))return!1}},l.a=0,l.b=0,O(qt,"CollectSpliterators/1FlatMapSpliterator",1123),M(1124,1,Un,Qze),l.td=function(t){eYt(this.a,this.b,t)},O(qt,"CollectSpliterators/1FlatMapSpliterator/lambda$0$Type",1124),M(1125,1,Un,Kze),l.td=function(t){FWt(this.b,this.a,t)},O(qt,"CollectSpliterators/1FlatMapSpliterator/lambda$1$Type",1125),M(1117,1,Hh,cWe),l.qd=function(){return 16464|this.b},l.rd=function(){return this.a.rd()},l.Nb=function(t){this.a.xe(new Jze(t,this.c))},l.sd=function(t){return this.a.ye(new Zze(t,this.c))},l.b=0,O(qt,"CollectSpliterators/1WithCharacteristics",1117),M(1118,1,SI,Zze),l.ud=function(t){this.a.td(this.b.ld(t))},O(qt,"CollectSpliterators/1WithCharacteristics/lambda$0$Type",1118),M(1119,1,SI,Jze),l.ud=function(t){this.a.td(this.b.ld(t))},O(qt,"CollectSpliterators/1WithCharacteristics/lambda$1$Type",1119),M(245,1,Iae),l.wd=function(t){return this.vd(u(t,245))},l.vd=function(t){var n;return t==(Yee(),due)?1:t==(Xee(),fue)?-1:(n=(_j(),CD(this.a,t.a)),n!=0?n:we(this,519)==we(t,519)?0:we(this,519)?1:-1)},l.zd=function(){return this.a},l.Fb=function(t){return c3e(this,t)},O(qt,"Cut",245),M(1761,245,Iae,ize),l.vd=function(t){return t==this?0:1},l.xd=function(t){throw J(new ope)},l.yd=function(t){t.a+="+∞)"},l.zd=function(){throw J(new Wo(aht))},l.Hb=function(){return Ud(),v3e(this)},l.Ad=function(t){return!1},l.Ib=function(){return"+∞"};var fue;O(qt,"Cut/AboveAll",1761),M(519,245,{245:1,519:1,3:1,35:1},nUe),l.xd=function(t){Ec((t.a+="(",t),this.a)},l.yd=function(t){Bp(Ec(t,this.a),93)},l.Hb=function(){return~Xi(this.a)},l.Ad=function(t){return _j(),CD(this.a,t)<0},l.Ib=function(){return"/"+this.a+"\\"},O(qt,"Cut/AboveValue",519),M(1760,245,Iae,sze),l.vd=function(t){return t==this?0:-1},l.xd=function(t){t.a+="(-∞"},l.yd=function(t){throw J(new ope)},l.zd=function(){throw J(new Wo(aht))},l.Hb=function(){return Ud(),v3e(this)},l.Ad=function(t){return!0},l.Ib=function(){return"-∞"};var due;O(qt,"Cut/BelowAll",1760),M(1762,245,Iae,rUe),l.xd=function(t){Ec((t.a+="[",t),this.a)},l.yd=function(t){Bp(Ec(t,this.a),41)},l.Hb=function(){return Xi(this.a)},l.Ad=function(t){return _j(),CD(this.a,t)<=0},l.Ib=function(){return"\\"+this.a+"/"},O(qt,"Cut/BelowValue",1762),M(537,1,i0),l.Jc=function(t){Da(this,t)},l.Ib=function(){return uon(u(Zj(this,"use Optional.orNull() instead of Optional.or(null)"),20).Kc())},O(qt,"FluentIterable",537),M(433,537,i0,JT),l.Kc=function(){return new cr(fr(this.a.Kc(),new V))},O(qt,"FluentIterable/2",433),M(1046,537,i0,oVe),l.Kc=function(){return Pp(this)},O(qt,"FluentIterable/3",1046),M(708,386,_7,nbe),l.Xb=function(t){return this.a[t].Kc()},O(qt,"FluentIterable/3/1",708),M(1972,1,{}),l.Ib=function(){return Qo(this.Bd().b)},O(qt,"ForwardingObject",1972),M(1973,1972,oht),l.Bd=function(){return this.Cd()},l.Jc=function(t){Da(this,t)},l.Lc=function(){return this.Oc()},l.Nc=function(){return new mn(this,0)},l.Oc=function(){return new vn(null,this.Nc())},l.Fc=function(t){return this.Cd(),Tze()},l.Gc=function(t){return this.Cd(),_ze()},l.$b=function(){this.Cd(),Cze()},l.Hc=function(t){return this.Cd().Hc(t)},l.Ic=function(t){return this.Cd().Ic(t)},l.dc=function(){return this.Cd().b.dc()},l.Kc=function(){return this.Cd().Kc()},l.Mc=function(t){return this.Cd(),Sze()},l.gc=function(){return this.Cd().b.gc()},l.Pc=function(){return this.Cd().Pc()},l.Qc=function(t){return this.Cd().Qc(t)},O(qt,"ForwardingCollection",1973),M(1980,28,p6e),l.Kc=function(){return this.Ed()},l.Fc=function(t){throw J(new Fr)},l.Gc=function(t){throw J(new Fr)},l.$b=function(){throw J(new Fr)},l.Hc=function(t){return t!=null&&Xm(this,t,!1)},l.Dd=function(){switch(this.gc()){case 0:return Rm(),Rm(),gue;case 1:return Rm(),new Tne(Nr(this.Ed().Pb()));default:return new qKe(this,this.Pc())}},l.Mc=function(t){throw J(new Fr)},O(qt,"ImmutableCollection",1980),M(712,1980,p6e,spe),l.Kc=function(){return q6(this.a.Kc())},l.Hc=function(t){return t!=null&&this.a.Hc(t)},l.Ic=function(t){return this.a.Ic(t)},l.dc=function(){return this.a.dc()},l.Ed=function(){return q6(this.a.Kc())},l.gc=function(){return this.a.gc()},l.Pc=function(){return this.a.Pc()},l.Qc=function(t){return this.a.Qc(t)},l.Ib=function(){return Qo(this.a)},O(qt,"ForwardingImmutableCollection",712),M(152,1980,vC),l.Kc=function(){return this.Ed()},l.Yc=function(){return this.Fd(0)},l.Zc=function(t){return this.Fd(t)},l.ad=function(t){Y3(this,t)},l.Nc=function(){return new mn(this,16)},l.bd=function(t,n){return this.Gd(t,n)},l.Vc=function(t,n){throw J(new Fr)},l.Wc=function(t,n){throw J(new Fr)},l.Fb=function(t){return i0n(this,t)},l.Hb=function(){return psn(this)},l.Xc=function(t){return t==null?-1:Aun(this,t)},l.Ed=function(){return this.Fd(0)},l.Fd=function(t){return vbe(this,t)},l.$c=function(t){throw J(new Fr)},l._c=function(t,n){throw J(new Fr)},l.Gd=function(t,n){var r;return pH((r=new fGe(this),new Zd(r,t,n)))};var gue;O(qt,"ImmutableList",152),M(2006,152,vC),l.Kc=function(){return q6(this.Hd().Kc())},l.bd=function(t,n){return pH(this.Hd().bd(t,n))},l.Hc=function(t){return t!=null&&this.Hd().Hc(t)},l.Ic=function(t){return this.Hd().Ic(t)},l.Fb=function(t){return Ci(this.Hd(),t)},l.Xb=function(t){return Mp(this,t)},l.Hb=function(){return Xi(this.Hd())},l.Xc=function(t){return this.Hd().Xc(t)},l.dc=function(){return this.Hd().dc()},l.Ed=function(){return q6(this.Hd().Kc())},l.gc=function(){return this.Hd().gc()},l.Gd=function(t,n){return pH(this.Hd().bd(t,n))},l.Pc=function(){return this.Hd().Qc(Me(Yn,yt,1,this.Hd().gc(),5,1))},l.Qc=function(t){return this.Hd().Qc(t)},l.Ib=function(){return Qo(this.Hd())},O(qt,"ForwardingImmutableList",2006),M(714,1,C7),l.vc=function(){return Cv(this)},l.wc=function(t){B_(this,t)},l.ec=function(){return Dne(this)},l.yc=function(t,n,r){return Rie(this,t,n,r)},l.Cc=function(){return this.Ld()},l.$b=function(){throw J(new Fr)},l._b=function(t){return this.xc(t)!=null},l.uc=function(t){return this.Ld().Hc(t)},l.Jd=function(){return new Y$e(this)},l.Kd=function(){return new X$e(this)},l.Fb=function(t){return oan(this,t)},l.Hb=function(){return Cv(this).Hb()},l.dc=function(){return this.gc()==0},l.zc=function(t,n){return BVt()},l.Bc=function(t){throw J(new Fr)},l.Ib=function(){return jfn(this)},l.Ld=function(){return this.e?this.e:this.e=this.Kd()},l.c=null,l.d=null,l.e=null;var k0t;O(qt,"ImmutableMap",714),M(715,714,C7),l._b=function(t){return yze(this,t)},l.uc=function(t){return bGe(this.b,t)},l.Id=function(){return Wnt(new uT(this))},l.Jd=function(){return Wnt(TYe(this.b))},l.Kd=function(){return wd(),new spe(EYe(this.b))},l.Fb=function(t){return vGe(this.b,t)},l.xc=function(t){return c_(this,t)},l.Hb=function(){return Xi(this.b.c)},l.dc=function(){return this.b.c.dc()},l.gc=function(){return this.b.c.gc()},l.Ib=function(){return Qo(this.b.c)},O(qt,"ForwardingImmutableMap",715),M(1974,1973,Oae),l.Bd=function(){return this.Md()},l.Cd=function(){return this.Md()},l.Nc=function(){return new mn(this,1)},l.Fb=function(t){return t===this||this.Md().Fb(t)},l.Hb=function(){return this.Md().Hb()},O(qt,"ForwardingSet",1974),M(1069,1974,Oae,uT),l.Bd=function(){return w8(this.a.b)},l.Cd=function(){return w8(this.a.b)},l.Hc=function(t){if(we(t,42)&&u(t,42).cd()==null)return!1;try{return pGe(w8(this.a.b),t)}catch(n){if(n=ts(n),we(n,205))return!1;throw J(n)}},l.Md=function(){return w8(this.a.b)},l.Qc=function(t){var n;return n=sXe(w8(this.a.b),t),w8(this.a.b).b.gc()=0?"+":"")+(r/60|0),n=ZF(b.Math.abs(r)%60),(Sst(),R0t)[this.q.getDay()]+" "+F0t[this.q.getMonth()]+" "+ZF(this.q.getDate())+" "+ZF(this.q.getHours())+":"+ZF(this.q.getMinutes())+":"+ZF(this.q.getSeconds())+" GMT"+t+n+" "+this.q.getFullYear()};var FG=O(wr,"Date",199);M(1915,199,bht,est),l.a=!1,l.b=0,l.c=0,l.d=0,l.e=0,l.f=0,l.g=!1,l.i=0,l.j=0,l.k=0,l.n=0,l.o=0,l.p=0,O("com.google.gwt.i18n.shared.impl","DateRecord",1915),M(1966,1,{}),l.fe=function(){return null},l.ge=function(){return null},l.he=function(){return null},l.ie=function(){return null},l.je=function(){return null},O(ok,"JSONValue",1966),M(216,1966,{216:1},hg,a6),l.Fb=function(t){return we(t,216)?Swe(this.a,u(t,216).a):!1},l.ee=function(){return iVt},l.Hb=function(){return gwe(this.a)},l.fe=function(){return this},l.Ib=function(){var t,n,r;for(r=new Fl("["),n=0,t=this.a.length;n0&&(r.a+=","),Ec(r,Gm(this,n));return r.a+="]",r.a},O(ok,"JSONArray",216),M(483,1966,{483:1},jx),l.ee=function(){return sVt},l.ge=function(){return this},l.Ib=function(){return Mn(),""+this.a},l.a=!1;var A0t,L0t;O(ok,"JSONBoolean",483),M(985,60,q0,UHe),O(ok,"JSONException",985),M(1023,1966,{},Ae),l.ee=function(){return lVt},l.Ib=function(){return Pu};var M0t;O(ok,"JSONNull",1023),M(258,1966,{258:1},lT),l.Fb=function(t){return we(t,258)?this.a==u(t,258).a:!1},l.ee=function(){return aVt},l.Hb=function(){return i8(this.a)},l.he=function(){return this},l.Ib=function(){return this.a+""},l.a=0,O(ok,"JSONNumber",258),M(183,1966,{183:1},p6,$x),l.Fb=function(t){return we(t,183)?Swe(this.a,u(t,183).a):!1},l.ee=function(){return oVt},l.Hb=function(){return gwe(this.a)},l.ie=function(){return this},l.Ib=function(){var t,n,r,s,o,h,d;for(d=new Fl("{"),t=!0,h=aie(this,Me(mt,Qe,2,0,6,1)),r=h,s=0,o=r.length;s=0?":"+this.c:"")+")"},l.c=0;var K8e=O(oc,"StackTraceElement",310);y0t={3:1,475:1,35:1,2:1};var mt=O(oc,b6e,2);M(107,418,{475:1},bg,ST,Ph),O(oc,"StringBuffer",107),M(100,418,{475:1},Tp,xm,Fl),O(oc,"StringBuilder",100),M(687,73,noe,Bpe),O(oc,"StringIndexOutOfBoundsException",687),M(2043,1,{});var Y8e;M(844,1,{},Bt),l.Kb=function(t){return u(t,78).e},O(oc,"Throwable/lambda$0$Type",844),M(41,60,{3:1,102:1,60:1,78:1,41:1},Fr,pg),O(oc,"UnsupportedOperationException",41),M(240,236,{3:1,35:1,236:1,240:1},kD,Vpe),l.wd=function(t){return out(this,u(t,240))},l.ke=function(){return ry(Gut(this))},l.Fb=function(t){var n;return this===t?!0:we(t,240)?(n=u(t,240),this.e==n.e&&out(this,n)==0):!1},l.Hb=function(){var t;return this.b!=0?this.b:this.a<54?(t=Ou(this.f),this.b=Or(qs(t,-1)),this.b=33*this.b+Or(qs(Np(t,32),-1)),this.b=17*this.b+_s(this.e),this.b):(this.b=17*Hnt(this.c)+_s(this.e),this.b)},l.Ib=function(){return Gut(this)},l.a=0,l.b=0,l.d=0,l.e=0,l.f=0;var N0t,Ab,X8e,Q8e,Z8e,J8e,e7e,t7e,xue=O("java.math","BigDecimal",240);M(91,236,{3:1,35:1,236:1,91:1},b3e,Tg,z3,Z3e,qrt,Ip),l.wd=function(t){return jrt(this,u(t,91))},l.ke=function(){return ry(Lae(this,0))},l.Fb=function(t){return Yye(this,t)},l.Hb=function(){return Hnt(this)},l.Ib=function(){return Lae(this,0)},l.b=-2,l.c=0,l.d=0,l.e=0;var Eue,jG,n7e,Tue,$G,K7,D4=O("java.math","BigInteger",91),P0t,B0t,yk,QC;M(488,1967,ow),l.$b=function(){sl(this)},l._b=function(t){return Il(this,t)},l.uc=function(t){return _nt(this,t,this.g)||_nt(this,t,this.f)},l.vc=function(){return new dg(this)},l.xc=function(t){return er(this,t)},l.zc=function(t,n){return Si(this,t,n)},l.Bc=function(t){return z6(this,t)},l.gc=function(){return MT(this)},O(wr,"AbstractHashMap",488),M(261,H1,Xu,dg),l.$b=function(){this.a.$b()},l.Hc=function(t){return kQe(this,t)},l.Kc=function(){return new ob(this.a)},l.Mc=function(t){var n;return kQe(this,t)?(n=u(t,42).cd(),this.a.Bc(n),!0):!1},l.gc=function(){return this.a.gc()},O(wr,"AbstractHashMap/EntrySet",261),M(262,1,ga,ob),l.Nb=function(t){La(this,t)},l.Pb=function(){return $v(this)},l.Ob=function(){return this.b},l.Qb=function(){wJe(this)},l.b=!1,O(wr,"AbstractHashMap/EntrySetIterator",262),M(417,1,ga,c6),l.Nb=function(t){La(this,t)},l.Ob=function(){return wM(this)},l.Pb=function(){return GYe(this)},l.Qb=function(){Ol(this)},l.b=0,l.c=-1,O(wr,"AbstractList/IteratorImpl",417),M(96,417,r0,Ea),l.Qb=function(){Ol(this)},l.Rb=function(t){Dm(this,t)},l.Sb=function(){return this.b>0},l.Tb=function(){return this.b},l.Ub=function(){return Qn(this.b>0),this.a.Xb(this.c=--this.b)},l.Vb=function(){return this.b-1},l.Wb=function(t){Am(this.c!=-1),this.a._c(this.c,t)},O(wr,"AbstractList/ListIteratorImpl",96),M(219,52,A7,Zd),l.Vc=function(t,n){jm(t,this.b),this.c.Vc(this.a+t,n),++this.b},l.Xb=function(t){return xn(t,this.b),this.c.Xb(this.a+t)},l.$c=function(t){var n;return xn(t,this.b),n=this.c.$c(this.a+t),--this.b,n},l._c=function(t,n){return xn(t,this.b),this.c._c(this.a+t,n)},l.gc=function(){return this.b},l.a=0,l.b=0,O(wr,"AbstractList/SubList",219),M(384,H1,Xu,vm),l.$b=function(){this.a.$b()},l.Hc=function(t){return this.a._b(t)},l.Kc=function(){var t;return t=this.a.vc().Kc(),new nM(t)},l.Mc=function(t){return this.a._b(t)?(this.a.Bc(t),!0):!1},l.gc=function(){return this.a.gc()},O(wr,"AbstractMap/1",384),M(691,1,ga,nM),l.Nb=function(t){La(this,t)},l.Ob=function(){return this.a.Ob()},l.Pb=function(){var t;return t=u(this.a.Pb(),42),t.cd()},l.Qb=function(){this.a.Qb()},O(wr,"AbstractMap/1/1",691),M(226,28,hy,E1),l.$b=function(){this.a.$b()},l.Hc=function(t){return this.a.uc(t)},l.Kc=function(){var t;return t=this.a.vc().Kc(),new T1(t)},l.gc=function(){return this.a.gc()},O(wr,"AbstractMap/2",226),M(294,1,ga,T1),l.Nb=function(t){La(this,t)},l.Ob=function(){return this.a.Ob()},l.Pb=function(){var t;return t=u(this.a.Pb(),42),t.dd()},l.Qb=function(){this.a.Qb()},O(wr,"AbstractMap/2/1",294),M(484,1,{484:1,42:1}),l.Fb=function(t){var n;return we(t,42)?(n=u(t,42),Vc(this.d,n.cd())&&Vc(this.e,n.dd())):!1},l.cd=function(){return this.d},l.dd=function(){return this.e},l.Hb=function(){return F3(this.d)^F3(this.e)},l.ed=function(t){return Rbe(this,t)},l.Ib=function(){return this.d+"="+this.e},O(wr,"AbstractMap/AbstractEntry",484),M(383,484,{484:1,383:1,42:1},OF),O(wr,"AbstractMap/SimpleEntry",383),M(1984,1,aoe),l.Fb=function(t){var n;return we(t,42)?(n=u(t,42),Vc(this.cd(),n.cd())&&Vc(this.dd(),n.dd())):!1},l.Hb=function(){return F3(this.cd())^F3(this.dd())},l.Ib=function(){return this.cd()+"="+this.dd()},O(wr,iht,1984),M(1992,1967,nht),l.tc=function(t){return LZe(this,t)},l._b=function(t){return fne(this,t)},l.vc=function(){return new k(this)},l.xc=function(t){var n;return n=t,hc(bye(this,n))},l.ec=function(){return new m(this)},O(wr,"AbstractNavigableMap",1992),M(739,H1,Xu,k),l.Hc=function(t){return we(t,42)&&LZe(this.b,u(t,42))},l.Kc=function(){return new o_(this.b)},l.Mc=function(t){var n;return we(t,42)?(n=u(t,42),bJe(this.b,n)):!1},l.gc=function(){return this.b.c},O(wr,"AbstractNavigableMap/EntrySet",739),M(493,H1,g6e,m),l.Nc=function(){return new DF(this)},l.$b=function(){ET(this.a)},l.Hc=function(t){return fne(this.a,t)},l.Kc=function(){var t;return t=new o_(new i_(this.a).b),new g(t)},l.Mc=function(t){return fne(this.a,t)?(k_(this.a,t),!0):!1},l.gc=function(){return this.a.c},O(wr,"AbstractNavigableMap/NavigableKeySet",493),M(494,1,ga,g),l.Nb=function(t){La(this,t)},l.Ob=function(){return wM(this.a.a)},l.Pb=function(){var t;return t=dj(this.a),t.cd()},l.Qb=function(){mWe(this.a)},O(wr,"AbstractNavigableMap/NavigableKeySet/1",494),M(2004,28,hy),l.Fc=function(t){return S8(l7(this,t)),!0},l.Gc=function(t){return Sn(t),kj(t!=this,"Can't add a queue to itself"),no(this,t)},l.$b=function(){for(;Kre(this)!=null;);},O(wr,"AbstractQueue",2004),M(302,28,{4:1,20:1,28:1,14:1},L3,UXe),l.Fc=function(t){return Pwe(this,t),!0},l.$b=function(){Hwe(this)},l.Hc=function(t){return Ktt(new y_(this),t)},l.dc=function(){return TT(this)},l.Kc=function(){return new y_(this)},l.Mc=function(t){return yen(new y_(this),t)},l.gc=function(){return this.c-this.b&this.a.length-1},l.Nc=function(){return new mn(this,272)},l.Qc=function(t){var n;return n=this.c-this.b&this.a.length-1,t.lengthn&&cs(t,n,null),t},l.b=0,l.c=0,O(wr,"ArrayDeque",302),M(446,1,ga,y_),l.Nb=function(t){La(this,t)},l.Ob=function(){return this.a!=this.b},l.Pb=function(){return gH(this)},l.Qb=function(){Uet(this)},l.a=0,l.b=0,l.c=-1,O(wr,"ArrayDeque/IteratorImpl",446),M(12,52,mht,st,su,Uu),l.Vc=function(t,n){Om(this,t,n)},l.Fc=function(t){return it(this,t)},l.Wc=function(t,n){return xye(this,t,n)},l.Gc=function(t){return Rs(this,t)},l.$b=function(){this.c=Me(Yn,yt,1,0,5,1)},l.Hc=function(t){return Yo(this,t,0)!=-1},l.Jc=function(t){Mu(this,t)},l.Xb=function(t){return St(this,t)},l.Xc=function(t){return Yo(this,t,0)},l.dc=function(){return this.c.length==0},l.Kc=function(){return new C(this)},l.$c=function(t){return Eg(this,t)},l.Mc=function(t){return Au(this,t)},l.Ud=function(t,n){VXe(this,t,n)},l._c=function(t,n){return gh(this,t,n)},l.gc=function(){return this.c.length},l.ad=function(t){aa(this,t)},l.Pc=function(){return tne(this)},l.Qc=function(t){return j1(this,t)};var i3n=O(wr,"ArrayList",12);M(7,1,ga,C),l.Nb=function(t){La(this,t)},l.Ob=function(){return nc(this)},l.Pb=function(){return Y(this)},l.Qb=function(){b_(this)},l.a=0,l.b=-1,O(wr,"ArrayList/1",7),M(2013,b.Function,{},he),l.te=function(t,n){return Fs(t,n)},M(154,52,yht,Al),l.Hc=function(t){return Ket(this,t)!=-1},l.Jc=function(t){var n,r,s,o;for(Sn(t),r=this.a,s=0,o=r.length;s>>0,t.toString(16)))},l.f=0,l.i=Ds;var VG=O(o0,"CNode",57);M(814,1,{},bpe),O(o0,"CNode/CNodeBuilder",814);var Z0t;M(1525,1,{},Er),l.Oe=function(t,n){return 0},l.Pe=function(t,n){return 0},O(o0,Aht,1525),M(1790,1,{},br),l.Le=function(t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W,X;for(_=gs,s=new C(t.a.b);s.as.d.c||s.d.c==h.d.c&&s.d.b0?t+this.n.d+this.n.a:0},l.Se=function(){var t,n,r,s,o;if(o=0,this.e)this.b?o=this.b.a:this.a[1][1]&&(o=this.a[1][1].Se());else if(this.g)o=qye(this,wse(this,null,!0));else for(n=(n1(),ie(re(Ey,1),tt,232,0,[pc,lu,bc])),r=0,s=n.length;r0?o+this.n.b+this.n.c:0},l.Te=function(){var t,n,r,s,o;if(this.g)for(t=wse(this,null,!1),r=(n1(),ie(re(Ey,1),tt,232,0,[pc,lu,bc])),s=0,o=r.length;s0&&(s[0]+=this.d,r-=s[0]),s[2]>0&&(s[2]+=this.d,r-=s[2]),this.c.a=b.Math.max(0,r),this.c.d=n.d+t.d+(this.c.a-r)/2,s[1]=b.Math.max(s[1],r),Kwe(this,lu,n.d+t.d+s[0]-(s[1]-r)/2,s)},l.b=null,l.d=0,l.e=!1,l.f=!1,l.g=!1;var Due=0,UG=0;O(wb,"GridContainerCell",1473),M(461,22,{3:1,35:1,22:1,461:1},pte);var a2,Nd,Af,cgt=Gr(wb,"HorizontalLabelAlignment",461,Wr,Pen,mYt),ugt;M(306,212,{212:1,306:1},fXe,yet,uXe),l.Re=function(){return XWe(this)},l.Se=function(){return kve(this)},l.a=0,l.c=!1;var g3n=O(wb,"LabelCell",306);M(244,326,{212:1,326:1,244:1},W_),l.Re=function(){return oI(this)},l.Se=function(){return cI(this)},l.Te=function(){uae(this)},l.Ue=function(){lae(this)},l.b=0,l.c=0,l.d=!1,O(wb,"StripContainerCell",244),M(1626,1,vi,Ms),l.Mb=function(t){return IVt(u(t,212))},O(wb,"StripContainerCell/lambda$0$Type",1626),M(1627,1,{},Pa),l.Fe=function(t){return u(t,212).Se()},O(wb,"StripContainerCell/lambda$1$Type",1627),M(1628,1,vi,Ta),l.Mb=function(t){return OVt(u(t,212))},O(wb,"StripContainerCell/lambda$2$Type",1628),M(1629,1,{},_a),l.Fe=function(t){return u(t,212).Re()},O(wb,"StripContainerCell/lambda$3$Type",1629),M(462,22,{3:1,35:1,22:1,462:1},bte);var Lf,o2,u1,lgt=Gr(wb,"VerticalLabelAlignment",462,Wr,Ben,yYt),hgt;M(789,1,{},i6e),l.c=0,l.d=0,l.k=0,l.s=0,l.t=0,l.v=!1,l.w=0,l.D=!1,O(Iz,"NodeContext",789),M(1471,1,ji,ka),l.ue=function(t,n){return fVe(u(t,61),u(n,61))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Iz,"NodeContext/0methodref$comparePortSides$Type",1471),M(1472,1,ji,Qi),l.ue=function(t,n){return afn(u(t,111),u(n,111))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Iz,"NodeContext/1methodref$comparePortContexts$Type",1472),M(159,22,{3:1,35:1,22:1,159:1},vh);var fgt,dgt,ggt,pgt,bgt,vgt,wgt,mgt,ygt,kgt,xgt,Egt,Tgt,_gt,Cgt,Sgt,Agt,Lgt,Mgt,Dgt,Igt,Iue,Ogt=Gr(Iz,"NodeLabelLocation",159,Wr,Xie,kYt),Ngt;M(111,1,{111:1},Wat),l.a=!1,O(Iz,"PortContext",111),M(1476,1,Un,ea),l.td=function(t){Dze(u(t,306))},O(PI,Hht,1476),M(1477,1,vi,Ca),l.Mb=function(t){return!!u(t,111).c},O(PI,zht,1477),M(1478,1,Un,Sa),l.td=function(t){Dze(u(t,111).c)},O(PI,"LabelPlacer/lambda$2$Type",1478);var F7e;M(1475,1,Un,cg),l.td=function(t){Mm(),fVt(u(t,111))},O(PI,"NodeLabelAndSizeUtilities/lambda$0$Type",1475),M(790,1,Un,eve),l.td=function(t){TUt(this.b,this.c,this.a,u(t,181))},l.a=!1,l.c=!1,O(PI,"NodeLabelCellCreator/lambda$0$Type",790),M(1474,1,Un,fn),l.td=function(t){pVt(this.a,u(t,181))},O(PI,"PortContextCreator/lambda$0$Type",1474);var WG;M(1829,1,{},Gc),O(I7,"GreedyRectangleStripOverlapRemover",1829),M(1830,1,ji,Ka),l.ue=function(t,n){return nKt(u(t,222),u(n,222))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(I7,"GreedyRectangleStripOverlapRemover/0methodref$compareByYCoordinate$Type",1830),M(1786,1,{},uHe),l.a=5,l.e=0,O(I7,"RectangleStripOverlapRemover",1786),M(1787,1,ji,Es),l.ue=function(t,n){return rKt(u(t,222),u(n,222))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(I7,"RectangleStripOverlapRemover/0methodref$compareLeftRectangleBorders$Type",1787),M(1789,1,ji,lp),l.ue=function(t,n){return SZt(u(t,222),u(n,222))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(I7,"RectangleStripOverlapRemover/1methodref$compareRightRectangleBorders$Type",1789),M(406,22,{3:1,35:1,22:1,406:1},BF);var iO,Oue,Nue,sO,Pgt=Gr(I7,"RectangleStripOverlapRemover/OverlapRemovalDirection",406,Wr,Ptn,xYt),Bgt;M(222,1,{222:1},Lne),O(I7,"RectangleStripOverlapRemover/RectangleNode",222),M(1788,1,Un,vr),l.td=function(t){Dun(this.a,u(t,222))},O(I7,"RectangleStripOverlapRemover/lambda$1$Type",1788),M(1304,1,ji,sd),l.ue=function(t,n){return Rvn(u(t,167),u(n,167))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Cd,"PolyominoCompactor/CornerCasesGreaterThanRestComparator",1304),M(1307,1,{},sh),l.Kb=function(t){return u(t,324).a},O(Cd,"PolyominoCompactor/CornerCasesGreaterThanRestComparator/lambda$0$Type",1307),M(1308,1,vi,Ai),l.Mb=function(t){return u(t,323).a},O(Cd,"PolyominoCompactor/CornerCasesGreaterThanRestComparator/lambda$1$Type",1308),M(1309,1,vi,nn),l.Mb=function(t){return u(t,323).a},O(Cd,"PolyominoCompactor/CornerCasesGreaterThanRestComparator/lambda$2$Type",1309),M(1302,1,ji,Tr),l.ue=function(t,n){return v2n(u(t,167),u(n,167))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Cd,"PolyominoCompactor/MinNumOfExtensionDirectionsComparator",1302),M(1305,1,{},Dh),l.Kb=function(t){return u(t,324).a},O(Cd,"PolyominoCompactor/MinNumOfExtensionDirectionsComparator/lambda$0$Type",1305),M(767,1,ji,ai),l.ue=function(t,n){return msn(u(t,167),u(n,167))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Cd,"PolyominoCompactor/MinNumOfExtensionsComparator",767),M(1300,1,ji,Ns),l.ue=function(t,n){return Ain(u(t,321),u(n,321))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Cd,"PolyominoCompactor/MinPerimeterComparator",1300),M(1301,1,ji,mc),l.ue=function(t,n){return iun(u(t,321),u(n,321))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Cd,"PolyominoCompactor/MinPerimeterComparatorWithShape",1301),M(1303,1,ji,yu),l.ue=function(t,n){return $2n(u(t,167),u(n,167))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Cd,"PolyominoCompactor/SingleExtensionSideGreaterThanRestComparator",1303),M(1306,1,{},Mo),l.Kb=function(t){return u(t,324).a},O(Cd,"PolyominoCompactor/SingleExtensionSideGreaterThanRestComparator/lambda$0$Type",1306),M(777,1,{},o2e),l.Ce=function(t,n){return Dtn(this,u(t,46),u(n,167))},O(Cd,"SuccessorCombination",777),M(644,1,{},ku),l.Ce=function(t,n){var r;return ydn((r=u(t,46),u(n,167),r))},O(Cd,"SuccessorJitter",644),M(643,1,{},Ih),l.Ce=function(t,n){var r;return cpn((r=u(t,46),u(n,167),r))},O(Cd,"SuccessorLineByLine",643),M(568,1,{},qf),l.Ce=function(t,n){var r;return k0n((r=u(t,46),u(n,167),r))},O(Cd,"SuccessorManhattan",568),M(1356,1,{},lx),l.Ce=function(t,n){var r;return Ign((r=u(t,46),u(n,167),r))},O(Cd,"SuccessorMaxNormWindingInMathPosSense",1356),M(400,1,{},gr),l.Ce=function(t,n){return Yve(this,t,n)},l.c=!1,l.d=!1,l.e=!1,l.f=!1,O(Cd,"SuccessorQuadrantsGeneric",400),M(1357,1,{},ad),l.Kb=function(t){return u(t,324).a},O(Cd,"SuccessorQuadrantsGeneric/lambda$0$Type",1357),M(323,22,{3:1,35:1,22:1,323:1},PF),l.a=!1;var aO,oO,cO,uO,Rgt=Gr(Nz,P6e,323,Wr,Ftn,EYt),Fgt;M(1298,1,{}),l.Ib=function(){var t,n,r,s,o,h;for(r=" ",t=ct(0),o=0;o=0?"b"+t+"["+Sre(this.a)+"]":"b["+Sre(this.a)+"]"):"b_"+xv(this)},O(RI,"FBendpoint",559),M(282,134,{3:1,282:1,94:1,134:1},UUe),l.Ib=function(){return Sre(this)},O(RI,"FEdge",282),M(231,134,{3:1,231:1,94:1,134:1},k$);var b3n=O(RI,"FGraph",231);M(447,357,{3:1,447:1,357:1,94:1,134:1},YQe),l.Ib=function(){return this.b==null||this.b.length==0?"l["+Sre(this.a)+"]":"l_"+this.b},O(RI,"FLabel",447),M(144,357,{3:1,144:1,357:1,94:1,134:1},sYe),l.Ib=function(){return Cwe(this)},l.b=0,O(RI,"FNode",144),M(2003,1,{}),l.bf=function(t){R5e(this,t)},l.cf=function(){Mit(this)},l.d=0,O(V6e,"AbstractForceModel",2003),M(631,2003,{631:1},$tt),l.af=function(t,n){var r,s,o,h,d;return Cat(this.f,t,n),o=da(fc(n.d),t.d),d=b.Math.sqrt(o.a*o.a+o.b*o.b),s=b.Math.max(0,d-w_(t.e)/2-w_(n.e)/2),r=bnt(this.e,t,n),r>0?h=-TZt(s,this.c)*r:h=bKt(s,this.b)*u(K(t,(a1(),Q7)),19).a,bd(o,h/d),o},l.bf=function(t){R5e(this,t),this.a=u(K(t,(a1(),JG)),19).a,this.c=Ue(ft(K(t,eq))),this.b=Ue(ft(K(t,Hue)))},l.df=function(t){return t0&&(h-=AVt(s,this.a)*r),bd(o,h*this.b/d),o},l.bf=function(t){var n,r,s,o,h,d,v;for(R5e(this,t),this.b=Ue(ft(K(t,(a1(),zue)))),this.c=this.b/u(K(t,JG),19).a,s=t.e.c.length,h=0,o=0,v=new C(t.e);v.a0},l.a=0,l.b=0,l.c=0,O(V6e,"FruchtermanReingoldModel",632),M(849,1,zh,DJ),l.Qe=function(t){en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Rz),""),"Force Model"),"Determines the model for force calculation."),W7e),(Ng(),vs)),K7e),rn((i1(),Fn))))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,U6e),""),"Iterations"),"The number of iterations on the force model."),ct(300)),Cc),Za),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,W6e),""),"Repulsive Power"),"Determines how many bend points are added to the edge; such bend points are regarded as repelling particles in the force model"),ct(0)),Cc),Za),rn(Fd)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Aoe),""),"FR Temperature"),"The temperature is used as a scaling factor for particle displacements."),Sd),qo),ma),rn(Fn)))),va(t,Aoe,Rz,ipt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Loe),""),"Eades Repulsion"),"Factor for repulsive forces in Eades' model."),5),qo),ma),rn(Fn)))),va(t,Loe,Rz,tpt),Slt((new rT,t))};var Zgt,Jgt,W7e,ept,tpt,npt,rpt,ipt;O(TC,"ForceMetaDataProvider",849),M(424,22,{3:1,35:1,22:1,424:1},h2e);var $ue,ZG,K7e=Gr(TC,"ForceModelStrategy",424,Wr,len,CYt),spt;M(988,1,zh,rT),l.Qe=function(t){Slt(t)};var apt,opt,Y7e,JG,X7e,cpt,upt,lpt,Q7e,hpt,Z7e,J7e,fpt,Q7,dpt,Hue,eEe,gpt,ppt,eq,zue;O(TC,"ForceOptions",988),M(989,1,{},N5),l.$e=function(){var t;return t=new dpe,t},l._e=function(t){},O(TC,"ForceOptions/ForceFactory",989);var fO,eS,kk,tq;M(850,1,zh,IJ),l.Qe=function(t){en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Y6e),""),"Fixed Position"),"Prevent that the node is moved by the layout algorithm."),(Mn(),!1)),(Ng(),za)),Us),rn((i1(),ua))))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,X6e),""),"Desired Edge Length"),"Either specified for parent nodes or for individual edges, where the latter takes higher precedence."),100),qo),ma),Ui(Fn,ie(re(Ug,1),tt,175,0,[Fd]))))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Q6e),""),"Layout Dimension"),"Dimensions that are permitted to be altered during layout."),tEe),vs),cEe),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Z6e),""),"Stress Epsilon"),"Termination criterion for the iterative process."),Sd),qo),ma),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,J6e),""),"Iteration Limit"),"Maximum number of performed iterations. Takes higher precedence than 'epsilon'."),ct(Ei)),Cc),Za),rn(Fn)))),hlt((new OJ,t))};var bpt,vpt,tEe,wpt,mpt,ypt;O(TC,"StressMetaDataProvider",850),M(992,1,zh,OJ),l.Qe=function(t){hlt(t)};var nq,nEe,rEe,iEe,sEe,aEe,kpt,xpt,Ept,Tpt,oEe,_pt;O(TC,"StressOptions",992),M(993,1,{},ah),l.$e=function(){var t;return t=new WUe,t},l._e=function(t){},O(TC,"StressOptions/StressFactory",993),M(1128,209,mb,WUe),l.Ze=function(t,n){var r,s,o,h,d;for(kr(n,eft,1),It(Mt(Ft(t,(ZD(),sEe))))?It(Mt(Ft(t,oEe)))||i$((r=new sr((Tm(),new ym(t))),r)):Iot(new dpe,t,Kc(n,1)),o=cnt(t),s=kut(this.a,o),d=s.Kc();d.Ob();)h=u(d.Pb(),231),!(h.e.c.length<=1)&&(Pvn(this.b,h),d0n(this.b),Mu(h.d,new od));o=Nlt(s),Dlt(o),ur(n)},O($z,"StressLayoutProvider",1128),M(1129,1,Un,od),l.td=function(t){q5e(u(t,447))},O($z,"StressLayoutProvider/lambda$0$Type",1129),M(990,1,{},nHe),l.c=0,l.e=0,l.g=0,O($z,"StressMajorization",990),M(379,22,{3:1,35:1,22:1,379:1},vte);var Gue,que,Vue,cEe=Gr($z,"StressMajorization/Dimension",379,Wr,Fen,SYt),Cpt;M(991,1,ji,Li),l.ue=function(t,n){return rYt(this.a,u(t,144),u(n,144))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O($z,"StressMajorization/lambda$0$Type",991),M(1229,1,{},cQe),O(pk,"ElkLayered",1229),M(1230,1,Un,P5),l.td=function(t){gdn(u(t,37))},O(pk,"ElkLayered/lambda$0$Type",1230),M(1231,1,Un,wi),l.td=function(t){iYt(this.a,u(t,37))},O(pk,"ElkLayered/lambda$1$Type",1231),M(1263,1,{},NVe);var Spt,Apt,Lpt;O(pk,"GraphConfigurator",1263),M(759,1,Un,Ts),l.td=function(t){Fst(this.a,u(t,10))},O(pk,"GraphConfigurator/lambda$0$Type",759),M(760,1,{},B5),l.Kb=function(t){return H3e(),new vn(null,new mn(u(t,29).a,16))},O(pk,"GraphConfigurator/lambda$1$Type",760),M(761,1,Un,Yi),l.td=function(t){Fst(this.a,u(t,10))},O(pk,"GraphConfigurator/lambda$2$Type",761),M(1127,209,mb,sHe),l.Ze=function(t,n){var r;r=nvn(new hHe,t),je(Ft(t,(pt(),Iy)))===je((F0(),Wg))?Non(this.a,r,n):Mdn(this.a,r,n),Clt(new PJ,r)},O(pk,"LayeredLayoutProvider",1127),M(356,22,{3:1,35:1,22:1,356:1},yM);var Pd,c2,bu,Zc,Go,uEe=Gr(pk,"LayeredPhases",356,Wr,knn,AYt),Mpt;M(1651,1,{},Yet),l.i=0;var Dpt;O($I,"ComponentsToCGraphTransformer",1651);var Ipt;M(1652,1,{},y9),l.ef=function(t,n){return b.Math.min(t.a!=null?Ue(t.a):t.c.i,n.a!=null?Ue(n.a):n.c.i)},l.ff=function(t,n){return b.Math.min(t.a!=null?Ue(t.a):t.c.i,n.a!=null?Ue(n.a):n.c.i)},O($I,"ComponentsToCGraphTransformer/1",1652),M(81,1,{81:1}),l.i=0,l.k=!0,l.o=Ds;var Uue=O(SC,"CNode",81);M(460,81,{460:1,81:1},fbe,d3e),l.Ib=function(){return""},O($I,"ComponentsToCGraphTransformer/CRectNode",460),M(1623,1,{},vL);var Wue,Kue;O($I,"OneDimensionalComponentsCompaction",1623),M(1624,1,{},v1),l.Kb=function(t){return Len(u(t,46))},l.Fb=function(t){return this===t},O($I,"OneDimensionalComponentsCompaction/lambda$0$Type",1624),M(1625,1,{},dp),l.Kb=function(t){return zon(u(t,46))},l.Fb=function(t){return this===t},O($I,"OneDimensionalComponentsCompaction/lambda$1$Type",1625),M(1654,1,{},iYe),O(SC,"CGraph",1654),M(189,1,{189:1},Wie),l.b=0,l.c=0,l.e=0,l.g=!0,l.i=Ds,O(SC,"CGroup",189),M(1653,1,{},om),l.ef=function(t,n){return b.Math.max(t.a!=null?Ue(t.a):t.c.i,n.a!=null?Ue(n.a):n.c.i)},l.ff=function(t,n){return b.Math.max(t.a!=null?Ue(t.a):t.c.i,n.a!=null?Ue(n.a):n.c.i)},O(SC,Aht,1653),M(1655,1,{},jat),l.d=!1;var Opt,Yue=O(SC,Dht,1655);M(1656,1,{},yc),l.Kb=function(t){return Zpe(),Mn(),u(u(t,46).a,81).d.e!=0},l.Fb=function(t){return this===t},O(SC,Iht,1656),M(823,1,{},xve),l.a=!1,l.b=!1,l.c=!1,l.d=!1,O(SC,Oht,823),M(1825,1,{},xKe),O(Hz,Nht,1825);var dO=ss(kb,Cht);M(1826,1,{369:1},JYe),l.Ke=function(t){Epn(this,u(t,466))},O(Hz,Pht,1826),M(1827,1,ji,hx),l.ue=function(t,n){return EJt(u(t,81),u(n,81))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Hz,Bht,1827),M(466,1,{466:1},d2e),l.a=!1,O(Hz,Rht,466),M(1828,1,ji,Vo),l.ue=function(t,n){return Pln(u(t,466),u(n,466))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Hz,Fht,1828),M(140,1,{140:1},r8,vve),l.Fb=function(t){var n;return t==null||v3n!=pl(t)?!1:(n=u(t,140),Vc(this.c,n.c)&&Vc(this.d,n.d))},l.Hb=function(){return fH(ie(re(Yn,1),yt,1,5,[this.c,this.d]))},l.Ib=function(){return"("+this.c+io+this.d+(this.a?"cx":"")+this.b+")"},l.a=!0,l.c=0,l.d=0;var v3n=O(kb,"Point",140);M(405,22,{3:1,35:1,22:1,405:1},RF);var vw,Ty,O4,_y,Npt=Gr(kb,"Point/Quadrant",405,Wr,jtn,LYt),Ppt;M(1642,1,{},aHe),l.b=null,l.c=null,l.d=null,l.e=null,l.f=null;var Bpt,Rpt,Fpt,jpt,$pt;O(kb,"RectilinearConvexHull",1642),M(574,1,{369:1},IH),l.Ke=function(t){xrn(this,u(t,140))},l.b=0;var lEe;O(kb,"RectilinearConvexHull/MaximalElementsEventHandler",574),M(1644,1,ji,am),l.ue=function(t,n){return fJt(ft(t),ft(n))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(kb,"RectilinearConvexHull/MaximalElementsEventHandler/lambda$0$Type",1644),M(1643,1,{369:1},vet),l.Ke=function(t){Bgn(this,u(t,140))},l.a=0,l.b=null,l.c=null,l.d=null,l.e=null,O(kb,"RectilinearConvexHull/RectangleEventHandler",1643),M(1645,1,ji,ev),l.ue=function(t,n){return ptn(u(t,140),u(n,140))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(kb,"RectilinearConvexHull/lambda$0$Type",1645),M(1646,1,ji,cd),l.ue=function(t,n){return btn(u(t,140),u(n,140))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(kb,"RectilinearConvexHull/lambda$1$Type",1646),M(1647,1,ji,fx),l.ue=function(t,n){return wtn(u(t,140),u(n,140))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(kb,"RectilinearConvexHull/lambda$2$Type",1647),M(1648,1,ji,oh),l.ue=function(t,n){return vtn(u(t,140),u(n,140))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(kb,"RectilinearConvexHull/lambda$3$Type",1648),M(1649,1,ji,QK),l.ue=function(t,n){return yfn(u(t,140),u(n,140))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(kb,"RectilinearConvexHull/lambda$4$Type",1649),M(1650,1,{},MXe),O(kb,"Scanline",1650),M(2005,1,{}),O(Ad,"AbstractGraphPlacer",2005),M(325,1,{325:1},xUe),l.mf=function(t){return this.nf(t)?(sn(this.b,u(K(t,(et(),Sy)),21),t),!0):!1},l.nf=function(t){var n,r,s,o;for(n=u(K(t,(et(),Sy)),21),o=u(Ii($i,n),21),s=o.Kc();s.Ob();)if(r=u(s.Pb(),21),!u(Ii(this.b,r),15).dc())return!1;return!0};var $i;O(Ad,"ComponentGroup",325),M(765,2005,{},vpe),l.of=function(t){var n,r;for(r=new C(this.a);r.aq&&(nt=0,bt+=z+o,z=0),le=d.c,cC(d,nt+le.a,bt+le.b),Zf(le),r=b.Math.max(r,nt+Ee.a),z=b.Math.max(z,Ee.b),nt+=Ee.a+o;if(n.f.a=r,n.f.b=bt+z,It(Mt(K(h,zq)))){for(s=new k9,l6e(s,t,o),P=t.Kc();P.Ob();)L=u(P.Pb(),37),Ni(Zf(L.c),s.e);Ni(Zf(n.f),s.a)}lme(n,t)},O(Ad,"SimpleRowGraphPlacer",1291),M(1292,1,ji,Vf),l.ue=function(t,n){return wsn(u(t,37),u(n,37))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Ad,"SimpleRowGraphPlacer/1",1292);var zpt;M(1262,1,_d,cm),l.Lb=function(t){var n;return n=u(K(u(t,243).b,(pt(),Fo)),74),!!n&&n.b!=0},l.Fb=function(t){return this===t},l.Mb=function(t){var n;return n=u(K(u(t,243).b,(pt(),Fo)),74),!!n&&n.b!=0},O(zz,"CompoundGraphPostprocessor/1",1262),M(1261,1,ps,fHe),l.pf=function(t,n){dit(this,u(t,37),n)},O(zz,"CompoundGraphPreprocessor",1261),M(441,1,{441:1},ert),l.c=!1,O(zz,"CompoundGraphPreprocessor/ExternalPort",441),M(243,1,{243:1},mj),l.Ib=function(){return nne(this.c)+":"+Pat(this.b)},O(zz,"CrossHierarchyEdge",243),M(763,1,ji,Di),l.ue=function(t,n){return oln(this,u(t,243),u(n,243))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(zz,"CrossHierarchyEdgeComparator",763),M(299,134,{3:1,299:1,94:1,134:1}),l.p=0,O(uu,"LGraphElement",299),M(17,299,{3:1,17:1,299:1,94:1,134:1},Iv),l.Ib=function(){return Pat(this)};var Que=O(uu,"LEdge",17);M(37,299,{3:1,20:1,37:1,299:1,94:1,134:1},Ime),l.Jc=function(t){Da(this,t)},l.Kc=function(){return new C(this.b)},l.Ib=function(){return this.b.c.length==0?"G-unlayered"+Yp(this.a):this.a.c.length==0?"G-layered"+Yp(this.b):"G[layerless"+Yp(this.a)+", layers"+Yp(this.b)+"]"};var Gpt=O(uu,"LGraph",37),qpt;M(657,1,{}),l.qf=function(){return this.e.n},l.We=function(t){return K(this.e,t)},l.rf=function(){return this.e.o},l.sf=function(){return this.e.p},l.Xe=function(t){return ta(this.e,t)},l.tf=function(t){this.e.n.a=t.a,this.e.n.b=t.b},l.uf=function(t){this.e.o.a=t.a,this.e.o.b=t.b},l.vf=function(t){this.e.p=t},O(uu,"LGraphAdapters/AbstractLShapeAdapter",657),M(577,1,{839:1},es),l.wf=function(){var t,n;if(!this.b)for(this.b=Wd(this.a.b.c.length),n=new C(this.a.b);n.a0&&$nt((zr(n-1,t.length),t.charCodeAt(n-1)),aft);)--n;if(h> ",t),zH(r)),Yr(Ec((t.a+="[",t),r.i),"]")),t.a},l.c=!0,l.d=!1;var pEe,bEe,vEe,wEe,mEe,yEe,Upt=O(uu,"LPort",11);M(397,1,i0,sa),l.Jc=function(t){Da(this,t)},l.Kc=function(){var t;return t=new C(this.a.e),new Ks(t)},O(uu,"LPort/1",397),M(1290,1,ga,Ks),l.Nb=function(t){La(this,t)},l.Pb=function(){return u(Y(this.a),17).c},l.Ob=function(){return nc(this.a)},l.Qb=function(){b_(this.a)},O(uu,"LPort/1/1",1290),M(359,1,i0,Ar),l.Jc=function(t){Da(this,t)},l.Kc=function(){var t;return t=new C(this.a.g),new We(t)},O(uu,"LPort/2",359),M(762,1,ga,We),l.Nb=function(t){La(this,t)},l.Pb=function(){return u(Y(this.a),17).d},l.Ob=function(){return nc(this.a)},l.Qb=function(){b_(this.a)},O(uu,"LPort/2/1",762),M(1283,1,i0,JGe),l.Jc=function(t){Da(this,t)},l.Kc=function(){return new N1(this)},O(uu,"LPort/CombineIter",1283),M(201,1,ga,N1),l.Nb=function(t){La(this,t)},l.Qb=function(){Eze()},l.Ob=function(){return s_(this)},l.Pb=function(){return nc(this.a)?Y(this.a):Y(this.b)},O(uu,"LPort/CombineIter/1",201),M(1285,1,_d,gp),l.Lb=function(t){return NKe(t)},l.Fb=function(t){return this===t},l.Mb=function(t){return Ku(),u(t,11).e.c.length!=0},O(uu,"LPort/lambda$0$Type",1285),M(1284,1,_d,um),l.Lb=function(t){return PKe(t)},l.Fb=function(t){return this===t},l.Mb=function(t){return Ku(),u(t,11).g.c.length!=0},O(uu,"LPort/lambda$1$Type",1284),M(1286,1,_d,JK),l.Lb=function(t){return Ku(),u(t,11).j==(ht(),An)},l.Fb=function(t){return this===t},l.Mb=function(t){return Ku(),u(t,11).j==(ht(),An)},O(uu,"LPort/lambda$2$Type",1286),M(1287,1,_d,R2),l.Lb=function(t){return Ku(),u(t,11).j==(ht(),$n)},l.Fb=function(t){return this===t},l.Mb=function(t){return Ku(),u(t,11).j==(ht(),$n)},O(uu,"LPort/lambda$3$Type",1287),M(1288,1,_d,eY),l.Lb=function(t){return Ku(),u(t,11).j==(ht(),xr)},l.Fb=function(t){return this===t},l.Mb=function(t){return Ku(),u(t,11).j==(ht(),xr)},O(uu,"LPort/lambda$4$Type",1288),M(1289,1,_d,tY),l.Lb=function(t){return Ku(),u(t,11).j==(ht(),Dn)},l.Fb=function(t){return this===t},l.Mb=function(t){return Ku(),u(t,11).j==(ht(),Dn)},O(uu,"LPort/lambda$5$Type",1289),M(29,299,{3:1,20:1,299:1,29:1,94:1,134:1},Bh),l.Jc=function(t){Da(this,t)},l.Kc=function(){return new C(this.a)},l.Ib=function(){return"L_"+Yo(this.b.b,this,0)+Yp(this.a)},O(uu,"Layer",29),M(1342,1,{},hHe),O(Rg,lft,1342),M(1346,1,{},R5),l.Kb=function(t){return zo(u(t,82))},O(Rg,"ElkGraphImporter/0methodref$connectableShapeToNode$Type",1346),M(1349,1,{},x9),l.Kb=function(t){return zo(u(t,82))},O(Rg,"ElkGraphImporter/1methodref$connectableShapeToNode$Type",1349),M(1343,1,Un,On),l.td=function(t){Yat(this.a,u(t,118))},O(Rg,hft,1343),M(1344,1,Un,Ir),l.td=function(t){Yat(this.a,u(t,118))},O(Rg,fft,1344),M(1345,1,{},VP),l.Kb=function(t){return new vn(null,new mn(oJt(u(t,79)),16))},O(Rg,dft,1345),M(1347,1,vi,ar),l.Mb=function(t){return cWt(this.a,u(t,33))},O(Rg,gft,1347),M(1348,1,{},dx),l.Kb=function(t){return new vn(null,new mn(cJt(u(t,79)),16))},O(Rg,"ElkGraphImporter/lambda$5$Type",1348),M(1350,1,vi,or),l.Mb=function(t){return uWt(this.a,u(t,33))},O(Rg,"ElkGraphImporter/lambda$7$Type",1350),M(1351,1,vi,nY),l.Mb=function(t){return _Jt(u(t,79))},O(Rg,"ElkGraphImporter/lambda$8$Type",1351),M(1278,1,{},PJ);var Wpt;O(Rg,"ElkGraphLayoutTransferrer",1278),M(1279,1,vi,qa),l.Mb=function(t){return QKt(this.a,u(t,17))},O(Rg,"ElkGraphLayoutTransferrer/lambda$0$Type",1279),M(1280,1,Un,qr),l.td=function(t){bM(),it(this.a,u(t,17))},O(Rg,"ElkGraphLayoutTransferrer/lambda$1$Type",1280),M(1281,1,vi,is),l.Mb=function(t){return BKt(this.a,u(t,17))},O(Rg,"ElkGraphLayoutTransferrer/lambda$2$Type",1281),M(1282,1,Un,Uo),l.td=function(t){bM(),it(this.a,u(t,17))},O(Rg,"ElkGraphLayoutTransferrer/lambda$3$Type",1282),M(1485,1,ps,gx),l.pf=function(t,n){Fin(u(t,37),n)},O(Pn,"CommentNodeMarginCalculator",1485),M(1486,1,{},rY),l.Kb=function(t){return new vn(null,new mn(u(t,29).a,16))},O(Pn,"CommentNodeMarginCalculator/lambda$0$Type",1486),M(1487,1,Un,iY),l.td=function(t){wvn(u(t,10))},O(Pn,"CommentNodeMarginCalculator/lambda$1$Type",1487),M(1488,1,ps,sY),l.pf=function(t,n){Dpn(u(t,37),n)},O(Pn,"CommentPostprocessor",1488),M(1489,1,ps,aY),l.pf=function(t,n){Fmn(u(t,37),n)},O(Pn,"CommentPreprocessor",1489),M(1490,1,ps,oY),l.pf=function(t,n){egn(u(t,37),n)},O(Pn,"ConstraintsPostprocessor",1490),M(1491,1,ps,cY),l.pf=function(t,n){osn(u(t,37),n)},O(Pn,"EdgeAndLayerConstraintEdgeReverser",1491),M(1492,1,ps,uY),l.pf=function(t,n){Yon(u(t,37),n)},O(Pn,"EndLabelPostprocessor",1492),M(1493,1,{},lY),l.Kb=function(t){return new vn(null,new mn(u(t,29).a,16))},O(Pn,"EndLabelPostprocessor/lambda$0$Type",1493),M(1494,1,vi,hY),l.Mb=function(t){return GJt(u(t,10))},O(Pn,"EndLabelPostprocessor/lambda$1$Type",1494),M(1495,1,Un,fY),l.td=function(t){Bln(u(t,10))},O(Pn,"EndLabelPostprocessor/lambda$2$Type",1495),M(1496,1,ps,dY),l.pf=function(t,n){_1n(u(t,37),n)},O(Pn,"EndLabelPreprocessor",1496),M(1497,1,{},mL),l.Kb=function(t){return new vn(null,new mn(u(t,29).a,16))},O(Pn,"EndLabelPreprocessor/lambda$0$Type",1497),M(1498,1,Un,_We),l.td=function(t){_Ut(this.a,this.b,this.c,u(t,10))},l.a=0,l.b=0,l.c=!1,O(Pn,"EndLabelPreprocessor/lambda$1$Type",1498),M(1499,1,vi,gY),l.Mb=function(t){return je(K(u(t,70),(pt(),Rd)))===je((P1(),TE))},O(Pn,"EndLabelPreprocessor/lambda$2$Type",1499),M(1500,1,Un,qc),l.td=function(t){ci(this.a,u(t,70))},O(Pn,"EndLabelPreprocessor/lambda$3$Type",1500),M(1501,1,vi,pY),l.Mb=function(t){return je(K(u(t,70),(pt(),Rd)))===je((P1(),zy))},O(Pn,"EndLabelPreprocessor/lambda$4$Type",1501),M(1502,1,Un,uo),l.td=function(t){ci(this.a,u(t,70))},O(Pn,"EndLabelPreprocessor/lambda$5$Type",1502),M(1551,1,ps,NJ),l.pf=function(t,n){ron(u(t,37),n)};var Kpt;O(Pn,"EndLabelSorter",1551),M(1552,1,ji,E9),l.ue=function(t,n){return Ocn(u(t,456),u(n,456))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Pn,"EndLabelSorter/1",1552),M(456,1,{456:1},VYe),O(Pn,"EndLabelSorter/LabelGroup",456),M(1553,1,{},UP),l.Kb=function(t){return vM(),new vn(null,new mn(u(t,29).a,16))},O(Pn,"EndLabelSorter/lambda$0$Type",1553),M(1554,1,vi,F5),l.Mb=function(t){return vM(),u(t,10).k==(zn(),Hs)},O(Pn,"EndLabelSorter/lambda$1$Type",1554),M(1555,1,Un,bY),l.td=function(t){Bfn(u(t,10))},O(Pn,"EndLabelSorter/lambda$2$Type",1555),M(1556,1,vi,vY),l.Mb=function(t){return vM(),je(K(u(t,70),(pt(),Rd)))===je((P1(),zy))},O(Pn,"EndLabelSorter/lambda$3$Type",1556),M(1557,1,vi,wY),l.Mb=function(t){return vM(),je(K(u(t,70),(pt(),Rd)))===je((P1(),TE))},O(Pn,"EndLabelSorter/lambda$4$Type",1557),M(1503,1,ps,mY),l.pf=function(t,n){Lvn(this,u(t,37))},l.b=0,l.c=0,O(Pn,"FinalSplineBendpointsCalculator",1503),M(1504,1,{},yY),l.Kb=function(t){return new vn(null,new mn(u(t,29).a,16))},O(Pn,"FinalSplineBendpointsCalculator/lambda$0$Type",1504),M(1505,1,{},T9),l.Kb=function(t){return new vn(null,new Sv(new cr(fr(js(u(t,10)).a.Kc(),new V))))},O(Pn,"FinalSplineBendpointsCalculator/lambda$1$Type",1505),M(1506,1,vi,yL),l.Mb=function(t){return!to(u(t,17))},O(Pn,"FinalSplineBendpointsCalculator/lambda$2$Type",1506),M(1507,1,vi,WP),l.Mb=function(t){return ta(u(t,17),(et(),Mb))},O(Pn,"FinalSplineBendpointsCalculator/lambda$3$Type",1507),M(1508,1,Un,Lc),l.td=function(t){z2n(this.a,u(t,128))},O(Pn,"FinalSplineBendpointsCalculator/lambda$4$Type",1508),M(1509,1,Un,v3),l.td=function(t){Nse(u(t,17).a)},O(Pn,"FinalSplineBendpointsCalculator/lambda$5$Type",1509),M(792,1,ps,Ra),l.pf=function(t,n){xwn(this,u(t,37),n)},O(Pn,"GraphTransformer",792),M(511,22,{3:1,35:1,22:1,511:1},f2e);var Jue,gO,Ypt=Gr(Pn,"GraphTransformer/Mode",511,Wr,hen,GXt),Xpt;M(1510,1,ps,w3),l.pf=function(t,n){Zgn(u(t,37),n)},O(Pn,"HierarchicalNodeResizingProcessor",1510),M(1511,1,ps,kY),l.pf=function(t,n){Oin(u(t,37),n)},O(Pn,"HierarchicalPortConstraintProcessor",1511),M(1512,1,ji,df),l.ue=function(t,n){return qcn(u(t,10),u(n,10))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Pn,"HierarchicalPortConstraintProcessor/NodeComparator",1512),M(1513,1,ps,j5),l.pf=function(t,n){Jbn(u(t,37),n)},O(Pn,"HierarchicalPortDummySizeProcessor",1513),M(1514,1,ps,xY),l.pf=function(t,n){Xpn(this,u(t,37),n)},l.a=0,O(Pn,"HierarchicalPortOrthogonalEdgeRouter",1514),M(1515,1,ji,px),l.ue=function(t,n){return tKt(u(t,10),u(n,10))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Pn,"HierarchicalPortOrthogonalEdgeRouter/1",1515),M(1516,1,ji,zd),l.ue=function(t,n){return prn(u(t,10),u(n,10))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Pn,"HierarchicalPortOrthogonalEdgeRouter/2",1516),M(1517,1,ps,EY),l.pf=function(t,n){kfn(u(t,37),n)},O(Pn,"HierarchicalPortPositionProcessor",1517),M(1518,1,ps,BJ),l.pf=function(t,n){byn(this,u(t,37))},l.a=0,l.c=0;var rq,iq;O(Pn,"HighDegreeNodeLayeringProcessor",1518),M(571,1,{571:1},TY),l.b=-1,l.d=-1,O(Pn,"HighDegreeNodeLayeringProcessor/HighDegreeNodeInformation",571),M(1519,1,{},_Y),l.Kb=function(t){return GM(),Xo(u(t,10))},l.Fb=function(t){return this===t},O(Pn,"HighDegreeNodeLayeringProcessor/lambda$0$Type",1519),M(1520,1,{},CY),l.Kb=function(t){return GM(),js(u(t,10))},l.Fb=function(t){return this===t},O(Pn,"HighDegreeNodeLayeringProcessor/lambda$1$Type",1520),M(1526,1,ps,_9),l.pf=function(t,n){Sbn(this,u(t,37),n)},O(Pn,"HyperedgeDummyMerger",1526),M(793,1,{},nve),l.a=!1,l.b=!1,l.c=!1,O(Pn,"HyperedgeDummyMerger/MergeState",793),M(1527,1,{},kL),l.Kb=function(t){return new vn(null,new mn(u(t,29).a,16))},O(Pn,"HyperedgeDummyMerger/lambda$0$Type",1527),M(1528,1,{},KP),l.Kb=function(t){return new vn(null,new mn(u(t,10).j,16))},O(Pn,"HyperedgeDummyMerger/lambda$1$Type",1528),M(1529,1,Un,xL),l.td=function(t){u(t,11).p=-1},O(Pn,"HyperedgeDummyMerger/lambda$2$Type",1529),M(1530,1,ps,$5),l.pf=function(t,n){_bn(u(t,37),n)},O(Pn,"HypernodesProcessor",1530),M(1531,1,ps,SY),l.pf=function(t,n){Cbn(u(t,37),n)},O(Pn,"InLayerConstraintProcessor",1531),M(1532,1,ps,YP),l.pf=function(t,n){nsn(u(t,37),n)},O(Pn,"InnermostNodeMarginCalculator",1532),M(1533,1,ps,XP),l.pf=function(t,n){Omn(this,u(t,37))},l.a=Ds,l.b=Ds,l.c=gs,l.d=gs;var w3n=O(Pn,"InteractiveExternalPortPositioner",1533);M(1534,1,{},AY),l.Kb=function(t){return u(t,17).d.i},l.Fb=function(t){return this===t},O(Pn,"InteractiveExternalPortPositioner/lambda$0$Type",1534),M(1535,1,{},lo),l.Kb=function(t){return iKt(this.a,ft(t))},l.Fb=function(t){return this===t},O(Pn,"InteractiveExternalPortPositioner/lambda$1$Type",1535),M(1536,1,{},LY),l.Kb=function(t){return u(t,17).c.i},l.Fb=function(t){return this===t},O(Pn,"InteractiveExternalPortPositioner/lambda$2$Type",1536),M(1537,1,{},Sl),l.Kb=function(t){return sKt(this.a,ft(t))},l.Fb=function(t){return this===t},O(Pn,"InteractiveExternalPortPositioner/lambda$3$Type",1537),M(1538,1,{},Yf),l.Kb=function(t){return KKt(this.a,ft(t))},l.Fb=function(t){return this===t},O(Pn,"InteractiveExternalPortPositioner/lambda$4$Type",1538),M(1539,1,{},mp),l.Kb=function(t){return YKt(this.a,ft(t))},l.Fb=function(t){return this===t},O(Pn,"InteractiveExternalPortPositioner/lambda$5$Type",1539),M(77,22,{3:1,35:1,22:1,77:1,234:1},Cs),l.Kf=function(){switch(this.g){case 15:return new VX;case 22:return new UX;case 47:return new YX;case 28:case 35:return new m3;case 32:return new gx;case 42:return new sY;case 1:return new aY;case 41:return new oY;case 56:return new Ra((j8(),gO));case 0:return new Ra((j8(),Jue));case 2:return new cY;case 54:return new uY;case 33:return new dY;case 51:return new mY;case 55:return new w3;case 13:return new kY;case 38:return new j5;case 44:return new xY;case 40:return new EY;case 9:return new BJ;case 49:return new hUe;case 37:return new _9;case 43:return new $5;case 27:return new SY;case 30:return new YP;case 3:return new XP;case 18:return new DY;case 29:return new IY;case 5:return new _R;case 50:return new MY;case 34:return new RJ;case 36:return new bx;case 52:return new NJ;case 11:return new lm;case 7:return new jJ;case 39:return new vx;case 45:return new BY;case 16:return new C9;case 10:return new ud;case 48:return new TL;case 21:return new wx;case 23:return new ete((Gv(),xS));case 8:return new eB;case 12:return new CL;case 4:return new FY;case 19:return new iT;case 17:return new GY;case 53:return new qY;case 6:return new oB;case 25:return new pHe;case 46:return new KY;case 31:return new YUe;case 14:return new AL;case 26:return new ZX;case 20:return new nX;case 24:return new ete((Gv(),cV));default:throw J(new Ln(Noe+(this.f!=null?this.f:""+this.g)))}};var kEe,xEe,EEe,TEe,_Ee,CEe,SEe,AEe,LEe,MEe,tS,sq,aq,DEe,IEe,OEe,NEe,PEe,BEe,REe,nS,FEe,jEe,$Ee,HEe,zEe,ele,oq,cq,GEe,uq,lq,hq,Z7,J7,eE,qEe,fq,dq,VEe,gq,pq,UEe,WEe,KEe,YEe,bq,tle,pO,vq,wq,mq,yq,XEe,QEe,ZEe,JEe,m3n=Gr(Pn,tke,77,Wr,Hot,zXt),Qpt;M(1540,1,ps,DY),l.pf=function(t,n){Pmn(u(t,37),n)},O(Pn,"InvertedPortProcessor",1540),M(1541,1,ps,IY),l.pf=function(t,n){P2n(u(t,37),n)},O(Pn,"LabelAndNodeSizeProcessor",1541),M(1542,1,vi,OY),l.Mb=function(t){return u(t,10).k==(zn(),Hs)},O(Pn,"LabelAndNodeSizeProcessor/lambda$0$Type",1542),M(1543,1,vi,Gd),l.Mb=function(t){return u(t,10).k==(zn(),Ls)},O(Pn,"LabelAndNodeSizeProcessor/lambda$1$Type",1543),M(1544,1,Un,CWe),l.td=function(t){CUt(this.b,this.a,this.c,u(t,10))},l.a=!1,l.c=!1,O(Pn,"LabelAndNodeSizeProcessor/lambda$2$Type",1544),M(1545,1,ps,_R),l.pf=function(t,n){smn(u(t,37),n)};var Zpt;O(Pn,"LabelDummyInserter",1545),M(1546,1,_d,tv),l.Lb=function(t){return je(K(u(t,70),(pt(),Rd)))===je((P1(),EE))},l.Fb=function(t){return this===t},l.Mb=function(t){return je(K(u(t,70),(pt(),Rd)))===je((P1(),EE))},O(Pn,"LabelDummyInserter/1",1546),M(1547,1,ps,MY),l.pf=function(t,n){own(u(t,37),n)},O(Pn,"LabelDummyRemover",1547),M(1548,1,vi,NY),l.Mb=function(t){return It(Mt(K(u(t,70),(pt(),Gle))))},O(Pn,"LabelDummyRemover/lambda$0$Type",1548),M(1359,1,ps,RJ),l.pf=function(t,n){Bwn(this,u(t,37),n)},l.a=null;var nle;O(Pn,"LabelDummySwitcher",1359),M(286,1,{286:1},jct),l.c=0,l.d=null,l.f=0,O(Pn,"LabelDummySwitcher/LabelDummyInfo",286),M(1360,1,{},QP),l.Kb=function(t){return U6(),new vn(null,new mn(u(t,29).a,16))},O(Pn,"LabelDummySwitcher/lambda$0$Type",1360),M(1361,1,vi,ZP),l.Mb=function(t){return U6(),u(t,10).k==(zn(),Rl)},O(Pn,"LabelDummySwitcher/lambda$1$Type",1361),M(1362,1,{},gg),l.Kb=function(t){return RKt(this.a,u(t,10))},O(Pn,"LabelDummySwitcher/lambda$2$Type",1362),M(1363,1,Un,fd),l.td=function(t){BZt(this.a,u(t,286))},O(Pn,"LabelDummySwitcher/lambda$3$Type",1363),M(1364,1,ji,PY),l.ue=function(t,n){return lZt(u(t,286),u(n,286))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Pn,"LabelDummySwitcher/lambda$4$Type",1364),M(791,1,ps,m3),l.pf=function(t,n){Wnn(u(t,37),n)},O(Pn,"LabelManagementProcessor",791),M(1549,1,ps,bx),l.pf=function(t,n){wpn(u(t,37),n)},O(Pn,"LabelSideSelector",1549),M(1550,1,vi,EL),l.Mb=function(t){return It(Mt(K(u(t,70),(pt(),Gle))))},O(Pn,"LabelSideSelector/lambda$0$Type",1550),M(1558,1,ps,lm),l.pf=function(t,n){evn(u(t,37),n)},O(Pn,"LayerConstraintPostprocessor",1558),M(1559,1,ps,jJ),l.pf=function(t,n){g0n(u(t,37),n)};var e9e;O(Pn,"LayerConstraintPreprocessor",1559),M(360,22,{3:1,35:1,22:1,360:1},FF);var bO,kq,xq,rle,Jpt=Gr(Pn,"LayerConstraintPreprocessor/HiddenNodeConnections",360,Wr,$tn,OYt),e2t;M(1560,1,ps,vx),l.pf=function(t,n){iwn(u(t,37),n)},O(Pn,"LayerSizeAndGraphHeightCalculator",1560),M(1561,1,ps,BY),l.pf=function(t,n){ogn(u(t,37),n)},O(Pn,"LongEdgeJoiner",1561),M(1562,1,ps,C9),l.pf=function(t,n){jvn(u(t,37),n)},O(Pn,"LongEdgeSplitter",1562),M(1563,1,ps,ud),l.pf=function(t,n){jwn(this,u(t,37),n)},l.d=0,l.e=0,l.i=0,l.j=0,l.k=0,l.n=0,O(Pn,"NodePromotion",1563),M(1564,1,{},JP),l.Kb=function(t){return u(t,46),Mn(),!0},l.Fb=function(t){return this===t},O(Pn,"NodePromotion/lambda$0$Type",1564),M(1565,1,{},yp),l.Kb=function(t){return rJt(this.a,u(t,46))},l.Fb=function(t){return this===t},l.a=0,O(Pn,"NodePromotion/lambda$1$Type",1565),M(1566,1,{},Xf),l.Kb=function(t){return iJt(this.a,u(t,46))},l.Fb=function(t){return this===t},l.a=0,O(Pn,"NodePromotion/lambda$2$Type",1566),M(1567,1,ps,TL),l.pf=function(t,n){uyn(u(t,37),n)},O(Pn,"NorthSouthPortPostprocessor",1567),M(1568,1,ps,wx),l.pf=function(t,n){Kmn(u(t,37),n)},O(Pn,"NorthSouthPortPreprocessor",1568),M(1569,1,ji,_L),l.ue=function(t,n){return Esn(u(t,11),u(n,11))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Pn,"NorthSouthPortPreprocessor/lambda$0$Type",1569),M(1570,1,ps,eB),l.pf=function(t,n){hbn(u(t,37),n)},O(Pn,"PartitionMidprocessor",1570),M(1571,1,vi,RY),l.Mb=function(t){return ta(u(t,10),(pt(),dE))},O(Pn,"PartitionMidprocessor/lambda$0$Type",1571),M(1572,1,Un,ov),l.td=function(t){CJt(this.a,u(t,10))},O(Pn,"PartitionMidprocessor/lambda$1$Type",1572),M(1573,1,ps,CL),l.pf=function(t,n){Sgn(u(t,37),n)},O(Pn,"PartitionPostprocessor",1573),M(1574,1,ps,FY),l.pf=function(t,n){Rdn(u(t,37),n)},O(Pn,"PartitionPreprocessor",1574),M(1575,1,vi,jY),l.Mb=function(t){return ta(u(t,10),(pt(),dE))},O(Pn,"PartitionPreprocessor/lambda$0$Type",1575),M(1576,1,{},tB),l.Kb=function(t){return new vn(null,new Sv(new cr(fr(js(u(t,10)).a.Kc(),new V))))},O(Pn,"PartitionPreprocessor/lambda$1$Type",1576),M(1577,1,vi,H5),l.Mb=function(t){return Mcn(u(t,17))},O(Pn,"PartitionPreprocessor/lambda$2$Type",1577),M(1578,1,Un,nB),l.td=function(t){Osn(u(t,17))},O(Pn,"PartitionPreprocessor/lambda$3$Type",1578),M(1579,1,ps,iT),l.pf=function(t,n){Y2n(u(t,37),n)};var t9e,t2t,n2t,r2t,n9e,r9e;O(Pn,"PortListSorter",1579),M(1580,1,{},z5),l.Kb=function(t){return X8(),u(t,11).e},O(Pn,"PortListSorter/lambda$0$Type",1580),M(1581,1,{},$Y),l.Kb=function(t){return X8(),u(t,11).g},O(Pn,"PortListSorter/lambda$1$Type",1581),M(1582,1,ji,SL),l.ue=function(t,n){return QQe(u(t,11),u(n,11))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Pn,"PortListSorter/lambda$2$Type",1582),M(1583,1,ji,HY),l.ue=function(t,n){return eln(u(t,11),u(n,11))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Pn,"PortListSorter/lambda$3$Type",1583),M(1584,1,ji,zY),l.ue=function(t,n){return cut(u(t,11),u(n,11))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Pn,"PortListSorter/lambda$4$Type",1584),M(1585,1,ps,GY),l.pf=function(t,n){c0n(u(t,37),n)},O(Pn,"PortSideProcessor",1585),M(1586,1,ps,qY),l.pf=function(t,n){u2n(u(t,37),n)},O(Pn,"ReversedEdgeRestorer",1586),M(1591,1,ps,pHe),l.pf=function(t,n){Fun(this,u(t,37),n)},O(Pn,"SelfLoopPortRestorer",1591),M(1592,1,{},rB),l.Kb=function(t){return new vn(null,new mn(u(t,29).a,16))},O(Pn,"SelfLoopPortRestorer/lambda$0$Type",1592),M(1593,1,vi,VY),l.Mb=function(t){return u(t,10).k==(zn(),Hs)},O(Pn,"SelfLoopPortRestorer/lambda$1$Type",1593),M(1594,1,vi,UY),l.Mb=function(t){return ta(u(t,10),(et(),lE))},O(Pn,"SelfLoopPortRestorer/lambda$2$Type",1594),M(1595,1,{},WY),l.Kb=function(t){return u(K(u(t,10),(et(),lE)),403)},O(Pn,"SelfLoopPortRestorer/lambda$3$Type",1595),M(1596,1,Un,mm),l.td=function(t){Wfn(this.a,u(t,403))},O(Pn,"SelfLoopPortRestorer/lambda$4$Type",1596),M(794,1,Un,iB),l.td=function(t){c1n(u(t,101))},O(Pn,"SelfLoopPortRestorer/lambda$5$Type",794),M(1597,1,ps,KY),l.pf=function(t,n){Wcn(u(t,37),n)},O(Pn,"SelfLoopPostProcessor",1597),M(1598,1,{},YY),l.Kb=function(t){return new vn(null,new mn(u(t,29).a,16))},O(Pn,"SelfLoopPostProcessor/lambda$0$Type",1598),M(1599,1,vi,XY),l.Mb=function(t){return u(t,10).k==(zn(),Hs)},O(Pn,"SelfLoopPostProcessor/lambda$1$Type",1599),M(1600,1,vi,sB),l.Mb=function(t){return ta(u(t,10),(et(),lE))},O(Pn,"SelfLoopPostProcessor/lambda$2$Type",1600),M(1601,1,Un,QY),l.td=function(t){ehn(u(t,10))},O(Pn,"SelfLoopPostProcessor/lambda$3$Type",1601),M(1602,1,{},ZY),l.Kb=function(t){return new vn(null,new mn(u(t,101).f,1))},O(Pn,"SelfLoopPostProcessor/lambda$4$Type",1602),M(1603,1,Un,l6),l.td=function(t){Gtn(this.a,u(t,409))},O(Pn,"SelfLoopPostProcessor/lambda$5$Type",1603),M(1604,1,vi,aB),l.Mb=function(t){return!!u(t,101).i},O(Pn,"SelfLoopPostProcessor/lambda$6$Type",1604),M(1605,1,Un,S3),l.td=function(t){SVt(this.a,u(t,101))},O(Pn,"SelfLoopPostProcessor/lambda$7$Type",1605),M(1587,1,ps,oB),l.pf=function(t,n){$0n(u(t,37),n)},O(Pn,"SelfLoopPreProcessor",1587),M(1588,1,{},cB),l.Kb=function(t){return new vn(null,new mn(u(t,101).f,1))},O(Pn,"SelfLoopPreProcessor/lambda$0$Type",1588),M(1589,1,{},JY),l.Kb=function(t){return u(t,409).a},O(Pn,"SelfLoopPreProcessor/lambda$1$Type",1589),M(1590,1,Un,eX),l.td=function(t){IWt(u(t,17))},O(Pn,"SelfLoopPreProcessor/lambda$2$Type",1590),M(1606,1,ps,YUe),l.pf=function(t,n){Rfn(this,u(t,37),n)},O(Pn,"SelfLoopRouter",1606),M(1607,1,{},mx),l.Kb=function(t){return new vn(null,new mn(u(t,29).a,16))},O(Pn,"SelfLoopRouter/lambda$0$Type",1607),M(1608,1,vi,G5),l.Mb=function(t){return u(t,10).k==(zn(),Hs)},O(Pn,"SelfLoopRouter/lambda$1$Type",1608),M(1609,1,vi,S9),l.Mb=function(t){return ta(u(t,10),(et(),lE))},O(Pn,"SelfLoopRouter/lambda$2$Type",1609),M(1610,1,{},tX),l.Kb=function(t){return u(K(u(t,10),(et(),lE)),403)},O(Pn,"SelfLoopRouter/lambda$3$Type",1610),M(1611,1,Un,VGe),l.td=function(t){vJt(this.a,this.b,u(t,403))},O(Pn,"SelfLoopRouter/lambda$4$Type",1611),M(1612,1,ps,AL),l.pf=function(t,n){apn(u(t,37),n)},O(Pn,"SemiInteractiveCrossMinProcessor",1612),M(1613,1,vi,A9),l.Mb=function(t){return u(t,10).k==(zn(),Hs)},O(Pn,"SemiInteractiveCrossMinProcessor/lambda$0$Type",1613),M(1614,1,vi,LL),l.Mb=function(t){return hKe(u(t,10))._b((pt(),By))},O(Pn,"SemiInteractiveCrossMinProcessor/lambda$1$Type",1614),M(1615,1,ji,uB),l.ue=function(t,n){return Pin(u(t,10),u(n,10))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Pn,"SemiInteractiveCrossMinProcessor/lambda$2$Type",1615),M(1616,1,{},lB),l.Ce=function(t,n){return NJt(u(t,10),u(n,10))},O(Pn,"SemiInteractiveCrossMinProcessor/lambda$3$Type",1616),M(1618,1,ps,nX),l.pf=function(t,n){tvn(u(t,37),n)},O(Pn,"SortByInputModelProcessor",1618),M(1619,1,vi,rX),l.Mb=function(t){return u(t,11).g.c.length!=0},O(Pn,"SortByInputModelProcessor/lambda$0$Type",1619),M(1620,1,Un,h6),l.td=function(t){d1n(this.a,u(t,11))},O(Pn,"SortByInputModelProcessor/lambda$1$Type",1620),M(1693,803,{},ctt),l.Me=function(t){var n,r,s,o;switch(this.c=t,this.a.g){case 2:n=new st,ms(Vi(new vn(null,new mn(this.c.a.b,16)),new gB),new XGe(this,n)),sI(this,new fB),Mu(n,new sX),n.c=Me(Yn,yt,1,0,5,1),ms(Vi(new vn(null,new mn(this.c.a.b,16)),new aX),new A3(n)),sI(this,new oX),Mu(n,new cX),n.c=Me(Yn,yt,1,0,5,1),r=LVe(ktt(Kj(new vn(null,new mn(this.c.a.b,16)),new qd(this))),new uX),ms(new vn(null,new mn(this.c.a.a,16)),new WGe(r,n)),sI(this,new lX),Mu(n,new iX),n.c=Me(Yn,yt,1,0,5,1);break;case 3:s=new st,sI(this,new hB),o=LVe(ktt(Kj(new vn(null,new mn(this.c.a.b,16)),new gT(this))),new dB),ms(Vi(new vn(null,new mn(this.c.a.b,16)),new hX),new YGe(o,s)),sI(this,new fX),Mu(s,new dX),s.c=Me(Yn,yt,1,0,5,1);break;default:throw J(new eHe)}},l.b=0,O(Is,"EdgeAwareScanlineConstraintCalculation",1693),M(1694,1,_d,hB),l.Lb=function(t){return we(u(t,57).g,145)},l.Fb=function(t){return this===t},l.Mb=function(t){return we(u(t,57).g,145)},O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$0$Type",1694),M(1695,1,{},gT),l.Fe=function(t){return U1n(this.a,u(t,57))},O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$1$Type",1695),M(1703,1,Az,UGe),l.Vd=function(){Z_(this.a,this.b,-1)},l.b=0,O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$10$Type",1703),M(1705,1,_d,fB),l.Lb=function(t){return we(u(t,57).g,145)},l.Fb=function(t){return this===t},l.Mb=function(t){return we(u(t,57).g,145)},O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$11$Type",1705),M(1706,1,Un,sX),l.td=function(t){u(t,365).Vd()},O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$12$Type",1706),M(1707,1,vi,aX),l.Mb=function(t){return we(u(t,57).g,10)},O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$13$Type",1707),M(1709,1,Un,A3),l.td=function(t){mon(this.a,u(t,57))},O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$14$Type",1709),M(1708,1,Az,eqe),l.Vd=function(){Z_(this.b,this.a,-1)},l.a=0,O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$15$Type",1708),M(1710,1,_d,oX),l.Lb=function(t){return we(u(t,57).g,10)},l.Fb=function(t){return this===t},l.Mb=function(t){return we(u(t,57).g,10)},O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$16$Type",1710),M(1711,1,Un,cX),l.td=function(t){u(t,365).Vd()},O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$17$Type",1711),M(1712,1,{},qd),l.Fe=function(t){return W1n(this.a,u(t,57))},O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$18$Type",1712),M(1713,1,{},uX),l.De=function(){return 0},O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$19$Type",1713),M(1696,1,{},dB),l.De=function(){return 0},O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$2$Type",1696),M(1715,1,Un,WGe),l.td=function(t){eZt(this.a,this.b,u(t,307))},l.a=0,O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$20$Type",1715),M(1714,1,Az,KGe),l.Vd=function(){wot(this.a,this.b,-1)},l.b=0,O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$21$Type",1714),M(1716,1,_d,lX),l.Lb=function(t){return u(t,57),!0},l.Fb=function(t){return this===t},l.Mb=function(t){return u(t,57),!0},O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$22$Type",1716),M(1717,1,Un,iX),l.td=function(t){u(t,365).Vd()},O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$23$Type",1717),M(1697,1,vi,hX),l.Mb=function(t){return we(u(t,57).g,10)},O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$3$Type",1697),M(1699,1,Un,YGe),l.td=function(t){tZt(this.a,this.b,u(t,57))},l.a=0,O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$4$Type",1699),M(1698,1,Az,tqe),l.Vd=function(){Z_(this.b,this.a,-1)},l.a=0,O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$5$Type",1698),M(1700,1,_d,fX),l.Lb=function(t){return u(t,57),!0},l.Fb=function(t){return this===t},l.Mb=function(t){return u(t,57),!0},O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$6$Type",1700),M(1701,1,Un,dX),l.td=function(t){u(t,365).Vd()},O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$7$Type",1701),M(1702,1,vi,gB),l.Mb=function(t){return we(u(t,57).g,145)},O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$8$Type",1702),M(1704,1,Un,XGe),l.td=function(t){Zrn(this.a,this.b,u(t,57))},O(Is,"EdgeAwareScanlineConstraintCalculation/lambda$9$Type",1704),M(1521,1,ps,hUe),l.pf=function(t,n){Uvn(this,u(t,37),n)};var i2t;O(Is,"HorizontalGraphCompactor",1521),M(1522,1,{},_1),l.Oe=function(t,n){var r,s,o;return mme(t,n)||(r=U3(t),s=U3(n),r&&r.k==(zn(),Ls)||s&&s.k==(zn(),Ls))?0:(o=u(K(this.a.a,(et(),G4)),304),aKt(o,r?r.k:(zn(),ca),s?s.k:(zn(),ca)))},l.Pe=function(t,n){var r,s,o;return mme(t,n)?1:(r=U3(t),s=U3(n),o=u(K(this.a.a,(et(),G4)),304),gbe(o,r?r.k:(zn(),ca),s?s.k:(zn(),ca)))},O(Is,"HorizontalGraphCompactor/1",1522),M(1523,1,{},L9),l.Ne=function(t,n){return IT(),t.a.i==0},O(Is,"HorizontalGraphCompactor/lambda$0$Type",1523),M(1524,1,{},Vd),l.Ne=function(t,n){return MJt(this.a,t,n)},O(Is,"HorizontalGraphCompactor/lambda$1$Type",1524),M(1664,1,{},VJe);var s2t,a2t;O(Is,"LGraphToCGraphTransformer",1664),M(1672,1,vi,gX),l.Mb=function(t){return t!=null},O(Is,"LGraphToCGraphTransformer/0methodref$nonNull$Type",1672),M(1665,1,{},pX),l.Kb=function(t){return mf(),Qo(K(u(u(t,57).g,10),(et(),Mi)))},O(Is,"LGraphToCGraphTransformer/lambda$0$Type",1665),M(1666,1,{},pB),l.Kb=function(t){return mf(),Xnt(u(u(t,57).g,145))},O(Is,"LGraphToCGraphTransformer/lambda$1$Type",1666),M(1675,1,vi,bX),l.Mb=function(t){return mf(),we(u(t,57).g,10)},O(Is,"LGraphToCGraphTransformer/lambda$10$Type",1675),M(1676,1,Un,vX),l.td=function(t){LJt(u(t,57))},O(Is,"LGraphToCGraphTransformer/lambda$11$Type",1676),M(1677,1,vi,wX),l.Mb=function(t){return mf(),we(u(t,57).g,145)},O(Is,"LGraphToCGraphTransformer/lambda$12$Type",1677),M(1681,1,Un,mX),l.td=function(t){Nan(u(t,57))},O(Is,"LGraphToCGraphTransformer/lambda$13$Type",1681),M(1678,1,Un,pT),l.td=function(t){iWt(this.a,u(t,8))},l.a=0,O(Is,"LGraphToCGraphTransformer/lambda$14$Type",1678),M(1679,1,Un,$2),l.td=function(t){aWt(this.a,u(t,110))},l.a=0,O(Is,"LGraphToCGraphTransformer/lambda$15$Type",1679),M(1680,1,Un,QR),l.td=function(t){sWt(this.a,u(t,8))},l.a=0,O(Is,"LGraphToCGraphTransformer/lambda$16$Type",1680),M(1682,1,{},yX),l.Kb=function(t){return mf(),new vn(null,new Sv(new cr(fr(js(u(t,10)).a.Kc(),new V))))},O(Is,"LGraphToCGraphTransformer/lambda$17$Type",1682),M(1683,1,vi,kX),l.Mb=function(t){return mf(),to(u(t,17))},O(Is,"LGraphToCGraphTransformer/lambda$18$Type",1683),M(1684,1,Un,Dee),l.td=function(t){$rn(this.a,u(t,17))},O(Is,"LGraphToCGraphTransformer/lambda$19$Type",1684),M(1668,1,Un,Iee),l.td=function(t){ytn(this.a,u(t,145))},O(Is,"LGraphToCGraphTransformer/lambda$2$Type",1668),M(1685,1,{},bB),l.Kb=function(t){return mf(),new vn(null,new mn(u(t,29).a,16))},O(Is,"LGraphToCGraphTransformer/lambda$20$Type",1685),M(1686,1,{},xX),l.Kb=function(t){return mf(),new vn(null,new Sv(new cr(fr(js(u(t,10)).a.Kc(),new V))))},O(Is,"LGraphToCGraphTransformer/lambda$21$Type",1686),M(1687,1,{},vB),l.Kb=function(t){return mf(),u(K(u(t,17),(et(),Mb)),15)},O(Is,"LGraphToCGraphTransformer/lambda$22$Type",1687),M(1688,1,vi,EX),l.Mb=function(t){return cKt(u(t,15))},O(Is,"LGraphToCGraphTransformer/lambda$23$Type",1688),M(1689,1,Un,Oee),l.td=function(t){R1n(this.a,u(t,15))},O(Is,"LGraphToCGraphTransformer/lambda$24$Type",1689),M(1667,1,Un,QGe),l.td=function(t){onn(this.a,this.b,u(t,145))},O(Is,"LGraphToCGraphTransformer/lambda$3$Type",1667),M(1669,1,{},TX),l.Kb=function(t){return mf(),new vn(null,new mn(u(t,29).a,16))},O(Is,"LGraphToCGraphTransformer/lambda$4$Type",1669),M(1670,1,{},_X),l.Kb=function(t){return mf(),new vn(null,new Sv(new cr(fr(js(u(t,10)).a.Kc(),new V))))},O(Is,"LGraphToCGraphTransformer/lambda$5$Type",1670),M(1671,1,{},M9),l.Kb=function(t){return mf(),u(K(u(t,17),(et(),Mb)),15)},O(Is,"LGraphToCGraphTransformer/lambda$6$Type",1671),M(1673,1,Un,Nee),l.td=function(t){pdn(this.a,u(t,15))},O(Is,"LGraphToCGraphTransformer/lambda$8$Type",1673),M(1674,1,Un,ZGe),l.td=function(t){AWt(this.a,this.b,u(t,145))},O(Is,"LGraphToCGraphTransformer/lambda$9$Type",1674),M(1663,1,{},CX),l.Le=function(t){var n,r,s,o,h;for(this.a=t,this.d=new Gee,this.c=Me(R7e,yt,121,this.a.a.a.c.length,0,1),this.b=0,r=new C(this.a.a.a);r.a=X&&(it(h,ct(L)),Ee=b.Math.max(Ee,Ne[L-1]-P),v+=W,le+=Ne[L-1]-le,P=Ne[L-1],W=x[L]),W=b.Math.max(W,x[L]),++L;v+=W}q=b.Math.min(1/Ee,1/n.b/v),q>s&&(s=q,r=h)}return r},l.Wf=function(){return!1},O(Ld,"MSDCutIndexHeuristic",802),M(1617,1,ps,ZX),l.pf=function(t,n){Wbn(u(t,37),n)},O(Ld,"SingleEdgeGraphWrapper",1617),M(227,22,{3:1,35:1,22:1,227:1},jT);var B4,rE,iE,Cy,rS,R4,sE=Gr(Ic,"CenterEdgeLabelPlacementStrategy",227,Wr,irn,BYt),w2t;M(422,22,{3:1,35:1,22:1,422:1},g2e);var s9e,gle,a9e=Gr(Ic,"ConstraintCalculationStrategy",422,Wr,KJt,RYt),m2t;M(314,22,{3:1,35:1,22:1,314:1,246:1,234:1},yte),l.Kf=function(){return Lat(this)},l.Xf=function(){return Lat(this)};var vO,Ek,o9e,c9e=Gr(Ic,"CrossingMinimizationStrategy",314,Wr,$en,FYt),y2t;M(337,22,{3:1,35:1,22:1,337:1},kte);var u9e,ple,Aq,l9e=Gr(Ic,"CuttingStrategy",337,Wr,Hen,HYt),k2t;M(335,22,{3:1,35:1,22:1,335:1,246:1,234:1},xM),l.Kf=function(){return pot(this)},l.Xf=function(){return pot(this)};var h9e,ble,iS,vle,sS,f9e=Gr(Ic,"CycleBreakingStrategy",335,Wr,Mnn,zYt),x2t;M(419,22,{3:1,35:1,22:1,419:1},p2e);var Lq,d9e,g9e=Gr(Ic,"DirectionCongruency",419,Wr,WJt,GYt),E2t;M(450,22,{3:1,35:1,22:1,450:1},xte);var aE,wle,F4,T2t=Gr(Ic,"EdgeConstraint",450,Wr,zen,qYt),_2t;M(276,22,{3:1,35:1,22:1,276:1},$T);var mle,yle,kle,xle,Mq,Ele,p9e=Gr(Ic,"EdgeLabelSideSelection",276,Wr,crn,VYt),C2t;M(479,22,{3:1,35:1,22:1,479:1},b2e);var Dq,b9e,v9e=Gr(Ic,"EdgeStraighteningStrategy",479,Wr,UJt,UYt),S2t;M(274,22,{3:1,35:1,22:1,274:1},HT);var Tle,w9e,m9e,Iq,y9e,k9e,x9e=Gr(Ic,"FixedAlignment",274,Wr,arn,WYt),A2t;M(275,22,{3:1,35:1,22:1,275:1},zT);var E9e,T9e,_9e,C9e,aS,S9e,A9e=Gr(Ic,"GraphCompactionStrategy",275,Wr,srn,KYt),L2t;M(256,22,{3:1,35:1,22:1,256:1},_m);var oE,Oq,cE,Th,oS,Nq,uE,j4,Pq,cS,_le=Gr(Ic,"GraphProperties",256,Wr,Win,YYt),M2t;M(292,22,{3:1,35:1,22:1,292:1},Ete);var wO,Cle,Sle,Ale=Gr(Ic,"GreedySwitchType",292,Wr,Ven,XYt),D2t;M(303,22,{3:1,35:1,22:1,303:1},Tte);var Tk,mO,$4,I2t=Gr(Ic,"InLayerConstraint",303,Wr,qen,QYt),O2t;M(420,22,{3:1,35:1,22:1,420:1},v2e);var Lle,L9e,M9e=Gr(Ic,"InteractiveReferencePoint",420,Wr,YJt,ZYt),N2t,D9e,_k,yw,Bq,I9e,O9e,Rq,N9e,yO,Fq,uS,Ck,Sy,Mle,jq,vc,P9e,kw,eu,Dle,Ile,kO,Lb,xw,Sk,B9e,Ak,xO,Ay,l1,Yh,Ole,H4,Nc,Mi,R9e,F9e,j9e,$9e,H9e,Nle,$q,cl,Ew,Ple,Lk,EO,W1,z4,lE,G4,q4,hE,Mb,z9e,Ble,Rle,Mk;M(163,22,{3:1,35:1,22:1,163:1},TM);var lS,l2,hS,Ly,TO,G9e=Gr(Ic,"LayerConstraint",163,Wr,Onn,JYt),P2t;M(848,1,zh,VJ),l.Qe=function(t){en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,nke),""),"Direction Congruency"),"Specifies how drawings of the same graph with different layout directions compare to each other: either a natural reading direction is preserved or the drawings are rotated versions of each other."),J9e),(Ng(),vs)),g9e),rn((i1(),Fn))))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,rke),""),"Feedback Edges"),"Whether feedback edges should be highlighted by routing around the nodes."),(Mn(),!1)),za),Us),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Gz),""),"Interactive Reference Point"),"Determines which point of a node is considered by interactive layout phases."),sTe),vs),M9e),rn(Fn)))),va(t,Gz,Roe,Cbt),va(t,Gz,MC,_bt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,ike),""),"Merge Edges"),"Edges that have no ports are merged so they touch the connected nodes at the same points. When this option is disabled, one port is created for each edge directly connected to a node. When it is enabled, all such incoming edges share an input port, and all outgoing edges share an output port."),!1),za),Us),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,ske),""),"Merge Hierarchy-Crossing Edges"),"If hierarchical layout is active, hierarchy-crossing edges use as few hierarchical ports as possible. They are broken by the algorithm, with hierarchical ports inserted as required. Usually, one such port is created for each edge at each hierarchy crossing point. With this option set to true, we try to create as few hierarchical ports as possible in the process. In particular, all edges that form a hyperedge can share a port."),!0),za),Us),rn(Fn)))),en(t,new Vt(sUt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,ake),""),"Allow Non-Flow Ports To Switch Sides"),"Specifies whether non-flow ports may switch sides if their node's port constraints are either FIXED_SIDE or FIXED_ORDER. A non-flow port is a port on a side that is not part of the currently configured layout flow. For instance, given a left-to-right layout direction, north and south ports would be considered non-flow ports. Further note that the underlying criterium whether to switch sides or not solely relies on the minimization of edge crossings. Hence, edge length and other aesthetics criteria are not addressed."),!1),za),Us),rn(Bb)),ie(re(mt,1),Qe,2,6,["org.eclipse.elk.layered.northOrSouthPort"])))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,oke),""),"Port Sorting Strategy"),"Only relevant for nodes with FIXED_SIDE port constraints. Determines the way a node's ports are distributed on the sides of a node if their order is not prescribed. The option is set on parent nodes."),dTe),vs),k_e),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,cke),""),"Thoroughness"),"How much effort should be spent to produce a nice layout."),ct(7)),Cc),Za),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,uke),""),"Add Unnecessary Bendpoints"),"Adds bend points even if an edge does not change direction. If true, each long edge dummy will contribute a bend point to its edges and hierarchy-crossing edges will always get a bend point where they cross hierarchy boundaries. By default, bend points are only added where an edge changes direction."),!1),za),Us),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,lke),""),"Generate Position and Layer IDs"),"If enabled position id and layer id are generated, which are usually only used internally when setting the interactiveLayout option. This option should be specified on the root node."),!1),za),Us),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Roe),"cycleBreaking"),"Cycle Breaking Strategy"),"Strategy for cycle breaking. Cycle breaking looks for cycles in the graph and determines which edges to reverse to break the cycles. Reversed edges will end up pointing to the opposite direction of regular edges (that is, reversed edges will point left if edges usually point right)."),Z9e),vs),f9e),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,GI),oce),"Node Layering Strategy"),"Strategy for node layering."),cTe),vs),u_e),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,hke),oce),"Layer Constraint"),"Determines a constraint on the placement of the node regarding the layering."),aTe),vs),G9e),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,fke),oce),"Layer Choice Constraint"),"Allows to set a constraint regarding the layer placement of a node. Let i be the value of teh constraint. Assumed the drawing has n layers and i < n. If set to i, it expresses that the node should be placed in i-th layer. Should i>=n be true then the node is placed in the last layer of the drawing. Note that this option is not part of any of ELK Layered's default configurations but is only evaluated as part of the `InteractiveLayeredGraphVisitor`, which must be applied manually or used via the `DiagramLayoutEngine."),ct(-1)),Cc),Za),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,dke),oce),"Layer ID"),"Layer identifier that was calculated by ELK Layered for a node. This is only generated if interactiveLayot or generatePositionAndLayerIds is set."),ct(-1)),Cc),Za),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Foe),_ft),"Upper Bound On Width [MinWidth Layerer]"),"Defines a loose upper bound on the width of the MinWidth layerer. If set to '-1' multiple values are tested and the best result is selected."),ct(4)),Cc),Za),rn(Fn)))),va(t,Foe,GI,Obt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,joe),_ft),"Upper Layer Estimation Scaling Factor [MinWidth Layerer]"),"Multiplied with Upper Bound On Width for defining an upper bound on the width of layers which haven't been determined yet, but whose maximum width had been (roughly) estimated by the MinWidth algorithm. Compensates for too high estimations. If set to '-1' multiple values are tested and the best result is selected."),ct(2)),Cc),Za),rn(Fn)))),va(t,joe,GI,Pbt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,$oe),Cft),"Node Promotion Strategy"),"Reduces number of dummy nodes after layering phase (if possible)."),oTe),vs),w_e),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Hoe),Cft),"Max Node Promotion Iterations"),"Limits the number of iterations for node promotion."),ct(0)),Cc),Za),rn(Fn)))),va(t,Hoe,$oe,null),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,zoe),"layering.coffmanGraham"),"Layer Bound"),"The maximum number of nodes allowed per layer."),ct(Ei)),Cc),Za),rn(Fn)))),va(t,zoe,GI,Abt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,MC),qI),"Crossing Minimization Strategy"),"Strategy for crossing minimization."),Q9e),vs),c9e),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,gke),qI),"Force Node Model Order"),"The node order given by the model does not change to produce a better layout. E.g. if node A is before node B in the model this is not changed during crossing minimization. This assumes that the node model order is already respected before crossing minimization. This can be achieved by setting considerModelOrder.strategy to NODES_AND_EDGES."),!1),za),Us),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Goe),qI),"Hierarchical Sweepiness"),"How likely it is to use cross-hierarchy (1) vs bottom-up (-1)."),.1),qo),ma),rn(Fn)))),va(t,Goe,nG,ebt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,qoe),qI),"Semi-Interactive Crossing Minimization"),"Preserves the order of nodes within a layer but still minimizes crossings between edges connecting long edge dummies. Derives the desired order from positions specified by the 'org.eclipse.elk.position' layout option. Requires a crossing minimization strategy that is able to process 'in-layer' constraints."),!1),za),Us),rn(Fn)))),va(t,qoe,MC,ibt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,pke),qI),"Position Choice Constraint"),"Allows to set a constraint regarding the position placement of a node in a layer. Assumed the layer in which the node placed includes n other nodes and i < n. If set to i, it expresses that the node should be placed at the i-th position. Should i>=n be true then the node is placed at the last position in the layer. Note that this option is not part of any of ELK Layered's default configurations but is only evaluated as part of the `InteractiveLayeredGraphVisitor`, which must be applied manually or used via the `DiagramLayoutEngine."),ct(-1)),Cc),Za),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,bke),qI),"Position ID"),"Position within a layer that was determined by ELK Layered for a node. This is only generated if interactiveLayot or generatePositionAndLayerIds is set."),ct(-1)),Cc),Za),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,vke),Sft),"Greedy Switch Activation Threshold"),"By default it is decided automatically if the greedy switch is activated or not. The decision is based on whether the size of the input graph (without dummy nodes) is smaller than the value of this option. A '0' enforces the activation."),ct(40)),Cc),Za),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Voe),Sft),"Greedy Switch Crossing Minimization"),"Greedy Switch strategy for crossing minimization. The greedy switch heuristic is executed after the regular crossing minimization as a post-processor. Note that if 'hierarchyHandling' is set to 'INCLUDE_CHILDREN', the 'greedySwitchHierarchical.type' option must be used."),X9e),vs),Ale),rn(Fn)))),va(t,Voe,MC,Z2t),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,qz),"crossingMinimization.greedySwitchHierarchical"),"Greedy Switch Crossing Minimization (hierarchical)"),"Activates the greedy switch heuristic in case hierarchical layout is used. The differences to the non-hierarchical case (see 'greedySwitch.type') are: 1) greedy switch is inactive by default, 3) only the option value set on the node at which hierarchical layout starts is relevant, and 2) if it's activated by the user, it properly addresses hierarchy-crossing edges."),Y9e),vs),Ale),rn(Fn)))),va(t,qz,MC,Y2t),va(t,qz,nG,X2t),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,T4),Aft),"Node Placement Strategy"),"Strategy for node placement."),fTe),vs),d_e),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,Vz),Aft),"Favor Straight Edges Over Balancing"),"Favor straight edges over a balanced node placement. The default behavior is determined automatically based on the used 'edgeRouting'. For an orthogonal style it is set to true, for all other styles to false."),za),Us),rn(Fn)))),va(t,Vz,T4,Ubt),va(t,Vz,T4,Wbt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Uoe),Lft),"BK Edge Straightening"),"Specifies whether the Brandes Koepf node placer tries to increase the number of straight edges at the expense of diagram size. There is a subtle difference to the 'favorStraightEdges' option, which decides whether a balanced placement of the nodes is desired, or not. In bk terms this means combining the four alignments into a single balanced one, or not. This option on the other hand tries to straighten additional edges during the creation of each of the four alignments."),uTe),vs),v9e),rn(Fn)))),va(t,Uoe,T4,zbt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Woe),Lft),"BK Fixed Alignment"),"Tells the BK node placer to use a certain alignment (out of its four) instead of the one producing the smallest height, or the combination of all four."),lTe),vs),x9e),rn(Fn)))),va(t,Woe,T4,qbt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Koe),"nodePlacement.linearSegments"),"Linear Segments Deflection Dampening"),"Dampens the movement of nodes to keep the diagram from getting too large."),.3),qo),ma),rn(Fn)))),va(t,Koe,T4,Ybt),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,Yoe),"nodePlacement.networkSimplex"),"Node Flexibility"),"Aims at shorter and straighter edges. Two configurations are possible: (a) allow ports to move freely on the side they are assigned to (the order is always defined beforehand), (b) additionally allow to enlarge a node wherever it helps. If this option is not configured for a node, the 'nodeFlexibility.default' value is used, which is specified for the node's parent."),vs),ahe),rn(ua)))),va(t,Yoe,T4,Jbt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Xoe),"nodePlacement.networkSimplex.nodeFlexibility"),"Node Flexibility Default"),"Default value of the 'nodeFlexibility' option for the children of a hierarchical node."),hTe),vs),ahe),rn(Fn)))),va(t,Xoe,T4,Zbt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,wke),Mft),"Self-Loop Distribution"),"Alter the distribution of the loops around the node. It only takes effect for PortConstraints.FREE."),nTe),vs),T_e),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,mke),Mft),"Self-Loop Ordering"),"Alter the ordering of the loops they can either be stacked or sequenced. It only takes effect for PortConstraints.FREE."),rTe),vs),__e),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Uz),"edgeRouting.splines"),"Spline Routing Mode"),"Specifies the way control points are assembled for each individual edge. CONSERVATIVE ensures that edges are properly routed around the nodes but feels rather orthogonal at times. SLOPPY uses fewer control points to obtain curvier edge routes but may result in edges overlapping nodes."),iTe),vs),S_e),rn(Fn)))),va(t,Uz,VI,pbt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Wz),"edgeRouting.splines.sloppy"),"Sloppy Spline Layer Spacing Factor"),"Spacing factor for routing area between layers when using sloppy spline routing."),.2),qo),ma),rn(Fn)))),va(t,Wz,VI,vbt),va(t,Wz,Uz,wbt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Qoe),"edgeRouting.polyline"),"Sloped Edge Zone Width"),"Width of the strip to the left and to the right of each layer where the polyline edge router is allowed to refrain from ensuring that edges are routed horizontally. This prevents awkward bend points for nodes that extent almost to the edge of their layer."),2),qo),ma),rn(Fn)))),va(t,Qoe,VI,hbt),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,yke),G1),"Spacing Base Value"),"An optional base value for all other layout options of the 'spacing' group. It can be used to conveniently alter the overall 'spaciousness' of the drawing. Whenever an explicit value is set for the other layout options, this base value will have no effect. The base value is not inherited, i.e. it must be set for each hierarchical node."),qo),ma),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,kke),G1),"Edge Node Between Layers Spacing"),"The spacing to be preserved between nodes and edges that are routed next to the node's layer. For the spacing between nodes and edges that cross the node's layer 'spacing.edgeNode' is used."),10),qo),ma),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,xke),G1),"Edge Edge Between Layer Spacing"),"Spacing to be preserved between pairs of edges that are routed between the same pair of layers. Note that 'spacing.edgeEdge' is used for the spacing between pairs of edges crossing the same layer."),10),qo),ma),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Eke),G1),"Node Node Between Layers Spacing"),"The spacing to be preserved between any pair of nodes of two adjacent layers. Note that 'spacing.nodeNode' is used for the spacing between nodes within the layer itself."),20),qo),ma),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Tke),Oke),"Direction Priority"),"Defines how important it is to have a certain edge point into the direction of the overall layout. This option is evaluated during the cycle breaking phase."),ct(0)),Cc),Za),rn(Fd)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,_ke),Oke),"Shortness Priority"),"Defines how important it is to keep an edge as short as possible. This option is evaluated during the layering phase."),ct(0)),Cc),Za),rn(Fd)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Cke),Oke),"Straightness Priority"),"Defines how important it is to keep an edge straight, i.e. aligned with one of the two axes. This option is evaluated during node placement."),ct(0)),Cc),Za),rn(Fd)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Zoe),Nke),Uht),"Tries to further compact components (disconnected sub-graphs)."),!1),za),Us),rn(Fn)))),va(t,Zoe,_C,!0),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Ske),Dft),"Post Compaction Strategy"),Ift),V9e),vs),A9e),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Ake),Dft),"Post Compaction Constraint Calculation"),Ift),q9e),vs),a9e),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Kz),Pke),"High Degree Node Treatment"),"Makes room around high degree nodes to place leafs and trees."),!1),za),Us),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Joe),Pke),"High Degree Node Threshold"),"Whether a node is considered to have a high degree."),ct(16)),Cc),Za),rn(Fn)))),va(t,Joe,Kz,!0),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,ece),Pke),"High Degree Node Maximum Tree Height"),"Maximum height of a subtree connected to a high degree node to be moved to separate layers."),ct(5)),Cc),Za),rn(Fn)))),va(t,ece,Kz,!0),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,W0),Bke),"Graph Wrapping Strategy"),"For certain graphs and certain prescribed drawing areas it may be desirable to split the laid out graph into chunks that are placed side by side. The edges that connect different chunks are 'wrapped' around from the end of one chunk to the start of the other chunk. The points between the chunks are referred to as 'cuts'."),bTe),vs),D_e),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Yz),Bke),"Additional Wrapped Edges Spacing"),"To visually separate edges that are wrapped from regularly routed edges an additional spacing value can be specified in form of this layout option. The spacing is added to the regular edgeNode spacing."),10),qo),ma),rn(Fn)))),va(t,Yz,W0,fvt),va(t,Yz,W0,dvt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Xz),Bke),"Correction Factor for Wrapping"),"At times and for certain types of graphs the executed wrapping may produce results that are consistently biased in the same fashion: either wrapping to often or to rarely. This factor can be used to correct the bias. Internally, it is simply multiplied with the 'aspect ratio' layout option."),1),qo),ma),rn(Fn)))),va(t,Xz,W0,pvt),va(t,Xz,W0,bvt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,DC),Oft),"Cutting Strategy"),"The strategy by which the layer indexes are determined at which the layering crumbles into chunks."),pTe),vs),l9e),rn(Fn)))),va(t,DC,W0,xvt),va(t,DC,W0,Evt),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,tce),Oft),"Manually Specified Cuts"),"Allows the user to specify her own cuts for a certain graph."),Y1),Eh),rn(Fn)))),va(t,tce,DC,wvt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,nce),"wrapping.cutting.msd"),"MSD Freedom"),"The MSD cutting strategy starts with an initial guess on the number of chunks the graph should be split into. The freedom specifies how much the strategy may deviate from this guess. E.g. if an initial number of 3 is computed, a freedom of 1 allows 2, 3, and 4 cuts."),gTe),Cc),Za),rn(Fn)))),va(t,nce,DC,yvt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Qz),Nft),"Validification Strategy"),"When wrapping graphs, one can specify indices that are not allowed as split points. The validification strategy makes sure every computed split point is allowed."),vTe),vs),M_e),rn(Fn)))),va(t,Qz,W0,Pvt),va(t,Qz,W0,Bvt),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,Zz),Nft),"Valid Indices for Wrapping"),null),Y1),Eh),rn(Fn)))),va(t,Zz,W0,Ivt),va(t,Zz,W0,Ovt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Jz),Rke),"Improve Cuts"),"For general graphs it is important that not too many edges wrap backwards. Thus a compromise between evenly-distributed cuts and the total number of cut edges is sought."),!0),za),Us),rn(Fn)))),va(t,Jz,W0,Svt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,eG),Rke),"Distance Penalty When Improving Cuts"),null),2),qo),ma),rn(Fn)))),va(t,eG,W0,_vt),va(t,eG,Jz,!0),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,rce),Rke),"Improve Wrapped Edges"),"The initial wrapping is performed in a very simple way. As a consequence, edges that wrap from one chunk to another may be unnecessarily long. Activating this option tries to shorten such edges."),!0),za),Us),rn(Fn)))),va(t,rce,W0,Lvt),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Lke),cce),"Edge Label Side Selection"),"Method to decide on edge label sides."),tTe),vs),p9e),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Mke),cce),"Edge Center Label Placement Strategy"),"Determines in which layer center labels of long edges should be placed."),eTe),vs),sE),Ui(Fn,ie(re(Ug,1),tt,175,0,[Vg]))))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,tG),UI),"Consider Model Order"),"Preserves the order of nodes and edges in the model file if this does not lead to additional edge crossings. Depending on the strategy this is not always possible since the node and edge order might be conflicting."),K9e),vs),y_e),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Dke),UI),"No Model Order"),"Set on a node to not set a model order for this node even though it is a real node."),!1),za),Us),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,ice),UI),"Consider Model Order for Components"),"If set to NONE the usual ordering strategy (by cumulative node priority and size of nodes) is used. INSIDE_PORT_SIDES orders the components with external ports only inside the groups with the same port side. FORCE_MODEL_ORDER enforces the mode order on components. This option might produce bad alignments and sub optimal drawings in terms of used area since the ordering should be respected."),U9e),vs),fEe),rn(Fn)))),va(t,ice,_C,null),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Ike),UI),"Long Edge Ordering Strategy"),"Indicates whether long edges are sorted under, over, or equal to nodes that have no connection to a previous layer in a left-to-right or right-to-left layout. Under and over changes to right and left in a vertical layout."),W9e),vs),h_e),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,sce),UI),"Crossing Counter Node Order Influence"),"Indicates with what percentage (1 for 100%) violations of the node model order are weighted against the crossings e.g. a value of 0.5 means two model order violations are as important as on edge crossing. This allows some edge crossings in favor of preserving the model order. It is advised to set this value to a very small positive value (e.g. 0.001) to have minimal crossing and a optimal node order. Defaults to no influence (0)."),0),qo),ma),rn(Fn)))),va(t,sce,tG,null),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,ace),UI),"Crossing Counter Port Order Influence"),"Indicates with what percentage (1 for 100%) violations of the port model order are weighted against the crossings e.g. a value of 0.5 means two model order violations are as important as on edge crossing. This allows some edge crossings in favor of preserving the model order. It is advised to set this value to a very small positive value (e.g. 0.001) to have minimal crossing and a optimal port order. Defaults to no influence (0)."),0),qo),ma),rn(Fn)))),va(t,ace,tG,null),Qlt((new SR,t))};var B2t,R2t,F2t,q9e,j2t,V9e,$2t,U9e,H2t,z2t,G2t,W9e,q2t,V2t,K9e,U2t,W2t,K2t,Y9e,Y2t,X2t,Q2t,X9e,Z2t,J2t,ebt,tbt,nbt,rbt,ibt,sbt,Q9e,abt,Z9e,obt,J9e,cbt,eTe,ubt,tTe,lbt,hbt,fbt,nTe,dbt,rTe,gbt,iTe,pbt,bbt,vbt,wbt,mbt,ybt,kbt,xbt,Ebt,Tbt,sTe,_bt,Cbt,Sbt,Abt,Lbt,Mbt,aTe,Dbt,Ibt,Obt,Nbt,Pbt,Bbt,Rbt,oTe,Fbt,cTe,jbt,$bt,Hbt,uTe,zbt,Gbt,lTe,qbt,Vbt,Ubt,Wbt,Kbt,Ybt,Xbt,Qbt,hTe,Zbt,Jbt,evt,fTe,tvt,dTe,nvt,rvt,ivt,svt,avt,ovt,cvt,uvt,lvt,hvt,fvt,dvt,gvt,pvt,bvt,vvt,wvt,mvt,gTe,yvt,kvt,pTe,xvt,Evt,Tvt,_vt,Cvt,Svt,Avt,Lvt,Mvt,bTe,Dvt,Ivt,Ovt,Nvt,vTe,Pvt,Bvt;O(Ic,"LayeredMetaDataProvider",848),M(986,1,zh,SR),l.Qe=function(t){Qlt(t)};var Bd,Fle,Hq,fS,zq,wTe,Gq,Dk,qq,mTe,yTe,jle,h2,$le,My,kTe,_O,Hle,xTe,Rvt,Vq,zle,dS,Dy,Fvt,Zl,ETe,TTe,Uq,Gle,Rd,Wq,K0,_Te,CTe,STe,qle,Vle,ATe,Hg,Ule,LTe,Iy,MTe,DTe,ITe,Kq,Oy,Db,OTe,NTe,Fo,PTe,jvt,vu,Yq,BTe,RTe,FTe,Wle,jTe,Xq,$Te,HTe,Qq,Tw,zTe,Kle,gS,GTe,_w,pS,Zq,Ib,Yle,fE,Jq,Ob,qTe,VTe,UTe,dE,WTe,$vt,Hvt,zvt,Gvt,Cw,Ny,bs,zg,qvt,Py,KTe,gE,YTe,By,Vvt,pE,XTe,Ik,Uvt,Wvt,CO,Xle,QTe,SO,Mf,V4,Ok,Sw,Nb,eV,Ry,Qle,bE,vE,Aw,U4,Zle,AO,bS,vS,Jle,ZTe,JTe,e_e,t_e,ehe,n_e,r_e,i_e,s_e,the,tV;O(Ic,"LayeredOptions",986),M(987,1,{},eQ),l.$e=function(){var t;return t=new sHe,t},l._e=function(t){},O(Ic,"LayeredOptions/LayeredFactory",987),M(1372,1,{}),l.a=0;var Kvt;O(Oc,"ElkSpacings/AbstractSpacingsBuilder",1372),M(779,1372,{},Kye);var nV,Yvt;O(Ic,"LayeredSpacings/LayeredSpacingsBuilder",779),M(313,22,{3:1,35:1,22:1,313:1,246:1,234:1},GT),l.Kf=function(){return Mot(this)},l.Xf=function(){return Mot(this)};var nhe,a_e,o_e,rV,rhe,c_e,u_e=Gr(Ic,"LayeringStrategy",313,Wr,orn,eXt),Xvt;M(378,22,{3:1,35:1,22:1,378:1},_te);var ihe,l_e,iV,h_e=Gr(Ic,"LongEdgeOrderingStrategy",378,Wr,jen,tXt),Qvt;M(197,22,{3:1,35:1,22:1,197:1},$F);var W4,K4,sV,she,ahe=Gr(Ic,"NodeFlexibility",197,Wr,Utn,nXt),Zvt;M(315,22,{3:1,35:1,22:1,315:1,246:1,234:1},EM),l.Kf=function(){return got(this)},l.Xf=function(){return got(this)};var wS,ohe,che,mS,f_e,d_e=Gr(Ic,"NodePlacementStrategy",315,Wr,Lnn,cXt),Jvt;M(260,22,{3:1,35:1,22:1,260:1},k6);var g_e,LO,p_e,b_e,MO,v_e,aV,oV,w_e=Gr(Ic,"NodePromotionStrategy",260,Wr,ain,iXt),ewt;M(339,22,{3:1,35:1,22:1,339:1},Cte);var m_e,f2,uhe,y_e=Gr(Ic,"OrderingStrategy",339,Wr,Wen,sXt),twt;M(421,22,{3:1,35:1,22:1,421:1},w2e);var lhe,hhe,k_e=Gr(Ic,"PortSortingStrategy",421,Wr,XJt,aXt),nwt;M(452,22,{3:1,35:1,22:1,452:1},Ste);var ul,hu,yS,rwt=Gr(Ic,"PortType",452,Wr,Uen,rXt),iwt;M(375,22,{3:1,35:1,22:1,375:1},Ate);var x_e,fhe,E_e,T_e=Gr(Ic,"SelfLoopDistributionStrategy",375,Wr,Ken,oXt),swt;M(376,22,{3:1,35:1,22:1,376:1},m2e);var DO,dhe,__e=Gr(Ic,"SelfLoopOrderingStrategy",376,Wr,VJt,uXt),awt;M(304,1,{304:1},Jut),O(Ic,"Spacings",304),M(336,22,{3:1,35:1,22:1,336:1},Lte);var ghe,C_e,kS,S_e=Gr(Ic,"SplineRoutingMode",336,Wr,Xen,lXt),owt;M(338,22,{3:1,35:1,22:1,338:1},Mte);var phe,A_e,L_e,M_e=Gr(Ic,"ValidifyStrategy",338,Wr,Qen,hXt),cwt;M(377,22,{3:1,35:1,22:1,377:1},Dte);var Fy,bhe,wE,D_e=Gr(Ic,"WrappingStrategy",377,Wr,Yen,fXt),uwt;M(1383,1,Qc,KJ),l.Yf=function(t){return u(t,37),lwt},l.pf=function(t,n){Hvn(this,u(t,37),n)};var lwt;O(sG,"DepthFirstCycleBreaker",1383),M(782,1,Qc,Ive),l.Yf=function(t){return u(t,37),hwt},l.pf=function(t,n){jyn(this,u(t,37),n)},l.Zf=function(t){return u(St(t,BH(this.d,t.c.length)),10)};var hwt;O(sG,"GreedyCycleBreaker",782),M(1386,782,Qc,Fqe),l.Zf=function(t){var n,r,s,o;for(o=null,n=Ei,s=new C(t);s.a1&&(It(Mt(K(Ya((xn(0,t.c.length),u(t.c[0],10))),(pt(),My))))?Tot(t,this.d,u(this,660)):(hn(),aa(t,this.d)),qtt(this.e,t))},l.Sf=function(t,n,r,s){var o,h,d,v,x,_,L;for(n!=dKe(r,t.length)&&(h=t[n-(r?1:-1)],rme(this.f,h,r?(vo(),hu):(vo(),ul))),o=t[n][0],L=!s||o.k==(zn(),Ls),_=O1(t[n]),this.ag(_,L,!1,r),d=0,x=new C(_);x.a"),t0?hre(this.a,t[n-1],t[n]):!r&&n1&&(It(Mt(K(Ya((xn(0,t.c.length),u(t.c[0],10))),(pt(),My))))?Tot(t,this.d,this):(hn(),aa(t,this.d)),It(Mt(K(Ya((xn(0,t.c.length),u(t.c[0],10))),My)))||qtt(this.e,t))},O(Qu,"ModelOrderBarycenterHeuristic",660),M(1803,1,ji,xje),l.ue=function(t,n){return t1n(this.a,u(t,10),u(n,10))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Qu,"ModelOrderBarycenterHeuristic/lambda$0$Type",1803),M(1403,1,Qc,ZJ),l.Yf=function(t){var n;return u(t,37),n=JF(Twt),xi(n,(ro(),bu),(po(),bq)),n},l.pf=function(t,n){$Jt((u(t,37),n))};var Twt;O(Qu,"NoCrossingMinimizer",1403),M(796,402,mxe,zpe),l.$f=function(t,n,r){var s,o,h,d,v,x,_,L,P,z,q;switch(P=this.g,r.g){case 1:{for(o=0,h=0,L=new C(t.j);L.a1&&(o.j==(ht(),$n)?this.b[t]=!0:o.j==Dn&&t>0&&(this.b[t-1]=!0))},l.f=0,O(u0,"AllCrossingsCounter",1798),M(587,1,{},Z$),l.b=0,l.d=0,O(u0,"BinaryIndexedTree",587),M(524,1,{},zM);var N_e,uV;O(u0,"CrossingsCounter",524),M(1906,1,ji,Eje),l.ue=function(t,n){return GQt(this.a,u(t,11),u(n,11))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(u0,"CrossingsCounter/lambda$0$Type",1906),M(1907,1,ji,Tje),l.ue=function(t,n){return qQt(this.a,u(t,11),u(n,11))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(u0,"CrossingsCounter/lambda$1$Type",1907),M(1908,1,ji,_je),l.ue=function(t,n){return VQt(this.a,u(t,11),u(n,11))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(u0,"CrossingsCounter/lambda$2$Type",1908),M(1909,1,ji,Cje),l.ue=function(t,n){return UQt(this.a,u(t,11),u(n,11))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(u0,"CrossingsCounter/lambda$3$Type",1909),M(1910,1,Un,Sje),l.td=function(t){Srn(this.a,u(t,11))},O(u0,"CrossingsCounter/lambda$4$Type",1910),M(1911,1,vi,Aje),l.Mb=function(t){return HUt(this.a,u(t,11))},O(u0,"CrossingsCounter/lambda$5$Type",1911),M(1912,1,Un,Lje),l.td=function(t){Nqe(this,t)},O(u0,"CrossingsCounter/lambda$6$Type",1912),M(1913,1,Un,aqe),l.td=function(t){var n;h8(),$p(this.b,(n=this.a,u(t,11),n))},O(u0,"CrossingsCounter/lambda$7$Type",1913),M(826,1,_d,IB),l.Lb=function(t){return h8(),ta(u(t,11),(et(),cl))},l.Fb=function(t){return this===t},l.Mb=function(t){return h8(),ta(u(t,11),(et(),cl))},O(u0,"CrossingsCounter/lambda$8$Type",826),M(1905,1,{},Mje),O(u0,"HyperedgeCrossingsCounter",1905),M(467,1,{35:1,467:1},XUe),l.wd=function(t){return Tcn(this,u(t,467))},l.b=0,l.c=0,l.e=0,l.f=0;var y3n=O(u0,"HyperedgeCrossingsCounter/Hyperedge",467);M(362,1,{35:1,362:1},Xj),l.wd=function(t){return x0n(this,u(t,362))},l.b=0,l.c=0;var _wt=O(u0,"HyperedgeCrossingsCounter/HyperedgeCorner",362);M(523,22,{3:1,35:1,22:1,523:1},y2e);var ES,TS,Cwt=Gr(u0,"HyperedgeCrossingsCounter/HyperedgeCorner/Type",523,Wr,QJt,gXt),Swt;M(1405,1,Qc,WJ),l.Yf=function(t){return u(K(u(t,37),(et(),eu)),21).Hc((mo(),Th))?Awt:null},l.pf=function(t,n){Gln(this,u(t,37),n)};var Awt;O(ko,"InteractiveNodePlacer",1405),M(1406,1,Qc,UJ),l.Yf=function(t){return u(K(u(t,37),(et(),eu)),21).Hc((mo(),Th))?Lwt:null},l.pf=function(t,n){Sun(this,u(t,37),n)};var Lwt,lV,hV;O(ko,"LinearSegmentsNodePlacer",1406),M(257,1,{35:1,257:1},wpe),l.wd=function(t){return JVt(this,u(t,257))},l.Fb=function(t){var n;return we(t,257)?(n=u(t,257),this.b==n.b):!1},l.Hb=function(){return this.b},l.Ib=function(){return"ls"+Yp(this.e)},l.a=0,l.b=0,l.c=-1,l.d=-1,l.g=0;var Mwt=O(ko,"LinearSegmentsNodePlacer/LinearSegment",257);M(1408,1,Qc,EKe),l.Yf=function(t){return u(K(u(t,37),(et(),eu)),21).Hc((mo(),Th))?Dwt:null},l.pf=function(t,n){Dyn(this,u(t,37),n)},l.b=0,l.g=0;var Dwt;O(ko,"NetworkSimplexPlacer",1408),M(1427,1,ji,sQ),l.ue=function(t,n){return Tu(u(t,19).a,u(n,19).a)},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(ko,"NetworkSimplexPlacer/0methodref$compare$Type",1427),M(1429,1,ji,aQ),l.ue=function(t,n){return Tu(u(t,19).a,u(n,19).a)},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(ko,"NetworkSimplexPlacer/1methodref$compare$Type",1429),M(649,1,{649:1},oqe);var k3n=O(ko,"NetworkSimplexPlacer/EdgeRep",649);M(401,1,{401:1},lwe),l.b=!1;var x3n=O(ko,"NetworkSimplexPlacer/NodeRep",401);M(508,12,{3:1,4:1,20:1,28:1,52:1,12:1,14:1,15:1,54:1,508:1},bHe),O(ko,"NetworkSimplexPlacer/Path",508),M(1409,1,{},oQ),l.Kb=function(t){return u(t,17).d.i.k},O(ko,"NetworkSimplexPlacer/Path/lambda$0$Type",1409),M(1410,1,vi,cQ),l.Mb=function(t){return u(t,267)==(zn(),ca)},O(ko,"NetworkSimplexPlacer/Path/lambda$1$Type",1410),M(1411,1,{},uQ),l.Kb=function(t){return u(t,17).d.i},O(ko,"NetworkSimplexPlacer/Path/lambda$2$Type",1411),M(1412,1,vi,Dje),l.Mb=function(t){return NUe(krt(u(t,10)))},O(ko,"NetworkSimplexPlacer/Path/lambda$3$Type",1412),M(1413,1,vi,lQ),l.Mb=function(t){return IQt(u(t,11))},O(ko,"NetworkSimplexPlacer/lambda$0$Type",1413),M(1414,1,Un,cqe),l.td=function(t){LWt(this.a,this.b,u(t,11))},O(ko,"NetworkSimplexPlacer/lambda$1$Type",1414),M(1423,1,Un,Ije),l.td=function(t){Y1n(this.a,u(t,17))},O(ko,"NetworkSimplexPlacer/lambda$10$Type",1423),M(1424,1,{},hQ),l.Kb=function(t){return $l(),new vn(null,new mn(u(t,29).a,16))},O(ko,"NetworkSimplexPlacer/lambda$11$Type",1424),M(1425,1,Un,Oje),l.td=function(t){Vpn(this.a,u(t,10))},O(ko,"NetworkSimplexPlacer/lambda$12$Type",1425),M(1426,1,{},fQ),l.Kb=function(t){return $l(),ct(u(t,121).e)},O(ko,"NetworkSimplexPlacer/lambda$13$Type",1426),M(1428,1,{},dQ),l.Kb=function(t){return $l(),ct(u(t,121).e)},O(ko,"NetworkSimplexPlacer/lambda$15$Type",1428),M(1430,1,vi,gQ),l.Mb=function(t){return $l(),u(t,401).c.k==(zn(),Hs)},O(ko,"NetworkSimplexPlacer/lambda$17$Type",1430),M(1431,1,vi,pQ),l.Mb=function(t){return $l(),u(t,401).c.j.c.length>1},O(ko,"NetworkSimplexPlacer/lambda$18$Type",1431),M(1432,1,Un,MYe),l.td=function(t){Pon(this.c,this.b,this.d,this.a,u(t,401))},l.c=0,l.d=0,O(ko,"NetworkSimplexPlacer/lambda$19$Type",1432),M(1415,1,{},bQ),l.Kb=function(t){return $l(),new vn(null,new mn(u(t,29).a,16))},O(ko,"NetworkSimplexPlacer/lambda$2$Type",1415),M(1433,1,Un,Nje),l.td=function(t){SWt(this.a,u(t,11))},l.a=0,O(ko,"NetworkSimplexPlacer/lambda$20$Type",1433),M(1434,1,{},V5),l.Kb=function(t){return $l(),new vn(null,new mn(u(t,29).a,16))},O(ko,"NetworkSimplexPlacer/lambda$21$Type",1434),M(1435,1,Un,Pje),l.td=function(t){zWt(this.a,u(t,10))},O(ko,"NetworkSimplexPlacer/lambda$22$Type",1435),M(1436,1,vi,OB),l.Mb=function(t){return NUe(t)},O(ko,"NetworkSimplexPlacer/lambda$23$Type",1436),M(1437,1,{},vQ),l.Kb=function(t){return $l(),new vn(null,new mn(u(t,29).a,16))},O(ko,"NetworkSimplexPlacer/lambda$24$Type",1437),M(1438,1,vi,Bje),l.Mb=function(t){return KUt(this.a,u(t,10))},O(ko,"NetworkSimplexPlacer/lambda$25$Type",1438),M(1439,1,Un,uqe),l.td=function(t){v1n(this.a,this.b,u(t,10))},O(ko,"NetworkSimplexPlacer/lambda$26$Type",1439),M(1440,1,vi,wQ),l.Mb=function(t){return $l(),!to(u(t,17))},O(ko,"NetworkSimplexPlacer/lambda$27$Type",1440),M(1441,1,vi,mQ),l.Mb=function(t){return $l(),!to(u(t,17))},O(ko,"NetworkSimplexPlacer/lambda$28$Type",1441),M(1442,1,{},Rje),l.Ce=function(t,n){return jWt(this.a,u(t,29),u(n,29))},O(ko,"NetworkSimplexPlacer/lambda$29$Type",1442),M(1416,1,{},NB),l.Kb=function(t){return $l(),new vn(null,new Sv(new cr(fr(js(u(t,10)).a.Kc(),new V))))},O(ko,"NetworkSimplexPlacer/lambda$3$Type",1416),M(1417,1,vi,yQ),l.Mb=function(t){return $l(),Ctn(u(t,17))},O(ko,"NetworkSimplexPlacer/lambda$4$Type",1417),M(1418,1,Un,Fje),l.td=function(t){qbn(this.a,u(t,17))},O(ko,"NetworkSimplexPlacer/lambda$5$Type",1418),M(1419,1,{},N9),l.Kb=function(t){return $l(),new vn(null,new mn(u(t,29).a,16))},O(ko,"NetworkSimplexPlacer/lambda$6$Type",1419),M(1420,1,vi,kQ),l.Mb=function(t){return $l(),u(t,10).k==(zn(),Hs)},O(ko,"NetworkSimplexPlacer/lambda$7$Type",1420),M(1421,1,{},xQ),l.Kb=function(t){return $l(),new vn(null,new Sv(new cr(fr(j0(u(t,10)).a.Kc(),new V))))},O(ko,"NetworkSimplexPlacer/lambda$8$Type",1421),M(1422,1,vi,EQ),l.Mb=function(t){return $l(),CQt(u(t,17))},O(ko,"NetworkSimplexPlacer/lambda$9$Type",1422),M(1404,1,Qc,sT),l.Yf=function(t){return u(K(u(t,37),(et(),eu)),21).Hc((mo(),Th))?Iwt:null},l.pf=function(t,n){_vn(u(t,37),n)};var Iwt;O(ko,"SimpleNodePlacer",1404),M(180,1,{180:1},p4),l.Ib=function(){var t;return t="",this.c==(yd(),Lw)?t+=lk:this.c==Gg&&(t+=uk),this.o==(M1(),Pb)?t+=voe:this.o==K1?t+="UP":t+="BALANCED",t},O(r2,"BKAlignedLayout",180),M(516,22,{3:1,35:1,22:1,516:1},x2e);var Gg,Lw,Owt=Gr(r2,"BKAlignedLayout/HDirection",516,Wr,JJt,pXt),Nwt;M(515,22,{3:1,35:1,22:1,515:1},k2e);var Pb,K1,Pwt=Gr(r2,"BKAlignedLayout/VDirection",515,Wr,een,bXt),Bwt;M(1634,1,{},lqe),O(r2,"BKAligner",1634),M(1637,1,{},Vit),O(r2,"BKCompactor",1637),M(654,1,{654:1},TQ),l.a=0,O(r2,"BKCompactor/ClassEdge",654),M(458,1,{458:1},gHe),l.a=null,l.b=0,O(r2,"BKCompactor/ClassNode",458),M(1407,1,Qc,Bqe),l.Yf=function(t){return u(K(u(t,37),(et(),eu)),21).Hc((mo(),Th))?Rwt:null},l.pf=function(t,n){Uyn(this,u(t,37),n)},l.d=!1;var Rwt;O(r2,"BKNodePlacer",1407),M(1635,1,{},_Q),l.d=0,O(r2,"NeighborhoodInformation",1635),M(1636,1,ji,jje),l.ue=function(t,n){return Jrn(this,u(t,46),u(n,46))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(r2,"NeighborhoodInformation/NeighborComparator",1636),M(808,1,{}),O(r2,"ThresholdStrategy",808),M(1763,808,{},mHe),l.bg=function(t,n,r){return this.a.o==(M1(),K1)?gs:Ds},l.cg=function(){},O(r2,"ThresholdStrategy/NullThresholdStrategy",1763),M(579,1,{579:1},hqe),l.c=!1,l.d=!1,O(r2,"ThresholdStrategy/Postprocessable",579),M(1764,808,{},yHe),l.bg=function(t,n,r){var s,o,h;return o=n==r,s=this.a.a[r.p]==n,o||s?(h=t,this.a.c==(yd(),Lw)?(o&&(h=vae(this,n,!0)),!isNaN(h)&&!isFinite(h)&&s&&(h=vae(this,r,!1))):(o&&(h=vae(this,n,!0)),!isNaN(h)&&!isFinite(h)&&s&&(h=vae(this,r,!1))),h):t},l.cg=function(){for(var t,n,r,s,o;this.d.b!=0;)o=u(ben(this.d),579),s=fut(this,o),s.a&&(t=s.a,r=It(this.a.f[this.a.g[o.b.p].p]),!(!r&&!to(t)&&t.c.i.c==t.d.i.c)&&(n=mot(this,o),n||nWt(this.e,o)));for(;this.e.a.c.length!=0;)mot(this,u(Lnt(this.e),579))},O(r2,"ThresholdStrategy/SimpleThresholdStrategy",1764),M(635,1,{635:1,246:1,234:1},CQ),l.Kf=function(){return jtt(this)},l.Xf=function(){return jtt(this)};var vhe;O(dce,"EdgeRouterFactory",635),M(1458,1,Qc,hd),l.Yf=function(t){return Tpn(u(t,37))},l.pf=function(t,n){Ivn(u(t,37),n)};var Fwt,jwt,$wt,Hwt,zwt,P_e,Gwt,qwt;O(dce,"OrthogonalEdgeRouter",1458),M(1451,1,Qc,Rqe),l.Yf=function(t){return Kln(u(t,37))},l.pf=function(t,n){Zmn(this,u(t,37),n)};var Vwt,Uwt,Wwt,Kwt,OO,Ywt;O(dce,"PolylineEdgeRouter",1451),M(1452,1,_d,SQ),l.Lb=function(t){return Qme(u(t,10))},l.Fb=function(t){return this===t},l.Mb=function(t){return Qme(u(t,10))},O(dce,"PolylineEdgeRouter/1",1452),M(1809,1,vi,AQ),l.Mb=function(t){return u(t,129).c==(Jf(),d2)},O(o1,"HyperEdgeCycleDetector/lambda$0$Type",1809),M(1810,1,{},LQ),l.Ge=function(t){return u(t,129).d},O(o1,"HyperEdgeCycleDetector/lambda$1$Type",1810),M(1811,1,vi,MQ),l.Mb=function(t){return u(t,129).c==(Jf(),d2)},O(o1,"HyperEdgeCycleDetector/lambda$2$Type",1811),M(1812,1,{},U5),l.Ge=function(t){return u(t,129).d},O(o1,"HyperEdgeCycleDetector/lambda$3$Type",1812),M(1813,1,{},DQ),l.Ge=function(t){return u(t,129).d},O(o1,"HyperEdgeCycleDetector/lambda$4$Type",1813),M(1814,1,{},IQ),l.Ge=function(t){return u(t,129).d},O(o1,"HyperEdgeCycleDetector/lambda$5$Type",1814),M(112,1,{35:1,112:1},AD),l.wd=function(t){return eUt(this,u(t,112))},l.Fb=function(t){var n;return we(t,112)?(n=u(t,112),this.g==n.g):!1},l.Hb=function(){return this.g},l.Ib=function(){var t,n,r,s;for(t=new Fl("{"),s=new C(this.n);s.a"+this.b+" ("+hKt(this.c)+")"},l.d=0,O(o1,"HyperEdgeSegmentDependency",129),M(520,22,{3:1,35:1,22:1,520:1},E2e);var d2,jy,Xwt=Gr(o1,"HyperEdgeSegmentDependency/DependencyType",520,Wr,ZJt,vXt),Qwt;M(1815,1,{},$je),O(o1,"HyperEdgeSegmentSplitter",1815),M(1816,1,{},vze),l.a=0,l.b=0,O(o1,"HyperEdgeSegmentSplitter/AreaRating",1816),M(329,1,{329:1},vne),l.a=0,l.b=0,l.c=0,O(o1,"HyperEdgeSegmentSplitter/FreeArea",329),M(1817,1,ji,jQ),l.ue=function(t,n){return oYt(u(t,112),u(n,112))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(o1,"HyperEdgeSegmentSplitter/lambda$0$Type",1817),M(1818,1,Un,DYe),l.td=function(t){fnn(this.a,this.d,this.c,this.b,u(t,112))},l.b=0,O(o1,"HyperEdgeSegmentSplitter/lambda$1$Type",1818),M(1819,1,{},$Q),l.Kb=function(t){return new vn(null,new mn(u(t,112).e,16))},O(o1,"HyperEdgeSegmentSplitter/lambda$2$Type",1819),M(1820,1,{},HQ),l.Kb=function(t){return new vn(null,new mn(u(t,112).j,16))},O(o1,"HyperEdgeSegmentSplitter/lambda$3$Type",1820),M(1821,1,{},zQ),l.Fe=function(t){return Ue(ft(t))},O(o1,"HyperEdgeSegmentSplitter/lambda$4$Type",1821),M(655,1,{},Hne),l.a=0,l.b=0,l.c=0,O(o1,"OrthogonalRoutingGenerator",655),M(1638,1,{},GQ),l.Kb=function(t){return new vn(null,new mn(u(t,112).e,16))},O(o1,"OrthogonalRoutingGenerator/lambda$0$Type",1638),M(1639,1,{},qQ),l.Kb=function(t){return new vn(null,new mn(u(t,112).j,16))},O(o1,"OrthogonalRoutingGenerator/lambda$1$Type",1639),M(661,1,{}),O(gce,"BaseRoutingDirectionStrategy",661),M(1807,661,{},kHe),l.dg=function(t,n,r){var s,o,h,d,v,x,_,L,P,z,q,W,X;if(!(t.r&&!t.q))for(L=n+t.o*r,_=new C(t.n);_.a<_.c.c.length;)for(x=u(Y(_),11),P=sc(ie(re(na,1),Qe,8,0,[x.i.n,x.n,x.a])).a,v=new C(x.g);v.aSd&&(h=L,o=t,s=new Pt(P,h),ci(d.a,s),rw(this,d,o,s,!1),z=t.r,z&&(q=Ue(ft(s1(z.e,0))),s=new Pt(q,h),ci(d.a,s),rw(this,d,o,s,!1),h=n+z.o*r,o=z,s=new Pt(q,h),ci(d.a,s),rw(this,d,o,s,!1)),s=new Pt(X,h),ci(d.a,s),rw(this,d,o,s,!1)))},l.eg=function(t){return t.i.n.a+t.n.a+t.a.a},l.fg=function(){return ht(),xr},l.gg=function(){return ht(),An},O(gce,"NorthToSouthRoutingStrategy",1807),M(1808,661,{},xHe),l.dg=function(t,n,r){var s,o,h,d,v,x,_,L,P,z,q,W,X;if(!(t.r&&!t.q))for(L=n-t.o*r,_=new C(t.n);_.a<_.c.c.length;)for(x=u(Y(_),11),P=sc(ie(re(na,1),Qe,8,0,[x.i.n,x.n,x.a])).a,v=new C(x.g);v.aSd&&(h=L,o=t,s=new Pt(P,h),ci(d.a,s),rw(this,d,o,s,!1),z=t.r,z&&(q=Ue(ft(s1(z.e,0))),s=new Pt(q,h),ci(d.a,s),rw(this,d,o,s,!1),h=n-z.o*r,o=z,s=new Pt(q,h),ci(d.a,s),rw(this,d,o,s,!1)),s=new Pt(X,h),ci(d.a,s),rw(this,d,o,s,!1)))},l.eg=function(t){return t.i.n.a+t.n.a+t.a.a},l.fg=function(){return ht(),An},l.gg=function(){return ht(),xr},O(gce,"SouthToNorthRoutingStrategy",1808),M(1806,661,{},EHe),l.dg=function(t,n,r){var s,o,h,d,v,x,_,L,P,z,q,W,X;if(!(t.r&&!t.q))for(L=n+t.o*r,_=new C(t.n);_.a<_.c.c.length;)for(x=u(Y(_),11),P=sc(ie(re(na,1),Qe,8,0,[x.i.n,x.n,x.a])).b,v=new C(x.g);v.aSd&&(h=L,o=t,s=new Pt(h,P),ci(d.a,s),rw(this,d,o,s,!0),z=t.r,z&&(q=Ue(ft(s1(z.e,0))),s=new Pt(h,q),ci(d.a,s),rw(this,d,o,s,!0),h=n+z.o*r,o=z,s=new Pt(h,q),ci(d.a,s),rw(this,d,o,s,!0)),s=new Pt(h,X),ci(d.a,s),rw(this,d,o,s,!0)))},l.eg=function(t){return t.i.n.b+t.n.b+t.a.b},l.fg=function(){return ht(),$n},l.gg=function(){return ht(),Dn},O(gce,"WestToEastRoutingStrategy",1806),M(813,1,{},G5e),l.Ib=function(){return Yp(this.a)},l.b=0,l.c=!1,l.d=!1,l.f=0,O(vy,"NubSpline",813),M(407,1,{407:1},Kot,hXe),O(vy,"NubSpline/PolarCP",407),M(1453,1,Qc,Rit),l.Yf=function(t){return Rhn(u(t,37))},l.pf=function(t,n){vyn(this,u(t,37),n)};var Zwt,Jwt,emt,tmt,nmt;O(vy,"SplineEdgeRouter",1453),M(268,1,{268:1},x$),l.Ib=function(){return this.a+" ->("+this.c+") "+this.b},l.c=0,O(vy,"SplineEdgeRouter/Dependency",268),M(455,22,{3:1,35:1,22:1,455:1},T2e);var g2,Y4,rmt=Gr(vy,"SplineEdgeRouter/SideToProcess",455,Wr,ten,wXt),imt;M(1454,1,vi,FQ),l.Mb=function(t){return aC(),!u(t,128).o},O(vy,"SplineEdgeRouter/lambda$0$Type",1454),M(1455,1,{},RQ),l.Ge=function(t){return aC(),u(t,128).v+1},O(vy,"SplineEdgeRouter/lambda$1$Type",1455),M(1456,1,Un,fqe),l.td=function(t){AQt(this.a,this.b,u(t,46))},O(vy,"SplineEdgeRouter/lambda$2$Type",1456),M(1457,1,Un,dqe),l.td=function(t){LQt(this.a,this.b,u(t,46))},O(vy,"SplineEdgeRouter/lambda$3$Type",1457),M(128,1,{35:1,128:1},hat,Y5e),l.wd=function(t){return tUt(this,u(t,128))},l.b=0,l.e=!1,l.f=0,l.g=0,l.j=!1,l.k=!1,l.n=0,l.o=!1,l.p=!1,l.q=!1,l.s=0,l.u=0,l.v=0,l.F=0,O(vy,"SplineSegment",128),M(459,1,{459:1},P9),l.a=0,l.b=!1,l.c=!1,l.d=!1,l.e=!1,l.f=0,O(vy,"SplineSegment/EdgeInformation",459),M(1234,1,{},OQ),O(IC,q6e,1234),M(1235,1,ji,NQ),l.ue=function(t,n){return hdn(u(t,135),u(n,135))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(IC,Yht,1235),M(1233,1,{},Oze),O(IC,"MrTree",1233),M(393,22,{3:1,35:1,22:1,393:1,246:1,234:1},HF),l.Kf=function(){return Bat(this)},l.Xf=function(){return Bat(this)};var fV,_S,NO,CS,B_e=Gr(IC,"TreeLayoutPhases",393,Wr,Wtn,mXt),smt;M(1130,209,mb,JUe),l.Ze=function(t,n){var r,s,o,h,d,v,x;for(It(Mt(Ft(t,(nw(),z_e))))||i$((r=new sr((Tm(),new ym(t))),r)),d=(v=new E$,Ho(v,t),Ye(v,(Tc(),LS),t),x=new Mr,nbn(t,v,x),mbn(t,v,x),v),h=fbn(this.a,d),o=new C(h);o.a"+h$(this.c):"e_"+Xi(this)},O(OC,"TEdge",188),M(135,134,{3:1,135:1,94:1,134:1},E$),l.Ib=function(){var t,n,r,s,o;for(o=null,s=ii(this.b,0);s.b!=s.d.c;)r=u(ri(s),86),o+=(r.c==null||r.c.length==0?"n_"+r.g:"n_"+r.c)+` +`;for(n=ii(this.a,0);n.b!=n.d.c;)t=u(ri(n),188),o+=(t.b&&t.c?h$(t.b)+"->"+h$(t.c):"e_"+Xi(t))+` +`;return o};var E3n=O(OC,"TGraph",135);M(633,502,{3:1,502:1,633:1,94:1,134:1}),O(OC,"TShape",633),M(86,633,{3:1,502:1,86:1,633:1,94:1,134:1},vie),l.Ib=function(){return h$(this)};var T3n=O(OC,"TNode",86);M(255,1,i0,Ep),l.Jc=function(t){Da(this,t)},l.Kc=function(){var t;return t=ii(this.a.d,0),new f6(t)},O(OC,"TNode/2",255),M(358,1,ga,f6),l.Nb=function(t){La(this,t)},l.Pb=function(){return u(ri(this.a),188).c},l.Ob=function(){return vF(this.a)},l.Qb=function(){F$(this.a)},O(OC,"TNode/2/1",358),M(1840,1,ps,ZUe),l.pf=function(t,n){Pbn(this,u(t,135),n)},O(vk,"FanProcessor",1840),M(327,22,{3:1,35:1,22:1,327:1,234:1},qT),l.Kf=function(){switch(this.g){case 0:return new FHe;case 1:return new ZUe;case 2:return new W5;case 3:return new VQ;case 4:return new WQ;case 5:return new IL;default:throw J(new Ln(Noe+(this.f!=null?this.f:""+this.g)))}};var whe,mhe,yhe,khe,xhe,dV,amt=Gr(vk,tke,327,Wr,urn,yXt),omt;M(1843,1,ps,VQ),l.pf=function(t,n){v0n(this,u(t,135),n)},l.a=0,O(vk,"LevelHeightProcessor",1843),M(1844,1,i0,UQ),l.Jc=function(t){Da(this,t)},l.Kc=function(){return hn(),e8(),Y7},O(vk,"LevelHeightProcessor/1",1844),M(1841,1,ps,W5),l.pf=function(t,n){T1n(this,u(t,135),n)},l.a=0,O(vk,"NeighborsProcessor",1841),M(1842,1,i0,PB),l.Jc=function(t){Da(this,t)},l.Kc=function(){return hn(),e8(),Y7},O(vk,"NeighborsProcessor/1",1842),M(1845,1,ps,WQ),l.pf=function(t,n){b0n(this,u(t,135),n)},l.a=0,O(vk,"NodePositionProcessor",1845),M(1839,1,ps,FHe),l.pf=function(t,n){zvn(this,u(t,135))},O(vk,"RootProcessor",1839),M(1846,1,ps,IL),l.pf=function(t,n){Qan(u(t,135))},O(vk,"Untreeifyer",1846);var PO,SS,cmt,Ehe,gV,AS,The,pV,bV,mE,LS,vV,qg,R_e,umt,_he,$y,Che,F_e;M(851,1,zh,E3),l.Qe=function(t){en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,yxe),""),"Weighting of Nodes"),"Which weighting to use when computing a node order."),$_e),(Ng(),vs)),W_e),rn((i1(),Fn))))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,kxe),""),"Search Order"),"Which search order to use when computing a spanning tree."),j_e),vs),Y_e),rn(Fn)))),clt((new WL,t))};var lmt,j_e,hmt,$_e;O(oG,"MrTreeMetaDataProvider",851),M(994,1,zh,WL),l.Qe=function(t){clt(t)};var fmt,H_e,dmt,gmt,pmt,bmt,z_e,vmt,G_e,wmt,wV,q_e,mmt,V_e,ymt;O(oG,"MrTreeOptions",994),M(995,1,{},KQ),l.$e=function(){var t;return t=new JUe,t},l._e=function(t){},O(oG,"MrTreeOptions/MrtreeFactory",995),M(480,22,{3:1,35:1,22:1,480:1},_2e);var She,U_e,W_e=Gr(oG,"OrderWeighting",480,Wr,ren,kXt),kmt;M(425,22,{3:1,35:1,22:1,425:1},C2e);var K_e,Ahe,Y_e=Gr(oG,"TreeifyingOrder",425,Wr,nen,EXt),xmt;M(1459,1,Qc,UL),l.Yf=function(t){return u(t,135),Emt},l.pf=function(t,n){Xin(this,u(t,135),n)};var Emt;O("org.eclipse.elk.alg.mrtree.p1treeify","DFSTreeifyer",1459),M(1460,1,Qc,XJ),l.Yf=function(t){return u(t,135),Tmt},l.pf=function(t,n){N1n(this,u(t,135),n)};var Tmt;O("org.eclipse.elk.alg.mrtree.p2order","NodeOrderer",1460),M(1461,1,Qc,YJ),l.Yf=function(t){return u(t,135),_mt},l.pf=function(t,n){Qpn(this,u(t,135),n)},l.a=0;var _mt;O("org.eclipse.elk.alg.mrtree.p3place","NodePlacer",1461),M(1462,1,Qc,LR),l.Yf=function(t){return u(t,135),Cmt},l.pf=function(t,n){Eln(u(t,135),n)};var Cmt;O("org.eclipse.elk.alg.mrtree.p4route","EdgeRouter",1462);var MS;M(495,22,{3:1,35:1,22:1,495:1,246:1,234:1},S2e),l.Kf=function(){return grt(this)},l.Xf=function(){return grt(this)};var mV,yE,X_e=Gr(xxe,"RadialLayoutPhases",495,Wr,ien,xXt),Smt;M(1131,209,mb,Ize),l.Ze=function(t,n){var r,s,o,h,d,v;if(r=vat(this,t),kr(n,"Radial layout",r.c.length),It(Mt(Ft(t,(Jm(),aCe))))||i$((s=new sr((Tm(),new ym(t))),s)),v=$hn(t),So(t,(a_(),MS),v),!v)throw J(new Ln("The given graph is not a tree!"));for(o=Ue(ft(Ft(t,xV))),o==0&&(o=Dat(t)),So(t,xV,o),d=new C(vat(this,t));d.a0&&jnt((zr(n-1,t.length),t.charCodeAt(n-1)),aft);)--n;if(s>=n)throw J(new Ln("The given string does not contain any numbers."));if(o=cy(t.substr(s,n-s),`,|;|\r| +`),o.length!=2)throw J(new Ln("Exactly two numbers are expected, "+o.length+" were found."));try{this.a=ry(ny(o[0])),this.b=ry(ny(o[1]))}catch(h){throw h=ts(h),we(h,127)?(r=h,J(new Ln(oft+r))):J(h)}},l.Ib=function(){return"("+this.a+","+this.b+")"},l.a=0,l.b=0;var na=O(HI,"KVector",8);M(74,68,{3:1,4:1,20:1,28:1,52:1,14:1,68:1,15:1,74:1,414:1},Gu,pF,kUe),l.Pc=function(){return uan(this)},l.Jf=function(t){var n,r,s,o,h,d;s=cy(t,`,|;|\\(|\\)|\\[|\\]|\\{|\\}| | | +`),Rh(this);try{for(r=0,h=0,o=0,d=0;r0&&(h%2==0?o=ry(s[r]):d=ry(s[r]),h>0&&h%2!=0&&ci(this,new Pt(o,d)),++h),++r}catch(v){throw v=ts(v),we(v,127)?(n=v,J(new Ln("The given string does not match the expected format for vectors."+n))):J(v)}},l.Ib=function(){var t,n,r;for(t=new Fl("("),n=ii(this,0);n.b!=n.d.c;)r=u(ri(n),8),Yr(t,r.a+","+r.b),n.b!=n.d.c&&(t.a+="; ");return(t.a+=")",t).a};var sSe=O(HI,"KVectorChain",74);M(248,22,{3:1,35:1,22:1,248:1},VT);var Yhe,LV,MV,jO,$O,DV,aSe=Gr(qh,"Alignment",248,Wr,rrn,$Xt),Uyt;M(979,1,zh,JJ),l.Qe=function(t){rut(t)};var oSe,Xhe,Wyt,cSe,uSe,Kyt,lSe,Yyt,Xyt,hSe,fSe,Qyt;O(qh,"BoxLayouterOptions",979),M(980,1,{},MZ),l.$e=function(){var t;return t=new BZ,t},l._e=function(t){},O(qh,"BoxLayouterOptions/BoxFactory",980),M(291,22,{3:1,35:1,22:1,291:1},UT);var HO,Qhe,zO,GO,qO,Zhe,Jhe=Gr(qh,"ContentAlignment",291,Wr,nrn,HXt),Zyt;M(684,1,zh,wp),l.Qe=function(t){en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,n1t),""),"Layout Algorithm"),"Select a specific layout algorithm."),(Ng(),kE)),mt),rn((i1(),Fn))))),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,r1t),""),"Resolved Layout Algorithm"),"Meta data associated with the selected algorithm."),Y1),S3n),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Zke),""),"Alignment"),"Alignment of the selected node relative to other nodes; the exact meaning depends on the used algorithm."),dSe),vs),aSe),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,fk),""),"Aspect Ratio"),"The desired aspect ratio of the drawing, that is the quotient of width by height."),qo),ma),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,Uxe),""),"Bend Points"),"A fixed list of bend points for the edge. This is used by the 'Fixed Layout' algorithm to specify a pre-defined routing for an edge. The vector chain must include the source point, any bend points, and the target point, so it must have at least two points."),Y1),sSe),rn(Fd)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,rG),""),"Content Alignment"),"Specifies how the content of a node are aligned. Each node can individually control the alignment of its contents. I.e. if a node should be aligned top left in its parent node, the parent node should specify that option."),pSe),Pk),Jhe),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,WI),""),"Debug Mode"),"Whether additional debug information shall be generated."),(Mn(),!1)),za),Us),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,txe),""),P6e),"Overall direction of edges: horizontal (right / left) or vertical (down / up)."),bSe),vs),RS),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,VI),""),"Edge Routing"),"What kind of edge routing style should be applied for the content of a parent node. Algorithms may also set this option to single edges in order to mark them as splines. The bend point list of edges with this option set to SPLINES must be interpreted as control points for a piecewise cubic spline."),mSe),vs),ffe),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,uG),""),"Expand Nodes"),"If active, nodes are expanded to fill the area of their parent."),!1),za),Us),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,nG),""),"Hierarchy Handling"),"Determines whether separate layout runs are triggered for different compound nodes in a hierarchical graph. Setting a node's hierarchy handling to `INCLUDE_CHILDREN` will lay out that node and all of its descendants in a single layout run, until a descendant is encountered which has its hierarchy handling set to `SEPARATE_CHILDREN`. In general, `SEPARATE_CHILDREN` will ensure that a new layout run is triggered for a node with that setting. Including multiple levels of hierarchy in a single layout run may allow cross-hierarchical edges to be laid out properly. If the root node is set to `INHERIT` (or not set at all), the default behavior is `SEPARATE_CHILDREN`."),ESe),vs),cAe),Ui(Fn,ie(re(Ug,1),tt,175,0,[ua]))))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,uw),""),"Padding"),"The padding to be left to a parent element's border when placing child elements. This can also serve as an output option of a layout algorithm if node size calculation is setup appropriately."),OSe),Y1),gEe),Ui(Fn,ie(re(Ug,1),tt,175,0,[ua]))))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,jI),""),"Interactive"),"Whether the algorithm should be run in interactive mode for the content of a parent node. What this means exactly depends on how the specific algorithm interprets this option. Usually in the interactive mode algorithms try to modify the current layout as little as possible."),!1),za),Us),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,fce),""),"interactive Layout"),"Whether the graph should be changeable interactively and by setting constraints"),!1),za),Us),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,CC),""),"Omit Node Micro Layout"),"Node micro layout comprises the computation of node dimensions (if requested), the placement of ports and their labels, and the placement of node labels. The functionality is implemented independent of any specific layout algorithm and shouldn't have any negative impact on the layout algorithm's performance itself. Yet, if any unforeseen behavior occurs, this option allows to deactivate the micro layout."),!1),za),Us),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Doe),""),"Port Constraints"),"Defines constraints of the position of the ports of a node."),FSe),vs),hAe),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,iG),""),"Position"),"The position of a node, port, or label. This is used by the 'Fixed Layout' algorithm to specify a pre-defined position."),Y1),na),Ui(ua,ie(re(Ug,1),tt,175,0,[Bb,Vg]))))),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,FI),""),"Priority"),"Defines the priority of an object; its meaning depends on the specific layout algorithm and the context where it is used."),Cc),Za),Ui(ua,ie(re(Ug,1),tt,175,0,[Fd]))))),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,Fz),""),"Randomization Seed"),"Seed used for pseudo-random number generators to control the layout algorithm. If the value is 0, the seed shall be determined pseudo-randomly (e.g. from the system time)."),Cc),Za),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,_C),""),"Separate Connected Components"),"Whether each connected component should be processed separately."),za),Us),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,lxe),""),"Junction Points"),"This option is not used as option, but as output of the layout algorithms. It is attached to edges and determines the points where junction symbols should be drawn in order to represent hyperedges with orthogonal routing. Whether such points are computed depends on the chosen layout algorithm and edge routing style. The points are put into the vector chain with no specific order."),_Se),Y1),sSe),rn(Fd)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,dxe),""),"Comment Box"),"Whether the node should be regarded as a comment box instead of a regular node. In that case its placement should be similar to how labels are handled. Any edges incident to a comment box specify to which graph elements the comment is related."),!1),za),Us),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,gxe),""),"Hypernode"),"Whether the node should be handled as a hypernode."),!1),za),Us),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,t3n),""),"Label Manager"),"Label managers can shorten labels upon a layout algorithm's request."),Y1),I3n),Ui(Fn,ie(re(Ug,1),tt,175,0,[Vg]))))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,bxe),""),"Margins"),"Margins define additional space around the actual bounds of a graph element. For instance, ports or labels being placed on the outside of a node's border might introduce such a margin. The margin is used to guarantee non-overlap of other graph elements with those ports or labels."),CSe),Y1),dEe),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Xke),""),"No Layout"),"No layout is done for the associated element. This is used to mark parts of a diagram to avoid their inclusion in the layout graph, or to mark parts of the layout graph to prevent layout engines from processing them. If you wish to exclude the contents of a compound node from automatic layout, while the node itself is still considered on its own layer, use the 'Fixed Layout' algorithm for that node."),!1),za),Us),Ui(ua,ie(re(Ug,1),tt,175,0,[Fd,Bb,Vg]))))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,i1t),""),"Scale Factor"),"The scaling factor to be applied to the corresponding node in recursive layout. It causes the corresponding node's size to be adjusted, and its ports and labels to be sized and placed accordingly after the layout of that node has been determined (and before the node itself and its siblings are arranged). The scaling is not reverted afterwards, so the resulting layout graph contains the adjusted size and position data. This option is currently not supported if 'Layout Hierarchy' is set."),1),qo),ma),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,s1t),""),"Animate"),"Whether the shift from the old layout to the new computed layout shall be animated."),!0),za),Us),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,a1t),""),"Animation Time Factor"),"Factor for computation of animation time. The higher the value, the longer the animation time. If the value is 0, the resulting time is always equal to the minimum defined by 'Minimal Animation Time'."),ct(100)),Cc),Za),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,o1t),""),"Layout Ancestors"),"Whether the hierarchy levels on the path from the selected element to the root of the diagram shall be included in the layout process."),!1),za),Us),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,c1t),""),"Maximal Animation Time"),"The maximal time for animations, in milliseconds."),ct(4e3)),Cc),Za),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,u1t),""),"Minimal Animation Time"),"The minimal time for animations, in milliseconds."),ct(400)),Cc),Za),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,l1t),""),"Progress Bar"),"Whether a progress bar shall be displayed during layout computations."),!1),za),Us),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,h1t),""),"Validate Graph"),"Whether the graph shall be validated before any layout algorithm is applied. If this option is enabled and at least one error is found, the layout process is aborted and a message is shown to the user."),!1),za),Us),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,f1t),""),"Validate Options"),"Whether layout options shall be validated before any layout algorithm is applied. If this option is enabled and at least one error is found, the layout process is aborted and a message is shown to the user."),!0),za),Us),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,d1t),""),"Zoom to Fit"),"Whether the zoom level shall be set to view the whole diagram after layout."),!1),za),Us),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Vxe),"box"),"Box Layout Mode"),"Configures the packing mode used by the {@link BoxLayoutProvider}. If SIMPLE is not required (neither priorities are used nor the interactive mode), GROUP_DEC can improve the packing and decrease the area. GROUP_MIXED and GROUP_INC may, in very specific scenarios, work better."),gSe),vs),vAe),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Fke),G1),"Comment Comment Spacing"),"Spacing to be preserved between a comment box and other comment boxes connected to the same node. The space left between comment boxes of different nodes is controlled by the node-node spacing."),10),qo),ma),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,jke),G1),"Comment Node Spacing"),"Spacing to be preserved between a node and its connected comment boxes. The space left between a node and the comments of another node is controlled by the node-node spacing."),10),qo),ma),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,_oe),G1),"Components Spacing"),"Spacing to be preserved between pairs of connected components. This option is only relevant if 'separateConnectedComponents' is activated."),20),qo),ma),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,$ke),G1),"Edge Spacing"),"Spacing to be preserved between any two edges. Note that while this can somewhat easily be satisfied for the segments of orthogonally drawn edges, it is harder for general polylines or splines."),10),qo),ma),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Moe),G1),"Edge Label Spacing"),"The minimal distance to be preserved between a label and the edge it is associated with. Note that the placement of a label is influenced by the 'edgelabels.placement' option."),2),qo),ma),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Hke),G1),"Edge Node Spacing"),"Spacing to be preserved between nodes and edges."),10),qo),ma),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,zke),G1),"Label Spacing"),"Determines the amount of space to be left between two labels of the same graph element."),0),qo),ma),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Vke),G1),"Label Node Spacing"),"Spacing to be preserved between labels and the border of node they are associated with. Note that the placement of a label is influenced by the 'nodelabels.placement' option."),5),qo),ma),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Gke),G1),"Horizontal spacing between Label and Port"),"Horizontal spacing to be preserved between labels and the ports they are associated with. Note that the placement of a label is influenced by the 'portlabels.placement' option."),1),qo),ma),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,qke),G1),"Vertical spacing between Label and Port"),"Vertical spacing to be preserved between labels and the ports they are associated with. Note that the placement of a label is influenced by the 'portlabels.placement' option."),1),qo),ma),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,py),G1),"Node Spacing"),"The minimal distance to be preserved between each two nodes."),20),qo),ma),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Uke),G1),"Node Self Loop Spacing"),"Spacing to be preserved between a node and its self loops."),10),qo),ma),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Wke),G1),"Port Spacing"),"Spacing between pairs of ports of the same node."),10),qo),ma),Ui(Fn,ie(re(Ug,1),tt,175,0,[ua]))))),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,Kke),G1),"Individual Spacing"),"Allows to specify individual spacing values for graph elements that shall be different from the value specified for the element's parent."),Y1),O3t),Ui(ua,ie(re(Ug,1),tt,175,0,[Fd,Bb,Vg]))))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,vxe),G1),"Additional Port Space"),"Additional space around the sets of ports on each node side. For each side of a node, this option can reserve additional space before and after the ports on each side. For example, a top spacing of 20 makes sure that the first port on the western and eastern side is 20 units away from the northern border."),KSe),Y1),dEe),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,hce),b1t),"Layout Partition"),"Partition to which the node belongs. This requires Layout Partitioning to be active. Nodes with lower partition IDs will appear to the left of nodes with higher partition IDs (assuming a left-to-right layout direction)."),Cc),Za),Ui(Fn,ie(re(Ug,1),tt,175,0,[ua]))))),va(t,hce,lce,a3t),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,lce),b1t),"Layout Partitioning"),"Whether to activate partitioned layout. This will allow to group nodes through the Layout Partition option. a pair of nodes with different partition indices is then placed such that the node with lower index is placed to the left of the other node (with left-to-right layout direction). Depending on the layout algorithm, this may only be guaranteed to work if all nodes have a layout partition configured, or at least if edges that cross partitions are not part of a partition-crossing cycle."),NSe),za),Us),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,nxe),v1t),"Node Label Padding"),"Define padding for node labels that are placed inside of a node."),ASe),Y1),gEe),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,P7),v1t),"Node Label Placement"),"Hints for where node labels are to be placed; if empty, the node label's position is not modified."),LSe),Pk),xo),Ui(ua,ie(re(Ug,1),tt,175,0,[Vg]))))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,sxe),hG),"Port Alignment"),"Defines the default port distribution for a node. May be overridden for each side individually."),BSe),vs),HS),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,axe),hG),"Port Alignment (North)"),"Defines how ports on the northern side are placed, overriding the node's general port alignment."),vs),HS),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,oxe),hG),"Port Alignment (South)"),"Defines how ports on the southern side are placed, overriding the node's general port alignment."),vs),HS),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,cxe),hG),"Port Alignment (West)"),"Defines how ports on the western side are placed, overriding the node's general port alignment."),vs),HS),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,uxe),hG),"Port Alignment (East)"),"Defines how ports on the eastern side are placed, overriding the node's general port alignment."),vs),HS),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,E4),Dce),"Node Size Constraints"),"What should be taken into account when calculating a node's size. Empty size constraints specify that a node's size is already fixed and should not be changed."),MSe),Pk),qS),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,dk),Dce),"Node Size Options"),"Options modifying the behavior of the size constraints set on a node. Each member of the set specifies something that should be taken into account when calculating node sizes. The empty set corresponds to no further modifications."),ISe),Pk),dAe),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,gk),Dce),"Node Size Minimum"),"The minimal size to which a node can be reduced."),DSe),Y1),na),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,uce),Dce),"Fixed Graph Size"),"By default, the fixed layout provider will enlarge a graph until it is large enough to contain its children. If this option is set, it won't do so."),!1),za),Us),rn(Fn)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,hxe),cce),"Edge Label Placement"),"Gives a hint on where to put edge labels."),vSe),vs),XSe),rn(Vg)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,jz),cce),"Inline Edge Labels"),"If true, an edge label is placed directly on its edge. May only apply to center edge labels. This kind of label placement is only advisable if the label's rendering is such that it is not crossed by its edge and thus stays legible."),!1),za),Us),rn(Vg)))),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,n3n),"font"),"Font Name"),"Font name used for a label."),kE),mt),rn(Vg)))),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,g1t),"font"),"Font Size"),"Font size used for a label."),Cc),Za),rn(Vg)))),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,pxe),Ice),"Port Anchor Offset"),"The offset to the port position where connections shall be attached."),Y1),na),rn(Bb)))),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,fxe),Ice),"Port Index"),"The index of a port in the fixed order around a node. The order is assumed as clockwise, starting with the leftmost port on the top side. This option must be set if 'Port Constraints' is set to FIXED_ORDER and no specific positions are given for the ports. Additionally, the option 'Port Side' must be defined in this case."),Cc),Za),rn(Bb)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Qke),Ice),"Port Side"),"The side of a node on which a port is situated. This option must be set if 'Port Constraints' is set to FIXED_SIDE or FIXED_ORDER and no specific positions are given for the ports."),HSe),vs),ao),rn(Bb)))),en(t,new Vt(Zt(Qt(Jt(Wt(Xt(Kt(Yt(new Ht,Yke),Ice),"Port Border Offset"),"The offset of ports on the node border. With a positive offset the port is moved outside of the node, while with a negative offset the port is moved towards the inside. An offset of 0 means that the port is placed directly on the node border, i.e. if the port side is north, the port's south border touches the nodes's north border; if the port side is east, the port's west border touches the nodes's east border; if the port side is south, the port's north border touches the node's south border; if the port side is west, the port's east border touches the node's west border."),qo),ma),rn(Bb)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,B7),Wxe),"Port Label Placement"),"Decides on a placement method for port labels; if empty, the node label's position is not modified."),jSe),Pk),jV),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,rxe),Wxe),"Port Labels Next to Port"),"Use 'portLabels.placement': NEXT_TO_PORT_OF_POSSIBLE."),!1),za),Us),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,ixe),Wxe),"Treat Port Labels as Group"),"If this option is true (default), the labels of a port will be treated as a group when it comes to centering them next to their port. If this option is false, only the first label will be centered next to the port, with the others being placed below. This only applies to labels of eastern and western ports and will have no effect if labels are not placed next to their port."),!0),za),Us),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Jke),w1t),"Activate Inside Self Loops"),"Whether this node allows to route self loops inside of it instead of around it. If set to true, this will make the node a compound node if it isn't already, and will require the layout algorithm to support compound nodes with hierarchical ports."),!1),za),Us),rn(ua)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,exe),w1t),"Inside Self Loop"),"Whether a self loop should be routed inside a node instead of around that node."),!1),za),Us),rn(Fd)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,Coe),"edge"),"Edge Thickness"),"The thickness of an edge. This is a hint on the line width used to draw an edge, possibly requiring more space to be reserved for it."),1),qo),ma),rn(Fd)))),en(t,new Vt(Zt(Qt(Jt(pn(Wt(Xt(Kt(Yt(new Ht,p1t),"edge"),"Edge Type"),"The type of an edge. This is usually used for UML class diagrams, where associations must be handled differently from generalizations."),kSe),vs),nAe),rn(Fd)))),NT(t,new R6(AT(Xx(Yx(new hm,qn),"Layered"),'The layer-based method was introduced by Sugiyama, Tagawa and Toda in 1981. It emphasizes the direction of edges by pointing as many edges as possible into the same direction. The nodes are arranged in layers, which are sometimes called "hierarchies", and then reordered such that the number of edge crossings is minimized. Afterwards, concrete coordinates are computed for the nodes and edge bend points.'))),NT(t,new R6(AT(Xx(Yx(new hm,"org.eclipse.elk.orthogonal"),"Orthogonal"),`Orthogonal methods that follow the "topology-shape-metrics" approach by Batini, Nardelli and Tamassia '86. The first phase determines the topology of the drawing by applying a planarization technique, which results in a planar representation of the graph. The orthogonal shape is computed in the second phase, which aims at minimizing the number of edge bends, and is called orthogonalization. The third phase leads to concrete coordinates for nodes and edge bend points by applying a compaction method, thus defining the metrics.`))),NT(t,new R6(AT(Xx(Yx(new hm,Yl),"Force"),"Layout algorithms that follow physical analogies by simulating a system of attractive and repulsive forces. The first successful method of this kind was proposed by Eades in 1984."))),NT(t,new R6(AT(Xx(Yx(new hm,"org.eclipse.elk.circle"),"Circle"),"Circular layout algorithms emphasize cycles or biconnected components of a graph by arranging them in circles. This is useful if a drawing is desired where such components are clearly grouped, or where cycles are shown as prominent OPTIONS of the graph."))),NT(t,new R6(AT(Xx(Yx(new hm,zft),"Tree"),"Specialized layout methods for trees, i.e. acyclic graphs. The regular structure of graphs that have no undirected cycles can be emphasized using an algorithm of this type."))),NT(t,new R6(AT(Xx(Yx(new hm,"org.eclipse.elk.planar"),"Planar"),"Algorithms that require a planar or upward planar graph. Most of these algorithms are theoretically interesting, but not practically usable."))),NT(t,new R6(AT(Xx(Yx(new hm,Dd),"Radial"),"Radial layout algorithms usually position the nodes of the graph on concentric circles."))),zct((new PR,t)),rut((new JJ,t)),wct((new BR,t))};var PS,Jyt,dSe,Bk,e3t,t3t,gSe,n3t,IV,pSe,VO,Mw,bSe,efe,tfe,vSe,wSe,mSe,ySe,kSe,xSe,Q4,ESe,r3t,UO,nfe,OV,TSe,Z4,_Se,WO,CSe,SSe,ASe,J4,LSe,Rb,MSe,NV,e5,DSe,p2,ISe,PV,KO,Fb,OSe,i3t,NSe,s3t,a3t,PSe,BSe,rfe,ife,sfe,afe,RSe,kl,BS,FSe,ofe,cfe,Hy,jSe,$Se,t5,HSe,Rk,BV,ufe,xE,o3t,lfe,c3t,u3t,zSe,l3t,GSe,h3t,Fk,qSe,RV,VSe,USe,jb,f3t,WSe,KSe,YSe;O(qh,"CoreOptions",684),M(103,22,{3:1,35:1,22:1,103:1},AM);var Y0,Xh,Df,f0,X0,RS=Gr(qh,P6e,103,Wr,_nn,qXt),d3t;M(272,22,{3:1,35:1,22:1,272:1},Fte);var EE,zy,TE,XSe=Gr(qh,"EdgeLabelPlacement",272,Wr,stn,VXt),g3t;M(218,22,{3:1,35:1,22:1,218:1},GF);var _E,YO,jk,hfe,ffe=Gr(qh,"EdgeRouting",218,Wr,Qtn,UXt),p3t;M(312,22,{3:1,35:1,22:1,312:1},WT);var QSe,ZSe,JSe,eAe,dfe,tAe,nAe=Gr(qh,"EdgeType",312,Wr,hrn,WXt),b3t;M(977,1,zh,PR),l.Qe=function(t){zct(t)};var rAe,iAe,sAe,aAe,v3t,oAe,FS;O(qh,"FixedLayouterOptions",977),M(978,1,{},BL),l.$e=function(){var t;return t=new NZ,t},l._e=function(t){},O(qh,"FixedLayouterOptions/FixedFactory",978),M(334,22,{3:1,35:1,22:1,334:1},jte);var Wg,FV,jS,cAe=Gr(qh,"HierarchyHandling",334,Wr,itn,KXt),w3t;M(285,22,{3:1,35:1,22:1,285:1},qF);var d0,b2,XO,QO,m3t=Gr(qh,"LabelSide",285,Wr,Xtn,YXt),y3t;M(93,22,{3:1,35:1,22:1,93:1},N3);var Q0,If,Qh,Of,Jl,Nf,Zh,g0,Pf,xo=Gr(qh,"NodeLabelPlacement",93,Wr,gin,XXt),k3t;M(249,22,{3:1,35:1,22:1,249:1},LM);var uAe,$S,v2,lAe,ZO,HS=Gr(qh,"PortAlignment",249,Wr,Cnn,QXt),x3t;M(98,22,{3:1,35:1,22:1,98:1},KT);var $b,tu,p0,CE,X1,w2,hAe=Gr(qh,"PortConstraints",98,Wr,Knn,ZXt),E3t;M(273,22,{3:1,35:1,22:1,273:1},YT);var zS,GS,Z0,JO,m2,$k,jV=Gr(qh,"PortLabelPlacement",273,Wr,lrn,JXt),T3t;M(61,22,{3:1,35:1,22:1,61:1},MM);var $n,An,_h,Ch,Bu,wu,Q1,Bf,ll,Ju,nu,hl,Ru,Fu,Rf,eh,th,Jh,xr,uc,Dn,ao=Gr(qh,"PortSide",61,Wr,xnn,nQt),_3t;M(981,1,zh,BR),l.Qe=function(t){wct(t)};var C3t,S3t,fAe,A3t,L3t;O(qh,"RandomLayouterOptions",981),M(982,1,{},$Z),l.$e=function(){var t;return t=new zZ,t},l._e=function(t){},O(qh,"RandomLayouterOptions/RandomFactory",982),M(374,22,{3:1,35:1,22:1,374:1},VF);var Gy,eN,tN,Hb,qS=Gr(qh,"SizeConstraint",374,Wr,Ytn,eQt),M3t;M(259,22,{3:1,35:1,22:1,259:1},P3);var nN,$V,SE,gfe,rN,VS,HV,zV,GV,dAe=Gr(qh,"SizeOptions",259,Wr,kin,tQt),D3t;M(370,1,{1949:1},Ux),l.b=!1,l.c=0,l.d=-1,l.e=null,l.f=null,l.g=-1,l.j=!1,l.k=!1,l.n=!1,l.o=0,l.q=0,l.r=0,O(Oc,"BasicProgressMonitor",370),M(972,209,mb,BZ),l.Ze=function(t,n){var r,s,o,h,d,v,x,_,L;switch(kr(n,"Box layout",2),o=uM(ft(Ft(t,(XH(),Qyt)))),h=u(Ft(t,Xyt),116),r=It(Mt(Ft(t,cSe))),s=It(Mt(Ft(t,uSe))),u(Ft(t,Xhe),311).g){case 0:d=(v=new Uu((!t.a&&(t.a=new at(hs,t,10,11)),t.a)),hn(),aa(v,new Zje(s)),v),x=A4e(t),_=ft(Ft(t,oSe)),(_==null||(Sn(_),_<=0))&&(_=1.3),L=ayn(d,o,h,x.a,x.b,r,(Sn(_),_)),sw(t,L.a,L.b,!1,!0);break;default:nwn(t,o,h,r)}ur(n)},O(Oc,"BoxLayoutProvider",972),M(973,1,ji,Zje),l.ue=function(t,n){return Tgn(this,u(t,33),u(n,33))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},l.a=!1,O(Oc,"BoxLayoutProvider/1",973),M(157,1,{157:1},H$,yUe),l.Ib=function(){return this.c?S5e(this.c):Yp(this.b)},O(Oc,"BoxLayoutProvider/Group",157),M(311,22,{3:1,35:1,22:1,311:1},UF);var gAe,pAe,bAe,pfe,vAe=Gr(Oc,"BoxLayoutProvider/PackingMode",311,Wr,Ztn,rQt),I3t;M(974,1,ji,RZ),l.ue=function(t,n){return SJt(u(t,157),u(n,157))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Oc,"BoxLayoutProvider/lambda$0$Type",974),M(975,1,ji,GB),l.ue=function(t,n){return yJt(u(t,157),u(n,157))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Oc,"BoxLayoutProvider/lambda$1$Type",975),M(976,1,ji,FZ),l.ue=function(t,n){return kJt(u(t,157),u(n,157))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(Oc,"BoxLayoutProvider/lambda$2$Type",976),M(1365,1,{831:1},jZ),l.qg=function(t,n){return SF(),!we(n,160)||Mze((W6(),u(t,160)),n)},O(Oc,"ElkSpacings/AbstractSpacingsBuilder/lambda$0$Type",1365),M(1366,1,Un,Jje),l.td=function(t){han(this.a,u(t,146))},O(Oc,"ElkSpacings/AbstractSpacingsBuilder/lambda$1$Type",1366),M(1367,1,Un,PZ),l.td=function(t){u(t,94),SF()},O(Oc,"ElkSpacings/AbstractSpacingsBuilder/lambda$2$Type",1367),M(1371,1,Un,e$e),l.td=function(t){Bin(this.a,u(t,94))},O(Oc,"ElkSpacings/AbstractSpacingsBuilder/lambda$3$Type",1371),M(1369,1,vi,bqe),l.Mb=function(t){return Qsn(this.a,this.b,u(t,146))},O(Oc,"ElkSpacings/AbstractSpacingsBuilder/lambda$4$Type",1369),M(1368,1,vi,vqe),l.Mb=function(t){return gKt(this.a,this.b,u(t,831))},O(Oc,"ElkSpacings/AbstractSpacingsBuilder/lambda$5$Type",1368),M(1370,1,Un,wqe),l.td=function(t){gZt(this.a,this.b,u(t,146))},O(Oc,"ElkSpacings/AbstractSpacingsBuilder/lambda$6$Type",1370),M(935,1,{},OZ),l.Kb=function(t){return wVe(t)},l.Fb=function(t){return this===t},O(Oc,"ElkUtil/lambda$0$Type",935),M(936,1,Un,mqe),l.td=function(t){Cdn(this.a,this.b,u(t,79))},l.a=0,l.b=0,O(Oc,"ElkUtil/lambda$1$Type",936),M(937,1,Un,yqe),l.td=function(t){CVt(this.a,this.b,u(t,202))},l.a=0,l.b=0,O(Oc,"ElkUtil/lambda$2$Type",937),M(938,1,Un,kqe),l.td=function(t){vWt(this.a,this.b,u(t,137))},l.a=0,l.b=0,O(Oc,"ElkUtil/lambda$3$Type",938),M(939,1,Un,t$e),l.td=function(t){MQt(this.a,u(t,469))},O(Oc,"ElkUtil/lambda$4$Type",939),M(342,1,{35:1,342:1},nVt),l.wd=function(t){return VWt(this,u(t,236))},l.Fb=function(t){var n;return we(t,342)?(n=u(t,342),this.a==n.a):!1},l.Hb=function(){return _s(this.a)},l.Ib=function(){return this.a+" (exclusive)"},l.a=0,O(Oc,"ExclusiveBounds/ExclusiveLowerBound",342),M(1138,209,mb,NZ),l.Ze=function(t,n){var r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce,Ee,Ne,Ve,nt,bt,zt,Ut;for(kr(n,"Fixed Layout",1),h=u(Ft(t,(bi(),wSe)),218),P=0,z=0,Ee=new rr((!t.a&&(t.a=new at(hs,t,10,11)),t.a));Ee.e!=Ee.i.gc();){for(le=u(pr(Ee),33),Ut=u(Ft(le,(hH(),FS)),8),Ut&&(C1(le,Ut.a,Ut.b),u(Ft(le,iAe),174).Hc((Bl(),Gy))&&(q=u(Ft(le,aAe),8),q.a>0&&q.b>0&&sw(le,q.a,q.b,!0,!0))),P=b.Math.max(P,le.i+le.g),z=b.Math.max(z,le.j+le.f),_=new rr((!le.n&&(le.n=new at(Jo,le,1,7)),le.n));_.e!=_.i.gc();)v=u(pr(_),137),Ut=u(Ft(v,FS),8),Ut&&C1(v,Ut.a,Ut.b),P=b.Math.max(P,le.i+v.i+v.g),z=b.Math.max(z,le.j+v.j+v.f);for(nt=new rr((!le.c&&(le.c=new at(xl,le,9,9)),le.c));nt.e!=nt.i.gc();)for(Ve=u(pr(nt),118),Ut=u(Ft(Ve,FS),8),Ut&&C1(Ve,Ut.a,Ut.b),bt=le.i+Ve.i,zt=le.j+Ve.j,P=b.Math.max(P,bt+Ve.g),z=b.Math.max(z,zt+Ve.f),x=new rr((!Ve.n&&(Ve.n=new at(Jo,Ve,1,7)),Ve.n));x.e!=x.i.gc();)v=u(pr(x),137),Ut=u(Ft(v,FS),8),Ut&&C1(v,Ut.a,Ut.b),P=b.Math.max(P,bt+v.i+v.g),z=b.Math.max(z,zt+v.j+v.f);for(o=new cr(fr(z0(le).a.Kc(),new V));Vr(o);)r=u(Pr(o),79),L=Olt(r),P=b.Math.max(P,L.a),z=b.Math.max(z,L.b);for(s=new cr(fr(hI(le).a.Kc(),new V));Vr(s);)r=u(Pr(s),79),us(n0(r))!=t&&(L=Olt(r),P=b.Math.max(P,L.a),z=b.Math.max(z,L.b))}if(h==($0(),_E))for(Ce=new rr((!t.a&&(t.a=new at(hs,t,10,11)),t.a));Ce.e!=Ce.i.gc();)for(le=u(pr(Ce),33),s=new cr(fr(z0(le).a.Kc(),new V));Vr(s);)r=u(Pr(s),79),d=Ebn(r),d.b==0?So(r,Z4,null):So(r,Z4,d);It(Mt(Ft(t,(hH(),sAe))))||(Ne=u(Ft(t,v3t),116),X=P+Ne.b+Ne.c,W=z+Ne.d+Ne.a,sw(t,X,W,!0,!0)),ur(n)},O(Oc,"FixedLayoutProvider",1138),M(373,134,{3:1,414:1,373:1,94:1,134:1},rl,KJe),l.Jf=function(t){var n,r,s,o,h,d,v,x,_;if(t)try{for(x=cy(t,";,;"),h=x,d=0,v=h.length;d>16&Ss|n^s<<16},l.Kc=function(){return new n$e(this)},l.Ib=function(){return this.a==null&&this.b==null?"pair(null,null)":this.a==null?"pair(null,"+Qo(this.b)+")":this.b==null?"pair("+Qo(this.a)+",null)":"pair("+Qo(this.a)+","+Qo(this.b)+")"},O(Oc,"Pair",46),M(983,1,ga,n$e),l.Nb=function(t){La(this,t)},l.Ob=function(){return!this.c&&(!this.b&&this.a.a!=null||this.a.b!=null)},l.Pb=function(){if(!this.c&&!this.b&&this.a.a!=null)return this.b=!0,this.a.a;if(!this.c&&this.a.b!=null)return this.c=!0,this.a.b;throw J(new xc)},l.Qb=function(){throw this.c&&this.a.b!=null?this.a.b=null:this.b&&this.a.a!=null&&(this.a.a=null),J(new zu)},l.b=!1,l.c=!1,O(Oc,"Pair/1",983),M(448,1,{448:1},IYe),l.Fb=function(t){return Vc(this.a,u(t,448).a)&&Vc(this.c,u(t,448).c)&&Vc(this.d,u(t,448).d)&&Vc(this.b,u(t,448).b)},l.Hb=function(){return fH(ie(re(Yn,1),yt,1,5,[this.a,this.c,this.d,this.b]))},l.Ib=function(){return"("+this.a+io+this.c+io+this.d+io+this.b+")"},O(Oc,"Quadruple",448),M(1126,209,mb,zZ),l.Ze=function(t,n){var r,s,o,h,d;if(kr(n,"Random Layout",1),(!t.a&&(t.a=new at(hs,t,10,11)),t.a).i==0){ur(n);return}h=u(Ft(t,(i3e(),A3t)),19),h&&h.a!=0?o=new m$(h.a):o=new Fie,r=uM(ft(Ft(t,C3t))),d=uM(ft(Ft(t,L3t))),s=u(Ft(t,S3t),116),Rmn(t,o,r,d,s),ur(n)},O(Oc,"RandomLayoutProvider",1126);var B3t;M(553,1,{}),l.qf=function(){return new Pt(this.f.i,this.f.j)},l.We=function(t){return iXe(t,(bi(),kl))?Ft(this.f,R3t):Ft(this.f,t)},l.rf=function(){return new Pt(this.f.g,this.f.f)},l.sf=function(){return this.g},l.Xe=function(t){return J2(this.f,t)},l.tf=function(t){Du(this.f,t.a),Iu(this.f,t.b)},l.uf=function(t){zv(this.f,t.a),Hv(this.f,t.b)},l.vf=function(t){this.g=t},l.g=0;var R3t;O(BC,"ElkGraphAdapters/AbstractElkGraphElementAdapter",553),M(554,1,{839:1},tF),l.wf=function(){var t,n;if(!this.b)for(this.b=p$(Wj(this.a).i),n=new rr(Wj(this.a));n.e!=n.i.gc();)t=u(pr(n),137),it(this.b,new tte(t));return this.b},l.b=null,O(BC,"ElkGraphAdapters/ElkEdgeAdapter",554),M(301,553,{},ym),l.xf=function(){return Nit(this)},l.a=null,O(BC,"ElkGraphAdapters/ElkGraphAdapter",301),M(630,553,{181:1},tte),O(BC,"ElkGraphAdapters/ElkLabelAdapter",630),M(629,553,{680:1},ene),l.wf=function(){return jun(this)},l.Af=function(){var t;return t=u(Ft(this.f,(bi(),WO)),142),!t&&(t=new yT),t},l.Cf=function(){return $un(this)},l.Ef=function(t){var n;n=new pne(t),So(this.f,(bi(),WO),n)},l.Ff=function(t){So(this.f,(bi(),Fb),new Jbe(t))},l.yf=function(){return this.d},l.zf=function(){var t,n;if(!this.a)for(this.a=new st,n=new cr(fr(hI(u(this.f,33)).a.Kc(),new V));Vr(n);)t=u(Pr(n),79),it(this.a,new tF(t));return this.a},l.Bf=function(){var t,n;if(!this.c)for(this.c=new st,n=new cr(fr(z0(u(this.f,33)).a.Kc(),new V));Vr(n);)t=u(Pr(n),79),it(this.c,new tF(t));return this.c},l.Df=function(){return Jj(u(this.f,33)).i!=0||It(Mt(u(this.f,33).We((bi(),UO))))},l.Gf=function(){Mrn(this,(Tm(),B3t))},l.a=null,l.b=null,l.c=null,l.d=null,l.e=null,O(BC,"ElkGraphAdapters/ElkNodeAdapter",629),M(1266,553,{838:1},D$e),l.wf=function(){return Kun(this)},l.zf=function(){var t,n;if(!this.a)for(this.a=Wd(u(this.f,118).xg().i),n=new rr(u(this.f,118).xg());n.e!=n.i.gc();)t=u(pr(n),79),it(this.a,new tF(t));return this.a},l.Bf=function(){var t,n;if(!this.c)for(this.c=Wd(u(this.f,118).yg().i),n=new rr(u(this.f,118).yg());n.e!=n.i.gc();)t=u(pr(n),79),it(this.c,new tF(t));return this.c},l.Hf=function(){return u(u(this.f,118).We((bi(),t5)),61)},l.If=function(){var t,n,r,s,o,h,d,v;for(s=L1(u(this.f,118)),r=new rr(u(this.f,118).yg());r.e!=r.i.gc();)for(t=u(pr(r),79),v=new rr((!t.c&&(t.c=new wn(mr,t,5,8)),t.c));v.e!=v.i.gc();){if(d=u(pr(v),82),Vm(zo(d),s))return!0;if(zo(d)==s&&It(Mt(Ft(t,(bi(),nfe)))))return!0}for(n=new rr(u(this.f,118).xg());n.e!=n.i.gc();)for(t=u(pr(n),79),h=new rr((!t.b&&(t.b=new wn(mr,t,4,7)),t.b));h.e!=h.i.gc();)if(o=u(pr(h),82),Vm(zo(o),s))return!0;return!1},l.a=null,l.b=null,l.c=null,O(BC,"ElkGraphAdapters/ElkPortAdapter",1266),M(1267,1,ji,GZ),l.ue=function(t,n){return b2n(u(t,118),u(n,118))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(BC,"ElkGraphAdapters/PortComparator",1267);var y2=ss(kh,"EObject"),AE=ss(S4,k1t),ef=ss(S4,x1t),iN=ss(S4,E1t),sN=ss(S4,"ElkShape"),mr=ss(S4,T1t),ra=ss(S4,Kxe),os=ss(S4,_1t),aN=ss(kh,C1t),US=ss(kh,"EFactory"),F3t,bfe=ss(kh,S1t),h1=ss(kh,"EPackage"),la,j3t,$3t,kAe,qV,H3t,xAe,EAe,TAe,k2,z3t,G3t,Jo=ss(S4,Yxe),hs=ss(S4,Xxe),xl=ss(S4,Qxe);M(90,1,A1t),l.Jg=function(){return this.Kg(),null},l.Kg=function(){return null},l.Lg=function(){return this.Kg(),!1},l.Mg=function(){return!1},l.Ng=function(t){_i(this,t)},O(wk,"BasicNotifierImpl",90),M(97,90,I1t),l.nh=function(){return Ll(this)},l.Og=function(t,n){return t},l.Pg=function(){throw J(new Fr)},l.Qg=function(t){var n;return n=go(u(gn(this.Tg(),this.Vg()),18)),this.eh().ih(this,n.n,n.f,t)},l.Rg=function(t,n){throw J(new Fr)},l.Sg=function(t,n,r){return Kl(this,t,n,r)},l.Tg=function(){var t;return this.Pg()&&(t=this.Pg().ck(),t)?t:this.zh()},l.Ug=function(){return Hse(this)},l.Vg=function(){throw J(new Fr)},l.Wg=function(){var t,n;return n=this.ph().dk(),!n&&this.Pg().ik(n=(PT(),t=bwe(xd(this.Tg())),t==null?Tfe:new OM(this,t))),n},l.Xg=function(t,n){return t},l.Yg=function(t){var n;return n=t.Gj(),n?t.aj():Ji(this.Tg(),t)},l.Zg=function(){var t;return t=this.Pg(),t?t.fk():null},l.$g=function(){return this.Pg()?this.Pg().ck():null},l._g=function(t,n,r){return NH(this,t,n,r)},l.ah=function(t){return A8(this,t)},l.bh=function(t,n){return Ire(this,t,n)},l.dh=function(){var t;return t=this.Pg(),!!t&&t.gk()},l.eh=function(){throw J(new Fr)},l.fh=function(){return SH(this)},l.gh=function(t,n,r,s){return Q6(this,t,n,s)},l.hh=function(t,n,r){var s;return s=u(gn(this.Tg(),n),66),s.Nj().Qj(this,this.yh(),n-this.Ah(),t,r)},l.ih=function(t,n,r,s){return r$(this,t,n,s)},l.jh=function(t,n,r){var s;return s=u(gn(this.Tg(),n),66),s.Nj().Rj(this,this.yh(),n-this.Ah(),t,r)},l.kh=function(){return!!this.Pg()&&!!this.Pg().ek()},l.lh=function(t){return Zie(this,t)},l.mh=function(t){return kXe(this,t)},l.oh=function(t){return Kut(this,t)},l.ph=function(){throw J(new Fr)},l.qh=function(){return this.Pg()?this.Pg().ek():null},l.rh=function(){return SH(this)},l.sh=function(t,n){Bse(this,t,n)},l.th=function(t){this.ph().hk(t)},l.uh=function(t){this.ph().kk(t)},l.vh=function(t){this.ph().jk(t)},l.wh=function(t,n){var r,s,o,h;return h=this.Zg(),h&&t&&(n=Xa(h.Vk(),this,n),h.Zk(this)),s=this.eh(),s&&(rae(this,this.eh(),this.Vg()).Bb&so?(o=s.fh(),o&&(t?!h&&o.Zk(this):o.Yk(this))):(n=(r=this.Vg(),r>=0?this.Qg(n):this.eh().ih(this,-1-r,null,n)),n=this.Sg(null,-1,n))),this.uh(t),n},l.xh=function(t){var n,r,s,o,h,d,v,x;if(r=this.Tg(),h=Ji(r,t),n=this.Ah(),h>=n)return u(t,66).Nj().Uj(this,this.yh(),h-n);if(h<=-1)if(d=v4((Yu(),Oa),r,t),d){if(ho(),u(d,66).Oj()||(d=F6(Po(Oa,d))),o=(s=this.Yg(d),u(s>=0?this._g(s,!0,!0):tw(this,d,!0),153)),x=d.Zj(),x>1||x==-1)return u(u(o,215).hl(t,!1),76)}else throw J(new Ln(i2+t.ne()+Oce));else if(t.$j())return s=this.Yg(t),u(s>=0?this._g(s,!1,!0):tw(this,t,!1),76);return v=new Hqe(this,t),v},l.yh=function(){return vme(this)},l.zh=function(){return(Rp(),En).S},l.Ah=function(){return Jn(this.zh())},l.Bh=function(t){Dse(this,t)},l.Ib=function(){return _f(this)},O(Tn,"BasicEObjectImpl",97);var q3t;M(114,97,{105:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1}),l.Ch=function(t){var n;return n=wme(this),n[t]},l.Dh=function(t,n){var r;r=wme(this),cs(r,t,n)},l.Eh=function(t){var n;n=wme(this),cs(n,t,null)},l.Jg=function(){return u(_n(this,4),126)},l.Kg=function(){throw J(new Fr)},l.Lg=function(){return(this.Db&4)!=0},l.Pg=function(){throw J(new Fr)},l.Fh=function(t){X6(this,2,t)},l.Rg=function(t,n){this.Db=n<<16|this.Db&255,this.Fh(t)},l.Tg=function(){return Su(this)},l.Vg=function(){return this.Db>>16},l.Wg=function(){var t,n;return PT(),n=bwe(xd((t=u(_n(this,16),26),t||this.zh()))),n==null?Tfe:new OM(this,n)},l.Mg=function(){return(this.Db&1)==0},l.Zg=function(){return u(_n(this,128),1935)},l.$g=function(){return u(_n(this,16),26)},l.dh=function(){return(this.Db&32)!=0},l.eh=function(){return u(_n(this,2),49)},l.kh=function(){return(this.Db&64)!=0},l.ph=function(){throw J(new Fr)},l.qh=function(){return u(_n(this,64),281)},l.th=function(t){X6(this,16,t)},l.uh=function(t){X6(this,128,t)},l.vh=function(t){X6(this,64,t)},l.yh=function(){return du(this)},l.Db=0,O(Tn,"MinimalEObjectImpl",114),M(115,114,{105:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1}),l.Fh=function(t){this.Cb=t},l.eh=function(){return this.Cb},O(Tn,"MinimalEObjectImpl/Container",115),M(1985,115,{105:1,413:1,94:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1}),l._g=function(t,n,r){return L3e(this,t,n,r)},l.jh=function(t,n,r){return v4e(this,t,n,r)},l.lh=function(t){return Awe(this,t)},l.sh=function(t,n){gye(this,t,n)},l.zh=function(){return cu(),G3t},l.Bh=function(t){rye(this,t)},l.Ve=function(){return tit(this)},l.We=function(t){return Ft(this,t)},l.Xe=function(t){return J2(this,t)},l.Ye=function(t,n){return So(this,t,n)},O(xb,"EMapPropertyHolderImpl",1985),M(567,115,{105:1,469:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1},pp),l._g=function(t,n,r){switch(t){case 0:return this.a;case 1:return this.b}return NH(this,t,n,r)},l.lh=function(t){switch(t){case 0:return this.a!=0;case 1:return this.b!=0}return Zie(this,t)},l.sh=function(t,n){switch(t){case 0:z$(this,Ue(ft(n)));return;case 1:G$(this,Ue(ft(n)));return}Bse(this,t,n)},l.zh=function(){return cu(),j3t},l.Bh=function(t){switch(t){case 0:z$(this,0);return;case 1:G$(this,0);return}Dse(this,t)},l.Ib=function(){var t;return this.Db&64?_f(this):(t=new Ph(_f(this)),t.a+=" (x: ",I3(t,this.a),t.a+=", y: ",I3(t,this.b),t.a+=")",t.a)},l.a=0,l.b=0,O(xb,"ElkBendPointImpl",567),M(723,1985,{105:1,413:1,160:1,94:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1}),l._g=function(t,n,r){return Oye(this,t,n,r)},l.hh=function(t,n,r){return _se(this,t,n,r)},l.jh=function(t,n,r){return uie(this,t,n,r)},l.lh=function(t){return Yme(this,t)},l.sh=function(t,n){K3e(this,t,n)},l.zh=function(){return cu(),H3t},l.Bh=function(t){Lye(this,t)},l.zg=function(){return this.k},l.Ag=function(){return Wj(this)},l.Ib=function(){return Bie(this)},l.k=null,O(xb,"ElkGraphElementImpl",723),M(724,723,{105:1,413:1,160:1,470:1,94:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1}),l._g=function(t,n,r){return Gye(this,t,n,r)},l.lh=function(t){return Xye(this,t)},l.sh=function(t,n){Y3e(this,t,n)},l.zh=function(){return cu(),z3t},l.Bh=function(t){t3e(this,t)},l.Bg=function(){return this.f},l.Cg=function(){return this.g},l.Dg=function(){return this.i},l.Eg=function(){return this.j},l.Fg=function(t,n){ej(this,t,n)},l.Gg=function(t,n){C1(this,t,n)},l.Hg=function(t){Du(this,t)},l.Ig=function(t){Iu(this,t)},l.Ib=function(){return Mse(this)},l.f=0,l.g=0,l.i=0,l.j=0,O(xb,"ElkShapeImpl",724),M(725,724,{105:1,413:1,82:1,160:1,470:1,94:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1}),l._g=function(t,n,r){return E3e(this,t,n,r)},l.hh=function(t,n,r){return z3e(this,t,n,r)},l.jh=function(t,n,r){return G3e(this,t,n,r)},l.lh=function(t){return fye(this,t)},l.sh=function(t,n){Z4e(this,t,n)},l.zh=function(){return cu(),$3t},l.Bh=function(t){p3e(this,t)},l.xg=function(){return!this.d&&(this.d=new wn(ra,this,8,5)),this.d},l.yg=function(){return!this.e&&(this.e=new wn(ra,this,7,4)),this.e},O(xb,"ElkConnectableShapeImpl",725),M(352,723,{105:1,413:1,79:1,160:1,352:1,94:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1},rv),l.Qg=function(t){return F3e(this,t)},l._g=function(t,n,r){switch(t){case 3:return nD(this);case 4:return!this.b&&(this.b=new wn(mr,this,4,7)),this.b;case 5:return!this.c&&(this.c=new wn(mr,this,5,8)),this.c;case 6:return!this.a&&(this.a=new at(os,this,6,6)),this.a;case 7:return Mn(),!this.b&&(this.b=new wn(mr,this,4,7)),!(this.b.i<=1&&(!this.c&&(this.c=new wn(mr,this,5,8)),this.c.i<=1));case 8:return Mn(),!!iC(this);case 9:return Mn(),!!ew(this);case 10:return Mn(),!this.b&&(this.b=new wn(mr,this,4,7)),this.b.i!=0&&(!this.c&&(this.c=new wn(mr,this,5,8)),this.c.i!=0)}return Oye(this,t,n,r)},l.hh=function(t,n,r){var s;switch(n){case 3:return this.Cb&&(r=(s=this.Db>>16,s>=0?F3e(this,r):this.Cb.ih(this,-1-s,null,r))),Dbe(this,u(t,33),r);case 4:return!this.b&&(this.b=new wn(mr,this,4,7)),ou(this.b,t,r);case 5:return!this.c&&(this.c=new wn(mr,this,5,8)),ou(this.c,t,r);case 6:return!this.a&&(this.a=new at(os,this,6,6)),ou(this.a,t,r)}return _se(this,t,n,r)},l.jh=function(t,n,r){switch(n){case 3:return Dbe(this,null,r);case 4:return!this.b&&(this.b=new wn(mr,this,4,7)),Xa(this.b,t,r);case 5:return!this.c&&(this.c=new wn(mr,this,5,8)),Xa(this.c,t,r);case 6:return!this.a&&(this.a=new at(os,this,6,6)),Xa(this.a,t,r)}return uie(this,t,n,r)},l.lh=function(t){switch(t){case 3:return!!nD(this);case 4:return!!this.b&&this.b.i!=0;case 5:return!!this.c&&this.c.i!=0;case 6:return!!this.a&&this.a.i!=0;case 7:return!this.b&&(this.b=new wn(mr,this,4,7)),!(this.b.i<=1&&(!this.c&&(this.c=new wn(mr,this,5,8)),this.c.i<=1));case 8:return iC(this);case 9:return ew(this);case 10:return!this.b&&(this.b=new wn(mr,this,4,7)),this.b.i!=0&&(!this.c&&(this.c=new wn(mr,this,5,8)),this.c.i!=0)}return Yme(this,t)},l.sh=function(t,n){switch(t){case 3:Wse(this,u(n,33));return;case 4:!this.b&&(this.b=new wn(mr,this,4,7)),_r(this.b),!this.b&&(this.b=new wn(mr,this,4,7)),fs(this.b,u(n,14));return;case 5:!this.c&&(this.c=new wn(mr,this,5,8)),_r(this.c),!this.c&&(this.c=new wn(mr,this,5,8)),fs(this.c,u(n,14));return;case 6:!this.a&&(this.a=new at(os,this,6,6)),_r(this.a),!this.a&&(this.a=new at(os,this,6,6)),fs(this.a,u(n,14));return}K3e(this,t,n)},l.zh=function(){return cu(),kAe},l.Bh=function(t){switch(t){case 3:Wse(this,null);return;case 4:!this.b&&(this.b=new wn(mr,this,4,7)),_r(this.b);return;case 5:!this.c&&(this.c=new wn(mr,this,5,8)),_r(this.c);return;case 6:!this.a&&(this.a=new at(os,this,6,6)),_r(this.a);return}Lye(this,t)},l.Ib=function(){return Out(this)},O(xb,"ElkEdgeImpl",352),M(439,1985,{105:1,413:1,202:1,439:1,94:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1},ld),l.Qg=function(t){return N3e(this,t)},l._g=function(t,n,r){switch(t){case 1:return this.j;case 2:return this.k;case 3:return this.b;case 4:return this.c;case 5:return!this.a&&(this.a=new Bs(ef,this,5)),this.a;case 6:return wXe(this);case 7:return n?rse(this):this.i;case 8:return n?nse(this):this.f;case 9:return!this.g&&(this.g=new wn(os,this,9,10)),this.g;case 10:return!this.e&&(this.e=new wn(os,this,10,9)),this.e;case 11:return this.d}return L3e(this,t,n,r)},l.hh=function(t,n,r){var s,o,h;switch(n){case 6:return this.Cb&&(r=(o=this.Db>>16,o>=0?N3e(this,r):this.Cb.ih(this,-1-o,null,r))),Ibe(this,u(t,79),r);case 9:return!this.g&&(this.g=new wn(os,this,9,10)),ou(this.g,t,r);case 10:return!this.e&&(this.e=new wn(os,this,10,9)),ou(this.e,t,r)}return h=u(gn((s=u(_n(this,16),26),s||(cu(),qV)),n),66),h.Nj().Qj(this,du(this),n-Jn((cu(),qV)),t,r)},l.jh=function(t,n,r){switch(n){case 5:return!this.a&&(this.a=new Bs(ef,this,5)),Xa(this.a,t,r);case 6:return Ibe(this,null,r);case 9:return!this.g&&(this.g=new wn(os,this,9,10)),Xa(this.g,t,r);case 10:return!this.e&&(this.e=new wn(os,this,10,9)),Xa(this.e,t,r)}return v4e(this,t,n,r)},l.lh=function(t){switch(t){case 1:return this.j!=0;case 2:return this.k!=0;case 3:return this.b!=0;case 4:return this.c!=0;case 5:return!!this.a&&this.a.i!=0;case 6:return!!wXe(this);case 7:return!!this.i;case 8:return!!this.f;case 9:return!!this.g&&this.g.i!=0;case 10:return!!this.e&&this.e.i!=0;case 11:return this.d!=null}return Awe(this,t)},l.sh=function(t,n){switch(t){case 1:N8(this,Ue(ft(n)));return;case 2:B8(this,Ue(ft(n)));return;case 3:O8(this,Ue(ft(n)));return;case 4:P8(this,Ue(ft(n)));return;case 5:!this.a&&(this.a=new Bs(ef,this,5)),_r(this.a),!this.a&&(this.a=new Bs(ef,this,5)),fs(this.a,u(n,14));return;case 6:Not(this,u(n,79));return;case 7:K$(this,u(n,82));return;case 8:W$(this,u(n,82));return;case 9:!this.g&&(this.g=new wn(os,this,9,10)),_r(this.g),!this.g&&(this.g=new wn(os,this,9,10)),fs(this.g,u(n,14));return;case 10:!this.e&&(this.e=new wn(os,this,10,9)),_r(this.e),!this.e&&(this.e=new wn(os,this,10,9)),fs(this.e,u(n,14));return;case 11:$me(this,Hr(n));return}gye(this,t,n)},l.zh=function(){return cu(),qV},l.Bh=function(t){switch(t){case 1:N8(this,0);return;case 2:B8(this,0);return;case 3:O8(this,0);return;case 4:P8(this,0);return;case 5:!this.a&&(this.a=new Bs(ef,this,5)),_r(this.a);return;case 6:Not(this,null);return;case 7:K$(this,null);return;case 8:W$(this,null);return;case 9:!this.g&&(this.g=new wn(os,this,9,10)),_r(this.g);return;case 10:!this.e&&(this.e=new wn(os,this,10,9)),_r(this.e);return;case 11:$me(this,null);return}rye(this,t)},l.Ib=function(){return Zat(this)},l.b=0,l.c=0,l.d=null,l.j=0,l.k=0,O(xb,"ElkEdgeSectionImpl",439),M(150,115,{105:1,92:1,90:1,147:1,56:1,108:1,49:1,97:1,150:1,114:1,115:1}),l._g=function(t,n,r){var s;return t==0?(!this.Ab&&(this.Ab=new at(ti,this,0,3)),this.Ab):ph(this,t-Jn(this.zh()),gn((s=u(_n(this,16),26),s||this.zh()),t),n,r)},l.hh=function(t,n,r){var s,o;return n==0?(!this.Ab&&(this.Ab=new at(ti,this,0,3)),ou(this.Ab,t,r)):(o=u(gn((s=u(_n(this,16),26),s||this.zh()),n),66),o.Nj().Qj(this,du(this),n-Jn(this.zh()),t,r))},l.jh=function(t,n,r){var s,o;return n==0?(!this.Ab&&(this.Ab=new at(ti,this,0,3)),Xa(this.Ab,t,r)):(o=u(gn((s=u(_n(this,16),26),s||this.zh()),n),66),o.Nj().Rj(this,du(this),n-Jn(this.zh()),t,r))},l.lh=function(t){var n;return t==0?!!this.Ab&&this.Ab.i!=0:dh(this,t-Jn(this.zh()),gn((n=u(_n(this,16),26),n||this.zh()),t))},l.oh=function(t){return a6e(this,t)},l.sh=function(t,n){var r;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab),!this.Ab&&(this.Ab=new at(ti,this,0,3)),fs(this.Ab,u(n,14));return}yh(this,t-Jn(this.zh()),gn((r=u(_n(this,16),26),r||this.zh()),t),n)},l.uh=function(t){X6(this,128,t)},l.zh=function(){return on(),c4t},l.Bh=function(t){var n;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab);return}wh(this,t-Jn(this.zh()),gn((n=u(_n(this,16),26),n||this.zh()),t))},l.Gh=function(){this.Bb|=1},l.Hh=function(t){return uC(this,t)},l.Bb=0,O(Tn,"EModelElementImpl",150),M(704,150,{105:1,92:1,90:1,471:1,147:1,56:1,108:1,49:1,97:1,150:1,114:1,115:1},RR),l.Ih=function(t,n){return ult(this,t,n)},l.Jh=function(t){var n,r,s,o,h;if(this.a!=Gl(t)||t.Bb&256)throw J(new Ln(Pce+t.zb+dw));for(s=jo(t);jc(s.a).i!=0;){if(r=u(xI(s,0,(n=u(Te(jc(s.a),0),87),h=n.c,we(h,88)?u(h,26):(on(),sf))),26),Jv(r))return o=Gl(r).Nh().Jh(r),u(o,49).th(t),o;s=jo(r)}return(t.D!=null?t.D:t.B)=="java.util.Map$Entry"?new nKe(t):new wve(t)},l.Kh=function(t,n){return aw(this,t,n)},l._g=function(t,n,r){var s;switch(t){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),this.Ab;case 1:return this.a}return ph(this,t-Jn((on(),_2)),gn((s=u(_n(this,16),26),s||_2),t),n,r)},l.hh=function(t,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),ou(this.Ab,t,r);case 1:return this.a&&(r=u(this.a,49).ih(this,4,h1,r)),Sye(this,u(t,235),r)}return o=u(gn((s=u(_n(this,16),26),s||(on(),_2)),n),66),o.Nj().Qj(this,du(this),n-Jn((on(),_2)),t,r)},l.jh=function(t,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),Xa(this.Ab,t,r);case 1:return Sye(this,null,r)}return o=u(gn((s=u(_n(this,16),26),s||(on(),_2)),n),66),o.Nj().Rj(this,du(this),n-Jn((on(),_2)),t,r)},l.lh=function(t){var n;switch(t){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return!!this.a}return dh(this,t-Jn((on(),_2)),gn((n=u(_n(this,16),26),n||_2),t))},l.sh=function(t,n){var r;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab),!this.Ab&&(this.Ab=new at(ti,this,0,3)),fs(this.Ab,u(n,14));return;case 1:Nst(this,u(n,235));return}yh(this,t-Jn((on(),_2)),gn((r=u(_n(this,16),26),r||_2),t),n)},l.zh=function(){return on(),_2},l.Bh=function(t){var n;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab);return;case 1:Nst(this,null);return}wh(this,t-Jn((on(),_2)),gn((n=u(_n(this,16),26),n||_2),t))};var WS,_Ae,V3t;O(Tn,"EFactoryImpl",704),M(Sf,704,{105:1,2014:1,92:1,90:1,471:1,147:1,56:1,108:1,49:1,97:1,150:1,114:1,115:1},Y5),l.Ih=function(t,n){switch(t.yj()){case 12:return u(n,146).tg();case 13:return Qo(n);default:throw J(new Ln($7+t.ne()+dw))}},l.Jh=function(t){var n,r,s,o,h,d,v,x;switch(t.G==-1&&(t.G=(n=Gl(t),n?Dg(n.Mh(),t):-1)),t.G){case 4:return h=new j9,h;case 6:return d=new kpe,d;case 7:return v=new xpe,v;case 8:return s=new rv,s;case 9:return r=new pp,r;case 10:return o=new ld,o;case 11:return x=new qB,x;default:throw J(new Ln(Pce+t.zb+dw))}},l.Kh=function(t,n){switch(t.yj()){case 13:case 12:return null;default:throw J(new Ln($7+t.ne()+dw))}},O(xb,"ElkGraphFactoryImpl",Sf),M(438,150,{105:1,92:1,90:1,147:1,191:1,56:1,108:1,49:1,97:1,150:1,114:1,115:1}),l.Wg=function(){var t,n;return n=(t=u(_n(this,16),26),bwe(xd(t||this.zh()))),n==null?(PT(),PT(),Tfe):new EUe(this,n)},l._g=function(t,n,r){var s;switch(t){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),this.Ab;case 1:return this.ne()}return ph(this,t-Jn(this.zh()),gn((s=u(_n(this,16),26),s||this.zh()),t),n,r)},l.lh=function(t){var n;switch(t){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null}return dh(this,t-Jn(this.zh()),gn((n=u(_n(this,16),26),n||this.zh()),t))},l.sh=function(t,n){var r;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab),!this.Ab&&(this.Ab=new at(ti,this,0,3)),fs(this.Ab,u(n,14));return;case 1:this.Lh(Hr(n));return}yh(this,t-Jn(this.zh()),gn((r=u(_n(this,16),26),r||this.zh()),t),n)},l.zh=function(){return on(),u4t},l.Bh=function(t){var n;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab);return;case 1:this.Lh(null);return}wh(this,t-Jn(this.zh()),gn((n=u(_n(this,16),26),n||this.zh()),t))},l.ne=function(){return this.zb},l.Lh=function(t){au(this,t)},l.Ib=function(){return $_(this)},l.zb=null,O(Tn,"ENamedElementImpl",438),M(179,438,{105:1,92:1,90:1,147:1,191:1,56:1,235:1,108:1,49:1,97:1,150:1,179:1,114:1,115:1,675:1},rXe),l.Qg=function(t){return Kit(this,t)},l._g=function(t,n,r){var s;switch(t){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),this.Ab;case 1:return this.zb;case 2:return this.yb;case 3:return this.xb;case 4:return this.sb;case 5:return!this.rb&&(this.rb=new Pm(this,f1,this)),this.rb;case 6:return!this.vb&&(this.vb=new S6(h1,this,6,7)),this.vb;case 7:return n?this.Db>>16==7?u(this.Cb,235):null:mXe(this)}return ph(this,t-Jn((on(),Qg)),gn((s=u(_n(this,16),26),s||Qg),t),n,r)},l.hh=function(t,n,r){var s,o,h;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),ou(this.Ab,t,r);case 4:return this.sb&&(r=u(this.sb,49).ih(this,1,US,r)),Dye(this,u(t,471),r);case 5:return!this.rb&&(this.rb=new Pm(this,f1,this)),ou(this.rb,t,r);case 6:return!this.vb&&(this.vb=new S6(h1,this,6,7)),ou(this.vb,t,r);case 7:return this.Cb&&(r=(o=this.Db>>16,o>=0?Kit(this,r):this.Cb.ih(this,-1-o,null,r))),Kl(this,t,7,r)}return h=u(gn((s=u(_n(this,16),26),s||(on(),Qg)),n),66),h.Nj().Qj(this,du(this),n-Jn((on(),Qg)),t,r)},l.jh=function(t,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),Xa(this.Ab,t,r);case 4:return Dye(this,null,r);case 5:return!this.rb&&(this.rb=new Pm(this,f1,this)),Xa(this.rb,t,r);case 6:return!this.vb&&(this.vb=new S6(h1,this,6,7)),Xa(this.vb,t,r);case 7:return Kl(this,null,7,r)}return o=u(gn((s=u(_n(this,16),26),s||(on(),Qg)),n),66),o.Nj().Rj(this,du(this),n-Jn((on(),Qg)),t,r)},l.lh=function(t){var n;switch(t){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return this.yb!=null;case 3:return this.xb!=null;case 4:return!!this.sb;case 5:return!!this.rb&&this.rb.i!=0;case 6:return!!this.vb&&this.vb.i!=0;case 7:return!!mXe(this)}return dh(this,t-Jn((on(),Qg)),gn((n=u(_n(this,16),26),n||Qg),t))},l.oh=function(t){var n;return n=Fgn(this,t),n||a6e(this,t)},l.sh=function(t,n){var r;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab),!this.Ab&&(this.Ab=new at(ti,this,0,3)),fs(this.Ab,u(n,14));return;case 1:au(this,Hr(n));return;case 2:tH(this,Hr(n));return;case 3:eH(this,Hr(n));return;case 4:Lse(this,u(n,471));return;case 5:!this.rb&&(this.rb=new Pm(this,f1,this)),_r(this.rb),!this.rb&&(this.rb=new Pm(this,f1,this)),fs(this.rb,u(n,14));return;case 6:!this.vb&&(this.vb=new S6(h1,this,6,7)),_r(this.vb),!this.vb&&(this.vb=new S6(h1,this,6,7)),fs(this.vb,u(n,14));return}yh(this,t-Jn((on(),Qg)),gn((r=u(_n(this,16),26),r||Qg),t),n)},l.vh=function(t){var n,r;if(t&&this.rb)for(r=new rr(this.rb);r.e!=r.i.gc();)n=pr(r),we(n,351)&&(u(n,351).w=null);X6(this,64,t)},l.zh=function(){return on(),Qg},l.Bh=function(t){var n;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab);return;case 1:au(this,null);return;case 2:tH(this,null);return;case 3:eH(this,null);return;case 4:Lse(this,null);return;case 5:!this.rb&&(this.rb=new Pm(this,f1,this)),_r(this.rb);return;case 6:!this.vb&&(this.vb=new S6(h1,this,6,7)),_r(this.vb);return}wh(this,t-Jn((on(),Qg)),gn((n=u(_n(this,16),26),n||Qg),t))},l.Gh=function(){bse(this)},l.Mh=function(){return!this.rb&&(this.rb=new Pm(this,f1,this)),this.rb},l.Nh=function(){return this.sb},l.Oh=function(){return this.ub},l.Ph=function(){return this.xb},l.Qh=function(){return this.yb},l.Rh=function(t){this.ub=t},l.Ib=function(){var t;return this.Db&64?$_(this):(t=new Ph($_(this)),t.a+=" (nsURI: ",To(t,this.yb),t.a+=", nsPrefix: ",To(t,this.xb),t.a+=")",t.a)},l.xb=null,l.yb=null,O(Tn,"EPackageImpl",179),M(555,179,{105:1,2016:1,555:1,92:1,90:1,147:1,191:1,56:1,235:1,108:1,49:1,97:1,150:1,179:1,114:1,115:1,675:1},oot),l.q=!1,l.r=!1;var U3t=!1;O(xb,"ElkGraphPackageImpl",555),M(354,724,{105:1,413:1,160:1,137:1,470:1,354:1,94:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1},j9),l.Qg=function(t){return P3e(this,t)},l._g=function(t,n,r){switch(t){case 7:return yXe(this);case 8:return this.a}return Gye(this,t,n,r)},l.hh=function(t,n,r){var s;switch(n){case 7:return this.Cb&&(r=(s=this.Db>>16,s>=0?P3e(this,r):this.Cb.ih(this,-1-s,null,r))),Ove(this,u(t,160),r)}return _se(this,t,n,r)},l.jh=function(t,n,r){return n==7?Ove(this,null,r):uie(this,t,n,r)},l.lh=function(t){switch(t){case 7:return!!yXe(this);case 8:return!an("",this.a)}return Xye(this,t)},l.sh=function(t,n){switch(t){case 7:f5e(this,u(n,160));return;case 8:Ome(this,Hr(n));return}Y3e(this,t,n)},l.zh=function(){return cu(),xAe},l.Bh=function(t){switch(t){case 7:f5e(this,null);return;case 8:Ome(this,"");return}t3e(this,t)},l.Ib=function(){return Kst(this)},l.a="",O(xb,"ElkLabelImpl",354),M(239,725,{105:1,413:1,82:1,160:1,33:1,470:1,239:1,94:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1},kpe),l.Qg=function(t){return j3e(this,t)},l._g=function(t,n,r){switch(t){case 9:return!this.c&&(this.c=new at(xl,this,9,9)),this.c;case 10:return!this.a&&(this.a=new at(hs,this,10,11)),this.a;case 11:return us(this);case 12:return!this.b&&(this.b=new at(ra,this,12,3)),this.b;case 13:return Mn(),!this.a&&(this.a=new at(hs,this,10,11)),this.a.i>0}return E3e(this,t,n,r)},l.hh=function(t,n,r){var s;switch(n){case 9:return!this.c&&(this.c=new at(xl,this,9,9)),ou(this.c,t,r);case 10:return!this.a&&(this.a=new at(hs,this,10,11)),ou(this.a,t,r);case 11:return this.Cb&&(r=(s=this.Db>>16,s>=0?j3e(this,r):this.Cb.ih(this,-1-s,null,r))),Hbe(this,u(t,33),r);case 12:return!this.b&&(this.b=new at(ra,this,12,3)),ou(this.b,t,r)}return z3e(this,t,n,r)},l.jh=function(t,n,r){switch(n){case 9:return!this.c&&(this.c=new at(xl,this,9,9)),Xa(this.c,t,r);case 10:return!this.a&&(this.a=new at(hs,this,10,11)),Xa(this.a,t,r);case 11:return Hbe(this,null,r);case 12:return!this.b&&(this.b=new at(ra,this,12,3)),Xa(this.b,t,r)}return G3e(this,t,n,r)},l.lh=function(t){switch(t){case 9:return!!this.c&&this.c.i!=0;case 10:return!!this.a&&this.a.i!=0;case 11:return!!us(this);case 12:return!!this.b&&this.b.i!=0;case 13:return!this.a&&(this.a=new at(hs,this,10,11)),this.a.i>0}return fye(this,t)},l.sh=function(t,n){switch(t){case 9:!this.c&&(this.c=new at(xl,this,9,9)),_r(this.c),!this.c&&(this.c=new at(xl,this,9,9)),fs(this.c,u(n,14));return;case 10:!this.a&&(this.a=new at(hs,this,10,11)),_r(this.a),!this.a&&(this.a=new at(hs,this,10,11)),fs(this.a,u(n,14));return;case 11:u5e(this,u(n,33));return;case 12:!this.b&&(this.b=new at(ra,this,12,3)),_r(this.b),!this.b&&(this.b=new at(ra,this,12,3)),fs(this.b,u(n,14));return}Z4e(this,t,n)},l.zh=function(){return cu(),EAe},l.Bh=function(t){switch(t){case 9:!this.c&&(this.c=new at(xl,this,9,9)),_r(this.c);return;case 10:!this.a&&(this.a=new at(hs,this,10,11)),_r(this.a);return;case 11:u5e(this,null);return;case 12:!this.b&&(this.b=new at(ra,this,12,3)),_r(this.b);return}p3e(this,t)},l.Ib=function(){return S5e(this)},O(xb,"ElkNodeImpl",239),M(186,725,{105:1,413:1,82:1,160:1,118:1,470:1,186:1,94:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1},xpe),l.Qg=function(t){return B3e(this,t)},l._g=function(t,n,r){return t==9?L1(this):E3e(this,t,n,r)},l.hh=function(t,n,r){var s;switch(n){case 9:return this.Cb&&(r=(s=this.Db>>16,s>=0?B3e(this,r):this.Cb.ih(this,-1-s,null,r))),Obe(this,u(t,33),r)}return z3e(this,t,n,r)},l.jh=function(t,n,r){return n==9?Obe(this,null,r):G3e(this,t,n,r)},l.lh=function(t){return t==9?!!L1(this):fye(this,t)},l.sh=function(t,n){switch(t){case 9:c5e(this,u(n,33));return}Z4e(this,t,n)},l.zh=function(){return cu(),TAe},l.Bh=function(t){switch(t){case 9:c5e(this,null);return}p3e(this,t)},l.Ib=function(){return Nct(this)},O(xb,"ElkPortImpl",186);var W3t=ss(Qa,"BasicEMap/Entry");M(1092,115,{105:1,42:1,92:1,90:1,133:1,56:1,108:1,49:1,97:1,114:1,115:1},qB),l.Fb=function(t){return this===t},l.cd=function(){return this.b},l.Hb=function(){return xv(this)},l.Uh=function(t){Nme(this,u(t,146))},l._g=function(t,n,r){switch(t){case 0:return this.b;case 1:return this.c}return NH(this,t,n,r)},l.lh=function(t){switch(t){case 0:return!!this.b;case 1:return this.c!=null}return Zie(this,t)},l.sh=function(t,n){switch(t){case 0:Nme(this,u(n,146));return;case 1:Rme(this,n);return}Bse(this,t,n)},l.zh=function(){return cu(),k2},l.Bh=function(t){switch(t){case 0:Nme(this,null);return;case 1:Rme(this,null);return}Dse(this,t)},l.Sh=function(){var t;return this.a==-1&&(t=this.b,this.a=t?Xi(t):0),this.a},l.dd=function(){return this.c},l.Th=function(t){this.a=t},l.ed=function(t){var n;return n=this.c,Rme(this,t),n},l.Ib=function(){var t;return this.Db&64?_f(this):(t=new Tp,Yr(Yr(Yr(t,this.b?this.b.tg():Pu),Ioe),r_(this.c)),t.a)},l.a=-1,l.c=null;var Dw=O(xb,"ElkPropertyToValueMapEntryImpl",1092);M(984,1,{},VB),O(Ia,"JsonAdapter",984),M(210,60,q0,dd),O(Ia,"JsonImportException",210),M(857,1,{},Yit),O(Ia,"JsonImporter",857),M(891,1,{},xqe),O(Ia,"JsonImporter/lambda$0$Type",891),M(892,1,{},Eqe),O(Ia,"JsonImporter/lambda$1$Type",892),M(900,1,{},r$e),O(Ia,"JsonImporter/lambda$10$Type",900),M(902,1,{},Tqe),O(Ia,"JsonImporter/lambda$11$Type",902),M(903,1,{},_qe),O(Ia,"JsonImporter/lambda$12$Type",903),M(909,1,{},RYe),O(Ia,"JsonImporter/lambda$13$Type",909),M(908,1,{},BYe),O(Ia,"JsonImporter/lambda$14$Type",908),M(904,1,{},Cqe),O(Ia,"JsonImporter/lambda$15$Type",904),M(905,1,{},Sqe),O(Ia,"JsonImporter/lambda$16$Type",905),M(906,1,{},Aqe),O(Ia,"JsonImporter/lambda$17$Type",906),M(907,1,{},Lqe),O(Ia,"JsonImporter/lambda$18$Type",907),M(912,1,{},i$e),O(Ia,"JsonImporter/lambda$19$Type",912),M(893,1,{},s$e),O(Ia,"JsonImporter/lambda$2$Type",893),M(910,1,{},a$e),O(Ia,"JsonImporter/lambda$20$Type",910),M(911,1,{},o$e),O(Ia,"JsonImporter/lambda$21$Type",911),M(915,1,{},c$e),O(Ia,"JsonImporter/lambda$22$Type",915),M(913,1,{},u$e),O(Ia,"JsonImporter/lambda$23$Type",913),M(914,1,{},l$e),O(Ia,"JsonImporter/lambda$24$Type",914),M(917,1,{},h$e),O(Ia,"JsonImporter/lambda$25$Type",917),M(916,1,{},f$e),O(Ia,"JsonImporter/lambda$26$Type",916),M(918,1,Un,Mqe),l.td=function(t){drn(this.b,this.a,Hr(t))},O(Ia,"JsonImporter/lambda$27$Type",918),M(919,1,Un,Dqe),l.td=function(t){grn(this.b,this.a,Hr(t))},O(Ia,"JsonImporter/lambda$28$Type",919),M(920,1,{},Iqe),O(Ia,"JsonImporter/lambda$29$Type",920),M(896,1,{},d$e),O(Ia,"JsonImporter/lambda$3$Type",896),M(921,1,{},Oqe),O(Ia,"JsonImporter/lambda$30$Type",921),M(922,1,{},g$e),O(Ia,"JsonImporter/lambda$31$Type",922),M(923,1,{},p$e),O(Ia,"JsonImporter/lambda$32$Type",923),M(924,1,{},b$e),O(Ia,"JsonImporter/lambda$33$Type",924),M(925,1,{},v$e),O(Ia,"JsonImporter/lambda$34$Type",925),M(859,1,{},w$e),O(Ia,"JsonImporter/lambda$35$Type",859),M(929,1,{},AWe),O(Ia,"JsonImporter/lambda$36$Type",929),M(926,1,Un,m$e),l.td=function(t){vnn(this.a,u(t,469))},O(Ia,"JsonImporter/lambda$37$Type",926),M(927,1,Un,jqe),l.td=function(t){VUt(this.a,this.b,u(t,202))},O(Ia,"JsonImporter/lambda$38$Type",927),M(928,1,Un,$qe),l.td=function(t){UUt(this.a,this.b,u(t,202))},O(Ia,"JsonImporter/lambda$39$Type",928),M(894,1,{},y$e),O(Ia,"JsonImporter/lambda$4$Type",894),M(930,1,Un,k$e),l.td=function(t){wnn(this.a,u(t,8))},O(Ia,"JsonImporter/lambda$40$Type",930),M(895,1,{},x$e),O(Ia,"JsonImporter/lambda$5$Type",895),M(899,1,{},E$e),O(Ia,"JsonImporter/lambda$6$Type",899),M(897,1,{},T$e),O(Ia,"JsonImporter/lambda$7$Type",897),M(898,1,{},_$e),O(Ia,"JsonImporter/lambda$8$Type",898),M(901,1,{},C$e),O(Ia,"JsonImporter/lambda$9$Type",901),M(948,1,Un,S$e),l.td=function(t){O6(this.a,new Bm(Hr(t)))},O(Ia,"JsonMetaDataConverter/lambda$0$Type",948),M(949,1,Un,A$e),l.td=function(t){NZt(this.a,u(t,237))},O(Ia,"JsonMetaDataConverter/lambda$1$Type",949),M(950,1,Un,L$e),l.td=function(t){Den(this.a,u(t,149))},O(Ia,"JsonMetaDataConverter/lambda$2$Type",950),M(951,1,Un,M$e),l.td=function(t){PZt(this.a,u(t,175))},O(Ia,"JsonMetaDataConverter/lambda$3$Type",951),M(237,22,{3:1,35:1,22:1,237:1},E6);var VV,UV,vfe,WV,KV,YV,wfe,mfe,XV=Gr(BI,"GraphFeature",237,Wr,rin,sQt),K3t;M(13,1,{35:1,146:1},Zi,zs,dn,fo),l.wd=function(t){return qWt(this,u(t,146))},l.Fb=function(t){return iXe(this,t)},l.wg=function(){return xt(this)},l.tg=function(){return this.b},l.Hb=function(){return Ig(this.b)},l.Ib=function(){return this.b},O(BI,"Property",13),M(818,1,ji,epe),l.ue=function(t,n){return con(this,u(t,94),u(n,94))},l.Fb=function(t){return this===t},l.ve=function(){return new ue(this)},O(BI,"PropertyHolderComparator",818),M(695,1,ga,tpe),l.Nb=function(t){La(this,t)},l.Pb=function(){return wrn(this)},l.Qb=function(){Eze()},l.Ob=function(){return!!this.a},O(pG,"ElkGraphUtil/AncestorIterator",695);var CAe=ss(Qa,"EList");M(67,52,{20:1,28:1,52:1,14:1,15:1,67:1,58:1}),l.Vc=function(t,n){G_(this,t,n)},l.Fc=function(t){return Br(this,t)},l.Wc=function(t,n){return iye(this,t,n)},l.Gc=function(t){return fs(this,t)},l.Zh=function(){return new C6(this)},l.$h=function(){return new NM(this)},l._h=function(t){return _D(this,t)},l.ai=function(){return!0},l.bi=function(t,n){},l.ci=function(){},l.di=function(t,n){Nre(this,t,n)},l.ei=function(t,n,r){},l.fi=function(t,n){},l.gi=function(t,n,r){},l.Fb=function(t){return yct(this,t)},l.Hb=function(){return Jme(this)},l.hi=function(){return!1},l.Kc=function(){return new rr(this)},l.Yc=function(){return new _6(this)},l.Zc=function(t){var n;if(n=this.gc(),t<0||t>n)throw J(new Im(t,n));return new jne(this,t)},l.ji=function(t,n){this.ii(t,this.Xc(n))},l.Mc=function(t){return N$(this,t)},l.li=function(t,n){return n},l._c=function(t,n){return r4(this,t,n)},l.Ib=function(){return Vye(this)},l.ni=function(){return!0},l.oi=function(t,n){return K8(this,n)},O(Qa,"AbstractEList",67),M(63,67,Od,X5,jv,Vme),l.Vh=function(t,n){return Cse(this,t,n)},l.Wh=function(t){return xit(this,t)},l.Xh=function(t,n){$D(this,t,n)},l.Yh=function(t){cD(this,t)},l.pi=function(t){return fme(this,t)},l.$b=function(){A_(this)},l.Hc=function(t){return u7(this,t)},l.Xb=function(t){return Te(this,t)},l.qi=function(t){var n,r,s;++this.j,r=this.g==null?0:this.g.length,t>r&&(s=this.g,n=r+(r/2|0)+4,n=0?(this.$c(n),!0):!1},l.mi=function(t,n){return this.Ui(t,this.oi(t,n))},l.gc=function(){return this.Vi()},l.Pc=function(){return this.Wi()},l.Qc=function(t){return this.Xi(t)},l.Ib=function(){return this.Yi()},O(Qa,"DelegatingEList",1995),M(1996,1995,bdt),l.Vh=function(t,n){return B5e(this,t,n)},l.Wh=function(t){return this.Vh(this.Vi(),t)},l.Xh=function(t,n){sot(this,t,n)},l.Yh=function(t){Xat(this,t)},l.ai=function(){return!this.bj()},l.$b=function(){pC(this)},l.Zi=function(t,n,r,s,o){return new aXe(this,t,n,r,s,o)},l.$i=function(t){_i(this.Ai(),t)},l._i=function(){return null},l.aj=function(){return-1},l.Ai=function(){return null},l.bj=function(){return!1},l.cj=function(t,n){return n},l.dj=function(t,n){return n},l.ej=function(){return!1},l.fj=function(){return!this.Ri()},l.ii=function(t,n){var r,s;return this.ej()?(s=this.fj(),r=g4e(this,t,n),this.$i(this.Zi(7,ct(n),r,t,s)),r):g4e(this,t,n)},l.$c=function(t){var n,r,s,o;return this.ej()?(r=null,s=this.fj(),n=this.Zi(4,o=Sj(this,t),null,t,s),this.bj()&&o?(r=this.dj(o,r),r?(r.Ei(n),r.Fi()):this.$i(n)):r?(r.Ei(n),r.Fi()):this.$i(n),o):(o=Sj(this,t),this.bj()&&o&&(r=this.dj(o,null),r&&r.Fi()),o)},l.mi=function(t,n){return dut(this,t,n)},O(wk,"DelegatingNotifyingListImpl",1996),M(143,1,XI),l.Ei=function(t){return t4e(this,t)},l.Fi=function(){Gre(this)},l.xi=function(){return this.d},l._i=function(){return null},l.gj=function(){return null},l.yi=function(t){return-1},l.zi=function(){return Jot(this)},l.Ai=function(){return null},l.Bi=function(){return v5e(this)},l.Ci=function(){return this.o<0?this.o<-2?-2-this.o-1:-1:this.o},l.hj=function(){return!1},l.Di=function(t){var n,r,s,o,h,d,v,x,_,L,P;switch(this.d){case 1:case 2:switch(o=t.xi(),o){case 1:case 2:if(h=t.Ai(),je(h)===je(this.Ai())&&this.yi(null)==t.yi(null))return this.g=t.zi(),t.xi()==1&&(this.d=1),!0}case 4:{switch(o=t.xi(),o){case 4:{if(h=t.Ai(),je(h)===je(this.Ai())&&this.yi(null)==t.yi(null))return _=J5e(this),x=this.o<0?this.o<-2?-2-this.o-1:-1:this.o,d=t.Ci(),this.d=6,P=new jv(2),x<=d?(Br(P,this.n),Br(P,t.Bi()),this.g=ie(re(Lr,1),Jr,25,15,[this.o=x,d+1])):(Br(P,t.Bi()),Br(P,this.n),this.g=ie(re(Lr,1),Jr,25,15,[this.o=d,x])),this.n=P,_||(this.o=-2-this.o-1),!0;break}}break}case 6:{switch(o=t.xi(),o){case 4:{if(h=t.Ai(),je(h)===je(this.Ai())&&this.yi(null)==t.yi(null)){for(_=J5e(this),d=t.Ci(),L=u(this.g,48),s=Me(Lr,Jr,25,L.length+1,15,1),n=0;n>>0,n.toString(16))),s.a+=" (eventType: ",this.d){case 1:{s.a+="SET";break}case 2:{s.a+="UNSET";break}case 3:{s.a+="ADD";break}case 5:{s.a+="ADD_MANY";break}case 4:{s.a+="REMOVE";break}case 6:{s.a+="REMOVE_MANY";break}case 7:{s.a+="MOVE";break}case 8:{s.a+="REMOVING_ADAPTER";break}case 9:{s.a+="RESOLVE";break}default:{cte(s,this.d);break}}if(Hct(this)&&(s.a+=", touch: true"),s.a+=", position: ",cte(s,this.o<0?this.o<-2?-2-this.o-1:-1:this.o),s.a+=", notifier: ",QT(s,this.Ai()),s.a+=", feature: ",QT(s,this._i()),s.a+=", oldValue: ",QT(s,v5e(this)),s.a+=", newValue: ",this.d==6&&we(this.g,48)){for(r=u(this.g,48),s.a+="[",t=0;t10?((!this.b||this.c.j!=this.a)&&(this.b=new l_(this),this.a=this.j),_0(this.b,t)):u7(this,t)},l.ni=function(){return!0},l.a=0,O(Qa,"AbstractEList/1",953),M(295,73,noe,Im),O(Qa,"AbstractEList/BasicIndexOutOfBoundsException",295),M(40,1,ga,rr),l.Nb=function(t){La(this,t)},l.mj=function(){if(this.i.j!=this.f)throw J(new uh)},l.nj=function(){return pr(this)},l.Ob=function(){return this.e!=this.i.gc()},l.Pb=function(){return this.nj()},l.Qb=function(){J_(this)},l.e=0,l.f=0,l.g=-1,O(Qa,"AbstractEList/EIterator",40),M(278,40,r0,_6,jne),l.Qb=function(){J_(this)},l.Rb=function(t){Trt(this,t)},l.oj=function(){var t;try{return t=this.d.Xb(--this.e),this.mj(),this.g=this.e,t}catch(n){throw n=ts(n),we(n,73)?(this.mj(),J(new xc)):J(n)}},l.pj=function(t){_it(this,t)},l.Sb=function(){return this.e!=0},l.Tb=function(){return this.e},l.Ub=function(){return this.oj()},l.Vb=function(){return this.e-1},l.Wb=function(t){this.pj(t)},O(Qa,"AbstractEList/EListIterator",278),M(341,40,ga,C6),l.nj=function(){return Jie(this)},l.Qb=function(){throw J(new Fr)},O(Qa,"AbstractEList/NonResolvingEIterator",341),M(385,278,r0,NM,Kbe),l.Rb=function(t){throw J(new Fr)},l.nj=function(){var t;try{return t=this.c.ki(this.e),this.mj(),this.g=this.e++,t}catch(n){throw n=ts(n),we(n,73)?(this.mj(),J(new xc)):J(n)}},l.oj=function(){var t;try{return t=this.c.ki(--this.e),this.mj(),this.g=this.e,t}catch(n){throw n=ts(n),we(n,73)?(this.mj(),J(new xc)):J(n)}},l.Qb=function(){throw J(new Fr)},l.Wb=function(t){throw J(new Fr)},O(Qa,"AbstractEList/NonResolvingEListIterator",385),M(1982,67,vdt),l.Vh=function(t,n){var r,s,o,h,d,v,x,_,L,P,z;if(o=n.gc(),o!=0){for(_=u(_n(this.a,4),126),L=_==null?0:_.length,z=L+o,s=kie(this,z),P=L-t,P>0&&Hc(_,t,s,t+o,P),x=n.Kc(),d=0;dr)throw J(new Im(t,r));return new vYe(this,t)},l.$b=function(){var t,n;++this.j,t=u(_n(this.a,4),126),n=t==null?0:t.length,s7(this,null),Nre(this,n,t)},l.Hc=function(t){var n,r,s,o,h;if(n=u(_n(this.a,4),126),n!=null){if(t!=null){for(s=n,o=0,h=s.length;o=r)throw J(new Im(t,r));return n[t]},l.Xc=function(t){var n,r,s;if(n=u(_n(this.a,4),126),n!=null){if(t!=null){for(r=0,s=n.length;rr)throw J(new Im(t,r));return new bYe(this,t)},l.ii=function(t,n){var r,s,o;if(r=Irt(this),o=r==null?0:r.length,t>=o)throw J(new Do(qce+t+Eb+o));if(n>=o)throw J(new Do(Vce+n+Eb+o));return s=r[n],t!=n&&(t0&&Hc(t,0,n,0,r),n},l.Qc=function(t){var n,r,s;return n=u(_n(this.a,4),126),s=n==null?0:n.length,s>0&&(t.lengths&&cs(t,s,null),t};var Y3t;O(Qa,"ArrayDelegatingEList",1982),M(1038,40,ga,CZe),l.mj=function(){if(this.b.j!=this.f||je(u(_n(this.b.a,4),126))!==je(this.a))throw J(new uh)},l.Qb=function(){J_(this),this.a=u(_n(this.b.a,4),126)},O(Qa,"ArrayDelegatingEList/EIterator",1038),M(706,278,r0,$Ke,bYe),l.mj=function(){if(this.b.j!=this.f||je(u(_n(this.b.a,4),126))!==je(this.a))throw J(new uh)},l.pj=function(t){_it(this,t),this.a=u(_n(this.b.a,4),126)},l.Qb=function(){J_(this),this.a=u(_n(this.b.a,4),126)},O(Qa,"ArrayDelegatingEList/EListIterator",706),M(1039,341,ga,SZe),l.mj=function(){if(this.b.j!=this.f||je(u(_n(this.b.a,4),126))!==je(this.a))throw J(new uh)},O(Qa,"ArrayDelegatingEList/NonResolvingEIterator",1039),M(707,385,r0,HKe,vYe),l.mj=function(){if(this.b.j!=this.f||je(u(_n(this.b.a,4),126))!==je(this.a))throw J(new uh)},O(Qa,"ArrayDelegatingEList/NonResolvingEListIterator",707),M(606,295,noe,zte),O(Qa,"BasicEList/BasicIndexOutOfBoundsException",606),M(696,63,Od,O2e),l.Vc=function(t,n){throw J(new Fr)},l.Fc=function(t){throw J(new Fr)},l.Wc=function(t,n){throw J(new Fr)},l.Gc=function(t){throw J(new Fr)},l.$b=function(){throw J(new Fr)},l.qi=function(t){throw J(new Fr)},l.Kc=function(){return this.Zh()},l.Yc=function(){return this.$h()},l.Zc=function(t){return this._h(t)},l.ii=function(t,n){throw J(new Fr)},l.ji=function(t,n){throw J(new Fr)},l.$c=function(t){throw J(new Fr)},l.Mc=function(t){throw J(new Fr)},l._c=function(t,n){throw J(new Fr)},O(Qa,"BasicEList/UnmodifiableEList",696),M(705,1,{3:1,20:1,14:1,15:1,58:1,589:1}),l.Vc=function(t,n){NWt(this,t,u(n,42))},l.Fc=function(t){return yKt(this,u(t,42))},l.Jc=function(t){Da(this,t)},l.Xb=function(t){return u(Te(this.c,t),133)},l.ii=function(t,n){return u(this.c.ii(t,n),42)},l.ji=function(t,n){PWt(this,t,u(n,42))},l.Lc=function(){return new vn(null,new mn(this,16))},l.$c=function(t){return u(this.c.$c(t),42)},l._c=function(t,n){return AZt(this,t,u(n,42))},l.ad=function(t){Y3(this,t)},l.Nc=function(){return new mn(this,16)},l.Oc=function(){return new vn(null,new mn(this,16))},l.Wc=function(t,n){return this.c.Wc(t,n)},l.Gc=function(t){return this.c.Gc(t)},l.$b=function(){this.c.$b()},l.Hc=function(t){return this.c.Hc(t)},l.Ic=function(t){return MD(this.c,t)},l.qj=function(){var t,n,r;if(this.d==null){for(this.d=Me(SAe,p8e,63,2*this.f+1,0,1),r=this.e,this.f=0,n=this.c.Kc();n.e!=n.i.gc();)t=u(n.nj(),133),RH(this,t);this.e=r}},l.Fb=function(t){return fWe(this,t)},l.Hb=function(){return Jme(this.c)},l.Xc=function(t){return this.c.Xc(t)},l.rj=function(){this.c=new I$e(this)},l.dc=function(){return this.f==0},l.Kc=function(){return this.c.Kc()},l.Yc=function(){return this.c.Yc()},l.Zc=function(t){return this.c.Zc(t)},l.sj=function(){return hD(this)},l.tj=function(t,n,r){return new LWe(t,n,r)},l.uj=function(){return new bp},l.Mc=function(t){return Wet(this,t)},l.gc=function(){return this.f},l.bd=function(t,n){return new Zd(this.c,t,n)},l.Pc=function(){return this.c.Pc()},l.Qc=function(t){return this.c.Qc(t)},l.Ib=function(){return Vye(this.c)},l.e=0,l.f=0,O(Qa,"BasicEMap",705),M(1033,63,Od,I$e),l.bi=function(t,n){vVt(this,u(n,133))},l.ei=function(t,n,r){var s;++(s=this,u(n,133),s).a.e},l.fi=function(t,n){wVt(this,u(n,133))},l.gi=function(t,n,r){oKt(this,u(n,133),u(r,133))},l.di=function(t,n){Rtt(this.a)},O(Qa,"BasicEMap/1",1033),M(1034,63,Od,bp),l.ri=function(t){return Me(L3n,wdt,612,t,0,1)},O(Qa,"BasicEMap/2",1034),M(1035,H1,Xu,O$e),l.$b=function(){this.a.c.$b()},l.Hc=function(t){return qie(this.a,t)},l.Kc=function(){return this.a.f==0?(u8(),uN.a):new gze(this.a)},l.Mc=function(t){var n;return n=this.a.f,CH(this.a,t),this.a.f!=n},l.gc=function(){return this.a.f},O(Qa,"BasicEMap/3",1035),M(1036,28,hy,N$e),l.$b=function(){this.a.c.$b()},l.Hc=function(t){return kct(this.a,t)},l.Kc=function(){return this.a.f==0?(u8(),uN.a):new pze(this.a)},l.gc=function(){return this.a.f},O(Qa,"BasicEMap/4",1036),M(1037,H1,Xu,P$e),l.$b=function(){this.a.c.$b()},l.Hc=function(t){var n,r,s,o,h,d,v,x,_;if(this.a.f>0&&we(t,42)&&(this.a.qj(),x=u(t,42),v=x.cd(),o=v==null?0:Xi(v),h=Nbe(this.a,o),n=this.a.d[h],n)){for(r=u(n.g,367),_=n.i,d=0;d<_;++d)if(s=r[d],s.Sh()==o&&s.Fb(x))return!0}return!1},l.Kc=function(){return this.a.f==0?(u8(),uN.a):new tre(this.a)},l.Mc=function(t){return dot(this,t)},l.gc=function(){return this.a.f},O(Qa,"BasicEMap/5",1037),M(613,1,ga,tre),l.Nb=function(t){La(this,t)},l.Ob=function(){return this.b!=-1},l.Pb=function(){var t;if(this.f.e!=this.c)throw J(new uh);if(this.b==-1)throw J(new xc);return this.d=this.a,this.e=this.b,tst(this),t=u(this.f.d[this.d].g[this.e],133),this.vj(t)},l.Qb=function(){if(this.f.e!=this.c)throw J(new uh);if(this.e==-1)throw J(new zu);this.f.c.Mc(Te(this.f.d[this.d],this.e)),this.c=this.f.e,this.e=-1,this.a==this.d&&this.b!=-1&&--this.b},l.vj=function(t){return t},l.a=0,l.b=-1,l.c=0,l.d=0,l.e=0,O(Qa,"BasicEMap/BasicEMapIterator",613),M(1031,613,ga,gze),l.vj=function(t){return t.cd()},O(Qa,"BasicEMap/BasicEMapKeyIterator",1031),M(1032,613,ga,pze),l.vj=function(t){return t.dd()},O(Qa,"BasicEMap/BasicEMapValueIterator",1032),M(1030,1,ow,B$e),l.wc=function(t){B_(this,t)},l.yc=function(t,n,r){return Rie(this,t,n,r)},l.$b=function(){this.a.c.$b()},l._b=function(t){return Kqe(this,t)},l.uc=function(t){return kct(this.a,t)},l.vc=function(){return Xnn(this.a)},l.Fb=function(t){return fWe(this.a,t)},l.xc=function(t){return r1(this.a,t)},l.Hb=function(){return Jme(this.a.c)},l.dc=function(){return this.a.f==0},l.ec=function(){return Qnn(this.a)},l.zc=function(t,n){return qH(this.a,t,n)},l.Bc=function(t){return CH(this.a,t)},l.gc=function(){return this.a.f},l.Ib=function(){return Vye(this.a.c)},l.Cc=function(){return Ynn(this.a)},O(Qa,"BasicEMap/DelegatingMap",1030),M(612,1,{42:1,133:1,612:1},LWe),l.Fb=function(t){var n;return we(t,42)?(n=u(t,42),(this.b!=null?Ci(this.b,n.cd()):je(this.b)===je(n.cd()))&&(this.c!=null?Ci(this.c,n.dd()):je(this.c)===je(n.dd()))):!1},l.Sh=function(){return this.a},l.cd=function(){return this.b},l.dd=function(){return this.c},l.Hb=function(){return this.a^(this.c==null?0:Xi(this.c))},l.Th=function(t){this.a=t},l.Uh=function(t){throw J(new H2)},l.ed=function(t){var n;return n=this.c,this.c=t,n},l.Ib=function(){return this.b+"->"+this.c},l.a=0;var L3n=O(Qa,"BasicEMap/EntryImpl",612);M(536,1,{},kx),O(Qa,"BasicEMap/View",536);var uN;M(768,1,{}),l.Fb=function(t){return J4e((hn(),bo),t)},l.Hb=function(){return hye((hn(),bo))},l.Ib=function(){return Yp((hn(),bo))},O(Qa,"ECollections/BasicEmptyUnmodifiableEList",768),M(1312,1,r0,UB),l.Nb=function(t){La(this,t)},l.Rb=function(t){throw J(new Fr)},l.Ob=function(){return!1},l.Sb=function(){return!1},l.Pb=function(){throw J(new xc)},l.Tb=function(){return 0},l.Ub=function(){throw J(new xc)},l.Vb=function(){return-1},l.Qb=function(){throw J(new Fr)},l.Wb=function(t){throw J(new Fr)},O(Qa,"ECollections/BasicEmptyUnmodifiableEList/1",1312),M(1310,768,{20:1,14:1,15:1,58:1},_He),l.Vc=function(t,n){Bze()},l.Fc=function(t){return Rze()},l.Wc=function(t,n){return Fze()},l.Gc=function(t){return jze()},l.$b=function(){$ze()},l.Hc=function(t){return!1},l.Ic=function(t){return!1},l.Jc=function(t){Da(this,t)},l.Xb=function(t){return B2e((hn(),t)),null},l.Xc=function(t){return-1},l.dc=function(){return!0},l.Kc=function(){return this.a},l.Yc=function(){return this.a},l.Zc=function(t){return this.a},l.ii=function(t,n){return Hze()},l.ji=function(t,n){zze()},l.Lc=function(){return new vn(null,new mn(this,16))},l.$c=function(t){return Gze()},l.Mc=function(t){return qze()},l._c=function(t,n){return Vze()},l.gc=function(){return 0},l.ad=function(t){Y3(this,t)},l.Nc=function(){return new mn(this,16)},l.Oc=function(){return new vn(null,new mn(this,16))},l.bd=function(t,n){return hn(),new Zd(bo,t,n)},l.Pc=function(){return Bve((hn(),bo))},l.Qc=function(t){return hn(),YD(bo,t)},O(Qa,"ECollections/EmptyUnmodifiableEList",1310),M(1311,768,{20:1,14:1,15:1,58:1,589:1},CHe),l.Vc=function(t,n){Bze()},l.Fc=function(t){return Rze()},l.Wc=function(t,n){return Fze()},l.Gc=function(t){return jze()},l.$b=function(){$ze()},l.Hc=function(t){return!1},l.Ic=function(t){return!1},l.Jc=function(t){Da(this,t)},l.Xb=function(t){return B2e((hn(),t)),null},l.Xc=function(t){return-1},l.dc=function(){return!0},l.Kc=function(){return this.a},l.Yc=function(){return this.a},l.Zc=function(t){return this.a},l.ii=function(t,n){return Hze()},l.ji=function(t,n){zze()},l.Lc=function(){return new vn(null,new mn(this,16))},l.$c=function(t){return Gze()},l.Mc=function(t){return qze()},l._c=function(t,n){return Vze()},l.gc=function(){return 0},l.ad=function(t){Y3(this,t)},l.Nc=function(){return new mn(this,16)},l.Oc=function(){return new vn(null,new mn(this,16))},l.bd=function(t,n){return hn(),new Zd(bo,t,n)},l.Pc=function(){return Bve((hn(),bo))},l.Qc=function(t){return hn(),YD(bo,t)},l.sj=function(){return hn(),hn(),l0},O(Qa,"ECollections/EmptyUnmodifiableEMap",1311);var LAe=ss(Qa,"Enumerator"),QV;M(281,1,{281:1},Zse),l.Fb=function(t){var n;return this===t?!0:we(t,281)?(n=u(t,281),this.f==n.f&&YQt(this.i,n.i)&&_ne(this.a,this.f&256?n.f&256?n.a:null:n.f&256?null:n.a)&&_ne(this.d,n.d)&&_ne(this.g,n.g)&&_ne(this.e,n.e)&&Gcn(this,n)):!1},l.Hb=function(){return this.f},l.Ib=function(){return Zct(this)},l.f=0;var X3t=0,Q3t=0,Z3t=0,J3t=0,MAe=0,DAe=0,IAe=0,OAe=0,NAe=0,e4t,KS=0,YS=0,t4t=0,n4t=0,ZV,PAe;O(Qa,"URI",281),M(1091,43,y4,SHe),l.zc=function(t,n){return u(Oo(this,Hr(t),u(n,281)),281)},O(Qa,"URI/URICache",1091),M(497,63,Od,xx,Lj),l.hi=function(){return!0},O(Qa,"UniqueEList",497),M(581,60,q0,D$),O(Qa,"WrappedException",581);var ti=ss(kh,kdt),qy=ss(kh,xdt),ju=ss(kh,Edt),Vy=ss(kh,Tdt),f1=ss(kh,_dt),tf=ss(kh,"EClass"),xfe=ss(kh,"EDataType"),r4t;M(1183,43,y4,AHe),l.xc=function(t){return fa(t)?Uc(this,t):hc($o(this.f,t))},O(kh,"EDataType/Internal/ConversionDelegate/Factory/Registry/Impl",1183);var JV=ss(kh,"EEnum"),J0=ss(kh,Cdt),Eo=ss(kh,Sdt),nf=ss(kh,Adt),rf,Iw=ss(kh,Ldt),Uy=ss(kh,Mdt);M(1029,1,{},qZ),l.Ib=function(){return"NIL"},O(kh,"EStructuralFeature/Internal/DynamicValueHolder/1",1029);var i4t;M(1028,43,y4,LHe),l.xc=function(t){return fa(t)?Uc(this,t):hc($o(this.f,t))},O(kh,"EStructuralFeature/Internal/SettingDelegate/Factory/Registry/Impl",1028);var mu=ss(kh,Ddt),Hk=ss(kh,"EValidator/PatternMatcher"),BAe,RAe,En,Kg,Wy,E2,s4t,a4t,o4t,T2,Yg,_2,Ow,Z1,c4t,u4t,sf,Xg,l4t,Qg,Ky,n5,oo,h4t,f4t,Nw,eU=ss(Wi,"FeatureMap/Entry");M(535,1,{72:1},KF),l.ak=function(){return this.a},l.dd=function(){return this.b},O(Tn,"BasicEObjectImpl/1",535),M(1027,1,Qce,Hqe),l.Wj=function(t){return Ire(this.a,this.b,t)},l.fj=function(){return kXe(this.a,this.b)},l.Wb=function(t){wwe(this.a,this.b,t)},l.Xj=function(){VZt(this.a,this.b)},O(Tn,"BasicEObjectImpl/4",1027),M(1983,1,{108:1}),l.bk=function(t){this.e=t==0?d4t:Me(Yn,yt,1,t,5,1)},l.Ch=function(t){return this.e[t]},l.Dh=function(t,n){this.e[t]=n},l.Eh=function(t){this.e[t]=null},l.ck=function(){return this.c},l.dk=function(){throw J(new Fr)},l.ek=function(){throw J(new Fr)},l.fk=function(){return this.d},l.gk=function(){return this.e!=null},l.hk=function(t){this.c=t},l.ik=function(t){throw J(new Fr)},l.jk=function(t){throw J(new Fr)},l.kk=function(t){this.d=t};var d4t;O(Tn,"BasicEObjectImpl/EPropertiesHolderBaseImpl",1983),M(185,1983,{108:1},ch),l.dk=function(){return this.a},l.ek=function(){return this.b},l.ik=function(t){this.a=t},l.jk=function(t){this.b=t},O(Tn,"BasicEObjectImpl/EPropertiesHolderImpl",185),M(506,97,I1t,Ex),l.Kg=function(){return this.f},l.Pg=function(){return this.k},l.Rg=function(t,n){this.g=t,this.i=n},l.Tg=function(){return this.j&2?this.ph().ck():this.zh()},l.Vg=function(){return this.i},l.Mg=function(){return(this.j&1)!=0},l.eh=function(){return this.g},l.kh=function(){return(this.j&4)!=0},l.ph=function(){return!this.k&&(this.k=new ch),this.k},l.th=function(t){this.ph().hk(t),t?this.j|=2:this.j&=-3},l.vh=function(t){this.ph().jk(t),t?this.j|=4:this.j&=-5},l.zh=function(){return(Rp(),En).S},l.i=0,l.j=1,O(Tn,"EObjectImpl",506),M(780,506,{105:1,92:1,90:1,56:1,108:1,49:1,97:1},wve),l.Ch=function(t){return this.e[t]},l.Dh=function(t,n){this.e[t]=n},l.Eh=function(t){this.e[t]=null},l.Tg=function(){return this.d},l.Yg=function(t){return Ji(this.d,t)},l.$g=function(){return this.d},l.dh=function(){return this.e!=null},l.ph=function(){return!this.k&&(this.k=new WB),this.k},l.th=function(t){this.d=t},l.yh=function(){var t;return this.e==null&&(t=Jn(this.d),this.e=t==0?g4t:Me(Yn,yt,1,t,5,1)),this},l.Ah=function(){return 0};var g4t;O(Tn,"DynamicEObjectImpl",780),M(1376,780,{105:1,42:1,92:1,90:1,133:1,56:1,108:1,49:1,97:1},nKe),l.Fb=function(t){return this===t},l.Hb=function(){return xv(this)},l.th=function(t){this.d=t,this.b=dI(t,"key"),this.c=dI(t,jC)},l.Sh=function(){var t;return this.a==-1&&(t=qre(this,this.b),this.a=t==null?0:Xi(t)),this.a},l.cd=function(){return qre(this,this.b)},l.dd=function(){return qre(this,this.c)},l.Th=function(t){this.a=t},l.Uh=function(t){wwe(this,this.b,t)},l.ed=function(t){var n;return n=qre(this,this.c),wwe(this,this.c,t),n},l.a=0,O(Tn,"DynamicEObjectImpl/BasicEMapEntry",1376),M(1377,1,{108:1},WB),l.bk=function(t){throw J(new Fr)},l.Ch=function(t){throw J(new Fr)},l.Dh=function(t,n){throw J(new Fr)},l.Eh=function(t){throw J(new Fr)},l.ck=function(){throw J(new Fr)},l.dk=function(){return this.a},l.ek=function(){return this.b},l.fk=function(){return this.c},l.gk=function(){throw J(new Fr)},l.hk=function(t){throw J(new Fr)},l.ik=function(t){this.a=t},l.jk=function(t){this.b=t},l.kk=function(t){this.c=t},O(Tn,"DynamicEObjectImpl/DynamicEPropertiesHolderImpl",1377),M(510,150,{105:1,92:1,90:1,590:1,147:1,56:1,108:1,49:1,97:1,510:1,150:1,114:1,115:1},KB),l.Qg=function(t){return R3e(this,t)},l._g=function(t,n,r){var s;switch(t){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),this.Ab;case 1:return this.d;case 2:return r?(!this.b&&(this.b=new Ml((on(),oo),wc,this)),this.b):(!this.b&&(this.b=new Ml((on(),oo),wc,this)),hD(this.b));case 3:return CXe(this);case 4:return!this.a&&(this.a=new Bs(y2,this,4)),this.a;case 5:return!this.c&&(this.c=new $3(y2,this,5)),this.c}return ph(this,t-Jn((on(),Kg)),gn((s=u(_n(this,16),26),s||Kg),t),n,r)},l.hh=function(t,n,r){var s,o,h;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),ou(this.Ab,t,r);case 3:return this.Cb&&(r=(o=this.Db>>16,o>=0?R3e(this,r):this.Cb.ih(this,-1-o,null,r))),Nve(this,u(t,147),r)}return h=u(gn((s=u(_n(this,16),26),s||(on(),Kg)),n),66),h.Nj().Qj(this,du(this),n-Jn((on(),Kg)),t,r)},l.jh=function(t,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),Xa(this.Ab,t,r);case 2:return!this.b&&(this.b=new Ml((on(),oo),wc,this)),vj(this.b,t,r);case 3:return Nve(this,null,r);case 4:return!this.a&&(this.a=new Bs(y2,this,4)),Xa(this.a,t,r)}return o=u(gn((s=u(_n(this,16),26),s||(on(),Kg)),n),66),o.Nj().Rj(this,du(this),n-Jn((on(),Kg)),t,r)},l.lh=function(t){var n;switch(t){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.d!=null;case 2:return!!this.b&&this.b.f!=0;case 3:return!!CXe(this);case 4:return!!this.a&&this.a.i!=0;case 5:return!!this.c&&this.c.i!=0}return dh(this,t-Jn((on(),Kg)),gn((n=u(_n(this,16),26),n||Kg),t))},l.sh=function(t,n){var r;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab),!this.Ab&&(this.Ab=new at(ti,this,0,3)),fs(this.Ab,u(n,14));return;case 1:NQt(this,Hr(n));return;case 2:!this.b&&(this.b=new Ml((on(),oo),wc,this)),sH(this.b,n);return;case 3:zot(this,u(n,147));return;case 4:!this.a&&(this.a=new Bs(y2,this,4)),_r(this.a),!this.a&&(this.a=new Bs(y2,this,4)),fs(this.a,u(n,14));return;case 5:!this.c&&(this.c=new $3(y2,this,5)),_r(this.c),!this.c&&(this.c=new $3(y2,this,5)),fs(this.c,u(n,14));return}yh(this,t-Jn((on(),Kg)),gn((r=u(_n(this,16),26),r||Kg),t),n)},l.zh=function(){return on(),Kg},l.Bh=function(t){var n;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab);return;case 1:Fme(this,null);return;case 2:!this.b&&(this.b=new Ml((on(),oo),wc,this)),this.b.c.$b();return;case 3:zot(this,null);return;case 4:!this.a&&(this.a=new Bs(y2,this,4)),_r(this.a);return;case 5:!this.c&&(this.c=new $3(y2,this,5)),_r(this.c);return}wh(this,t-Jn((on(),Kg)),gn((n=u(_n(this,16),26),n||Kg),t))},l.Ib=function(){return rrt(this)},l.d=null,O(Tn,"EAnnotationImpl",510),M(151,705,b8e,Nl),l.Xh=function(t,n){bWt(this,t,u(n,42))},l.lk=function(t,n){return lYt(this,u(t,42),n)},l.pi=function(t){return u(u(this.c,69).pi(t),133)},l.Zh=function(){return u(this.c,69).Zh()},l.$h=function(){return u(this.c,69).$h()},l._h=function(t){return u(this.c,69)._h(t)},l.mk=function(t,n){return vj(this,t,n)},l.Wj=function(t){return u(this.c,76).Wj(t)},l.rj=function(){},l.fj=function(){return u(this.c,76).fj()},l.tj=function(t,n,r){var s;return s=u(Gl(this.b).Nh().Jh(this.b),133),s.Th(t),s.Uh(n),s.ed(r),s},l.uj=function(){return new rpe(this)},l.Wb=function(t){sH(this,t)},l.Xj=function(){u(this.c,76).Xj()},O(Wi,"EcoreEMap",151),M(158,151,b8e,Ml),l.qj=function(){var t,n,r,s,o,h;if(this.d==null){for(h=Me(SAe,p8e,63,2*this.f+1,0,1),r=this.c.Kc();r.e!=r.i.gc();)n=u(r.nj(),133),s=n.Sh(),o=(s&Ei)%h.length,t=h[o],!t&&(t=h[o]=new rpe(this)),t.Fc(n);this.d=h}},O(Tn,"EAnnotationImpl/1",158),M(284,438,{105:1,92:1,90:1,147:1,191:1,56:1,108:1,472:1,49:1,97:1,150:1,284:1,114:1,115:1}),l._g=function(t,n,r){var s,o;switch(t){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),this.Ab;case 1:return this.zb;case 2:return Mn(),!!(this.Bb&256);case 3:return Mn(),!!(this.Bb&512);case 4:return ct(this.s);case 5:return ct(this.t);case 6:return Mn(),!!this.$j();case 7:return Mn(),o=this.s,o>=1;case 8:return n?$h(this):this.r;case 9:return this.q}return ph(this,t-Jn(this.zh()),gn((s=u(_n(this,16),26),s||this.zh()),t),n,r)},l.jh=function(t,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),Xa(this.Ab,t,r);case 9:return zne(this,r)}return o=u(gn((s=u(_n(this,16),26),s||this.zh()),n),66),o.Nj().Rj(this,du(this),n-Jn(this.zh()),t,r)},l.lh=function(t){var n,r;switch(t){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return(this.Bb&256)==0;case 3:return(this.Bb&512)==0;case 4:return this.s!=0;case 5:return this.t!=1;case 6:return this.$j();case 7:return r=this.s,r>=1;case 8:return!!this.r&&!this.q.e&&Mv(this.q).i==0;case 9:return!!this.q&&!(this.r&&!this.q.e&&Mv(this.q).i==0)}return dh(this,t-Jn(this.zh()),gn((n=u(_n(this,16),26),n||this.zh()),t))},l.sh=function(t,n){var r,s;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab),!this.Ab&&(this.Ab=new at(ti,this,0,3)),fs(this.Ab,u(n,14));return;case 1:this.Lh(Hr(n));return;case 2:Lg(this,It(Mt(n)));return;case 3:Mg(this,It(Mt(n)));return;case 4:Cg(this,u(n,19).a);return;case 5:this.ok(u(n,19).a);return;case 8:cb(this,u(n,138));return;case 9:s=$1(this,u(n,87),null),s&&s.Fi();return}yh(this,t-Jn(this.zh()),gn((r=u(_n(this,16),26),r||this.zh()),t),n)},l.zh=function(){return on(),f4t},l.Bh=function(t){var n,r;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab);return;case 1:this.Lh(null);return;case 2:Lg(this,!0);return;case 3:Mg(this,!0);return;case 4:Cg(this,0);return;case 5:this.ok(1);return;case 8:cb(this,null);return;case 9:r=$1(this,null,null),r&&r.Fi();return}wh(this,t-Jn(this.zh()),gn((n=u(_n(this,16),26),n||this.zh()),t))},l.Gh=function(){$h(this),this.Bb|=1},l.Yj=function(){return $h(this)},l.Zj=function(){return this.t},l.$j=function(){var t;return t=this.t,t>1||t==-1},l.hi=function(){return(this.Bb&512)!=0},l.nk=function(t,n){return Iye(this,t,n)},l.ok=function(t){Wm(this,t)},l.Ib=function(){return G4e(this)},l.s=0,l.t=1,O(Tn,"ETypedElementImpl",284),M(449,284,{105:1,92:1,90:1,147:1,191:1,56:1,170:1,66:1,108:1,472:1,49:1,97:1,150:1,449:1,284:1,114:1,115:1,677:1}),l.Qg=function(t){return jit(this,t)},l._g=function(t,n,r){var s,o;switch(t){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),this.Ab;case 1:return this.zb;case 2:return Mn(),!!(this.Bb&256);case 3:return Mn(),!!(this.Bb&512);case 4:return ct(this.s);case 5:return ct(this.t);case 6:return Mn(),!!this.$j();case 7:return Mn(),o=this.s,o>=1;case 8:return n?$h(this):this.r;case 9:return this.q;case 10:return Mn(),!!(this.Bb&Sf);case 11:return Mn(),!!(this.Bb&ky);case 12:return Mn(),!!(this.Bb&dy);case 13:return this.j;case 14:return b7(this);case 15:return Mn(),!!(this.Bb&Zu);case 16:return Mn(),!!(this.Bb&Ed);case 17:return Fm(this)}return ph(this,t-Jn(this.zh()),gn((s=u(_n(this,16),26),s||this.zh()),t),n,r)},l.hh=function(t,n,r){var s,o,h;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),ou(this.Ab,t,r);case 17:return this.Cb&&(r=(o=this.Db>>16,o>=0?jit(this,r):this.Cb.ih(this,-1-o,null,r))),Kl(this,t,17,r)}return h=u(gn((s=u(_n(this,16),26),s||this.zh()),n),66),h.Nj().Qj(this,du(this),n-Jn(this.zh()),t,r)},l.jh=function(t,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),Xa(this.Ab,t,r);case 9:return zne(this,r);case 17:return Kl(this,null,17,r)}return o=u(gn((s=u(_n(this,16),26),s||this.zh()),n),66),o.Nj().Rj(this,du(this),n-Jn(this.zh()),t,r)},l.lh=function(t){var n,r;switch(t){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return(this.Bb&256)==0;case 3:return(this.Bb&512)==0;case 4:return this.s!=0;case 5:return this.t!=1;case 6:return this.$j();case 7:return r=this.s,r>=1;case 8:return!!this.r&&!this.q.e&&Mv(this.q).i==0;case 9:return!!this.q&&!(this.r&&!this.q.e&&Mv(this.q).i==0);case 10:return(this.Bb&Sf)==0;case 11:return(this.Bb&ky)!=0;case 12:return(this.Bb&dy)!=0;case 13:return this.j!=null;case 14:return b7(this)!=null;case 15:return(this.Bb&Zu)!=0;case 16:return(this.Bb&Ed)!=0;case 17:return!!Fm(this)}return dh(this,t-Jn(this.zh()),gn((n=u(_n(this,16),26),n||this.zh()),t))},l.sh=function(t,n){var r,s;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab),!this.Ab&&(this.Ab=new at(ti,this,0,3)),fs(this.Ab,u(n,14));return;case 1:bre(this,Hr(n));return;case 2:Lg(this,It(Mt(n)));return;case 3:Mg(this,It(Mt(n)));return;case 4:Cg(this,u(n,19).a);return;case 5:this.ok(u(n,19).a);return;case 8:cb(this,u(n,138));return;case 9:s=$1(this,u(n,87),null),s&&s.Fi();return;case 10:J8(this,It(Mt(n)));return;case 11:n7(this,It(Mt(n)));return;case 12:e7(this,It(Mt(n)));return;case 13:N2e(this,Hr(n));return;case 15:t7(this,It(Mt(n)));return;case 16:r7(this,It(Mt(n)));return}yh(this,t-Jn(this.zh()),gn((r=u(_n(this,16),26),r||this.zh()),t),n)},l.zh=function(){return on(),h4t},l.Bh=function(t){var n,r;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab);return;case 1:we(this.Cb,88)&&iy(dl(u(this.Cb,88)),4),au(this,null);return;case 2:Lg(this,!0);return;case 3:Mg(this,!0);return;case 4:Cg(this,0);return;case 5:this.ok(1);return;case 8:cb(this,null);return;case 9:r=$1(this,null,null),r&&r.Fi();return;case 10:J8(this,!0);return;case 11:n7(this,!1);return;case 12:e7(this,!1);return;case 13:this.i=null,X$(this,null);return;case 15:t7(this,!1);return;case 16:r7(this,!1);return}wh(this,t-Jn(this.zh()),gn((n=u(_n(this,16),26),n||this.zh()),t))},l.Gh=function(){m8(Po((Yu(),Oa),this)),$h(this),this.Bb|=1},l.Gj=function(){return this.f},l.zj=function(){return b7(this)},l.Hj=function(){return Fm(this)},l.Lj=function(){return null},l.pk=function(){return this.k},l.aj=function(){return this.n},l.Mj=function(){return UH(this)},l.Nj=function(){var t,n,r,s,o,h,d,v,x;return this.p||(r=Fm(this),(r.i==null&&xd(r),r.i).length,s=this.Lj(),s&&Jn(Fm(s)),o=$h(this),d=o.Bj(),t=d?d.i&1?d==El?Us:d==Lr?Za:d==Xy?W7:d==pa?ma:d==S2?pw:d==a5?bw:d==el?mk:XC:d:null,n=b7(this),v=o.zj(),gon(this),this.Bb&Ed&&((h=q3e((Yu(),Oa),r))&&h!=this||(h=F6(Po(Oa,this))))?this.p=new Gqe(this,h):this.$j()?this.rk()?s?this.Bb&Zu?t?this.sk()?this.p=new K2(47,t,this,s):this.p=new K2(5,t,this,s):this.sk()?this.p=new Q2(46,this,s):this.p=new Q2(4,this,s):t?this.sk()?this.p=new K2(49,t,this,s):this.p=new K2(7,t,this,s):this.sk()?this.p=new Q2(48,this,s):this.p=new Q2(6,this,s):this.Bb&Zu?t?t==Cb?this.p=new yg(50,W3t,this):this.sk()?this.p=new yg(43,t,this):this.p=new yg(1,t,this):this.sk()?this.p=new xg(42,this):this.p=new xg(0,this):t?t==Cb?this.p=new yg(41,W3t,this):this.sk()?this.p=new yg(45,t,this):this.p=new yg(3,t,this):this.sk()?this.p=new xg(44,this):this.p=new xg(2,this):we(o,148)?t==eU?this.p=new xg(40,this):this.Bb&512?this.Bb&Zu?t?this.p=new yg(9,t,this):this.p=new xg(8,this):t?this.p=new yg(11,t,this):this.p=new xg(10,this):this.Bb&Zu?t?this.p=new yg(13,t,this):this.p=new xg(12,this):t?this.p=new yg(15,t,this):this.p=new xg(14,this):s?(x=s.t,x>1||x==-1?this.sk()?this.Bb&Zu?t?this.p=new K2(25,t,this,s):this.p=new Q2(24,this,s):t?this.p=new K2(27,t,this,s):this.p=new Q2(26,this,s):this.Bb&Zu?t?this.p=new K2(29,t,this,s):this.p=new Q2(28,this,s):t?this.p=new K2(31,t,this,s):this.p=new Q2(30,this,s):this.sk()?this.Bb&Zu?t?this.p=new K2(33,t,this,s):this.p=new Q2(32,this,s):t?this.p=new K2(35,t,this,s):this.p=new Q2(34,this,s):this.Bb&Zu?t?this.p=new K2(37,t,this,s):this.p=new Q2(36,this,s):t?this.p=new K2(39,t,this,s):this.p=new Q2(38,this,s)):this.sk()?this.Bb&Zu?t?this.p=new yg(17,t,this):this.p=new xg(16,this):t?this.p=new yg(19,t,this):this.p=new xg(18,this):this.Bb&Zu?t?this.p=new yg(21,t,this):this.p=new xg(20,this):t?this.p=new yg(23,t,this):this.p=new xg(22,this):this.qk()?this.sk()?this.p=new MWe(u(o,26),this,s):this.p=new vwe(u(o,26),this,s):we(o,148)?t==eU?this.p=new xg(40,this):this.Bb&Zu?t?this.p=new AKe(n,v,this,(Gie(),d==Lr?qAe:d==El?jAe:d==S2?VAe:d==Xy?GAe:d==pa?zAe:d==a5?UAe:d==el?$Ae:d==Sh?HAe:_fe)):this.p=new $Ye(u(o,148),n,v,this):t?this.p=new SKe(n,v,this,(Gie(),d==Lr?qAe:d==El?jAe:d==S2?VAe:d==Xy?GAe:d==pa?zAe:d==a5?UAe:d==el?$Ae:d==Sh?HAe:_fe)):this.p=new jYe(u(o,148),n,v,this):this.rk()?s?this.Bb&Zu?this.sk()?this.p=new IWe(u(o,26),this,s):this.p=new cve(u(o,26),this,s):this.sk()?this.p=new DWe(u(o,26),this,s):this.p=new wne(u(o,26),this,s):this.Bb&Zu?this.sk()?this.p=new SUe(u(o,26),this):this.p=new xbe(u(o,26),this):this.sk()?this.p=new CUe(u(o,26),this):this.p=new ine(u(o,26),this):this.sk()?s?this.Bb&Zu?this.p=new OWe(u(o,26),this,s):this.p=new ave(u(o,26),this,s):this.Bb&Zu?this.p=new AUe(u(o,26),this):this.p=new Ebe(u(o,26),this):s?this.Bb&Zu?this.p=new NWe(u(o,26),this,s):this.p=new ove(u(o,26),this,s):this.Bb&Zu?this.p=new LUe(u(o,26),this):this.p=new Mj(u(o,26),this)),this.p},l.Ij=function(){return(this.Bb&Sf)!=0},l.qk=function(){return!1},l.rk=function(){return!1},l.Jj=function(){return(this.Bb&Ed)!=0},l.Oj=function(){return Ure(this)},l.sk=function(){return!1},l.Kj=function(){return(this.Bb&Zu)!=0},l.tk=function(t){this.k=t},l.Lh=function(t){bre(this,t)},l.Ib=function(){return lz(this)},l.e=!1,l.n=0,O(Tn,"EStructuralFeatureImpl",449),M(322,449,{105:1,92:1,90:1,34:1,147:1,191:1,56:1,170:1,66:1,108:1,472:1,49:1,97:1,322:1,150:1,449:1,284:1,114:1,115:1,677:1},Vee),l._g=function(t,n,r){var s,o;switch(t){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),this.Ab;case 1:return this.zb;case 2:return Mn(),!!(this.Bb&256);case 3:return Mn(),!!(this.Bb&512);case 4:return ct(this.s);case 5:return ct(this.t);case 6:return Mn(),!!j4e(this);case 7:return Mn(),o=this.s,o>=1;case 8:return n?$h(this):this.r;case 9:return this.q;case 10:return Mn(),!!(this.Bb&Sf);case 11:return Mn(),!!(this.Bb&ky);case 12:return Mn(),!!(this.Bb&dy);case 13:return this.j;case 14:return b7(this);case 15:return Mn(),!!(this.Bb&Zu);case 16:return Mn(),!!(this.Bb&Ed);case 17:return Fm(this);case 18:return Mn(),!!(this.Bb&_c);case 19:return n?lie(this):$Ze(this)}return ph(this,t-Jn((on(),Wy)),gn((s=u(_n(this,16),26),s||Wy),t),n,r)},l.lh=function(t){var n,r;switch(t){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return(this.Bb&256)==0;case 3:return(this.Bb&512)==0;case 4:return this.s!=0;case 5:return this.t!=1;case 6:return j4e(this);case 7:return r=this.s,r>=1;case 8:return!!this.r&&!this.q.e&&Mv(this.q).i==0;case 9:return!!this.q&&!(this.r&&!this.q.e&&Mv(this.q).i==0);case 10:return(this.Bb&Sf)==0;case 11:return(this.Bb&ky)!=0;case 12:return(this.Bb&dy)!=0;case 13:return this.j!=null;case 14:return b7(this)!=null;case 15:return(this.Bb&Zu)!=0;case 16:return(this.Bb&Ed)!=0;case 17:return!!Fm(this);case 18:return(this.Bb&_c)!=0;case 19:return!!$Ze(this)}return dh(this,t-Jn((on(),Wy)),gn((n=u(_n(this,16),26),n||Wy),t))},l.sh=function(t,n){var r,s;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab),!this.Ab&&(this.Ab=new at(ti,this,0,3)),fs(this.Ab,u(n,14));return;case 1:bre(this,Hr(n));return;case 2:Lg(this,It(Mt(n)));return;case 3:Mg(this,It(Mt(n)));return;case 4:Cg(this,u(n,19).a);return;case 5:wze(this,u(n,19).a);return;case 8:cb(this,u(n,138));return;case 9:s=$1(this,u(n,87),null),s&&s.Fi();return;case 10:J8(this,It(Mt(n)));return;case 11:n7(this,It(Mt(n)));return;case 12:e7(this,It(Mt(n)));return;case 13:N2e(this,Hr(n));return;case 15:t7(this,It(Mt(n)));return;case 16:r7(this,It(Mt(n)));return;case 18:Pie(this,It(Mt(n)));return}yh(this,t-Jn((on(),Wy)),gn((r=u(_n(this,16),26),r||Wy),t),n)},l.zh=function(){return on(),Wy},l.Bh=function(t){var n,r;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab);return;case 1:we(this.Cb,88)&&iy(dl(u(this.Cb,88)),4),au(this,null);return;case 2:Lg(this,!0);return;case 3:Mg(this,!0);return;case 4:Cg(this,0);return;case 5:this.b=0,Wm(this,1);return;case 8:cb(this,null);return;case 9:r=$1(this,null,null),r&&r.Fi();return;case 10:J8(this,!0);return;case 11:n7(this,!1);return;case 12:e7(this,!1);return;case 13:this.i=null,X$(this,null);return;case 15:t7(this,!1);return;case 16:r7(this,!1);return;case 18:Pie(this,!1);return}wh(this,t-Jn((on(),Wy)),gn((n=u(_n(this,16),26),n||Wy),t))},l.Gh=function(){lie(this),m8(Po((Yu(),Oa),this)),$h(this),this.Bb|=1},l.$j=function(){return j4e(this)},l.nk=function(t,n){return this.b=0,this.a=null,Iye(this,t,n)},l.ok=function(t){wze(this,t)},l.Ib=function(){var t;return this.Db&64?lz(this):(t=new Ph(lz(this)),t.a+=" (iD: ",vg(t,(this.Bb&_c)!=0),t.a+=")",t.a)},l.b=0,O(Tn,"EAttributeImpl",322),M(351,438,{105:1,92:1,90:1,138:1,147:1,191:1,56:1,108:1,49:1,97:1,351:1,150:1,114:1,115:1,676:1}),l.uk=function(t){return t.Tg()==this},l.Qg=function(t){return pse(this,t)},l.Rg=function(t,n){this.w=null,this.Db=n<<16|this.Db&255,this.Cb=t},l._g=function(t,n,r){var s;switch(t){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),this.Ab;case 1:return this.zb;case 2:return this.D!=null?this.D:this.B;case 3:return Jv(this);case 4:return this.zj();case 5:return this.F;case 6:return n?Gl(this):x8(this);case 7:return!this.A&&(this.A=new qu(mu,this,7)),this.A}return ph(this,t-Jn(this.zh()),gn((s=u(_n(this,16),26),s||this.zh()),t),n,r)},l.hh=function(t,n,r){var s,o,h;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),ou(this.Ab,t,r);case 6:return this.Cb&&(r=(o=this.Db>>16,o>=0?pse(this,r):this.Cb.ih(this,-1-o,null,r))),Kl(this,t,6,r)}return h=u(gn((s=u(_n(this,16),26),s||this.zh()),n),66),h.Nj().Qj(this,du(this),n-Jn(this.zh()),t,r)},l.jh=function(t,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),Xa(this.Ab,t,r);case 6:return Kl(this,null,6,r);case 7:return!this.A&&(this.A=new qu(mu,this,7)),Xa(this.A,t,r)}return o=u(gn((s=u(_n(this,16),26),s||this.zh()),n),66),o.Nj().Rj(this,du(this),n-Jn(this.zh()),t,r)},l.lh=function(t){var n;switch(t){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return this.D!=null&&this.D==this.F;case 3:return!!Jv(this);case 4:return this.zj()!=null;case 5:return this.F!=null&&this.F!=this.D&&this.F!=this.B;case 6:return!!x8(this);case 7:return!!this.A&&this.A.i!=0}return dh(this,t-Jn(this.zh()),gn((n=u(_n(this,16),26),n||this.zh()),t))},l.sh=function(t,n){var r;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab),!this.Ab&&(this.Ab=new at(ti,this,0,3)),fs(this.Ab,u(n,14));return;case 1:l$(this,Hr(n));return;case 2:Vte(this,Hr(n));return;case 5:x7(this,Hr(n));return;case 7:!this.A&&(this.A=new qu(mu,this,7)),_r(this.A),!this.A&&(this.A=new qu(mu,this,7)),fs(this.A,u(n,14));return}yh(this,t-Jn(this.zh()),gn((r=u(_n(this,16),26),r||this.zh()),t),n)},l.zh=function(){return on(),s4t},l.Bh=function(t){var n;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab);return;case 1:we(this.Cb,179)&&(u(this.Cb,179).tb=null),au(this,null);return;case 2:Y8(this,null),R8(this,this.D);return;case 5:x7(this,null);return;case 7:!this.A&&(this.A=new qu(mu,this,7)),_r(this.A);return}wh(this,t-Jn(this.zh()),gn((n=u(_n(this,16),26),n||this.zh()),t))},l.yj=function(){var t;return this.G==-1&&(this.G=(t=Gl(this),t?Dg(t.Mh(),this):-1)),this.G},l.zj=function(){return null},l.Aj=function(){return Gl(this)},l.vk=function(){return this.v},l.Bj=function(){return Jv(this)},l.Cj=function(){return this.D!=null?this.D:this.B},l.Dj=function(){return this.F},l.wj=function(t){return oae(this,t)},l.wk=function(t){this.v=t},l.xk=function(t){wtt(this,t)},l.yk=function(t){this.C=t},l.Lh=function(t){l$(this,t)},l.Ib=function(){return xH(this)},l.C=null,l.D=null,l.G=-1,O(Tn,"EClassifierImpl",351),M(88,351,{105:1,92:1,90:1,26:1,138:1,147:1,191:1,56:1,108:1,49:1,97:1,88:1,351:1,150:1,473:1,114:1,115:1,676:1},YL),l.uk=function(t){return XKt(this,t.Tg())},l._g=function(t,n,r){var s;switch(t){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),this.Ab;case 1:return this.zb;case 2:return this.D!=null?this.D:this.B;case 3:return Jv(this);case 4:return null;case 5:return this.F;case 6:return n?Gl(this):x8(this);case 7:return!this.A&&(this.A=new qu(mu,this,7)),this.A;case 8:return Mn(),!!(this.Bb&256);case 9:return Mn(),!!(this.Bb&512);case 10:return jo(this);case 11:return!this.q&&(this.q=new at(nf,this,11,10)),this.q;case 12:return b4(this);case 13:return fC(this);case 14:return fC(this),this.r;case 15:return b4(this),this.k;case 16:return L4e(this);case 17:return fae(this);case 18:return xd(this);case 19:return rz(this);case 20:return b4(this),this.o;case 21:return!this.s&&(this.s=new at(ju,this,21,17)),this.s;case 22:return jc(this);case 23:return Qse(this)}return ph(this,t-Jn((on(),E2)),gn((s=u(_n(this,16),26),s||E2),t),n,r)},l.hh=function(t,n,r){var s,o,h;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),ou(this.Ab,t,r);case 6:return this.Cb&&(r=(o=this.Db>>16,o>=0?pse(this,r):this.Cb.ih(this,-1-o,null,r))),Kl(this,t,6,r);case 11:return!this.q&&(this.q=new at(nf,this,11,10)),ou(this.q,t,r);case 21:return!this.s&&(this.s=new at(ju,this,21,17)),ou(this.s,t,r)}return h=u(gn((s=u(_n(this,16),26),s||(on(),E2)),n),66),h.Nj().Qj(this,du(this),n-Jn((on(),E2)),t,r)},l.jh=function(t,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),Xa(this.Ab,t,r);case 6:return Kl(this,null,6,r);case 7:return!this.A&&(this.A=new qu(mu,this,7)),Xa(this.A,t,r);case 11:return!this.q&&(this.q=new at(nf,this,11,10)),Xa(this.q,t,r);case 21:return!this.s&&(this.s=new at(ju,this,21,17)),Xa(this.s,t,r);case 22:return Xa(jc(this),t,r)}return o=u(gn((s=u(_n(this,16),26),s||(on(),E2)),n),66),o.Nj().Rj(this,du(this),n-Jn((on(),E2)),t,r)},l.lh=function(t){var n;switch(t){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return this.D!=null&&this.D==this.F;case 3:return!!Jv(this);case 4:return!1;case 5:return this.F!=null&&this.F!=this.D&&this.F!=this.B;case 6:return!!x8(this);case 7:return!!this.A&&this.A.i!=0;case 8:return(this.Bb&256)!=0;case 9:return(this.Bb&512)!=0;case 10:return!!this.u&&jc(this.u.a).i!=0&&!(this.n&&ise(this.n));case 11:return!!this.q&&this.q.i!=0;case 12:return b4(this).i!=0;case 13:return fC(this).i!=0;case 14:return fC(this),this.r.i!=0;case 15:return b4(this),this.k.i!=0;case 16:return L4e(this).i!=0;case 17:return fae(this).i!=0;case 18:return xd(this).i!=0;case 19:return rz(this).i!=0;case 20:return b4(this),!!this.o;case 21:return!!this.s&&this.s.i!=0;case 22:return!!this.n&&ise(this.n);case 23:return Qse(this).i!=0}return dh(this,t-Jn((on(),E2)),gn((n=u(_n(this,16),26),n||E2),t))},l.oh=function(t){var n;return n=this.i==null||this.q&&this.q.i!=0?null:dI(this,t),n||a6e(this,t)},l.sh=function(t,n){var r;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab),!this.Ab&&(this.Ab=new at(ti,this,0,3)),fs(this.Ab,u(n,14));return;case 1:l$(this,Hr(n));return;case 2:Vte(this,Hr(n));return;case 5:x7(this,Hr(n));return;case 7:!this.A&&(this.A=new qu(mu,this,7)),_r(this.A),!this.A&&(this.A=new qu(mu,this,7)),fs(this.A,u(n,14));return;case 8:Nye(this,It(Mt(n)));return;case 9:Pye(this,It(Mt(n)));return;case 10:pC(jo(this)),fs(jo(this),u(n,14));return;case 11:!this.q&&(this.q=new at(nf,this,11,10)),_r(this.q),!this.q&&(this.q=new at(nf,this,11,10)),fs(this.q,u(n,14));return;case 21:!this.s&&(this.s=new at(ju,this,21,17)),_r(this.s),!this.s&&(this.s=new at(ju,this,21,17)),fs(this.s,u(n,14));return;case 22:_r(jc(this)),fs(jc(this),u(n,14));return}yh(this,t-Jn((on(),E2)),gn((r=u(_n(this,16),26),r||E2),t),n)},l.zh=function(){return on(),E2},l.Bh=function(t){var n;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab);return;case 1:we(this.Cb,179)&&(u(this.Cb,179).tb=null),au(this,null);return;case 2:Y8(this,null),R8(this,this.D);return;case 5:x7(this,null);return;case 7:!this.A&&(this.A=new qu(mu,this,7)),_r(this.A);return;case 8:Nye(this,!1);return;case 9:Pye(this,!1);return;case 10:this.u&&pC(this.u);return;case 11:!this.q&&(this.q=new at(nf,this,11,10)),_r(this.q);return;case 21:!this.s&&(this.s=new at(ju,this,21,17)),_r(this.s);return;case 22:this.n&&_r(this.n);return}wh(this,t-Jn((on(),E2)),gn((n=u(_n(this,16),26),n||E2),t))},l.Gh=function(){var t,n;if(b4(this),fC(this),L4e(this),fae(this),xd(this),rz(this),Qse(this),A_(dQt(dl(this))),this.s)for(t=0,n=this.s.i;t=0;--n)Te(this,n);return r3e(this,t)},l.Xj=function(){_r(this)},l.oi=function(t,n){return Het(this,t,n)},O(Wi,"EcoreEList",622),M(496,622,Zo,UM),l.ai=function(){return!1},l.aj=function(){return this.c},l.bj=function(){return!1},l.Fk=function(){return!0},l.hi=function(){return!0},l.li=function(t,n){return n},l.ni=function(){return!1},l.c=0,O(Wi,"EObjectEList",496),M(85,496,Zo,Bs),l.bj=function(){return!0},l.Dk=function(){return!1},l.rk=function(){return!0},O(Wi,"EObjectContainmentEList",85),M(545,85,Zo,aj),l.ci=function(){this.b=!0},l.fj=function(){return this.b},l.Xj=function(){var t;_r(this),Ll(this.e)?(t=this.b,this.b=!1,_i(this.e,new xf(this.e,2,this.c,t,!1))):this.b=!1},l.b=!1,O(Wi,"EObjectContainmentEList/Unsettable",545),M(1140,545,Zo,_Ke),l.ii=function(t,n){var r,s;return r=u(q_(this,t,n),87),Ll(this.e)&&Vx(this,new dD(this.a,7,(on(),a4t),ct(n),(s=r.c,we(s,88)?u(s,26):sf),t)),r},l.jj=function(t,n){return tcn(this,u(t,87),n)},l.kj=function(t,n){return ecn(this,u(t,87),n)},l.lj=function(t,n,r){return nhn(this,u(t,87),u(n,87),r)},l.Zi=function(t,n,r,s,o){switch(t){case 3:return x_(this,t,n,r,s,this.i>1);case 5:return x_(this,t,n,r,s,this.i-u(r,15).gc()>0);default:return new N0(this.e,t,this.c,n,r,s,!0)}},l.ij=function(){return!0},l.fj=function(){return ise(this)},l.Xj=function(){_r(this)},O(Tn,"EClassImpl/1",1140),M(1154,1153,g8e),l.ui=function(t){var n,r,s,o,h,d,v;if(r=t.xi(),r!=8){if(s=Fcn(t),s==0)switch(r){case 1:case 9:{v=t.Bi(),v!=null&&(n=dl(u(v,473)),!n.c&&(n.c=new gm),N$(n.c,t.Ai())),d=t.zi(),d!=null&&(o=u(d,473),o.Bb&1||(n=dl(o),!n.c&&(n.c=new gm),Br(n.c,u(t.Ai(),26))));break}case 3:{d=t.zi(),d!=null&&(o=u(d,473),o.Bb&1||(n=dl(o),!n.c&&(n.c=new gm),Br(n.c,u(t.Ai(),26))));break}case 5:{if(d=t.zi(),d!=null)for(h=u(d,14).Kc();h.Ob();)o=u(h.Pb(),473),o.Bb&1||(n=dl(o),!n.c&&(n.c=new gm),Br(n.c,u(t.Ai(),26)));break}case 4:{v=t.Bi(),v!=null&&(o=u(v,473),o.Bb&1||(n=dl(o),!n.c&&(n.c=new gm),N$(n.c,t.Ai())));break}case 6:{if(v=t.Bi(),v!=null)for(h=u(v,14).Kc();h.Ob();)o=u(h.Pb(),473),o.Bb&1||(n=dl(o),!n.c&&(n.c=new gm),N$(n.c,t.Ai()));break}}this.Hk(s)}},l.Hk=function(t){Cct(this,t)},l.b=63,O(Tn,"ESuperAdapter",1154),M(1155,1154,g8e,R$e),l.Hk=function(t){iy(this,t)},O(Tn,"EClassImpl/10",1155),M(1144,696,Zo),l.Vh=function(t,n){return Cse(this,t,n)},l.Wh=function(t){return xit(this,t)},l.Xh=function(t,n){$D(this,t,n)},l.Yh=function(t){cD(this,t)},l.pi=function(t){return fme(this,t)},l.mi=function(t,n){return Vre(this,t,n)},l.lk=function(t,n){throw J(new Fr)},l.Zh=function(){return new C6(this)},l.$h=function(){return new NM(this)},l._h=function(t){return _D(this,t)},l.mk=function(t,n){throw J(new Fr)},l.Wj=function(t){return this},l.fj=function(){return this.i!=0},l.Wb=function(t){throw J(new Fr)},l.Xj=function(){throw J(new Fr)},O(Wi,"EcoreEList/UnmodifiableEList",1144),M(319,1144,Zo,B3),l.ni=function(){return!1},O(Wi,"EcoreEList/UnmodifiableEList/FastCompare",319),M(1147,319,Zo,lnt),l.Xc=function(t){var n,r,s;if(we(t,170)&&(n=u(t,170),r=n.aj(),r!=-1)){for(s=this.i;r4)if(this.wj(t)){if(this.rk()){if(s=u(t,49),r=s.Ug(),v=r==this.b&&(this.Dk()?s.Og(s.Vg(),u(gn(Su(this.b),this.aj()).Yj(),26).Bj())==go(u(gn(Su(this.b),this.aj()),18)).n:-1-s.Vg()==this.aj()),this.Ek()&&!v&&!r&&s.Zg()){for(o=0;o1||s==-1)):!1},l.Dk=function(){var t,n,r;return n=gn(Su(this.b),this.aj()),we(n,99)?(t=u(n,18),r=go(t),!!r):!1},l.Ek=function(){var t,n;return n=gn(Su(this.b),this.aj()),we(n,99)?(t=u(n,18),(t.Bb&so)!=0):!1},l.Xc=function(t){var n,r,s,o;if(s=this.Qi(t),s>=0)return s;if(this.Fk()){for(r=0,o=this.Vi();r=0;--t)xI(this,t,this.Oi(t));return this.Wi()},l.Qc=function(t){var n;if(this.Ek())for(n=this.Vi()-1;n>=0;--n)xI(this,n,this.Oi(n));return this.Xi(t)},l.Xj=function(){pC(this)},l.oi=function(t,n){return EJe(this,t,n)},O(Wi,"DelegatingEcoreEList",742),M(1150,742,w8e,$Ue),l.Hi=function(t,n){TKt(this,t,u(n,26))},l.Ii=function(t){wWt(this,u(t,26))},l.Oi=function(t){var n,r;return n=u(Te(jc(this.a),t),87),r=n.c,we(r,88)?u(r,26):(on(),sf)},l.Ti=function(t){var n,r;return n=u(ay(jc(this.a),t),87),r=n.c,we(r,88)?u(r,26):(on(),sf)},l.Ui=function(t,n){return _un(this,t,u(n,26))},l.ai=function(){return!1},l.Zi=function(t,n,r,s,o){return null},l.Ji=function(){return new j$e(this)},l.Ki=function(){_r(jc(this.a))},l.Li=function(t){return trt(this,t)},l.Mi=function(t){var n,r;for(r=t.Kc();r.Ob();)if(n=r.Pb(),!trt(this,n))return!1;return!0},l.Ni=function(t){var n,r,s;if(we(t,15)&&(s=u(t,15),s.gc()==jc(this.a).i)){for(n=s.Kc(),r=new rr(this);n.Ob();)if(je(n.Pb())!==je(pr(r)))return!1;return!0}return!1},l.Pi=function(){var t,n,r,s,o;for(r=1,n=new rr(jc(this.a));n.e!=n.i.gc();)t=u(pr(n),87),s=(o=t.c,we(o,88)?u(o,26):(on(),sf)),r=31*r+(s?xv(s):0);return r},l.Qi=function(t){var n,r,s,o;for(s=0,r=new rr(jc(this.a));r.e!=r.i.gc();){if(n=u(pr(r),87),je(t)===je((o=n.c,we(o,88)?u(o,26):(on(),sf))))return s;++s}return-1},l.Ri=function(){return jc(this.a).i==0},l.Si=function(){return null},l.Vi=function(){return jc(this.a).i},l.Wi=function(){var t,n,r,s,o,h;for(h=jc(this.a).i,o=Me(Yn,yt,1,h,5,1),r=0,n=new rr(jc(this.a));n.e!=n.i.gc();)t=u(pr(n),87),o[r++]=(s=t.c,we(s,88)?u(s,26):(on(),sf));return o},l.Xi=function(t){var n,r,s,o,h,d,v;for(v=jc(this.a).i,t.lengthv&&cs(t,v,null),s=0,r=new rr(jc(this.a));r.e!=r.i.gc();)n=u(pr(r),87),h=(d=n.c,we(d,88)?u(d,26):(on(),sf)),cs(t,s++,h);return t},l.Yi=function(){var t,n,r,s,o;for(o=new bg,o.a+="[",t=jc(this.a),n=0,s=jc(this.a).i;n>16,o>=0?pse(this,r):this.Cb.ih(this,-1-o,null,r))),Kl(this,t,6,r);case 9:return!this.a&&(this.a=new at(J0,this,9,5)),ou(this.a,t,r)}return h=u(gn((s=u(_n(this,16),26),s||(on(),T2)),n),66),h.Nj().Qj(this,du(this),n-Jn((on(),T2)),t,r)},l.jh=function(t,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),Xa(this.Ab,t,r);case 6:return Kl(this,null,6,r);case 7:return!this.A&&(this.A=new qu(mu,this,7)),Xa(this.A,t,r);case 9:return!this.a&&(this.a=new at(J0,this,9,5)),Xa(this.a,t,r)}return o=u(gn((s=u(_n(this,16),26),s||(on(),T2)),n),66),o.Nj().Rj(this,du(this),n-Jn((on(),T2)),t,r)},l.lh=function(t){var n;switch(t){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return this.D!=null&&this.D==this.F;case 3:return!!Jv(this);case 4:return!!yye(this);case 5:return this.F!=null&&this.F!=this.D&&this.F!=this.B;case 6:return!!x8(this);case 7:return!!this.A&&this.A.i!=0;case 8:return(this.Bb&256)==0;case 9:return!!this.a&&this.a.i!=0}return dh(this,t-Jn((on(),T2)),gn((n=u(_n(this,16),26),n||T2),t))},l.sh=function(t,n){var r;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab),!this.Ab&&(this.Ab=new at(ti,this,0,3)),fs(this.Ab,u(n,14));return;case 1:l$(this,Hr(n));return;case 2:Vte(this,Hr(n));return;case 5:x7(this,Hr(n));return;case 7:!this.A&&(this.A=new qu(mu,this,7)),_r(this.A),!this.A&&(this.A=new qu(mu,this,7)),fs(this.A,u(n,14));return;case 8:bH(this,It(Mt(n)));return;case 9:!this.a&&(this.a=new at(J0,this,9,5)),_r(this.a),!this.a&&(this.a=new at(J0,this,9,5)),fs(this.a,u(n,14));return}yh(this,t-Jn((on(),T2)),gn((r=u(_n(this,16),26),r||T2),t),n)},l.zh=function(){return on(),T2},l.Bh=function(t){var n;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab);return;case 1:we(this.Cb,179)&&(u(this.Cb,179).tb=null),au(this,null);return;case 2:Y8(this,null),R8(this,this.D);return;case 5:x7(this,null);return;case 7:!this.A&&(this.A=new qu(mu,this,7)),_r(this.A);return;case 8:bH(this,!0);return;case 9:!this.a&&(this.a=new at(J0,this,9,5)),_r(this.a);return}wh(this,t-Jn((on(),T2)),gn((n=u(_n(this,16),26),n||T2),t))},l.Gh=function(){var t,n;if(this.a)for(t=0,n=this.a.i;t>16==5?u(this.Cb,671):null}return ph(this,t-Jn((on(),Yg)),gn((s=u(_n(this,16),26),s||Yg),t),n,r)},l.hh=function(t,n,r){var s,o,h;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),ou(this.Ab,t,r);case 5:return this.Cb&&(r=(o=this.Db>>16,o>=0?Wit(this,r):this.Cb.ih(this,-1-o,null,r))),Kl(this,t,5,r)}return h=u(gn((s=u(_n(this,16),26),s||(on(),Yg)),n),66),h.Nj().Qj(this,du(this),n-Jn((on(),Yg)),t,r)},l.jh=function(t,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),Xa(this.Ab,t,r);case 5:return Kl(this,null,5,r)}return o=u(gn((s=u(_n(this,16),26),s||(on(),Yg)),n),66),o.Nj().Rj(this,du(this),n-Jn((on(),Yg)),t,r)},l.lh=function(t){var n;switch(t){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return this.d!=0;case 3:return!!this.b;case 4:return this.c!=null;case 5:return!!(this.Db>>16==5&&u(this.Cb,671))}return dh(this,t-Jn((on(),Yg)),gn((n=u(_n(this,16),26),n||Yg),t))},l.sh=function(t,n){var r;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab),!this.Ab&&(this.Ab=new at(ti,this,0,3)),fs(this.Ab,u(n,14));return;case 1:au(this,Hr(n));return;case 2:Qre(this,u(n,19).a);return;case 3:zat(this,u(n,1940));return;case 4:Jre(this,Hr(n));return}yh(this,t-Jn((on(),Yg)),gn((r=u(_n(this,16),26),r||Yg),t),n)},l.zh=function(){return on(),Yg},l.Bh=function(t){var n;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab);return;case 1:au(this,null);return;case 2:Qre(this,0);return;case 3:zat(this,null);return;case 4:Jre(this,null);return}wh(this,t-Jn((on(),Yg)),gn((n=u(_n(this,16),26),n||Yg),t))},l.Ib=function(){var t;return t=this.c,t??this.zb},l.b=null,l.c=null,l.d=0,O(Tn,"EEnumLiteralImpl",573);var M3n=ss(Tn,"EFactoryImpl/InternalEDateTimeFormat");M(489,1,{2015:1},aM),O(Tn,"EFactoryImpl/1ClientInternalEDateTimeFormat",489),M(241,115,{105:1,92:1,90:1,87:1,56:1,108:1,49:1,97:1,241:1,114:1,115:1},uv),l.Sg=function(t,n,r){var s;return r=Kl(this,t,n,r),this.e&&we(t,170)&&(s=nz(this,this.e),s!=this.c&&(r=E7(this,s,r))),r},l._g=function(t,n,r){var s;switch(t){case 0:return this.f;case 1:return!this.d&&(this.d=new Bs(Eo,this,1)),this.d;case 2:return n?dz(this):this.c;case 3:return this.b;case 4:return this.e;case 5:return n?ose(this):this.a}return ph(this,t-Jn((on(),Ow)),gn((s=u(_n(this,16),26),s||Ow),t),n,r)},l.jh=function(t,n,r){var s,o;switch(n){case 0:return Vnt(this,null,r);case 1:return!this.d&&(this.d=new Bs(Eo,this,1)),Xa(this.d,t,r);case 3:return qnt(this,null,r)}return o=u(gn((s=u(_n(this,16),26),s||(on(),Ow)),n),66),o.Nj().Rj(this,du(this),n-Jn((on(),Ow)),t,r)},l.lh=function(t){var n;switch(t){case 0:return!!this.f;case 1:return!!this.d&&this.d.i!=0;case 2:return!!this.c;case 3:return!!this.b;case 4:return!!this.e;case 5:return!!this.a}return dh(this,t-Jn((on(),Ow)),gn((n=u(_n(this,16),26),n||Ow),t))},l.sh=function(t,n){var r;switch(t){case 0:hst(this,u(n,87));return;case 1:!this.d&&(this.d=new Bs(Eo,this,1)),_r(this.d),!this.d&&(this.d=new Bs(Eo,this,1)),fs(this.d,u(n,14));return;case 3:J3e(this,u(n,87));return;case 4:b4e(this,u(n,836));return;case 5:I8(this,u(n,138));return}yh(this,t-Jn((on(),Ow)),gn((r=u(_n(this,16),26),r||Ow),t),n)},l.zh=function(){return on(),Ow},l.Bh=function(t){var n;switch(t){case 0:hst(this,null);return;case 1:!this.d&&(this.d=new Bs(Eo,this,1)),_r(this.d);return;case 3:J3e(this,null);return;case 4:b4e(this,null);return;case 5:I8(this,null);return}wh(this,t-Jn((on(),Ow)),gn((n=u(_n(this,16),26),n||Ow),t))},l.Ib=function(){var t;return t=new Fl(_f(this)),t.a+=" (expression: ",bae(this,t),t.a+=")",t.a};var FAe;O(Tn,"EGenericTypeImpl",241),M(1969,1964,yG),l.Xh=function(t,n){RUe(this,t,n)},l.lk=function(t,n){return RUe(this,this.gc(),t),n},l.pi=function(t){return s1(this.Gi(),t)},l.Zh=function(){return this.$h()},l.Gi=function(){return new G$e(this)},l.$h=function(){return this._h(0)},l._h=function(t){return this.Gi().Zc(t)},l.mk=function(t,n){return Xm(this,t,!0),n},l.ii=function(t,n){var r,s;return s=vse(this,n),r=this.Zc(t),r.Rb(s),s},l.ji=function(t,n){var r;Xm(this,n,!0),r=this.Zc(t),r.Rb(n)},O(Wi,"AbstractSequentialInternalEList",1969),M(486,1969,yG,OM),l.pi=function(t){return s1(this.Gi(),t)},l.Zh=function(){return this.b==null?(wg(),wg(),lN):this.Jk()},l.Gi=function(){return new cVe(this.a,this.b)},l.$h=function(){return this.b==null?(wg(),wg(),lN):this.Jk()},l._h=function(t){var n,r;if(this.b==null){if(t<0||t>1)throw J(new Do($C+t+", size=0"));return wg(),wg(),lN}for(r=this.Jk(),n=0;n0;)if(n=this.c[--this.d],(!this.e||n.Gj()!=AE||n.aj()!=0)&&(!this.Mk()||this.b.mh(n))){if(h=this.b.bh(n,this.Lk()),this.f=(ho(),u(n,66).Oj()),this.f||n.$j()){if(this.Lk()?(s=u(h,15),this.k=s):(s=u(h,69),this.k=this.j=s),we(this.k,54)?(this.o=this.k.gc(),this.n=this.o):this.p=this.j?this.j._h(this.k.gc()):this.k.Zc(this.k.gc()),this.p?rat(this,this.p):pat(this))return o=this.p?this.p.Ub():this.j?this.j.pi(--this.n):this.k.Xb(--this.n),this.f?(t=u(o,72),t.ak(),r=t.dd(),this.i=r):(r=o,this.i=r),this.g=-3,!0}else if(h!=null)return this.k=null,this.p=null,r=h,this.i=r,this.g=-2,!0}return this.k=null,this.p=null,this.g=-1,!1}else return o=this.p?this.p.Ub():this.j?this.j.pi(--this.n):this.k.Xb(--this.n),this.f?(t=u(o,72),t.ak(),r=t.dd(),this.i=r):(r=o,this.i=r),this.g=-3,!0}},l.Pb=function(){return aH(this)},l.Tb=function(){return this.a},l.Ub=function(){var t;if(this.g<-1||this.Sb())return--this.a,this.g=0,t=this.i,this.Sb(),t;throw J(new xc)},l.Vb=function(){return this.a-1},l.Qb=function(){throw J(new Fr)},l.Lk=function(){return!1},l.Wb=function(t){throw J(new Fr)},l.Mk=function(){return!0},l.a=0,l.d=0,l.f=!1,l.g=0,l.n=0,l.o=0;var lN;O(Wi,"EContentsEList/FeatureIteratorImpl",279),M(697,279,kG,kbe),l.Lk=function(){return!0},O(Wi,"EContentsEList/ResolvingFeatureIteratorImpl",697),M(1157,697,kG,_Ue),l.Mk=function(){return!1},O(Tn,"ENamedElementImpl/1/1",1157),M(1158,279,kG,TUe),l.Mk=function(){return!1},O(Tn,"ENamedElementImpl/1/2",1158),M(36,143,XI,Hm,Tre,oa,jre,N0,xf,_me,JXe,Cme,eQe,Xwe,tQe,Lme,nQe,Qwe,rQe,Sme,iQe,p_,dD,nre,Ame,sQe,Zwe,aQe),l._i=function(){return ume(this)},l.gj=function(){var t;return t=ume(this),t?t.zj():null},l.yi=function(t){return this.b==-1&&this.a&&(this.b=this.c.Xg(this.a.aj(),this.a.Gj())),this.c.Og(this.b,t)},l.Ai=function(){return this.c},l.hj=function(){var t;return t=ume(this),t?t.Kj():!1},l.b=-1,O(Tn,"ENotificationImpl",36),M(399,284,{105:1,92:1,90:1,147:1,191:1,56:1,59:1,108:1,472:1,49:1,97:1,150:1,399:1,284:1,114:1,115:1},Uee),l.Qg=function(t){return Xit(this,t)},l._g=function(t,n,r){var s,o,h;switch(t){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),this.Ab;case 1:return this.zb;case 2:return Mn(),!!(this.Bb&256);case 3:return Mn(),!!(this.Bb&512);case 4:return ct(this.s);case 5:return ct(this.t);case 6:return Mn(),h=this.t,h>1||h==-1;case 7:return Mn(),o=this.s,o>=1;case 8:return n?$h(this):this.r;case 9:return this.q;case 10:return this.Db>>16==10?u(this.Cb,26):null;case 11:return!this.d&&(this.d=new qu(mu,this,11)),this.d;case 12:return!this.c&&(this.c=new at(Iw,this,12,10)),this.c;case 13:return!this.a&&(this.a=new jM(this,this)),this.a;case 14:return gl(this)}return ph(this,t-Jn((on(),Xg)),gn((s=u(_n(this,16),26),s||Xg),t),n,r)},l.hh=function(t,n,r){var s,o,h;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),ou(this.Ab,t,r);case 10:return this.Cb&&(r=(o=this.Db>>16,o>=0?Xit(this,r):this.Cb.ih(this,-1-o,null,r))),Kl(this,t,10,r);case 12:return!this.c&&(this.c=new at(Iw,this,12,10)),ou(this.c,t,r)}return h=u(gn((s=u(_n(this,16),26),s||(on(),Xg)),n),66),h.Nj().Qj(this,du(this),n-Jn((on(),Xg)),t,r)},l.jh=function(t,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),Xa(this.Ab,t,r);case 9:return zne(this,r);case 10:return Kl(this,null,10,r);case 11:return!this.d&&(this.d=new qu(mu,this,11)),Xa(this.d,t,r);case 12:return!this.c&&(this.c=new at(Iw,this,12,10)),Xa(this.c,t,r);case 14:return Xa(gl(this),t,r)}return o=u(gn((s=u(_n(this,16),26),s||(on(),Xg)),n),66),o.Nj().Rj(this,du(this),n-Jn((on(),Xg)),t,r)},l.lh=function(t){var n,r,s;switch(t){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return(this.Bb&256)==0;case 3:return(this.Bb&512)==0;case 4:return this.s!=0;case 5:return this.t!=1;case 6:return s=this.t,s>1||s==-1;case 7:return r=this.s,r>=1;case 8:return!!this.r&&!this.q.e&&Mv(this.q).i==0;case 9:return!!this.q&&!(this.r&&!this.q.e&&Mv(this.q).i==0);case 10:return!!(this.Db>>16==10&&u(this.Cb,26));case 11:return!!this.d&&this.d.i!=0;case 12:return!!this.c&&this.c.i!=0;case 13:return!!this.a&&gl(this.a.a).i!=0&&!(this.b&&sse(this.b));case 14:return!!this.b&&sse(this.b)}return dh(this,t-Jn((on(),Xg)),gn((n=u(_n(this,16),26),n||Xg),t))},l.sh=function(t,n){var r,s;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab),!this.Ab&&(this.Ab=new at(ti,this,0,3)),fs(this.Ab,u(n,14));return;case 1:au(this,Hr(n));return;case 2:Lg(this,It(Mt(n)));return;case 3:Mg(this,It(Mt(n)));return;case 4:Cg(this,u(n,19).a);return;case 5:Wm(this,u(n,19).a);return;case 8:cb(this,u(n,138));return;case 9:s=$1(this,u(n,87),null),s&&s.Fi();return;case 11:!this.d&&(this.d=new qu(mu,this,11)),_r(this.d),!this.d&&(this.d=new qu(mu,this,11)),fs(this.d,u(n,14));return;case 12:!this.c&&(this.c=new at(Iw,this,12,10)),_r(this.c),!this.c&&(this.c=new at(Iw,this,12,10)),fs(this.c,u(n,14));return;case 13:!this.a&&(this.a=new jM(this,this)),pC(this.a),!this.a&&(this.a=new jM(this,this)),fs(this.a,u(n,14));return;case 14:_r(gl(this)),fs(gl(this),u(n,14));return}yh(this,t-Jn((on(),Xg)),gn((r=u(_n(this,16),26),r||Xg),t),n)},l.zh=function(){return on(),Xg},l.Bh=function(t){var n,r;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab);return;case 1:au(this,null);return;case 2:Lg(this,!0);return;case 3:Mg(this,!0);return;case 4:Cg(this,0);return;case 5:Wm(this,1);return;case 8:cb(this,null);return;case 9:r=$1(this,null,null),r&&r.Fi();return;case 11:!this.d&&(this.d=new qu(mu,this,11)),_r(this.d);return;case 12:!this.c&&(this.c=new at(Iw,this,12,10)),_r(this.c);return;case 13:this.a&&pC(this.a);return;case 14:this.b&&_r(this.b);return}wh(this,t-Jn((on(),Xg)),gn((n=u(_n(this,16),26),n||Xg),t))},l.Gh=function(){var t,n;if(this.c)for(t=0,n=this.c.i;tv&&cs(t,v,null),s=0,r=new rr(gl(this.a));r.e!=r.i.gc();)n=u(pr(r),87),h=(d=n.c,d||(on(),Z1)),cs(t,s++,h);return t},l.Yi=function(){var t,n,r,s,o;for(o=new bg,o.a+="[",t=gl(this.a),n=0,s=gl(this.a).i;n1);case 5:return x_(this,t,n,r,s,this.i-u(r,15).gc()>0);default:return new N0(this.e,t,this.c,n,r,s,!0)}},l.ij=function(){return!0},l.fj=function(){return sse(this)},l.Xj=function(){_r(this)},O(Tn,"EOperationImpl/2",1341),M(498,1,{1938:1,498:1},zqe),O(Tn,"EPackageImpl/1",498),M(16,85,Zo,at),l.zk=function(){return this.d},l.Ak=function(){return this.b},l.Dk=function(){return!0},l.b=0,O(Wi,"EObjectContainmentWithInverseEList",16),M(353,16,Zo,S6),l.Ek=function(){return!0},l.li=function(t,n){return rk(this,t,u(n,56))},O(Wi,"EObjectContainmentWithInverseEList/Resolving",353),M(298,353,Zo,Pm),l.ci=function(){this.a.tb=null},O(Tn,"EPackageImpl/2",298),M(1228,1,{},YB),O(Tn,"EPackageImpl/3",1228),M(718,43,y4,Epe),l._b=function(t){return fa(t)?rre(this,t):!!$o(this.f,t)},O(Tn,"EPackageRegistryImpl",718),M(509,284,{105:1,92:1,90:1,147:1,191:1,56:1,2017:1,108:1,472:1,49:1,97:1,150:1,509:1,284:1,114:1,115:1},Wee),l.Qg=function(t){return Qit(this,t)},l._g=function(t,n,r){var s,o,h;switch(t){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),this.Ab;case 1:return this.zb;case 2:return Mn(),!!(this.Bb&256);case 3:return Mn(),!!(this.Bb&512);case 4:return ct(this.s);case 5:return ct(this.t);case 6:return Mn(),h=this.t,h>1||h==-1;case 7:return Mn(),o=this.s,o>=1;case 8:return n?$h(this):this.r;case 9:return this.q;case 10:return this.Db>>16==10?u(this.Cb,59):null}return ph(this,t-Jn((on(),Ky)),gn((s=u(_n(this,16),26),s||Ky),t),n,r)},l.hh=function(t,n,r){var s,o,h;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),ou(this.Ab,t,r);case 10:return this.Cb&&(r=(o=this.Db>>16,o>=0?Qit(this,r):this.Cb.ih(this,-1-o,null,r))),Kl(this,t,10,r)}return h=u(gn((s=u(_n(this,16),26),s||(on(),Ky)),n),66),h.Nj().Qj(this,du(this),n-Jn((on(),Ky)),t,r)},l.jh=function(t,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),Xa(this.Ab,t,r);case 9:return zne(this,r);case 10:return Kl(this,null,10,r)}return o=u(gn((s=u(_n(this,16),26),s||(on(),Ky)),n),66),o.Nj().Rj(this,du(this),n-Jn((on(),Ky)),t,r)},l.lh=function(t){var n,r,s;switch(t){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return(this.Bb&256)==0;case 3:return(this.Bb&512)==0;case 4:return this.s!=0;case 5:return this.t!=1;case 6:return s=this.t,s>1||s==-1;case 7:return r=this.s,r>=1;case 8:return!!this.r&&!this.q.e&&Mv(this.q).i==0;case 9:return!!this.q&&!(this.r&&!this.q.e&&Mv(this.q).i==0);case 10:return!!(this.Db>>16==10&&u(this.Cb,59))}return dh(this,t-Jn((on(),Ky)),gn((n=u(_n(this,16),26),n||Ky),t))},l.zh=function(){return on(),Ky},O(Tn,"EParameterImpl",509),M(99,449,{105:1,92:1,90:1,147:1,191:1,56:1,18:1,170:1,66:1,108:1,472:1,49:1,97:1,150:1,99:1,449:1,284:1,114:1,115:1,677:1},Cbe),l._g=function(t,n,r){var s,o,h,d;switch(t){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),this.Ab;case 1:return this.zb;case 2:return Mn(),!!(this.Bb&256);case 3:return Mn(),!!(this.Bb&512);case 4:return ct(this.s);case 5:return ct(this.t);case 6:return Mn(),d=this.t,d>1||d==-1;case 7:return Mn(),o=this.s,o>=1;case 8:return n?$h(this):this.r;case 9:return this.q;case 10:return Mn(),!!(this.Bb&Sf);case 11:return Mn(),!!(this.Bb&ky);case 12:return Mn(),!!(this.Bb&dy);case 13:return this.j;case 14:return b7(this);case 15:return Mn(),!!(this.Bb&Zu);case 16:return Mn(),!!(this.Bb&Ed);case 17:return Fm(this);case 18:return Mn(),!!(this.Bb&_c);case 19:return Mn(),h=go(this),!!(h&&h.Bb&_c);case 20:return Mn(),!!(this.Bb&so);case 21:return n?go(this):this.b;case 22:return n?uye(this):AZe(this);case 23:return!this.a&&(this.a=new $3(Vy,this,23)),this.a}return ph(this,t-Jn((on(),n5)),gn((s=u(_n(this,16),26),s||n5),t),n,r)},l.lh=function(t){var n,r,s,o;switch(t){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return(this.Bb&256)==0;case 3:return(this.Bb&512)==0;case 4:return this.s!=0;case 5:return this.t!=1;case 6:return o=this.t,o>1||o==-1;case 7:return r=this.s,r>=1;case 8:return!!this.r&&!this.q.e&&Mv(this.q).i==0;case 9:return!!this.q&&!(this.r&&!this.q.e&&Mv(this.q).i==0);case 10:return(this.Bb&Sf)==0;case 11:return(this.Bb&ky)!=0;case 12:return(this.Bb&dy)!=0;case 13:return this.j!=null;case 14:return b7(this)!=null;case 15:return(this.Bb&Zu)!=0;case 16:return(this.Bb&Ed)!=0;case 17:return!!Fm(this);case 18:return(this.Bb&_c)!=0;case 19:return s=go(this),!!s&&(s.Bb&_c)!=0;case 20:return(this.Bb&so)==0;case 21:return!!this.b;case 22:return!!AZe(this);case 23:return!!this.a&&this.a.i!=0}return dh(this,t-Jn((on(),n5)),gn((n=u(_n(this,16),26),n||n5),t))},l.sh=function(t,n){var r,s;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab),!this.Ab&&(this.Ab=new at(ti,this,0,3)),fs(this.Ab,u(n,14));return;case 1:bre(this,Hr(n));return;case 2:Lg(this,It(Mt(n)));return;case 3:Mg(this,It(Mt(n)));return;case 4:Cg(this,u(n,19).a);return;case 5:Wm(this,u(n,19).a);return;case 8:cb(this,u(n,138));return;case 9:s=$1(this,u(n,87),null),s&&s.Fi();return;case 10:J8(this,It(Mt(n)));return;case 11:n7(this,It(Mt(n)));return;case 12:e7(this,It(Mt(n)));return;case 13:N2e(this,Hr(n));return;case 15:t7(this,It(Mt(n)));return;case 16:r7(this,It(Mt(n)));return;case 18:Men(this,It(Mt(n)));return;case 20:$ye(this,It(Mt(n)));return;case 21:jme(this,u(n,18));return;case 23:!this.a&&(this.a=new $3(Vy,this,23)),_r(this.a),!this.a&&(this.a=new $3(Vy,this,23)),fs(this.a,u(n,14));return}yh(this,t-Jn((on(),n5)),gn((r=u(_n(this,16),26),r||n5),t),n)},l.zh=function(){return on(),n5},l.Bh=function(t){var n,r;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab);return;case 1:we(this.Cb,88)&&iy(dl(u(this.Cb,88)),4),au(this,null);return;case 2:Lg(this,!0);return;case 3:Mg(this,!0);return;case 4:Cg(this,0);return;case 5:Wm(this,1);return;case 8:cb(this,null);return;case 9:r=$1(this,null,null),r&&r.Fi();return;case 10:J8(this,!0);return;case 11:n7(this,!1);return;case 12:e7(this,!1);return;case 13:this.i=null,X$(this,null);return;case 15:t7(this,!1);return;case 16:r7(this,!1);return;case 18:jye(this,!1),we(this.Cb,88)&&iy(dl(u(this.Cb,88)),2);return;case 20:$ye(this,!0);return;case 21:jme(this,null);return;case 23:!this.a&&(this.a=new $3(Vy,this,23)),_r(this.a);return}wh(this,t-Jn((on(),n5)),gn((n=u(_n(this,16),26),n||n5),t))},l.Gh=function(){uye(this),m8(Po((Yu(),Oa),this)),$h(this),this.Bb|=1},l.Lj=function(){return go(this)},l.qk=function(){var t;return t=go(this),!!t&&(t.Bb&_c)!=0},l.rk=function(){return(this.Bb&_c)!=0},l.sk=function(){return(this.Bb&so)!=0},l.nk=function(t,n){return this.c=null,Iye(this,t,n)},l.Ib=function(){var t;return this.Db&64?lz(this):(t=new Ph(lz(this)),t.a+=" (containment: ",vg(t,(this.Bb&_c)!=0),t.a+=", resolveProxies: ",vg(t,(this.Bb&so)!=0),t.a+=")",t.a)},O(Tn,"EReferenceImpl",99),M(548,115,{105:1,42:1,92:1,90:1,133:1,56:1,108:1,49:1,97:1,548:1,114:1,115:1},UZ),l.Fb=function(t){return this===t},l.cd=function(){return this.b},l.dd=function(){return this.c},l.Hb=function(){return xv(this)},l.Uh=function(t){PQt(this,Hr(t))},l.ed=function(t){return EQt(this,Hr(t))},l._g=function(t,n,r){var s;switch(t){case 0:return this.b;case 1:return this.c}return ph(this,t-Jn((on(),oo)),gn((s=u(_n(this,16),26),s||oo),t),n,r)},l.lh=function(t){var n;switch(t){case 0:return this.b!=null;case 1:return this.c!=null}return dh(this,t-Jn((on(),oo)),gn((n=u(_n(this,16),26),n||oo),t))},l.sh=function(t,n){var r;switch(t){case 0:BQt(this,Hr(n));return;case 1:Bme(this,Hr(n));return}yh(this,t-Jn((on(),oo)),gn((r=u(_n(this,16),26),r||oo),t),n)},l.zh=function(){return on(),oo},l.Bh=function(t){var n;switch(t){case 0:Pme(this,null);return;case 1:Bme(this,null);return}wh(this,t-Jn((on(),oo)),gn((n=u(_n(this,16),26),n||oo),t))},l.Sh=function(){var t;return this.a==-1&&(t=this.b,this.a=t==null?0:Ig(t)),this.a},l.Th=function(t){this.a=t},l.Ib=function(){var t;return this.Db&64?_f(this):(t=new Ph(_f(this)),t.a+=" (key: ",To(t,this.b),t.a+=", value: ",To(t,this.c),t.a+=")",t.a)},l.a=-1,l.b=null,l.c=null;var wc=O(Tn,"EStringToStringMapEntryImpl",548),b4t=ss(Wi,"FeatureMap/Entry/Internal");M(565,1,xG),l.Ok=function(t){return this.Pk(u(t,49))},l.Pk=function(t){return this.Ok(t)},l.Fb=function(t){var n,r;return this===t?!0:we(t,72)?(n=u(t,72),n.ak()==this.c?(r=this.dd(),r==null?n.dd()==null:Ci(r,n.dd())):!1):!1},l.ak=function(){return this.c},l.Hb=function(){var t;return t=this.dd(),Xi(this.c)^(t==null?0:Xi(t))},l.Ib=function(){var t,n;return t=this.c,n=Gl(t.Hj()).Ph(),t.ne(),(n!=null&&n.length!=0?n+":"+t.ne():t.ne())+"="+this.dd()},O(Tn,"EStructuralFeatureImpl/BasicFeatureMapEntry",565),M(776,565,xG,Pbe),l.Pk=function(t){return new Pbe(this.c,t)},l.dd=function(){return this.a},l.Qk=function(t,n,r){return Zin(this,t,this.a,n,r)},l.Rk=function(t,n,r){return Jin(this,t,this.a,n,r)},O(Tn,"EStructuralFeatureImpl/ContainmentUpdatingFeatureMapEntry",776),M(1314,1,{},Gqe),l.Pj=function(t,n,r,s,o){var h;return h=u(A8(t,this.b),215),h.nl(this.a).Wj(s)},l.Qj=function(t,n,r,s,o){var h;return h=u(A8(t,this.b),215),h.el(this.a,s,o)},l.Rj=function(t,n,r,s,o){var h;return h=u(A8(t,this.b),215),h.fl(this.a,s,o)},l.Sj=function(t,n,r){var s;return s=u(A8(t,this.b),215),s.nl(this.a).fj()},l.Tj=function(t,n,r,s){var o;o=u(A8(t,this.b),215),o.nl(this.a).Wb(s)},l.Uj=function(t,n,r){return u(A8(t,this.b),215).nl(this.a)},l.Vj=function(t,n,r){var s;s=u(A8(t,this.b),215),s.nl(this.a).Xj()},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateFeatureMapDelegator",1314),M(89,1,{},yg,K2,xg,Q2),l.Pj=function(t,n,r,s,o){var h;if(h=n.Ch(r),h==null&&n.Dh(r,h=Ez(this,t)),!o)switch(this.e){case 50:case 41:return u(h,589).sj();case 40:return u(h,215).kl()}return h},l.Qj=function(t,n,r,s,o){var h,d;return d=n.Ch(r),d==null&&n.Dh(r,d=Ez(this,t)),h=u(d,69).lk(s,o),h},l.Rj=function(t,n,r,s,o){var h;return h=n.Ch(r),h!=null&&(o=u(h,69).mk(s,o)),o},l.Sj=function(t,n,r){var s;return s=n.Ch(r),s!=null&&u(s,76).fj()},l.Tj=function(t,n,r,s){var o;o=u(n.Ch(r),76),!o&&n.Dh(r,o=Ez(this,t)),o.Wb(s)},l.Uj=function(t,n,r){var s,o;return o=n.Ch(r),o==null&&n.Dh(r,o=Ez(this,t)),we(o,76)?u(o,76):(s=u(n.Ch(r),15),new z$e(s))},l.Vj=function(t,n,r){var s;s=u(n.Ch(r),76),!s&&n.Dh(r,s=Ez(this,t)),s.Xj()},l.b=0,l.e=0,O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateMany",89),M(504,1,{}),l.Qj=function(t,n,r,s,o){throw J(new Fr)},l.Rj=function(t,n,r,s,o){throw J(new Fr)},l.Uj=function(t,n,r){return new FYe(this,t,n,r)};var b0;O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingle",504),M(1331,1,Qce,FYe),l.Wj=function(t){return this.a.Pj(this.c,this.d,this.b,t,!0)},l.fj=function(){return this.a.Sj(this.c,this.d,this.b)},l.Wb=function(t){this.a.Tj(this.c,this.d,this.b,t)},l.Xj=function(){this.a.Vj(this.c,this.d,this.b)},l.b=0,O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingle/1",1331),M(769,504,{},vwe),l.Pj=function(t,n,r,s,o){return rae(t,t.eh(),t.Vg())==this.b?this.sk()&&s?Hse(t):t.eh():null},l.Qj=function(t,n,r,s,o){var h,d;return t.eh()&&(o=(h=t.Vg(),h>=0?t.Qg(o):t.eh().ih(t,-1-h,null,o))),d=Ji(t.Tg(),this.e),t.Sg(s,d,o)},l.Rj=function(t,n,r,s,o){var h;return h=Ji(t.Tg(),this.e),t.Sg(null,h,o)},l.Sj=function(t,n,r){var s;return s=Ji(t.Tg(),this.e),!!t.eh()&&t.Vg()==s},l.Tj=function(t,n,r,s){var o,h,d,v,x;if(s!=null&&!oae(this.a,s))throw J(new Wx(EG+(we(s,56)?Q3e(u(s,56).Tg()):kme(pl(s)))+TG+this.a+"'"));if(o=t.eh(),d=Ji(t.Tg(),this.e),je(s)!==je(o)||t.Vg()!=d&&s!=null){if(o7(t,u(s,56)))throw J(new Ln(FC+t.Ib()));x=null,o&&(x=(h=t.Vg(),h>=0?t.Qg(x):t.eh().ih(t,-1-h,null,x))),v=u(s,49),v&&(x=v.gh(t,Ji(v.Tg(),this.b),null,x)),x=t.Sg(v,d,x),x&&x.Fi()}else t.Lg()&&t.Mg()&&_i(t,new oa(t,1,d,s,s))},l.Vj=function(t,n,r){var s,o,h,d;s=t.eh(),s?(d=(o=t.Vg(),o>=0?t.Qg(null):t.eh().ih(t,-1-o,null,null)),h=Ji(t.Tg(),this.e),d=t.Sg(null,h,d),d&&d.Fi()):t.Lg()&&t.Mg()&&_i(t,new p_(t,1,this.e,null,null))},l.sk=function(){return!1},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleContainer",769),M(1315,769,{},MWe),l.sk=function(){return!0},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleContainerResolving",1315),M(563,504,{}),l.Pj=function(t,n,r,s,o){var h;return h=n.Ch(r),h==null?this.b:je(h)===je(b0)?null:h},l.Sj=function(t,n,r){var s;return s=n.Ch(r),s!=null&&(je(s)===je(b0)||!Ci(s,this.b))},l.Tj=function(t,n,r,s){var o,h;t.Lg()&&t.Mg()?(o=(h=n.Ch(r),h==null?this.b:je(h)===je(b0)?null:h),s==null?this.c!=null?(n.Dh(r,null),s=this.b):this.b!=null?n.Dh(r,b0):n.Dh(r,null):(this.Sk(s),n.Dh(r,s)),_i(t,this.d.Tk(t,1,this.e,o,s))):s==null?this.c!=null?n.Dh(r,null):this.b!=null?n.Dh(r,b0):n.Dh(r,null):(this.Sk(s),n.Dh(r,s))},l.Vj=function(t,n,r){var s,o;t.Lg()&&t.Mg()?(s=(o=n.Ch(r),o==null?this.b:je(o)===je(b0)?null:o),n.Eh(r),_i(t,this.d.Tk(t,1,this.e,s,this.b))):n.Eh(r)},l.Sk=function(t){throw J(new Z$e)},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleData",563),M(M4,1,{},XB),l.Tk=function(t,n,r,s,o){return new p_(t,n,r,s,o)},l.Uk=function(t,n,r,s,o,h){return new nre(t,n,r,s,o,h)};var jAe,$Ae,HAe,zAe,GAe,qAe,VAe,_fe,UAe;O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleData/NotificationCreator",M4),M(1332,M4,{},QB),l.Tk=function(t,n,r,s,o){return new Zwe(t,n,r,It(Mt(s)),It(Mt(o)))},l.Uk=function(t,n,r,s,o,h){return new aQe(t,n,r,It(Mt(s)),It(Mt(o)),h)},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleData/NotificationCreator/1",1332),M(1333,M4,{},ZB),l.Tk=function(t,n,r,s,o){return new _me(t,n,r,u(s,217).a,u(o,217).a)},l.Uk=function(t,n,r,s,o,h){return new JXe(t,n,r,u(s,217).a,u(o,217).a,h)},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleData/NotificationCreator/2",1333),M(1334,M4,{},_x),l.Tk=function(t,n,r,s,o){return new Cme(t,n,r,u(s,172).a,u(o,172).a)},l.Uk=function(t,n,r,s,o,h){return new eQe(t,n,r,u(s,172).a,u(o,172).a,h)},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleData/NotificationCreator/3",1334),M(1335,M4,{},JB),l.Tk=function(t,n,r,s,o){return new Xwe(t,n,r,Ue(ft(s)),Ue(ft(o)))},l.Uk=function(t,n,r,s,o,h){return new tQe(t,n,r,Ue(ft(s)),Ue(ft(o)),h)},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleData/NotificationCreator/4",1335),M(1336,M4,{},eR),l.Tk=function(t,n,r,s,o){return new Lme(t,n,r,u(s,155).a,u(o,155).a)},l.Uk=function(t,n,r,s,o,h){return new nQe(t,n,r,u(s,155).a,u(o,155).a,h)},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleData/NotificationCreator/5",1336),M(1337,M4,{},WZ),l.Tk=function(t,n,r,s,o){return new Qwe(t,n,r,u(s,19).a,u(o,19).a)},l.Uk=function(t,n,r,s,o,h){return new rQe(t,n,r,u(s,19).a,u(o,19).a,h)},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleData/NotificationCreator/6",1337),M(1338,M4,{},Cx),l.Tk=function(t,n,r,s,o){return new Sme(t,n,r,u(s,162).a,u(o,162).a)},l.Uk=function(t,n,r,s,o,h){return new iQe(t,n,r,u(s,162).a,u(o,162).a,h)},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleData/NotificationCreator/7",1338),M(1339,M4,{},Sx),l.Tk=function(t,n,r,s,o){return new Ame(t,n,r,u(s,184).a,u(o,184).a)},l.Uk=function(t,n,r,s,o,h){return new sQe(t,n,r,u(s,184).a,u(o,184).a,h)},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleData/NotificationCreator/8",1339),M(1317,563,{},jYe),l.Sk=function(t){if(!this.a.wj(t))throw J(new Wx(EG+pl(t)+TG+this.a+"'"))},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleDataDynamic",1317),M(1318,563,{},SKe),l.Sk=function(t){},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleDataStatic",1318),M(770,563,{}),l.Sj=function(t,n,r){var s;return s=n.Ch(r),s!=null},l.Tj=function(t,n,r,s){var o,h;t.Lg()&&t.Mg()?(o=!0,h=n.Ch(r),h==null?(o=!1,h=this.b):je(h)===je(b0)&&(h=null),s==null?this.c!=null?(n.Dh(r,null),s=this.b):n.Dh(r,b0):(this.Sk(s),n.Dh(r,s)),_i(t,this.d.Uk(t,1,this.e,h,s,!o))):s==null?this.c!=null?n.Dh(r,null):n.Dh(r,b0):(this.Sk(s),n.Dh(r,s))},l.Vj=function(t,n,r){var s,o;t.Lg()&&t.Mg()?(s=!0,o=n.Ch(r),o==null?(s=!1,o=this.b):je(o)===je(b0)&&(o=null),n.Eh(r),_i(t,this.d.Uk(t,2,this.e,o,this.b,s))):n.Eh(r)},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleDataUnsettable",770),M(1319,770,{},$Ye),l.Sk=function(t){if(!this.a.wj(t))throw J(new Wx(EG+pl(t)+TG+this.a+"'"))},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleDataUnsettableDynamic",1319),M(1320,770,{},AKe),l.Sk=function(t){},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleDataUnsettableStatic",1320),M(398,504,{},Mj),l.Pj=function(t,n,r,s,o){var h,d,v,x,_;if(_=n.Ch(r),this.Kj()&&je(_)===je(b0))return null;if(this.sk()&&s&&_!=null){if(v=u(_,49),v.kh()&&(x=Up(t,v),v!=x)){if(!oae(this.a,x))throw J(new Wx(EG+pl(x)+TG+this.a+"'"));n.Dh(r,_=x),this.rk()&&(h=u(x,49),d=v.ih(t,this.b?Ji(v.Tg(),this.b):-1-Ji(t.Tg(),this.e),null,null),!h.eh()&&(d=h.gh(t,this.b?Ji(h.Tg(),this.b):-1-Ji(t.Tg(),this.e),null,d)),d&&d.Fi()),t.Lg()&&t.Mg()&&_i(t,new p_(t,9,this.e,v,x))}return _}else return _},l.Qj=function(t,n,r,s,o){var h,d;return d=n.Ch(r),je(d)===je(b0)&&(d=null),n.Dh(r,s),this.bj()?je(d)!==je(s)&&d!=null&&(h=u(d,49),o=h.ih(t,Ji(h.Tg(),this.b),null,o)):this.rk()&&d!=null&&(o=u(d,49).ih(t,-1-Ji(t.Tg(),this.e),null,o)),t.Lg()&&t.Mg()&&(!o&&(o=new _p(4)),o.Ei(new p_(t,1,this.e,d,s))),o},l.Rj=function(t,n,r,s,o){var h;return h=n.Ch(r),je(h)===je(b0)&&(h=null),n.Eh(r),t.Lg()&&t.Mg()&&(!o&&(o=new _p(4)),this.Kj()?o.Ei(new p_(t,2,this.e,h,null)):o.Ei(new p_(t,1,this.e,h,null))),o},l.Sj=function(t,n,r){var s;return s=n.Ch(r),s!=null},l.Tj=function(t,n,r,s){var o,h,d,v,x;if(s!=null&&!oae(this.a,s))throw J(new Wx(EG+(we(s,56)?Q3e(u(s,56).Tg()):kme(pl(s)))+TG+this.a+"'"));x=n.Ch(r),v=x!=null,this.Kj()&&je(x)===je(b0)&&(x=null),d=null,this.bj()?je(x)!==je(s)&&(x!=null&&(o=u(x,49),d=o.ih(t,Ji(o.Tg(),this.b),null,d)),s!=null&&(o=u(s,49),d=o.gh(t,Ji(o.Tg(),this.b),null,d))):this.rk()&&je(x)!==je(s)&&(x!=null&&(d=u(x,49).ih(t,-1-Ji(t.Tg(),this.e),null,d)),s!=null&&(d=u(s,49).gh(t,-1-Ji(t.Tg(),this.e),null,d))),s==null&&this.Kj()?n.Dh(r,b0):n.Dh(r,s),t.Lg()&&t.Mg()?(h=new nre(t,1,this.e,x,s,this.Kj()&&!v),d?(d.Ei(h),d.Fi()):_i(t,h)):d&&d.Fi()},l.Vj=function(t,n,r){var s,o,h,d,v;v=n.Ch(r),d=v!=null,this.Kj()&&je(v)===je(b0)&&(v=null),h=null,v!=null&&(this.bj()?(s=u(v,49),h=s.ih(t,Ji(s.Tg(),this.b),null,h)):this.rk()&&(h=u(v,49).ih(t,-1-Ji(t.Tg(),this.e),null,h))),n.Eh(r),t.Lg()&&t.Mg()?(o=new nre(t,this.Kj()?2:1,this.e,v,null,d),h?(h.Ei(o),h.Fi()):_i(t,o)):h&&h.Fi()},l.bj=function(){return!1},l.rk=function(){return!1},l.sk=function(){return!1},l.Kj=function(){return!1},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObject",398),M(564,398,{},ine),l.rk=function(){return!0},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectContainment",564),M(1323,564,{},CUe),l.sk=function(){return!0},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectContainmentResolving",1323),M(772,564,{},xbe),l.Kj=function(){return!0},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectContainmentUnsettable",772),M(1325,772,{},SUe),l.sk=function(){return!0},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectContainmentUnsettableResolving",1325),M(640,564,{},wne),l.bj=function(){return!0},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectContainmentWithInverse",640),M(1324,640,{},DWe),l.sk=function(){return!0},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectContainmentWithInverseResolving",1324),M(773,640,{},cve),l.Kj=function(){return!0},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectContainmentWithInverseUnsettable",773),M(1326,773,{},IWe),l.sk=function(){return!0},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectContainmentWithInverseUnsettableResolving",1326),M(641,398,{},Ebe),l.sk=function(){return!0},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectResolving",641),M(1327,641,{},AUe),l.Kj=function(){return!0},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectResolvingUnsettable",1327),M(774,641,{},ave),l.bj=function(){return!0},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectResolvingWithInverse",774),M(1328,774,{},OWe),l.Kj=function(){return!0},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectResolvingWithInverseUnsettable",1328),M(1321,398,{},LUe),l.Kj=function(){return!0},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectUnsettable",1321),M(771,398,{},ove),l.bj=function(){return!0},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectWithInverse",771),M(1322,771,{},NWe),l.Kj=function(){return!0},O(Tn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectWithInverseUnsettable",1322),M(775,565,xG,rwe),l.Pk=function(t){return new rwe(this.a,this.c,t)},l.dd=function(){return this.b},l.Qk=function(t,n,r){return Jnn(this,t,this.b,r)},l.Rk=function(t,n,r){return ern(this,t,this.b,r)},O(Tn,"EStructuralFeatureImpl/InverseUpdatingFeatureMapEntry",775),M(1329,1,Qce,z$e),l.Wj=function(t){return this.a},l.fj=function(){return we(this.a,95)?u(this.a,95).fj():!this.a.dc()},l.Wb=function(t){this.a.$b(),this.a.Gc(u(t,15))},l.Xj=function(){we(this.a,95)?u(this.a,95).Xj():this.a.$b()},O(Tn,"EStructuralFeatureImpl/SettingMany",1329),M(1330,565,xG,KQe),l.Ok=function(t){return new one((Fi(),JS),this.b.Ih(this.a,t))},l.dd=function(){return null},l.Qk=function(t,n,r){return r},l.Rk=function(t,n,r){return r},O(Tn,"EStructuralFeatureImpl/SimpleContentFeatureMapEntry",1330),M(642,565,xG,one),l.Ok=function(t){return new one(this.c,t)},l.dd=function(){return this.a},l.Qk=function(t,n,r){return r},l.Rk=function(t,n,r){return r},O(Tn,"EStructuralFeatureImpl/SimpleFeatureMapEntry",642),M(391,497,Od,gm),l.ri=function(t){return Me(tf,yt,26,t,0,1)},l.ni=function(){return!1},O(Tn,"ESuperAdapter/1",391),M(444,438,{105:1,92:1,90:1,147:1,191:1,56:1,108:1,836:1,49:1,97:1,150:1,444:1,114:1,115:1},RL),l._g=function(t,n,r){var s;switch(t){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),this.Ab;case 1:return this.zb;case 2:return!this.a&&(this.a=new h_(this,Eo,this)),this.a}return ph(this,t-Jn((on(),Nw)),gn((s=u(_n(this,16),26),s||Nw),t),n,r)},l.jh=function(t,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new at(ti,this,0,3)),Xa(this.Ab,t,r);case 2:return!this.a&&(this.a=new h_(this,Eo,this)),Xa(this.a,t,r)}return o=u(gn((s=u(_n(this,16),26),s||(on(),Nw)),n),66),o.Nj().Rj(this,du(this),n-Jn((on(),Nw)),t,r)},l.lh=function(t){var n;switch(t){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return!!this.a&&this.a.i!=0}return dh(this,t-Jn((on(),Nw)),gn((n=u(_n(this,16),26),n||Nw),t))},l.sh=function(t,n){var r;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab),!this.Ab&&(this.Ab=new at(ti,this,0,3)),fs(this.Ab,u(n,14));return;case 1:au(this,Hr(n));return;case 2:!this.a&&(this.a=new h_(this,Eo,this)),_r(this.a),!this.a&&(this.a=new h_(this,Eo,this)),fs(this.a,u(n,14));return}yh(this,t-Jn((on(),Nw)),gn((r=u(_n(this,16),26),r||Nw),t),n)},l.zh=function(){return on(),Nw},l.Bh=function(t){var n;switch(t){case 0:!this.Ab&&(this.Ab=new at(ti,this,0,3)),_r(this.Ab);return;case 1:au(this,null);return;case 2:!this.a&&(this.a=new h_(this,Eo,this)),_r(this.a);return}wh(this,t-Jn((on(),Nw)),gn((n=u(_n(this,16),26),n||Nw),t))},O(Tn,"ETypeParameterImpl",444),M(445,85,Zo,h_),l.cj=function(t,n){return efn(this,u(t,87),n)},l.dj=function(t,n){return tfn(this,u(t,87),n)},O(Tn,"ETypeParameterImpl/1",445),M(634,43,y4,Kee),l.ec=function(){return new rF(this)},O(Tn,"ETypeParameterImpl/2",634),M(556,H1,Xu,rF),l.Fc=function(t){return tWe(this,u(t,87))},l.Gc=function(t){var n,r,s;for(s=!1,r=t.Kc();r.Ob();)n=u(r.Pb(),87),Si(this.a,n,"")==null&&(s=!0);return s},l.$b=function(){sl(this.a)},l.Hc=function(t){return Il(this.a,t)},l.Kc=function(){var t;return t=new ob(new dg(this.a).a),new iF(t)},l.Mc=function(t){return HZe(this,t)},l.gc=function(){return MT(this.a)},O(Tn,"ETypeParameterImpl/2/1",556),M(557,1,ga,iF),l.Nb=function(t){La(this,t)},l.Pb=function(){return u($v(this.a).cd(),87)},l.Ob=function(){return this.a.b},l.Qb=function(){wJe(this.a)},O(Tn,"ETypeParameterImpl/2/1/1",557),M(1276,43,y4,IHe),l._b=function(t){return fa(t)?rre(this,t):!!$o(this.f,t)},l.xc=function(t){var n,r;return n=fa(t)?Uc(this,t):hc($o(this.f,t)),we(n,837)?(r=u(n,837),n=r._j(),Si(this,u(t,235),n),n):n??(t==null?(hte(),w4t):null)},O(Tn,"EValidatorRegistryImpl",1276),M(1313,704,{105:1,92:1,90:1,471:1,147:1,56:1,108:1,1941:1,49:1,97:1,150:1,114:1,115:1},KZ),l.Ih=function(t,n){switch(t.yj()){case 21:case 22:case 23:case 24:case 26:case 31:case 32:case 37:case 38:case 39:case 40:case 43:case 44:case 48:case 49:case 20:return n==null?null:Qo(n);case 25:return cin(n);case 27:return _rn(n);case 28:return Crn(n);case 29:return n==null?null:PVe(WS[0],u(n,199));case 41:return n==null?"":Cp(u(n,290));case 42:return Qo(n);case 50:return Hr(n);default:throw J(new Ln($7+t.ne()+dw))}},l.Jh=function(t){var n,r,s,o,h,d,v,x,_,L,P,z,q,W,X,le;switch(t.G==-1&&(t.G=(z=Gl(t),z?Dg(z.Mh(),t):-1)),t.G){case 0:return r=new Vee,r;case 1:return n=new KB,n;case 2:return s=new YL,s;case 4:return o=new sF,o;case 5:return h=new DHe,h;case 6:return d=new tHe,d;case 7:return v=new RR,v;case 10:return _=new Ex,_;case 11:return L=new Uee,L;case 12:return P=new rXe,P;case 13:return q=new Wee,q;case 14:return W=new Cbe,W;case 17:return X=new UZ,X;case 18:return x=new uv,x;case 19:return le=new RL,le;default:throw J(new Ln(Pce+t.zb+dw))}},l.Kh=function(t,n){switch(t.yj()){case 20:return n==null?null:new Vpe(n);case 21:return n==null?null:new Ip(n);case 23:case 22:return n==null?null:dcn(n);case 26:case 24:return n==null?null:xD(Wl(n,-128,127)<<24>>24);case 25:return T0n(n);case 27:return Xun(n);case 28:return Qun(n);case 29:return mfn(n);case 32:case 31:return n==null?null:ry(n);case 38:case 37:return n==null?null:new hpe(n);case 40:case 39:return n==null?null:ct(Wl(n,$a,Ei));case 41:return null;case 42:return n==null,null;case 44:case 43:return n==null?null:lb(xz(n));case 49:case 48:return n==null?null:Z8(Wl(n,_G,32767)<<16>>16);case 50:return n;default:throw J(new Ln($7+t.ne()+dw))}},O(Tn,"EcoreFactoryImpl",1313),M(547,179,{105:1,92:1,90:1,147:1,191:1,56:1,235:1,108:1,1939:1,49:1,97:1,150:1,179:1,547:1,114:1,115:1,675:1},yYe),l.gb=!1,l.hb=!1;var WAe,v4t=!1;O(Tn,"EcorePackageImpl",547),M(1184,1,{837:1},YZ),l._j=function(){return sUe(),m4t},O(Tn,"EcorePackageImpl/1",1184),M(1193,1,li,XZ),l.wj=function(t){return we(t,147)},l.xj=function(t){return Me(aN,yt,147,t,0,1)},O(Tn,"EcorePackageImpl/10",1193),M(1194,1,li,QZ),l.wj=function(t){return we(t,191)},l.xj=function(t){return Me(bfe,yt,191,t,0,1)},O(Tn,"EcorePackageImpl/11",1194),M(1195,1,li,ZZ),l.wj=function(t){return we(t,56)},l.xj=function(t){return Me(y2,yt,56,t,0,1)},O(Tn,"EcorePackageImpl/12",1195),M(1196,1,li,JZ),l.wj=function(t){return we(t,399)},l.xj=function(t){return Me(nf,v8e,59,t,0,1)},O(Tn,"EcorePackageImpl/13",1196),M(1197,1,li,eJ),l.wj=function(t){return we(t,235)},l.xj=function(t){return Me(h1,yt,235,t,0,1)},O(Tn,"EcorePackageImpl/14",1197),M(1198,1,li,tJ),l.wj=function(t){return we(t,509)},l.xj=function(t){return Me(Iw,yt,2017,t,0,1)},O(Tn,"EcorePackageImpl/15",1198),M(1199,1,li,tR),l.wj=function(t){return we(t,99)},l.xj=function(t){return Me(Uy,L4,18,t,0,1)},O(Tn,"EcorePackageImpl/16",1199),M(1200,1,li,nJ),l.wj=function(t){return we(t,170)},l.xj=function(t){return Me(ju,L4,170,t,0,1)},O(Tn,"EcorePackageImpl/17",1200),M(1201,1,li,rJ),l.wj=function(t){return we(t,472)},l.xj=function(t){return Me(qy,yt,472,t,0,1)},O(Tn,"EcorePackageImpl/18",1201),M(1202,1,li,iJ),l.wj=function(t){return we(t,548)},l.xj=function(t){return Me(wc,wdt,548,t,0,1)},O(Tn,"EcorePackageImpl/19",1202),M(1185,1,li,nR),l.wj=function(t){return we(t,322)},l.xj=function(t){return Me(Vy,L4,34,t,0,1)},O(Tn,"EcorePackageImpl/2",1185),M(1203,1,li,Ax),l.wj=function(t){return we(t,241)},l.xj=function(t){return Me(Eo,Pdt,87,t,0,1)},O(Tn,"EcorePackageImpl/20",1203),M(1204,1,li,z9),l.wj=function(t){return we(t,444)},l.xj=function(t){return Me(mu,yt,836,t,0,1)},O(Tn,"EcorePackageImpl/21",1204),M(1205,1,li,rR),l.wj=function(t){return Cm(t)},l.xj=function(t){return Me(Us,Qe,476,t,8,1)},O(Tn,"EcorePackageImpl/22",1205),M(1206,1,li,sJ),l.wj=function(t){return we(t,190)},l.xj=function(t){return Me(el,Qe,190,t,0,2)},O(Tn,"EcorePackageImpl/23",1206),M(1207,1,li,iR),l.wj=function(t){return we(t,217)},l.xj=function(t){return Me(mk,Qe,217,t,0,1)},O(Tn,"EcorePackageImpl/24",1207),M(1208,1,li,sR),l.wj=function(t){return we(t,172)},l.xj=function(t){return Me(XC,Qe,172,t,0,1)},O(Tn,"EcorePackageImpl/25",1208),M(1209,1,li,aJ),l.wj=function(t){return we(t,199)},l.xj=function(t){return Me(FG,Qe,199,t,0,1)},O(Tn,"EcorePackageImpl/26",1209),M(1210,1,li,G9),l.wj=function(t){return!1},l.xj=function(t){return Me(hLe,yt,2110,t,0,1)},O(Tn,"EcorePackageImpl/27",1210),M(1211,1,li,pm),l.wj=function(t){return Sm(t)},l.xj=function(t){return Me(ma,Qe,333,t,7,1)},O(Tn,"EcorePackageImpl/28",1211),M(1212,1,li,aR),l.wj=function(t){return we(t,58)},l.xj=function(t){return Me(CAe,gy,58,t,0,1)},O(Tn,"EcorePackageImpl/29",1212),M(1186,1,li,oR),l.wj=function(t){return we(t,510)},l.xj=function(t){return Me(ti,{3:1,4:1,5:1,1934:1},590,t,0,1)},O(Tn,"EcorePackageImpl/3",1186),M(1213,1,li,oJ),l.wj=function(t){return we(t,573)},l.xj=function(t){return Me(LAe,yt,1940,t,0,1)},O(Tn,"EcorePackageImpl/30",1213),M(1214,1,li,cJ),l.wj=function(t){return we(t,153)},l.xj=function(t){return Me(ZAe,gy,153,t,0,1)},O(Tn,"EcorePackageImpl/31",1214),M(1215,1,li,q9),l.wj=function(t){return we(t,72)},l.xj=function(t){return Me(eU,qdt,72,t,0,1)},O(Tn,"EcorePackageImpl/32",1215),M(1216,1,li,cR),l.wj=function(t){return we(t,155)},l.xj=function(t){return Me(W7,Qe,155,t,0,1)},O(Tn,"EcorePackageImpl/33",1216),M(1217,1,li,uR),l.wj=function(t){return we(t,19)},l.xj=function(t){return Me(Za,Qe,19,t,0,1)},O(Tn,"EcorePackageImpl/34",1217),M(1218,1,li,kc),l.wj=function(t){return we(t,290)},l.xj=function(t){return Me(M8e,yt,290,t,0,1)},O(Tn,"EcorePackageImpl/35",1218),M(1219,1,li,uJ),l.wj=function(t){return we(t,162)},l.xj=function(t){return Me(pw,Qe,162,t,0,1)},O(Tn,"EcorePackageImpl/36",1219),M(1220,1,li,lR),l.wj=function(t){return we(t,83)},l.xj=function(t){return Me(D8e,yt,83,t,0,1)},O(Tn,"EcorePackageImpl/37",1220),M(1221,1,li,V9),l.wj=function(t){return we(t,591)},l.xj=function(t){return Me(KAe,yt,591,t,0,1)},O(Tn,"EcorePackageImpl/38",1221),M(1222,1,li,lJ),l.wj=function(t){return!1},l.xj=function(t){return Me(fLe,yt,2111,t,0,1)},O(Tn,"EcorePackageImpl/39",1222),M(1187,1,li,hJ),l.wj=function(t){return we(t,88)},l.xj=function(t){return Me(tf,yt,26,t,0,1)},O(Tn,"EcorePackageImpl/4",1187),M(1223,1,li,U9),l.wj=function(t){return we(t,184)},l.xj=function(t){return Me(bw,Qe,184,t,0,1)},O(Tn,"EcorePackageImpl/40",1223),M(1224,1,li,hR),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(Tn,"EcorePackageImpl/41",1224),M(1225,1,li,W9),l.wj=function(t){return we(t,588)},l.xj=function(t){return Me(AAe,yt,588,t,0,1)},O(Tn,"EcorePackageImpl/42",1225),M(1226,1,li,K9),l.wj=function(t){return!1},l.xj=function(t){return Me(dLe,Qe,2112,t,0,1)},O(Tn,"EcorePackageImpl/43",1226),M(1227,1,li,Uf),l.wj=function(t){return we(t,42)},l.xj=function(t){return Me(Cb,Sz,42,t,0,1)},O(Tn,"EcorePackageImpl/44",1227),M(1188,1,li,FL),l.wj=function(t){return we(t,138)},l.xj=function(t){return Me(f1,yt,138,t,0,1)},O(Tn,"EcorePackageImpl/5",1188),M(1189,1,li,jL),l.wj=function(t){return we(t,148)},l.xj=function(t){return Me(xfe,yt,148,t,0,1)},O(Tn,"EcorePackageImpl/6",1189),M(1190,1,li,J5),l.wj=function(t){return we(t,457)},l.xj=function(t){return Me(JV,yt,671,t,0,1)},O(Tn,"EcorePackageImpl/7",1190),M(1191,1,li,fJ),l.wj=function(t){return we(t,573)},l.xj=function(t){return Me(J0,yt,678,t,0,1)},O(Tn,"EcorePackageImpl/8",1191),M(1192,1,li,dJ),l.wj=function(t){return we(t,471)},l.xj=function(t){return Me(US,yt,471,t,0,1)},O(Tn,"EcorePackageImpl/9",1192),M(1025,1982,vdt,XHe),l.bi=function(t,n){jan(this,u(n,415))},l.fi=function(t,n){fat(this,t,u(n,415))},O(Tn,"MinimalEObjectImpl/1ArrayDelegatingAdapterList",1025),M(1026,143,XI,hYe),l.Ai=function(){return this.a.a},O(Tn,"MinimalEObjectImpl/1ArrayDelegatingAdapterList/1",1026),M(1053,1052,{},SVe),O("org.eclipse.emf.ecore.plugin","EcorePlugin",1053);var KAe=ss(Vdt,"Resource");M(781,1378,Udt),l.Yk=function(t){},l.Zk=function(t){},l.Vk=function(){return!this.a&&(this.a=new $ee(this)),this.a},l.Wk=function(t){var n,r,s,o,h;if(s=t.length,s>0)if(zr(0,t.length),t.charCodeAt(0)==47){for(h=new su(4),o=1,n=1;n0&&(t=t.substr(0,r)));return odn(this,t)},l.Xk=function(){return this.c},l.Ib=function(){var t;return Cp(this.gm)+"@"+(t=Xi(this)>>>0,t.toString(16))+" uri='"+this.d+"'"},l.b=!1,O(Zce,"ResourceImpl",781),M(1379,781,Udt,q$e),O(Zce,"BinaryResourceImpl",1379),M(1169,694,Uce),l.si=function(t){return we(t,56)?zJt(this,u(t,56)):we(t,591)?new rr(u(t,591).Vk()):je(t)===je(this.f)?u(t,14).Kc():(u8(),uN.a)},l.Ob=function(){return z4e(this)},l.a=!1,O(Wi,"EcoreUtil/ContentTreeIterator",1169),M(1380,1169,Uce,zKe),l.si=function(t){return je(t)===je(this.f)?u(t,15).Kc():new _Qe(u(t,56))},O(Zce,"ResourceImpl/5",1380),M(648,1994,Ndt,$ee),l.Hc=function(t){return this.i<=4?u7(this,t):we(t,49)&&u(t,49).Zg()==this.a},l.bi=function(t,n){t==this.i-1&&(this.a.b||(this.a.b=!0))},l.di=function(t,n){t==0?this.a.b||(this.a.b=!0):Nre(this,t,n)},l.fi=function(t,n){},l.gi=function(t,n,r){},l.aj=function(){return 2},l.Ai=function(){return this.a},l.bj=function(){return!0},l.cj=function(t,n){var r;return r=u(t,49),n=r.wh(this.a,n),n},l.dj=function(t,n){var r;return r=u(t,49),r.wh(null,n)},l.ej=function(){return!1},l.hi=function(){return!0},l.ri=function(t){return Me(y2,yt,56,t,0,1)},l.ni=function(){return!1},O(Zce,"ResourceImpl/ContentsEList",648),M(957,1964,A7,G$e),l.Zc=function(t){return this.a._h(t)},l.gc=function(){return this.a.gc()},O(Wi,"AbstractSequentialInternalEList/1",957);var YAe,XAe,Oa,QAe;M(624,1,{},qWe);var tU,nU;O(Wi,"BasicExtendedMetaData",624),M(1160,1,{},qqe),l.$k=function(){return null},l._k=function(){return this.a==-2&&fg(this,gfn(this.d,this.b)),this.a},l.al=function(){return null},l.bl=function(){return hn(),hn(),bo},l.ne=function(){return this.c==G7&&_3(this,Grt(this.d,this.b)),this.c},l.cl=function(){return 0},l.a=-2,l.c=G7,O(Wi,"BasicExtendedMetaData/EClassExtendedMetaDataImpl",1160),M(1161,1,{},hQe),l.$k=function(){return this.a==(C8(),tU)&&Qge(this,Mgn(this.f,this.b)),this.a},l._k=function(){return 0},l.al=function(){return this.c==(C8(),tU)&&Eee(this,Dgn(this.f,this.b)),this.c},l.bl=function(){return!this.d&&Tee(this,M2n(this.f,this.b)),this.d},l.ne=function(){return this.e==G7&&UR(this,Grt(this.f,this.b)),this.e},l.cl=function(){return this.g==-2&&WR(this,Ohn(this.f,this.b)),this.g},l.e=G7,l.g=-2,O(Wi,"BasicExtendedMetaData/EDataTypeExtendedMetaDataImpl",1161),M(1159,1,{},Uqe),l.b=!1,l.c=!1,O(Wi,"BasicExtendedMetaData/EPackageExtendedMetaDataImpl",1159),M(1162,1,{},lQe),l.c=-2,l.e=G7,l.f=G7,O(Wi,"BasicExtendedMetaData/EStructuralFeatureExtendedMetaDataImpl",1162),M(585,622,Zo,xj),l.aj=function(){return this.c},l.Fk=function(){return!1},l.li=function(t,n){return n},l.c=0,O(Wi,"EDataTypeEList",585);var ZAe=ss(Wi,"FeatureMap");M(75,585,{3:1,4:1,20:1,28:1,52:1,14:1,15:1,54:1,67:1,63:1,58:1,76:1,153:1,215:1,1937:1,69:1,95:1},ds),l.Vc=function(t,n){Cgn(this,t,u(n,72))},l.Fc=function(t){return V0n(this,u(t,72))},l.Yh=function(t){DZt(this,u(t,72))},l.cj=function(t,n){return hYt(this,u(t,72),n)},l.dj=function(t,n){return Ybe(this,u(t,72),n)},l.ii=function(t,n){return K2n(this,t,n)},l.li=function(t,n){return Swn(this,t,u(n,72))},l._c=function(t,n){return bpn(this,t,u(n,72))},l.jj=function(t,n){return fYt(this,u(t,72),n)},l.kj=function(t,n){return pWe(this,u(t,72),n)},l.lj=function(t,n,r){return bhn(this,u(t,72),u(n,72),r)},l.oi=function(t,n){return Tse(this,t,u(n,72))},l.dl=function(t,n){return M5e(this,t,n)},l.Wc=function(t,n){var r,s,o,h,d,v,x,_,L;for(_=new jv(n.gc()),o=n.Kc();o.Ob();)if(s=u(o.Pb(),72),h=s.ak(),G0(this.e,h))(!h.hi()||!v$(this,h,s.dd())&&!u7(_,s))&&Br(_,s);else{for(L=pu(this.e.Tg(),h),r=u(this.g,119),d=!0,v=0;v=0;)if(n=t[this.c],this.k.rl(n.ak()))return this.j=this.f?n:n.dd(),this.i=-2,!0;return this.i=-1,this.g=-1,!1},O(Wi,"BasicFeatureMap/FeatureEIterator",410),M(662,410,r0,Gte),l.Lk=function(){return!0},O(Wi,"BasicFeatureMap/ResolvingFeatureEIterator",662),M(955,486,yG,RVe),l.Gi=function(){return this},O(Wi,"EContentsEList/1",955),M(956,486,yG,cVe),l.Lk=function(){return!1},O(Wi,"EContentsEList/2",956),M(954,279,kG,FVe),l.Nk=function(t){},l.Ob=function(){return!1},l.Sb=function(){return!1},O(Wi,"EContentsEList/FeatureIteratorImpl/1",954),M(825,585,Zo,ebe),l.ci=function(){this.a=!0},l.fj=function(){return this.a},l.Xj=function(){var t;_r(this),Ll(this.e)?(t=this.a,this.a=!1,_i(this.e,new xf(this.e,2,this.c,t,!1))):this.a=!1},l.a=!1,O(Wi,"EDataTypeEList/Unsettable",825),M(1849,585,Zo,UVe),l.hi=function(){return!0},O(Wi,"EDataTypeUniqueEList",1849),M(1850,825,Zo,WVe),l.hi=function(){return!0},O(Wi,"EDataTypeUniqueEList/Unsettable",1850),M(139,85,Zo,qu),l.Ek=function(){return!0},l.li=function(t,n){return rk(this,t,u(n,56))},O(Wi,"EObjectContainmentEList/Resolving",139),M(1163,545,Zo,VVe),l.Ek=function(){return!0},l.li=function(t,n){return rk(this,t,u(n,56))},O(Wi,"EObjectContainmentEList/Unsettable/Resolving",1163),M(748,16,Zo,zbe),l.ci=function(){this.a=!0},l.fj=function(){return this.a},l.Xj=function(){var t;_r(this),Ll(this.e)?(t=this.a,this.a=!1,_i(this.e,new xf(this.e,2,this.c,t,!1))):this.a=!1},l.a=!1,O(Wi,"EObjectContainmentWithInverseEList/Unsettable",748),M(1173,748,Zo,nWe),l.Ek=function(){return!0},l.li=function(t,n){return rk(this,t,u(n,56))},O(Wi,"EObjectContainmentWithInverseEList/Unsettable/Resolving",1173),M(743,496,Zo,J2e),l.ci=function(){this.a=!0},l.fj=function(){return this.a},l.Xj=function(){var t;_r(this),Ll(this.e)?(t=this.a,this.a=!1,_i(this.e,new xf(this.e,2,this.c,t,!1))):this.a=!1},l.a=!1,O(Wi,"EObjectEList/Unsettable",743),M(328,496,Zo,$3),l.Ek=function(){return!0},l.li=function(t,n){return rk(this,t,u(n,56))},O(Wi,"EObjectResolvingEList",328),M(1641,743,Zo,KVe),l.Ek=function(){return!0},l.li=function(t,n){return rk(this,t,u(n,56))},O(Wi,"EObjectResolvingEList/Unsettable",1641),M(1381,1,{},gJ);var w4t;O(Wi,"EObjectValidator",1381),M(546,496,Zo,Hj),l.zk=function(){return this.d},l.Ak=function(){return this.b},l.bj=function(){return!0},l.Dk=function(){return!0},l.b=0,O(Wi,"EObjectWithInverseEList",546),M(1176,546,Zo,rWe),l.Ck=function(){return!0},O(Wi,"EObjectWithInverseEList/ManyInverse",1176),M(625,546,Zo,une),l.ci=function(){this.a=!0},l.fj=function(){return this.a},l.Xj=function(){var t;_r(this),Ll(this.e)?(t=this.a,this.a=!1,_i(this.e,new xf(this.e,2,this.c,t,!1))):this.a=!1},l.a=!1,O(Wi,"EObjectWithInverseEList/Unsettable",625),M(1175,625,Zo,iWe),l.Ck=function(){return!0},O(Wi,"EObjectWithInverseEList/Unsettable/ManyInverse",1175),M(749,546,Zo,Gbe),l.Ek=function(){return!0},l.li=function(t,n){return rk(this,t,u(n,56))},O(Wi,"EObjectWithInverseResolvingEList",749),M(31,749,Zo,wn),l.Ck=function(){return!0},O(Wi,"EObjectWithInverseResolvingEList/ManyInverse",31),M(750,625,Zo,qbe),l.Ek=function(){return!0},l.li=function(t,n){return rk(this,t,u(n,56))},O(Wi,"EObjectWithInverseResolvingEList/Unsettable",750),M(1174,750,Zo,sWe),l.Ck=function(){return!0},O(Wi,"EObjectWithInverseResolvingEList/Unsettable/ManyInverse",1174),M(1164,622,Zo),l.ai=function(){return(this.b&1792)==0},l.ci=function(){this.b|=1},l.Bk=function(){return(this.b&4)!=0},l.bj=function(){return(this.b&40)!=0},l.Ck=function(){return(this.b&16)!=0},l.Dk=function(){return(this.b&8)!=0},l.Ek=function(){return(this.b&ky)!=0},l.rk=function(){return(this.b&32)!=0},l.Fk=function(){return(this.b&Sf)!=0},l.wj=function(t){return this.d?$Qe(this.d,t):this.ak().Yj().wj(t)},l.fj=function(){return this.b&2?(this.b&1)!=0:this.i!=0},l.hi=function(){return(this.b&128)!=0},l.Xj=function(){var t;_r(this),this.b&2&&(Ll(this.e)?(t=(this.b&1)!=0,this.b&=-2,Vx(this,new xf(this.e,2,Ji(this.e.Tg(),this.ak()),t,!1))):this.b&=-2)},l.ni=function(){return(this.b&1536)==0},l.b=0,O(Wi,"EcoreEList/Generic",1164),M(1165,1164,Zo,YYe),l.ak=function(){return this.a},O(Wi,"EcoreEList/Dynamic",1165),M(747,63,Od,rpe),l.ri=function(t){return TD(this.a.a,t)},O(Wi,"EcoreEMap/1",747),M(746,85,Zo,zve),l.bi=function(t,n){RH(this.b,u(n,133))},l.di=function(t,n){Rtt(this.b)},l.ei=function(t,n,r){var s;++(s=this.b,u(n,133),s).e},l.fi=function(t,n){Oie(this.b,u(n,133))},l.gi=function(t,n,r){Oie(this.b,u(r,133)),je(r)===je(n)&&u(r,133).Th(yWt(u(n,133).cd())),RH(this.b,u(n,133))},O(Wi,"EcoreEMap/DelegateEObjectContainmentEList",746),M(1171,151,b8e,Xet),O(Wi,"EcoreEMap/Unsettable",1171),M(1172,746,Zo,aWe),l.ci=function(){this.a=!0},l.fj=function(){return this.a},l.Xj=function(){var t;_r(this),Ll(this.e)?(t=this.a,this.a=!1,_i(this.e,new xf(this.e,2,this.c,t,!1))):this.a=!1},l.a=!1,O(Wi,"EcoreEMap/Unsettable/UnsettableDelegateEObjectContainmentEList",1172),M(1168,228,y4,ZKe),l.a=!1,l.b=!1,O(Wi,"EcoreUtil/Copier",1168),M(745,1,ga,_Qe),l.Nb=function(t){La(this,t)},l.Ob=function(){return Ert(this)},l.Pb=function(){var t;return Ert(this),t=this.b,this.b=null,t},l.Qb=function(){this.a.Qb()},O(Wi,"EcoreUtil/ProperContentIterator",745),M(1382,1381,{},FR);var m4t;O(Wi,"EcoreValidator",1382);var y4t;ss(Wi,"FeatureMapUtil/Validator"),M(1260,1,{1942:1},pJ),l.rl=function(t){return!0},O(Wi,"FeatureMapUtil/1",1260),M(757,1,{1942:1},s6e),l.rl=function(t){var n;return this.c==t?!0:(n=Mt(er(this.a,t)),n==null?h2n(this,t)?(OZe(this.a,t,(Mn(),U7)),!0):(OZe(this.a,t,(Mn(),Sb)),!1):n==(Mn(),U7))},l.e=!1;var Cfe;O(Wi,"FeatureMapUtil/BasicValidator",757),M(758,43,y4,Y2e),O(Wi,"FeatureMapUtil/BasicValidator/Cache",758),M(501,52,{20:1,28:1,52:1,14:1,15:1,58:1,76:1,69:1,95:1},DM),l.Vc=function(t,n){Zot(this.c,this.b,t,n)},l.Fc=function(t){return M5e(this.c,this.b,t)},l.Wc=function(t,n){return Cvn(this.c,this.b,t,n)},l.Gc=function(t){return t_(this,t)},l.Xh=function(t,n){Wrn(this.c,this.b,t,n)},l.lk=function(t,n){return T5e(this.c,this.b,t,n)},l.pi=function(t){return bz(this.c,this.b,t,!1)},l.Zh=function(){return mVe(this.c,this.b)},l.$h=function(){return oWt(this.c,this.b)},l._h=function(t){return Znn(this.c,this.b,t)},l.mk=function(t,n){return FUe(this,t,n)},l.$b=function(){d6(this)},l.Hc=function(t){return v$(this.c,this.b,t)},l.Ic=function(t){return Qin(this.c,this.b,t)},l.Xb=function(t){return bz(this.c,this.b,t,!0)},l.Wj=function(t){return this},l.Xc=function(t){return unn(this.c,this.b,t)},l.dc=function(){return YF(this)},l.fj=function(){return!qD(this.c,this.b)},l.Kc=function(){return Prn(this.c,this.b)},l.Yc=function(){return Brn(this.c,this.b)},l.Zc=function(t){return Kan(this.c,this.b,t)},l.ii=function(t,n){return but(this.c,this.b,t,n)},l.ji=function(t,n){Unn(this.c,this.b,t,n)},l.$c=function(t){return Yst(this.c,this.b,t)},l.Mc=function(t){return I2n(this.c,this.b,t)},l._c=function(t,n){return xut(this.c,this.b,t,n)},l.Wb=function(t){JH(this.c,this.b),t_(this,u(t,15))},l.gc=function(){return oon(this.c,this.b)},l.Pc=function(){return atn(this.c,this.b)},l.Qc=function(t){return lnn(this.c,this.b,t)},l.Ib=function(){var t,n;for(n=new bg,n.a+="[",t=mVe(this.c,this.b);Eie(t);)To(n,r_(PH(t))),Eie(t)&&(n.a+=io);return n.a+="]",n.a},l.Xj=function(){JH(this.c,this.b)},O(Wi,"FeatureMapUtil/FeatureEList",501),M(627,36,XI,_re),l.yi=function(t){return z_(this,t)},l.Di=function(t){var n,r,s,o,h,d,v;switch(this.d){case 1:case 2:{if(h=t.Ai(),je(h)===je(this.c)&&z_(this,null)==t.yi(null))return this.g=t.zi(),t.xi()==1&&(this.d=1),!0;break}case 3:{switch(o=t.xi(),o){case 3:{if(h=t.Ai(),je(h)===je(this.c)&&z_(this,null)==t.yi(null))return this.d=5,n=new jv(2),Br(n,this.g),Br(n,t.zi()),this.g=n,!0;break}}break}case 5:{switch(o=t.xi(),o){case 3:{if(h=t.Ai(),je(h)===je(this.c)&&z_(this,null)==t.yi(null))return r=u(this.g,14),r.Fc(t.zi()),!0;break}}break}case 4:{switch(o=t.xi(),o){case 3:{if(h=t.Ai(),je(h)===je(this.c)&&z_(this,null)==t.yi(null))return this.d=1,this.g=t.zi(),!0;break}case 4:{if(h=t.Ai(),je(h)===je(this.c)&&z_(this,null)==t.yi(null))return this.d=6,v=new jv(2),Br(v,this.n),Br(v,t.Bi()),this.n=v,d=ie(re(Lr,1),Jr,25,15,[this.o,t.Ci()]),this.g=d,!0;break}}break}case 6:{switch(o=t.xi(),o){case 4:{if(h=t.Ai(),je(h)===je(this.c)&&z_(this,null)==t.yi(null))return r=u(this.n,14),r.Fc(t.Bi()),d=u(this.g,48),s=Me(Lr,Jr,25,d.length+1,15,1),Hc(d,0,s,0,d.length),s[d.length]=t.Ci(),this.g=s,!0;break}}break}}return!1},O(Wi,"FeatureMapUtil/FeatureENotificationImpl",627),M(552,501,{20:1,28:1,52:1,14:1,15:1,58:1,76:1,153:1,215:1,1937:1,69:1,95:1},Cj),l.dl=function(t,n){return M5e(this.c,t,n)},l.el=function(t,n,r){return T5e(this.c,t,n,r)},l.fl=function(t,n,r){return W5e(this.c,t,n,r)},l.gl=function(){return this},l.hl=function(t,n){return kI(this.c,t,n)},l.il=function(t){return u(bz(this.c,this.b,t,!1),72).ak()},l.jl=function(t){return u(bz(this.c,this.b,t,!1),72).dd()},l.kl=function(){return this.a},l.ll=function(t){return!qD(this.c,t)},l.ml=function(t,n){vz(this.c,t,n)},l.nl=function(t){return rtt(this.c,t)},l.ol=function(t){Sit(this.c,t)},O(Wi,"FeatureMapUtil/FeatureFeatureMap",552),M(1259,1,Qce,Wqe),l.Wj=function(t){return bz(this.b,this.a,-1,t)},l.fj=function(){return!qD(this.b,this.a)},l.Wb=function(t){vz(this.b,this.a,t)},l.Xj=function(){JH(this.b,this.a)},O(Wi,"FeatureMapUtil/FeatureValue",1259);var zk,Sfe,Afe,Gk,k4t,hN=ss(LG,"AnyType");M(666,60,q0,nte),O(LG,"InvalidDatatypeValueException",666);var rU=ss(LG,Kdt),fN=ss(LG,Ydt),JAe=ss(LG,Xdt),x4t,Sc,eLe,zb,E4t,T4t,_4t,C4t,S4t,A4t,L4t,M4t,D4t,I4t,O4t,r5,N4t,i5,QS,P4t,Pw,dN,gN,B4t,ZS,JS;M(830,506,{105:1,92:1,90:1,56:1,49:1,97:1,843:1},Tpe),l._g=function(t,n,r){switch(t){case 0:return r?(!this.c&&(this.c=new ds(this,0)),this.c):(!this.c&&(this.c=new ds(this,0)),this.c.b);case 1:return r?(!this.c&&(this.c=new ds(this,0)),u(Wc(this.c,(Fi(),zb)),153)):(!this.c&&(this.c=new ds(this,0)),u(u(Wc(this.c,(Fi(),zb)),153),215)).kl();case 2:return r?(!this.b&&(this.b=new ds(this,2)),this.b):(!this.b&&(this.b=new ds(this,2)),this.b.b)}return ph(this,t-Jn(this.zh()),gn(this.j&2?(!this.k&&(this.k=new ch),this.k).ck():this.zh(),t),n,r)},l.jh=function(t,n,r){var s;switch(n){case 0:return!this.c&&(this.c=new ds(this,0)),vI(this.c,t,r);case 1:return(!this.c&&(this.c=new ds(this,0)),u(u(Wc(this.c,(Fi(),zb)),153),69)).mk(t,r);case 2:return!this.b&&(this.b=new ds(this,2)),vI(this.b,t,r)}return s=u(gn(this.j&2?(!this.k&&(this.k=new ch),this.k).ck():this.zh(),n),66),s.Nj().Rj(this,vme(this),n-Jn(this.zh()),t,r)},l.lh=function(t){switch(t){case 0:return!!this.c&&this.c.i!=0;case 1:return!(!this.c&&(this.c=new ds(this,0)),u(Wc(this.c,(Fi(),zb)),153)).dc();case 2:return!!this.b&&this.b.i!=0}return dh(this,t-Jn(this.zh()),gn(this.j&2?(!this.k&&(this.k=new ch),this.k).ck():this.zh(),t))},l.sh=function(t,n){switch(t){case 0:!this.c&&(this.c=new ds(this,0)),XM(this.c,n);return;case 1:(!this.c&&(this.c=new ds(this,0)),u(u(Wc(this.c,(Fi(),zb)),153),215)).Wb(n);return;case 2:!this.b&&(this.b=new ds(this,2)),XM(this.b,n);return}yh(this,t-Jn(this.zh()),gn(this.j&2?(!this.k&&(this.k=new ch),this.k).ck():this.zh(),t),n)},l.zh=function(){return Fi(),eLe},l.Bh=function(t){switch(t){case 0:!this.c&&(this.c=new ds(this,0)),_r(this.c);return;case 1:(!this.c&&(this.c=new ds(this,0)),u(Wc(this.c,(Fi(),zb)),153)).$b();return;case 2:!this.b&&(this.b=new ds(this,2)),_r(this.b);return}wh(this,t-Jn(this.zh()),gn(this.j&2?(!this.k&&(this.k=new ch),this.k).ck():this.zh(),t))},l.Ib=function(){var t;return this.j&4?_f(this):(t=new Ph(_f(this)),t.a+=" (mixed: ",QT(t,this.c),t.a+=", anyAttribute: ",QT(t,this.b),t.a+=")",t.a)},O(As,"AnyTypeImpl",830),M(667,506,{105:1,92:1,90:1,56:1,49:1,97:1,2021:1,667:1},fR),l._g=function(t,n,r){switch(t){case 0:return this.a;case 1:return this.b}return ph(this,t-Jn((Fi(),r5)),gn(this.j&2?(!this.k&&(this.k=new ch),this.k).ck():r5,t),n,r)},l.lh=function(t){switch(t){case 0:return this.a!=null;case 1:return this.b!=null}return dh(this,t-Jn((Fi(),r5)),gn(this.j&2?(!this.k&&(this.k=new ch),this.k).ck():r5,t))},l.sh=function(t,n){switch(t){case 0:Aee(this,Hr(n));return;case 1:Jge(this,Hr(n));return}yh(this,t-Jn((Fi(),r5)),gn(this.j&2?(!this.k&&(this.k=new ch),this.k).ck():r5,t),n)},l.zh=function(){return Fi(),r5},l.Bh=function(t){switch(t){case 0:this.a=null;return;case 1:this.b=null;return}wh(this,t-Jn((Fi(),r5)),gn(this.j&2?(!this.k&&(this.k=new ch),this.k).ck():r5,t))},l.Ib=function(){var t;return this.j&4?_f(this):(t=new Ph(_f(this)),t.a+=" (data: ",To(t,this.a),t.a+=", target: ",To(t,this.b),t.a+=")",t.a)},l.a=null,l.b=null,O(As,"ProcessingInstructionImpl",667),M(668,830,{105:1,92:1,90:1,56:1,49:1,97:1,843:1,2022:1,668:1},NHe),l._g=function(t,n,r){switch(t){case 0:return r?(!this.c&&(this.c=new ds(this,0)),this.c):(!this.c&&(this.c=new ds(this,0)),this.c.b);case 1:return r?(!this.c&&(this.c=new ds(this,0)),u(Wc(this.c,(Fi(),zb)),153)):(!this.c&&(this.c=new ds(this,0)),u(u(Wc(this.c,(Fi(),zb)),153),215)).kl();case 2:return r?(!this.b&&(this.b=new ds(this,2)),this.b):(!this.b&&(this.b=new ds(this,2)),this.b.b);case 3:return!this.c&&(this.c=new ds(this,0)),Hr(kI(this.c,(Fi(),QS),!0));case 4:return Vbe(this.a,(!this.c&&(this.c=new ds(this,0)),Hr(kI(this.c,(Fi(),QS),!0))));case 5:return this.a}return ph(this,t-Jn((Fi(),i5)),gn(this.j&2?(!this.k&&(this.k=new ch),this.k).ck():i5,t),n,r)},l.lh=function(t){switch(t){case 0:return!!this.c&&this.c.i!=0;case 1:return!(!this.c&&(this.c=new ds(this,0)),u(Wc(this.c,(Fi(),zb)),153)).dc();case 2:return!!this.b&&this.b.i!=0;case 3:return!this.c&&(this.c=new ds(this,0)),Hr(kI(this.c,(Fi(),QS),!0))!=null;case 4:return Vbe(this.a,(!this.c&&(this.c=new ds(this,0)),Hr(kI(this.c,(Fi(),QS),!0))))!=null;case 5:return!!this.a}return dh(this,t-Jn((Fi(),i5)),gn(this.j&2?(!this.k&&(this.k=new ch),this.k).ck():i5,t))},l.sh=function(t,n){switch(t){case 0:!this.c&&(this.c=new ds(this,0)),XM(this.c,n);return;case 1:(!this.c&&(this.c=new ds(this,0)),u(u(Wc(this.c,(Fi(),zb)),153),215)).Wb(n);return;case 2:!this.b&&(this.b=new ds(this,2)),XM(this.b,n);return;case 3:Mwe(this,Hr(n));return;case 4:Mwe(this,Ube(this.a,n));return;case 5:Ac(this,u(n,148));return}yh(this,t-Jn((Fi(),i5)),gn(this.j&2?(!this.k&&(this.k=new ch),this.k).ck():i5,t),n)},l.zh=function(){return Fi(),i5},l.Bh=function(t){switch(t){case 0:!this.c&&(this.c=new ds(this,0)),_r(this.c);return;case 1:(!this.c&&(this.c=new ds(this,0)),u(Wc(this.c,(Fi(),zb)),153)).$b();return;case 2:!this.b&&(this.b=new ds(this,2)),_r(this.b);return;case 3:!this.c&&(this.c=new ds(this,0)),vz(this.c,(Fi(),QS),null);return;case 4:Mwe(this,Ube(this.a,null));return;case 5:this.a=null;return}wh(this,t-Jn((Fi(),i5)),gn(this.j&2?(!this.k&&(this.k=new ch),this.k).ck():i5,t))},O(As,"SimpleAnyTypeImpl",668),M(669,506,{105:1,92:1,90:1,56:1,49:1,97:1,2023:1,669:1},OHe),l._g=function(t,n,r){switch(t){case 0:return r?(!this.a&&(this.a=new ds(this,0)),this.a):(!this.a&&(this.a=new ds(this,0)),this.a.b);case 1:return r?(!this.b&&(this.b=new Nl((on(),oo),wc,this,1)),this.b):(!this.b&&(this.b=new Nl((on(),oo),wc,this,1)),hD(this.b));case 2:return r?(!this.c&&(this.c=new Nl((on(),oo),wc,this,2)),this.c):(!this.c&&(this.c=new Nl((on(),oo),wc,this,2)),hD(this.c));case 3:return!this.a&&(this.a=new ds(this,0)),Wc(this.a,(Fi(),dN));case 4:return!this.a&&(this.a=new ds(this,0)),Wc(this.a,(Fi(),gN));case 5:return!this.a&&(this.a=new ds(this,0)),Wc(this.a,(Fi(),ZS));case 6:return!this.a&&(this.a=new ds(this,0)),Wc(this.a,(Fi(),JS))}return ph(this,t-Jn((Fi(),Pw)),gn(this.j&2?(!this.k&&(this.k=new ch),this.k).ck():Pw,t),n,r)},l.jh=function(t,n,r){var s;switch(n){case 0:return!this.a&&(this.a=new ds(this,0)),vI(this.a,t,r);case 1:return!this.b&&(this.b=new Nl((on(),oo),wc,this,1)),vj(this.b,t,r);case 2:return!this.c&&(this.c=new Nl((on(),oo),wc,this,2)),vj(this.c,t,r);case 5:return!this.a&&(this.a=new ds(this,0)),FUe(Wc(this.a,(Fi(),ZS)),t,r)}return s=u(gn(this.j&2?(!this.k&&(this.k=new ch),this.k).ck():(Fi(),Pw),n),66),s.Nj().Rj(this,vme(this),n-Jn((Fi(),Pw)),t,r)},l.lh=function(t){switch(t){case 0:return!!this.a&&this.a.i!=0;case 1:return!!this.b&&this.b.f!=0;case 2:return!!this.c&&this.c.f!=0;case 3:return!this.a&&(this.a=new ds(this,0)),!YF(Wc(this.a,(Fi(),dN)));case 4:return!this.a&&(this.a=new ds(this,0)),!YF(Wc(this.a,(Fi(),gN)));case 5:return!this.a&&(this.a=new ds(this,0)),!YF(Wc(this.a,(Fi(),ZS)));case 6:return!this.a&&(this.a=new ds(this,0)),!YF(Wc(this.a,(Fi(),JS)))}return dh(this,t-Jn((Fi(),Pw)),gn(this.j&2?(!this.k&&(this.k=new ch),this.k).ck():Pw,t))},l.sh=function(t,n){switch(t){case 0:!this.a&&(this.a=new ds(this,0)),XM(this.a,n);return;case 1:!this.b&&(this.b=new Nl((on(),oo),wc,this,1)),sH(this.b,n);return;case 2:!this.c&&(this.c=new Nl((on(),oo),wc,this,2)),sH(this.c,n);return;case 3:!this.a&&(this.a=new ds(this,0)),d6(Wc(this.a,(Fi(),dN))),!this.a&&(this.a=new ds(this,0)),t_(Wc(this.a,dN),u(n,14));return;case 4:!this.a&&(this.a=new ds(this,0)),d6(Wc(this.a,(Fi(),gN))),!this.a&&(this.a=new ds(this,0)),t_(Wc(this.a,gN),u(n,14));return;case 5:!this.a&&(this.a=new ds(this,0)),d6(Wc(this.a,(Fi(),ZS))),!this.a&&(this.a=new ds(this,0)),t_(Wc(this.a,ZS),u(n,14));return;case 6:!this.a&&(this.a=new ds(this,0)),d6(Wc(this.a,(Fi(),JS))),!this.a&&(this.a=new ds(this,0)),t_(Wc(this.a,JS),u(n,14));return}yh(this,t-Jn((Fi(),Pw)),gn(this.j&2?(!this.k&&(this.k=new ch),this.k).ck():Pw,t),n)},l.zh=function(){return Fi(),Pw},l.Bh=function(t){switch(t){case 0:!this.a&&(this.a=new ds(this,0)),_r(this.a);return;case 1:!this.b&&(this.b=new Nl((on(),oo),wc,this,1)),this.b.c.$b();return;case 2:!this.c&&(this.c=new Nl((on(),oo),wc,this,2)),this.c.c.$b();return;case 3:!this.a&&(this.a=new ds(this,0)),d6(Wc(this.a,(Fi(),dN)));return;case 4:!this.a&&(this.a=new ds(this,0)),d6(Wc(this.a,(Fi(),gN)));return;case 5:!this.a&&(this.a=new ds(this,0)),d6(Wc(this.a,(Fi(),ZS)));return;case 6:!this.a&&(this.a=new ds(this,0)),d6(Wc(this.a,(Fi(),JS)));return}wh(this,t-Jn((Fi(),Pw)),gn(this.j&2?(!this.k&&(this.k=new ch),this.k).ck():Pw,t))},l.Ib=function(){var t;return this.j&4?_f(this):(t=new Ph(_f(this)),t.a+=" (mixed: ",QT(t,this.a),t.a+=")",t.a)},O(As,"XMLTypeDocumentRootImpl",669),M(1919,704,{105:1,92:1,90:1,471:1,147:1,56:1,108:1,49:1,97:1,150:1,114:1,115:1,2024:1},bm),l.Ih=function(t,n){switch(t.yj()){case 7:case 8:case 9:case 10:case 16:case 22:case 23:case 24:case 25:case 26:case 32:case 33:case 34:case 36:case 37:case 44:case 45:case 50:case 51:case 53:case 55:case 56:case 57:case 58:case 60:case 61:case 4:return n==null?null:Qo(n);case 19:case 28:case 29:case 35:case 38:case 39:case 41:case 46:case 52:case 54:case 5:return Hr(n);case 6:return _Kt(u(n,190));case 12:case 47:case 49:case 11:return ult(this,t,n);case 13:return n==null?null:fvn(u(n,240));case 15:case 14:return n==null?null:xZt(Ue(ft(n)));case 17:return fst((Fi(),n));case 18:return fst(n);case 21:case 20:return n==null?null:EZt(u(n,155).a);case 27:return CKt(u(n,190));case 30:return Ait((Fi(),u(n,15)));case 31:return Ait(u(n,15));case 40:return AKt((Fi(),n));case 42:return dst((Fi(),n));case 43:return dst(n);case 59:case 48:return SKt((Fi(),n));default:throw J(new Ln($7+t.ne()+dw))}},l.Jh=function(t){var n,r,s,o,h;switch(t.G==-1&&(t.G=(r=Gl(t),r?Dg(r.Mh(),t):-1)),t.G){case 0:return n=new Tpe,n;case 1:return s=new fR,s;case 2:return o=new NHe,o;case 3:return h=new OHe,h;default:throw J(new Ln(Pce+t.zb+dw))}},l.Kh=function(t,n){var r,s,o,h,d,v,x,_,L,P,z,q,W,X,le,Ce;switch(t.yj()){case 5:case 52:case 4:return n;case 6:return zcn(n);case 8:case 7:return n==null?null:Lhn(n);case 9:return n==null?null:xD(Wl((s=Xc(n,!0),s.length>0&&(zr(0,s.length),s.charCodeAt(0)==43)?s.substr(1):s),-128,127)<<24>>24);case 10:return n==null?null:xD(Wl((o=Xc(n,!0),o.length>0&&(zr(0,o.length),o.charCodeAt(0)==43)?o.substr(1):o),-128,127)<<24>>24);case 11:return Hr(aw(this,(Fi(),_4t),n));case 12:return Hr(aw(this,(Fi(),C4t),n));case 13:return n==null?null:new Vpe(Xc(n,!0));case 15:case 14:return X0n(n);case 16:return Hr(aw(this,(Fi(),S4t),n));case 17:return Nrt((Fi(),n));case 18:return Nrt(n);case 28:case 29:case 35:case 38:case 39:case 41:case 54:case 19:return Xc(n,!0);case 21:case 20:return sgn(n);case 22:return Hr(aw(this,(Fi(),A4t),n));case 23:return Hr(aw(this,(Fi(),L4t),n));case 24:return Hr(aw(this,(Fi(),M4t),n));case 25:return Hr(aw(this,(Fi(),D4t),n));case 26:return Hr(aw(this,(Fi(),I4t),n));case 27:return Rcn(n);case 30:return Prt((Fi(),n));case 31:return Prt(n);case 32:return n==null?null:ct(Wl((L=Xc(n,!0),L.length>0&&(zr(0,L.length),L.charCodeAt(0)==43)?L.substr(1):L),$a,Ei));case 33:return n==null?null:new Ip((P=Xc(n,!0),P.length>0&&(zr(0,P.length),P.charCodeAt(0)==43)?P.substr(1):P));case 34:return n==null?null:ct(Wl((z=Xc(n,!0),z.length>0&&(zr(0,z.length),z.charCodeAt(0)==43)?z.substr(1):z),$a,Ei));case 36:return n==null?null:lb(xz((q=Xc(n,!0),q.length>0&&(zr(0,q.length),q.charCodeAt(0)==43)?q.substr(1):q)));case 37:return n==null?null:lb(xz((W=Xc(n,!0),W.length>0&&(zr(0,W.length),W.charCodeAt(0)==43)?W.substr(1):W)));case 40:return Jon((Fi(),n));case 42:return Brt((Fi(),n));case 43:return Brt(n);case 44:return n==null?null:new Ip((X=Xc(n,!0),X.length>0&&(zr(0,X.length),X.charCodeAt(0)==43)?X.substr(1):X));case 45:return n==null?null:new Ip((le=Xc(n,!0),le.length>0&&(zr(0,le.length),le.charCodeAt(0)==43)?le.substr(1):le));case 46:return Xc(n,!1);case 47:return Hr(aw(this,(Fi(),O4t),n));case 59:case 48:return Zon((Fi(),n));case 49:return Hr(aw(this,(Fi(),N4t),n));case 50:return n==null?null:Z8(Wl((Ce=Xc(n,!0),Ce.length>0&&(zr(0,Ce.length),Ce.charCodeAt(0)==43)?Ce.substr(1):Ce),_G,32767)<<16>>16);case 51:return n==null?null:Z8(Wl((h=Xc(n,!0),h.length>0&&(zr(0,h.length),h.charCodeAt(0)==43)?h.substr(1):h),_G,32767)<<16>>16);case 53:return Hr(aw(this,(Fi(),P4t),n));case 55:return n==null?null:Z8(Wl((d=Xc(n,!0),d.length>0&&(zr(0,d.length),d.charCodeAt(0)==43)?d.substr(1):d),_G,32767)<<16>>16);case 56:return n==null?null:Z8(Wl((v=Xc(n,!0),v.length>0&&(zr(0,v.length),v.charCodeAt(0)==43)?v.substr(1):v),_G,32767)<<16>>16);case 57:return n==null?null:lb(xz((x=Xc(n,!0),x.length>0&&(zr(0,x.length),x.charCodeAt(0)==43)?x.substr(1):x)));case 58:return n==null?null:lb(xz((_=Xc(n,!0),_.length>0&&(zr(0,_.length),_.charCodeAt(0)==43)?_.substr(1):_)));case 60:return n==null?null:ct(Wl((r=Xc(n,!0),r.length>0&&(zr(0,r.length),r.charCodeAt(0)==43)?r.substr(1):r),$a,Ei));case 61:return n==null?null:ct(Wl(Xc(n,!0),$a,Ei));default:throw J(new Ln($7+t.ne()+dw))}};var R4t,tLe,F4t,nLe;O(As,"XMLTypeFactoryImpl",1919),M(586,179,{105:1,92:1,90:1,147:1,191:1,56:1,235:1,108:1,49:1,97:1,150:1,179:1,114:1,115:1,675:1,1945:1,586:1},mYe),l.N=!1,l.O=!1;var j4t=!1;O(As,"XMLTypePackageImpl",586),M(1852,1,{837:1},e6),l._j=function(){return F5e(),K4t},O(As,"XMLTypePackageImpl/1",1852),M(1861,1,li,w1),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/10",1861),M(1862,1,li,dR),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/11",1862),M(1863,1,li,gR),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/12",1863),M(1864,1,li,pR),l.wj=function(t){return Sm(t)},l.xj=function(t){return Me(ma,Qe,333,t,7,1)},O(As,"XMLTypePackageImpl/13",1864),M(1865,1,li,bR),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/14",1865),M(1866,1,li,vR),l.wj=function(t){return we(t,15)},l.xj=function(t){return Me(Eh,gy,15,t,0,1)},O(As,"XMLTypePackageImpl/15",1866),M(1867,1,li,wR),l.wj=function(t){return we(t,15)},l.xj=function(t){return Me(Eh,gy,15,t,0,1)},O(As,"XMLTypePackageImpl/16",1867),M(1868,1,li,Wf),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/17",1868),M(1869,1,li,xu),l.wj=function(t){return we(t,155)},l.xj=function(t){return Me(W7,Qe,155,t,0,1)},O(As,"XMLTypePackageImpl/18",1869),M(1870,1,li,bJ),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/19",1870),M(1853,1,li,vJ),l.wj=function(t){return we(t,843)},l.xj=function(t){return Me(hN,yt,843,t,0,1)},O(As,"XMLTypePackageImpl/2",1853),M(1871,1,li,wJ),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/20",1871),M(1872,1,li,Eu),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/21",1872),M(1873,1,li,Y9),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/22",1873),M(1874,1,li,mR),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/23",1874),M(1875,1,li,yR),l.wj=function(t){return we(t,190)},l.xj=function(t){return Me(el,Qe,190,t,0,2)},O(As,"XMLTypePackageImpl/24",1875),M(1876,1,li,t6),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/25",1876),M(1877,1,li,mJ),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/26",1877),M(1878,1,li,Lx),l.wj=function(t){return we(t,15)},l.xj=function(t){return Me(Eh,gy,15,t,0,1)},O(As,"XMLTypePackageImpl/27",1878),M(1879,1,li,yJ),l.wj=function(t){return we(t,15)},l.xj=function(t){return Me(Eh,gy,15,t,0,1)},O(As,"XMLTypePackageImpl/28",1879),M(1880,1,li,kR),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/29",1880),M(1854,1,li,kJ),l.wj=function(t){return we(t,667)},l.xj=function(t){return Me(rU,yt,2021,t,0,1)},O(As,"XMLTypePackageImpl/3",1854),M(1881,1,li,xJ),l.wj=function(t){return we(t,19)},l.xj=function(t){return Me(Za,Qe,19,t,0,1)},O(As,"XMLTypePackageImpl/30",1881),M(1882,1,li,X9),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/31",1882),M(1883,1,li,xR),l.wj=function(t){return we(t,162)},l.xj=function(t){return Me(pw,Qe,162,t,0,1)},O(As,"XMLTypePackageImpl/32",1883),M(1884,1,li,$L),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/33",1884),M(1885,1,li,Q9),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/34",1885),M(1886,1,li,EJ),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/35",1886),M(1887,1,li,TJ),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/36",1887),M(1888,1,li,HL),l.wj=function(t){return we(t,15)},l.xj=function(t){return Me(Eh,gy,15,t,0,1)},O(As,"XMLTypePackageImpl/37",1888),M(1889,1,li,Z9),l.wj=function(t){return we(t,15)},l.xj=function(t){return Me(Eh,gy,15,t,0,1)},O(As,"XMLTypePackageImpl/38",1889),M(1890,1,li,m1),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/39",1890),M(1855,1,li,Mx),l.wj=function(t){return we(t,668)},l.xj=function(t){return Me(fN,yt,2022,t,0,1)},O(As,"XMLTypePackageImpl/4",1855),M(1891,1,li,_J),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/40",1891),M(1892,1,li,Dx),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/41",1892),M(1893,1,li,zL),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/42",1893),M(1894,1,li,j2),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/43",1894),M(1895,1,li,J9),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/44",1895),M(1896,1,li,GL),l.wj=function(t){return we(t,184)},l.xj=function(t){return Me(bw,Qe,184,t,0,1)},O(As,"XMLTypePackageImpl/45",1896),M(1897,1,li,Kf),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/46",1897),M(1898,1,li,eT),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/47",1898),M(1899,1,li,y1),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/48",1899),M(e2,1,li,k1),l.wj=function(t){return we(t,184)},l.xj=function(t){return Me(bw,Qe,184,t,0,1)},O(As,"XMLTypePackageImpl/49",e2),M(1856,1,li,CJ),l.wj=function(t){return we(t,669)},l.xj=function(t){return Me(JAe,yt,2023,t,0,1)},O(As,"XMLTypePackageImpl/5",1856),M(1901,1,li,SJ),l.wj=function(t){return we(t,162)},l.xj=function(t){return Me(pw,Qe,162,t,0,1)},O(As,"XMLTypePackageImpl/50",1901),M(1902,1,li,x3),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/51",1902),M(1903,1,li,Ix),l.wj=function(t){return we(t,19)},l.xj=function(t){return Me(Za,Qe,19,t,0,1)},O(As,"XMLTypePackageImpl/52",1903),M(1857,1,li,Ox),l.wj=function(t){return fa(t)},l.xj=function(t){return Me(mt,Qe,2,t,6,1)},O(As,"XMLTypePackageImpl/6",1857),M(1858,1,li,tT),l.wj=function(t){return we(t,190)},l.xj=function(t){return Me(el,Qe,190,t,0,2)},O(As,"XMLTypePackageImpl/7",1858),M(1859,1,li,AJ),l.wj=function(t){return Cm(t)},l.xj=function(t){return Me(Us,Qe,476,t,8,1)},O(As,"XMLTypePackageImpl/8",1859),M(1860,1,li,n6),l.wj=function(t){return we(t,217)},l.xj=function(t){return Me(mk,Qe,217,t,0,1)},O(As,"XMLTypePackageImpl/9",1860);var J1,Zg,eA,iU,fe;M(50,60,q0,$r),O($g,"RegEx/ParseException",50),M(820,1,{},qL),l.sl=function(t){return tr*16)throw J(new $r(Ur((jr(),odt))));r=r*16+o}while(!0);if(this.a!=125)throw J(new $r(Ur((jr(),cdt))));if(r>q7)throw J(new $r(Ur((jr(),udt))));t=r}else{if(o=0,this.c!=0||(o=fb(this.a))<0)throw J(new $r(Ur((jr(),jg))));if(r=o,mi(this),this.c!=0||(o=fb(this.a))<0)throw J(new $r(Ur((jr(),jg))));r=r*16+o,t=r}break;case 117:if(s=0,mi(this),this.c!=0||(s=fb(this.a))<0)throw J(new $r(Ur((jr(),jg))));if(n=s,mi(this),this.c!=0||(s=fb(this.a))<0)throw J(new $r(Ur((jr(),jg))));if(n=n*16+s,mi(this),this.c!=0||(s=fb(this.a))<0)throw J(new $r(Ur((jr(),jg))));if(n=n*16+s,mi(this),this.c!=0||(s=fb(this.a))<0)throw J(new $r(Ur((jr(),jg))));n=n*16+s,t=n;break;case 118:if(mi(this),this.c!=0||(s=fb(this.a))<0)throw J(new $r(Ur((jr(),jg))));if(n=s,mi(this),this.c!=0||(s=fb(this.a))<0)throw J(new $r(Ur((jr(),jg))));if(n=n*16+s,mi(this),this.c!=0||(s=fb(this.a))<0)throw J(new $r(Ur((jr(),jg))));if(n=n*16+s,mi(this),this.c!=0||(s=fb(this.a))<0)throw J(new $r(Ur((jr(),jg))));if(n=n*16+s,mi(this),this.c!=0||(s=fb(this.a))<0)throw J(new $r(Ur((jr(),jg))));if(n=n*16+s,mi(this),this.c!=0||(s=fb(this.a))<0)throw J(new $r(Ur((jr(),jg))));if(n=n*16+s,n>q7)throw J(new $r(Ur((jr(),"parser.descappe.4"))));t=n;break;case 65:case 90:case 122:throw J(new $r(Ur((jr(),ldt))))}return t},l.ul=function(t){var n,r;switch(t){case 100:r=(this.e&32)==32?Zp("Nd",!0):(yi(),sU);break;case 68:r=(this.e&32)==32?Zp("Nd",!1):(yi(),cLe);break;case 119:r=(this.e&32)==32?Zp("IsWord",!0):(yi(),DE);break;case 87:r=(this.e&32)==32?Zp("IsWord",!1):(yi(),lLe);break;case 115:r=(this.e&32)==32?Zp("IsSpace",!0):(yi(),qk);break;case 83:r=(this.e&32)==32?Zp("IsSpace",!1):(yi(),uLe);break;default:throw J(new tc((n=t,l0t+n.toString(16))))}return r},l.vl=function(t){var n,r,s,o,h,d,v,x,_,L,P,z;for(this.b=1,mi(this),n=null,this.c==0&&this.a==94?(mi(this),t?L=(yi(),yi(),new Hl(5)):(n=(yi(),yi(),new Hl(4)),Yc(n,0,q7),L=new Hl(4))):L=(yi(),yi(),new Hl(4)),o=!0;(z=this.c)!=1&&!(z==0&&this.a==93&&!o);){if(o=!1,r=this.a,s=!1,z==10)switch(r){case 100:case 68:case 119:case 87:case 115:case 83:ly(L,this.ul(r)),s=!0;break;case 105:case 73:case 99:case 67:r=this.Ll(L,r),r<0&&(s=!0);break;case 112:case 80:if(P=$4e(this,r),!P)throw J(new $r(Ur((jr(),Kce))));ly(L,P),s=!0;break;default:r=this.tl()}else if(z==20){if(d=o8(this.i,58,this.d),d<0)throw J(new $r(Ur((jr(),l8e))));if(v=!0,Ma(this.i,this.d)==94&&(++this.d,v=!1),h=jl(this.i,this.d,d),x=yJe(h,v,(this.e&512)==512),!x)throw J(new $r(Ur((jr(),ndt))));if(ly(L,x),s=!0,d+1>=this.j||Ma(this.i,d+1)!=93)throw J(new $r(Ur((jr(),l8e))));this.d=d+2}if(mi(this),!s)if(this.c!=0||this.a!=45)Yc(L,r,r);else{if(mi(this),(z=this.c)==1)throw J(new $r(Ur((jr(),wG))));z==0&&this.a==93?(Yc(L,r,r),Yc(L,45,45)):(_=this.a,z==10&&(_=this.tl()),mi(this),Yc(L,r,_))}(this.e&Sf)==Sf&&this.c==0&&this.a==44&&mi(this)}if(this.c==1)throw J(new $r(Ur((jr(),wG))));return n&&(bC(n,L),L=n),l4(L),gC(L),this.b=0,mi(this),L},l.wl=function(){var t,n,r,s;for(r=this.vl(!1);(s=this.c)!=7;)if(t=this.a,s==0&&(t==45||t==38)||s==4){if(mi(this),this.c!=9)throw J(new $r(Ur((jr(),idt))));if(n=this.vl(!1),s==4)ly(r,n);else if(t==45)bC(r,n);else if(t==38)rlt(r,n);else throw J(new tc("ASSERT"))}else throw J(new $r(Ur((jr(),sdt))));return mi(this),r},l.xl=function(){var t,n;return t=this.a-48,n=(yi(),yi(),new cre(12,null,t)),!this.g&&(this.g=new oF),aF(this.g,new ipe(t)),mi(this),n},l.yl=function(){return mi(this),yi(),z4t},l.zl=function(){return mi(this),yi(),H4t},l.Al=function(){throw J(new $r(Ur((jr(),xh))))},l.Bl=function(){throw J(new $r(Ur((jr(),xh))))},l.Cl=function(){return mi(this),ean()},l.Dl=function(){return mi(this),yi(),q4t},l.El=function(){return mi(this),yi(),U4t},l.Fl=function(){var t;if(this.d>=this.j||((t=Ma(this.i,this.d++))&65504)!=64)throw J(new $r(Ur((jr(),J1t))));return mi(this),yi(),yi(),new Yd(0,t-64)},l.Gl=function(){return mi(this),Rbn()},l.Hl=function(){return mi(this),yi(),W4t},l.Il=function(){var t;return t=(yi(),yi(),new Yd(0,105)),mi(this),t},l.Jl=function(){return mi(this),yi(),V4t},l.Kl=function(){return mi(this),yi(),G4t},l.Ll=function(t,n){return this.tl()},l.Ml=function(){return mi(this),yi(),aLe},l.Nl=function(){var t,n,r,s,o;if(this.d+1>=this.j)throw J(new $r(Ur((jr(),X1t))));if(s=-1,n=null,t=Ma(this.i,this.d),49<=t&&t<=57){if(s=t-48,!this.g&&(this.g=new oF),aF(this.g,new ipe(s)),++this.d,Ma(this.i,this.d)!=41)throw J(new $r(Ur((jr(),Tb))));++this.d}else switch(t==63&&--this.d,mi(this),n=u6e(this),n.e){case 20:case 21:case 22:case 23:break;case 8:if(this.c!=7)throw J(new $r(Ur((jr(),Tb))));break;default:throw J(new $r(Ur((jr(),Q1t))))}if(mi(this),o=Xv(this),r=null,o.e==2){if(o.em()!=2)throw J(new $r(Ur((jr(),Z1t))));r=o.am(1),o=o.am(0)}if(this.c!=7)throw J(new $r(Ur((jr(),Tb))));return mi(this),yi(),yi(),new ZJe(s,n,o,r)},l.Ol=function(){return mi(this),yi(),oLe},l.Pl=function(){var t;if(mi(this),t=zj(24,Xv(this)),this.c!=7)throw J(new $r(Ur((jr(),Tb))));return mi(this),t},l.Ql=function(){var t;if(mi(this),t=zj(20,Xv(this)),this.c!=7)throw J(new $r(Ur((jr(),Tb))));return mi(this),t},l.Rl=function(){var t;if(mi(this),t=zj(22,Xv(this)),this.c!=7)throw J(new $r(Ur((jr(),Tb))));return mi(this),t},l.Sl=function(){var t,n,r,s,o;for(t=0,r=0,n=-1;this.d=this.j)throw J(new $r(Ur((jr(),c8e))));if(n==45){for(++this.d;this.d=this.j)throw J(new $r(Ur((jr(),c8e))))}if(n==58){if(++this.d,mi(this),s=rYe(Xv(this),t,r),this.c!=7)throw J(new $r(Ur((jr(),Tb))));mi(this)}else if(n==41)++this.d,mi(this),s=rYe(Xv(this),t,r);else throw J(new $r(Ur((jr(),Y1t))));return s},l.Tl=function(){var t;if(mi(this),t=zj(21,Xv(this)),this.c!=7)throw J(new $r(Ur((jr(),Tb))));return mi(this),t},l.Ul=function(){var t;if(mi(this),t=zj(23,Xv(this)),this.c!=7)throw J(new $r(Ur((jr(),Tb))));return mi(this),t},l.Vl=function(){var t,n;if(mi(this),t=this.f++,n=Pne(Xv(this),t),this.c!=7)throw J(new $r(Ur((jr(),Tb))));return mi(this),n},l.Wl=function(){var t;if(mi(this),t=Pne(Xv(this),0),this.c!=7)throw J(new $r(Ur((jr(),Tb))));return mi(this),t},l.Xl=function(t){return mi(this),this.c==5?(mi(this),Ij(t,(yi(),yi(),new $m(9,t)))):Ij(t,(yi(),yi(),new $m(3,t)))},l.Yl=function(t){var n;return mi(this),n=(yi(),yi(),new e_(2)),this.c==5?(mi(this),pb(n,nA),pb(n,t)):(pb(n,t),pb(n,nA)),n},l.Zl=function(t){return mi(this),this.c==5?(mi(this),yi(),yi(),new $m(9,t)):(yi(),yi(),new $m(3,t))},l.a=0,l.b=0,l.c=0,l.d=0,l.e=0,l.f=1,l.g=null,l.j=0,O($g,"RegEx/RegexParser",820),M(1824,820,{},PHe),l.sl=function(t){return!1},l.tl=function(){return y5e(this)},l.ul=function(t){return m7(t)},l.vl=function(t){return Ylt(this)},l.wl=function(){throw J(new $r(Ur((jr(),xh))))},l.xl=function(){throw J(new $r(Ur((jr(),xh))))},l.yl=function(){throw J(new $r(Ur((jr(),xh))))},l.zl=function(){throw J(new $r(Ur((jr(),xh))))},l.Al=function(){return mi(this),m7(67)},l.Bl=function(){return mi(this),m7(73)},l.Cl=function(){throw J(new $r(Ur((jr(),xh))))},l.Dl=function(){throw J(new $r(Ur((jr(),xh))))},l.El=function(){throw J(new $r(Ur((jr(),xh))))},l.Fl=function(){return mi(this),m7(99)},l.Gl=function(){throw J(new $r(Ur((jr(),xh))))},l.Hl=function(){throw J(new $r(Ur((jr(),xh))))},l.Il=function(){return mi(this),m7(105)},l.Jl=function(){throw J(new $r(Ur((jr(),xh))))},l.Kl=function(){throw J(new $r(Ur((jr(),xh))))},l.Ll=function(t,n){return ly(t,m7(n)),-1},l.Ml=function(){return mi(this),yi(),yi(),new Yd(0,94)},l.Nl=function(){throw J(new $r(Ur((jr(),xh))))},l.Ol=function(){return mi(this),yi(),yi(),new Yd(0,36)},l.Pl=function(){throw J(new $r(Ur((jr(),xh))))},l.Ql=function(){throw J(new $r(Ur((jr(),xh))))},l.Rl=function(){throw J(new $r(Ur((jr(),xh))))},l.Sl=function(){throw J(new $r(Ur((jr(),xh))))},l.Tl=function(){throw J(new $r(Ur((jr(),xh))))},l.Ul=function(){throw J(new $r(Ur((jr(),xh))))},l.Vl=function(){var t;if(mi(this),t=Pne(Xv(this),0),this.c!=7)throw J(new $r(Ur((jr(),Tb))));return mi(this),t},l.Wl=function(){throw J(new $r(Ur((jr(),xh))))},l.Xl=function(t){return mi(this),Ij(t,(yi(),yi(),new $m(3,t)))},l.Yl=function(t){var n;return mi(this),n=(yi(),yi(),new e_(2)),pb(n,t),pb(n,nA),n},l.Zl=function(t){return mi(this),yi(),yi(),new $m(3,t)};var s5=null,LE=null;O($g,"RegEx/ParserForXMLSchema",1824),M(117,1,V7,cv),l.$l=function(t){throw J(new tc("Not supported."))},l._l=function(){return-1},l.am=function(t){return null},l.bm=function(){return null},l.cm=function(t){},l.dm=function(t){},l.em=function(){return 0},l.Ib=function(){return this.fm(0)},l.fm=function(t){return this.e==11?".":""},l.e=0;var rLe,ME,tA,$4t,iLe,Yy=null,sU,Lfe=null,sLe,nA,Mfe=null,aLe,oLe,cLe,uLe,lLe,H4t,qk,z4t,G4t,q4t,V4t,DE,U4t,W4t,D3n=O($g,"RegEx/Token",117);M(136,117,{3:1,136:1,117:1},Hl),l.fm=function(t){var n,r,s;if(this.e==4)if(this==sLe)r=".";else if(this==sU)r="\\d";else if(this==DE)r="\\w";else if(this==qk)r="\\s";else{for(s=new bg,s.a+="[",n=0;n0&&(s.a+=","),this.b[n]===this.b[n+1]?To(s,yI(this.b[n])):(To(s,yI(this.b[n])),s.a+="-",To(s,yI(this.b[n+1])));s.a+="]",r=s.a}else if(this==cLe)r="\\D";else if(this==lLe)r="\\W";else if(this==uLe)r="\\S";else{for(s=new bg,s.a+="[^",n=0;n0&&(s.a+=","),this.b[n]===this.b[n+1]?To(s,yI(this.b[n])):(To(s,yI(this.b[n])),s.a+="-",To(s,yI(this.b[n+1])));s.a+="]",r=s.a}return r},l.a=!1,l.c=!1,O($g,"RegEx/RangeToken",136),M(584,1,{584:1},ipe),l.a=0,O($g,"RegEx/RegexParser/ReferencePosition",584),M(583,1,{3:1,583:1},Uze),l.Fb=function(t){var n;return t==null||!we(t,583)?!1:(n=u(t,583),an(this.b,n.b)&&this.a==n.a)},l.Hb=function(){return Ig(this.b+"/"+g5e(this.a))},l.Ib=function(){return this.c.fm(this.a)},l.a=0,O($g,"RegEx/RegularExpression",583),M(223,117,V7,Yd),l._l=function(){return this.a},l.fm=function(t){var n,r,s;switch(this.e){case 0:switch(this.a){case 124:case 42:case 43:case 63:case 40:case 41:case 46:case 91:case 123:case 92:s="\\"+cne(this.a&Ss);break;case 12:s="\\f";break;case 10:s="\\n";break;case 13:s="\\r";break;case 9:s="\\t";break;case 27:s="\\e";break;default:this.a>=so?(r=(n=this.a>>>0,"0"+n.toString(16)),s="\\v"+jl(r,r.length-6,r.length)):s=""+cne(this.a&Ss)}break;case 8:this==aLe||this==oLe?s=""+cne(this.a&Ss):s="\\"+cne(this.a&Ss);break;default:s=null}return s},l.a=0,O($g,"RegEx/Token/CharToken",223),M(309,117,V7,$m),l.am=function(t){return this.a},l.cm=function(t){this.b=t},l.dm=function(t){this.c=t},l.em=function(){return 1},l.fm=function(t){var n;if(this.e==3)if(this.c<0&&this.b<0)n=this.a.fm(t)+"*";else if(this.c==this.b)n=this.a.fm(t)+"{"+this.c+"}";else if(this.c>=0&&this.b>=0)n=this.a.fm(t)+"{"+this.c+","+this.b+"}";else if(this.c>=0&&this.b<0)n=this.a.fm(t)+"{"+this.c+",}";else throw J(new tc("Token#toString(): CLOSURE "+this.c+io+this.b));else if(this.c<0&&this.b<0)n=this.a.fm(t)+"*?";else if(this.c==this.b)n=this.a.fm(t)+"{"+this.c+"}?";else if(this.c>=0&&this.b>=0)n=this.a.fm(t)+"{"+this.c+","+this.b+"}?";else if(this.c>=0&&this.b<0)n=this.a.fm(t)+"{"+this.c+",}?";else throw J(new tc("Token#toString(): NONGREEDYCLOSURE "+this.c+io+this.b));return n},l.b=0,l.c=0,O($g,"RegEx/Token/ClosureToken",309),M(821,117,V7,Xve),l.am=function(t){return t==0?this.a:this.b},l.em=function(){return 2},l.fm=function(t){var n;return this.b.e==3&&this.b.am(0)==this.a?n=this.a.fm(t)+"+":this.b.e==9&&this.b.am(0)==this.a?n=this.a.fm(t)+"+?":n=this.a.fm(t)+(""+this.b.fm(t)),n},O($g,"RegEx/Token/ConcatToken",821),M(1822,117,V7,ZJe),l.am=function(t){if(t==0)return this.d;if(t==1)return this.b;throw J(new tc("Internal Error: "+t))},l.em=function(){return this.b?2:1},l.fm=function(t){var n;return this.c>0?n="(?("+this.c+")":this.a.e==8?n="(?("+this.a+")":n="(?"+this.a,this.b?n+=this.d+"|"+this.b+")":n+=this.d+")",n},l.c=0,O($g,"RegEx/Token/ConditionToken",1822),M(1823,117,V7,ZXe),l.am=function(t){return this.b},l.em=function(){return 1},l.fm=function(t){return"(?"+(this.a==0?"":g5e(this.a))+(this.c==0?"":g5e(this.c))+":"+this.b.fm(t)+")"},l.a=0,l.c=0,O($g,"RegEx/Token/ModifierToken",1823),M(822,117,V7,nwe),l.am=function(t){return this.a},l.em=function(){return 1},l.fm=function(t){var n;switch(n=null,this.e){case 6:this.b==0?n="(?:"+this.a.fm(t)+")":n="("+this.a.fm(t)+")";break;case 20:n="(?="+this.a.fm(t)+")";break;case 21:n="(?!"+this.a.fm(t)+")";break;case 22:n="(?<="+this.a.fm(t)+")";break;case 23:n="(?"+this.a.fm(t)+")"}return n},l.b=0,O($g,"RegEx/Token/ParenToken",822),M(521,117,{3:1,117:1,521:1},cre),l.bm=function(){return this.b},l.fm=function(t){return this.e==12?"\\"+this.a:Vdn(this.b)},l.a=0,O($g,"RegEx/Token/StringToken",521),M(465,117,V7,e_),l.$l=function(t){pb(this,t)},l.am=function(t){return u(Lv(this.a,t),117)},l.em=function(){return this.a?this.a.a.c.length:0},l.fm=function(t){var n,r,s,o,h;if(this.e==1){if(this.a.a.c.length==2)n=u(Lv(this.a,0),117),r=u(Lv(this.a,1),117),r.e==3&&r.am(0)==n?o=n.fm(t)+"+":r.e==9&&r.am(0)==n?o=n.fm(t)+"+?":o=n.fm(t)+(""+r.fm(t));else{for(h=new bg,s=0;s=this.c.b:this.a<=this.c.b},l.Sb=function(){return this.b>0},l.Tb=function(){return this.b},l.Vb=function(){return this.b-1},l.Qb=function(){throw J(new pg(v0t))},l.a=0,l.b=0,O(L8e,"ExclusiveRange/RangeIterator",254);var Sh=v8(mG,"C"),Lr=v8(qC,"I"),El=v8(sk,"Z"),S2=v8(VC,"J"),el=v8(HC,"B"),pa=v8(zC,"D"),Xy=v8(GC,"F"),a5=v8(UC,"S"),I3n=ss("org.eclipse.elk.core.labels","ILabelManager"),hLe=ss(Qa,"DiagnosticChain"),fLe=ss(Vdt,"ResourceSet"),dLe=O(Qa,"InvocationTargetException",null),Y4t=(fF(),Enn),X4t=X4t=fhn;win(hVt),qin("permProps",[[[IG,OG],[NG,"gecko1_8"]],[[IG,OG],[NG,"ie10"]],[[IG,OG],[NG,"ie8"]],[[IG,OG],[NG,"ie9"]],[[IG,OG],[NG,"safari"]]]),X4t(null,"elk",null)}).call(this)}).call(this,typeof Wk<"u"?Wk:typeof self<"u"?self:typeof window<"u"?window:{})},{}],3:[function(f,p,w){function y(B,R){if(!(B instanceof R))throw new TypeError("Cannot call a class as a function")}function b(B,R){if(!B)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return R&&(typeof R=="object"||typeof R=="function")?R:B}function E(B,R){if(typeof R!="function"&&R!==null)throw new TypeError("Super expression must either be null or a function, not "+typeof R);B.prototype=Object.create(R&&R.prototype,{constructor:{value:B,enumerable:!1,writable:!0,configurable:!0}}),R&&(Object.setPrototypeOf?Object.setPrototypeOf(B,R):B.__proto__=R)}var S=f("./elk-api.js").default,N=function(B){E(R,B);function R(){var j=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};y(this,R);var $=Object.assign({},j),V=!1;try{f.resolve("web-worker"),V=!0}catch{}if(j.workerUrl)if(V){var Q=f("web-worker");$.workerFactory=function(se){return new Q(se)}}else console.warn(`Web worker requested but 'web-worker' package not installed. +Consider installing the package or pass your own 'workerFactory' to ELK's constructor. +... Falling back to non-web worker version.`);if(!$.workerFactory){var oe=f("./elk-worker.min.js"),ce=oe.Worker;$.workerFactory=function(se){return new ce(se)}}return b(this,(R.__proto__||Object.getPrototypeOf(R)).call(this,$))}return R}(S);Object.defineProperty(p.exports,"__esModule",{value:!0}),p.exports=N,N.default=N},{"./elk-api.js":1,"./elk-worker.min.js":2,"web-worker":4}],4:[function(f,p,w){p.exports=Worker},{}]},{},[3])(3)})})(qGt);const VGt=xLe(Mge),HFe=new VGt;let Zb={};const UGt={};let O5={};const WGt=async function(i,a,f,p,w,y,b){const S=f.select(`[id="${a}"]`).insert("g").attr("class","nodes"),N=Object.keys(i);return await Promise.all(N.map(async function(B){const R=i[B];let j="default";R.classes.length>0&&(j=R.classes.join(" ")),j=j+" flowchart-label";const $=Yw(R.styles);let V=R.text!==void 0?R.text:R.id;const Q={width:0,height:0},oe=[{id:R.id+"-west",layoutOptions:{"port.side":"WEST"}},{id:R.id+"-east",layoutOptions:{"port.side":"EAST"}},{id:R.id+"-south",layoutOptions:{"port.side":"SOUTH"}},{id:R.id+"-north",layoutOptions:{"port.side":"NORTH"}}];let ce=0,se="",ge={};switch(R.type){case"round":ce=5,se="rect";break;case"square":se="rect";break;case"diamond":se="question",ge={portConstraints:"FIXED_SIDE"};break;case"hexagon":se="hexagon";break;case"odd":se="rect_left_inv_arrow";break;case"lean_right":se="lean_right";break;case"lean_left":se="lean_left";break;case"trapezoid":se="trapezoid";break;case"inv_trapezoid":se="inv_trapezoid";break;case"odd_right":se="rect_left_inv_arrow";break;case"circle":se="circle";break;case"ellipse":se="ellipse";break;case"stadium":se="stadium";break;case"subroutine":se="subroutine";break;case"cylinder":se="cylinder";break;case"group":se="rect";break;case"doublecircle":se="doublecircle";break;default:se="rect"}const ye={labelStyle:$.labelStyle,shape:se,labelText:V,labelType:R.labelType,rx:ce,ry:ce,class:j,style:$.style,id:R.id,link:R.link,linkTarget:R.linkTarget,tooltip:w.db.getTooltip(R.id)||"",domId:w.db.lookUpDomId(R.id),haveCallback:R.haveCallback,width:R.type==="group"?500:void 0,dir:R.dir,type:R.type,props:R.props,padding:Tt().flowchart.padding};let ke,Ae;if(ye.type!=="group")Ae=await KBe(S,ye,R.dir),ke=Ae.node().getBBox();else{p.createElementNS("http://www.w3.org/2000/svg","text");const{shapeSvg:ve,bbox:te}=await jd(S,ye,void 0,!0);Q.width=te.width,Q.wrappingWidth=Tt().flowchart.wrappingWidth,Q.height=te.height,Q.labelNode=ve.node(),ye.labelData=Q}const de={id:R.id,ports:R.type==="diamond"?oe:[],layoutOptions:ge,labelText:V,labelData:Q,domId:w.db.lookUpDomId(R.id),width:ke==null?void 0:ke.width,height:ke==null?void 0:ke.height,type:R.type,el:Ae,parent:y.parentById[R.id]};O5[ye.id]=de})),b},zFe=(i,a,f)=>{const p={TB:{in:{north:"north"},out:{south:"west",west:"east",east:"south"}},LR:{in:{west:"west"},out:{east:"south",south:"north",north:"east"}},RL:{in:{east:"east"},out:{west:"north",north:"south",south:"west"}},BT:{in:{south:"south"},out:{north:"east",east:"west",west:"north"}}};return p.TD=p.TB,Fe.info("abc88",f,a,i),p[f][a][i]},GFe=(i,a,f)=>{if(Fe.info("getNextPort abc88",{node:i,edgeDirection:a,graphDirection:f}),!Zb[i])switch(f){case"TB":case"TD":Zb[i]={inPosition:"north",outPosition:"south"};break;case"BT":Zb[i]={inPosition:"south",outPosition:"north"};break;case"RL":Zb[i]={inPosition:"east",outPosition:"west"};break;case"LR":Zb[i]={inPosition:"west",outPosition:"east"};break}const p=a==="in"?Zb[i].inPosition:Zb[i].outPosition;return a==="in"?Zb[i].inPosition=zFe(Zb[i].inPosition,a,f):Zb[i].outPosition=zFe(Zb[i].outPosition,a,f),p},KGt=(i,a)=>{let f=i.start,p=i.end;const w=f,y=p,b=O5[f],E=O5[p];return!b||!E?{source:f,target:p}:(b.type==="diamond"&&(f=`${f}-${GFe(f,"out",a)}`),E.type==="diamond"&&(p=`${p}-${GFe(p,"in",a)}`),{source:f,target:p,sourceId:w,targetId:y})},YGt=function(i,a,f,p){Fe.info("abc78 edges = ",i);const w=p.insert("g").attr("class","edgeLabels");let y={},b=a.db.getDirection(),E,S;if(i.defaultStyle!==void 0){const N=Yw(i.defaultStyle);E=N.style,S=N.labelStyle}return i.forEach(function(N){var B="L-"+N.start+"-"+N.end;y[B]===void 0?(y[B]=0,Fe.info("abc78 new entry",B,y[B])):(y[B]++,Fe.info("abc78 new entry",B,y[B]));let R=B+"-"+y[B];Fe.info("abc78 new link id to be used is",B,R,y[B]);var j="LS-"+N.start,$="LE-"+N.end;const V={style:"",labelStyle:""};switch(V.minlen=N.length||1,N.type==="arrow_open"?V.arrowhead="none":V.arrowhead="normal",V.arrowTypeStart="arrow_open",V.arrowTypeEnd="arrow_open",N.type){case"double_arrow_cross":V.arrowTypeStart="arrow_cross";case"arrow_cross":V.arrowTypeEnd="arrow_cross";break;case"double_arrow_point":V.arrowTypeStart="arrow_point";case"arrow_point":V.arrowTypeEnd="arrow_point";break;case"double_arrow_circle":V.arrowTypeStart="arrow_circle";case"arrow_circle":V.arrowTypeEnd="arrow_circle";break}let Q="",oe="";switch(N.stroke){case"normal":Q="fill:none;",E!==void 0&&(Q=E),S!==void 0&&(oe=S),V.thickness="normal",V.pattern="solid";break;case"dotted":V.thickness="normal",V.pattern="dotted",V.style="fill:none;stroke-width:2px;stroke-dasharray:3;";break;case"thick":V.thickness="thick",V.pattern="solid",V.style="stroke-width: 3.5px;fill:none;";break}if(N.style!==void 0){const Ae=Yw(N.style);Q=Ae.style,oe=Ae.labelStyle}V.style=V.style+=Q,V.labelStyle=V.labelStyle+=oe,N.interpolate!==void 0?V.curve=Ub(N.interpolate,ng):i.defaultInterpolate!==void 0?V.curve=Ub(i.defaultInterpolate,ng):V.curve=Ub(UGt.curve,ng),N.text===void 0?N.style!==void 0&&(V.arrowheadStyle="fill: #333"):(V.arrowheadStyle="fill: #333",V.labelpos="c"),V.labelType=N.labelType,V.label=N.text.replace(Wa.lineBreakRegex,` +`),N.style===void 0&&(V.style=V.style||"stroke: #333; stroke-width: 1.5px;fill:none;"),V.labelStyle=V.labelStyle.replace("color:","fill:"),V.id=R,V.classes="flowchart-link "+j+" "+$;const ce=QBe(w,V),{source:se,target:ge,sourceId:ye,targetId:ke}=KGt(N,b);Fe.debug("abc78 source and target",se,ge),f.edges.push({id:"e"+N.start+N.end,sources:[se],targets:[ge],sourceId:ye,targetId:ke,labelEl:ce,labels:[{width:V.width,height:V.height,orgWidth:V.width,orgHeight:V.height,text:V.label,layoutOptions:{"edgeLabels.inline":"true","edgeLabels.placement":"CENTER"}}],edgeData:V})}),f},XGt=function(i,a,f,p){let w="";switch(p&&(w=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search,w=w.replace(/\(/g,"\\("),w=w.replace(/\)/g,"\\)")),a.arrowTypeStart){case"arrow_cross":i.attr("marker-start","url("+w+"#"+f+"-crossStart)");break;case"arrow_point":i.attr("marker-start","url("+w+"#"+f+"-pointStart)");break;case"arrow_barb":i.attr("marker-start","url("+w+"#"+f+"-barbStart)");break;case"arrow_circle":i.attr("marker-start","url("+w+"#"+f+"-circleStart)");break;case"aggregation":i.attr("marker-start","url("+w+"#"+f+"-aggregationStart)");break;case"extension":i.attr("marker-start","url("+w+"#"+f+"-extensionStart)");break;case"composition":i.attr("marker-start","url("+w+"#"+f+"-compositionStart)");break;case"dependency":i.attr("marker-start","url("+w+"#"+f+"-dependencyStart)");break;case"lollipop":i.attr("marker-start","url("+w+"#"+f+"-lollipopStart)");break}switch(a.arrowTypeEnd){case"arrow_cross":i.attr("marker-end","url("+w+"#"+f+"-crossEnd)");break;case"arrow_point":i.attr("marker-end","url("+w+"#"+f+"-pointEnd)");break;case"arrow_barb":i.attr("marker-end","url("+w+"#"+f+"-barbEnd)");break;case"arrow_circle":i.attr("marker-end","url("+w+"#"+f+"-circleEnd)");break;case"aggregation":i.attr("marker-end","url("+w+"#"+f+"-aggregationEnd)");break;case"extension":i.attr("marker-end","url("+w+"#"+f+"-extensionEnd)");break;case"composition":i.attr("marker-end","url("+w+"#"+f+"-compositionEnd)");break;case"dependency":i.attr("marker-end","url("+w+"#"+f+"-dependencyEnd)");break;case"lollipop":i.attr("marker-end","url("+w+"#"+f+"-lollipopEnd)");break}},QGt=function(i,a){Fe.info("Extracting classes"),a.db.clear("ver-2");try{return a.parse(i),a.db.getClasses()}catch{return{}}},ZGt=function(i){const a={parentById:{},childrenById:{}},f=i.getSubGraphs();return Fe.info("Subgraphs - ",f),f.forEach(function(p){p.nodes.forEach(function(w){a.parentById[w]=p.id,a.childrenById[p.id]===void 0&&(a.childrenById[p.id]=[]),a.childrenById[p.id].push(w)})}),f.forEach(function(p){p.id,a.parentById[p.id]!==void 0&&a.parentById[p.id]}),a},JGt=function(i,a,f){const p=GGt(i,a,f);if(p===void 0||p==="root")return{x:0,y:0};const w=O5[p].offset;return{x:w.posX,y:w.posY}},eqt=function(i,a,f,p,w){const y=JGt(a.sourceId,a.targetId,w),b=a.sections[0].startPoint,E=a.sections[0].endPoint,N=(a.sections[0].bendPoints?a.sections[0].bendPoints:[]).map(oe=>[oe.x+y.x,oe.y+y.y]),B=[[b.x+y.x,b.y+y.y],...N,[E.x+y.x,E.y+y.y]],R=WE().curve(ng),j=i.insert("path").attr("d",R(B)).attr("class","path").attr("fill","none"),$=i.insert("g").attr("class","edgeLabel"),V=Cr($.node().appendChild(a.labelEl)),Q=V.node().firstChild.getBoundingClientRect();V.attr("width",Q.width),V.attr("height",Q.height),$.attr("transform",`translate(${a.labels[0].x+y.x}, ${a.labels[0].y+y.y})`),XGt(j,f,p.type,p.arrowMarkerAbsolute)},qFe=(i,a)=>{i.forEach(f=>{f.children||(f.children=[]);const p=a.childrenById[f.id];p&&p.forEach(w=>{f.children.push(O5[w])}),qFe(f.children,a)})},tqt=async function(i,a,f,p){var de;p.db.clear(),O5={},Zb={},p.db.setGen("gen-2"),p.parser.parse(i);const w=Cr("body").append("div").attr("style","height:400px").attr("id","cy");let y={id:"root",layoutOptions:{"elk.hierarchyHandling":"INCLUDE_CHILDREN","org.eclipse.elk.padding":"[top=100, left=100, bottom=110, right=110]","elk.layered.spacing.edgeNodeBetweenLayers":"30","elk.direction":"DOWN"},children:[],edges:[]};switch(Fe.info("Drawing flowchart using v3 renderer",HFe),p.db.getDirection()){case"BT":y.layoutOptions["elk.direction"]="UP";break;case"TB":y.layoutOptions["elk.direction"]="DOWN";break;case"LR":y.layoutOptions["elk.direction"]="RIGHT";break;case"RL":y.layoutOptions["elk.direction"]="LEFT";break}const{securityLevel:E,flowchart:S}=Tt();let N;E==="sandbox"&&(N=Cr("#i"+a));const B=Cr(E==="sandbox"?N.nodes()[0].contentDocument.body:"body"),R=E==="sandbox"?N.nodes()[0].contentDocument:document,j=B.select(`[id="${a}"]`);vBe(j,["point","circle","cross"],p.type,p.arrowMarkerAbsolute);const V=p.db.getVertices();let Q;const oe=p.db.getSubGraphs();Fe.info("Subgraphs - ",oe);for(let ve=oe.length-1;ve>=0;ve--)Q=oe[ve],p.db.addVertex(Q.id,{text:Q.title,type:Q.labelType},"group",void 0,Q.classes,Q.dir);const ce=j.insert("g").attr("class","subgraphs"),se=ZGt(p.db);y=await WGt(V,a,B,R,p,se,y);const ge=j.insert("g").attr("class","edges edgePath"),ye=p.db.getEdges();y=YGt(ye,p,y,j),Object.keys(O5).forEach(ve=>{const te=O5[ve];te.parent||y.children.push(te),se.childrenById[ve]!==void 0&&(te.labels=[{text:te.labelText,layoutOptions:{"nodeLabels.placement":"[H_CENTER, V_TOP, INSIDE]"},width:te.labelData.width,height:te.labelData.height}],delete te.x,delete te.y,delete te.width,delete te.height)}),qFe(y.children,se),Fe.info("after layout",JSON.stringify(y,null,2));const Ae=await HFe.layout(y);VFe(0,0,Ae.children,j,ce,p,0),Fe.info("after layout",Ae),(de=Ae.edges)==null||de.map(ve=>{eqt(ge,ve,ve.edgeData,p,se)}),YE({},j,S.diagramPadding,S.useMaxWidth),w.remove()},VFe=(i,a,f,p,w,y,b)=>{f.forEach(function(E){if(E)if(O5[E.id].offset={posX:E.x+i,posY:E.y+a,x:i,y:a,depth:b,width:E.width,height:E.height},E.type==="group"){const S=w.insert("g").attr("class","subgraph");S.insert("rect").attr("class","subgraph subgraph-lvl-"+b%5+" node").attr("x",E.x+i).attr("y",E.y+a).attr("width",E.width).attr("height",E.height);const N=S.insert("g").attr("class","label"),B=Tt().flowchart.htmlLabels?E.labelData.width/2:0;N.attr("transform",`translate(${E.labels[0].x+i+E.x+B}, ${E.labels[0].y+a+E.y+3})`),N.node().appendChild(E.labelData.labelNode),Fe.info("Id (UGH)= ",E.type,E.labels)}else Fe.info("Id (UGH)= ",E.id),E.el.attr("transform",`translate(${E.x+i+E.width/2}, ${E.y+a+E.height/2})`)}),f.forEach(function(E){E&&E.type==="group"&&VFe(i+E.x,a+E.y,E.children,p,w,y,b+1)})},nqt={getClasses:QGt,draw:tqt},rqt=i=>{let a="";for(let f=0;f<5;f++)a+=` + .subgraph-lvl-${f} { + fill: ${i[`surface${f}`]}; + stroke: ${i[`surfacePeer${f}`]}; + } + `;return a},iqt=Object.freeze(Object.defineProperty({__proto__:null,diagram:{db:hMt,renderer:nqt,parser:Dde,styles:i=>`.label { + font-family: ${i.fontFamily}; + color: ${i.nodeTextColor||i.textColor}; + } + .cluster-label text { + fill: ${i.titleColor}; + } + .cluster-label span { + color: ${i.titleColor}; + } + + .label text,span { + fill: ${i.nodeTextColor||i.textColor}; + color: ${i.nodeTextColor||i.textColor}; + } + + .node rect, + .node circle, + .node ellipse, + .node polygon, + .node path { + fill: ${i.mainBkg}; + stroke: ${i.nodeBorder}; + stroke-width: 1px; + } + + .node .label { + text-align: center; + } + .node.clickable { + cursor: pointer; + } + + .arrowheadPath { + fill: ${i.arrowheadColor}; + } + + .edgePath .path { + stroke: ${i.lineColor}; + stroke-width: 2.0px; + } + + .flowchart-link { + stroke: ${i.lineColor}; + fill: none; + } + + .edgeLabel { + background-color: ${i.edgeLabelBackground}; + rect { + opacity: 0.85; + background-color: ${i.edgeLabelBackground}; + fill: ${i.edgeLabelBackground}; + } + text-align: center; + } + + .cluster rect { + fill: ${i.clusterBkg}; + stroke: ${i.clusterBorder}; + stroke-width: 1px; + } + + .cluster text { + fill: ${i.titleColor}; + } + + .cluster span { + color: ${i.titleColor}; + } + /* .cluster div { + color: ${i.titleColor}; + } */ + + div.mermaidTooltip { + position: absolute; + text-align: center; + max-width: 200px; + padding: 2px; + font-family: ${i.fontFamily}; + font-size: 12px; + background: ${i.tertiaryColor}; + border: 1px solid ${i.border2}; + border-radius: 2px; + pointer-events: none; + z-index: 100; + } + + .flowchartTitleText { + text-anchor: middle; + font-size: 18px; + fill: ${i.textColor}; + } + .subgraph { + stroke-width:2; + rx:3; + } + // .subgraph-lvl-1 { + // fill:#ccc; + // // stroke:black; + // } + + .flowchart-label text { + text-anchor: middle; + } + + ${rqt(i)} +`}},Symbol.toStringTag,{value:"Module"}));var Dge=function(){var i=function(oe,ce,se,ge){for(se=se||{},ge=oe.length;ge--;se[oe[ge]]=ce);return se},a=[1,2],f=[1,5],p=[6,9,11,17,18,20,22,23,26,27,28],w=[1,15],y=[1,16],b=[1,17],E=[1,18],S=[1,19],N=[1,23],B=[1,24],R=[1,27],j=[4,6,9,11,17,18,20,22,23,26,27,28],$={trace:function(){},yy:{},symbols_:{error:2,start:3,timeline:4,document:5,EOF:6,directive:7,line:8,SPACE:9,statement:10,NEWLINE:11,openDirective:12,typeDirective:13,closeDirective:14,":":15,argDirective:16,title:17,acc_title:18,acc_title_value:19,acc_descr:20,acc_descr_value:21,acc_descr_multiline_value:22,section:23,period_statement:24,event_statement:25,period:26,event:27,open_directive:28,type_directive:29,arg_directive:30,close_directive:31,$accept:0,$end:1},terminals_:{2:"error",4:"timeline",6:"EOF",9:"SPACE",11:"NEWLINE",15:":",17:"title",18:"acc_title",19:"acc_title_value",20:"acc_descr",21:"acc_descr_value",22:"acc_descr_multiline_value",23:"section",26:"period",27:"event",28:"open_directive",29:"type_directive",30:"arg_directive",31:"close_directive"},productions_:[0,[3,3],[3,2],[5,0],[5,2],[8,2],[8,1],[8,1],[8,1],[7,4],[7,6],[10,1],[10,2],[10,2],[10,1],[10,1],[10,1],[10,1],[10,1],[24,1],[25,1],[12,1],[13,1],[16,1],[14,1]],performAction:function(ce,se,ge,ye,ke,Ae,de){var ve=Ae.length-1;switch(ke){case 1:return Ae[ve-1];case 3:this.$=[];break;case 4:Ae[ve-1].push(Ae[ve]),this.$=Ae[ve-1];break;case 5:case 6:this.$=Ae[ve];break;case 7:case 8:this.$=[];break;case 11:ye.getCommonDb().setDiagramTitle(Ae[ve].substr(6)),this.$=Ae[ve].substr(6);break;case 12:this.$=Ae[ve].trim(),ye.getCommonDb().setAccTitle(this.$);break;case 13:case 14:this.$=Ae[ve].trim(),ye.getCommonDb().setAccDescription(this.$);break;case 15:ye.addSection(Ae[ve].substr(8)),this.$=Ae[ve].substr(8);break;case 19:ye.addTask(Ae[ve],0,""),this.$=Ae[ve];break;case 20:ye.addEvent(Ae[ve].substr(2)),this.$=Ae[ve];break;case 21:ye.parseDirective("%%{","open_directive");break;case 22:ye.parseDirective(Ae[ve],"type_directive");break;case 23:Ae[ve]=Ae[ve].trim().replace(/'/g,'"'),ye.parseDirective(Ae[ve],"arg_directive");break;case 24:ye.parseDirective("}%%","close_directive","timeline");break}},table:[{3:1,4:a,7:3,12:4,28:f},{1:[3]},i(p,[2,3],{5:6}),{3:7,4:a,7:3,12:4,28:f},{13:8,29:[1,9]},{29:[2,21]},{6:[1,10],7:22,8:11,9:[1,12],10:13,11:[1,14],12:4,17:w,18:y,20:b,22:E,23:S,24:20,25:21,26:N,27:B,28:f},{1:[2,2]},{14:25,15:[1,26],31:R},i([15,31],[2,22]),i(p,[2,8],{1:[2,1]}),i(p,[2,4]),{7:22,10:28,12:4,17:w,18:y,20:b,22:E,23:S,24:20,25:21,26:N,27:B,28:f},i(p,[2,6]),i(p,[2,7]),i(p,[2,11]),{19:[1,29]},{21:[1,30]},i(p,[2,14]),i(p,[2,15]),i(p,[2,16]),i(p,[2,17]),i(p,[2,18]),i(p,[2,19]),i(p,[2,20]),{11:[1,31]},{16:32,30:[1,33]},{11:[2,24]},i(p,[2,5]),i(p,[2,12]),i(p,[2,13]),i(j,[2,9]),{14:34,31:R},{31:[2,23]},{11:[1,35]},i(j,[2,10])],defaultActions:{5:[2,21],7:[2,2],27:[2,24],33:[2,23]},parseError:function(ce,se){if(se.recoverable)this.trace(ce);else{var ge=new Error(ce);throw ge.hash=se,ge}},parse:function(ce){var se=this,ge=[0],ye=[],ke=[null],Ae=[],de=this.table,ve="",te=0,xe=0,De=2,he=1,Ie=Ae.slice.call(arguments,1),ee=Object.create(this.lexer),rt={yy:{}};for(var me in this.yy)Object.prototype.hasOwnProperty.call(this.yy,me)&&(rt.yy[me]=this.yy[me]);ee.setInput(ce,rt.yy),rt.yy.lexer=ee,rt.yy.parser=this,typeof ee.yylloc>"u"&&(ee.yylloc={});var gt=ee.yylloc;Ae.push(gt);var pe=ee.options&&ee.options.ranges;typeof rt.yy.parseError=="function"?this.parseError=rt.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Et(){var vt;return vt=ye.pop()||ee.lex()||he,typeof vt!="number"&&(vt instanceof Array&&(ye=vt,vt=ye.pop()),vt=se.symbols_[vt]||vt),vt}for(var wt,jt,At,Bt,cn={},Nn,Ot,oi,kt;;){if(jt=ge[ge.length-1],this.defaultActions[jt]?At=this.defaultActions[jt]:((wt===null||typeof wt>"u")&&(wt=Et()),At=de[jt]&&de[jt][wt]),typeof At>"u"||!At.length||!At[0]){var Dt="";kt=[];for(Nn in de[jt])this.terminals_[Nn]&&Nn>De&&kt.push("'"+this.terminals_[Nn]+"'");ee.showPosition?Dt="Parse error on line "+(te+1)+`: +`+ee.showPosition()+` +Expecting `+kt.join(", ")+", got '"+(this.terminals_[wt]||wt)+"'":Dt="Parse error on line "+(te+1)+": Unexpected "+(wt==he?"end of input":"'"+(this.terminals_[wt]||wt)+"'"),this.parseError(Dt,{text:ee.match,token:this.terminals_[wt]||wt,line:ee.yylineno,loc:gt,expected:kt})}if(At[0]instanceof Array&&At.length>1)throw new Error("Parse Error: multiple actions possible at state: "+jt+", token: "+wt);switch(At[0]){case 1:ge.push(wt),ke.push(ee.yytext),Ae.push(ee.yylloc),ge.push(At[1]),wt=null,xe=ee.yyleng,ve=ee.yytext,te=ee.yylineno,gt=ee.yylloc;break;case 2:if(Ot=this.productions_[At[1]][1],cn.$=ke[ke.length-Ot],cn._$={first_line:Ae[Ae.length-(Ot||1)].first_line,last_line:Ae[Ae.length-1].last_line,first_column:Ae[Ae.length-(Ot||1)].first_column,last_column:Ae[Ae.length-1].last_column},pe&&(cn._$.range=[Ae[Ae.length-(Ot||1)].range[0],Ae[Ae.length-1].range[1]]),Bt=this.performAction.apply(cn,[ve,xe,te,rt.yy,At[1],ke,Ae].concat(Ie)),typeof Bt<"u")return Bt;Ot&&(ge=ge.slice(0,-1*Ot*2),ke=ke.slice(0,-1*Ot),Ae=Ae.slice(0,-1*Ot)),ge.push(this.productions_[At[1]][0]),ke.push(cn.$),Ae.push(cn._$),oi=de[ge[ge.length-2]][ge[ge.length-1]],ge.push(oi);break;case 3:return!0}}return!0}},V=function(){var oe={EOF:1,parseError:function(se,ge){if(this.yy.parser)this.yy.parser.parseError(se,ge);else throw new Error(se)},setInput:function(ce,se){return this.yy=se||this.yy||{},this._input=ce,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var ce=this._input[0];this.yytext+=ce,this.yyleng++,this.offset++,this.match+=ce,this.matched+=ce;var se=ce.match(/(?:\r\n?|\n).*/g);return se?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),ce},unput:function(ce){var se=ce.length,ge=ce.split(/(?:\r\n?|\n)/g);this._input=ce+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-se),this.offset-=se;var ye=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),ge.length-1&&(this.yylineno-=ge.length-1);var ke=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:ge?(ge.length===ye.length?this.yylloc.first_column:0)+ye[ye.length-ge.length].length-ge[0].length:this.yylloc.first_column-se},this.options.ranges&&(this.yylloc.range=[ke[0],ke[0]+this.yyleng-se]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(ce){this.unput(this.match.slice(ce))},pastInput:function(){var ce=this.matched.substr(0,this.matched.length-this.match.length);return(ce.length>20?"...":"")+ce.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var ce=this.match;return ce.length<20&&(ce+=this._input.substr(0,20-ce.length)),(ce.substr(0,20)+(ce.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var ce=this.pastInput(),se=new Array(ce.length+1).join("-");return ce+this.upcomingInput()+` +`+se+"^"},test_match:function(ce,se){var ge,ye,ke;if(this.options.backtrack_lexer&&(ke={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(ke.yylloc.range=this.yylloc.range.slice(0))),ye=ce[0].match(/(?:\r\n?|\n).*/g),ye&&(this.yylineno+=ye.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:ye?ye[ye.length-1].length-ye[ye.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+ce[0].length},this.yytext+=ce[0],this.match+=ce[0],this.matches=ce,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(ce[0].length),this.matched+=ce[0],ge=this.performAction.call(this,this.yy,this,se,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),ge)return ge;if(this._backtrack){for(var Ae in ke)this[Ae]=ke[Ae];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var ce,se,ge,ye;this._more||(this.yytext="",this.match="");for(var ke=this._currentRules(),Ae=0;Aese[0].length)){if(se=ge,ye=Ae,this.options.backtrack_lexer){if(ce=this.test_match(ge,ke[Ae]),ce!==!1)return ce;if(this._backtrack){se=!1;continue}else return!1}else if(!this.options.flex)break}return se?(ce=this.test_match(se,ke[ye]),ce!==!1?ce:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var se=this.next();return se||this.lex()},begin:function(se){this.conditionStack.push(se)},popState:function(){var se=this.conditionStack.length-1;return se>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(se){return se=this.conditionStack.length-1-Math.abs(se||0),se>=0?this.conditionStack[se]:"INITIAL"},pushState:function(se){this.begin(se)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(se,ge,ye,ke){switch(ye){case 0:return this.begin("open_directive"),28;case 1:return this.begin("type_directive"),29;case 2:return this.popState(),this.begin("arg_directive"),15;case 3:return this.popState(),this.popState(),31;case 4:return 30;case 5:break;case 6:break;case 7:return 11;case 8:break;case 9:break;case 10:return 4;case 11:return 17;case 12:return this.begin("acc_title"),18;case 13:return this.popState(),"acc_title_value";case 14:return this.begin("acc_descr"),20;case 15:return this.popState(),"acc_descr_value";case 16:this.begin("acc_descr_multiline");break;case 17:this.popState();break;case 18:return"acc_descr_multiline_value";case 19:return 23;case 20:return 27;case 21:return 26;case 22:return 6;case 23:return"INVALID"}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:timeline\b)/i,/^(?:title\s[^#\n;]+)/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:section\s[^#:\n;]+)/i,/^(?::\s[^#:\n;]+)/i,/^(?:[^#:\n;]+)/i,/^(?:$)/i,/^(?:.)/i],conditions:{open_directive:{rules:[1],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},acc_descr_multiline:{rules:[17,18],inclusive:!1},acc_descr:{rules:[15],inclusive:!1},acc_title:{rules:[13],inclusive:!1},INITIAL:{rules:[0,5,6,7,8,9,10,11,12,14,16,19,20,21,22,23],inclusive:!0}}};return oe}();$.lexer=V;function Q(){this.yy={}}return Q.prototype=$,$.Parser=Q,new Q}();Dge.parser=Dge;const sqt=Dge;let gL="",UFe=0;const Ige=[],WK=[],pL=[],WFe=()=>kIe,KFe=(i,a,f)=>{rde(globalThis,i,a,f)},YFe=function(){Ige.length=0,WK.length=0,gL="",pL.length=0,rp()},XFe=function(i){gL=i,Ige.push(i)},QFe=function(){return Ige},ZFe=function(){let i=nje();const a=100;let f=0;for(;!i&&ff.id===UFe-1).events.push(i)},tje=function(i){const a={section:gL,type:gL,description:i,task:i,classes:[]};WK.push(a)},nje=function(){const i=function(f){return pL[f].processed};let a=!0;for(const[f,p]of pL.entries())i(f),a=a&&p.processed;return a},aqt=Object.freeze(Object.defineProperty({__proto__:null,addEvent:eje,addSection:XFe,addTask:JFe,addTaskOrg:tje,clear:YFe,default:{clear:YFe,getCommonDb:WFe,addSection:XFe,getSections:QFe,getTasks:ZFe,addTask:JFe,addTaskOrg:tje,addEvent:eje,parseDirective:KFe},getCommonDb:WFe,getSections:QFe,getTasks:ZFe,parseDirective:KFe},Symbol.toStringTag,{value:"Module"})),oqt=12,KK=function(i,a){const f=i.append("rect");return f.attr("x",a.x),f.attr("y",a.y),f.attr("fill",a.fill),f.attr("stroke",a.stroke),f.attr("width",a.width),f.attr("height",a.height),f.attr("rx",a.rx),f.attr("ry",a.ry),a.class!==void 0&&f.attr("class",a.class),f},cqt=function(i,a){const p=i.append("circle").attr("cx",a.cx).attr("cy",a.cy).attr("class","face").attr("r",15).attr("stroke-width",2).attr("overflow","visible"),w=i.append("g");w.append("circle").attr("cx",a.cx-15/3).attr("cy",a.cy-15/3).attr("r",1.5).attr("stroke-width",2).attr("fill","#666").attr("stroke","#666"),w.append("circle").attr("cx",a.cx+15/3).attr("cy",a.cy-15/3).attr("r",1.5).attr("stroke-width",2).attr("fill","#666").attr("stroke","#666");function y(S){const N=CA().startAngle(Math.PI/2).endAngle(3*(Math.PI/2)).innerRadius(7.5).outerRadius(6.8181818181818175);S.append("path").attr("class","mouth").attr("d",N).attr("transform","translate("+a.cx+","+(a.cy+2)+")")}function b(S){const N=CA().startAngle(3*Math.PI/2).endAngle(5*(Math.PI/2)).innerRadius(7.5).outerRadius(6.8181818181818175);S.append("path").attr("class","mouth").attr("d",N).attr("transform","translate("+a.cx+","+(a.cy+7)+")")}function E(S){S.append("line").attr("class","mouth").attr("stroke",2).attr("x1",a.cx-5).attr("y1",a.cy+7).attr("x2",a.cx+5).attr("y2",a.cy+7).attr("class","mouth").attr("stroke-width","1px").attr("stroke","#666")}return a.score>3?y(w):a.score<3?b(w):E(w),p},uqt=function(i,a){const f=i.append("circle");return f.attr("cx",a.cx),f.attr("cy",a.cy),f.attr("class","actor-"+a.pos),f.attr("fill",a.fill),f.attr("stroke",a.stroke),f.attr("r",a.r),f.class!==void 0&&f.attr("class",f.class),a.title!==void 0&&f.append("title").text(a.title),f},rje=function(i,a){const f=a.text.replace(//gi," "),p=i.append("text");p.attr("x",a.x),p.attr("y",a.y),p.attr("class","legend"),p.style("text-anchor",a.anchor),a.class!==void 0&&p.attr("class",a.class);const w=p.append("tspan");return w.attr("x",a.x+a.textMargin*2),w.text(f),p},lqt=function(i,a){function f(w,y,b,E,S){return w+","+y+" "+(w+b)+","+y+" "+(w+b)+","+(y+E-S)+" "+(w+b-S*1.2)+","+(y+E)+" "+w+","+(y+E)}const p=i.append("polygon");p.attr("points",f(a.x,a.y,50,20,7)),p.attr("class","labelBox"),a.y=a.y+a.labelMargin,a.x=a.x+.5*a.labelMargin,rje(i,a)},hqt=function(i,a,f){const p=i.append("g"),w=Oge();w.x=a.x,w.y=a.y,w.fill=a.fill,w.width=f.width,w.height=f.height,w.class="journey-section section-type-"+a.num,w.rx=3,w.ry=3,KK(p,w),sje(f)(a.text,p,w.x,w.y,w.width,w.height,{class:"journey-section section-type-"+a.num},f,a.colour)};let ije=-1;const fqt=function(i,a,f){const p=a.x+f.width/2,w=i.append("g");ije++;const y=300+5*30;w.append("line").attr("id","task"+ije).attr("x1",p).attr("y1",a.y).attr("x2",p).attr("y2",y).attr("class","task-line").attr("stroke-width","1px").attr("stroke-dasharray","4 2").attr("stroke","#666"),cqt(w,{cx:p,cy:300+(5-a.score)*30,score:a.score});const b=Oge();b.x=a.x,b.y=a.y,b.fill=a.fill,b.width=f.width,b.height=f.height,b.class="task task-type-"+a.num,b.rx=3,b.ry=3,KK(w,b),a.x+14,sje(f)(a.task,w,b.x,b.y,b.width,b.height,{class:"task"},f,a.colour)},dqt=function(i,a){KK(i,{x:a.startx,y:a.starty,width:a.stopx-a.startx,height:a.stopy-a.starty,fill:a.fill,class:"rect"}).lower()},gqt=function(){return{x:0,y:0,fill:void 0,"text-anchor":"start",width:100,height:100,textMargin:0,rx:0,ry:0}},Oge=function(){return{x:0,y:0,width:100,anchor:"start",height:100,rx:0,ry:0}},sje=function(){function i(w,y,b,E,S,N,B,R){const j=y.append("text").attr("x",b+S/2).attr("y",E+N/2+5).style("font-color",R).style("text-anchor","middle").text(w);p(j,B)}function a(w,y,b,E,S,N,B,R,j){const{taskFontSize:$,taskFontFamily:V}=R,Q=w.split(//gi);for(let oe=0;oe)/).reverse(),w,y=[],b=1.1,E=f.attr("y"),S=parseFloat(f.attr("dy")),N=f.text(null).append("tspan").attr("x",0).attr("y",E).attr("dy",S+"em");for(let B=0;Ba||w==="
")&&(y.pop(),N.text(y.join(" ").trim()),w==="
"?y=[""]:y=[w],N=f.append("tspan").attr("x",0).attr("y",E).attr("dy",b+"em").text(w))})}const bqt=function(i,a,f,p){const w=f%oqt-1,y=i.append("g");a.section=w,y.attr("class",(a.class?a.class+" ":"")+"timeline-node "+("section-"+w));const b=y.append("g"),E=y.append("g"),N=E.append("text").text(a.descr).attr("dy","1em").attr("alignment-baseline","middle").attr("dominant-baseline","middle").attr("text-anchor","middle").call(aje,a.width).node().getBBox(),B=p.fontSize&&p.fontSize.replace?p.fontSize.replace("px",""):p.fontSize;return a.height=N.height+B*1.1*.5+a.padding,a.height=Math.max(a.height,a.maxHeight),a.width=a.width+2*a.padding,E.attr("transform","translate("+a.width/2+", "+a.padding/2+")"),wqt(b,a,w),a},vqt=function(i,a,f){const p=i.append("g"),y=p.append("text").text(a.descr).attr("dy","1em").attr("alignment-baseline","middle").attr("dominant-baseline","middle").attr("text-anchor","middle").call(aje,a.width).node().getBBox(),b=f.fontSize&&f.fontSize.replace?f.fontSize.replace("px",""):f.fontSize;return p.remove(),y.height+b*1.1*.5+a.padding},wqt=function(i,a,f){i.append("path").attr("id","node-"+a.id).attr("class","node-bkg node-"+a.type).attr("d",`M0 ${a.height-5} v${-a.height+2*5} q0,-5 5,-5 h${a.width-2*5} q5,0 5,5 v${a.height-5} H0 Z`),i.append("line").attr("class","node-line-"+f).attr("x1",0).attr("y1",a.height).attr("x2",a.width).attr("y2",a.height)},v9={drawRect:KK,drawCircle:uqt,drawSection:hqt,drawText:rje,drawLabel:lqt,drawTask:fqt,drawBackgroundRect:dqt,getTextObj:gqt,getNoteRect:Oge,initGraphics:pqt,drawNode:bqt,getVirtualNodeHeight:vqt},mqt=function(i,a,f,p){var te,xe,De,he;const w=Tt(),y=w.leftMargin??50;(xe=(te=p.db).clear)==null||xe.call(te),p.parser.parse(i+` +`),Fe.debug("timeline",p.db);const b=w.securityLevel;let E;b==="sandbox"&&(E=Cr("#i"+a));const N=Cr(b==="sandbox"?E.nodes()[0].contentDocument.body:"body").select("#"+a);N.append("g");const B=p.db.getTasks(),R=p.db.getCommonDb().getDiagramTitle();Fe.debug("task",B),v9.initGraphics(N);const j=p.db.getSections();Fe.debug("sections",j);let $=0,V=0,Q=0,oe=0,ce=50+y,se=50;oe=50;let ge=0,ye=!0;j.forEach(function(Ie){const ee={number:ge,descr:Ie,section:ge,width:150,padding:20,maxHeight:$},rt=v9.getVirtualNodeHeight(N,ee,w);Fe.debug("sectionHeight before draw",rt),$=Math.max($,rt+20)});let ke=0,Ae=0;Fe.debug("tasks.length",B.length);for(const[Ie,ee]of B.entries()){const rt={number:Ie,descr:ee,section:ee.section,width:150,padding:20,maxHeight:V},me=v9.getVirtualNodeHeight(N,rt,w);Fe.debug("taskHeight before draw",me),V=Math.max(V,me+20),ke=Math.max(ke,ee.events.length);let gt=0;for(let pe=0;pe0?j.forEach(Ie=>{const ee=B.filter(pe=>pe.section===Ie),rt={number:ge,descr:Ie,section:ge,width:200*Math.max(ee.length,1)-50,padding:20,maxHeight:$};Fe.debug("sectionNode",rt);const me=N.append("g"),gt=v9.drawNode(me,rt,ge,w);Fe.debug("sectionNode output",gt),me.attr("transform",`translate(${ce}, ${oe})`),se+=$+50,ee.length>0&&oje(N,ee,ge,ce,se,V,w,ke,Ae,$,!1),ce+=200*Math.max(ee.length,1),se=oe,ge++}):(ye=!1,oje(N,B,ge,ce,se,V,w,ke,Ae,$,!0));const de=N.node().getBBox();Fe.debug("bounds",de),R&&N.append("text").text(R).attr("x",de.width/2-y).attr("font-size","4ex").attr("font-weight","bold").attr("y",20),Q=ye?$+V+150:V+100,N.append("g").attr("class","lineWrapper").append("line").attr("x1",y).attr("y1",Q).attr("x2",de.width+3*y).attr("y2",Q).attr("stroke-width",4).attr("stroke","black").attr("marker-end","url(#arrowhead)"),YE(void 0,N,((De=w.timeline)==null?void 0:De.padding)??50,((he=w.timeline)==null?void 0:he.useMaxWidth)??!1)},oje=function(i,a,f,p,w,y,b,E,S,N,B){var R;for(const j of a){const $={descr:j.task,section:f,number:f,width:150,padding:20,maxHeight:y};Fe.debug("taskNode",$);const V=i.append("g").attr("class","taskWrapper"),oe=v9.drawNode(V,$,f,b).height;if(Fe.debug("taskHeight after draw",oe),V.attr("transform",`translate(${p}, ${w})`),y=Math.max(y,oe),j.events){const ce=i.append("g").attr("class","lineWrapper");let se=y;w+=100,se=se+yqt(i,j.events,f,p,w,b),w-=100,ce.append("line").attr("x1",p+190/2).attr("y1",w+y).attr("x2",p+190/2).attr("y2",w+y+(B?y:N)+S+120).attr("stroke-width",2).attr("stroke","black").attr("marker-end","url(#arrowhead)").attr("stroke-dasharray","5,5")}p=p+200,B&&!((R=b.timeline)!=null&&R.disableMulticolor)&&f++}w=w-10},yqt=function(i,a,f,p,w,y){let b=0;const E=w;w=w+100;for(const S of a){const N={descr:S,section:f,number:f,width:150,padding:20,maxHeight:50};Fe.debug("eventNode",N);const B=i.append("g").attr("class","eventWrapper"),j=v9.drawNode(B,N,f,y).height;b=b+j,B.attr("transform",`translate(${p}, ${w})`),w=w+10+j}return w=E,b},kqt={setConf:()=>{},draw:mqt},xqt=i=>{let a="";for(let f=0;f` + .edge { + stroke-width: 3; + } + ${xqt(i)} + .section-root rect, .section-root path, .section-root circle { + fill: ${i.git0}; + } + .section-root text { + fill: ${i.gitBranchLabel0}; + } + .icon-container { + height:100%; + display: flex; + justify-content: center; + align-items: center; + } + .edge { + fill: none; + } + .eventWrapper { + filter: brightness(120%); + } +`}},Symbol.toStringTag,{value:"Module"}));var Nge=function(){var i=function(ye,ke,Ae,de){for(Ae=Ae||{},de=ye.length;de--;Ae[ye[de]]=ke);return Ae},a=[1,4],f=[1,13],p=[1,12],w=[1,15],y=[1,16],b=[1,20],E=[1,19],S=[6,7,8],N=[1,26],B=[1,24],R=[1,25],j=[6,7,11],$=[1,6,13,15,16,19,22],V=[1,33],Q=[1,34],oe=[1,6,7,11,13,15,16,19,22],ce={trace:function(){},yy:{},symbols_:{error:2,start:3,mindMap:4,spaceLines:5,SPACELINE:6,NL:7,MINDMAP:8,document:9,stop:10,EOF:11,statement:12,SPACELIST:13,node:14,ICON:15,CLASS:16,nodeWithId:17,nodeWithoutId:18,NODE_DSTART:19,NODE_DESCR:20,NODE_DEND:21,NODE_ID:22,$accept:0,$end:1},terminals_:{2:"error",6:"SPACELINE",7:"NL",8:"MINDMAP",11:"EOF",13:"SPACELIST",15:"ICON",16:"CLASS",19:"NODE_DSTART",20:"NODE_DESCR",21:"NODE_DEND",22:"NODE_ID"},productions_:[0,[3,1],[3,2],[5,1],[5,2],[5,2],[4,2],[4,3],[10,1],[10,1],[10,1],[10,2],[10,2],[9,3],[9,2],[12,2],[12,2],[12,2],[12,1],[12,1],[12,1],[12,1],[12,1],[14,1],[14,1],[18,3],[17,1],[17,4]],performAction:function(ke,Ae,de,ve,te,xe,De){var he=xe.length-1;switch(te){case 6:case 7:return ve;case 8:ve.getLogger().trace("Stop NL ");break;case 9:ve.getLogger().trace("Stop EOF ");break;case 11:ve.getLogger().trace("Stop NL2 ");break;case 12:ve.getLogger().trace("Stop EOF2 ");break;case 15:ve.getLogger().info("Node: ",xe[he].id),ve.addNode(xe[he-1].length,xe[he].id,xe[he].descr,xe[he].type);break;case 16:ve.getLogger().trace("Icon: ",xe[he]),ve.decorateNode({icon:xe[he]});break;case 17:case 21:ve.decorateNode({class:xe[he]});break;case 18:ve.getLogger().trace("SPACELIST");break;case 19:ve.getLogger().trace("Node: ",xe[he].id),ve.addNode(0,xe[he].id,xe[he].descr,xe[he].type);break;case 20:ve.decorateNode({icon:xe[he]});break;case 25:ve.getLogger().trace("node found ..",xe[he-2]),this.$={id:xe[he-1],descr:xe[he-1],type:ve.getType(xe[he-2],xe[he])};break;case 26:this.$={id:xe[he],descr:xe[he],type:ve.nodeType.DEFAULT};break;case 27:ve.getLogger().trace("node found ..",xe[he-3]),this.$={id:xe[he-3],descr:xe[he-1],type:ve.getType(xe[he-2],xe[he])};break}},table:[{3:1,4:2,5:3,6:[1,5],8:a},{1:[3]},{1:[2,1]},{4:6,6:[1,7],7:[1,8],8:a},{6:f,7:[1,10],9:9,12:11,13:p,14:14,15:w,16:y,17:17,18:18,19:b,22:E},i(S,[2,3]),{1:[2,2]},i(S,[2,4]),i(S,[2,5]),{1:[2,6],6:f,12:21,13:p,14:14,15:w,16:y,17:17,18:18,19:b,22:E},{6:f,9:22,12:11,13:p,14:14,15:w,16:y,17:17,18:18,19:b,22:E},{6:N,7:B,10:23,11:R},i(j,[2,22],{17:17,18:18,14:27,15:[1,28],16:[1,29],19:b,22:E}),i(j,[2,18]),i(j,[2,19]),i(j,[2,20]),i(j,[2,21]),i(j,[2,23]),i(j,[2,24]),i(j,[2,26],{19:[1,30]}),{20:[1,31]},{6:N,7:B,10:32,11:R},{1:[2,7],6:f,12:21,13:p,14:14,15:w,16:y,17:17,18:18,19:b,22:E},i($,[2,14],{7:V,11:Q}),i(oe,[2,8]),i(oe,[2,9]),i(oe,[2,10]),i(j,[2,15]),i(j,[2,16]),i(j,[2,17]),{20:[1,35]},{21:[1,36]},i($,[2,13],{7:V,11:Q}),i(oe,[2,11]),i(oe,[2,12]),{21:[1,37]},i(j,[2,25]),i(j,[2,27])],defaultActions:{2:[2,1],6:[2,2]},parseError:function(ke,Ae){if(Ae.recoverable)this.trace(ke);else{var de=new Error(ke);throw de.hash=Ae,de}},parse:function(ke){var Ae=this,de=[0],ve=[],te=[null],xe=[],De=this.table,he="",Ie=0,ee=0,rt=2,me=1,gt=xe.slice.call(arguments,1),pe=Object.create(this.lexer),Et={yy:{}};for(var wt in this.yy)Object.prototype.hasOwnProperty.call(this.yy,wt)&&(Et.yy[wt]=this.yy[wt]);pe.setInput(ke,Et.yy),Et.yy.lexer=pe,Et.yy.parser=this,typeof pe.yylloc>"u"&&(pe.yylloc={});var jt=pe.yylloc;xe.push(jt);var At=pe.options&&pe.options.ranges;typeof Et.yy.parseError=="function"?this.parseError=Et.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Bt(){var Lt;return Lt=ve.pop()||pe.lex()||me,typeof Lt!="number"&&(Lt instanceof Array&&(ve=Lt,Lt=ve.pop()),Lt=Ae.symbols_[Lt]||Lt),Lt}for(var cn,Nn,Ot,oi,kt={},Dt,vt,Nt,ze;;){if(Nn=de[de.length-1],this.defaultActions[Nn]?Ot=this.defaultActions[Nn]:((cn===null||typeof cn>"u")&&(cn=Bt()),Ot=De[Nn]&&De[Nn][cn]),typeof Ot>"u"||!Ot.length||!Ot[0]){var Xe="";ze=[];for(Dt in De[Nn])this.terminals_[Dt]&&Dt>rt&&ze.push("'"+this.terminals_[Dt]+"'");pe.showPosition?Xe="Parse error on line "+(Ie+1)+`: +`+pe.showPosition()+` +Expecting `+ze.join(", ")+", got '"+(this.terminals_[cn]||cn)+"'":Xe="Parse error on line "+(Ie+1)+": Unexpected "+(cn==me?"end of input":"'"+(this.terminals_[cn]||cn)+"'"),this.parseError(Xe,{text:pe.match,token:this.terminals_[cn]||cn,line:pe.yylineno,loc:jt,expected:ze})}if(Ot[0]instanceof Array&&Ot.length>1)throw new Error("Parse Error: multiple actions possible at state: "+Nn+", token: "+cn);switch(Ot[0]){case 1:de.push(cn),te.push(pe.yytext),xe.push(pe.yylloc),de.push(Ot[1]),cn=null,ee=pe.yyleng,he=pe.yytext,Ie=pe.yylineno,jt=pe.yylloc;break;case 2:if(vt=this.productions_[Ot[1]][1],kt.$=te[te.length-vt],kt._$={first_line:xe[xe.length-(vt||1)].first_line,last_line:xe[xe.length-1].last_line,first_column:xe[xe.length-(vt||1)].first_column,last_column:xe[xe.length-1].last_column},At&&(kt._$.range=[xe[xe.length-(vt||1)].range[0],xe[xe.length-1].range[1]]),oi=this.performAction.apply(kt,[he,ee,Ie,Et.yy,Ot[1],te,xe].concat(gt)),typeof oi<"u")return oi;vt&&(de=de.slice(0,-1*vt*2),te=te.slice(0,-1*vt),xe=xe.slice(0,-1*vt)),de.push(this.productions_[Ot[1]][0]),te.push(kt.$),xe.push(kt._$),Nt=De[de[de.length-2]][de[de.length-1]],de.push(Nt);break;case 3:return!0}}return!0}},se=function(){var ye={EOF:1,parseError:function(Ae,de){if(this.yy.parser)this.yy.parser.parseError(Ae,de);else throw new Error(Ae)},setInput:function(ke,Ae){return this.yy=Ae||this.yy||{},this._input=ke,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var ke=this._input[0];this.yytext+=ke,this.yyleng++,this.offset++,this.match+=ke,this.matched+=ke;var Ae=ke.match(/(?:\r\n?|\n).*/g);return Ae?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),ke},unput:function(ke){var Ae=ke.length,de=ke.split(/(?:\r\n?|\n)/g);this._input=ke+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-Ae),this.offset-=Ae;var ve=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),de.length-1&&(this.yylineno-=de.length-1);var te=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:de?(de.length===ve.length?this.yylloc.first_column:0)+ve[ve.length-de.length].length-de[0].length:this.yylloc.first_column-Ae},this.options.ranges&&(this.yylloc.range=[te[0],te[0]+this.yyleng-Ae]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(ke){this.unput(this.match.slice(ke))},pastInput:function(){var ke=this.matched.substr(0,this.matched.length-this.match.length);return(ke.length>20?"...":"")+ke.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var ke=this.match;return ke.length<20&&(ke+=this._input.substr(0,20-ke.length)),(ke.substr(0,20)+(ke.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var ke=this.pastInput(),Ae=new Array(ke.length+1).join("-");return ke+this.upcomingInput()+` +`+Ae+"^"},test_match:function(ke,Ae){var de,ve,te;if(this.options.backtrack_lexer&&(te={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(te.yylloc.range=this.yylloc.range.slice(0))),ve=ke[0].match(/(?:\r\n?|\n).*/g),ve&&(this.yylineno+=ve.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:ve?ve[ve.length-1].length-ve[ve.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+ke[0].length},this.yytext+=ke[0],this.match+=ke[0],this.matches=ke,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(ke[0].length),this.matched+=ke[0],de=this.performAction.call(this,this.yy,this,Ae,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),de)return de;if(this._backtrack){for(var xe in te)this[xe]=te[xe];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var ke,Ae,de,ve;this._more||(this.yytext="",this.match="");for(var te=this._currentRules(),xe=0;xeAe[0].length)){if(Ae=de,ve=xe,this.options.backtrack_lexer){if(ke=this.test_match(de,te[xe]),ke!==!1)return ke;if(this._backtrack){Ae=!1;continue}else return!1}else if(!this.options.flex)break}return Ae?(ke=this.test_match(Ae,te[ve]),ke!==!1?ke:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var Ae=this.next();return Ae||this.lex()},begin:function(Ae){this.conditionStack.push(Ae)},popState:function(){var Ae=this.conditionStack.length-1;return Ae>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(Ae){return Ae=this.conditionStack.length-1-Math.abs(Ae||0),Ae>=0?this.conditionStack[Ae]:"INITIAL"},pushState:function(Ae){this.begin(Ae)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(Ae,de,ve,te){switch(ve){case 0:return Ae.getLogger().trace("Found comment",de.yytext),6;case 1:return 8;case 2:this.begin("CLASS");break;case 3:return this.popState(),16;case 4:this.popState();break;case 5:Ae.getLogger().trace("Begin icon"),this.begin("ICON");break;case 6:return Ae.getLogger().trace("SPACELINE"),6;case 7:return 7;case 8:return 15;case 9:Ae.getLogger().trace("end icon"),this.popState();break;case 10:return Ae.getLogger().trace("Exploding node"),this.begin("NODE"),19;case 11:return Ae.getLogger().trace("Cloud"),this.begin("NODE"),19;case 12:return Ae.getLogger().trace("Explosion Bang"),this.begin("NODE"),19;case 13:return Ae.getLogger().trace("Cloud Bang"),this.begin("NODE"),19;case 14:return this.begin("NODE"),19;case 15:return this.begin("NODE"),19;case 16:return this.begin("NODE"),19;case 17:return this.begin("NODE"),19;case 18:return 13;case 19:return 22;case 20:return 11;case 21:this.begin("NSTR2");break;case 22:return"NODE_DESCR";case 23:this.popState();break;case 24:Ae.getLogger().trace("Starting NSTR"),this.begin("NSTR");break;case 25:return Ae.getLogger().trace("description:",de.yytext),"NODE_DESCR";case 26:this.popState();break;case 27:return this.popState(),Ae.getLogger().trace("node end ))"),"NODE_DEND";case 28:return this.popState(),Ae.getLogger().trace("node end )"),"NODE_DEND";case 29:return this.popState(),Ae.getLogger().trace("node end ...",de.yytext),"NODE_DEND";case 30:return this.popState(),Ae.getLogger().trace("node end (("),"NODE_DEND";case 31:return this.popState(),Ae.getLogger().trace("node end (-"),"NODE_DEND";case 32:return this.popState(),Ae.getLogger().trace("node end (-"),"NODE_DEND";case 33:return this.popState(),Ae.getLogger().trace("node end (("),"NODE_DEND";case 34:return this.popState(),Ae.getLogger().trace("node end (("),"NODE_DEND";case 35:return Ae.getLogger().trace("Long description:",de.yytext),20;case 36:return Ae.getLogger().trace("Long description:",de.yytext),20}},rules:[/^(?:\s*%%.*)/i,/^(?:mindmap\b)/i,/^(?::::)/i,/^(?:.+)/i,/^(?:\n)/i,/^(?:::icon\()/i,/^(?:[\s]+[\n])/i,/^(?:[\n]+)/i,/^(?:[^\)]+)/i,/^(?:\))/i,/^(?:-\))/i,/^(?:\(-)/i,/^(?:\)\))/i,/^(?:\))/i,/^(?:\(\()/i,/^(?:\{\{)/i,/^(?:\()/i,/^(?:\[)/i,/^(?:[\s]+)/i,/^(?:[^\(\[\n\-\)\{\}]+)/i,/^(?:$)/i,/^(?:["][`])/i,/^(?:[^`"]+)/i,/^(?:[`]["])/i,/^(?:["])/i,/^(?:[^"]+)/i,/^(?:["])/i,/^(?:[\)]\))/i,/^(?:[\)])/i,/^(?:[\]])/i,/^(?:\}\})/i,/^(?:\(-)/i,/^(?:-\))/i,/^(?:\(\()/i,/^(?:\()/i,/^(?:[^\)\]\(\}]+)/i,/^(?:.+(?!\(\())/i],conditions:{CLASS:{rules:[3,4],inclusive:!1},ICON:{rules:[8,9],inclusive:!1},NSTR2:{rules:[22,23],inclusive:!1},NSTR:{rules:[25,26],inclusive:!1},NODE:{rules:[21,24,27,28,29,30,31,32,33,34,35,36],inclusive:!1},INITIAL:{rules:[0,1,2,5,6,7,10,11,12,13,14,15,16,17,18,19,20],inclusive:!0}}};return ye}();ce.lexer=se;function ge(){this.yy={}}return ge.prototype=ce,ce.Parser=ge,new ge}();Nge.parser=Nge;const Tqt=Nge,zP=i=>ep(i,Tt());let Jb=[],cje=0,Pge={};const _qt=()=>{Jb=[],cje=0,Pge={}},Cqt=function(i){for(let a=Jb.length-1;a>=0;a--)if(Jb[a].levelJb.length>0?Jb[0]:null,Aqt=(i,a,f,p)=>{Fe.info("addNode",i,a,f,p);const w=Tt(),y={id:cje++,nodeId:zP(a),level:i,descr:zP(f),type:p,children:[],width:Tt().mindmap.maxNodeWidth};switch(y.type){case nl.ROUNDED_RECT:y.padding=2*w.mindmap.padding;break;case nl.RECT:y.padding=2*w.mindmap.padding;break;case nl.HEXAGON:y.padding=2*w.mindmap.padding;break;default:y.padding=w.mindmap.padding}const b=Cqt(i);if(b)b.children.push(y),Jb.push(y);else if(Jb.length===0)Jb.push(y);else{let E=new Error('There can be only one root. No parent could be found for ("'+y.descr+'")');throw E.hash={text:"branch "+name,token:"branch "+name,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:['"checkout '+name+'"']},E}},nl={DEFAULT:0,NO_BORDER:0,ROUNDED_RECT:1,RECT:2,CIRCLE:3,CLOUD:4,BANG:5,HEXAGON:6},Lqt=(i,a)=>{switch(Fe.debug("In get type",i,a),i){case"[":return nl.RECT;case"(":return a===")"?nl.ROUNDED_RECT:nl.CLOUD;case"((":return nl.CIRCLE;case")":return nl.CLOUD;case"))":return nl.BANG;case"{{":return nl.HEXAGON;default:return nl.DEFAULT}},uje=(i,a)=>{Pge[i]=a},Mqt=i=>{const a=Jb[Jb.length-1];i&&i.icon&&(a.icon=zP(i.icon)),i&&i.class&&(a.class=zP(i.class))},w9=i=>{switch(i){case nl.DEFAULT:return"no-border";case nl.RECT:return"rect";case nl.ROUNDED_RECT:return"rounded-rect";case nl.CIRCLE:return"circle";case nl.CLOUD:return"cloud";case nl.BANG:return"bang";case nl.HEXAGON:return"hexgon";default:return"no-border"}};let lje;const Dqt=i=>{lje=i},Iqt=()=>Fe,Oqt=i=>Jb[i],Bge=i=>Pge[i],Nqt=Object.freeze(Object.defineProperty({__proto__:null,addNode:Aqt,clear:_qt,decorateNode:Mqt,getElementById:Bge,getLogger:Iqt,getMindmap:Sqt,getNodeById:Oqt,getType:Lqt,nodeType:nl,get parseError(){return lje},sanitizeText:zP,setElementForId:uje,setErrorHandler:Dqt,type2Str:w9},Symbol.toStringTag,{value:"Module"})),hje=12,Pqt=function(i,a,f){i.append("path").attr("id","node-"+a.id).attr("class","node-bkg node-"+w9(a.type)).attr("d",`M0 ${a.height-5} v${-a.height+2*5} q0,-5 5,-5 h${a.width-2*5} q5,0 5,5 v${a.height-5} H0 Z`),i.append("line").attr("class","node-line-"+f).attr("x1",0).attr("y1",a.height).attr("x2",a.width).attr("y2",a.height)},Bqt=function(i,a){i.append("rect").attr("id","node-"+a.id).attr("class","node-bkg node-"+w9(a.type)).attr("height",a.height).attr("width",a.width)},Rqt=function(i,a){const f=a.width,p=a.height,w=.15*f,y=.25*f,b=.35*f,E=.2*f;i.append("path").attr("id","node-"+a.id).attr("class","node-bkg node-"+w9(a.type)).attr("d",`M0 0 a${w},${w} 0 0,1 ${f*.25},${-1*f*.1} + a${b},${b} 1 0,1 ${f*.4},${-1*f*.1} + a${y},${y} 1 0,1 ${f*.35},${1*f*.2} + + a${w},${w} 1 0,1 ${f*.15},${1*p*.35} + a${E},${E} 1 0,1 ${-1*f*.15},${1*p*.65} + + a${y},${w} 1 0,1 ${-1*f*.25},${f*.15} + a${b},${b} 1 0,1 ${-1*f*.5},0 + a${w},${w} 1 0,1 ${-1*f*.25},${-1*f*.15} + + a${w},${w} 1 0,1 ${-1*f*.1},${-1*p*.35} + a${E},${E} 1 0,1 ${f*.1},${-1*p*.65} + + H0 V0 Z`)},Fqt=function(i,a){const f=a.width,p=a.height,w=.15*f;i.append("path").attr("id","node-"+a.id).attr("class","node-bkg node-"+w9(a.type)).attr("d",`M0 0 a${w},${w} 1 0,0 ${f*.25},${-1*p*.1} + a${w},${w} 1 0,0 ${f*.25},0 + a${w},${w} 1 0,0 ${f*.25},0 + a${w},${w} 1 0,0 ${f*.25},${1*p*.1} + + a${w},${w} 1 0,0 ${f*.15},${1*p*.33} + a${w*.8},${w*.8} 1 0,0 0,${1*p*.34} + a${w},${w} 1 0,0 ${-1*f*.15},${1*p*.33} + + a${w},${w} 1 0,0 ${-1*f*.25},${p*.15} + a${w},${w} 1 0,0 ${-1*f*.25},0 + a${w},${w} 1 0,0 ${-1*f*.25},0 + a${w},${w} 1 0,0 ${-1*f*.25},${-1*p*.15} + + a${w},${w} 1 0,0 ${-1*f*.1},${-1*p*.33} + a${w*.8},${w*.8} 1 0,0 0,${-1*p*.34} + a${w},${w} 1 0,0 ${f*.1},${-1*p*.33} + + H0 V0 Z`)},jqt=function(i,a){i.append("circle").attr("id","node-"+a.id).attr("class","node-bkg node-"+w9(a.type)).attr("r",a.width/2)};function $qt(i,a,f,p,w){return i.insert("polygon",":first-child").attr("points",p.map(function(y){return y.x+","+y.y}).join(" ")).attr("transform","translate("+(w.width-a)/2+", "+f+")")}const Hqt=function(i,a){const f=a.height,w=f/4,y=a.width-a.padding+2*w,b=[{x:w,y:0},{x:y-w,y:0},{x:y,y:-f/2},{x:y-w,y:-f},{x:w,y:-f},{x:0,y:-f/2}];$qt(i,y,f,b,a)},zqt=function(i,a){i.append("rect").attr("id","node-"+a.id).attr("class","node-bkg node-"+w9(a.type)).attr("height",a.height).attr("rx",a.padding).attr("ry",a.padding).attr("width",a.width)},fje={drawNode:function(i,a,f,p){const w=p.htmlLabels,y=f%(hje-1),b=i.append("g");a.section=y;let E="section-"+y;y<0&&(E+=" section-root"),b.attr("class",(a.class?a.class+" ":"")+"mindmap-node "+E);const S=b.append("g"),N=b.append("g"),B=a.descr.replace(/()/g,` +`);dK(N,B,{useHtmlLabels:w,width:a.width,classes:"mindmap-node-label"}),w||N.attr("dy","1em").attr("alignment-baseline","middle").attr("dominant-baseline","middle").attr("text-anchor","middle");const R=N.node().getBBox(),j=p.fontSize.replace?p.fontSize.replace("px",""):p.fontSize;if(a.height=R.height+j*1.1*.5+a.padding,a.width=R.width+2*a.padding,a.icon)if(a.type===nl.CIRCLE)a.height+=50,a.width+=50,b.append("foreignObject").attr("height","50px").attr("width",a.width).attr("style","text-align: center;").append("div").attr("class","icon-container").append("i").attr("class","node-icon-"+y+" "+a.icon),N.attr("transform","translate("+a.width/2+", "+(a.height/2-1.5*a.padding)+")");else{a.width+=50;const $=a.height;a.height=Math.max($,60);const V=Math.abs(a.height-$);b.append("foreignObject").attr("width","60px").attr("height",a.height).attr("style","text-align: center;margin-top:"+V/2+"px;").append("div").attr("class","icon-container").append("i").attr("class","node-icon-"+y+" "+a.icon),N.attr("transform","translate("+(25+a.width/2)+", "+(V/2+a.padding/2)+")")}else if(w){const $=(a.width-R.width)/2,V=(a.height-R.height)/2;N.attr("transform","translate("+$+", "+V+")")}else{const $=a.width/2,V=a.padding/2;N.attr("transform","translate("+$+", "+V+")")}switch(a.type){case nl.DEFAULT:Pqt(S,a,y);break;case nl.ROUNDED_RECT:zqt(S,a);break;case nl.RECT:Bqt(S,a);break;case nl.CIRCLE:S.attr("transform","translate("+a.width/2+", "+ +a.height/2+")"),jqt(S,a);break;case nl.CLOUD:Rqt(S,a);break;case nl.BANG:Fqt(S,a);break;case nl.HEXAGON:Hqt(S,a);break}return uje(a.id,b),a.height},positionNode:function(i){const a=Bge(i.id),f=i.x||0,p=i.y||0;a.attr("transform","translate("+f+","+p+")")},drawEdge:function(a,f,p,w,y){const b=y%(hje-1),E=p.x+p.width/2,S=p.y+p.height/2,N=f.x+f.width/2,B=f.y+f.height/2,R=N>E?E+Math.abs(E-N)/2:E-Math.abs(E-N)/2,j=B>S?S+Math.abs(S-B)/2:S-Math.abs(S-B)/2,$=N>E?Math.abs(E-R)/2+E:-Math.abs(E-R)/2+E,V=B>S?Math.abs(S-j)/2+S:-Math.abs(S-j)/2+S;a.append("path").attr("d",p.direction==="TB"||p.direction==="BT"?`M${E},${S} Q${E},${V} ${R},${j} T${N},${B}`:`M${E},${S} Q${$},${S} ${R},${j} T${N},${B}`).attr("class","edge section-edge-"+b+" edge-depth-"+w)}};var Rge={},Gqt={get exports(){return Rge},set exports(i){Rge=i}};(function(i,a){(function(f,p){i.exports=p()})(Wk,function(){function f(m){return f=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(g){return typeof g}:function(g){return g&&typeof Symbol=="function"&&g.constructor===Symbol&&g!==Symbol.prototype?"symbol":typeof g},f(m)}function p(m,g){if(!(m instanceof g))throw new TypeError("Cannot call a class as a function")}function w(m,g){for(var k=0;km.length)&&(g=m.length);for(var k=0,T=new Array(g);k"u"?null:window,V=$?$.navigator:null;$&&$.document;var Q=f(""),oe=f({}),ce=f(function(){}),se=typeof HTMLElement>"u"?"undefined":f(HTMLElement),ge=function(g){return g&&g.instanceString&&ke(g.instanceString)?g.instanceString():null},ye=function(g){return g!=null&&f(g)==Q},ke=function(g){return g!=null&&f(g)===ce},Ae=function(g){return!he(g)&&(Array.isArray?Array.isArray(g):g!=null&&g instanceof Array)},de=function(g){return g!=null&&f(g)===oe&&!Ae(g)&&g.constructor===Object},ve=function(g){return g!=null&&f(g)===oe},te=function(g){return g!=null&&f(g)===f(1)&&!isNaN(g)},xe=function(g){return te(g)&&Math.floor(g)===g},De=function(g){if(se!=="undefined")return g!=null&&g instanceof HTMLElement},he=function(g){return Ie(g)||ee(g)},Ie=function(g){return ge(g)==="collection"&&g._private.single},ee=function(g){return ge(g)==="collection"&&!g._private.single},rt=function(g){return ge(g)==="core"},me=function(g){return ge(g)==="stylesheet"},gt=function(g){return ge(g)==="event"},pe=function(g){return g==null?!0:!!(g===""||g.match(/^\s+$/))},Et=function(g){return typeof HTMLElement>"u"?!1:g instanceof HTMLElement},wt=function(g){return de(g)&&te(g.x1)&&te(g.x2)&&te(g.y1)&&te(g.y2)},jt=function(g){return ve(g)&&ke(g.then)},At=function(){return V&&V.userAgent.match(/msie|trident|edge/i)},Bt=function(g,k){k||(k=function(){if(arguments.length===1)return arguments[0];if(arguments.length===0)return"undefined";for(var D=[],I=0;Ik?1:0},Bn=function(g,k){return-1*Ge(g,k)},Oe=Object.assign!=null?Object.assign.bind(Object):function(m){for(var g=arguments,k=1;k1&&(_e-=1),_e<1/6?ae+(ue-ae)*6*_e:_e<1/2?ue:_e<2/3?ae+(ue-ae)*(2/3-_e)*6:ae}var U=new RegExp("^"+Nt+"$").exec(g);if(U){if(T=parseInt(U[1]),T<0?T=(360- -1*T%360)%360:T>360&&(T=T%360),T/=360,A=parseFloat(U[2]),A<0||A>100||(A=A/100,D=parseFloat(U[3]),D<0||D>100)||(D=D/100,I=U[4],I!==void 0&&(I=parseFloat(I),I<0||I>1)))return;if(A===0)F=H=C=Math.round(D*255);else{var Z=D<.5?D*(1+A):D+A-D*A,ne=2*D-Z;F=Math.round(255*G(ne,Z,T+1/3)),H=Math.round(255*G(ne,Z,T)),C=Math.round(255*G(ne,Z,T-1/3))}k=[F,H,C,I]}return k},hi=function(g){var k,T=new RegExp("^"+Dt+"$").exec(g);if(T){k=[];for(var A=[],D=1;D<=3;D++){var I=T[D];if(I[I.length-1]==="%"&&(A[D]=!0),I=parseFloat(I),A[D]&&(I=I/100*255),I<0||I>255)return;k.push(Math.floor(I))}var F=A[1]||A[2]||A[3],H=A[1]&&A[2]&&A[3];if(F&&!H)return;var C=T[4];if(C!==void 0){if(C=parseFloat(C),C<0||C>1)return;k.push(C)}}return k},Sr=function(g){return Xn[g.toLowerCase()]},Zn=function(g){return(Ae(g)?g:null)||Sr(g)||Ri(g)||hi(g)||tn(g)},Xn={transparent:[0,0,0,0],aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],grey:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},ir=function(g){for(var k=g.map,T=g.keys,A=T.length,D=0;D=g||Re<0||U&&Ze>=D}function be(){var qe=Er();if(_e(qe))return Se(qe);F=setTimeout(be,ue(qe))}function Se(qe){return F=void 0,Z&&T?ne(qe):(T=A=void 0,I)}function Le(){F!==void 0&&clearTimeout(F),C=0,T=H=A=F=void 0}function Be(){return F===void 0?I:Se(Er())}function Ke(){var qe=Er(),Re=_e(qe);if(T=arguments,A=this,H=qe,Re){if(F===void 0)return ae(H);if(U)return clearTimeout(F),F=setTimeout(be,g),ne(H)}return F===void 0&&(F=setTimeout(be,g)),I}return Ke.cancel=Le,Ke.flush=Be,Ke}var im=bL,ug=$?$.performance:null,rs=ug&&ug.now?function(){return ug.now()}:function(){return Date.now()},Ps=function(){if($){if($.requestAnimationFrame)return function(m){$.requestAnimationFrame(m)};if($.mozRequestAnimationFrame)return function(m){$.mozRequestAnimationFrame(m)};if($.webkitRequestAnimationFrame)return function(m){$.webkitRequestAnimationFrame(m)};if($.msRequestAnimationFrame)return function(m){$.msRequestAnimationFrame(m)}}return function(m){m&&setTimeout(function(){m(rs())},1e3/60)}}(),Aa=function(g){return Ps(g)},pi=rs,Rc=9261,_t=65599,hp=5381,Gt=function(g){for(var k=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Rc,T=k,A;A=g.next(),!A.done;)T=T*_t+A.value|0;return T},ff=function(g){var k=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Rc;return k*_t+g|0},sm=function(g){var k=arguments.length>1&&arguments[1]!==void 0?arguments[1]:hp;return(k<<5)+k+g|0},m9=function(g,k){return g*2097152+k},fp=function(g){return g[0]*2097152+g[1]},N5=function(g,k){return[ff(g[0],k[0]),sm(g[1],k[1])]},ah=function(g,k){var T={value:0,done:!1},A=0,D=g.length,I={next:function(){return A=0&&!(g[A]===k&&(g.splice(A,1),T));A--);},wL=function(g){g.splice(0,g.length)},qP=function(g,k){for(var T=0;T"u"?"undefined":f(Set))!==eY?Set:tY,x9=function(g,k){var T=arguments.length>2&&arguments[2]!==void 0?arguments[2]:!0;if(g===void 0||k===void 0||!rt(g)){yc("An element must have a core reference and parameters set");return}var A=k.group;if(A==null&&(k.data&&k.data.source!=null&&k.data.target!=null?A="edges":A="nodes"),A!=="nodes"&&A!=="edges"){yc("An element must be of type `nodes` or `edges`; you specified `"+A+"`");return}this.length=1,this[0]=this;var D=this._private={cy:g,single:!0,data:k.data||{},position:k.position||{x:0,y:0},autoWidth:void 0,autoHeight:void 0,autoPadding:void 0,compoundBoundsClean:!1,listeners:[],group:A,style:{},rstyle:{},styleCxts:[],styleKeys:{},removed:!0,selected:!!k.selected,selectable:k.selectable===void 0?!0:!!k.selectable,locked:!!k.locked,grabbed:!1,grabbable:k.grabbable===void 0?!0:!!k.grabbable,pannable:k.pannable===void 0?A==="edges":!!k.pannable,active:!1,classes:new R5,animation:{current:[],queue:[]},rscratch:{},scratch:k.scratch||{},edges:[],children:[],parent:k.parent&&k.parent.isNode()?k.parent:null,traversalCache:{},backgrounding:!1,bbCache:null,bbCacheShift:{x:0,y:0},bodyBounds:null,overlayBounds:null,labelBounds:{all:null,source:null,target:null,main:null},arrowBounds:{source:null,target:null,"mid-source":null,"mid-target":null}};if(D.position.x==null&&(D.position.x=0),D.position.y==null&&(D.position.y=0),k.renderedPosition){var I=k.renderedPosition,F=g.pan(),H=g.zoom();D.position={x:(I.x-F.x)/H,y:(I.y-F.y)/H}}var C=[];Ae(k.classes)?C=k.classes:ye(k.classes)&&(C=k.classes.split(/\s+/));for(var G=0,U=C.length;GSe?1:0},G=function(be,Se,Le,Be,Ke){var qe;if(Le==null&&(Le=0),Ke==null&&(Ke=T),Le<0)throw new Error("lo must be non-negative");for(Be==null&&(Be=be.length);Leot;0<=ot?$e++:$e--)Ze.push($e);return Ze}.apply(this).reverse(),Re=[],Be=0,Ke=qe.length;Beut;0<=ut?++Ze:--Ze)Je.push(I(be,Le));return Je},ue=function(be,Se,Le,Be){var Ke,qe,Re;for(Be==null&&(Be=T),Ke=be[Le];Le>Se;){if(Re=Le-1>>1,qe=be[Re],Be(Ke,qe)<0){be[Le]=qe,Le=Re;continue}break}return be[Le]=Ke},_e=function(be,Se,Le){var Be,Ke,qe,Re,Ze;for(Le==null&&(Le=T),Ke=be.length,Ze=Se,qe=be[Se],Be=2*Se+1;Be0;){var qe=Se.pop(),Re=_e(qe),Ze=qe.id();if(Z[Ze]=Re,Re!==1/0)for(var $e=qe.neighborhood().intersect(ae),ot=0;ot<$e.length;ot++){var ut=$e[ot],Je=ut.id(),Ct=Ke(qe,ut),lt=Re+Ct.dist;lt<_e(ut)&&(be(ut,lt),U[Je]={node:qe,edge:Ct.edge})}}return{distanceTo:function(Rt){var $t=ye(Rt)?ae.filter(Rt)[0]:Rt[0];return Z[$t.id()]},pathTo:function(Rt){var $t=ye(Rt)?ae.filter(Rt)[0]:Rt[0],bn=[],Cn=$t,Kn=Cn.id();if($t.length>0)for(bn.unshift($t);U[Kn];){var kn=U[Kn];bn.unshift(kn.edge),bn.unshift(kn.node),Cn=kn.node,Kn=Cn.id()}return F.spawn(bn)}}}},sY={kruskal:function(g){g=g||function(Le){return 1};for(var k=this.byGroup(),T=k.nodes,A=k.edges,D=T.length,I=new Array(D),F=T,H=function(Be){for(var Ke=0;Ke0;){if(Ke(),Re++,Be===G){for(var Ze=[],$e=D,ot=G,ut=be[ot];Ze.unshift($e),ut!=null&&Ze.unshift(ut),$e=_e[ot],$e!=null;)ot=$e.id(),ut=be[ot];return{found:!0,distance:U[Be],path:this.spawn(Ze),steps:Re}}ne[Be]=!0;for(var Je=Le._private.edges,Ct=0;Ctut&&(ae[ot]=ut,Se[ot]=$e,Le[ot]=Ke),!D){var Je=$e*G+Ze;!D&&ae[Je]>ut&&(ae[Je]=ut,Se[Je]=Ze,Le[Je]=Ke)}}}for(var Ct=0;Ct1&&arguments[1]!==void 0?arguments[1]:I,eo=Le(Di),sa=[],Ks=eo;;){if(Ks==null)return k.spawn();var Ar=Se(Ks),We=Ar.edge,On=Ar.pred;if(sa.unshift(Ks[0]),Ks.same(es)&&sa.length>0)break;We!=null&&sa.unshift(We),Ks=On}return H.spawn(sa)},qe=0;qe=0;G--){var U=C[G],Z=U[1],ne=U[2];(k[Z]===F&&k[ne]===H||k[Z]===H&&k[ne]===F)&&C.splice(G,1)}for(var ae=0;aeA;){var D=Math.floor(Math.random()*k.length);k=dY(D,g,k),T--}return k},gY={kargerStein:function(){var g=this,k=this.byGroup(),T=k.nodes,A=k.edges;A.unmergeBy(function(bn){return bn.isLoop()});var D=T.length,I=A.length,F=Math.ceil(Math.pow(Math.log(D)/Math.LN2,2)),H=Math.floor(D/fY);if(D<2){yc("At least 2 nodes are required for Karger-Stein algorithm");return}for(var C=[],G=0;G1&&arguments[1]!==void 0?arguments[1]:0,T=arguments.length>2&&arguments[2]!==void 0?arguments[2]:g.length,A=1/0,D=k;D1&&arguments[1]!==void 0?arguments[1]:0,T=arguments.length>2&&arguments[2]!==void 0?arguments[2]:g.length,A=-1/0,D=k;D1&&arguments[1]!==void 0?arguments[1]:0,T=arguments.length>2&&arguments[2]!==void 0?arguments[2]:g.length,A=0,D=0,I=k;I1&&arguments[1]!==void 0?arguments[1]:0,T=arguments.length>2&&arguments[2]!==void 0?arguments[2]:g.length,A=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!0,D=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,I=arguments.length>5&&arguments[5]!==void 0?arguments[5]:!0;A?g=g.slice(k,T):(T0&&g.splice(0,k));for(var F=0,H=g.length-1;H>=0;H--){var C=g[H];I?isFinite(C)||(g[H]=-1/0,F++):g.splice(H,1)}D&&g.sort(function(Z,ne){return Z-ne});var G=g.length,U=Math.floor(G/2);return G%2!==0?g[U+1+F]:(g[U-1+F]+g[U+F])/2},yY=function(g){return Math.PI*g/180},T9=function(g,k){return Math.atan2(k,g)-Math.PI/2},yL=Math.log2||function(m){return Math.log(m)/Math.log(2)},WP=function(g){return g>0?1:g<0?-1:0},v3=function(g,k){return Math.sqrt(w3(g,k))},w3=function(g,k){var T=k.x-g.x,A=k.y-g.y;return T*T+A*A},kY=function(g){for(var k=g.length,T=0,A=0;A=g.x1&&g.y2>=g.y1)return{x1:g.x1,y1:g.y1,x2:g.x2,y2:g.y2,w:g.x2-g.x1,h:g.y2-g.y1};if(g.w!=null&&g.h!=null&&g.w>=0&&g.h>=0)return{x1:g.x1,y1:g.y1,x2:g.x1+g.w,y2:g.y1+g.h,w:g.w,h:g.h}}},EY=function(g){return{x1:g.x1,x2:g.x2,w:g.w,y1:g.y1,y2:g.y2,h:g.h}},TY=function(g){g.x1=1/0,g.y1=1/0,g.x2=-1/0,g.y2=-1/0,g.w=0,g.h=0},_Y=function(g,k){g.x1=Math.min(g.x1,k.x1),g.x2=Math.max(g.x2,k.x2),g.w=g.x2-g.x1,g.y1=Math.min(g.y1,k.y1),g.y2=Math.max(g.y2,k.y2),g.h=g.y2-g.y1},CY=function(g,k,T){g.x1=Math.min(g.x1,k),g.x2=Math.max(g.x2,k),g.w=g.x2-g.x1,g.y1=Math.min(g.y1,T),g.y2=Math.max(g.y2,T),g.h=g.y2-g.y1},_9=function(g){var k=arguments.length>1&&arguments[1]!==void 0?arguments[1]:0;return g.x1-=k,g.x2+=k,g.y1-=k,g.y2+=k,g.w=g.x2-g.x1,g.h=g.y2-g.y1,g},kL=function(g){var k=arguments.length>1&&arguments[1]!==void 0?arguments[1]:[0],T,A,D,I;if(k.length===1)T=A=D=I=k[0];else if(k.length===2)T=D=k[0],I=A=k[1];else if(k.length===4){var F=E(k,4);T=F[0],A=F[1],D=F[2],I=F[3]}return g.x1-=I,g.x2+=A,g.y1-=T,g.y2+=D,g.w=g.x2-g.x1,g.h=g.y2-g.y1,g},KP=function(g,k){g.x1=k.x1,g.y1=k.y1,g.x2=k.x2,g.y2=k.y2,g.w=g.x2-g.x1,g.h=g.y2-g.y1},xL=function(g,k){return!(g.x1>k.x2||k.x1>g.x2||g.x2k.y2||k.y1>g.y2)},$5=function(g,k,T){return g.x1<=k&&k<=g.x2&&g.y1<=T&&T<=g.y2},SY=function(g,k){return $5(g,k.x,k.y)},YP=function(g,k){return $5(g,k.x1,k.y1)&&$5(g,k.x2,k.y2)},XP=function(g,k,T,A,D,I,F){var H=wx(D,I),C=D/2,G=I/2,U;{var Z=T-C+H-F,ne=A-G-F,ae=T+C-H+F,ue=ne;if(U=lm(g,k,T,A,Z,ne,ae,ue,!1),U.length>0)return U}{var _e=T+C+F,be=A-G+H-F,Se=_e,Le=A+G-H+F;if(U=lm(g,k,T,A,_e,be,Se,Le,!1),U.length>0)return U}{var Be=T-C+H-F,Ke=A+G+F,qe=T+C-H+F,Re=Ke;if(U=lm(g,k,T,A,Be,Ke,qe,Re,!1),U.length>0)return U}{var Ze=T-C-F,$e=A-G+H-F,ot=Ze,ut=A+G-H+F;if(U=lm(g,k,T,A,Ze,$e,ot,ut,!1),U.length>0)return U}var Je;{var Ct=T-C+H,lt=A-G+H;if(Je=bx(g,k,T,A,Ct,lt,H+F),Je.length>0&&Je[0]<=Ct&&Je[1]<=lt)return[Je[0],Je[1]]}{var un=T+C-H,Rt=A-G+H;if(Je=bx(g,k,T,A,un,Rt,H+F),Je.length>0&&Je[0]>=un&&Je[1]<=Rt)return[Je[0],Je[1]]}{var $t=T+C-H,bn=A+G-H;if(Je=bx(g,k,T,A,$t,bn,H+F),Je.length>0&&Je[0]>=$t&&Je[1]>=bn)return[Je[0],Je[1]]}{var Cn=T-C+H,Kn=A+G-H;if(Je=bx(g,k,T,A,Cn,Kn,H+F),Je.length>0&&Je[0]<=Cn&&Je[1]>=Kn)return[Je[0],Je[1]]}return[]},AY=function(g,k,T,A,D,I,F){var H=F,C=Math.min(T,D),G=Math.max(T,D),U=Math.min(A,I),Z=Math.max(A,I);return C-H<=g&&g<=G+H&&U-H<=k&&k<=Z+H},LY=function(g,k,T,A,D,I,F,H,C){var G={x1:Math.min(T,F,D)-C,x2:Math.max(T,F,D)+C,y1:Math.min(A,H,I)-C,y2:Math.max(A,H,I)+C};return!(gG.x2||kG.y2)},MY=function(g,k,T,A){T-=A;var D=k*k-4*g*T;if(D<0)return[];var I=Math.sqrt(D),F=2*g,H=(-k+I)/F,C=(-k-I)/F;return[H,C]},DY=function(g,k,T,A,D){var I=1e-5;g===0&&(g=I),k/=g,T/=g,A/=g;var F,H,C,G,U,Z,ne,ae;if(H=(3*T-k*k)/9,C=-(27*A)+k*(9*T-2*(k*k)),C/=54,F=H*H*H+C*C,D[1]=0,ne=k/3,F>0){U=C+Math.sqrt(F),U=U<0?-Math.pow(-U,1/3):Math.pow(U,1/3),Z=C-Math.sqrt(F),Z=Z<0?-Math.pow(-Z,1/3):Math.pow(Z,1/3),D[0]=-ne+U+Z,ne+=(U+Z)/2,D[4]=D[2]=-ne,ne=Math.sqrt(3)*(-Z+U)/2,D[3]=ne,D[5]=-ne;return}if(D[5]=D[3]=0,F===0){ae=C<0?-Math.pow(-C,1/3):Math.pow(C,1/3),D[0]=-ne+2*ae,D[4]=D[2]=-(ae+ne);return}H=-H,G=H*H*H,G=Math.acos(C/Math.sqrt(G)),ae=2*Math.sqrt(H),D[0]=-ne+ae*Math.cos(G/3),D[2]=-ne+ae*Math.cos((G+2*Math.PI)/3),D[4]=-ne+ae*Math.cos((G+4*Math.PI)/3)},IY=function(g,k,T,A,D,I,F,H){var C=1*T*T-4*T*D+2*T*F+4*D*D-4*D*F+F*F+A*A-4*A*I+2*A*H+4*I*I-4*I*H+H*H,G=1*9*T*D-3*T*T-3*T*F-6*D*D+3*D*F+9*A*I-3*A*A-3*A*H-6*I*I+3*I*H,U=1*3*T*T-6*T*D+T*F-T*g+2*D*D+2*D*g-F*g+3*A*A-6*A*I+A*H-A*k+2*I*I+2*I*k-H*k,Z=1*T*D-T*T+T*g-D*g+A*I-A*A+A*k-I*k,ne=[];DY(C,G,U,Z,ne);for(var ae=1e-7,ue=[],_e=0;_e<6;_e+=2)Math.abs(ne[_e+1])=0&&ne[_e]<=1&&ue.push(ne[_e]);ue.push(1),ue.push(0);for(var be=-1,Se,Le,Be,Ke=0;Ke=0?BeC?(g-D)*(g-D)+(k-I)*(k-I):G-Z},Gd=function(g,k,T){for(var A,D,I,F,H,C=0,G=0;G=g&&g>=I||A<=g&&g<=I)H=(g-A)/(I-A)*(F-D)+D,H>k&&C++;else continue;return C%2!==0},tv=function(g,k,T,A,D,I,F,H,C){var G=new Array(T.length),U;H[0]!=null?(U=Math.atan(H[1]/H[0]),H[0]<0?U=U+Math.PI/2:U=-U-Math.PI/2):U=H;for(var Z=Math.cos(-U),ne=Math.sin(-U),ae=0;ae0){var _e=ZP(G,-C);ue=QP(_e)}else ue=G;return Gd(g,k,ue)},NY=function(g,k,T,A,D,I,F){for(var H=new Array(T.length),C=I/2,G=F/2,U=_L(I,F),Z=U*U,ne=0;ne=0&&_e<=1&&Se.push(_e),be>=0&&be<=1&&Se.push(be),Se.length===0)return[];var Le=Se[0]*H[0]+g,Be=Se[0]*H[1]+k;if(Se.length>1){if(Se[0]==Se[1])return[Le,Be];var Ke=Se[1]*H[0]+g,qe=Se[1]*H[1]+k;return[Le,Be,Ke,qe]}else return[Le,Be]},EL=function(g,k,T){return k<=g&&g<=T||T<=g&&g<=k?g:g<=k&&k<=T||T<=k&&k<=g?k:T},lm=function(g,k,T,A,D,I,F,H,C){var G=g-D,U=T-g,Z=F-D,ne=k-I,ae=A-k,ue=H-I,_e=Z*ne-ue*G,be=U*ne-ae*G,Se=ue*U-Z*ae;if(Se!==0){var Le=_e/Se,Be=be/Se,Ke=.001,qe=0-Ke,Re=1+Ke;return qe<=Le&&Le<=Re&&qe<=Be&&Be<=Re?[g+Le*U,k+Le*ae]:C?[g+Le*U,k+Le*ae]:[]}else return _e===0||be===0?EL(g,T,F)===F?[F,H]:EL(g,T,D)===D?[D,I]:EL(D,F,T)===T?[T,A]:[]:[]},vx=function(g,k,T,A,D,I,F,H){var C=[],G,U=new Array(T.length),Z=!0;I==null&&(Z=!1);var ne;if(Z){for(var ae=0;ae0){var ue=ZP(U,-H);ne=QP(ue)}else ne=U}else ne=T;for(var _e,be,Se,Le,Be=0;Be2){for(var Rt=[C[0],C[1]],$t=Math.pow(Rt[0]-g,2)+Math.pow(Rt[1]-k,2),bn=1;bnG&&(G=Be)},get:function(Le){return C[Le]}},Z=0;Z0?Rt=un.edgesTo(lt)[0]:Rt=lt.edgesTo(un)[0];var $t=A(Rt);lt=lt.id(),Ze[lt]>Ze[Je]+$t&&(Ze[lt]=Ze[Je]+$t,$e.nodes.indexOf(lt)<0?$e.push(lt):$e.updateItem(lt),Re[lt]=0,qe[lt]=[]),Ze[lt]==Ze[Je]+$t&&(Re[lt]=Re[lt]+Re[Je],qe[lt].push(Je))}else for(var bn=0;bn0;){for(var Wn=Ke.pop(),sr=0;sr0&&F.push(T[H]);F.length!==0&&D.push(A.collection(F))}return D},YY=function(g,k){for(var T=0;T5&&arguments[5]!==void 0?arguments[5]:ZY,F=A,H,C,G=0;G=2?mx(g,k,T,0,cB,JY):mx(g,k,T,0,oB)},squaredEuclidean:function(g,k,T){return mx(g,k,T,0,cB)},manhattan:function(g,k,T){return mx(g,k,T,0,oB)},max:function(g,k,T){return mx(g,k,T,-1/0,eX)}};G5["squared-euclidean"]=G5.squaredEuclidean,G5.squaredeuclidean=G5.squaredEuclidean;function S9(m,g,k,T,A,D){var I;return ke(m)?I=m:I=G5[m]||G5.euclidean,g===0&&ke(m)?I(A,D):I(g,k,T,A,D)}var tX=Vf({k:2,m:2,sensitivityThreshold:1e-4,distance:"euclidean",maxIterations:10,attributes:[],testMode:!1,testCentroids:null}),AL=function(g){return tX(g)},A9=function(g,k,T,A,D){var I=D!=="kMedoids",F=I?function(U){return T[U]}:function(U){return A[U](T)},H=function(Z){return A[Z](k)},C=T,G=k;return S9(g,A.length,F,H,C,G)},LL=function(g,k,T){for(var A=T.length,D=new Array(A),I=new Array(A),F=new Array(k),H=null,C=0;CT)return!1}return!0},iX=function(g,k,T){for(var A=0;AF&&(F=k[C][G],H=G);D[H].push(g[C])}for(var U=0;U=D.threshold||D.mode==="dendrogram"&&g.length===1)return!1;var ae=k[I],ue=k[A[I]],_e;D.mode==="dendrogram"?_e={left:ae,right:ue,key:ae.key}:_e={value:ae.value.concat(ue.value),key:ae.key},g[ae.index]=_e,g.splice(ue.index,1),k[ae.key]=_e;for(var be=0;beT[ue.key][Se.key]&&(H=T[ue.key][Se.key])):D.linkage==="max"?(H=T[ae.key][Se.key],T[ae.key][Se.key]0&&A.push(D);return A},bB=function(g,k,T){for(var A=[],D=0;DF&&(I=C,F=k[D*g+C])}I>0&&A.push(I)}for(var G=0;GC&&(H=G,C=U)}T[D]=I[H]}return A=bB(g,k,T),A},vB=function(g){for(var k=this.cy(),T=this.nodes(),A=wX(g),D={},I=0;I=ut?(Je=ut,ut=lt,Ct=un):lt>Je&&(Je=lt);for(var Rt=0;Rt0?1:0;Re[$e%A.minIterations*F+Wn]=sr,kn+=sr}if(kn>0&&($e>=A.minIterations-1||$e==A.maxIterations-1)){for(var yr=0,hr=0;hr1||qe>1)&&(F=!0),U[Le]=[],Se.outgoers().forEach(function(Ze){Ze.isEdge()&&U[Le].push(Ze.id())})}else Z[Le]=[void 0,Se.target().id()]}):I.forEach(function(Se){var Le=Se.id();if(Se.isNode()){var Be=Se.degree(!0);Be%2&&(H?C?F=!0:C=Le:H=Le),U[Le]=[],Se.connectedEdges().forEach(function(Ke){return U[Le].push(Ke.id())})}else Z[Le]=[Se.source().id(),Se.target().id()]});var ne={found:!1,trail:void 0};if(F)return ne;if(C&&H)if(D){if(G&&C!=G)return ne;G=C}else{if(G&&C!=G&&H!=G)return ne;G||(G=C)}else G||(G=I[0].id());var ae=function(Le){for(var Be=Le,Ke=[Le],qe,Re,Ze;U[Be].length;)qe=U[Be].shift(),Re=Z[qe][0],Ze=Z[qe][1],Be!=Ze?(U[Ze]=U[Ze].filter(function($e){return $e!=qe}),Be=Ze):!D&&Be!=Re&&(U[Re]=U[Re].filter(function($e){return $e!=qe}),Be=Re),Ke.unshift(qe),Ke.unshift(Be);return Ke},ue=[],_e=[];for(_e=ae(G);_e.length!=1;)U[_e[0]].length==0?(ue.unshift(I.getElementById(_e.shift())),ue.unshift(I.getElementById(_e.shift()))):_e=ae(_e.shift()).concat(_e);ue.unshift(I.getElementById(_e.shift()));for(var be in U)if(U[be].length)return ne;return ne.found=!0,ne.trail=this.spawn(ue,!0),ne}},M9=function(){var g=this,k={},T=0,A=0,D=[],I=[],F={},H=function(Z,ne){for(var ae=I.length-1,ue=[],_e=g.spawn();I[ae].x!=Z||I[ae].y!=ne;)ue.push(I.pop().edge),ae--;ue.push(I.pop().edge),ue.forEach(function(be){var Se=be.connectedNodes().intersection(g);_e.merge(be),Se.forEach(function(Le){var Be=Le.id(),Ke=Le.connectedEdges().intersection(g);_e.merge(Le),k[Be].cutVertex?_e.merge(Ke.filter(function(qe){return qe.isLoop()})):_e.merge(Ke)})}),D.push(_e)},C=function U(Z,ne,ae){Z===ae&&(A+=1),k[ne]={id:T,low:T++,cutVertex:!1};var ue=g.getElementById(ne).connectedEdges().intersection(g);if(ue.size()===0)D.push(g.spawn(g.getElementById(ne)));else{var _e,be,Se,Le;ue.forEach(function(Be){_e=Be.source().id(),be=Be.target().id(),Se=_e===ne?be:_e,Se!==ae&&(Le=Be.id(),F[Le]||(F[Le]=!0,I.push({x:ne,y:Se,edge:Be})),Se in k?k[ne].low=Math.min(k[ne].low,k[Se].id):(U(Z,Se,ne),k[ne].low=Math.min(k[ne].low,k[Se].low),k[ne].id<=k[Se].low&&(k[ne].cutVertex=!0,H(ne,Se))))})}};g.forEach(function(U){if(U.isNode()){var Z=U.id();Z in k||(A=0,C(Z,Z),k[Z].cutVertex=A>1)}});var G=Object.keys(k).filter(function(U){return k[U].cutVertex}).map(function(U){return g.getElementById(U)});return{cut:g.spawn(G),components:D}},CX={hopcroftTarjanBiconnected:M9,htbc:M9,htb:M9,hopcroftTarjanBiconnectedComponents:M9},D9=function(){var g=this,k={},T=0,A=[],D=[],I=g.spawn(g),F=function H(C){D.push(C),k[C]={index:T,low:T++,explored:!1};var G=g.getElementById(C).connectedEdges().intersection(g);if(G.forEach(function(ue){var _e=ue.target().id();_e!==C&&(_e in k||H(_e),k[_e].explored||(k[C].low=Math.min(k[C].low,k[_e].low)))}),k[C].index===k[C].low){for(var U=g.spawn();;){var Z=D.pop();if(U.merge(g.getElementById(Z)),k[Z].low=k[C].index,k[Z].explored=!0,Z===C)break}var ne=U.edgesWith(U),ae=U.merge(ne);A.push(ae),I=I.difference(ae)}};return g.forEach(function(H){if(H.isNode()){var C=H.id();C in k||F(C)}}),{cut:I,components:A}},SX={tarjanStronglyConnected:D9,tsc:D9,tscc:D9,tarjanStronglyConnectedComponents:D9},wB={};[dx,iY,sY,oY,uY,hY,gY,jY,H5,z5,SL,QY,lX,bX,EX,_X,CX,SX].forEach(function(m){Oe(wB,m)});/*! +Embeddable Minimum Strictly-Compliant Promises/A+ 1.1.1 Thenable +Copyright (c) 2013-2014 Ralf S. Engelschall (http://engelschall.com) +Licensed under The MIT License (http://opensource.org/licenses/MIT) +*/var mB=0,yB=1,kB=2,nv=function m(g){if(!(this instanceof m))return new m(g);this.id="Thenable/1.0.7",this.state=mB,this.fulfillValue=void 0,this.rejectReason=void 0,this.onFulfilled=[],this.onRejected=[],this.proxy={then:this.then.bind(this)},typeof g=="function"&&g.call(this,this.fulfill.bind(this),this.reject.bind(this))};nv.prototype={fulfill:function(g){return xB(this,yB,"fulfillValue",g)},reject:function(g){return xB(this,kB,"rejectReason",g)},then:function(g,k){var T=this,A=new nv;return T.onFulfilled.push(_B(g,A,"fulfill")),T.onRejected.push(_B(k,A,"reject")),EB(T),A.proxy}};var xB=function(g,k,T,A){return g.state===mB&&(g.state=k,g[T]=A,EB(g)),g},EB=function(g){g.state===yB?TB(g,"onFulfilled",g.fulfillValue):g.state===kB&&TB(g,"onRejected",g.rejectReason)},TB=function(g,k,T){if(g[k].length!==0){var A=g[k];g[k]=[];var D=function(){for(var F=0;F0}},clearQueue:function(){return function(){var k=this,T=k.length!==void 0,A=T?k:[k],D=this._private.cy||this;if(!D.styleEnabled())return this;for(var I=0;I-1}var AQ=SQ;function LQ(m,g){var k=this.__data__,T=N9(k,m);return T<0?(++this.size,k.push([m,g])):k[T][1]=g,this}var MQ=LQ;function U5(m){var g=-1,k=m==null?0:m.length;for(this.clear();++g-1&&m%1==0&&m0&&this.spawn(A).updateStyle().emit("class"),k},addClass:function(g){return this.toggleClass(g,!0)},hasClass:function(g){var k=this[0];return k!=null&&k._private.classes.has(g)},toggleClass:function(g,k){Ae(g)||(g=g.match(/\S+/g)||[]);for(var T=this,A=k===void 0,D=[],I=0,F=T.length;I0&&this.spawn(D).updateStyle().emit("class"),T},removeClass:function(g){return this.toggleClass(g,!1)},flashClass:function(g,k){var T=this;if(k==null)k=250;else if(k===0)return T;return T.addClass(g),setTimeout(function(){T.removeClass(g)},k),T}};F9.className=F9.classNames=F9.classes;var lc={metaChar:"[\\!\\\"\\#\\$\\%\\&\\'\\(\\)\\*\\+\\,\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\]\\^\\`\\{\\|\\}\\~]",comparatorOp:"=|\\!=|>|>=|<|<=|\\$=|\\^=|\\*=",boolOp:"\\?|\\!|\\^",string:`"(?:\\\\"|[^"])*"|'(?:\\\\'|[^'])*'`,number:kt,meta:"degree|indegree|outdegree",separator:"\\s*,\\s*",descendant:"\\s+",child:"\\s+>\\s+",subject:"\\$",group:"node|edge|\\*",directedEdge:"\\s+->\\s+",undirectedEdge:"\\s+<->\\s+"};lc.variable="(?:[\\w-.]|(?:\\\\"+lc.metaChar+"))+",lc.className="(?:[\\w-]|(?:\\\\"+lc.metaChar+"))+",lc.value=lc.string+"|"+lc.number,lc.id=lc.variable,function(){var m,g,k;for(m=lc.comparatorOp.split("|"),k=0;k=0)&&g!=="="&&(lc.comparatorOp+="|\\!"+g)}();var iu=function(){return{checks:[]}},Ki={GROUP:0,COLLECTION:1,FILTER:2,DATA_COMPARE:3,DATA_EXIST:4,DATA_BOOL:5,META_COMPARE:6,STATE:7,ID:8,CLASS:9,UNDIRECTED_EDGE:10,DIRECTED_EDGE:11,NODE_SOURCE:12,NODE_TARGET:13,NODE_NEIGHBOR:14,CHILD:15,DESCENDANT:16,PARENT:17,ANCESTOR:18,COMPOUND_SPLIT:19,TRUE:20},PL=[{selector:":selected",matches:function(g){return g.selected()}},{selector:":unselected",matches:function(g){return!g.selected()}},{selector:":selectable",matches:function(g){return g.selectable()}},{selector:":unselectable",matches:function(g){return!g.selectable()}},{selector:":locked",matches:function(g){return g.locked()}},{selector:":unlocked",matches:function(g){return!g.locked()}},{selector:":visible",matches:function(g){return g.visible()}},{selector:":hidden",matches:function(g){return!g.visible()}},{selector:":transparent",matches:function(g){return g.transparent()}},{selector:":grabbed",matches:function(g){return g.grabbed()}},{selector:":free",matches:function(g){return!g.grabbed()}},{selector:":removed",matches:function(g){return g.removed()}},{selector:":inside",matches:function(g){return!g.removed()}},{selector:":grabbable",matches:function(g){return g.grabbable()}},{selector:":ungrabbable",matches:function(g){return!g.grabbable()}},{selector:":animated",matches:function(g){return g.animated()}},{selector:":unanimated",matches:function(g){return!g.animated()}},{selector:":parent",matches:function(g){return g.isParent()}},{selector:":childless",matches:function(g){return g.isChildless()}},{selector:":child",matches:function(g){return g.isChild()}},{selector:":orphan",matches:function(g){return g.isOrphan()}},{selector:":nonorphan",matches:function(g){return g.isChild()}},{selector:":compound",matches:function(g){return g.isNode()?g.isParent():g.source().isParent()||g.target().isParent()}},{selector:":loop",matches:function(g){return g.isLoop()}},{selector:":simple",matches:function(g){return g.isSimple()}},{selector:":active",matches:function(g){return g.active()}},{selector:":inactive",matches:function(g){return!g.active()}},{selector:":backgrounding",matches:function(g){return g.backgrounding()}},{selector:":nonbackgrounding",matches:function(g){return!g.backgrounding()}}].sort(function(m,g){return Bn(m.selector,g.selector)}),MZ=function(){for(var m={},g,k=0;k0&&G.edgeCount>0)return Vo("The selector `"+g+"` is invalid because it uses both a compound selector and an edge selector"),!1;if(G.edgeCount>1)return Vo("The selector `"+g+"` is invalid because it uses multiple edge selectors"),!1;G.edgeCount===1&&Vo("The selector `"+g+"` is deprecated. Edge selectors do not take effect on changes to source and target nodes after an edge is added, for performance reasons. Use a class or data selector on edges instead, updating the class or data of an edge when your app detects a change in source or target nodes.")}return!0},BZ=function(){if(this.toStringCache!=null)return this.toStringCache;for(var g=function(G){return G??""},k=function(G){return ye(G)?'"'+G+'"':g(G)},T=function(G){return" "+G+" "},A=function(G,U){var Z=G.type,ne=G.value;switch(Z){case Ki.GROUP:{var ae=g(ne);return ae.substring(0,ae.length-1)}case Ki.DATA_COMPARE:{var ue=G.field,_e=G.operator;return"["+ue+T(g(_e))+k(ne)+"]"}case Ki.DATA_BOOL:{var be=G.operator,Se=G.field;return"["+g(be)+Se+"]"}case Ki.DATA_EXIST:{var Le=G.field;return"["+Le+"]"}case Ki.META_COMPARE:{var Be=G.operator,Ke=G.field;return"[["+Ke+T(g(Be))+k(ne)+"]]"}case Ki.STATE:return ne;case Ki.ID:return"#"+ne;case Ki.CLASS:return"."+ne;case Ki.PARENT:case Ki.CHILD:return D(G.parent,U)+T(">")+D(G.child,U);case Ki.ANCESTOR:case Ki.DESCENDANT:return D(G.ancestor,U)+" "+D(G.descendant,U);case Ki.COMPOUND_SPLIT:{var qe=D(G.left,U),Re=D(G.subject,U),Ze=D(G.right,U);return qe+(qe.length>0?" ":"")+Re+Ze}case Ki.TRUE:return""}},D=function(G,U){return G.checks.reduce(function(Z,ne,ae){return Z+(U===G&&ae===0?"$":"")+A(ne,U)},"")},I="",F=0;F1&&F=0&&(k=k.replace("!",""),U=!0),k.indexOf("@")>=0&&(k=k.replace("@",""),G=!0),(D||F||G)&&(H=!D&&!I?"":""+g,C=""+T),G&&(g=H=H.toLowerCase(),T=C=C.toLowerCase()),k){case"*=":A=H.indexOf(C)>=0;break;case"$=":A=H.indexOf(C,H.length-C.length)>=0;break;case"^=":A=H.indexOf(C)===0;break;case"=":A=g===T;break;case">":Z=!0,A=g>T;break;case">=":Z=!0,A=g>=T;break;case"<":Z=!0,A=g0;){var G=A.shift();g(G),D.add(G.id()),F&&T(A,D,G)}return m}function kx(m,g,k){if(k.isParent())for(var T=k._private.children,A=0;A1&&arguments[1]!==void 0?arguments[1]:!0;return j9(this,m,g,kx)};function qB(m,g,k){if(k.isChild()){var T=k._private.parent;g.has(T.id())||m.push(T)}}Y5.forEachUp=function(m){var g=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0;return j9(this,m,g,qB)};function qZ(m,g,k){qB(m,g,k),kx(m,g,k)}Y5.forEachUpAndDown=function(m){var g=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0;return j9(this,m,g,qZ)},Y5.ancestors=Y5.parents;var xx,VB;xx=VB={data:Fc.data({field:"data",bindingEvent:"data",allowBinding:!0,allowSetting:!0,settingEvent:"data",settingTriggersEvent:!0,triggerFnName:"trigger",allowGetting:!0,immutableKeys:{id:!0,source:!0,target:!0,parent:!0},updateStyle:!0}),removeData:Fc.removeData({field:"data",event:"data",triggerFnName:"trigger",triggerEvent:!0,immutableKeys:{id:!0,source:!0,target:!0,parent:!0},updateStyle:!0}),scratch:Fc.data({field:"scratch",bindingEvent:"scratch",allowBinding:!0,allowSetting:!0,settingEvent:"scratch",settingTriggersEvent:!0,triggerFnName:"trigger",allowGetting:!0,updateStyle:!0}),removeScratch:Fc.removeData({field:"scratch",event:"scratch",triggerFnName:"trigger",triggerEvent:!0,updateStyle:!0}),rscratch:Fc.data({field:"rscratch",allowBinding:!1,allowSetting:!0,settingTriggersEvent:!1,allowGetting:!0}),removeRscratch:Fc.removeData({field:"rscratch",triggerEvent:!1}),id:function(){var g=this[0];if(g)return g._private.data.id}},xx.attr=xx.data,xx.removeAttr=xx.removeData;var VZ=VB,$9={};function X5(m){return function(g){var k=this;if(g===void 0&&(g=!0),k.length!==0)if(k.isNode()&&!k.removed()){for(var T=0,A=k[0],D=A._private.edges,I=0;Ig}),minIndegree:Q5("indegree",function(m,g){return mg}),minOutdegree:Q5("outdegree",function(m,g){return mg})}),Oe($9,{totalDegree:function(g){for(var k=0,T=this.nodes(),A=0;A0,Z=U;U&&(G=G[0]);var ne=Z?G.position():{x:0,y:0};k!==void 0?C.position(g,k+ne[g]):D!==void 0&&C.position({x:D.x+ne.x,y:D.y+ne.y})}else{var ae=T.position(),ue=F?T.parent():null,_e=ue&&ue.length>0,be=_e;_e&&(ue=ue[0]);var Se=be?ue.position():{x:0,y:0};return D={x:ae.x-Se.x,y:ae.y-Se.y},g===void 0?D:D[g]}else if(!I)return;return this}},bp.modelPosition=bp.point=bp.position,bp.modelPositions=bp.points=bp.positions,bp.renderedPoint=bp.renderedPosition,bp.relativePoint=bp.relativePosition;var KB=UB,Z5,F2;Z5=F2={},F2.renderedBoundingBox=function(m){var g=this.boundingBox(m),k=this.cy(),T=k.zoom(),A=k.pan(),D=g.x1*T+A.x,I=g.x2*T+A.x,F=g.y1*T+A.y,H=g.y2*T+A.y;return{x1:D,x2:I,y1:F,y2:H,w:I-D,h:H-F}},F2.dirtyCompoundBoundsCache=function(){var m=arguments.length>0&&arguments[0]!==void 0?arguments[0]:!1,g=this.cy();return!g.styleEnabled()||!g.hasCompoundNodes()?this:(this.forEachUp(function(k){if(k.isParent()){var T=k._private;T.compoundBoundsClean=!1,T.bbCache=null,m||k.emitAndNotify("bounds")}}),this)},F2.updateCompoundBounds=function(){var m=arguments.length>0&&arguments[0]!==void 0?arguments[0]:!1,g=this.cy();if(!g.styleEnabled()||!g.hasCompoundNodes())return this;if(!m&&g.batching())return this;function k(I){if(!I.isParent())return;var F=I._private,H=I.children(),C=I.pstyle("compound-sizing-wrt-labels").value==="include",G={width:{val:I.pstyle("min-width").pfValue,left:I.pstyle("min-width-bias-left"),right:I.pstyle("min-width-bias-right")},height:{val:I.pstyle("min-height").pfValue,top:I.pstyle("min-height-bias-top"),bottom:I.pstyle("min-height-bias-bottom")}},U=H.boundingBox({includeLabels:C,includeOverlays:!1,useCache:!1}),Z=F.position;(U.w===0||U.h===0)&&(U={w:I.pstyle("width").pfValue,h:I.pstyle("height").pfValue},U.x1=Z.x-U.w/2,U.x2=Z.x+U.w/2,U.y1=Z.y-U.h/2,U.y2=Z.y+U.h/2);function ne($e,ot,ut){var Je=0,Ct=0,lt=ot+ut;return $e>0&<>0&&(Je=ot/lt*$e,Ct=ut/lt*$e),{biasDiff:Je,biasComplementDiff:Ct}}function ae($e,ot,ut,Je){if(ut.units==="%")switch(Je){case"width":return $e>0?ut.pfValue*$e:0;case"height":return ot>0?ut.pfValue*ot:0;case"average":return $e>0&&ot>0?ut.pfValue*($e+ot)/2:0;case"min":return $e>0&&ot>0?$e>ot?ut.pfValue*ot:ut.pfValue*$e:0;case"max":return $e>0&&ot>0?$e>ot?ut.pfValue*$e:ut.pfValue*ot:0;default:return 0}else return ut.units==="px"?ut.pfValue:0}var ue=G.width.left.value;G.width.left.units==="px"&&G.width.val>0&&(ue=ue*100/G.width.val);var _e=G.width.right.value;G.width.right.units==="px"&&G.width.val>0&&(_e=_e*100/G.width.val);var be=G.height.top.value;G.height.top.units==="px"&&G.height.val>0&&(be=be*100/G.height.val);var Se=G.height.bottom.value;G.height.bottom.units==="px"&&G.height.val>0&&(Se=Se*100/G.height.val);var Le=ne(G.width.val-U.w,ue,_e),Be=Le.biasDiff,Ke=Le.biasComplementDiff,qe=ne(G.height.val-U.h,be,Se),Re=qe.biasDiff,Ze=qe.biasComplementDiff;F.autoPadding=ae(U.w,U.h,I.pstyle("padding"),I.pstyle("padding-relative-to").value),F.autoWidth=Math.max(U.w,G.width.val),Z.x=(-Be+U.x1+U.x2+Ke)/2,F.autoHeight=Math.max(U.h,G.height.val),Z.y=(-Re+U.y1+U.y2+Ze)/2}for(var T=0;Tg.x2?A:g.x2,g.y1=Tg.y2?D:g.y2,g.w=g.x2-g.x1,g.h=g.y2-g.y1)},k3=function(g,k){return k==null?g:vp(g,k.x1,k.y1,k.x2,k.y2)},Tx=function(g,k,T){return gp(g,k,T)},H9=function(g,k,T){if(!k.cy().headless()){var A=k._private,D=A.rstyle,I=D.arrowWidth/2,F=k.pstyle(T+"-arrow-shape").value,H,C;if(F!=="none"){T==="source"?(H=D.srcX,C=D.srcY):T==="target"?(H=D.tgtX,C=D.tgtY):(H=D.midX,C=D.midY);var G=A.arrowBounds=A.arrowBounds||{},U=G[T]=G[T]||{};U.x1=H-I,U.y1=C-I,U.x2=H+I,U.y2=C+I,U.w=U.x2-U.x1,U.h=U.y2-U.y1,_9(U,1),vp(g,U.x1,U.y1,U.x2,U.y2)}}},YB=function(g,k,T){if(!k.cy().headless()){var A;T?A=T+"-":A="";var D=k._private,I=D.rstyle,F=k.pstyle(A+"label").strValue;if(F){var H=k.pstyle("text-halign"),C=k.pstyle("text-valign"),G=Tx(I,"labelWidth",T),U=Tx(I,"labelHeight",T),Z=Tx(I,"labelX",T),ne=Tx(I,"labelY",T),ae=k.pstyle(A+"text-margin-x").pfValue,ue=k.pstyle(A+"text-margin-y").pfValue,_e=k.isEdge(),be=k.pstyle(A+"text-rotation"),Se=k.pstyle("text-outline-width").pfValue,Le=k.pstyle("text-border-width").pfValue,Be=Le/2,Ke=k.pstyle("text-background-padding").pfValue,qe=2,Re=U,Ze=G,$e=Ze/2,ot=Re/2,ut,Je,Ct,lt;if(_e)ut=Z-$e,Je=Z+$e,Ct=ne-ot,lt=ne+ot;else{switch(H.value){case"left":ut=Z-Ze,Je=Z;break;case"center":ut=Z-$e,Je=Z+$e;break;case"right":ut=Z,Je=Z+Ze;break}switch(C.value){case"top":Ct=ne-Re,lt=ne;break;case"center":Ct=ne-ot,lt=ne+ot;break;case"bottom":Ct=ne,lt=ne+Re;break}}ut+=ae-Math.max(Se,Be)-Ke-qe,Je+=ae+Math.max(Se,Be)+Ke+qe,Ct+=ue-Math.max(Se,Be)-Ke-qe,lt+=ue+Math.max(Se,Be)+Ke+qe;var un=T||"main",Rt=D.labelBounds,$t=Rt[un]=Rt[un]||{};$t.x1=ut,$t.y1=Ct,$t.x2=Je,$t.y2=lt,$t.w=Je-ut,$t.h=lt-Ct;var bn=_e&&be.strValue==="autorotate",Cn=be.pfValue!=null&&be.pfValue!==0;if(bn||Cn){var Kn=bn?Tx(D.rstyle,"labelAngle",T):be.pfValue,kn=Math.cos(Kn),Wn=Math.sin(Kn),sr=(ut+Je)/2,yr=(Ct+lt)/2;if(!_e){switch(H.value){case"left":sr=Je;break;case"right":sr=ut;break}switch(C.value){case"top":yr=lt;break;case"bottom":yr=Ct;break}}var hr=function(Ba,Li){return Ba=Ba-sr,Li=Li-yr,{x:Ba*kn-Li*Wn+sr,y:Ba*Wn+Li*kn+yr}},nr=hr(ut,Ct),fn=hr(ut,lt),vr=hr(Je,Ct),gr=hr(Je,lt);ut=Math.min(nr.x,fn.x,vr.x,gr.x),Je=Math.max(nr.x,fn.x,vr.x,gr.x),Ct=Math.min(nr.y,fn.y,vr.y,gr.y),lt=Math.max(nr.y,fn.y,vr.y,gr.y)}var ni=un+"Rot",Ti=Rt[ni]=Rt[ni]||{};Ti.x1=ut,Ti.y1=Ct,Ti.x2=Je,Ti.y2=lt,Ti.w=Je-ut,Ti.h=lt-Ct,vp(g,ut,Ct,Je,lt),vp(D.labelBounds.all,ut,Ct,Je,lt)}return g}},UZ=function(g,k){var T=g._private.cy,A=T.styleEnabled(),D=T.headless(),I=zd(),F=g._private,H=g.isNode(),C=g.isEdge(),G,U,Z,ne,ae,ue,_e=F.rstyle,be=H&&A?g.pstyle("bounds-expansion").pfValue:[0],Se=function(Ts){return Ts.pstyle("display").value!=="none"},Le=!A||Se(g)&&(!C||Se(g.source())&&Se(g.target()));if(Le){var Be=0,Ke=0;A&&k.includeOverlays&&(Be=g.pstyle("overlay-opacity").value,Be!==0&&(Ke=g.pstyle("overlay-padding").value));var qe=0,Re=0;A&&k.includeUnderlays&&(qe=g.pstyle("underlay-opacity").value,qe!==0&&(Re=g.pstyle("underlay-padding").value));var Ze=Math.max(Ke,Re),$e=0,ot=0;if(A&&($e=g.pstyle("width").pfValue,ot=$e/2),H&&k.includeNodes){var ut=g.position();ae=ut.x,ue=ut.y;var Je=g.outerWidth(),Ct=Je/2,lt=g.outerHeight(),un=lt/2;G=ae-Ct,U=ae+Ct,Z=ue-un,ne=ue+un,vp(I,G,Z,U,ne)}else if(C&&k.includeEdges)if(A&&!D){var Rt=g.pstyle("curve-style").strValue;if(G=Math.min(_e.srcX,_e.midX,_e.tgtX),U=Math.max(_e.srcX,_e.midX,_e.tgtX),Z=Math.min(_e.srcY,_e.midY,_e.tgtY),ne=Math.max(_e.srcY,_e.midY,_e.tgtY),G-=ot,U+=ot,Z-=ot,ne+=ot,vp(I,G,Z,U,ne),Rt==="haystack"){var $t=_e.haystackPts;if($t&&$t.length===2){if(G=$t[0].x,Z=$t[0].y,U=$t[1].x,ne=$t[1].y,G>U){var bn=G;G=U,U=bn}if(Z>ne){var Cn=Z;Z=ne,ne=Cn}vp(I,G-ot,Z-ot,U+ot,ne+ot)}}else if(Rt==="bezier"||Rt==="unbundled-bezier"||Rt==="segments"||Rt==="taxi"){var Kn;switch(Rt){case"bezier":case"unbundled-bezier":Kn=_e.bezierPts;break;case"segments":case"taxi":Kn=_e.linePts;break}if(Kn!=null)for(var kn=0;knU){var fn=G;G=U,U=fn}if(Z>ne){var vr=Z;Z=ne,ne=vr}G-=ot,U+=ot,Z-=ot,ne+=ot,vp(I,G,Z,U,ne)}if(A&&k.includeEdges&&C&&(H9(I,g,"mid-source"),H9(I,g,"mid-target"),H9(I,g,"source"),H9(I,g,"target")),A){var gr=g.pstyle("ghost").value==="yes";if(gr){var ni=g.pstyle("ghost-offset-x").pfValue,Ti=g.pstyle("ghost-offset-y").pfValue;vp(I,I.x1+ni,I.y1+Ti,I.x2+ni,I.y2+Ti)}}var ia=F.bodyBounds=F.bodyBounds||{};KP(ia,I),kL(ia,be),_9(ia,1),A&&(G=I.x1,U=I.x2,Z=I.y1,ne=I.y2,vp(I,G-Ze,Z-Ze,U+Ze,ne+Ze));var Ba=F.overlayBounds=F.overlayBounds||{};KP(Ba,I),kL(Ba,be),_9(Ba,1);var Li=F.labelBounds=F.labelBounds||{};Li.all!=null?TY(Li.all):Li.all=zd(),A&&k.includeLabels&&(k.includeMainLabels&&YB(I,g,null),C&&(k.includeSourceLabels&&YB(I,g,"source"),k.includeTargetLabels&&YB(I,g,"target")))}return I.x1=E0(I.x1),I.y1=E0(I.y1),I.x2=E0(I.x2),I.y2=E0(I.y2),I.w=E0(I.x2-I.x1),I.h=E0(I.y2-I.y1),I.w>0&&I.h>0&&Le&&(kL(I,be),_9(I,1)),I},XB=function(g){var k=0,T=function(I){return(I?1:0)<0&&arguments[0]!==void 0?arguments[0]:aJ,g=arguments.length>1?arguments[1]:void 0,k=0;k=0;F--)I(F);return this},pm.removeAllListeners=function(){return this.removeListener("*")},pm.emit=pm.trigger=function(m,g,k){var T=this.listeners,A=T.length;return this.emitting++,Ae(g)||(g=[g]),oJ(this,function(D,I){k!=null&&(T=[{event:I.event,type:I.type,namespace:I.namespace,callback:k}],A=T.length);for(var F=function(G){var U=T[G];if(U.type===I.type&&(!U.namespace||U.namespace===I.namespace||U.namespace===sJ)&&D.eventMatches(D.context,U,I)){var Z=[I];g!=null&&qP(Z,g),D.beforeEmit(D.context,U,I),U.conf&&U.conf.one&&(D.listeners=D.listeners.filter(function(ue){return ue!==U}));var ne=D.callbackContext(D.context,U,I),ae=U.callback.apply(ne,Z);D.afterEmit(D.context,U,I),ae===!1&&(I.stopPropagation(),I.preventDefault())}},H=0;H1&&!I){var F=this.length-1,H=this[F],C=H._private.data.id;this[F]=void 0,this[g]=H,D.set(C,{ele:H,index:g})}return this.length--,this},unmergeOne:function(g){g=g[0];var k=this._private,T=g._private.data.id,A=k.map,D=A.get(T);if(!D)return this;var I=D.index;return this.unmergeAt(I),this},unmerge:function(g){var k=this._private.cy;if(!g)return this;if(g&&ye(g)){var T=g;g=k.mutableElements().filter(T)}for(var A=0;A=0;k--){var T=this[k];g(T)&&this.unmergeAt(k)}return this},map:function(g,k){for(var T=[],A=this,D=0;DT&&(T=H,A=F)}return{value:T,ele:A}},min:function(g,k){for(var T=1/0,A,D=this,I=0;I=0&&D"u"?"undefined":f(Symbol))!=g&&f(Symbol.iterator)!=g;k&&(V9[Symbol.iterator]=function(){var T=this,A={value:void 0,done:!1},D=0,I=this.length;return b({next:function(){return D1&&arguments[1]!==void 0?arguments[1]:!0,T=this[0],A=T.cy();if(A.styleEnabled()&&T){this.cleanStyle();var D=T._private.style[g];return D??(k?A.style().getDefaultProperty(g):null)}},numericStyle:function(g){var k=this[0];if(k.cy().styleEnabled()&&k){var T=k.pstyle(g);return T.pfValue!==void 0?T.pfValue:T.value}},numericStyleUnits:function(g){var k=this[0];if(k.cy().styleEnabled()&&k)return k.pstyle(g).units},renderedStyle:function(g){var k=this.cy();if(!k.styleEnabled())return this;var T=this[0];if(T)return k.style().getRenderedStyle(T,g)},style:function(g,k){var T=this.cy();if(!T.styleEnabled())return this;var A=!1,D=T.style();if(de(g)){var I=g;D.applyBypass(this,I,A),this.emitAndNotify("style")}else if(ye(g))if(k===void 0){var F=this[0];return F?D.getStylePropertyValue(F,g):void 0}else D.applyBypass(this,g,k,A),this.emitAndNotify("style");else if(g===void 0){var H=this[0];return H?D.getRawStyle(H):void 0}return this},removeStyle:function(g){var k=this.cy();if(!k.styleEnabled())return this;var T=!1,A=k.style(),D=this;if(g===void 0)for(var I=0;I0&&g.push(G[0]),g.push(F[0])}return this.spawn(g,!0).filter(m)},"neighborhood"),closedNeighborhood:function(g){return this.neighborhood().add(this).filter(g)},openNeighborhood:function(g){return this.neighborhood(g)}}),w1.neighbourhood=w1.neighborhood,w1.closedNeighbourhood=w1.closedNeighborhood,w1.openNeighbourhood=w1.openNeighborhood,Oe(w1,{source:ld(function(g){var k=this[0],T;return k&&(T=k._private.source||k.cy().collection()),T&&g?T.filter(g):T},"source"),target:ld(function(g){var k=this[0],T;return k&&(T=k._private.target||k.cy().collection()),T&&g?T.filter(g):T},"target"),sources:bR({attr:"source"}),targets:bR({attr:"target"})});function bR(m){return function(k){for(var T=[],A=0;A0);return I},component:function(){var g=this[0];return g.cy().mutableElements().components(g)[0]}}),w1.componentsOf=w1.components;var Wf=function(g,k){var T=arguments.length>2&&arguments[2]!==void 0?arguments[2]:!1,A=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!1;if(g===void 0){yc("A collection must have a reference to the core");return}var D=new R2,I=!1;if(!k)k=[];else if(k.length>0&&de(k[0])&&!Ie(k[0])){I=!0;for(var F=[],H=new R5,C=0,G=k.length;C0&&arguments[0]!==void 0?arguments[0]:!0,g=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,k=this,T=k.cy(),A=T._private,D=[],I=[],F,H=0,C=k.length;H0){for(var Cn=F.length===k.length?k:new Wf(T,F),Kn=0;Kn0&&arguments[0]!==void 0?arguments[0]:!0,g=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,k=this,T=[],A={},D=k._private.cy;function I(lt){for(var un=lt._private.edges,Rt=0;Rt0&&(m?ut.emitAndNotify("remove"):g&&ut.emit("remove"));for(var Je=0;Je0?Je=lt:ut=lt;while(Math.abs(Ct)>I&&++un=D?Se(ot,un):Rt===0?un:Be(ot,ut,ut+C)}var qe=!1;function Re(){qe=!0,(m!==g||k!==T)&&Le()}var Ze=function(ut){return qe||Re(),m===g&&k===T?ut:ut===0?0:ut===1?1:_e(Ke(ut),g,T)};Ze.getControlPoints=function(){return[{x:m,y:g},{x:k,y:T}]};var $e="generateBezier("+[m,g,k,T]+")";return Ze.toString=function(){return $e},Ze}/*! Runge-Kutta spring physics function generator. Adapted from Framer.js, copyright Koen Bok. MIT License: http://en.wikipedia.org/wiki/MIT_License */var wJ=function(){function m(T){return-T.tension*T.x-T.friction*T.v}function g(T,A,D){var I={x:T.x+D.dx*A,v:T.v+D.dv*A,tension:T.tension,friction:T.friction};return{dx:I.v,dv:m(I)}}function k(T,A){var D={dx:T.v,dv:m(T)},I=g(T,A*.5,D),F=g(T,A*.5,I),H=g(T,A,F),C=1/6*(D.dx+2*(I.dx+F.dx)+H.dx),G=1/6*(D.dv+2*(I.dv+F.dv)+H.dv);return T.x=T.x+C*A,T.v=T.v+G*A,T}return function T(A,D,I){var F={x:-1,v:0,tension:null,friction:null},H=[0],C=0,G=1/1e4,U=16/1e3,Z,ne,ae;for(A=parseFloat(A)||500,D=parseFloat(D)||20,I=I||null,F.tension=A,F.friction=D,Z=I!==null,Z?(C=T(A,D),ne=C/I*U):ne=U;ae=k(ae||F,ne),H.push(1+ae.x),C+=16,Math.abs(ae.x)>G&&Math.abs(ae.v)>G;);return Z?function(ue){return H[ue*(H.length-1)|0]}:C}}(),Eu=function(g,k,T,A){var D=vJ(g,k,T,A);return function(I,F,H){return I+(F-I)*D(H)}},Y9={linear:function(g,k,T){return g+(k-g)*T},ease:Eu(.25,.1,.25,1),"ease-in":Eu(.42,0,1,1),"ease-out":Eu(0,0,.58,1),"ease-in-out":Eu(.42,0,.58,1),"ease-in-sine":Eu(.47,0,.745,.715),"ease-out-sine":Eu(.39,.575,.565,1),"ease-in-out-sine":Eu(.445,.05,.55,.95),"ease-in-quad":Eu(.55,.085,.68,.53),"ease-out-quad":Eu(.25,.46,.45,.94),"ease-in-out-quad":Eu(.455,.03,.515,.955),"ease-in-cubic":Eu(.55,.055,.675,.19),"ease-out-cubic":Eu(.215,.61,.355,1),"ease-in-out-cubic":Eu(.645,.045,.355,1),"ease-in-quart":Eu(.895,.03,.685,.22),"ease-out-quart":Eu(.165,.84,.44,1),"ease-in-out-quart":Eu(.77,0,.175,1),"ease-in-quint":Eu(.755,.05,.855,.06),"ease-out-quint":Eu(.23,1,.32,1),"ease-in-out-quint":Eu(.86,0,.07,1),"ease-in-expo":Eu(.95,.05,.795,.035),"ease-out-expo":Eu(.19,1,.22,1),"ease-in-out-expo":Eu(1,0,0,1),"ease-in-circ":Eu(.6,.04,.98,.335),"ease-out-circ":Eu(.075,.82,.165,1),"ease-in-out-circ":Eu(.785,.135,.15,.86),spring:function(g,k,T){if(T===0)return Y9.linear;var A=wJ(g,k,T);return function(D,I,F){return D+(I-D)*A(F)}},"cubic-bezier":Eu};function mR(m,g,k,T,A){if(T===1||g===k)return k;var D=A(g,k,T);return m==null||((m.roundValue||m.color)&&(D=Math.round(D)),m.min!==void 0&&(D=Math.max(D,m.min)),m.max!==void 0&&(D=Math.min(D,m.max))),D}function yR(m,g){return m.pfValue!=null||m.value!=null?m.pfValue!=null&&(g==null||g.type.units!=="%")?m.pfValue:m.value:m}function t6(m,g,k,T,A){var D=A!=null?A.type:null;k<0?k=0:k>1&&(k=1);var I=yR(m,A),F=yR(g,A);if(te(I)&&te(F))return mR(D,I,F,k,T);if(Ae(I)&&Ae(F)){for(var H=[],C=0;C0?(ne==="spring"&&ae.push(I.duration),I.easingImpl=Y9[ne].apply(null,ae)):I.easingImpl=Y9[ne]}var ue=I.easingImpl,_e;if(I.duration===0?_e=1:_e=(k-H)/I.duration,I.applying&&(_e=I.progress),_e<0?_e=0:_e>1&&(_e=1),I.delay==null){var be=I.startPosition,Se=I.position;if(Se&&A&&!m.locked()){var Le={};Lx(be.x,Se.x)&&(Le.x=t6(be.x,Se.x,_e,ue)),Lx(be.y,Se.y)&&(Le.y=t6(be.y,Se.y,_e,ue)),m.position(Le)}var Be=I.startPan,Ke=I.pan,qe=D.pan,Re=Ke!=null&&T;Re&&(Lx(Be.x,Ke.x)&&(qe.x=t6(Be.x,Ke.x,_e,ue)),Lx(Be.y,Ke.y)&&(qe.y=t6(Be.y,Ke.y,_e,ue)),m.emit("pan"));var Ze=I.startZoom,$e=I.zoom,ot=$e!=null&&T;ot&&(Lx(Ze,$e)&&(D.zoom=px(D.minZoom,t6(Ze,$e,_e,ue),D.maxZoom)),m.emit("zoom")),(Re||ot)&&m.emit("viewport");var ut=I.style;if(ut&&ut.length>0&&A){for(var Je=0;Je=0;Re--){var Ze=qe[Re];Ze()}qe.splice(0,qe.length)},Se=ne.length-1;Se>=0;Se--){var Le=ne[Se],Be=Le._private;if(Be.stopped){ne.splice(Se,1),Be.hooked=!1,Be.playing=!1,Be.started=!1,be(Be.frames);continue}!Be.playing&&!Be.applying||(Be.playing&&Be.applying&&(Be.applying=!1),Be.started||yJ(G,Le,m),mJ(G,Le,m,U),Be.applying&&(Be.applying=!1),be(Be.frames),Be.step!=null&&Be.step(m),Le.completed()&&(ne.splice(Se,1),Be.hooked=!1,Be.playing=!1,Be.started=!1,be(Be.completes)),ue=!0)}return!U&&ne.length===0&&ae.length===0&&T.push(G),ue}for(var D=!1,I=0;I0?g.notify("draw",k):g.notify("draw")),k.unmerge(T),g.emit("step")}var kJ={animate:Fc.animate(),animation:Fc.animation(),animated:Fc.animated(),clearQueue:Fc.clearQueue(),delay:Fc.delay(),delayAnimation:Fc.delayAnimation(),stop:Fc.stop(),addToAnimationPool:function(g){var k=this;k.styleEnabled()&&k._private.aniEles.merge(g)},stopAnimationLoop:function(){this._private.animationsRunning=!1},startAnimationLoop:function(){var g=this;if(g._private.animationsRunning=!0,!g.styleEnabled())return;function k(){g._private.animationsRunning&&Aa(function(D){kR(D,g),k()})}var T=g.renderer();T&&T.beforeRender?T.beforeRender(function(D,I){kR(I,g)},T.beforeRenderPriorities.animations):k()}},xJ={qualifierCompare:function(g,k){return g==null||k==null?g==null&&k==null:g.sameText(k)},eventMatches:function(g,k,T){var A=k.qualifier;return A!=null?g!==T.target&&Ie(T.target)&&A.matches(T.target):!0},addEventFields:function(g,k){k.cy=g,k.target=g},callbackContext:function(g,k,T){return k.qualifier!=null?T.target:g}},X9=function(g){return ye(g)?new dm(g):g},xR={createEmitter:function(){var g=this._private;return g.emitter||(g.emitter=new G9(xJ,this)),this},emitter:function(){return this._private.emitter},on:function(g,k,T){return this.emitter().on(g,X9(k),T),this},removeListener:function(g,k,T){return this.emitter().removeListener(g,X9(k),T),this},removeAllListeners:function(){return this.emitter().removeAllListeners(),this},one:function(g,k,T){return this.emitter().one(g,X9(k),T),this},once:function(g,k,T){return this.emitter().one(g,X9(k),T),this},emit:function(g,k){return this.emitter().emit(g,k),this},emitAndNotify:function(g,k){return this.emit(g),this.notify(g,k),this}};Fc.eventAliasesOn(xR);var $L={png:function(g){var k=this._private.renderer;return g=g||{},k.png(g)},jpg:function(g){var k=this._private.renderer;return g=g||{},g.bg=g.bg||"#fff",k.jpg(g)}};$L.jpeg=$L.jpg;var Q9={layout:function(g){var k=this;if(g==null){yc("Layout options must be specified to make a layout");return}if(g.name==null){yc("A `name` must be specified to make a layout");return}var T=g.name,A=k.extension("layout",T);if(A==null){yc("No such layout `"+T+"` found. Did you forget to import it and `cytoscape.use()` it?");return}var D;ye(g.eles)?D=k.$(g.eles):D=g.eles!=null?g.eles:k.$();var I=new A(Oe({},g,{cy:k,eles:D}));return I}};Q9.createLayout=Q9.makeLayout=Q9.layout;var EJ={notify:function(g,k){var T=this._private;if(this.batching()){T.batchNotifications=T.batchNotifications||{};var A=T.batchNotifications[g]=T.batchNotifications[g]||this.collection();k!=null&&A.merge(k);return}if(T.notificationsEnabled){var D=this.renderer();this.destroyed()||!D||D.notify(g,k)}},notifications:function(g){var k=this._private;return g===void 0?k.notificationsEnabled:(k.notificationsEnabled=!!g,this)},noNotifications:function(g){this.notifications(!1),g(),this.notifications(!0)},batching:function(){return this._private.batchCount>0},startBatch:function(){var g=this._private;return g.batchCount==null&&(g.batchCount=0),g.batchCount===0&&(g.batchStyleEles=this.collection(),g.batchNotifications={}),g.batchCount++,this},endBatch:function(){var g=this._private;if(g.batchCount===0)return this;if(g.batchCount--,g.batchCount===0){g.batchStyleEles.updateStyle();var k=this.renderer();Object.keys(g.batchNotifications).forEach(function(T){var A=g.batchNotifications[T];A.empty()?k.notify(T):k.notify(T,A)})}return this},batch:function(g){return this.startBatch(),g(),this.endBatch(),this},batchData:function(g){var k=this;return this.batch(function(){for(var T=Object.keys(g),A=0;A0;)k.removeChild(k.childNodes[0]);g._private.renderer=null,g.mutableElements().forEach(function(T){var A=T._private;A.rscratch={},A.rstyle={},A.animation.current=[],A.animation.queue=[]})},onRender:function(g){return this.on("render",g)},offRender:function(g){return this.off("render",g)}};HL.invalidateDimensions=HL.resize;var Z9={collection:function(g,k){return ye(g)?this.$(g):he(g)?g.collection():Ae(g)?(k||(k={}),new Wf(this,g,k.unique,k.removed)):new Wf(this)},nodes:function(g){var k=this.$(function(T){return T.isNode()});return g?k.filter(g):k},edges:function(g){var k=this.$(function(T){return T.isEdge()});return g?k.filter(g):k},$:function(g){var k=this._private.elements;return g?k.filter(g):k.spawnSelf()},mutableElements:function(){return this._private.elements}};Z9.elements=Z9.filter=Z9.$;var m1={},Mx="t",_J="f";m1.apply=function(m){for(var g=this,k=g._private,T=k.cy,A=T.collection(),D=0;D0;if(Z||U&&ne){var ae=void 0;Z&&ne||Z?ae=C.properties:ne&&(ae=C.mappedProperties);for(var ue=0;ue1&&(Be=1),F.color){var qe=T.valueMin[0],Re=T.valueMax[0],Ze=T.valueMin[1],$e=T.valueMax[1],ot=T.valueMin[2],ut=T.valueMax[2],Je=T.valueMin[3]==null?1:T.valueMin[3],Ct=T.valueMax[3]==null?1:T.valueMax[3],lt=[Math.round(qe+(Re-qe)*Be),Math.round(Ze+($e-Ze)*Be),Math.round(ot+(ut-ot)*Be),Math.round(Je+(Ct-Je)*Be)];D={bypass:T.bypass,name:T.name,value:lt,strValue:"rgb("+lt[0]+", "+lt[1]+", "+lt[2]+")"}}else if(F.number){var un=T.valueMin+(T.valueMax-T.valueMin)*Be;D=this.parse(T.name,un,T.bypass,Z)}else return!1;if(!D)return ue(),!1;D.mapping=T,T=D;break}case I.data:{for(var Rt=T.field.split("."),$t=U.data,bn=0;bn0&&D>0){for(var F={},H=!1,C=0;C0?m.delayAnimation(I).play().promise().then(Le):Le()}).then(function(){return m.animation({style:F,duration:D,easing:m.pstyle("transition-timing-function").value,queue:!1}).play().promise()}).then(function(){k.removeBypasses(m,A),m.emitAndNotify("style"),T.transitioning=!1})}else T.transitioning&&(this.removeBypasses(m,A),m.emitAndNotify("style"),T.transitioning=!1)},m1.checkTrigger=function(m,g,k,T,A,D){var I=this.properties[g],F=A(I);F!=null&&F(k,T)&&D(I)},m1.checkZOrderTrigger=function(m,g,k,T){var A=this;this.checkTrigger(m,g,k,T,function(D){return D.triggersZOrder},function(){A._private.cy.notify("zorder",m)})},m1.checkBoundsTrigger=function(m,g,k,T){this.checkTrigger(m,g,k,T,function(A){return A.triggersBounds},function(A){m.dirtyCompoundBoundsCache(),m.dirtyBoundingBoxCache(),A.triggersBoundsOfParallelBeziers&&(g==="curve-style"&&(k==="bezier"||T==="bezier")||g==="display"&&(k==="none"||T==="none"))&&m.parallelEdges().forEach(function(D){D.isBundledBezier()&&D.dirtyBoundingBoxCache()})})},m1.checkTriggers=function(m,g,k,T){m.dirtyStyleCache(),this.checkZOrderTrigger(m,g,k,T),this.checkBoundsTrigger(m,g,k,T)};var Dx={};Dx.applyBypass=function(m,g,k,T){var A=this,D=[],I=!0;if(g==="*"||g==="**"){if(k!==void 0)for(var F=0;FA.length?T=T.substr(A.length):T=""}function H(){D.length>I.length?D=D.substr(I.length):D=""}for(;;){var C=T.match(/^\s*$/);if(C)break;var G=T.match(/^\s*((?:.|\s)+?)\s*\{((?:.|\s)+?)\}/);if(!G){Vo("Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: "+T);break}A=G[0];var U=G[1];if(U!=="core"){var Z=new dm(U);if(Z.invalid){Vo("Skipping parsing of block: Invalid selector found in string stylesheet: "+U),F();continue}}var ne=G[2],ae=!1;D=ne;for(var ue=[];;){var _e=D.match(/^\s*$/);if(_e)break;var be=D.match(/^\s*(.+?)\s*:\s*(.+?)(?:\s*;|\s*$)/);if(!be){Vo("Skipping parsing of block: Invalid formatting of style property and value definitions found in:"+ne),ae=!0;break}I=be[0];var Se=be[1],Le=be[2],Be=g.properties[Se];if(!Be){Vo("Skipping property: Invalid property name in: "+I),H();continue}var Ke=k.parse(Se,Le);if(!Ke){Vo("Skipping property: Invalid property definition in: "+I),H();continue}ue.push({name:Se,val:Le}),H()}if(ae){F();break}k.selector(U);for(var qe=0;qe=7&&g[0]==="d"&&(G=new RegExp(F.data.regex).exec(g))){if(k)return!1;var Z=F.data;return{name:m,value:G,strValue:""+g,mapped:Z,field:G[1],bypass:k}}else if(g.length>=10&&g[0]==="m"&&(U=new RegExp(F.mapData.regex).exec(g))){if(k||C.multiple)return!1;var ne=F.mapData;if(!(C.color||C.number))return!1;var ae=this.parse(m,U[4]);if(!ae||ae.mapped)return!1;var ue=this.parse(m,U[5]);if(!ue||ue.mapped)return!1;if(ae.pfValue===ue.pfValue||ae.strValue===ue.strValue)return Vo("`"+m+": "+g+"` is not a valid mapper because the output range is zero; converting to `"+m+": "+ae.strValue+"`"),this.parse(m,ae.strValue);if(C.color){var _e=ae.value,be=ue.value,Se=_e[0]===be[0]&&_e[1]===be[1]&&_e[2]===be[2]&&(_e[3]===be[3]||(_e[3]==null||_e[3]===1)&&(be[3]==null||be[3]===1));if(Se)return!1}return{name:m,value:U,strValue:""+g,mapped:ne,field:U[1],fieldMin:parseFloat(U[2]),fieldMax:parseFloat(U[3]),valueMin:ae.value,valueMax:ue.value,bypass:k}}}if(C.multiple&&T!=="multiple"){var Le;if(H?Le=g.split(/\s+/):Ae(g)?Le=g:Le=[g],C.evenMultiple&&Le.length%2!==0)return null;for(var Be=[],Ke=[],qe=[],Re="",Ze=!1,$e=0;$e0?" ":"")+ot.strValue}return C.validate&&!C.validate(Be,Ke)?null:C.singleEnum&&Ze?Be.length===1&&ye(Be[0])?{name:m,value:Be[0],strValue:Be[0],bypass:k}:null:{name:m,value:Be,pfValue:qe,strValue:Re,bypass:k,units:Ke}}var ut=function(){for(var gr=0;grC.max||C.strictMax&&g===C.max))return null;var Rt={name:m,value:g,strValue:""+g+(Je||""),units:Je,bypass:k};return C.unitless||Je!=="px"&&Je!=="em"?Rt.pfValue=g:Rt.pfValue=Je==="px"||!Je?g:this.getEmSizeInPixels()*g,(Je==="ms"||Je==="s")&&(Rt.pfValue=Je==="ms"?g:1e3*g),(Je==="deg"||Je==="rad")&&(Rt.pfValue=Je==="rad"?g:yY(g)),Je==="%"&&(Rt.pfValue=g/100),Rt}else if(C.propList){var $t=[],bn=""+g;if(bn!=="none"){for(var Cn=bn.split(/\s*,\s*|\s+/),Kn=0;Kn0&&F>0&&!isNaN(T.w)&&!isNaN(T.h)&&T.w>0&&T.h>0){H=Math.min((I-2*k)/T.w,(F-2*k)/T.h),H=H>this._private.maxZoom?this._private.maxZoom:H,H=H=T.minZoom&&(T.maxZoom=k),this},minZoom:function(g){return g===void 0?this._private.minZoom:this.zoomRange({min:g})},maxZoom:function(g){return g===void 0?this._private.maxZoom:this.zoomRange({max:g})},getZoomedViewport:function(g){var k=this._private,T=k.pan,A=k.zoom,D,I,F=!1;if(k.zoomingEnabled||(F=!0),te(g)?I=g:de(g)&&(I=g.level,g.position!=null?D=E9(g.position,A,T):g.renderedPosition!=null&&(D=g.renderedPosition),D!=null&&!k.panningEnabled&&(F=!0)),I=I>k.maxZoom?k.maxZoom:I,I=Ik.maxZoom||!k.zoomingEnabled?I=!0:(k.zoom=H,D.push("zoom"))}if(A&&(!I||!g.cancelOnFailedZoom)&&k.panningEnabled){var C=g.pan;te(C.x)&&(k.pan.x=C.x,F=!1),te(C.y)&&(k.pan.y=C.y,F=!1),F||D.push("pan")}return D.length>0&&(D.push("viewport"),this.emit(D.join(" ")),this.notify("viewport")),this},center:function(g){var k=this.getCenterPan(g);return k&&(this._private.pan=k,this.emit("pan viewport"),this.notify("viewport")),this},getCenterPan:function(g,k){if(this._private.panningEnabled){if(ye(g)){var T=g;g=this.mutableElements().filter(T)}else he(g)||(g=this.mutableElements());if(g.length!==0){var A=g.boundingBox(),D=this.width(),I=this.height();k=k===void 0?this._private.zoom:k;var F={x:(D-k*(A.x1+A.x2))/2,y:(I-k*(A.y1+A.y2))/2};return F}}},reset:function(){return!this._private.panningEnabled||!this._private.zoomingEnabled?this:(this.viewport({pan:{x:0,y:0},zoom:1}),this)},invalidateSize:function(){this._private.sizeCache=null},size:function(){var g=this._private,k=g.container;return g.sizeCache=g.sizeCache||(k?function(){var T=$.getComputedStyle(k),A=function(I){return parseFloat(T.getPropertyValue(I))};return{width:k.clientWidth-A("padding-left")-A("padding-right"),height:k.clientHeight-A("padding-top")-A("padding-bottom")}}():{width:1,height:1})},width:function(){return this.size().width},height:function(){return this.size().height},extent:function(){var g=this._private.pan,k=this._private.zoom,T=this.renderedExtent(),A={x1:(T.x1-g.x)/k,x2:(T.x2-g.x)/k,y1:(T.y1-g.y)/k,y2:(T.y2-g.y)/k};return A.w=A.x2-A.x1,A.h=A.y2-A.y1,A},renderedExtent:function(){var g=this.width(),k=this.height();return{x1:0,y1:0,x2:g,y2:k,w:g,h:k}},multiClickDebounceTime:function(g){if(g)this._private.multiClickDebounceTime=g;else return this._private.multiClickDebounceTime;return this}};x3.centre=x3.center,x3.autolockNodes=x3.autolock,x3.autoungrabifyNodes=x3.autoungrabify;var Ix={data:Fc.data({field:"data",bindingEvent:"data",allowBinding:!0,allowSetting:!0,settingEvent:"data",settingTriggersEvent:!0,triggerFnName:"trigger",allowGetting:!0,updateStyle:!0}),removeData:Fc.removeData({field:"data",event:"data",triggerFnName:"trigger",triggerEvent:!0,updateStyle:!0}),scratch:Fc.data({field:"scratch",bindingEvent:"scratch",allowBinding:!0,allowSetting:!0,settingEvent:"scratch",settingTriggersEvent:!0,triggerFnName:"trigger",allowGetting:!0,updateStyle:!0}),removeScratch:Fc.removeData({field:"scratch",event:"scratch",triggerFnName:"trigger",triggerEvent:!0,updateStyle:!0})};Ix.attr=Ix.data,Ix.removeAttr=Ix.removeData;var Ox=function(g){var k=this;g=Oe({},g);var T=g.container;T&&!De(T)&&De(T[0])&&(T=T[0]);var A=T?T._cyreg:null;A=A||{},A&&A.cy&&(A.cy.destroy(),A={});var D=A.readies=A.readies||[];T&&(T._cyreg=A),A.cy=k;var I=$!==void 0&&T!==void 0&&!g.headless,F=g;F.layout=Oe({name:I?"grid":"null"},F.layout),F.renderer=Oe({name:I?"canvas":"null"},F.renderer);var H=function(ae,ue,_e){return ue!==void 0?ue:_e!==void 0?_e:ae},C=this._private={container:T,ready:!1,options:F,elements:new Wf(this),listeners:[],aniEles:new Wf(this),data:F.data||{},scratch:{},layout:null,renderer:null,destroyed:!1,notificationsEnabled:!0,minZoom:1e-50,maxZoom:1e50,zoomingEnabled:H(!0,F.zoomingEnabled),userZoomingEnabled:H(!0,F.userZoomingEnabled),panningEnabled:H(!0,F.panningEnabled),userPanningEnabled:H(!0,F.userPanningEnabled),boxSelectionEnabled:H(!0,F.boxSelectionEnabled),autolock:H(!1,F.autolock,F.autolockNodes),autoungrabify:H(!1,F.autoungrabify,F.autoungrabifyNodes),autounselectify:H(!1,F.autounselectify),styleEnabled:F.styleEnabled===void 0?I:F.styleEnabled,zoom:te(F.zoom)?F.zoom:1,pan:{x:de(F.pan)&&te(F.pan.x)?F.pan.x:0,y:de(F.pan)&&te(F.pan.y)?F.pan.y:0},animation:{current:[],queue:[]},hasCompoundNodes:!1,multiClickDebounceTime:H(250,F.multiClickDebounceTime)};this.createEmitter(),this.selectionType(F.selectionType),this.zoomRange({min:F.minZoom,max:F.maxZoom});var G=function(ae,ue){var _e=ae.some(jt);if(_e)return q5.all(ae).then(ue);ue(ae)};C.styleEnabled&&k.setStyle([]);var U=Oe({},F,F.renderer);k.initRenderer(U);var Z=function(ae,ue,_e){k.notifications(!1);var be=k.mutableElements();be.length>0&&be.remove(),ae!=null&&(de(ae)||Ae(ae))&&k.add(ae),k.one("layoutready",function(Le){k.notifications(!0),k.emit(Le),k.one("load",ue),k.emitAndNotify("load")}).one("layoutstop",function(){k.one("done",_e),k.emit("done")});var Se=Oe({},k._private.options.layout);Se.eles=k.elements(),k.layout(Se).run()};G([F.style,F.elements],function(ne){var ae=ne[0],ue=ne[1];C.styleEnabled&&k.style().append(ae),Z(ue,function(){k.startAnimationLoop(),C.ready=!0,ke(F.ready)&&k.on("ready",F.ready);for(var _e=0;_e0,H=zd(g.boundingBox?g.boundingBox:{x1:0,y1:0,w:k.width(),h:k.height()}),C;if(he(g.roots))C=g.roots;else if(Ae(g.roots)){for(var G=[],U=0;U0;){var un=lt(),Rt=ot(un,Je);if(Rt)un.outgoers().filter(function(Li){return Li.isNode()&&T.has(Li)}).forEach(Ct);else if(Rt===null){Vo("Detected double maximal shift for node `"+un.id()+"`. Bailing maximal adjustment due to cycle. Use `options.maximal: true` only on DAGs.");break}}}$e();var $t=0;if(g.avoidOverlap)for(var bn=0;bn0&&be[0].length<=3?Ks/2:0),On=2*Math.PI/be[Yi].length*Di;return Yi===0&&be[0].length===1&&(We=1),{x:Ti.x+We*Math.cos(On),y:Ti.y+We*Math.sin(On)}}else{var Ar={x:Ti.x+(Di+1-(es+1)/2)*eo,y:(Yi+1)*sa};return Ar}};return T.nodes().layoutPositions(this,g,Ba),this};var LJ={fit:!0,padding:30,boundingBox:void 0,avoidOverlap:!0,nodeDimensionsIncludeLabels:!1,spacingFactor:void 0,radius:void 0,startAngle:3/2*Math.PI,sweep:void 0,clockwise:!0,sort:void 0,animate:!1,animationDuration:500,animationEasing:void 0,animateFilter:function(g,k){return!0},ready:void 0,stop:void 0,transform:function(g,k){return k}};function nT(m){this.options=Oe({},LJ,m)}nT.prototype.run=function(){var m=this.options,g=m,k=m.cy,T=g.eles,A=g.counterclockwise!==void 0?!g.counterclockwise:g.clockwise,D=T.nodes().not(":parent");g.sort&&(D=D.sort(g.sort));for(var I=zd(g.boundingBox?g.boundingBox:{x1:0,y1:0,w:k.width(),h:k.height()}),F={x:I.x1+I.w/2,y:I.y1+I.h/2},H=g.sweep===void 0?2*Math.PI-2*Math.PI/D.length:g.sweep,C=H/Math.max(1,D.length-1),G,U=0,Z=0;Z1&&g.avoidOverlap){U*=1.75;var be=Math.cos(C)-Math.cos(0),Se=Math.sin(C)-Math.sin(0),Le=Math.sqrt(U*U/(be*be+Se*Se));G=Math.max(Le,G)}var Be=function(qe,Re){var Ze=g.startAngle+Re*C*(A?1:-1),$e=G*Math.cos(Ze),ot=G*Math.sin(Ze),ut={x:F.x+$e,y:F.y+ot};return ut};return T.nodes().layoutPositions(this,g,Be),this};var MJ={fit:!0,padding:30,startAngle:3/2*Math.PI,sweep:void 0,clockwise:!0,equidistant:!1,minNodeSpacing:10,boundingBox:void 0,avoidOverlap:!0,nodeDimensionsIncludeLabels:!1,height:void 0,width:void 0,spacingFactor:void 0,concentric:function(g){return g.degree()},levelWidth:function(g){return g.maxDegree()/4},animate:!1,animationDuration:500,animationEasing:void 0,animateFilter:function(g,k){return!0},ready:void 0,stop:void 0,transform:function(g,k){return k}};function TR(m){this.options=Oe({},MJ,m)}TR.prototype.run=function(){for(var m=this.options,g=m,k=g.counterclockwise!==void 0?!g.counterclockwise:g.clockwise,T=m.cy,A=g.eles,D=A.nodes().not(":parent"),I=zd(g.boundingBox?g.boundingBox:{x1:0,y1:0,w:T.width(),h:T.height()}),F={x:I.x1+I.w/2,y:I.y1+I.h/2},H=[],C=0,G=0;G0){var Ke=Math.abs(Se[0].value-Be.value);Ke>=_e&&(Se=[],be.push(Se))}Se.push(Be)}var qe=C+g.minNodeSpacing;if(!g.avoidOverlap){var Re=be.length>0&&be[0].length>1,Ze=Math.min(I.w,I.h)/2-qe,$e=Ze/(be.length+Re?1:0);qe=Math.min(qe,$e)}for(var ot=0,ut=0;ut1&&g.avoidOverlap){var un=Math.cos(lt)-Math.cos(0),Rt=Math.sin(lt)-Math.sin(0),$t=Math.sqrt(qe*qe/(un*un+Rt*Rt));ot=Math.max($t,ot)}Je.r=ot,ot+=qe}if(g.equidistant){for(var bn=0,Cn=0,Kn=0;Kn=m.numIter||(FJ(T,m),T.temperature=T.temperature*m.coolingFactor,T.temperature=m.animationThreshold&&D(),Aa(U)}};G()}else{for(;C;)C=I(H),H++;SR(T,m),F()}return this},rT.prototype.stop=function(){return this.stopped=!0,this.thread&&this.thread.stop(),this.emit("layoutstop"),this},rT.prototype.destroy=function(){return this.thread&&this.thread.stop(),this};var IJ=function(g,k,T){for(var A=T.eles.edges(),D=T.eles.nodes(),I={isCompound:g.hasCompoundNodes(),layoutNodes:[],idToIndex:{},nodeSize:D.size(),graphSet:[],indexToGraph:[],layoutEdges:[],edgeSize:A.size(),temperature:T.initialTemp,clientWidth:g.width(),clientHeight:g.width(),boundingBox:zd(T.boundingBox?T.boundingBox:{x1:0,y1:0,w:g.width(),h:g.height()})},F=T.eles.components(),H={},C=0;C0){I.graphSet.push(Re);for(var C=0;CA.count?0:A.graph},NJ=function m(g,k,T,A){var D=A.graphSet[T];if(-10)var U=A.nodeOverlap*G,Z=Math.sqrt(F*F+H*H),ne=U*F/Z,ae=U*H/Z;else var ue=iT(g,F,H),_e=iT(k,-1*F,-1*H),be=_e.x-ue.x,Se=_e.y-ue.y,Le=be*be+Se*Se,Z=Math.sqrt(Le),U=(g.nodeRepulsion+k.nodeRepulsion)/Le,ne=U*be/Z,ae=U*Se/Z;g.isLocked||(g.offsetX-=ne,g.offsetY-=ae),k.isLocked||(k.offsetX+=ne,k.offsetY+=ae)}},HJ=function(g,k,T,A){if(T>0)var D=g.maxX-k.minX;else var D=k.maxX-g.minX;if(A>0)var I=g.maxY-k.minY;else var I=k.maxY-g.minY;return D>=0&&I>=0?Math.sqrt(D*D+I*I):0},iT=function(g,k,T){var A=g.positionX,D=g.positionY,I=g.height||1,F=g.width||1,H=T/k,C=I/F,G={};return k===0&&0T?(G.x=A,G.y=D+I/2,G):0k&&-1*C<=H&&H<=C?(G.x=A-F/2,G.y=D-F*T/2/k,G):0=C)?(G.x=A+I*k/2/T,G.y=D+I/2,G):(0>T&&(H<=-1*C||H>=C)&&(G.x=A-I*k/2/T,G.y=D-I/2),G)},zJ=function(g,k){for(var T=0;TT){var _e=k.gravity*ne/ue,be=k.gravity*ae/ue;Z.offsetX+=_e,Z.offsetY+=be}}}}},qJ=function(g,k){var T=[],A=0,D=-1;for(T.push.apply(T,g.graphSet[0]),D+=g.graphSet[0].length;A<=D;){var I=T[A++],F=g.idToIndex[I],H=g.layoutNodes[F],C=H.children;if(0T)var D={x:T*g/A,y:T*k/A};else var D={x:g,y:k};return D},WJ=function m(g,k){var T=g.parentId;if(T!=null){var A=k.layoutNodes[k.idToIndex[T]],D=!1;if((A.maxX==null||g.maxX+A.padRight>A.maxX)&&(A.maxX=g.maxX+A.padRight,D=!0),(A.minX==null||g.minX-A.padLeftA.maxY)&&(A.maxY=g.maxY+A.padBottom,D=!0),(A.minY==null||g.minY-A.padTopbe&&(ae+=_e+k.componentSpacing,ne=0,ue=0,_e=0)}}},KJ={fit:!0,padding:30,boundingBox:void 0,avoidOverlap:!0,avoidOverlapPadding:10,nodeDimensionsIncludeLabels:!1,spacingFactor:void 0,condense:!1,rows:void 0,cols:void 0,position:function(g){},sort:void 0,animate:!1,animationDuration:500,animationEasing:void 0,animateFilter:function(g,k){return!0},ready:void 0,stop:void 0,transform:function(g,k){return k}};function AR(m){this.options=Oe({},KJ,m)}AR.prototype.run=function(){var m=this.options,g=m,k=m.cy,T=g.eles,A=T.nodes().not(":parent");g.sort&&(A=A.sort(g.sort));var D=zd(g.boundingBox?g.boundingBox:{x1:0,y1:0,w:k.width(),h:k.height()});if(D.h===0||D.w===0)T.nodes().layoutPositions(this,g,function(sr){return{x:D.x1,y:D.y1}});else{var I=A.size(),F=Math.sqrt(I*D.h/D.w),H=Math.round(F),C=Math.round(D.w/D.h*F),G=function(yr){if(yr==null)return Math.min(H,C);var hr=Math.min(H,C);hr==H?H=yr:C=yr},U=function(yr){if(yr==null)return Math.max(H,C);var hr=Math.max(H,C);hr==H?H=yr:C=yr},Z=g.rows,ne=g.cols!=null?g.cols:g.columns;if(Z!=null&&ne!=null)H=Z,C=ne;else if(Z!=null&&ne==null)H=Z,C=Math.ceil(I/H);else if(Z==null&&ne!=null)C=ne,H=Math.ceil(I/C);else if(C*H>I){var ae=G(),ue=U();(ae-1)*ue>=I?G(ae-1):(ue-1)*ae>=I&&U(ue-1)}else for(;C*H=I?U(be+1):G(_e+1)}var Se=D.w/C,Le=D.h/H;if(g.condense&&(Se=0,Le=0),g.avoidOverlap)for(var Be=0;Be=C&&(un=0,lt++)},$t={},bn=0;bn(un=OY(m,g,Rt[$t],Rt[$t+1],Rt[$t+2],Rt[$t+3])))return _e(Re,un),!0}else if($e.edgeType==="bezier"||$e.edgeType==="multibezier"||$e.edgeType==="self"||$e.edgeType==="compound"){for(var Rt=$e.allpts,$t=0;$t+5<$e.allpts.length;$t+=4)if(LY(m,g,Rt[$t],Rt[$t+1],Rt[$t+2],Rt[$t+3],Rt[$t+4],Rt[$t+5],lt)&&Ct>(un=IY(m,g,Rt[$t],Rt[$t+1],Rt[$t+2],Rt[$t+3],Rt[$t+4],Rt[$t+5])))return _e(Re,un),!0}for(var bn=bn||Ze.source,Cn=Cn||Ze.target,Kn=A.getArrowWidth(ot,ut),kn=[{name:"source",x:$e.arrowStartX,y:$e.arrowStartY,angle:$e.srcArrowAngle},{name:"target",x:$e.arrowEndX,y:$e.arrowEndY,angle:$e.tgtArrowAngle},{name:"mid-source",x:$e.midX,y:$e.midY,angle:$e.midsrcArrowAngle},{name:"mid-target",x:$e.midX,y:$e.midY,angle:$e.midtgtArrowAngle}],$t=0;$t0&&(be(bn),be(Cn))}function Le(Re,Ze,$e){return gp(Re,Ze,$e)}function Be(Re,Ze){var $e=Re._private,ot=Z,ut;Ze?ut=Ze+"-":ut="",Re.boundingBox();var Je=$e.labelBounds[Ze||"main"],Ct=Re.pstyle(ut+"label").value,lt=Re.pstyle("text-events").strValue==="yes";if(!(!lt||!Ct)){var un=Le($e.rscratch,"labelX",Ze),Rt=Le($e.rscratch,"labelY",Ze),$t=Le($e.rscratch,"labelAngle",Ze),bn=Re.pstyle(ut+"text-margin-x").pfValue,Cn=Re.pstyle(ut+"text-margin-y").pfValue,Kn=Je.x1-ot-bn,kn=Je.x2+ot-bn,Wn=Je.y1-ot-Cn,sr=Je.y2+ot-Cn;if($t){var yr=Math.cos($t),hr=Math.sin($t),nr=function(Ba,Li){return Ba=Ba-un,Li=Li-Rt,{x:Ba*yr-Li*hr+un,y:Ba*hr+Li*yr+Rt}},fn=nr(Kn,Wn),vr=nr(Kn,sr),gr=nr(kn,Wn),ni=nr(kn,sr),Ti=[fn.x+bn,fn.y+Cn,gr.x+bn,gr.y+Cn,ni.x+bn,ni.y+Cn,vr.x+bn,vr.y+Cn];if(Gd(m,g,Ti))return _e(Re),!0}else if($5(Je,m,g))return _e(Re),!0}}for(var Ke=I.length-1;Ke>=0;Ke--){var qe=I[Ke];qe.isNode()?be(qe)||Be(qe):Se(qe)||Be(qe)||Be(qe,"source")||Be(qe,"target")}return F},E3.getAllInBox=function(m,g,k,T){var A=this.getCachedZSortedEles().interactive,D=[],I=Math.min(m,k),F=Math.max(m,k),H=Math.min(g,T),C=Math.max(g,T);m=I,k=F,g=H,T=C;for(var G=zd({x1:m,y1:g,x2:k,y2:T}),U=0;U0?Math.max(is-Uo,0):Math.min(is+Uo,0)},Ct=Je(ot,Ze),lt=Je(ut,$e),un=!1;Se===C?be=Math.abs(Ct)>Math.abs(lt)?A:T:Se===H||Se===F?(be=T,un=!0):(Se===D||Se===I)&&(be=A,un=!0);var Rt=be===T,$t=Rt?lt:Ct,bn=Rt?ut:ot,Cn=WP(bn),Kn=!1;!(un&&(Be||qe))&&(Se===F&&bn<0||Se===H&&bn>0||Se===D&&bn>0||Se===I&&bn<0)&&(Cn*=-1,$t=Cn*Math.abs($t),Kn=!0);var kn;if(Be){var Wn=Ke<0?1+Ke:Ke;kn=Wn*$t}else{var sr=Ke<0?$t:0;kn=sr+Ke*Cn}var yr=function(is){return Math.abs(is)=Math.abs($t)},hr=yr(kn),nr=yr(Math.abs($t)-Math.abs(kn)),fn=hr||nr;if(fn&&!Kn)if(Rt){var vr=Math.abs(bn)<=Z/2,gr=Math.abs(ot)<=ne/2;if(vr){var ni=(G.x1+G.x2)/2,Ti=G.y1,ia=G.y2;k.segpts=[ni,Ti,ni,ia]}else if(gr){var Ba=(G.y1+G.y2)/2,Li=G.x1,wi=G.x2;k.segpts=[Li,Ba,wi,Ba]}else k.segpts=[G.x1,G.y2]}else{var Ts=Math.abs(bn)<=U/2,Yi=Math.abs(ut)<=ae/2;if(Ts){var Di=(G.y1+G.y2)/2,es=G.x1,eo=G.x2;k.segpts=[es,Di,eo,Di]}else if(Yi){var sa=(G.x1+G.x2)/2,Ks=G.y1,Ar=G.y2;k.segpts=[sa,Ks,sa,Ar]}else k.segpts=[G.x2,G.y1]}else if(Rt){var We=G.y1+kn+(_e?Z/2*Cn:0),On=G.x1,Ir=G.x2;k.segpts=[On,We,Ir,We]}else{var ar=G.x1+kn+(_e?U/2*Cn:0),or=G.y1,qa=G.y2;k.segpts=[ar,or,ar,qa]}},hd.tryToCorrectInvalidPoints=function(m,g){var k=m._private.rscratch;if(k.edgeType==="bezier"){var T=g.srcPos,A=g.tgtPos,D=g.srcW,I=g.srcH,F=g.tgtW,H=g.tgtH,C=g.srcShape,G=g.tgtShape,U=!te(k.startX)||!te(k.startY),Z=!te(k.arrowStartX)||!te(k.arrowStartY),ne=!te(k.endX)||!te(k.endY),ae=!te(k.arrowEndX)||!te(k.arrowEndY),ue=3,_e=this.getArrowWidth(m.pstyle("width").pfValue,m.pstyle("arrow-scale").value)*this.arrowShapeWidth,be=ue*_e,Se=v3({x:k.ctrlpts[0],y:k.ctrlpts[1]},{x:k.startX,y:k.startY}),Le=Selt.poolIndex()){var un=Ct;Ct=lt,lt=un}var Rt=$e.srcPos=Ct.position(),$t=$e.tgtPos=lt.position(),bn=$e.srcW=Ct.outerWidth(),Cn=$e.srcH=Ct.outerHeight(),Kn=$e.tgtW=lt.outerWidth(),kn=$e.tgtH=lt.outerHeight(),Wn=$e.srcShape=k.nodeShapes[g.getNodeShape(Ct)],sr=$e.tgtShape=k.nodeShapes[g.getNodeShape(lt)];$e.dirCounts={north:0,west:0,south:0,east:0,northwest:0,southwest:0,northeast:0,southeast:0};for(var yr=0;yr<$e.eles.length;yr++){var hr=$e.eles[yr],nr=hr[0]._private.rscratch,fn=hr.pstyle("curve-style").value,vr=fn==="unbundled-bezier"||fn==="segments"||fn==="taxi",gr=!Ct.same(hr.source());if(!$e.calculatedIntersection&&Ct!==lt&&($e.hasBezier||$e.hasUnbundled)){$e.calculatedIntersection=!0;var ni=Wn.intersectLine(Rt.x,Rt.y,bn,Cn,$t.x,$t.y,0),Ti=$e.srcIntn=ni,ia=sr.intersectLine($t.x,$t.y,Kn,kn,Rt.x,Rt.y,0),Ba=$e.tgtIntn=ia,Li=$e.intersectionPts={x1:ni[0],x2:ia[0],y1:ni[1],y2:ia[1]},wi=$e.posPts={x1:Rt.x,x2:$t.x,y1:Rt.y,y2:$t.y},Ts=ia[1]-ni[1],Yi=ia[0]-ni[0],Di=Math.sqrt(Yi*Yi+Ts*Ts),es=$e.vector={x:Yi,y:Ts},eo=$e.vectorNorm={x:es.x/Di,y:es.y/Di},sa={x:-eo.y,y:eo.x};$e.nodesOverlap=!te(Di)||sr.checkPoint(ni[0],ni[1],0,Kn,kn,$t.x,$t.y)||Wn.checkPoint(ia[0],ia[1],0,bn,Cn,Rt.x,Rt.y),$e.vectorNormInverse=sa,ot={nodesOverlap:$e.nodesOverlap,dirCounts:$e.dirCounts,calculatedIntersection:!0,hasBezier:$e.hasBezier,hasUnbundled:$e.hasUnbundled,eles:$e.eles,srcPos:$t,tgtPos:Rt,srcW:Kn,srcH:kn,tgtW:bn,tgtH:Cn,srcIntn:Ba,tgtIntn:Ti,srcShape:sr,tgtShape:Wn,posPts:{x1:wi.x2,y1:wi.y2,x2:wi.x1,y2:wi.y1},intersectionPts:{x1:Li.x2,y1:Li.y2,x2:Li.x1,y2:Li.y1},vector:{x:-es.x,y:-es.y},vectorNorm:{x:-eo.x,y:-eo.y},vectorNormInverse:{x:-sa.x,y:-sa.y}}}var Ks=gr?ot:$e;nr.nodesOverlap=Ks.nodesOverlap,nr.srcIntn=Ks.srcIntn,nr.tgtIntn=Ks.tgtIntn,A&&(Ct.isParent()||Ct.isChild()||lt.isParent()||lt.isChild())&&(Ct.parents().anySame(lt)||lt.parents().anySame(Ct)||Ct.same(lt)&&Ct.isParent())?g.findCompoundLoopPoints(hr,Ks,yr,vr):Ct===lt?g.findLoopPoints(hr,Ks,yr,vr):fn==="segments"?g.findSegmentsPoints(hr,Ks):fn==="taxi"?g.findTaxiPoints(hr,Ks):fn==="straight"||!vr&&$e.eles.length%2===1&&yr===Math.floor($e.eles.length/2)?g.findStraightEdgePoints(hr):g.findBezierPoints(hr,Ks,yr,vr,gr),g.findEndpoints(hr),g.tryToCorrectInvalidPoints(hr,Ks),g.checkForInvalidEdgeWarning(hr),g.storeAllpts(hr),g.storeEdgeProjections(hr),g.calculateArrowAngles(hr),g.recalculateEdgeLabelProjections(hr),g.calculateLabelAngles(hr)}},Ke=0;Ke0){var vr=D,gr=w3(vr,F5(k)),ni=w3(vr,F5(fn)),Ti=gr;if(ni2){var ia=w3(vr,{x:fn[2],y:fn[3]});ia0){var On=I,Ir=w3(On,F5(k)),ar=w3(On,F5(We)),or=Ir;if(ar2){var qa=w3(On,{x:We[2],y:We[3]});qa=ae||Re){_e={cp:Be,segment:qe};break}}if(_e)break}var Ze=_e.cp,$e=_e.segment,ot=(ae-be)/$e.length,ut=$e.t1-$e.t0,Je=ne?$e.t0+ut*ot:$e.t1-ut*ot;Je=px(0,Je,1),g=j5(Ze.p0,Ze.p1,Ze.p2,Je),Z=RR(Ze.p0,Ze.p1,Ze.p2,Je);break}case"straight":case"segments":case"haystack":{for(var Ct=0,lt,un,Rt,$t,bn=T.allpts.length,Cn=0;Cn+3=ae));Cn+=2);var Kn=ae-un,kn=Kn/lt;kn=px(0,kn,1),g=xY(Rt,$t,kn),Z=BR(Rt,$t);break}}I("labelX",U,g.x),I("labelY",U,g.y),I("labelAutoAngle",U,Z)}};C("source"),C("target"),this.applyLabelDimensions(m)}},wp.applyLabelDimensions=function(m){this.applyPrefixedLabelDimensions(m),m.isEdge()&&(this.applyPrefixedLabelDimensions(m,"source"),this.applyPrefixedLabelDimensions(m,"target"))},wp.applyPrefixedLabelDimensions=function(m,g){var k=m._private,T=this.getLabelText(m,g),A=this.calculateLabelDimensions(m,T),D=m.pstyle("line-height").pfValue,I=m.pstyle("text-wrap").strValue,F=gp(k.rscratch,"labelWrapCachedLines",g)||[],H=I!=="wrap"?1:Math.max(F.length,1),C=A.height/H,G=C*D,U=A.width,Z=A.height+(H-1)*(D-1)*C;um(k.rstyle,"labelWidth",g,U),um(k.rscratch,"labelWidth",g,U),um(k.rstyle,"labelHeight",g,Z),um(k.rscratch,"labelHeight",g,Z),um(k.rscratch,"labelLineHeight",g,G)},wp.getLabelText=function(m,g){var k=m._private,T=g?g+"-":"",A=m.pstyle(T+"label").strValue,D=m.pstyle("text-transform").value,I=function(Kn,kn){return kn?(um(k.rscratch,Kn,g,kn),kn):gp(k.rscratch,Kn,g)};if(!A)return"";D=="none"||(D=="uppercase"?A=A.toUpperCase():D=="lowercase"&&(A=A.toLowerCase()));var F=m.pstyle("text-wrap").value;if(F==="wrap"){var H=I("labelKey");if(H!=null&&I("labelWrapKey")===H)return I("labelWrapCachedText");for(var C="​",G=A.split(` +`),U=m.pstyle("text-max-width").pfValue,Z=m.pstyle("text-overflow-wrap").value,ne=Z==="anywhere",ae=[],ue=/[\s\u200b]+/,_e=ne?"":" ",be=0;beU){for(var qe=Se.split(ue),Re="",Ze=0;ZeCt)break;lt+=A[$t],$t===A.length-1&&(Rt=!0)}return Rt||(lt+=un),lt}return A},wp.getLabelJustification=function(m){var g=m.pstyle("text-justification").strValue,k=m.pstyle("text-halign").strValue;if(g==="auto")if(m.isNode())switch(k){case"left":return"right";case"right":return"left";default:return"center"}else return"center";else return g},wp.calculateLabelDimensions=function(m,g){var k=this,T=od(g,m._private.labelDimsKey),A=k.labelDimCache||(k.labelDimCache=[]),D=A[T];if(D!=null)return D;var I=0,F=m.pstyle("font-style").strValue,H=m.pstyle("font-size").pfValue,C=m.pstyle("font-family").strValue,G=m.pstyle("font-weight").strValue,U=this.labelCalcCanvas,Z=this.labelCalcCanvasContext;if(!U){U=this.labelCalcCanvas=document.createElement("canvas"),Z=this.labelCalcCanvasContext=U.getContext("2d");var ne=U.style;ne.position="absolute",ne.left="-9999px",ne.top="-9999px",ne.zIndex="-1",ne.visibility="hidden",ne.pointerEvents="none"}Z.font="".concat(F," ").concat(G," ").concat(H,"px ").concat(C);for(var ae=0,ue=0,_e=g.split(` +`),be=0;be<_e.length;be++){var Se=_e[be],Le=Z.measureText(Se),Be=Math.ceil(Le.width),Ke=H;ae=Math.max(Be,ae),ue+=Ke}return ae+=I,ue+=I,A[T]={width:ae,height:ue}},wp.calculateLabelAngle=function(m,g){var k=m._private,T=k.rscratch,A=m.isEdge(),D=g?g+"-":"",I=m.pstyle(D+"text-rotation"),F=I.strValue;return F==="none"?0:A&&F==="autorotate"?T.labelAutoAngle:F==="autorotate"?0:I.pfValue},wp.calculateLabelAngles=function(m){var g=this,k=m.isEdge(),T=m._private,A=T.rscratch;A.labelAngle=g.calculateLabelAngle(m),k&&(A.sourceLabelAngle=g.calculateLabelAngle(m,"source"),A.targetLabelAngle=g.calculateLabelAngle(m,"target"))};var ch={},YL=28,FR=!1;ch.getNodeShape=function(m){var g=this,k=m.pstyle("shape").value;if(k==="cutrectangle"&&(m.width()1&&arguments[1]!==void 0?arguments[1]:!0;if(g.merge(I),F)for(var H=0;H=m.desktopTapThreshold2}var ov=T(We);Yf&&(m.hoverData.tapholdCancelled=!0);var mm=function(){var $2=m.hoverData.dragDelta=m.hoverData.dragDelta||[];$2.length===0?($2.push(lo[0]),$2.push(lo[1])):($2[0]+=lo[0],$2[1]+=lo[1])};Ir=!0,k(uo,["mousemove","vmousemove","tapdrag"],We,{x:qr[0],y:qr[1]});var l6=function(){m.data.bgActivePosistion=void 0,m.hoverData.selecting||ar.emit({originalEvent:We,type:"boxstart",position:{x:qr[0],y:qr[1]}}),qc[4]=1,m.hoverData.selecting=!0,m.redrawHint("select",!0),m.redraw()};if(m.hoverData.which===3){if(Yf){var S3={originalEvent:We,type:"cxtdrag",position:{x:qr[0],y:qr[1]}};Ra?Ra.emit(S3):ar.emit(S3),m.hoverData.cxtDragged=!0,(!m.hoverData.cxtOver||uo!==m.hoverData.cxtOver)&&(m.hoverData.cxtOver&&m.hoverData.cxtOver.emit({originalEvent:We,type:"cxtdragout",position:{x:qr[0],y:qr[1]}}),m.hoverData.cxtOver=uo,uo&&uo.emit({originalEvent:We,type:"cxtdragover",position:{x:qr[0],y:qr[1]}}))}}else if(m.hoverData.dragging){if(Ir=!0,ar.panningEnabled()&&ar.userPanningEnabled()){var h6;if(m.hoverData.justStartedPan){var gT=m.hoverData.mdownPos;h6={x:(qr[0]-gT[0])*or,y:(qr[1]-gT[1])*or},m.hoverData.justStartedPan=!1}else h6={x:lo[0]*or,y:lo[1]*or};ar.panBy(h6),ar.emit("dragpan"),m.hoverData.dragged=!0}qr=m.projectIntoViewport(We.clientX,We.clientY)}else if(qc[4]==1&&(Ra==null||Ra.pannable())){if(Yf){if(!m.hoverData.dragging&&ar.boxSelectionEnabled()&&(ov||!ar.panningEnabled()||!ar.userPanningEnabled()))l6();else if(!m.hoverData.selecting&&ar.panningEnabled()&&ar.userPanningEnabled()){var A3=A(Ra,m.hoverData.downs);A3&&(m.hoverData.dragging=!0,m.hoverData.justStartedPan=!0,qc[4]=0,m.data.bgActivePosistion=F5(is),m.redrawHint("select",!0),m.redraw())}Ra&&Ra.pannable()&&Ra.active()&&Ra.unactivate()}}else{if(Ra&&Ra.pannable()&&Ra.active()&&Ra.unactivate(),(!Ra||!Ra.grabbed())&&uo!=Lc&&(Lc&&k(Lc,["mouseout","tapdragout"],We,{x:qr[0],y:qr[1]}),uo&&k(uo,["mouseover","tapdragover"],We,{x:qr[0],y:qr[1]}),m.hoverData.last=uo),Ra)if(Yf){if(ar.boxSelectionEnabled()&&ov)Ra&&Ra.grabbed()&&(ue(Sl),Ra.emit("freeon"),Sl.emit("free"),m.dragData.didDrag&&(Ra.emit("dragfreeon"),Sl.emit("dragfree"))),l6();else if(Ra&&Ra.grabbed()&&m.nodeIsDraggable(Ra)){var qd=!m.dragData.didDrag;qd&&m.redrawHint("eles",!0),m.dragData.didDrag=!0,m.hoverData.draggingEles||ne(Sl,{inDragLayer:!0});var _1={x:0,y:0};if(te(lo[0])&&te(lo[1])&&(_1.x+=lo[0],_1.y+=lo[1],qd)){var Vd=m.hoverData.dragDelta;Vd&&te(Vd[0])&&te(Vd[1])&&(_1.x+=Vd[0],_1.y+=Vd[1])}m.hoverData.draggingEles=!0,Sl.silentShift(_1).emit("position drag"),m.redrawHint("drag",!0),m.redraw()}}else mm();Ir=!0}if(qc[2]=qr[0],qc[3]=qr[1],Ir)return We.stopPropagation&&We.stopPropagation(),We.preventDefault&&We.preventDefault(),!1}},!1);var $e,ot,ut;m.registerBinding(window,"mouseup",function(We){var On=m.hoverData.capture;if(On){m.hoverData.capture=!1;var Ir=m.cy,ar=m.projectIntoViewport(We.clientX,We.clientY),or=m.selection,qa=m.findNearestElement(ar[0],ar[1],!0,!1),qr=m.dragData.possibleDragElements,is=m.hoverData.down,Uo=T(We);if(m.data.bgActivePosistion&&(m.redrawHint("select",!0),m.redraw()),m.hoverData.tapholdCancelled=!0,m.data.bgActivePosistion=void 0,is&&is.unactivate(),m.hoverData.which===3){var qc={originalEvent:We,type:"cxttapend",position:{x:ar[0],y:ar[1]}};if(is?is.emit(qc):Ir.emit(qc),!m.hoverData.cxtDragged){var uo={originalEvent:We,type:"cxttap",position:{x:ar[0],y:ar[1]}};is?is.emit(uo):Ir.emit(uo)}m.hoverData.cxtDragged=!1,m.hoverData.which=null}else if(m.hoverData.which===1){if(k(qa,["mouseup","tapend","vmouseup"],We,{x:ar[0],y:ar[1]}),!m.dragData.didDrag&&!m.hoverData.dragged&&!m.hoverData.selecting&&!m.hoverData.isOverThresholdDrag&&(k(is,["click","tap","vclick"],We,{x:ar[0],y:ar[1]}),ot=!1,We.timeStamp-ut<=Ir.multiClickDebounceTime()?($e&&clearTimeout($e),ot=!0,ut=null,k(is,["dblclick","dbltap","vdblclick"],We,{x:ar[0],y:ar[1]})):($e=setTimeout(function(){ot||k(is,["oneclick","onetap","voneclick"],We,{x:ar[0],y:ar[1]})},Ir.multiClickDebounceTime()),ut=We.timeStamp)),is==null&&!m.dragData.didDrag&&!m.hoverData.selecting&&!m.hoverData.dragged&&!T(We)&&(Ir.$(g).unselect(["tapunselect"]),qr.length>0&&m.redrawHint("eles",!0),m.dragData.possibleDragElements=qr=Ir.collection()),qa==is&&!m.dragData.didDrag&&!m.hoverData.selecting&&qa!=null&&qa._private.selectable&&(m.hoverData.dragging||(Ir.selectionType()==="additive"||Uo?qa.selected()?qa.unselect(["tapunselect"]):qa.select(["tapselect"]):Uo||(Ir.$(g).unmerge(qa).unselect(["tapunselect"]),qa.select(["tapselect"]))),m.redrawHint("eles",!0)),m.hoverData.selecting){var Lc=Ir.collection(m.getAllInBox(or[0],or[1],or[2],or[3]));m.redrawHint("select",!0),Lc.length>0&&m.redrawHint("eles",!0),Ir.emit({type:"boxend",originalEvent:We,position:{x:ar[0],y:ar[1]}});var Ra=function(Yf){return Yf.selectable()&&!Yf.selected()};Ir.selectionType()==="additive"||Uo||Ir.$(g).unmerge(Lc).unselect(),Lc.emit("box").stdFilter(Ra).select().emit("boxselect"),m.redraw()}if(m.hoverData.dragging&&(m.hoverData.dragging=!1,m.redrawHint("select",!0),m.redrawHint("eles",!0),m.redraw()),!or[4]){m.redrawHint("drag",!0),m.redrawHint("eles",!0);var lo=is&&is.grabbed();ue(qr),lo&&(is.emit("freeon"),qr.emit("free"),m.dragData.didDrag&&(is.emit("dragfreeon"),qr.emit("dragfree")))}}or[4]=0,m.hoverData.down=null,m.hoverData.cxtStarted=!1,m.hoverData.draggingEles=!1,m.hoverData.selecting=!1,m.hoverData.isOverThresholdDrag=!1,m.dragData.didDrag=!1,m.hoverData.dragged=!1,m.hoverData.dragDelta=[],m.hoverData.mdownPos=null,m.hoverData.mdownGPos=null}},!1);var Je=function(We){if(!m.scrollingPage){var On=m.cy,Ir=On.zoom(),ar=On.pan(),or=m.projectIntoViewport(We.clientX,We.clientY),qa=[or[0]*Ir+ar.x,or[1]*Ir+ar.y];if(m.hoverData.draggingEles||m.hoverData.dragging||m.hoverData.cxtStarted||Re()){We.preventDefault();return}if(On.panningEnabled()&&On.userPanningEnabled()&&On.zoomingEnabled()&&On.userZoomingEnabled()){We.preventDefault(),m.data.wheelZooming=!0,clearTimeout(m.data.wheelTimeout),m.data.wheelTimeout=setTimeout(function(){m.data.wheelZooming=!1,m.redrawHint("eles",!0),m.redraw()},150);var qr;We.deltaY!=null?qr=We.deltaY/-250:We.wheelDeltaY!=null?qr=We.wheelDeltaY/1e3:qr=We.wheelDelta/1e3,qr=qr*m.wheelSensitivity;var is=We.deltaMode===1;is&&(qr*=33);var Uo=On.zoom()*Math.pow(10,qr);We.type==="gesturechange"&&(Uo=m.gestureStartZoom*We.scale),On.zoom({level:Uo,renderedPosition:{x:qa[0],y:qa[1]}}),On.emit(We.type==="gesturechange"?"pinchzoom":"scrollzoom")}}};m.registerBinding(m.container,"wheel",Je,!0),m.registerBinding(window,"scroll",function(We){m.scrollingPage=!0,clearTimeout(m.scrollingPageTimeout),m.scrollingPageTimeout=setTimeout(function(){m.scrollingPage=!1},250)},!0),m.registerBinding(m.container,"gesturestart",function(We){m.gestureStartZoom=m.cy.zoom(),m.hasTouchStarted||We.preventDefault()},!0),m.registerBinding(m.container,"gesturechange",function(Ar){m.hasTouchStarted||Je(Ar)},!0),m.registerBinding(m.container,"mouseout",function(We){var On=m.projectIntoViewport(We.clientX,We.clientY);m.cy.emit({originalEvent:We,type:"mouseout",position:{x:On[0],y:On[1]}})},!1),m.registerBinding(m.container,"mouseover",function(We){var On=m.projectIntoViewport(We.clientX,We.clientY);m.cy.emit({originalEvent:We,type:"mouseover",position:{x:On[0],y:On[1]}})},!1);var Ct,lt,un,Rt,$t,bn,Cn,Kn,kn,Wn,sr,yr,hr,nr=function(We,On,Ir,ar){return Math.sqrt((Ir-We)*(Ir-We)+(ar-On)*(ar-On))},fn=function(We,On,Ir,ar){return(Ir-We)*(Ir-We)+(ar-On)*(ar-On)},vr;m.registerBinding(m.container,"touchstart",vr=function(We){if(m.hasTouchStarted=!0,!!Ze(We)){be(),m.touchData.capture=!0,m.data.bgActivePosistion=void 0;var On=m.cy,Ir=m.touchData.now,ar=m.touchData.earlier;if(We.touches[0]){var or=m.projectIntoViewport(We.touches[0].clientX,We.touches[0].clientY);Ir[0]=or[0],Ir[1]=or[1]}if(We.touches[1]){var or=m.projectIntoViewport(We.touches[1].clientX,We.touches[1].clientY);Ir[2]=or[0],Ir[3]=or[1]}if(We.touches[2]){var or=m.projectIntoViewport(We.touches[2].clientX,We.touches[2].clientY);Ir[4]=or[0],Ir[5]=or[1]}if(We.touches[1]){m.touchData.singleTouchMoved=!0,ue(m.dragData.touchDragEles);var qa=m.findContainerClientCoords();kn=qa[0],Wn=qa[1],sr=qa[2],yr=qa[3],Ct=We.touches[0].clientX-kn,lt=We.touches[0].clientY-Wn,un=We.touches[1].clientX-kn,Rt=We.touches[1].clientY-Wn,hr=0<=Ct&&Ct<=sr&&0<=un&&un<=sr&&0<=lt&<<=yr&&0<=Rt&&Rt<=yr;var qr=On.pan(),is=On.zoom();$t=nr(Ct,lt,un,Rt),bn=fn(Ct,lt,un,Rt),Cn=[(Ct+un)/2,(lt+Rt)/2],Kn=[(Cn[0]-qr.x)/is,(Cn[1]-qr.y)/is];var Uo=200,qc=Uo*Uo;if(bn=1){for(var yp=m.touchData.startPosition=[],Xf=0;Xf=m.touchTapThreshold2}if(On&&m.touchData.cxt){We.preventDefault();var yp=We.touches[0].clientX-kn,Xf=We.touches[0].clientY-Wn,gg=We.touches[1].clientX-kn,fd=We.touches[1].clientY-Wn,ov=fn(yp,Xf,gg,fd),mm=ov/bn,l6=150,S3=l6*l6,h6=1.5,gT=h6*h6;if(mm>=gT||ov>=S3){m.touchData.cxt=!1,m.data.bgActivePosistion=void 0,m.redrawHint("select",!0);var A3={originalEvent:We,type:"cxttapend",position:{x:or[0],y:or[1]}};m.touchData.start?(m.touchData.start.unactivate().emit(A3),m.touchData.start=null):ar.emit(A3)}}if(On&&m.touchData.cxt){var A3={originalEvent:We,type:"cxtdrag",position:{x:or[0],y:or[1]}};m.data.bgActivePosistion=void 0,m.redrawHint("select",!0),m.touchData.start?m.touchData.start.emit(A3):ar.emit(A3),m.touchData.start&&(m.touchData.start._private.grabbed=!1),m.touchData.cxtDragged=!0;var qd=m.findNearestElement(or[0],or[1],!0,!0);(!m.touchData.cxtOver||qd!==m.touchData.cxtOver)&&(m.touchData.cxtOver&&m.touchData.cxtOver.emit({originalEvent:We,type:"cxtdragout",position:{x:or[0],y:or[1]}}),m.touchData.cxtOver=qd,qd&&qd.emit({originalEvent:We,type:"cxtdragover",position:{x:or[0],y:or[1]}}))}else if(On&&We.touches[2]&&ar.boxSelectionEnabled())We.preventDefault(),m.data.bgActivePosistion=void 0,this.lastThreeTouch=+new Date,m.touchData.selecting||ar.emit({originalEvent:We,type:"boxstart",position:{x:or[0],y:or[1]}}),m.touchData.selecting=!0,m.touchData.didSelect=!0,Ir[4]=1,!Ir||Ir.length===0||Ir[0]===void 0?(Ir[0]=(or[0]+or[2]+or[4])/3,Ir[1]=(or[1]+or[3]+or[5])/3,Ir[2]=(or[0]+or[2]+or[4])/3+1,Ir[3]=(or[1]+or[3]+or[5])/3+1):(Ir[2]=(or[0]+or[2]+or[4])/3,Ir[3]=(or[1]+or[3]+or[5])/3),m.redrawHint("select",!0),m.redraw();else if(On&&We.touches[1]&&!m.touchData.didSelect&&ar.zoomingEnabled()&&ar.panningEnabled()&&ar.userZoomingEnabled()&&ar.userPanningEnabled()){We.preventDefault(),m.data.bgActivePosistion=void 0,m.redrawHint("select",!0);var _1=m.dragData.touchDragEles;if(_1){m.redrawHint("drag",!0);for(var Vd=0;Vd<_1.length;Vd++){var pT=_1[Vd]._private;pT.grabbed=!1,pT.rscratch.inDragLayer=!1}}var $2=m.touchData.start,yp=We.touches[0].clientX-kn,Xf=We.touches[0].clientY-Wn,gg=We.touches[1].clientX-kn,fd=We.touches[1].clientY-Wn,QR=nr(yp,Xf,gg,fd),Dee=QR/$t;if(hr){var Iee=yp-Ct,Oee=Xf-lt,Nee=gg-un,Pee=fd-Rt,Bee=(Iee+Nee)/2,Ree=(Oee+Pee)/2,Gx=ar.zoom(),iM=Gx*Dee,bT=ar.pan(),ZR=Kn[0]*Gx+bT.x,JR=Kn[1]*Gx+bT.y,Fee={x:-iM/Gx*(ZR-bT.x-Bee)+ZR,y:-iM/Gx*(JR-bT.y-Ree)+JR};if($2&&$2.active()){var _1=m.dragData.touchDragEles;ue(_1),m.redrawHint("drag",!0),m.redrawHint("eles",!0),$2.unactivate().emit("freeon"),_1.emit("free"),m.dragData.didDrag&&($2.emit("dragfreeon"),_1.emit("dragfree"))}ar.viewport({zoom:iM,pan:Fee,cancelOnFailedZoom:!0}),ar.emit("pinchzoom"),$t=QR,Ct=yp,lt=Xf,un=gg,Rt=fd,m.pinching=!0}if(We.touches[0]){var is=m.projectIntoViewport(We.touches[0].clientX,We.touches[0].clientY);or[0]=is[0],or[1]=is[1]}if(We.touches[1]){var is=m.projectIntoViewport(We.touches[1].clientX,We.touches[1].clientY);or[2]=is[0],or[3]=is[1]}if(We.touches[2]){var is=m.projectIntoViewport(We.touches[2].clientX,We.touches[2].clientY);or[4]=is[0],or[5]=is[1]}}else if(We.touches[0]&&!m.touchData.didSelect){var kp=m.touchData.start,sM=m.touchData.last,qd;if(!m.hoverData.draggingEles&&!m.swipePanning&&(qd=m.findNearestElement(or[0],or[1],!0,!0)),On&&kp!=null&&We.preventDefault(),On&&kp!=null&&m.nodeIsDraggable(kp))if(qc){var _1=m.dragData.touchDragEles,eF=!m.dragData.didDrag;eF&&ne(_1,{inDragLayer:!0}),m.dragData.didDrag=!0;var qx={x:0,y:0};if(te(uo[0])&&te(uo[1])&&(qx.x+=uo[0],qx.y+=uo[1],eF)){m.redrawHint("eles",!0);var xp=m.touchData.dragDelta;xp&&te(xp[0])&&te(xp[1])&&(qx.x+=xp[0],qx.y+=xp[1])}m.hoverData.draggingEles=!0,_1.silentShift(qx).emit("position drag"),m.redrawHint("drag",!0),m.touchData.startPosition[0]==qa[0]&&m.touchData.startPosition[1]==qa[1]&&m.redrawHint("eles",!0),m.redraw()}else{var xp=m.touchData.dragDelta=m.touchData.dragDelta||[];xp.length===0?(xp.push(uo[0]),xp.push(uo[1])):(xp[0]+=uo[0],xp[1]+=uo[1])}if(k(kp||qd,["touchmove","tapdrag","vmousemove"],We,{x:or[0],y:or[1]}),(!kp||!kp.grabbed())&&qd!=sM&&(sM&&sM.emit({originalEvent:We,type:"tapdragout",position:{x:or[0],y:or[1]}}),qd&&qd.emit({originalEvent:We,type:"tapdragover",position:{x:or[0],y:or[1]}})),m.touchData.last=qd,On)for(var Vd=0;Vd0&&!m.hoverData.draggingEles&&!m.swipePanning&&m.data.bgActivePosistion!=null&&(m.data.bgActivePosistion=void 0,m.redrawHint("select",!0),m.redraw())}},!1);var ni;m.registerBinding(window,"touchcancel",ni=function(We){var On=m.touchData.start;m.touchData.capture=!1,On&&On.unactivate()});var Ti,ia,Ba,Li;if(m.registerBinding(window,"touchend",Ti=function(We){var On=m.touchData.start,Ir=m.touchData.capture;if(Ir)We.touches.length===0&&(m.touchData.capture=!1),We.preventDefault();else return;var ar=m.selection;m.swipePanning=!1,m.hoverData.draggingEles=!1;var or=m.cy,qa=or.zoom(),qr=m.touchData.now,is=m.touchData.earlier;if(We.touches[0]){var Uo=m.projectIntoViewport(We.touches[0].clientX,We.touches[0].clientY);qr[0]=Uo[0],qr[1]=Uo[1]}if(We.touches[1]){var Uo=m.projectIntoViewport(We.touches[1].clientX,We.touches[1].clientY);qr[2]=Uo[0],qr[3]=Uo[1]}if(We.touches[2]){var Uo=m.projectIntoViewport(We.touches[2].clientX,We.touches[2].clientY);qr[4]=Uo[0],qr[5]=Uo[1]}On&&On.unactivate();var qc;if(m.touchData.cxt){if(qc={originalEvent:We,type:"cxttapend",position:{x:qr[0],y:qr[1]}},On?On.emit(qc):or.emit(qc),!m.touchData.cxtDragged){var uo={originalEvent:We,type:"cxttap",position:{x:qr[0],y:qr[1]}};On?On.emit(uo):or.emit(uo)}m.touchData.start&&(m.touchData.start._private.grabbed=!1),m.touchData.cxt=!1,m.touchData.start=null,m.redraw();return}if(!We.touches[2]&&or.boxSelectionEnabled()&&m.touchData.selecting){m.touchData.selecting=!1;var Lc=or.collection(m.getAllInBox(ar[0],ar[1],ar[2],ar[3]));ar[0]=void 0,ar[1]=void 0,ar[2]=void 0,ar[3]=void 0,ar[4]=0,m.redrawHint("select",!0),or.emit({type:"boxend",originalEvent:We,position:{x:qr[0],y:qr[1]}});var Ra=function(S3){return S3.selectable()&&!S3.selected()};Lc.emit("box").stdFilter(Ra).select().emit("boxselect"),Lc.nonempty()&&m.redrawHint("eles",!0),m.redraw()}if(On!=null&&On.unactivate(),We.touches[2])m.data.bgActivePosistion=void 0,m.redrawHint("select",!0);else if(!We.touches[1]){if(!We.touches[0]){if(!We.touches[0]){m.data.bgActivePosistion=void 0,m.redrawHint("select",!0);var lo=m.dragData.touchDragEles;if(On!=null){var Sl=On._private.grabbed;ue(lo),m.redrawHint("drag",!0),m.redrawHint("eles",!0),Sl&&(On.emit("freeon"),lo.emit("free"),m.dragData.didDrag&&(On.emit("dragfreeon"),lo.emit("dragfree"))),k(On,["touchend","tapend","vmouseup","tapdragout"],We,{x:qr[0],y:qr[1]}),On.unactivate(),m.touchData.start=null}else{var Yf=m.findNearestElement(qr[0],qr[1],!0,!0);k(Yf,["touchend","tapend","vmouseup","tapdragout"],We,{x:qr[0],y:qr[1]})}var mp=m.touchData.startPosition[0]-qr[0],yp=mp*mp,Xf=m.touchData.startPosition[1]-qr[1],gg=Xf*Xf,fd=yp+gg,ov=fd*qa*qa;m.touchData.singleTouchMoved||(On||or.$(":selected").unselect(["tapunselect"]),k(On,["tap","vclick"],We,{x:qr[0],y:qr[1]}),ia=!1,We.timeStamp-Li<=or.multiClickDebounceTime()?(Ba&&clearTimeout(Ba),ia=!0,Li=null,k(On,["dbltap","vdblclick"],We,{x:qr[0],y:qr[1]})):(Ba=setTimeout(function(){ia||k(On,["onetap","voneclick"],We,{x:qr[0],y:qr[1]})},or.multiClickDebounceTime()),Li=We.timeStamp)),On!=null&&!m.dragData.didDrag&&On._private.selectable&&ov"u"){var wi=[],Ts=function(We){return{clientX:We.clientX,clientY:We.clientY,force:1,identifier:We.pointerId,pageX:We.pageX,pageY:We.pageY,radiusX:We.width/2,radiusY:We.height/2,screenX:We.screenX,screenY:We.screenY,target:We.target}},Yi=function(We){return{event:We,touch:Ts(We)}},Di=function(We){wi.push(Yi(We))},es=function(We){for(var On=0;On0)return kn[0]}return null},ne=Object.keys(U),ae=0;ae0?Z:XP(D,I,g,k,T,A,F)},checkPoint:function(g,k,T,A,D,I,F){var H=wx(A,D),C=2*H;if(tv(g,k,this.points,I,F,A,D-C,[0,-1],T)||tv(g,k,this.points,I,F,A-C,D,[0,-1],T))return!0;var G=A/2+2*T,U=D/2+2*T,Z=[I-G,F-U,I-G,F,I+G,F,I+G,F-U];return!!(Gd(g,k,Z)||m3(g,k,C,C,I+A/2-H,F+D/2-H,T)||m3(g,k,C,C,I-A/2+H,F+D/2-H,T))}}},iv.registerNodeShapes=function(){var m=this.nodeShapes={},g=this;this.generateEllipse(),this.generatePolygon("triangle",ud(3,0)),this.generateRoundPolygon("round-triangle",ud(3,0)),this.generatePolygon("rectangle",ud(4,0)),m.square=m.rectangle,this.generateRoundRectangle(),this.generateCutRectangle(),this.generateBarrel(),this.generateBottomRoundrectangle();{var k=[0,1,1,0,0,-1,-1,0];this.generatePolygon("diamond",k),this.generateRoundPolygon("round-diamond",k)}this.generatePolygon("pentagon",ud(5,0)),this.generateRoundPolygon("round-pentagon",ud(5,0)),this.generatePolygon("hexagon",ud(6,0)),this.generateRoundPolygon("round-hexagon",ud(6,0)),this.generatePolygon("heptagon",ud(7,0)),this.generateRoundPolygon("round-heptagon",ud(7,0)),this.generatePolygon("octagon",ud(8,0)),this.generateRoundPolygon("round-octagon",ud(8,0));var T=new Array(20);{var A=TL(5,0),D=TL(5,Math.PI/5),I=.5*(3-Math.sqrt(5));I*=1.57;for(var F=0;F=g.deqFastCost*Be)break}else if(C){if(Se>=g.deqCost*ne||Se>=g.deqAvgCost*Z)break}else if(Le>=g.deqNoDrawCost*QL)break;var Ke=g.deq(T,_e,ue);if(Ke.length>0)for(var qe=0;qe0&&(g.onDeqd(T,ae),!C&&g.shouldRedraw(T,ae,_e,ue)&&D())},F=g.priority||om;A.beforeRender(I,F(T))}}}},tee=function(){function m(g){var k=arguments.length>1&&arguments[1]!==void 0?arguments[1]:am;p(this,m),this.idsByKey=new R2,this.keyForId=new R2,this.cachesByLvl=new R2,this.lvls=[],this.getKey=g,this.doesEleInvalidateKey=k}return y(m,[{key:"getIdsFor",value:function(k){k==null&&yc("Can not get id list for null key");var T=this.idsByKey,A=this.idsByKey.get(k);return A||(A=new R5,T.set(k,A)),A}},{key:"addIdForKey",value:function(k,T){k!=null&&this.getIdsFor(k).add(T)}},{key:"deleteIdForKey",value:function(k,T){k!=null&&this.getIdsFor(k).delete(T)}},{key:"getNumberOfIdsForKey",value:function(k){return k==null?0:this.getIdsFor(k).size}},{key:"updateKeyMappingFor",value:function(k){var T=k.id(),A=this.keyForId.get(T),D=this.getKey(k);this.deleteIdForKey(A,T),this.addIdForKey(D,T),this.keyForId.set(T,D)}},{key:"deleteKeyMappingFor",value:function(k){var T=k.id(),A=this.keyForId.get(T);this.deleteIdForKey(A,T),this.keyForId.delete(T)}},{key:"keyHasChangedFor",value:function(k){var T=k.id(),A=this.keyForId.get(T),D=this.getKey(k);return A!==D}},{key:"isInvalid",value:function(k){return this.keyHasChangedFor(k)||this.doesEleInvalidateKey(k)}},{key:"getCachesAt",value:function(k){var T=this.cachesByLvl,A=this.lvls,D=T.get(k);return D||(D=new R2,T.set(k,D),A.push(k)),D}},{key:"getCache",value:function(k,T){return this.getCachesAt(T).get(k)}},{key:"get",value:function(k,T){var A=this.getKey(k),D=this.getCache(A,T);return D!=null&&this.updateKeyMappingFor(k),D}},{key:"getForCachedKey",value:function(k,T){var A=this.keyForId.get(k.id()),D=this.getCache(A,T);return D}},{key:"hasCache",value:function(k,T){return this.getCachesAt(T).has(k)}},{key:"has",value:function(k,T){var A=this.getKey(k);return this.hasCache(A,T)}},{key:"setCache",value:function(k,T,A){A.key=k,this.getCachesAt(T).set(k,A)}},{key:"set",value:function(k,T,A){var D=this.getKey(k);this.setCache(D,T,A),this.updateKeyMappingFor(k)}},{key:"deleteCache",value:function(k,T){this.getCachesAt(T).delete(k)}},{key:"delete",value:function(k,T){var A=this.getKey(k);this.deleteCache(A,T)}},{key:"invalidateKey",value:function(k){var T=this;this.lvls.forEach(function(A){return T.deleteCache(k,A)})}},{key:"invalidate",value:function(k){var T=k.id(),A=this.keyForId.get(T);this.deleteKeyMappingFor(k);var D=this.doesEleInvalidateKey(k);return D&&this.invalidateKey(A),D||this.getNumberOfIdsForKey(A)===0}}]),m}(),cT=25,uT=50,i6=-4,ZL=3,JL=7.99,nee=8,ree=1024,iee=1024,HR=1024,see=.2,aee=.8,oee=10,cee=.15,uee=.1,lee=.9,hee=.9,fee=100,dee=1,s6={dequeue:"dequeue",downscale:"downscale",highQuality:"highQuality"},gee=Vf({getKey:null,doesEleInvalidateKey:am,drawElement:null,getBoundingBox:null,getRotationPoint:null,getRotationOffset:null,isVisible:cd,allowEdgeTxrCaching:!0,allowParentTxrCaching:!0}),Fx=function(g,k){var T=this;T.renderer=g,T.onDequeues=[];var A=gee(k);Oe(T,A),T.lookup=new tee(A.getKey,A.doesEleInvalidateKey),T.setupDequeueing()},Oh=Fx.prototype;Oh.reasons=s6,Oh.getTextureQueue=function(m){var g=this;return g.eleImgCaches=g.eleImgCaches||{},g.eleImgCaches[m]=g.eleImgCaches[m]||[]},Oh.getRetiredTextureQueue=function(m){var g=this,k=g.eleImgCaches.retired=g.eleImgCaches.retired||{},T=k[m]=k[m]||[];return T},Oh.getElementQueue=function(){var m=this,g=m.eleCacheQueue=m.eleCacheQueue||new gx(function(k,T){return T.reqs-k.reqs});return g},Oh.getElementKeyToQueue=function(){var m=this,g=m.eleKeyToCacheQueue=m.eleKeyToCacheQueue||{};return g},Oh.getElement=function(m,g,k,T,A){var D=this,I=this.renderer,F=I.cy.zoom(),H=this.lookup;if(!g||g.w===0||g.h===0||isNaN(g.w)||isNaN(g.h)||!m.visible()||m.removed()||!D.allowEdgeTxrCaching&&m.isEdge()||!D.allowParentTxrCaching&&m.isParent())return null;if(T==null&&(T=Math.ceil(yL(F*k))),T=JL||T>ZL)return null;var C=Math.pow(2,T),G=g.h*C,U=g.w*C,Z=I.eleTextBiggerThanMin(m,C);if(!this.isVisible(m,Z))return null;var ne=H.get(m,T);if(ne&&ne.invalidated&&(ne.invalidated=!1,ne.texture.invalidatedWidth-=ne.width),ne)return ne;var ae;if(G<=cT?ae=cT:G<=uT?ae=uT:ae=Math.ceil(G/uT)*uT,G>HR||U>iee)return null;var ue=D.getTextureQueue(ae),_e=ue[ue.length-2],be=function(){return D.recycleTexture(ae,U)||D.addTexture(ae,U)};_e||(_e=ue[ue.length-1]),_e||(_e=be()),_e.width-_e.usedWidthT;ut--)$e=D.getElement(m,g,k,ut,s6.downscale);ot()}else return D.queueElement(m,qe.level-1),qe;else{var Je;if(!Le&&!Be&&!Ke)for(var Ct=T-1;Ct>=i6;Ct--){var lt=H.get(m,Ct);if(lt){Je=lt;break}}if(Se(Je))return D.queueElement(m,T),Je;_e.context.translate(_e.usedWidth,0),_e.context.scale(C,C),this.drawElement(_e.context,m,g,Z,!1),_e.context.scale(1/C,1/C),_e.context.translate(-_e.usedWidth,0)}return ne={x:_e.usedWidth,texture:_e,level:T,scale:C,width:U,height:G,scaledLabelShown:Z},_e.usedWidth+=Math.ceil(U+nee),_e.eleCaches.push(ne),H.set(m,T,ne),D.checkTextureFullness(_e),ne},Oh.invalidateElements=function(m){for(var g=0;g=see*m.width&&this.retireTexture(m)},Oh.checkTextureFullness=function(m){var g=this,k=g.getTextureQueue(m.height);m.usedWidth/m.width>aee&&m.fullnessChecks>=oee?cm(k,m):m.fullnessChecks++},Oh.retireTexture=function(m){var g=this,k=m.height,T=g.getTextureQueue(k),A=this.lookup;cm(T,m),m.retired=!0;for(var D=m.eleCaches,I=0;I=g)return I.retired=!1,I.usedWidth=0,I.invalidatedWidth=0,I.fullnessChecks=0,wL(I.eleCaches),I.context.setTransform(1,0,0,1,0,0),I.context.clearRect(0,0,I.width,I.height),cm(A,I),T.push(I),I}},Oh.queueElement=function(m,g){var k=this,T=k.getElementQueue(),A=k.getElementKeyToQueue(),D=this.getKey(m),I=A[D];if(I)I.level=Math.max(I.level,g),I.eles.merge(m),I.reqs++,T.updateItem(I);else{var F={eles:m.spawn().merge(m),level:g,reqs:1,key:D};T.push(F),A[D]=F}},Oh.dequeue=function(m){for(var g=this,k=g.getElementQueue(),T=g.getElementKeyToQueue(),A=[],D=g.lookup,I=0;I0;I++){var F=k.pop(),H=F.key,C=F.eles[0],G=D.hasCache(C,F.level);if(T[H]=null,G)continue;A.push(F);var U=g.getBoundingBox(C);g.getElement(C,U,m,F.level,s6.dequeue)}return A},Oh.removeFromQueue=function(m){var g=this,k=g.getElementQueue(),T=g.getElementKeyToQueue(),A=this.getKey(m),D=T[A];D!=null&&(D.eles.length===1?(D.reqs=dp,k.updateItem(D),k.pop(),T[A]=null):D.eles.unmerge(m))},Oh.onDequeue=function(m){this.onDequeues.push(m)},Oh.offDequeue=function(m){cm(this.onDequeues,m)},Oh.setupDequeueing=oT.setupDequeueing({deqRedrawThreshold:fee,deqCost:cee,deqAvgCost:uee,deqNoDrawCost:lee,deqFastCost:hee,deq:function(g,k,T){return g.dequeue(k,T)},onDeqd:function(g,k){for(var T=0;T=lT||k>jx)return null}T.validateLayersElesOrdering(k,m);var H=T.layersByLevel,C=Math.pow(2,k),G=H[k]=H[k]||[],U,Z=T.levelIsComplete(k,m),ne,ae=function(){var ot=function(un){if(T.validateLayersElesOrdering(un,m),T.levelIsComplete(un,m))return ne=H[un],!0},ut=function(un){if(!ne)for(var Rt=k+un;a6<=Rt&&Rt<=jx&&!ot(Rt);Rt+=un);};ut(1),ut(-1);for(var Je=G.length-1;Je>=0;Je--){var Ct=G[Je];Ct.invalid&&cm(G,Ct)}};if(!Z)ae();else return G;var ue=function(){if(!U){U=zd();for(var ot=0;otGge)return null;var Ct=T.makeLayer(U,k);if(ut!=null){var lt=G.indexOf(ut)+1;G.splice(lt,0,Ct)}else(ot.insert===void 0||ot.insert)&&G.unshift(Ct);return Ct};if(T.skipping&&!F)return null;for(var be=null,Se=m.length/pee,Le=!F,Be=0;Be=Se||!YP(be.bb,Ke.boundingBox()))&&(be=_e({insert:!0,after:be}),!be))return null;ne||Le?T.queueLayer(be,Ke):T.drawEleInLayer(be,Ke,k,g),be.eles.push(Ke),Re[k]=be}return ne||(Le?null:G)},x1.getEleLevelForLayerLevel=function(m,g){return m},x1.drawEleInLayer=function(m,g,k,T){var A=this,D=this.renderer,I=m.context,F=g.boundingBox();F.w===0||F.h===0||!g.visible()||(k=A.getEleLevelForLayerLevel(k,T),D.setImgSmoothing(I,!1),D.drawCachedElement(I,g,null,null,k,qge),D.setImgSmoothing(I,!0))},x1.levelIsComplete=function(m,g){var k=this,T=k.layersByLevel[m];if(!T||T.length===0)return!1;for(var A=0,D=0;D0||I.invalid)return!1;A+=I.eles.length}return A===g.length},x1.validateLayersElesOrdering=function(m,g){var k=this.layersByLevel[m];if(k)for(var T=0;T0){g=!0;break}}return g},x1.invalidateElements=function(m){var g=this;m.length!==0&&(g.lastInvalidationTime=pi(),!(m.length===0||!g.haveLayers())&&g.updateElementsInLayers(m,function(T,A,D){g.invalidateLayer(T)}))},x1.invalidateLayer=function(m){if(this.lastInvalidationTime=pi(),!m.invalid){var g=m.level,k=m.eles,T=this.layersByLevel[g];cm(T,m),m.elesQueue=[],m.invalid=!0,m.replacement&&(m.replacement.invalid=!0);for(var A=0;A3&&arguments[3]!==void 0?arguments[3]:!0,A=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,D=arguments.length>5&&arguments[5]!==void 0?arguments[5]:!0,I=this,F=g._private.rscratch;if(!(D&&!g.visible())&&!(F.badLine||F.allpts==null||isNaN(F.allpts[0]))){var H;k&&(H=k,m.translate(-H.x1,-H.y1));var C=D?g.pstyle("opacity").value:1,G=D?g.pstyle("line-opacity").value:1,U=g.pstyle("curve-style").value,Z=g.pstyle("line-style").value,ne=g.pstyle("width").pfValue,ae=g.pstyle("line-cap").value,ue=C*G,_e=C*G,be=function(){var Je=arguments.length>0&&arguments[0]!==void 0?arguments[0]:ue;U==="straight-triangle"?(I.eleStrokeStyle(m,g,Je),I.drawEdgeTrianglePath(g,m,F.allpts)):(m.lineWidth=ne,m.lineCap=ae,I.eleStrokeStyle(m,g,Je),I.drawEdgePath(g,m,F.allpts,Z),m.lineCap="butt")},Se=function(){A&&I.drawEdgeOverlay(m,g)},Le=function(){A&&I.drawEdgeUnderlay(m,g)},Be=function(){var Je=arguments.length>0&&arguments[0]!==void 0?arguments[0]:_e;I.drawArrowheads(m,g,Je)},Ke=function(){I.drawElementText(m,g,null,T)};m.lineJoin="round";var qe=g.pstyle("ghost").value==="yes";if(qe){var Re=g.pstyle("ghost-offset-x").pfValue,Ze=g.pstyle("ghost-offset-y").pfValue,$e=g.pstyle("ghost-opacity").value,ot=ue*$e;m.translate(Re,Ze),be(ot),Be(ot),m.translate(-Re,-Ze)}Le(),be(),Be(),Se(),Ke(),k&&m.translate(H.x1,H.y1)}};var kee=function(g){if(!["overlay","underlay"].includes(g))throw new Error("Invalid state");return function(k,T){if(T.visible()){var A=T.pstyle("".concat(g,"-opacity")).value;if(A!==0){var D=this,I=D.usePaths(),F=T._private.rscratch,H=T.pstyle("".concat(g,"-padding")).pfValue,C=2*H,G=T.pstyle("".concat(g,"-color")).value;k.lineWidth=C,F.edgeType==="self"&&!I?k.lineCap="butt":k.lineCap="round",D.colorStrokeStyle(k,G[0],G[1],G[2],A),D.drawEdgePath(T,k,F.allpts,"solid")}}}};av.drawEdgeOverlay=kee("overlay"),av.drawEdgeUnderlay=kee("underlay"),av.drawEdgePath=function(m,g,k,T){var A=m._private.rscratch,D=g,I,F=!1,H=this.usePaths(),C=m.pstyle("line-dash-pattern").pfValue,G=m.pstyle("line-dash-offset").pfValue;if(H){var U=k.join("$"),Z=A.pathCacheKey&&A.pathCacheKey===U;Z?(I=g=A.pathCache,F=!0):(I=g=new Path2D,A.pathCacheKey=U,A.pathCache=I)}if(D.setLineDash)switch(T){case"dotted":D.setLineDash([1,1]);break;case"dashed":D.setLineDash(C),D.lineDashOffset=G;break;case"solid":D.setLineDash([]);break}if(!F&&!A.badLine)switch(g.beginPath&&g.beginPath(),g.moveTo(k[0],k[1]),A.edgeType){case"bezier":case"self":case"compound":case"multibezier":for(var ne=2;ne+35&&arguments[5]!==void 0?arguments[5]:!0,I=this;if(T==null){if(D&&!I.eleTextBiggerThanMin(g))return}else if(T===!1)return;if(g.isNode()){var F=g.pstyle("label");if(!F||!F.value)return;var H=I.getLabelJustification(g);m.textAlign=H,m.textBaseline="bottom"}else{var C=g.element()._private.rscratch.badLine,G=g.pstyle("label"),U=g.pstyle("source-label"),Z=g.pstyle("target-label");if(C||(!G||!G.value)&&(!U||!U.value)&&(!Z||!Z.value))return;m.textAlign="center",m.textBaseline="bottom"}var ne=!k,ae;k&&(ae=k,m.translate(-ae.x1,-ae.y1)),A==null?(I.drawText(m,g,null,ne,D),g.isEdge()&&(I.drawText(m,g,"source",ne,D),I.drawText(m,g,"target",ne,D))):I.drawText(m,g,A,ne,D),k&&m.translate(ae.x1,ae.y1)},o6.getFontCache=function(m){var g;this.fontCaches=this.fontCaches||[];for(var k=0;k2&&arguments[2]!==void 0?arguments[2]:!0,T=g.pstyle("font-style").strValue,A=g.pstyle("font-size").pfValue+"px",D=g.pstyle("font-family").strValue,I=g.pstyle("font-weight").strValue,F=k?g.effectiveOpacity()*g.pstyle("text-opacity").value:1,H=g.pstyle("text-outline-opacity").value*F,C=g.pstyle("color").value,G=g.pstyle("text-outline-color").value;m.font=T+" "+I+" "+A+" "+D,m.lineJoin="round",this.colorFillStyle(m,C[0],C[1],C[2],F),this.colorStrokeStyle(m,G[0],G[1],G[2],H)};function Xge(m,g,k,T,A){var D=arguments.length>5&&arguments[5]!==void 0?arguments[5]:5;m.beginPath(),m.moveTo(g+D,k),m.lineTo(g+T-D,k),m.quadraticCurveTo(g+T,k,g+T,k+D),m.lineTo(g+T,k+A-D),m.quadraticCurveTo(g+T,k+A,g+T-D,k+A),m.lineTo(g+D,k+A),m.quadraticCurveTo(g,k+A,g,k+A-D),m.lineTo(g,k+D),m.quadraticCurveTo(g,k,g+D,k),m.closePath(),m.fill()}o6.getTextAngle=function(m,g){var k,T=m._private,A=T.rscratch,D=g?g+"-":"",I=m.pstyle(D+"text-rotation"),F=gp(A,"labelAngle",g);return I.strValue==="autorotate"?k=m.isEdge()?F:0:I.strValue==="none"?k=0:k=I.pfValue,k},o6.drawText=function(m,g,k){var T=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!0,A=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,D=g._private,I=D.rscratch,F=A?g.effectiveOpacity():1;if(!(A&&(F===0||g.pstyle("text-opacity").value===0))){k==="main"&&(k=null);var H=gp(I,"labelX",k),C=gp(I,"labelY",k),G,U,Z=this.getLabelText(g,k);if(Z!=null&&Z!==""&&!isNaN(H)&&!isNaN(C)){this.setupTextStyle(m,g,A);var ne=k?k+"-":"",ae=gp(I,"labelWidth",k),ue=gp(I,"labelHeight",k),_e=g.pstyle(ne+"text-margin-x").pfValue,be=g.pstyle(ne+"text-margin-y").pfValue,Se=g.isEdge(),Le=g.pstyle("text-halign").value,Be=g.pstyle("text-valign").value;Se&&(Le="center",Be="center"),H+=_e,C+=be;var Ke;switch(T?Ke=this.getTextAngle(g,k):Ke=0,Ke!==0&&(G=H,U=C,m.translate(G,U),m.rotate(Ke),H=0,C=0),Be){case"top":break;case"center":C+=ue/2;break;case"bottom":C+=ue;break}var qe=g.pstyle("text-background-opacity").value,Re=g.pstyle("text-border-opacity").value,Ze=g.pstyle("text-border-width").pfValue,$e=g.pstyle("text-background-padding").pfValue;if(qe>0||Ze>0&&Re>0){var ot=H-$e;switch(Le){case"left":ot-=ae;break;case"center":ot-=ae/2;break}var ut=C-ue-$e,Je=ae+2*$e,Ct=ue+2*$e;if(qe>0){var lt=m.fillStyle,un=g.pstyle("text-background-color").value;m.fillStyle="rgba("+un[0]+","+un[1]+","+un[2]+","+qe*F+")";var Rt=g.pstyle("text-background-shape").strValue;Rt.indexOf("round")===0?Xge(m,ot,ut,Je,Ct,2):m.fillRect(ot,ut,Je,Ct),m.fillStyle=lt}if(Ze>0&&Re>0){var $t=m.strokeStyle,bn=m.lineWidth,Cn=g.pstyle("text-border-color").value,Kn=g.pstyle("text-border-style").value;if(m.strokeStyle="rgba("+Cn[0]+","+Cn[1]+","+Cn[2]+","+Re*F+")",m.lineWidth=Ze,m.setLineDash)switch(Kn){case"dotted":m.setLineDash([1,1]);break;case"dashed":m.setLineDash([4,2]);break;case"double":m.lineWidth=Ze/4,m.setLineDash([]);break;case"solid":m.setLineDash([]);break}if(m.strokeRect(ot,ut,Je,Ct),Kn==="double"){var kn=Ze/2;m.strokeRect(ot+kn,ut+kn,Je-kn*2,Ct-kn*2)}m.setLineDash&&m.setLineDash([]),m.lineWidth=bn,m.strokeStyle=$t}}var Wn=2*g.pstyle("text-outline-width").pfValue;if(Wn>0&&(m.lineWidth=Wn),g.pstyle("text-wrap").value==="wrap"){var sr=gp(I,"labelWrapCachedLines",k),yr=gp(I,"labelLineHeight",k),hr=ae/2,nr=this.getLabelJustification(g);switch(nr==="auto"||(Le==="left"?nr==="left"?H+=-ae:nr==="center"&&(H+=-hr):Le==="center"?nr==="left"?H+=-hr:nr==="right"&&(H+=hr):Le==="right"&&(nr==="center"?H+=hr:nr==="right"&&(H+=ae))),Be){case"top":C-=(sr.length-1)*yr;break;case"center":case"bottom":C-=(sr.length-1)*yr;break}for(var fn=0;fn0&&m.strokeText(sr[fn],H,C),m.fillText(sr[fn],H,C),C+=yr}else Wn>0&&m.strokeText(Z,H,C),m.fillText(Z,H,C);Ke!==0&&(m.rotate(-Ke),m.translate(-G,-U))}}};var Hx={};Hx.drawNode=function(m,g,k){var T=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!0,A=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,D=arguments.length>5&&arguments[5]!==void 0?arguments[5]:!0,I=this,F,H,C=g._private,G=C.rscratch,U=g.position();if(!(!te(U.x)||!te(U.y))&&!(D&&!g.visible())){var Z=D?g.effectiveOpacity():1,ne=I.usePaths(),ae,ue=!1,_e=g.padding();F=g.width()+2*_e,H=g.height()+2*_e;var be;k&&(be=k,m.translate(-be.x1,-be.y1));for(var Se=g.pstyle("background-image"),Le=Se.value,Be=new Array(Le.length),Ke=new Array(Le.length),qe=0,Re=0;Re0&&arguments[0]!==void 0?arguments[0]:Ct;I.eleFillStyle(m,g,Di)},bn=function(){var Di=arguments.length>0&&arguments[0]!==void 0?arguments[0]:Rt;I.colorStrokeStyle(m,lt[0],lt[1],lt[2],Di)},Cn=g.pstyle("shape").strValue,Kn=g.pstyle("shape-polygon-points").pfValue;if(ne){m.translate(U.x,U.y);var kn=I.nodePathCache=I.nodePathCache||[],Wn=P5(Cn==="polygon"?Cn+","+Kn.join(","):Cn,""+H,""+F),sr=kn[Wn];sr!=null?(ae=sr,ue=!0,G.pathCache=ae):(ae=new Path2D,kn[Wn]=G.pathCache=ae)}var yr=function(){if(!ue){var Di=U;ne&&(Di={x:0,y:0}),I.nodeShapes[I.getNodeShape(g)].draw(ae||m,Di.x,Di.y,F,H)}ne?m.fill(ae):m.fill()},hr=function(){for(var Di=arguments.length>0&&arguments[0]!==void 0?arguments[0]:Z,es=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,eo=C.backgrounding,sa=0,Ks=0;Ks0&&arguments[0]!==void 0?arguments[0]:!1,es=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Z;I.hasPie(g)&&(I.drawPie(m,g,es),Di&&(ne||I.nodeShapes[I.getNodeShape(g)].draw(m,U.x,U.y,F,H)))},fn=function(){var Di=arguments.length>0&&arguments[0]!==void 0?arguments[0]:Z,es=(ut>0?ut:-ut)*Di,eo=ut>0?0:255;ut!==0&&(I.colorFillStyle(m,eo,eo,eo,es),ne?m.fill(ae):m.fill())},vr=function(){if(Je>0){if(m.lineWidth=Je,m.lineCap="butt",m.setLineDash)switch(un){case"dotted":m.setLineDash([1,1]);break;case"dashed":m.setLineDash([4,2]);break;case"solid":case"double":m.setLineDash([]);break}if(ne?m.stroke(ae):m.stroke(),un==="double"){m.lineWidth=Je/3;var Di=m.globalCompositeOperation;m.globalCompositeOperation="destination-out",ne?m.stroke(ae):m.stroke(),m.globalCompositeOperation=Di}m.setLineDash&&m.setLineDash([])}},gr=function(){A&&I.drawNodeOverlay(m,g,U,F,H)},ni=function(){A&&I.drawNodeUnderlay(m,g,U,F,H)},Ti=function(){I.drawElementText(m,g,null,T)},ia=g.pstyle("ghost").value==="yes";if(ia){var Ba=g.pstyle("ghost-offset-x").pfValue,Li=g.pstyle("ghost-offset-y").pfValue,wi=g.pstyle("ghost-opacity").value,Ts=wi*Z;m.translate(Ba,Li),$t(wi*Ct),yr(),hr(Ts,!0),bn(wi*Rt),vr(),nr(ut!==0||Je!==0),hr(Ts,!1),fn(Ts),m.translate(-Ba,-Li)}ne&&m.translate(-U.x,-U.y),ni(),ne&&m.translate(U.x,U.y),$t(),yr(),hr(Z,!0),bn(),vr(),nr(ut!==0||Je!==0),hr(Z,!1),fn(),ne&&m.translate(-U.x,-U.y),Ti(),gr(),k&&m.translate(be.x1,be.y1)}};var xee=function(g){if(!["overlay","underlay"].includes(g))throw new Error("Invalid state");return function(k,T,A,D,I){var F=this;if(T.visible()){var H=T.pstyle("".concat(g,"-padding")).pfValue,C=T.pstyle("".concat(g,"-opacity")).value,G=T.pstyle("".concat(g,"-color")).value,U=T.pstyle("".concat(g,"-shape")).value;if(C>0){if(A=A||T.position(),D==null||I==null){var Z=T.padding();D=T.width()+2*Z,I=T.height()+2*Z}F.colorFillStyle(k,G[0],G[1],G[2],C),F.nodeShapes[U].draw(k,A.x,A.y,D+H*2,I+H*2),k.fill()}}}};Hx.drawNodeOverlay=xee("overlay"),Hx.drawNodeUnderlay=xee("underlay"),Hx.hasPie=function(m){return m=m[0],m._private.hasPie},Hx.drawPie=function(m,g,k,T){g=g[0],T=T||g.position();var A=g.cy().style(),D=g.pstyle("pie-size"),I=T.x,F=T.y,H=g.width(),C=g.height(),G=Math.min(H,C)/2,U=0,Z=this.usePaths();Z&&(I=0,F=0),D.units==="%"?G=G*D.pfValue:D.pfValue!==void 0&&(G=D.pfValue/2);for(var ne=1;ne<=A.pieBackgroundN;ne++){var ae=g.pstyle("pie-"+ne+"-background-size").value,ue=g.pstyle("pie-"+ne+"-background-color").value,_e=g.pstyle("pie-"+ne+"-background-opacity").value*k,be=ae/100;be+U>1&&(be=1-U);var Se=1.5*Math.PI+2*Math.PI*U,Le=2*Math.PI*be,Be=Se+Le;ae===0||U>=1||U+be>1||(m.beginPath(),m.moveTo(I,F),m.arc(I,F,G,Se,Be),m.closePath(),this.colorFillStyle(m,ue[0],ue[1],ue[2],_e),m.fill(),U+=be)}};var fg={},Qge=100;fg.getPixelRatio=function(){var m=this.data.contexts[0];if(this.forcedPixelRatio!=null)return this.forcedPixelRatio;var g=m.backingStorePixelRatio||m.webkitBackingStorePixelRatio||m.mozBackingStorePixelRatio||m.msBackingStorePixelRatio||m.oBackingStorePixelRatio||m.backingStorePixelRatio||1;return(window.devicePixelRatio||1)/g},fg.paintCache=function(m){for(var g=this.paintCaches=this.paintCaches||[],k=!0,T,A=0;AI.minMbLowQualFrames&&(I.motionBlurPxRatio=I.mbPxRBlurry)),I.clearingMotionBlur&&(I.motionBlurPxRatio=1),I.textureDrawLastFrame&&!U&&(G[I.NODE]=!0,G[I.SELECT_BOX]=!0);var Se=H.style(),Le=H.zoom(),Be=A!==void 0?A:Le,Ke=H.pan(),qe={x:Ke.x,y:Ke.y},Re={zoom:Le,pan:{x:Ke.x,y:Ke.y}},Ze=I.prevViewport,$e=Ze===void 0||Re.zoom!==Ze.zoom||Re.pan.x!==Ze.pan.x||Re.pan.y!==Ze.pan.y;!$e&&!(ue&&!ae)&&(I.motionBlurPxRatio=1),D&&(qe=D),Be*=F,qe.x*=F,qe.y*=F;var ot=I.getCachedZSortedEles();function ut(Li,wi,Ts,Yi,Di){var es=Li.globalCompositeOperation;Li.globalCompositeOperation="destination-out",I.colorFillStyle(Li,255,255,255,I.motionBlurTransparency),Li.fillRect(wi,Ts,Yi,Di),Li.globalCompositeOperation=es}function Je(Li,wi){var Ts,Yi,Di,es;!I.clearingMotionBlur&&(Li===C.bufferContexts[I.MOTIONBLUR_BUFFER_NODE]||Li===C.bufferContexts[I.MOTIONBLUR_BUFFER_DRAG])?(Ts={x:Ke.x*ne,y:Ke.y*ne},Yi=Le*ne,Di=I.canvasWidth*ne,es=I.canvasHeight*ne):(Ts=qe,Yi=Be,Di=I.canvasWidth,es=I.canvasHeight),Li.setTransform(1,0,0,1,0,0),wi==="motionBlur"?ut(Li,0,0,Di,es):!g&&(wi===void 0||wi)&&Li.clearRect(0,0,Di,es),k||(Li.translate(Ts.x,Ts.y),Li.scale(Yi,Yi)),D&&Li.translate(D.x,D.y),A&&Li.scale(A,A)}if(U||(I.textureDrawLastFrame=!1),U){if(I.textureDrawLastFrame=!0,!I.textureCache){I.textureCache={},I.textureCache.bb=H.mutableElements().boundingBox(),I.textureCache.texture=I.data.bufferCanvases[I.TEXTURE_BUFFER];var Ct=I.data.bufferContexts[I.TEXTURE_BUFFER];Ct.setTransform(1,0,0,1,0,0),Ct.clearRect(0,0,I.canvasWidth*I.textureMult,I.canvasHeight*I.textureMult),I.render({forcedContext:Ct,drawOnlyNodeLayer:!0,forcedPxRatio:F*I.textureMult});var Re=I.textureCache.viewport={zoom:H.zoom(),pan:H.pan(),width:I.canvasWidth,height:I.canvasHeight};Re.mpan={x:(0-Re.pan.x)/Re.zoom,y:(0-Re.pan.y)/Re.zoom}}G[I.DRAG]=!1,G[I.NODE]=!1;var lt=C.contexts[I.NODE],un=I.textureCache.texture,Re=I.textureCache.viewport;lt.setTransform(1,0,0,1,0,0),Z?ut(lt,0,0,Re.width,Re.height):lt.clearRect(0,0,Re.width,Re.height);var Rt=Se.core("outside-texture-bg-color").value,$t=Se.core("outside-texture-bg-opacity").value;I.colorFillStyle(lt,Rt[0],Rt[1],Rt[2],$t),lt.fillRect(0,0,Re.width,Re.height);var Le=H.zoom();Je(lt,!1),lt.clearRect(Re.mpan.x,Re.mpan.y,Re.width/Re.zoom/F,Re.height/Re.zoom/F),lt.drawImage(un,Re.mpan.x,Re.mpan.y,Re.width/Re.zoom/F,Re.height/Re.zoom/F)}else I.textureOnViewport&&!g&&(I.textureCache=null);var bn=H.extent(),Cn=I.pinching||I.hoverData.dragging||I.swipePanning||I.data.wheelZooming||I.hoverData.draggingEles||I.cy.animated(),Kn=I.hideEdgesOnViewport&&Cn,kn=[];if(kn[I.NODE]=!G[I.NODE]&&Z&&!I.clearedForMotionBlur[I.NODE]||I.clearingMotionBlur,kn[I.NODE]&&(I.clearedForMotionBlur[I.NODE]=!0),kn[I.DRAG]=!G[I.DRAG]&&Z&&!I.clearedForMotionBlur[I.DRAG]||I.clearingMotionBlur,kn[I.DRAG]&&(I.clearedForMotionBlur[I.DRAG]=!0),G[I.NODE]||k||T||kn[I.NODE]){var Wn=Z&&!kn[I.NODE]&&ne!==1,lt=g||(Wn?I.data.bufferContexts[I.MOTIONBLUR_BUFFER_NODE]:C.contexts[I.NODE]),sr=Z&&!Wn?"motionBlur":void 0;Je(lt,sr),Kn?I.drawCachedNodes(lt,ot.nondrag,F,bn):I.drawLayeredElements(lt,ot.nondrag,F,bn),I.debug&&I.drawDebugPoints(lt,ot.nondrag),!k&&!Z&&(G[I.NODE]=!1)}if(!T&&(G[I.DRAG]||k||kn[I.DRAG])){var Wn=Z&&!kn[I.DRAG]&&ne!==1,lt=g||(Wn?I.data.bufferContexts[I.MOTIONBLUR_BUFFER_DRAG]:C.contexts[I.DRAG]);Je(lt,Z&&!Wn?"motionBlur":void 0),Kn?I.drawCachedNodes(lt,ot.drag,F,bn):I.drawCachedElements(lt,ot.drag,F,bn),I.debug&&I.drawDebugPoints(lt,ot.drag),!k&&!Z&&(G[I.DRAG]=!1)}if(I.showFps||!T&&G[I.SELECT_BOX]&&!k){var lt=g||C.contexts[I.SELECT_BOX];if(Je(lt),I.selection[4]==1&&(I.hoverData.selecting||I.touchData.selecting)){var Le=I.cy.zoom(),yr=Se.core("selection-box-border-width").value/Le;lt.lineWidth=yr,lt.fillStyle="rgba("+Se.core("selection-box-color").value[0]+","+Se.core("selection-box-color").value[1]+","+Se.core("selection-box-color").value[2]+","+Se.core("selection-box-opacity").value+")",lt.fillRect(I.selection[0],I.selection[1],I.selection[2]-I.selection[0],I.selection[3]-I.selection[1]),yr>0&&(lt.strokeStyle="rgba("+Se.core("selection-box-border-color").value[0]+","+Se.core("selection-box-border-color").value[1]+","+Se.core("selection-box-border-color").value[2]+","+Se.core("selection-box-opacity").value+")",lt.strokeRect(I.selection[0],I.selection[1],I.selection[2]-I.selection[0],I.selection[3]-I.selection[1]))}if(C.bgActivePosistion&&!I.hoverData.selecting){var Le=I.cy.zoom(),hr=C.bgActivePosistion;lt.fillStyle="rgba("+Se.core("active-bg-color").value[0]+","+Se.core("active-bg-color").value[1]+","+Se.core("active-bg-color").value[2]+","+Se.core("active-bg-opacity").value+")",lt.beginPath(),lt.arc(hr.x,hr.y,Se.core("active-bg-size").pfValue/Le,0,2*Math.PI),lt.fill()}var nr=I.lastRedrawTime;if(I.showFps&&nr){nr=Math.round(nr);var fn=Math.round(1e3/nr);lt.setTransform(1,0,0,1,0,0),lt.fillStyle="rgba(255, 0, 0, 0.75)",lt.strokeStyle="rgba(255, 0, 0, 0.75)",lt.lineWidth=1,lt.fillText("1 frame = "+nr+" ms = "+fn+" fps",0,20);var vr=60;lt.strokeRect(0,30,250,20),lt.fillRect(0,30,250*Math.min(fn/vr,1),20)}k||(G[I.SELECT_BOX]=!1)}if(Z&&ne!==1){var gr=C.contexts[I.NODE],ni=I.data.bufferCanvases[I.MOTIONBLUR_BUFFER_NODE],Ti=C.contexts[I.DRAG],ia=I.data.bufferCanvases[I.MOTIONBLUR_BUFFER_DRAG],Ba=function(wi,Ts,Yi){wi.setTransform(1,0,0,1,0,0),Yi||!be?wi.clearRect(0,0,I.canvasWidth,I.canvasHeight):ut(wi,0,0,I.canvasWidth,I.canvasHeight);var Di=ne;wi.drawImage(Ts,0,0,I.canvasWidth*Di,I.canvasHeight*Di,0,0,I.canvasWidth,I.canvasHeight)};(G[I.NODE]||kn[I.NODE])&&(Ba(gr,ni,kn[I.NODE]),G[I.NODE]=!1),(G[I.DRAG]||kn[I.DRAG])&&(Ba(Ti,ia,kn[I.DRAG]),G[I.DRAG]=!1)}I.prevViewport=Re,I.clearingMotionBlur&&(I.clearingMotionBlur=!1,I.motionBlurCleared=!0,I.motionBlur=!0),Z&&(I.motionBlurTimeout=setTimeout(function(){I.motionBlurTimeout=null,I.clearedForMotionBlur[I.NODE]=!1,I.clearedForMotionBlur[I.DRAG]=!1,I.motionBlur=!1,I.clearingMotionBlur=!U,I.mbFrames=0,G[I.NODE]=!0,G[I.DRAG]=!0,I.redraw()},Qge)),g||H.emit("render")};var _3={};_3.drawPolygonPath=function(m,g,k,T,A,D){var I=T/2,F=A/2;m.beginPath&&m.beginPath(),m.moveTo(g+I*D[0],k+F*D[1]);for(var H=1;H0&&I>0){ne.clearRect(0,0,D,I),ne.globalCompositeOperation="source-over";var ae=this.getCachedZSortedEles();if(m.full)ne.translate(-T.x1*C,-T.y1*C),ne.scale(C,C),this.drawElements(ne,ae),ne.scale(1/C,1/C),ne.translate(T.x1*C,T.y1*C);else{var ue=g.pan(),_e={x:ue.x*C,y:ue.y*C};C*=g.zoom(),ne.translate(_e.x,_e.y),ne.scale(C,C),this.drawElements(ne,ae),ne.scale(1/C,1/C),ne.translate(-_e.x,-_e.y)}m.bg&&(ne.globalCompositeOperation="destination-over",ne.fillStyle=m.bg,ne.rect(0,0,D,I),ne.fill())}return Z};function Zge(m,g){for(var k=atob(m),T=new ArrayBuffer(k.length),A=new Uint8Array(T),D=0;D"u"?"undefined":f(OffscreenCanvas))!=="undefined"?k=new OffscreenCanvas(m,g):(k=document.createElement("canvas"),k.width=m,k.height=g),k},[T0,sv,av,fT,o6,Hx,fg,_3,dT,Aee].forEach(function(m){Oe(Ac,m)});var c6=[{name:"null",impl:DR},{name:"base",impl:XL},{name:"canvas",impl:Jge}],dg=[{type:"layout",extensions:ZJ},{type:"renderer",extensions:c6}],vm={},nM={};function E1(m,g,k){var T=k,A=function(Ze){Vo("Can not register `"+g+"` for `"+m+"` since `"+Ze+"` already exists in the prototype and can not be overridden")};if(m==="core"){if(Ox.prototype[g])return A(g);Ox.prototype[g]=k}else if(m==="collection"){if(Wf.prototype[g])return A(g);Wf.prototype[g]=k}else if(m==="layout"){for(var D=function(Ze){this.options=Ze,k.call(this,Ze),de(this._private)||(this._private={}),this._private.cy=Ze.cy,this._private.listeners=[],this.createEmitter()},I=D.prototype=Object.create(k.prototype),F=[],H=0;HV&&(this.rect.x-=(this.labelWidth-V)/2,this.setWidth(this.labelWidth)),this.labelHeight>Q&&(this.labelPos=="center"?this.rect.y-=(this.labelHeight-Q)/2:this.labelPos=="top"&&(this.rect.y-=this.labelHeight-Q),this.setHeight(this.labelHeight))}}},R.prototype.getInclusionTreeDepth=function(){if(this.inclusionTreeDepth==b.MAX_VALUE)throw"assert failed";return this.inclusionTreeDepth},R.prototype.transform=function($){var V=this.rect.x;V>S.WORLD_BOUNDARY?V=S.WORLD_BOUNDARY:V<-S.WORLD_BOUNDARY&&(V=-S.WORLD_BOUNDARY);var Q=this.rect.y;Q>S.WORLD_BOUNDARY?Q=S.WORLD_BOUNDARY:Q<-S.WORLD_BOUNDARY&&(Q=-S.WORLD_BOUNDARY);var oe=new B(V,Q),ce=$.inverseTransformPoint(oe);this.setLocation(ce.x,ce.y)},R.prototype.getLeft=function(){return this.rect.x},R.prototype.getRight=function(){return this.rect.x+this.rect.width},R.prototype.getTop=function(){return this.rect.y},R.prototype.getBottom=function(){return this.rect.y+this.rect.height},R.prototype.getParent=function(){return this.owner==null?null:this.owner.getParent()},f.exports=R},function(f,p,w){function y(b,E){b==null&&E==null?(this.x=0,this.y=0):(this.x=b,this.y=E)}y.prototype.getX=function(){return this.x},y.prototype.getY=function(){return this.y},y.prototype.setX=function(b){this.x=b},y.prototype.setY=function(b){this.y=b},y.prototype.getDifference=function(b){return new DimensionD(this.x-b.x,this.y-b.y)},y.prototype.getCopy=function(){return new y(this.x,this.y)},y.prototype.translate=function(b){return this.x+=b.width,this.y+=b.height,this},f.exports=y},function(f,p,w){var y=w(2),b=w(10),E=w(0),S=w(6),N=w(3),B=w(1),R=w(13),j=w(12),$=w(11);function V(oe,ce,se){y.call(this,se),this.estimatedSize=b.MIN_VALUE,this.margin=E.DEFAULT_GRAPH_MARGIN,this.edges=[],this.nodes=[],this.isConnected=!1,this.parent=oe,ce!=null&&ce instanceof S?this.graphManager=ce:ce!=null&&ce instanceof Layout&&(this.graphManager=ce.graphManager)}V.prototype=Object.create(y.prototype);for(var Q in y)V[Q]=y[Q];V.prototype.getNodes=function(){return this.nodes},V.prototype.getEdges=function(){return this.edges},V.prototype.getGraphManager=function(){return this.graphManager},V.prototype.getParent=function(){return this.parent},V.prototype.getLeft=function(){return this.left},V.prototype.getRight=function(){return this.right},V.prototype.getTop=function(){return this.top},V.prototype.getBottom=function(){return this.bottom},V.prototype.isConnected=function(){return this.isConnected},V.prototype.add=function(oe,ce,se){if(ce==null&&se==null){var ge=oe;if(this.graphManager==null)throw"Graph has no graph mgr!";if(this.getNodes().indexOf(ge)>-1)throw"Node already in graph!";return ge.owner=this,this.getNodes().push(ge),ge}else{var ye=oe;if(!(this.getNodes().indexOf(ce)>-1&&this.getNodes().indexOf(se)>-1))throw"Source or target not in graph!";if(!(ce.owner==se.owner&&ce.owner==this))throw"Both owners must be this graph!";return ce.owner!=se.owner?null:(ye.source=ce,ye.target=se,ye.isInterGraph=!1,this.getEdges().push(ye),ce.edges.push(ye),se!=ce&&se.edges.push(ye),ye)}},V.prototype.remove=function(oe){var ce=oe;if(oe instanceof N){if(ce==null)throw"Node is null!";if(!(ce.owner!=null&&ce.owner==this))throw"Owner graph is invalid!";if(this.graphManager==null)throw"Owner graph manager is invalid!";for(var se=ce.edges.slice(),ge,ye=se.length,ke=0;ke-1&&ve>-1))throw"Source and/or target doesn't know this edge!";ge.source.edges.splice(de,1),ge.target!=ge.source&&ge.target.edges.splice(ve,1);var Ae=ge.source.owner.getEdges().indexOf(ge);if(Ae==-1)throw"Not in owner's edge list!";ge.source.owner.getEdges().splice(Ae,1)}},V.prototype.updateLeftTop=function(){for(var oe=b.MAX_VALUE,ce=b.MAX_VALUE,se,ge,ye,ke=this.getNodes(),Ae=ke.length,de=0;dese&&(oe=se),ce>ge&&(ce=ge)}return oe==b.MAX_VALUE?null:(ke[0].getParent().paddingLeft!=null?ye=ke[0].getParent().paddingLeft:ye=this.margin,this.left=ce-ye,this.top=oe-ye,new j(this.left,this.top))},V.prototype.updateBounds=function(oe){for(var ce=b.MAX_VALUE,se=-b.MAX_VALUE,ge=b.MAX_VALUE,ye=-b.MAX_VALUE,ke,Ae,de,ve,te,xe=this.nodes,De=xe.length,he=0;heke&&(ce=ke),sede&&(ge=de),yeke&&(ce=ke),sede&&(ge=de),ye=this.nodes.length){var De=0;se.forEach(function(he){he.owner==oe&&De++}),De==this.nodes.length&&(this.isConnected=!0)}},f.exports=V},function(f,p,w){var y,b=w(1);function E(S){y=w(5),this.layout=S,this.graphs=[],this.edges=[]}E.prototype.addRoot=function(){var S=this.layout.newGraph(),N=this.layout.newNode(null),B=this.add(S,N);return this.setRootGraph(B),this.rootGraph},E.prototype.add=function(S,N,B,R,j){if(B==null&&R==null&&j==null){if(S==null)throw"Graph is null!";if(N==null)throw"Parent node is null!";if(this.graphs.indexOf(S)>-1)throw"Graph already in this graph mgr!";if(this.graphs.push(S),S.parent!=null)throw"Already has a parent!";if(N.child!=null)throw"Already has a child!";return S.parent=N,N.child=S,S}else{j=B,R=N,B=S;var $=R.getOwner(),V=j.getOwner();if(!($!=null&&$.getGraphManager()==this))throw"Source not in this graph mgr!";if(!(V!=null&&V.getGraphManager()==this))throw"Target not in this graph mgr!";if($==V)return B.isInterGraph=!1,$.add(B,R,j);if(B.isInterGraph=!0,B.source=R,B.target=j,this.edges.indexOf(B)>-1)throw"Edge already in inter-graph edge list!";if(this.edges.push(B),!(B.source!=null&&B.target!=null))throw"Edge source and/or target is null!";if(!(B.source.edges.indexOf(B)==-1&&B.target.edges.indexOf(B)==-1))throw"Edge already in source and/or target incidency list!";return B.source.edges.push(B),B.target.edges.push(B),B}},E.prototype.remove=function(S){if(S instanceof y){var N=S;if(N.getGraphManager()!=this)throw"Graph not in this graph mgr";if(!(N==this.rootGraph||N.parent!=null&&N.parent.graphManager==this))throw"Invalid parent node!";var B=[];B=B.concat(N.getEdges());for(var R,j=B.length,$=0;$=S.getRight()?N[0]+=Math.min(S.getX()-E.getX(),E.getRight()-S.getRight()):S.getX()<=E.getX()&&S.getRight()>=E.getRight()&&(N[0]+=Math.min(E.getX()-S.getX(),S.getRight()-E.getRight())),E.getY()<=S.getY()&&E.getBottom()>=S.getBottom()?N[1]+=Math.min(S.getY()-E.getY(),E.getBottom()-S.getBottom()):S.getY()<=E.getY()&&S.getBottom()>=E.getBottom()&&(N[1]+=Math.min(E.getY()-S.getY(),S.getBottom()-E.getBottom()));var j=Math.abs((S.getCenterY()-E.getCenterY())/(S.getCenterX()-E.getCenterX()));S.getCenterY()===E.getCenterY()&&S.getCenterX()===E.getCenterX()&&(j=1);var $=j*N[0],V=N[1]/j;N[0]$)return N[0]=B,N[1]=Q,N[2]=j,N[3]=xe,!1;if(R<$)return N[0]=B,N[1]=se,N[2]=j,N[3]=de,!1}else if(R===$){if(B>j)return N[0]=V,N[1]=R,N[2]=ve,N[3]=$,!1;if(Bj?(N[0]=ce,N[1]=se,ee=!0):(N[0]=oe,N[1]=Q,ee=!0):me===pe&&(B>j?(N[0]=V,N[1]=Q,ee=!0):(N[0]=ge,N[1]=se,ee=!0)),-gt===pe?j>B?(N[2]=te,N[3]=xe,rt=!0):(N[2]=ve,N[3]=de,rt=!0):gt===pe&&(j>B?(N[2]=Ae,N[3]=de,rt=!0):(N[2]=De,N[3]=xe,rt=!0)),ee&&rt)return!1;if(B>j?R>$?(Et=this.getCardinalDirection(me,pe,4),wt=this.getCardinalDirection(gt,pe,2)):(Et=this.getCardinalDirection(-me,pe,3),wt=this.getCardinalDirection(-gt,pe,1)):R>$?(Et=this.getCardinalDirection(-me,pe,1),wt=this.getCardinalDirection(-gt,pe,3)):(Et=this.getCardinalDirection(me,pe,2),wt=this.getCardinalDirection(gt,pe,4)),!ee)switch(Et){case 1:At=Q,jt=B+-ke/pe,N[0]=jt,N[1]=At;break;case 2:jt=ge,At=R+ye*pe,N[0]=jt,N[1]=At;break;case 3:At=se,jt=B+ke/pe,N[0]=jt,N[1]=At;break;case 4:jt=ce,At=R+-ye*pe,N[0]=jt,N[1]=At;break}if(!rt)switch(wt){case 1:cn=de,Bt=j+-Ie/pe,N[2]=Bt,N[3]=cn;break;case 2:Bt=De,cn=$+he*pe,N[2]=Bt,N[3]=cn;break;case 3:cn=xe,Bt=j+Ie/pe,N[2]=Bt,N[3]=cn;break;case 4:Bt=te,cn=$+-he*pe,N[2]=Bt,N[3]=cn;break}}return!1},b.getCardinalDirection=function(E,S,N){return E>S?N:1+N%4},b.getIntersection=function(E,S,N,B){if(B==null)return this.getIntersection2(E,S,N);var R=E.x,j=E.y,$=S.x,V=S.y,Q=N.x,oe=N.y,ce=B.x,se=B.y,ge=void 0,ye=void 0,ke=void 0,Ae=void 0,de=void 0,ve=void 0,te=void 0,xe=void 0,De=void 0;return ke=V-j,de=R-$,te=$*j-R*V,Ae=se-oe,ve=Q-ce,xe=ce*oe-Q*se,De=ke*ve-Ae*de,De===0?null:(ge=(de*xe-ve*te)/De,ye=(Ae*te-ke*xe)/De,new y(ge,ye))},b.angleOfVector=function(E,S,N,B){var R=void 0;return E!==N?(R=Math.atan((B-S)/(N-E)),N0?1:b<0?-1:0},y.floor=function(b){return b<0?Math.ceil(b):Math.floor(b)},y.ceil=function(b){return b<0?Math.floor(b):Math.ceil(b)},f.exports=y},function(f,p,w){function y(){}y.MAX_VALUE=2147483647,y.MIN_VALUE=-2147483648,f.exports=y},function(f,p,w){var y=function(){function R(j,$){for(var V=0;V<$.length;V++){var Q=$[V];Q.enumerable=Q.enumerable||!1,Q.configurable=!0,"value"in Q&&(Q.writable=!0),Object.defineProperty(j,Q.key,Q)}}return function(j,$,V){return $&&R(j.prototype,$),V&&R(j,V),j}}();function b(R,j){if(!(R instanceof j))throw new TypeError("Cannot call a class as a function")}var E=function(j){return{value:j,next:null,prev:null}},S=function(j,$,V,Q){return j!==null?j.next=$:Q.head=$,V!==null?V.prev=$:Q.tail=$,$.prev=j,$.next=V,Q.length++,$},N=function(j,$){var V=j.prev,Q=j.next;return V!==null?V.next=Q:$.head=Q,Q!==null?Q.prev=V:$.tail=V,j.prev=j.next=null,$.length--,j},B=function(){function R(j){var $=this;b(this,R),this.length=0,this.head=null,this.tail=null,j!=null&&j.forEach(function(V){return $.push(V)})}return y(R,[{key:"size",value:function(){return this.length}},{key:"insertBefore",value:function($,V){return S(V.prev,E($),V,this)}},{key:"insertAfter",value:function($,V){return S(V,E($),V.next,this)}},{key:"insertNodeBefore",value:function($,V){return S(V.prev,$,V,this)}},{key:"insertNodeAfter",value:function($,V){return S(V,$,V.next,this)}},{key:"push",value:function($){return S(this.tail,E($),null,this)}},{key:"unshift",value:function($){return S(null,E($),this.head,this)}},{key:"remove",value:function($){return N($,this)}},{key:"pop",value:function(){return N(this.tail,this).value}},{key:"popNode",value:function(){return N(this.tail,this)}},{key:"shift",value:function(){return N(this.head,this).value}},{key:"shiftNode",value:function(){return N(this.head,this)}},{key:"get_object_at",value:function($){if($<=this.length()){for(var V=1,Q=this.head;V<$;)Q=Q.next,V++;return Q.value}}},{key:"set_object_at",value:function($,V){if($<=this.length()){for(var Q=1,oe=this.head;Q<$;)oe=oe.next,Q++;oe.value=V}}}]),R}();f.exports=B},function(f,p,w){function y(b,E,S){this.x=null,this.y=null,b==null&&E==null&&S==null?(this.x=0,this.y=0):typeof b=="number"&&typeof E=="number"&&S==null?(this.x=b,this.y=E):b.constructor.name=="Point"&&E==null&&S==null&&(S=b,this.x=S.x,this.y=S.y)}y.prototype.getX=function(){return this.x},y.prototype.getY=function(){return this.y},y.prototype.getLocation=function(){return new y(this.x,this.y)},y.prototype.setLocation=function(b,E,S){b.constructor.name=="Point"&&E==null&&S==null?(S=b,this.setLocation(S.x,S.y)):typeof b=="number"&&typeof E=="number"&&S==null&&(parseInt(b)==b&&parseInt(E)==E?this.move(b,E):(this.x=Math.floor(b+.5),this.y=Math.floor(E+.5)))},y.prototype.move=function(b,E){this.x=b,this.y=E},y.prototype.translate=function(b,E){this.x+=b,this.y+=E},y.prototype.equals=function(b){if(b.constructor.name=="Point"){var E=b;return this.x==E.x&&this.y==E.y}return this==b},y.prototype.toString=function(){return new y().constructor.name+"[x="+this.x+",y="+this.y+"]"},f.exports=y},function(f,p,w){function y(b,E,S,N){this.x=0,this.y=0,this.width=0,this.height=0,b!=null&&E!=null&&S!=null&&N!=null&&(this.x=b,this.y=E,this.width=S,this.height=N)}y.prototype.getX=function(){return this.x},y.prototype.setX=function(b){this.x=b},y.prototype.getY=function(){return this.y},y.prototype.setY=function(b){this.y=b},y.prototype.getWidth=function(){return this.width},y.prototype.setWidth=function(b){this.width=b},y.prototype.getHeight=function(){return this.height},y.prototype.setHeight=function(b){this.height=b},y.prototype.getRight=function(){return this.x+this.width},y.prototype.getBottom=function(){return this.y+this.height},y.prototype.intersects=function(b){return!(this.getRight()"u"?"undefined":y(E);return E==null||S!="object"&&S!="function"},f.exports=b},function(f,p,w){function y(Q){if(Array.isArray(Q)){for(var oe=0,ce=Array(Q.length);oe0&&oe;){for(ke.push(de[0]);ke.length>0&&oe;){var ve=ke[0];ke.splice(0,1),ye.add(ve);for(var te=ve.getEdges(),ge=0;ge-1&&de.splice(Ie,1)}ye=new Set,Ae=new Map}}return Q},V.prototype.createDummyNodesForBendpoints=function(Q){for(var oe=[],ce=Q.source,se=this.graphManager.calcLowestCommonAncestor(Q.source,Q.target),ge=0;ge0){for(var se=this.edgeToDummyNodes.get(ce),ge=0;ge=0&&oe.splice(xe,1);var De=Ae.getNeighborsList();De.forEach(function(ee){if(ce.indexOf(ee)<0){var rt=se.get(ee),me=rt-1;me==1&&ve.push(ee),se.set(ee,me)}})}ce=ce.concat(ve),(oe.length==1||oe.length==2)&&(ge=!0,ye=oe[0])}return ye},V.prototype.setGraphManager=function(Q){this.graphManager=Q},f.exports=V},function(f,p,w){function y(){}y.seed=1,y.x=0,y.nextDouble=function(){return y.x=Math.sin(y.seed++)*1e4,y.x-Math.floor(y.x)},f.exports=y},function(f,p,w){var y=w(4);function b(E,S){this.lworldOrgX=0,this.lworldOrgY=0,this.ldeviceOrgX=0,this.ldeviceOrgY=0,this.lworldExtX=1,this.lworldExtY=1,this.ldeviceExtX=1,this.ldeviceExtY=1}b.prototype.getWorldOrgX=function(){return this.lworldOrgX},b.prototype.setWorldOrgX=function(E){this.lworldOrgX=E},b.prototype.getWorldOrgY=function(){return this.lworldOrgY},b.prototype.setWorldOrgY=function(E){this.lworldOrgY=E},b.prototype.getWorldExtX=function(){return this.lworldExtX},b.prototype.setWorldExtX=function(E){this.lworldExtX=E},b.prototype.getWorldExtY=function(){return this.lworldExtY},b.prototype.setWorldExtY=function(E){this.lworldExtY=E},b.prototype.getDeviceOrgX=function(){return this.ldeviceOrgX},b.prototype.setDeviceOrgX=function(E){this.ldeviceOrgX=E},b.prototype.getDeviceOrgY=function(){return this.ldeviceOrgY},b.prototype.setDeviceOrgY=function(E){this.ldeviceOrgY=E},b.prototype.getDeviceExtX=function(){return this.ldeviceExtX},b.prototype.setDeviceExtX=function(E){this.ldeviceExtX=E},b.prototype.getDeviceExtY=function(){return this.ldeviceExtY},b.prototype.setDeviceExtY=function(E){this.ldeviceExtY=E},b.prototype.transformX=function(E){var S=0,N=this.lworldExtX;return N!=0&&(S=this.ldeviceOrgX+(E-this.lworldOrgX)*this.ldeviceExtX/N),S},b.prototype.transformY=function(E){var S=0,N=this.lworldExtY;return N!=0&&(S=this.ldeviceOrgY+(E-this.lworldOrgY)*this.ldeviceExtY/N),S},b.prototype.inverseTransformX=function(E){var S=0,N=this.ldeviceExtX;return N!=0&&(S=this.lworldOrgX+(E-this.ldeviceOrgX)*this.lworldExtX/N),S},b.prototype.inverseTransformY=function(E){var S=0,N=this.ldeviceExtY;return N!=0&&(S=this.lworldOrgY+(E-this.ldeviceOrgY)*this.lworldExtY/N),S},b.prototype.inverseTransformPoint=function(E){var S=new y(this.inverseTransformX(E.x),this.inverseTransformY(E.y));return S},f.exports=b},function(f,p,w){function y($){if(Array.isArray($)){for(var V=0,Q=Array($.length);V<$.length;V++)Q[V]=$[V];return Q}else return Array.from($)}var b=w(15),E=w(7),S=w(0),N=w(8),B=w(9);function R(){b.call(this),this.useSmartIdealEdgeLengthCalculation=E.DEFAULT_USE_SMART_IDEAL_EDGE_LENGTH_CALCULATION,this.idealEdgeLength=E.DEFAULT_EDGE_LENGTH,this.springConstant=E.DEFAULT_SPRING_STRENGTH,this.repulsionConstant=E.DEFAULT_REPULSION_STRENGTH,this.gravityConstant=E.DEFAULT_GRAVITY_STRENGTH,this.compoundGravityConstant=E.DEFAULT_COMPOUND_GRAVITY_STRENGTH,this.gravityRangeFactor=E.DEFAULT_GRAVITY_RANGE_FACTOR,this.compoundGravityRangeFactor=E.DEFAULT_COMPOUND_GRAVITY_RANGE_FACTOR,this.displacementThresholdPerNode=3*E.DEFAULT_EDGE_LENGTH/100,this.coolingFactor=E.DEFAULT_COOLING_FACTOR_INCREMENTAL,this.initialCoolingFactor=E.DEFAULT_COOLING_FACTOR_INCREMENTAL,this.totalDisplacement=0,this.oldTotalDisplacement=0,this.maxIterations=E.MAX_ITERATIONS}R.prototype=Object.create(b.prototype);for(var j in b)R[j]=b[j];R.prototype.initParameters=function(){b.prototype.initParameters.call(this,arguments),this.totalIterations=0,this.notAnimatedIterations=0,this.useFRGridVariant=E.DEFAULT_USE_SMART_REPULSION_RANGE_CALCULATION,this.grid=[]},R.prototype.calcIdealEdgeLengths=function(){for(var $,V,Q,oe,ce,se,ge=this.getGraphManager().getAllEdges(),ye=0;yeE.ADAPTATION_LOWER_NODE_LIMIT&&(this.coolingFactor=Math.max(this.coolingFactor*E.COOLING_ADAPTATION_FACTOR,this.coolingFactor-($-E.ADAPTATION_LOWER_NODE_LIMIT)/(E.ADAPTATION_UPPER_NODE_LIMIT-E.ADAPTATION_LOWER_NODE_LIMIT)*this.coolingFactor*(1-E.COOLING_ADAPTATION_FACTOR))),this.maxNodeDisplacement=E.MAX_NODE_DISPLACEMENT_INCREMENTAL):($>E.ADAPTATION_LOWER_NODE_LIMIT?this.coolingFactor=Math.max(E.COOLING_ADAPTATION_FACTOR,1-($-E.ADAPTATION_LOWER_NODE_LIMIT)/(E.ADAPTATION_UPPER_NODE_LIMIT-E.ADAPTATION_LOWER_NODE_LIMIT)*(1-E.COOLING_ADAPTATION_FACTOR)):this.coolingFactor=1,this.initialCoolingFactor=this.coolingFactor,this.maxNodeDisplacement=E.MAX_NODE_DISPLACEMENT),this.maxIterations=Math.max(this.getAllNodes().length*5,this.maxIterations),this.totalDisplacementThreshold=this.displacementThresholdPerNode*this.getAllNodes().length,this.repulsionRange=this.calcRepulsionRange()},R.prototype.calcSpringForces=function(){for(var $=this.getAllEdges(),V,Q=0;Q<$.length;Q++)V=$[Q],this.calcSpringForce(V,V.idealLength)},R.prototype.calcRepulsionForces=function(){var $=arguments.length>0&&arguments[0]!==void 0?arguments[0]:!0,V=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1,Q,oe,ce,se,ge=this.getAllNodes(),ye;if(this.useFRGridVariant)for(this.totalIterations%E.GRID_CALCULATION_CHECK_PERIOD==1&&$&&this.updateGrid(),ye=new Set,Q=0;Qke||ye>ke)&&($.gravitationForceX=-this.gravityConstant*ce,$.gravitationForceY=-this.gravityConstant*se)):(ke=V.getEstimatedSize()*this.compoundGravityRangeFactor,(ge>ke||ye>ke)&&($.gravitationForceX=-this.gravityConstant*ce*this.compoundGravityConstant,$.gravitationForceY=-this.gravityConstant*se*this.compoundGravityConstant))},R.prototype.isConverged=function(){var $,V=!1;return this.totalIterations>this.maxIterations/3&&(V=Math.abs(this.totalDisplacement-this.oldTotalDisplacement)<2),$=this.totalDisplacement=ge.length||ke>=ge[0].length)){for(var Ae=0;AeR}}]),N}();f.exports=S},function(f,p,w){var y=function(){function S(N,B){for(var R=0;R2&&arguments[2]!==void 0?arguments[2]:1,j=arguments.length>3&&arguments[3]!==void 0?arguments[3]:-1,$=arguments.length>4&&arguments[4]!==void 0?arguments[4]:-1;b(this,S),this.sequence1=N,this.sequence2=B,this.match_score=R,this.mismatch_penalty=j,this.gap_penalty=$,this.iMax=N.length+1,this.jMax=B.length+1,this.grid=new Array(this.iMax);for(var V=0;V=0;N--){var B=this.listeners[N];B.event===E&&B.callback===S&&this.listeners.splice(N,1)}},b.emit=function(E,S){for(var N=0;NB.coolingFactor*B.maxNodeDisplacement&&(this.displacementX=B.coolingFactor*B.maxNodeDisplacement*E.sign(this.displacementX)),Math.abs(this.displacementY)>B.coolingFactor*B.maxNodeDisplacement&&(this.displacementY=B.coolingFactor*B.maxNodeDisplacement*E.sign(this.displacementY)),this.child==null?this.moveBy(this.displacementX,this.displacementY):this.child.getNodes().length==0?this.moveBy(this.displacementX,this.displacementY):this.propogateDisplacementToChildren(this.displacementX,this.displacementY),B.totalDisplacement+=Math.abs(this.displacementX)+Math.abs(this.displacementY),this.springForceX=0,this.springForceY=0,this.repulsionForceX=0,this.repulsionForceY=0,this.gravitationForceX=0,this.gravitationForceY=0,this.displacementX=0,this.displacementY=0},S.prototype.propogateDisplacementToChildren=function(B,R){for(var j=this.getChild().getNodes(),$,V=0;V0)this.positionNodesRadially(de);else{this.reduceTrees(),this.graphManager.resetAllNodesToApplyGravitation();var ve=new Set(this.getAllNodes()),te=this.nodesWithGravity.filter(function(xe){return ve.has(xe)});this.graphManager.setAllNodesToApplyGravitation(te),this.positionNodesRandomly()}}return this.initSpringEmbedder(),this.runSpringEmbedder(),!0},ke.prototype.tick=function(){if(this.totalIterations++,this.totalIterations===this.maxIterations&&!this.isTreeGrowing&&!this.isGrowthFinished)if(this.prunedNodesAll.length>0)this.isTreeGrowing=!0;else return!0;if(this.totalIterations%j.CONVERGENCE_CHECK_PERIOD==0&&!this.isTreeGrowing&&!this.isGrowthFinished){if(this.isConverged())if(this.prunedNodesAll.length>0)this.isTreeGrowing=!0;else return!0;this.coolingCycle++,this.layoutQuality==0?this.coolingAdjuster=this.coolingCycle:this.layoutQuality==1&&(this.coolingAdjuster=this.coolingCycle/3),this.coolingFactor=Math.max(this.initialCoolingFactor-Math.pow(this.coolingCycle,Math.log(100*(this.initialCoolingFactor-this.finalTemperature))/Math.log(this.maxCoolingCycle))/100*this.coolingAdjuster,this.finalTemperature),this.animationPeriod=Math.ceil(this.initialAnimationPeriod*Math.sqrt(this.coolingFactor))}if(this.isTreeGrowing){if(this.growTreeIterations%10==0)if(this.prunedNodesAll.length>0){this.graphManager.updateBounds(),this.updateGrid(),this.growTree(this.prunedNodesAll),this.graphManager.resetAllNodesToApplyGravitation();var de=new Set(this.getAllNodes()),ve=this.nodesWithGravity.filter(function(De){return de.has(De)});this.graphManager.setAllNodesToApplyGravitation(ve),this.graphManager.updateBounds(),this.updateGrid(),this.coolingFactor=j.DEFAULT_COOLING_FACTOR_INCREMENTAL}else this.isTreeGrowing=!1,this.isGrowthFinished=!0;this.growTreeIterations++}if(this.isGrowthFinished){if(this.isConverged())return!0;this.afterGrowthIterations%10==0&&(this.graphManager.updateBounds(),this.updateGrid()),this.coolingFactor=j.DEFAULT_COOLING_FACTOR_INCREMENTAL*((100-this.afterGrowthIterations)/100),this.afterGrowthIterations++}var te=!this.isTreeGrowing&&!this.isGrowthFinished,xe=this.growTreeIterations%10==1&&this.isTreeGrowing||this.afterGrowthIterations%10==1&&this.isGrowthFinished;return this.totalDisplacement=0,this.graphManager.updateBounds(),this.calcSpringForces(),this.calcRepulsionForces(te,xe),this.calcGravitationalForces(),this.moveNodes(),this.animate(),!1},ke.prototype.getPositionsData=function(){for(var de=this.graphManager.getAllNodes(),ve={},te=0;te1){var ee;for(ee=0;eexe&&(xe=Math.floor(Ie.y)),he=Math.floor(Ie.x+R.DEFAULT_COMPONENT_SEPERATION)}this.transform(new Q($.WORLD_CENTER_X-Ie.x/2,$.WORLD_CENTER_Y-Ie.y/2))},ke.radialLayout=function(de,ve,te){var xe=Math.max(this.maxDiagonalInTree(de),R.DEFAULT_RADIAL_SEPARATION);ke.branchRadialLayout(ve,null,0,359,0,xe);var De=ge.calculateBounds(de),he=new ye;he.setDeviceOrgX(De.getMinX()),he.setDeviceOrgY(De.getMinY()),he.setWorldOrgX(te.x),he.setWorldOrgY(te.y);for(var Ie=0;Ie1;){var cn=Bt[0];Bt.splice(0,1);var Nn=pe.indexOf(cn);Nn>=0&&pe.splice(Nn,1),jt--,Et--}ve!=null?At=(pe.indexOf(Bt[0])+1)%jt:At=0;for(var Ot=Math.abs(xe-te)/Et,oi=At;wt!=Et;oi=++oi%jt){var kt=pe[oi].getOtherEnd(de);if(kt!=ve){var Dt=(te+wt*Ot)%360,vt=(Dt+Ot)%360;ke.branchRadialLayout(kt,de,Dt,vt,De+he,he),wt++}}},ke.maxDiagonalInTree=function(de){for(var ve=ce.MIN_VALUE,te=0;teve&&(ve=De)}return ve},ke.prototype.calcRepulsionRange=function(){return 2*(this.level+1)*this.idealEdgeLength},ke.prototype.groupZeroDegreeMembers=function(){var de=this,ve={};this.memberGroups={},this.idToDummyNode={};for(var te=[],xe=this.graphManager.getAllNodes(),De=0;De"u"&&(ve[ee]=[]),ve[ee]=ve[ee].concat(he)}Object.keys(ve).forEach(function(rt){if(ve[rt].length>1){var me="DummyCompound_"+rt;de.memberGroups[me]=ve[rt];var gt=ve[rt][0].getParent(),pe=new N(de.graphManager);pe.id=me,pe.paddingLeft=gt.paddingLeft||0,pe.paddingRight=gt.paddingRight||0,pe.paddingBottom=gt.paddingBottom||0,pe.paddingTop=gt.paddingTop||0,de.idToDummyNode[me]=pe;var Et=de.getGraphManager().add(de.newGraph(),pe),wt=gt.getChild();wt.add(pe);for(var jt=0;jt=0;de--){var ve=this.compoundOrder[de],te=ve.id,xe=ve.paddingLeft,De=ve.paddingTop;this.adjustLocations(this.tiledMemberPack[te],ve.rect.x,ve.rect.y,xe,De)}},ke.prototype.repopulateZeroDegreeMembers=function(){var de=this,ve=this.tiledZeroDegreePack;Object.keys(ve).forEach(function(te){var xe=de.idToDummyNode[te],De=xe.paddingLeft,he=xe.paddingTop;de.adjustLocations(ve[te],xe.rect.x,xe.rect.y,De,he)})},ke.prototype.getToBeTiled=function(de){var ve=de.id;if(this.toBeTiled[ve]!=null)return this.toBeTiled[ve];var te=de.getChild();if(te==null)return this.toBeTiled[ve]=!1,!1;for(var xe=te.getNodes(),De=0;De0)return this.toBeTiled[ve]=!1,!1;if(he.getChild()==null){this.toBeTiled[he.id]=!1;continue}if(!this.getToBeTiled(he))return this.toBeTiled[ve]=!1,!1}return this.toBeTiled[ve]=!0,!0},ke.prototype.getNodeDegree=function(de){de.id;for(var ve=de.getEdges(),te=0,xe=0;xert&&(rt=gt.rect.height)}te+=rt+de.verticalPadding}},ke.prototype.tileCompoundMembers=function(de,ve){var te=this;this.tiledMemberPack=[],Object.keys(de).forEach(function(xe){var De=ve[xe];te.tiledMemberPack[xe]=te.tileNodes(de[xe],De.paddingLeft+De.paddingRight),De.rect.width=te.tiledMemberPack[xe].width,De.rect.height=te.tiledMemberPack[xe].height})},ke.prototype.tileNodes=function(de,ve){var te=R.TILING_PADDING_VERTICAL,xe=R.TILING_PADDING_HORIZONTAL,De={rows:[],rowWidth:[],rowHeight:[],width:0,height:ve,verticalPadding:te,horizontalPadding:xe};de.sort(function(ee,rt){return ee.rect.width*ee.rect.height>rt.rect.width*rt.rect.height?-1:ee.rect.width*ee.rect.height0&&(Ie+=de.horizontalPadding),de.rowWidth[te]=Ie,de.width0&&(ee+=de.verticalPadding);var rt=0;ee>de.rowHeight[te]&&(rt=de.rowHeight[te],de.rowHeight[te]=ee,rt=de.rowHeight[te]-rt),de.height+=rt,de.rows[te].push(ve)},ke.prototype.getShortestRowIndex=function(de){for(var ve=-1,te=Number.MAX_VALUE,xe=0;xete&&(ve=xe,te=de.rowWidth[xe]);return ve},ke.prototype.canAddHorizontal=function(de,ve,te){var xe=this.getShortestRowIndex(de);if(xe<0)return!0;var De=de.rowWidth[xe];if(De+de.horizontalPadding+ve<=de.width)return!0;var he=0;de.rowHeight[xe]0&&(he=te+de.verticalPadding-de.rowHeight[xe]);var Ie;de.width-De>=ve+de.horizontalPadding?Ie=(de.height+he)/(De+ve+de.horizontalPadding):Ie=(de.height+he)/de.width,he=te+de.verticalPadding;var ee;return de.widthhe&&ve!=te){xe.splice(-1,1),de.rows[te].push(De),de.rowWidth[ve]=de.rowWidth[ve]-he,de.rowWidth[te]=de.rowWidth[te]+he,de.width=de.rowWidth[instance.getLongestRowIndex(de)];for(var Ie=Number.MIN_VALUE,ee=0;eeIe&&(Ie=xe[ee].height);ve>0&&(Ie+=de.verticalPadding);var rt=de.rowHeight[ve]+de.rowHeight[te];de.rowHeight[ve]=Ie,de.rowHeight[te]0)for(var wt=De;wt<=he;wt++)Et[0]+=this.grid[wt][Ie-1].length+this.grid[wt][Ie].length-1;if(he0)for(var wt=Ie;wt<=ee;wt++)Et[3]+=this.grid[De-1][wt].length+this.grid[De][wt].length-1;for(var jt=ce.MAX_VALUE,At,Bt,cn=0;cn0){var ee;ee=ye.getGraphManager().add(ye.newGraph(),te),this.processChildrenList(ee,ve,ye)}}},Q.prototype.stop=function(){return this.stopped=!0,this};var ce=function(ge){ge("layout","cose-bilkent",Q)};typeof cytoscape<"u"&&ce(cytoscape),p.exports=ce}])})})(qqt);const Yqt=xLe(Fge);dje.use(Yqt);function bje(i,a,f,p){fje.drawNode(i,a,f,p),a.children&&a.children.forEach((w,y)=>{bje(i,w,f<0?y:f,p)})}function Xqt(i,a){a.edges().map((f,p)=>{const w=f.data();if(f[0]._private.bodyBounds){const y=f[0]._private.rscratch;Fe.trace("Edge: ",p,w),i.insert("path").attr("d",`M ${y.startX},${y.startY} L ${y.midX},${y.midY} L${y.endX},${y.endY} `).attr("class","edge section-edge-"+w.section+" edge-depth-"+w.depth)}})}function vje(i,a,f,p){a.add({group:"nodes",data:{id:i.id,labelText:i.descr,height:i.height,width:i.width,level:p,nodeId:i.id,padding:i.padding,type:i.type},position:{x:i.x,y:i.y}}),i.children&&i.children.forEach(w=>{vje(w,a,f,p+1),a.add({group:"edges",data:{id:`${i.id}_${w.id}`,source:i.id,target:w.id,depth:p,section:w.section}})})}function Qqt(i,a){return new Promise(f=>{const p=Cr("body").append("div").attr("id","cy").attr("style","display:none"),w=dje({container:document.getElementById("cy"),style:[{selector:"edge",style:{"curve-style":"bezier"}}]});p.remove(),vje(i,w,a,0),w.nodes().forEach(function(y){y.layoutDimensions=()=>{const b=y.data();return{w:b.width,h:b.height}}}),w.layout({name:"cose-bilkent",quality:"proof",styleEnabled:!1,animate:!1}).run(),w.ready(y=>{Fe.info("Ready",y),f(w)})})}function Zqt(i){i.nodes().map((a,f)=>{const p=a.data();p.x=a.position().x,p.y=a.position().y,fje.positionNode(p);const w=Bge(p.nodeId);Fe.info("Id:",f,"Position: (",a.position().x,", ",a.position().y,")",p),w.attr("transform",`translate(${a.position().x-p.width/2}, ${a.position().y-p.height/2})`),w.attr("attr",`apa-${f})`)})}const Jqt={draw:async(i,a,f,p)=>{const w=Tt();w.htmlLabels=!1,p.db.clear(),p.parser.parse(i),Fe.debug(`Rendering mindmap diagram +`+i,p.parser);const y=Tt().securityLevel;let b;y==="sandbox"&&(b=Cr("#i"+a));const S=Cr(y==="sandbox"?b.nodes()[0].contentDocument.body:"body").select("#"+a);S.append("g");const N=p.db.getMindmap(),B=S.append("g");B.attr("class","mindmap-edges");const R=S.append("g");R.attr("class","mindmap-nodes"),bje(R,N,-1,w);const j=await Qqt(N,w);Xqt(B,j),Zqt(j),YE(void 0,S,w.mindmap.padding,w.mindmap.useMaxWidth)}},eVt=i=>{let a="";for(let f=0;f` + .edge { + stroke-width: 3; + } + ${eVt(i)} + .section-root rect, .section-root path, .section-root circle, .section-root polygon { + fill: ${i.git0}; + } + .section-root text { + fill: ${i.gitBranchLabel0}; + } + .icon-container { + height:100%; + display: flex; + justify-content: center; + align-items: center; + } + .edge { + fill: none; + } + .mindmap-node-label { + dy: 1em; + alignment-baseline: middle; + text-anchor: middle; + dominant-baseline: middle; + text-align: center; + } +`}},Symbol.toStringTag,{value:"Module"}));return O2}); diff --git a/site_libs/quarto-html/anchor.min.js b/site_libs/quarto-html/anchor.min.js new file mode 100644 index 00000000..5ac814d1 --- /dev/null +++ b/site_libs/quarto-html/anchor.min.js @@ -0,0 +1,9 @@ +// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt Expat +// +// AnchorJS - v5.0.0 - 2023-01-18 +// https://www.bryanbraun.com/anchorjs/ +// Copyright (c) 2023 Bryan Braun; Licensed MIT +// +// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt Expat +!function(A,e){"use strict";"function"==typeof define&&define.amd?define([],e):"object"==typeof module&&module.exports?module.exports=e():(A.AnchorJS=e(),A.anchors=new A.AnchorJS)}(globalThis,function(){"use strict";return function(A){function u(A){A.icon=Object.prototype.hasOwnProperty.call(A,"icon")?A.icon:"",A.visible=Object.prototype.hasOwnProperty.call(A,"visible")?A.visible:"hover",A.placement=Object.prototype.hasOwnProperty.call(A,"placement")?A.placement:"right",A.ariaLabel=Object.prototype.hasOwnProperty.call(A,"ariaLabel")?A.ariaLabel:"Anchor",A.class=Object.prototype.hasOwnProperty.call(A,"class")?A.class:"",A.base=Object.prototype.hasOwnProperty.call(A,"base")?A.base:"",A.truncate=Object.prototype.hasOwnProperty.call(A,"truncate")?Math.floor(A.truncate):64,A.titleText=Object.prototype.hasOwnProperty.call(A,"titleText")?A.titleText:""}function d(A){var e;if("string"==typeof A||A instanceof String)e=[].slice.call(document.querySelectorAll(A));else{if(!(Array.isArray(A)||A instanceof NodeList))throw new TypeError("The selector provided to AnchorJS was invalid.");e=[].slice.call(A)}return e}this.options=A||{},this.elements=[],u(this.options),this.add=function(A){var e,t,o,i,n,s,a,r,l,c,h,p=[];if(u(this.options),0!==(e=d(A=A||"h2, h3, h4, h5, h6")).length){for(null===document.head.querySelector("style.anchorjs")&&((A=document.createElement("style")).className="anchorjs",A.appendChild(document.createTextNode("")),void 0===(h=document.head.querySelector('[rel="stylesheet"],style'))?document.head.appendChild(A):document.head.insertBefore(A,h),A.sheet.insertRule(".anchorjs-link{opacity:0;text-decoration:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}",A.sheet.cssRules.length),A.sheet.insertRule(":hover>.anchorjs-link,.anchorjs-link:focus{opacity:1}",A.sheet.cssRules.length),A.sheet.insertRule("[data-anchorjs-icon]::after{content:attr(data-anchorjs-icon)}",A.sheet.cssRules.length),A.sheet.insertRule('@font-face{font-family:anchorjs-icons;src:url(data:n/a;base64,AAEAAAALAIAAAwAwT1MvMg8yG2cAAAE4AAAAYGNtYXDp3gC3AAABpAAAAExnYXNwAAAAEAAAA9wAAAAIZ2x5ZlQCcfwAAAH4AAABCGhlYWQHFvHyAAAAvAAAADZoaGVhBnACFwAAAPQAAAAkaG10eASAADEAAAGYAAAADGxvY2EACACEAAAB8AAAAAhtYXhwAAYAVwAAARgAAAAgbmFtZQGOH9cAAAMAAAAAunBvc3QAAwAAAAADvAAAACAAAQAAAAEAAHzE2p9fDzz1AAkEAAAAAADRecUWAAAAANQA6R8AAAAAAoACwAAAAAgAAgAAAAAAAAABAAADwP/AAAACgAAA/9MCrQABAAAAAAAAAAAAAAAAAAAAAwABAAAAAwBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAMCQAGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAg//0DwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAAIAAAACgAAxAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADAAAAAIAAgAAgAAACDpy//9//8AAAAg6cv//f///+EWNwADAAEAAAAAAAAAAAAAAAAACACEAAEAAAAAAAAAAAAAAAAxAAACAAQARAKAAsAAKwBUAAABIiYnJjQ3NzY2MzIWFxYUBwcGIicmNDc3NjQnJiYjIgYHBwYUFxYUBwYGIwciJicmNDc3NjIXFhQHBwYUFxYWMzI2Nzc2NCcmNDc2MhcWFAcHBgYjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAAADACWAAEAAAAAAAEACAAAAAEAAAAAAAIAAwAIAAEAAAAAAAMACAAAAAEAAAAAAAQACAAAAAEAAAAAAAUAAQALAAEAAAAAAAYACAAAAAMAAQQJAAEAEAAMAAMAAQQJAAIABgAcAAMAAQQJAAMAEAAMAAMAAQQJAAQAEAAMAAMAAQQJAAUAAgAiAAMAAQQJAAYAEAAMYW5jaG9yanM0MDBAAGEAbgBjAGgAbwByAGoAcwA0ADAAMABAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAP) format("truetype")}',A.sheet.cssRules.length)),h=document.querySelectorAll("[id]"),t=[].map.call(h,function(A){return A.id}),i=0;i\]./()*\\\n\t\b\v\u00A0]/g,"-").replace(/-{2,}/g,"-").substring(0,this.options.truncate).replace(/^-+|-+$/gm,"").toLowerCase()},this.hasAnchorJSLink=function(A){var e=A.firstChild&&-1<(" "+A.firstChild.className+" ").indexOf(" anchorjs-link "),A=A.lastChild&&-1<(" "+A.lastChild.className+" ").indexOf(" anchorjs-link ");return e||A||!1}}}); +// @license-end \ No newline at end of file diff --git a/site_libs/quarto-html/popper.min.js b/site_libs/quarto-html/popper.min.js new file mode 100644 index 00000000..e3726d72 --- /dev/null +++ b/site_libs/quarto-html/popper.min.js @@ -0,0 +1,6 @@ +/** + * @popperjs/core v2.11.7 - MIT License + */ + +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Popper={})}(this,(function(e){"use strict";function t(e){if(null==e)return window;if("[object Window]"!==e.toString()){var t=e.ownerDocument;return t&&t.defaultView||window}return e}function n(e){return e instanceof t(e).Element||e instanceof Element}function r(e){return e instanceof t(e).HTMLElement||e instanceof HTMLElement}function o(e){return"undefined"!=typeof ShadowRoot&&(e instanceof t(e).ShadowRoot||e instanceof ShadowRoot)}var i=Math.max,a=Math.min,s=Math.round;function f(){var e=navigator.userAgentData;return null!=e&&e.brands&&Array.isArray(e.brands)?e.brands.map((function(e){return e.brand+"/"+e.version})).join(" "):navigator.userAgent}function c(){return!/^((?!chrome|android).)*safari/i.test(f())}function p(e,o,i){void 0===o&&(o=!1),void 0===i&&(i=!1);var a=e.getBoundingClientRect(),f=1,p=1;o&&r(e)&&(f=e.offsetWidth>0&&s(a.width)/e.offsetWidth||1,p=e.offsetHeight>0&&s(a.height)/e.offsetHeight||1);var u=(n(e)?t(e):window).visualViewport,l=!c()&&i,d=(a.left+(l&&u?u.offsetLeft:0))/f,h=(a.top+(l&&u?u.offsetTop:0))/p,m=a.width/f,v=a.height/p;return{width:m,height:v,top:h,right:d+m,bottom:h+v,left:d,x:d,y:h}}function u(e){var n=t(e);return{scrollLeft:n.pageXOffset,scrollTop:n.pageYOffset}}function l(e){return e?(e.nodeName||"").toLowerCase():null}function d(e){return((n(e)?e.ownerDocument:e.document)||window.document).documentElement}function h(e){return p(d(e)).left+u(e).scrollLeft}function m(e){return t(e).getComputedStyle(e)}function v(e){var t=m(e),n=t.overflow,r=t.overflowX,o=t.overflowY;return/auto|scroll|overlay|hidden/.test(n+o+r)}function y(e,n,o){void 0===o&&(o=!1);var i,a,f=r(n),c=r(n)&&function(e){var t=e.getBoundingClientRect(),n=s(t.width)/e.offsetWidth||1,r=s(t.height)/e.offsetHeight||1;return 1!==n||1!==r}(n),m=d(n),y=p(e,c,o),g={scrollLeft:0,scrollTop:0},b={x:0,y:0};return(f||!f&&!o)&&(("body"!==l(n)||v(m))&&(g=(i=n)!==t(i)&&r(i)?{scrollLeft:(a=i).scrollLeft,scrollTop:a.scrollTop}:u(i)),r(n)?((b=p(n,!0)).x+=n.clientLeft,b.y+=n.clientTop):m&&(b.x=h(m))),{x:y.left+g.scrollLeft-b.x,y:y.top+g.scrollTop-b.y,width:y.width,height:y.height}}function g(e){var t=p(e),n=e.offsetWidth,r=e.offsetHeight;return Math.abs(t.width-n)<=1&&(n=t.width),Math.abs(t.height-r)<=1&&(r=t.height),{x:e.offsetLeft,y:e.offsetTop,width:n,height:r}}function b(e){return"html"===l(e)?e:e.assignedSlot||e.parentNode||(o(e)?e.host:null)||d(e)}function x(e){return["html","body","#document"].indexOf(l(e))>=0?e.ownerDocument.body:r(e)&&v(e)?e:x(b(e))}function w(e,n){var r;void 0===n&&(n=[]);var o=x(e),i=o===(null==(r=e.ownerDocument)?void 0:r.body),a=t(o),s=i?[a].concat(a.visualViewport||[],v(o)?o:[]):o,f=n.concat(s);return i?f:f.concat(w(b(s)))}function O(e){return["table","td","th"].indexOf(l(e))>=0}function j(e){return r(e)&&"fixed"!==m(e).position?e.offsetParent:null}function E(e){for(var n=t(e),i=j(e);i&&O(i)&&"static"===m(i).position;)i=j(i);return i&&("html"===l(i)||"body"===l(i)&&"static"===m(i).position)?n:i||function(e){var t=/firefox/i.test(f());if(/Trident/i.test(f())&&r(e)&&"fixed"===m(e).position)return null;var n=b(e);for(o(n)&&(n=n.host);r(n)&&["html","body"].indexOf(l(n))<0;){var i=m(n);if("none"!==i.transform||"none"!==i.perspective||"paint"===i.contain||-1!==["transform","perspective"].indexOf(i.willChange)||t&&"filter"===i.willChange||t&&i.filter&&"none"!==i.filter)return n;n=n.parentNode}return null}(e)||n}var D="top",A="bottom",L="right",P="left",M="auto",k=[D,A,L,P],W="start",B="end",H="viewport",T="popper",R=k.reduce((function(e,t){return e.concat([t+"-"+W,t+"-"+B])}),[]),S=[].concat(k,[M]).reduce((function(e,t){return e.concat([t,t+"-"+W,t+"-"+B])}),[]),V=["beforeRead","read","afterRead","beforeMain","main","afterMain","beforeWrite","write","afterWrite"];function q(e){var t=new Map,n=new Set,r=[];function o(e){n.add(e.name),[].concat(e.requires||[],e.requiresIfExists||[]).forEach((function(e){if(!n.has(e)){var r=t.get(e);r&&o(r)}})),r.push(e)}return e.forEach((function(e){t.set(e.name,e)})),e.forEach((function(e){n.has(e.name)||o(e)})),r}function C(e){return e.split("-")[0]}function N(e,t){var n=t.getRootNode&&t.getRootNode();if(e.contains(t))return!0;if(n&&o(n)){var r=t;do{if(r&&e.isSameNode(r))return!0;r=r.parentNode||r.host}while(r)}return!1}function I(e){return Object.assign({},e,{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height})}function _(e,r,o){return r===H?I(function(e,n){var r=t(e),o=d(e),i=r.visualViewport,a=o.clientWidth,s=o.clientHeight,f=0,p=0;if(i){a=i.width,s=i.height;var u=c();(u||!u&&"fixed"===n)&&(f=i.offsetLeft,p=i.offsetTop)}return{width:a,height:s,x:f+h(e),y:p}}(e,o)):n(r)?function(e,t){var n=p(e,!1,"fixed"===t);return n.top=n.top+e.clientTop,n.left=n.left+e.clientLeft,n.bottom=n.top+e.clientHeight,n.right=n.left+e.clientWidth,n.width=e.clientWidth,n.height=e.clientHeight,n.x=n.left,n.y=n.top,n}(r,o):I(function(e){var t,n=d(e),r=u(e),o=null==(t=e.ownerDocument)?void 0:t.body,a=i(n.scrollWidth,n.clientWidth,o?o.scrollWidth:0,o?o.clientWidth:0),s=i(n.scrollHeight,n.clientHeight,o?o.scrollHeight:0,o?o.clientHeight:0),f=-r.scrollLeft+h(e),c=-r.scrollTop;return"rtl"===m(o||n).direction&&(f+=i(n.clientWidth,o?o.clientWidth:0)-a),{width:a,height:s,x:f,y:c}}(d(e)))}function F(e,t,o,s){var f="clippingParents"===t?function(e){var t=w(b(e)),o=["absolute","fixed"].indexOf(m(e).position)>=0&&r(e)?E(e):e;return n(o)?t.filter((function(e){return n(e)&&N(e,o)&&"body"!==l(e)})):[]}(e):[].concat(t),c=[].concat(f,[o]),p=c[0],u=c.reduce((function(t,n){var r=_(e,n,s);return t.top=i(r.top,t.top),t.right=a(r.right,t.right),t.bottom=a(r.bottom,t.bottom),t.left=i(r.left,t.left),t}),_(e,p,s));return u.width=u.right-u.left,u.height=u.bottom-u.top,u.x=u.left,u.y=u.top,u}function U(e){return e.split("-")[1]}function z(e){return["top","bottom"].indexOf(e)>=0?"x":"y"}function X(e){var t,n=e.reference,r=e.element,o=e.placement,i=o?C(o):null,a=o?U(o):null,s=n.x+n.width/2-r.width/2,f=n.y+n.height/2-r.height/2;switch(i){case D:t={x:s,y:n.y-r.height};break;case A:t={x:s,y:n.y+n.height};break;case L:t={x:n.x+n.width,y:f};break;case P:t={x:n.x-r.width,y:f};break;default:t={x:n.x,y:n.y}}var c=i?z(i):null;if(null!=c){var p="y"===c?"height":"width";switch(a){case W:t[c]=t[c]-(n[p]/2-r[p]/2);break;case B:t[c]=t[c]+(n[p]/2-r[p]/2)}}return t}function Y(e){return Object.assign({},{top:0,right:0,bottom:0,left:0},e)}function G(e,t){return t.reduce((function(t,n){return t[n]=e,t}),{})}function J(e,t){void 0===t&&(t={});var r=t,o=r.placement,i=void 0===o?e.placement:o,a=r.strategy,s=void 0===a?e.strategy:a,f=r.boundary,c=void 0===f?"clippingParents":f,u=r.rootBoundary,l=void 0===u?H:u,h=r.elementContext,m=void 0===h?T:h,v=r.altBoundary,y=void 0!==v&&v,g=r.padding,b=void 0===g?0:g,x=Y("number"!=typeof b?b:G(b,k)),w=m===T?"reference":T,O=e.rects.popper,j=e.elements[y?w:m],E=F(n(j)?j:j.contextElement||d(e.elements.popper),c,l,s),P=p(e.elements.reference),M=X({reference:P,element:O,strategy:"absolute",placement:i}),W=I(Object.assign({},O,M)),B=m===T?W:P,R={top:E.top-B.top+x.top,bottom:B.bottom-E.bottom+x.bottom,left:E.left-B.left+x.left,right:B.right-E.right+x.right},S=e.modifiersData.offset;if(m===T&&S){var V=S[i];Object.keys(R).forEach((function(e){var t=[L,A].indexOf(e)>=0?1:-1,n=[D,A].indexOf(e)>=0?"y":"x";R[e]+=V[n]*t}))}return R}var K={placement:"bottom",modifiers:[],strategy:"absolute"};function Q(){for(var e=arguments.length,t=new Array(e),n=0;n=0?-1:1,i="function"==typeof n?n(Object.assign({},t,{placement:e})):n,a=i[0],s=i[1];return a=a||0,s=(s||0)*o,[P,L].indexOf(r)>=0?{x:s,y:a}:{x:a,y:s}}(n,t.rects,i),e}),{}),s=a[t.placement],f=s.x,c=s.y;null!=t.modifiersData.popperOffsets&&(t.modifiersData.popperOffsets.x+=f,t.modifiersData.popperOffsets.y+=c),t.modifiersData[r]=a}},se={left:"right",right:"left",bottom:"top",top:"bottom"};function fe(e){return e.replace(/left|right|bottom|top/g,(function(e){return se[e]}))}var ce={start:"end",end:"start"};function pe(e){return e.replace(/start|end/g,(function(e){return ce[e]}))}function ue(e,t){void 0===t&&(t={});var n=t,r=n.placement,o=n.boundary,i=n.rootBoundary,a=n.padding,s=n.flipVariations,f=n.allowedAutoPlacements,c=void 0===f?S:f,p=U(r),u=p?s?R:R.filter((function(e){return U(e)===p})):k,l=u.filter((function(e){return c.indexOf(e)>=0}));0===l.length&&(l=u);var d=l.reduce((function(t,n){return t[n]=J(e,{placement:n,boundary:o,rootBoundary:i,padding:a})[C(n)],t}),{});return Object.keys(d).sort((function(e,t){return d[e]-d[t]}))}var le={name:"flip",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options,r=e.name;if(!t.modifiersData[r]._skip){for(var o=n.mainAxis,i=void 0===o||o,a=n.altAxis,s=void 0===a||a,f=n.fallbackPlacements,c=n.padding,p=n.boundary,u=n.rootBoundary,l=n.altBoundary,d=n.flipVariations,h=void 0===d||d,m=n.allowedAutoPlacements,v=t.options.placement,y=C(v),g=f||(y===v||!h?[fe(v)]:function(e){if(C(e)===M)return[];var t=fe(e);return[pe(e),t,pe(t)]}(v)),b=[v].concat(g).reduce((function(e,n){return e.concat(C(n)===M?ue(t,{placement:n,boundary:p,rootBoundary:u,padding:c,flipVariations:h,allowedAutoPlacements:m}):n)}),[]),x=t.rects.reference,w=t.rects.popper,O=new Map,j=!0,E=b[0],k=0;k=0,S=R?"width":"height",V=J(t,{placement:B,boundary:p,rootBoundary:u,altBoundary:l,padding:c}),q=R?T?L:P:T?A:D;x[S]>w[S]&&(q=fe(q));var N=fe(q),I=[];if(i&&I.push(V[H]<=0),s&&I.push(V[q]<=0,V[N]<=0),I.every((function(e){return e}))){E=B,j=!1;break}O.set(B,I)}if(j)for(var _=function(e){var t=b.find((function(t){var n=O.get(t);if(n)return n.slice(0,e).every((function(e){return e}))}));if(t)return E=t,"break"},F=h?3:1;F>0;F--){if("break"===_(F))break}t.placement!==E&&(t.modifiersData[r]._skip=!0,t.placement=E,t.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function de(e,t,n){return i(e,a(t,n))}var he={name:"preventOverflow",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options,r=e.name,o=n.mainAxis,s=void 0===o||o,f=n.altAxis,c=void 0!==f&&f,p=n.boundary,u=n.rootBoundary,l=n.altBoundary,d=n.padding,h=n.tether,m=void 0===h||h,v=n.tetherOffset,y=void 0===v?0:v,b=J(t,{boundary:p,rootBoundary:u,padding:d,altBoundary:l}),x=C(t.placement),w=U(t.placement),O=!w,j=z(x),M="x"===j?"y":"x",k=t.modifiersData.popperOffsets,B=t.rects.reference,H=t.rects.popper,T="function"==typeof y?y(Object.assign({},t.rects,{placement:t.placement})):y,R="number"==typeof T?{mainAxis:T,altAxis:T}:Object.assign({mainAxis:0,altAxis:0},T),S=t.modifiersData.offset?t.modifiersData.offset[t.placement]:null,V={x:0,y:0};if(k){if(s){var q,N="y"===j?D:P,I="y"===j?A:L,_="y"===j?"height":"width",F=k[j],X=F+b[N],Y=F-b[I],G=m?-H[_]/2:0,K=w===W?B[_]:H[_],Q=w===W?-H[_]:-B[_],Z=t.elements.arrow,$=m&&Z?g(Z):{width:0,height:0},ee=t.modifiersData["arrow#persistent"]?t.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},te=ee[N],ne=ee[I],re=de(0,B[_],$[_]),oe=O?B[_]/2-G-re-te-R.mainAxis:K-re-te-R.mainAxis,ie=O?-B[_]/2+G+re+ne+R.mainAxis:Q+re+ne+R.mainAxis,ae=t.elements.arrow&&E(t.elements.arrow),se=ae?"y"===j?ae.clientTop||0:ae.clientLeft||0:0,fe=null!=(q=null==S?void 0:S[j])?q:0,ce=F+ie-fe,pe=de(m?a(X,F+oe-fe-se):X,F,m?i(Y,ce):Y);k[j]=pe,V[j]=pe-F}if(c){var ue,le="x"===j?D:P,he="x"===j?A:L,me=k[M],ve="y"===M?"height":"width",ye=me+b[le],ge=me-b[he],be=-1!==[D,P].indexOf(x),xe=null!=(ue=null==S?void 0:S[M])?ue:0,we=be?ye:me-B[ve]-H[ve]-xe+R.altAxis,Oe=be?me+B[ve]+H[ve]-xe-R.altAxis:ge,je=m&&be?function(e,t,n){var r=de(e,t,n);return r>n?n:r}(we,me,Oe):de(m?we:ye,me,m?Oe:ge);k[M]=je,V[M]=je-me}t.modifiersData[r]=V}},requiresIfExists:["offset"]};var me={name:"arrow",enabled:!0,phase:"main",fn:function(e){var t,n=e.state,r=e.name,o=e.options,i=n.elements.arrow,a=n.modifiersData.popperOffsets,s=C(n.placement),f=z(s),c=[P,L].indexOf(s)>=0?"height":"width";if(i&&a){var p=function(e,t){return Y("number"!=typeof(e="function"==typeof e?e(Object.assign({},t.rects,{placement:t.placement})):e)?e:G(e,k))}(o.padding,n),u=g(i),l="y"===f?D:P,d="y"===f?A:L,h=n.rects.reference[c]+n.rects.reference[f]-a[f]-n.rects.popper[c],m=a[f]-n.rects.reference[f],v=E(i),y=v?"y"===f?v.clientHeight||0:v.clientWidth||0:0,b=h/2-m/2,x=p[l],w=y-u[c]-p[d],O=y/2-u[c]/2+b,j=de(x,O,w),M=f;n.modifiersData[r]=((t={})[M]=j,t.centerOffset=j-O,t)}},effect:function(e){var t=e.state,n=e.options.element,r=void 0===n?"[data-popper-arrow]":n;null!=r&&("string"!=typeof r||(r=t.elements.popper.querySelector(r)))&&N(t.elements.popper,r)&&(t.elements.arrow=r)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function ve(e,t,n){return void 0===n&&(n={x:0,y:0}),{top:e.top-t.height-n.y,right:e.right-t.width+n.x,bottom:e.bottom-t.height+n.y,left:e.left-t.width-n.x}}function ye(e){return[D,L,A,P].some((function(t){return e[t]>=0}))}var ge={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(e){var t=e.state,n=e.name,r=t.rects.reference,o=t.rects.popper,i=t.modifiersData.preventOverflow,a=J(t,{elementContext:"reference"}),s=J(t,{altBoundary:!0}),f=ve(a,r),c=ve(s,o,i),p=ye(f),u=ye(c);t.modifiersData[n]={referenceClippingOffsets:f,popperEscapeOffsets:c,isReferenceHidden:p,hasPopperEscaped:u},t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-reference-hidden":p,"data-popper-escaped":u})}},be=Z({defaultModifiers:[ee,te,oe,ie]}),xe=[ee,te,oe,ie,ae,le,he,me,ge],we=Z({defaultModifiers:xe});e.applyStyles=ie,e.arrow=me,e.computeStyles=oe,e.createPopper=we,e.createPopperLite=be,e.defaultModifiers=xe,e.detectOverflow=J,e.eventListeners=ee,e.flip=le,e.hide=ge,e.offset=ae,e.popperGenerator=Z,e.popperOffsets=te,e.preventOverflow=he,Object.defineProperty(e,"__esModule",{value:!0})})); + diff --git a/site_libs/quarto-html/quarto-syntax-highlighting.css b/site_libs/quarto-html/quarto-syntax-highlighting.css new file mode 100644 index 00000000..b30ce576 --- /dev/null +++ b/site_libs/quarto-html/quarto-syntax-highlighting.css @@ -0,0 +1,205 @@ +/* quarto syntax highlight colors */ +:root { + --quarto-hl-ot-color: #003B4F; + --quarto-hl-at-color: #657422; + --quarto-hl-ss-color: #20794D; + --quarto-hl-an-color: #5E5E5E; + --quarto-hl-fu-color: #4758AB; + --quarto-hl-st-color: #20794D; + --quarto-hl-cf-color: #003B4F; + --quarto-hl-op-color: #5E5E5E; + --quarto-hl-er-color: #AD0000; + --quarto-hl-bn-color: #AD0000; + --quarto-hl-al-color: #AD0000; + --quarto-hl-va-color: #111111; + --quarto-hl-bu-color: inherit; + --quarto-hl-ex-color: inherit; + --quarto-hl-pp-color: #AD0000; + --quarto-hl-in-color: #5E5E5E; + --quarto-hl-vs-color: #20794D; + --quarto-hl-wa-color: #5E5E5E; + --quarto-hl-do-color: #5E5E5E; + --quarto-hl-im-color: #00769E; + --quarto-hl-ch-color: #20794D; + --quarto-hl-dt-color: #AD0000; + --quarto-hl-fl-color: #AD0000; + --quarto-hl-co-color: #5E5E5E; + --quarto-hl-cv-color: #5E5E5E; + --quarto-hl-cn-color: #8f5902; + --quarto-hl-sc-color: #5E5E5E; + --quarto-hl-dv-color: #AD0000; + --quarto-hl-kw-color: #003B4F; +} + +/* other quarto variables */ +:root { + --quarto-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; +} + +pre > code.sourceCode > span { + color: #003B4F; +} + +code span { + color: #003B4F; +} + +code.sourceCode > span { + color: #003B4F; +} + +div.sourceCode, +div.sourceCode pre.sourceCode { + color: #003B4F; +} + +code span.ot { + color: #003B4F; + font-style: inherit; +} + +code span.at { + color: #657422; + font-style: inherit; +} + +code span.ss { + color: #20794D; + font-style: inherit; +} + +code span.an { + color: #5E5E5E; + font-style: inherit; +} + +code span.fu { + color: #4758AB; + font-style: inherit; +} + +code span.st { + color: #20794D; + font-style: inherit; +} + +code span.cf { + color: #003B4F; + font-weight: bold; + font-style: inherit; +} + +code span.op { + color: #5E5E5E; + font-style: inherit; +} + +code span.er { + color: #AD0000; + font-style: inherit; +} + +code span.bn { + color: #AD0000; + font-style: inherit; +} + +code span.al { + color: #AD0000; + font-style: inherit; +} + +code span.va { + color: #111111; + font-style: inherit; +} + +code span.bu { + font-style: inherit; +} + +code span.ex { + font-style: inherit; +} + +code span.pp { + color: #AD0000; + font-style: inherit; +} + +code span.in { + color: #5E5E5E; + font-style: inherit; +} + +code span.vs { + color: #20794D; + font-style: inherit; +} + +code span.wa { + color: #5E5E5E; + font-style: italic; +} + +code span.do { + color: #5E5E5E; + font-style: italic; +} + +code span.im { + color: #00769E; + font-style: inherit; +} + +code span.ch { + color: #20794D; + font-style: inherit; +} + +code span.dt { + color: #AD0000; + font-style: inherit; +} + +code span.fl { + color: #AD0000; + font-style: inherit; +} + +code span.co { + color: #5E5E5E; + font-style: inherit; +} + +code span.cv { + color: #5E5E5E; + font-style: italic; +} + +code span.cn { + color: #8f5902; + font-style: inherit; +} + +code span.sc { + color: #5E5E5E; + font-style: inherit; +} + +code span.dv { + color: #AD0000; + font-style: inherit; +} + +code span.kw { + color: #003B4F; + font-weight: bold; + font-style: inherit; +} + +.prevent-inlining { + content: " { + // Find any conflicting margin elements and add margins to the + // top to prevent overlap + const marginChildren = window.document.querySelectorAll( + ".column-margin.column-container > *, .margin-caption, .aside" + ); + + let lastBottom = 0; + for (const marginChild of marginChildren) { + if (marginChild.offsetParent !== null) { + // clear the top margin so we recompute it + marginChild.style.marginTop = null; + const top = marginChild.getBoundingClientRect().top + window.scrollY; + if (top < lastBottom) { + const marginChildStyle = window.getComputedStyle(marginChild); + const marginBottom = parseFloat(marginChildStyle["marginBottom"]); + const margin = lastBottom - top + marginBottom; + marginChild.style.marginTop = `${margin}px`; + } + const styles = window.getComputedStyle(marginChild); + const marginTop = parseFloat(styles["marginTop"]); + lastBottom = top + marginChild.getBoundingClientRect().height + marginTop; + } + } +}; + +window.document.addEventListener("DOMContentLoaded", function (_event) { + // Recompute the position of margin elements anytime the body size changes + if (window.ResizeObserver) { + const resizeObserver = new window.ResizeObserver( + throttle(() => { + layoutMarginEls(); + if ( + window.document.body.getBoundingClientRect().width < 990 && + isReaderMode() + ) { + quartoToggleReader(); + } + }, 50) + ); + resizeObserver.observe(window.document.body); + } + + const tocEl = window.document.querySelector('nav.toc-active[role="doc-toc"]'); + const sidebarEl = window.document.getElementById("quarto-sidebar"); + const leftTocEl = window.document.getElementById("quarto-sidebar-toc-left"); + const marginSidebarEl = window.document.getElementById( + "quarto-margin-sidebar" + ); + // function to determine whether the element has a previous sibling that is active + const prevSiblingIsActiveLink = (el) => { + const sibling = el.previousElementSibling; + if (sibling && sibling.tagName === "A") { + return sibling.classList.contains("active"); + } else { + return false; + } + }; + + // fire slideEnter for bootstrap tab activations (for htmlwidget resize behavior) + function fireSlideEnter(e) { + const event = window.document.createEvent("Event"); + event.initEvent("slideenter", true, true); + window.document.dispatchEvent(event); + } + const tabs = window.document.querySelectorAll('a[data-bs-toggle="tab"]'); + tabs.forEach((tab) => { + tab.addEventListener("shown.bs.tab", fireSlideEnter); + }); + + // fire slideEnter for tabby tab activations (for htmlwidget resize behavior) + document.addEventListener("tabby", fireSlideEnter, false); + + // Track scrolling and mark TOC links as active + // get table of contents and sidebar (bail if we don't have at least one) + const tocLinks = tocEl + ? [...tocEl.querySelectorAll("a[data-scroll-target]")] + : []; + const makeActive = (link) => tocLinks[link].classList.add("active"); + const removeActive = (link) => tocLinks[link].classList.remove("active"); + const removeAllActive = () => + [...Array(tocLinks.length).keys()].forEach((link) => removeActive(link)); + + // activate the anchor for a section associated with this TOC entry + tocLinks.forEach((link) => { + link.addEventListener("click", () => { + if (link.href.indexOf("#") !== -1) { + const anchor = link.href.split("#")[1]; + const heading = window.document.querySelector( + `[data-anchor-id="${anchor}"]` + ); + if (heading) { + // Add the class + heading.classList.add("reveal-anchorjs-link"); + + // function to show the anchor + const handleMouseout = () => { + heading.classList.remove("reveal-anchorjs-link"); + heading.removeEventListener("mouseout", handleMouseout); + }; + + // add a function to clear the anchor when the user mouses out of it + heading.addEventListener("mouseout", handleMouseout); + } + } + }); + }); + + const sections = tocLinks.map((link) => { + const target = link.getAttribute("data-scroll-target"); + if (target.startsWith("#")) { + return window.document.getElementById(decodeURI(`${target.slice(1)}`)); + } else { + return window.document.querySelector(decodeURI(`${target}`)); + } + }); + + const sectionMargin = 200; + let currentActive = 0; + // track whether we've initialized state the first time + let init = false; + + const updateActiveLink = () => { + // The index from bottom to top (e.g. reversed list) + let sectionIndex = -1; + if ( + window.innerHeight + window.pageYOffset >= + window.document.body.offsetHeight + ) { + // This is the no-scroll case where last section should be the active one + sectionIndex = 0; + } else { + // This finds the last section visible on screen that should be made active + sectionIndex = [...sections].reverse().findIndex((section) => { + if (section) { + return window.pageYOffset >= section.offsetTop - sectionMargin; + } else { + return false; + } + }); + } + if (sectionIndex > -1) { + const current = sections.length - sectionIndex - 1; + if (current !== currentActive) { + removeAllActive(); + currentActive = current; + makeActive(current); + if (init) { + window.dispatchEvent(sectionChanged); + } + init = true; + } + } + }; + + const inHiddenRegion = (top, bottom, hiddenRegions) => { + for (const region of hiddenRegions) { + if (top <= region.bottom && bottom >= region.top) { + return true; + } + } + return false; + }; + + const categorySelector = "header.quarto-title-block .quarto-category"; + const activateCategories = (href) => { + // Find any categories + // Surround them with a link pointing back to: + // #category=Authoring + try { + const categoryEls = window.document.querySelectorAll(categorySelector); + for (const categoryEl of categoryEls) { + const categoryText = categoryEl.textContent; + if (categoryText) { + const link = `${href}#category=${encodeURIComponent(categoryText)}`; + const linkEl = window.document.createElement("a"); + linkEl.setAttribute("href", link); + for (const child of categoryEl.childNodes) { + linkEl.append(child); + } + categoryEl.appendChild(linkEl); + } + } + } catch { + // Ignore errors + } + }; + function hasTitleCategories() { + return window.document.querySelector(categorySelector) !== null; + } + + function offsetRelativeUrl(url) { + const offset = getMeta("quarto:offset"); + return offset ? offset + url : url; + } + + function offsetAbsoluteUrl(url) { + const offset = getMeta("quarto:offset"); + const baseUrl = new URL(offset, window.location); + + const projRelativeUrl = url.replace(baseUrl, ""); + if (projRelativeUrl.startsWith("/")) { + return projRelativeUrl; + } else { + return "/" + projRelativeUrl; + } + } + + // read a meta tag value + function getMeta(metaName) { + const metas = window.document.getElementsByTagName("meta"); + for (let i = 0; i < metas.length; i++) { + if (metas[i].getAttribute("name") === metaName) { + return metas[i].getAttribute("content"); + } + } + return ""; + } + + async function findAndActivateCategories() { + const currentPagePath = offsetAbsoluteUrl(window.location.href); + const response = await fetch(offsetRelativeUrl("listings.json")); + if (response.status == 200) { + return response.json().then(function (listingPaths) { + const listingHrefs = []; + for (const listingPath of listingPaths) { + const pathWithoutLeadingSlash = listingPath.listing.substring(1); + for (const item of listingPath.items) { + if ( + item === currentPagePath || + item === currentPagePath + "index.html" + ) { + // Resolve this path against the offset to be sure + // we already are using the correct path to the listing + // (this adjusts the listing urls to be rooted against + // whatever root the page is actually running against) + const relative = offsetRelativeUrl(pathWithoutLeadingSlash); + const baseUrl = window.location; + const resolvedPath = new URL(relative, baseUrl); + listingHrefs.push(resolvedPath.pathname); + break; + } + } + } + + // Look up the tree for a nearby linting and use that if we find one + const nearestListing = findNearestParentListing( + offsetAbsoluteUrl(window.location.pathname), + listingHrefs + ); + if (nearestListing) { + activateCategories(nearestListing); + } else { + // See if the referrer is a listing page for this item + const referredRelativePath = offsetAbsoluteUrl(document.referrer); + const referrerListing = listingHrefs.find((listingHref) => { + const isListingReferrer = + listingHref === referredRelativePath || + listingHref === referredRelativePath + "index.html"; + return isListingReferrer; + }); + + if (referrerListing) { + // Try to use the referrer if possible + activateCategories(referrerListing); + } else if (listingHrefs.length > 0) { + // Otherwise, just fall back to the first listing + activateCategories(listingHrefs[0]); + } + } + }); + } + } + if (hasTitleCategories()) { + findAndActivateCategories(); + } + + const findNearestParentListing = (href, listingHrefs) => { + if (!href || !listingHrefs) { + return undefined; + } + // Look up the tree for a nearby linting and use that if we find one + const relativeParts = href.substring(1).split("/"); + while (relativeParts.length > 0) { + const path = relativeParts.join("/"); + for (const listingHref of listingHrefs) { + if (listingHref.startsWith(path)) { + return listingHref; + } + } + relativeParts.pop(); + } + + return undefined; + }; + + const manageSidebarVisiblity = (el, placeholderDescriptor) => { + let isVisible = true; + let elRect; + + return (hiddenRegions) => { + if (el === null) { + return; + } + + // Find the last element of the TOC + const lastChildEl = el.lastElementChild; + + if (lastChildEl) { + // Converts the sidebar to a menu + const convertToMenu = () => { + for (const child of el.children) { + child.style.opacity = 0; + child.style.overflow = "hidden"; + child.style.pointerEvents = "none"; + } + + nexttick(() => { + const toggleContainer = window.document.createElement("div"); + toggleContainer.style.width = "100%"; + toggleContainer.classList.add("zindex-over-content"); + toggleContainer.classList.add("quarto-sidebar-toggle"); + toggleContainer.classList.add("headroom-target"); // Marks this to be managed by headeroom + toggleContainer.id = placeholderDescriptor.id; + toggleContainer.style.position = "fixed"; + + const toggleIcon = window.document.createElement("i"); + toggleIcon.classList.add("quarto-sidebar-toggle-icon"); + toggleIcon.classList.add("bi"); + toggleIcon.classList.add("bi-caret-down-fill"); + + const toggleTitle = window.document.createElement("div"); + const titleEl = window.document.body.querySelector( + placeholderDescriptor.titleSelector + ); + if (titleEl) { + toggleTitle.append( + titleEl.textContent || titleEl.innerText, + toggleIcon + ); + } + toggleTitle.classList.add("zindex-over-content"); + toggleTitle.classList.add("quarto-sidebar-toggle-title"); + toggleContainer.append(toggleTitle); + + const toggleContents = window.document.createElement("div"); + toggleContents.classList = el.classList; + toggleContents.classList.add("zindex-over-content"); + toggleContents.classList.add("quarto-sidebar-toggle-contents"); + for (const child of el.children) { + if (child.id === "toc-title") { + continue; + } + + const clone = child.cloneNode(true); + clone.style.opacity = 1; + clone.style.pointerEvents = null; + clone.style.display = null; + toggleContents.append(clone); + } + toggleContents.style.height = "0px"; + const positionToggle = () => { + // position the element (top left of parent, same width as parent) + if (!elRect) { + elRect = el.getBoundingClientRect(); + } + toggleContainer.style.left = `${elRect.left}px`; + toggleContainer.style.top = `${elRect.top}px`; + toggleContainer.style.width = `${elRect.width}px`; + }; + positionToggle(); + + toggleContainer.append(toggleContents); + el.parentElement.prepend(toggleContainer); + + // Process clicks + let tocShowing = false; + // Allow the caller to control whether this is dismissed + // when it is clicked (e.g. sidebar navigation supports + // opening and closing the nav tree, so don't dismiss on click) + const clickEl = placeholderDescriptor.dismissOnClick + ? toggleContainer + : toggleTitle; + + const closeToggle = () => { + if (tocShowing) { + toggleContainer.classList.remove("expanded"); + toggleContents.style.height = "0px"; + tocShowing = false; + } + }; + + // Get rid of any expanded toggle if the user scrolls + window.document.addEventListener( + "scroll", + throttle(() => { + closeToggle(); + }, 50) + ); + + // Handle positioning of the toggle + window.addEventListener( + "resize", + throttle(() => { + elRect = undefined; + positionToggle(); + }, 50) + ); + + window.addEventListener("quarto-hrChanged", () => { + elRect = undefined; + }); + + // Process the click + clickEl.onclick = () => { + if (!tocShowing) { + toggleContainer.classList.add("expanded"); + toggleContents.style.height = null; + tocShowing = true; + } else { + closeToggle(); + } + }; + }); + }; + + // Converts a sidebar from a menu back to a sidebar + const convertToSidebar = () => { + for (const child of el.children) { + child.style.opacity = 1; + child.style.overflow = null; + child.style.pointerEvents = null; + } + + const placeholderEl = window.document.getElementById( + placeholderDescriptor.id + ); + if (placeholderEl) { + placeholderEl.remove(); + } + + el.classList.remove("rollup"); + }; + + if (isReaderMode()) { + convertToMenu(); + isVisible = false; + } else { + // Find the top and bottom o the element that is being managed + const elTop = el.offsetTop; + const elBottom = + elTop + lastChildEl.offsetTop + lastChildEl.offsetHeight; + + if (!isVisible) { + // If the element is current not visible reveal if there are + // no conflicts with overlay regions + if (!inHiddenRegion(elTop, elBottom, hiddenRegions)) { + convertToSidebar(); + isVisible = true; + } + } else { + // If the element is visible, hide it if it conflicts with overlay regions + // and insert a placeholder toggle (or if we're in reader mode) + if (inHiddenRegion(elTop, elBottom, hiddenRegions)) { + convertToMenu(); + isVisible = false; + } + } + } + } + }; + }; + + const tabEls = document.querySelectorAll('a[data-bs-toggle="tab"]'); + for (const tabEl of tabEls) { + const id = tabEl.getAttribute("data-bs-target"); + if (id) { + const columnEl = document.querySelector( + `${id} .column-margin, .tabset-margin-content` + ); + if (columnEl) + tabEl.addEventListener("shown.bs.tab", function (event) { + const el = event.srcElement; + if (el) { + const visibleCls = `${el.id}-margin-content`; + // walk up until we find a parent tabset + let panelTabsetEl = el.parentElement; + while (panelTabsetEl) { + if (panelTabsetEl.classList.contains("panel-tabset")) { + break; + } + panelTabsetEl = panelTabsetEl.parentElement; + } + + if (panelTabsetEl) { + const prevSib = panelTabsetEl.previousElementSibling; + if ( + prevSib && + prevSib.classList.contains("tabset-margin-container") + ) { + const childNodes = prevSib.querySelectorAll( + ".tabset-margin-content" + ); + for (const childEl of childNodes) { + if (childEl.classList.contains(visibleCls)) { + childEl.classList.remove("collapse"); + } else { + childEl.classList.add("collapse"); + } + } + } + } + } + + layoutMarginEls(); + }); + } + } + + // Manage the visibility of the toc and the sidebar + const marginScrollVisibility = manageSidebarVisiblity(marginSidebarEl, { + id: "quarto-toc-toggle", + titleSelector: "#toc-title", + dismissOnClick: true, + }); + const sidebarScrollVisiblity = manageSidebarVisiblity(sidebarEl, { + id: "quarto-sidebarnav-toggle", + titleSelector: ".title", + dismissOnClick: false, + }); + let tocLeftScrollVisibility; + if (leftTocEl) { + tocLeftScrollVisibility = manageSidebarVisiblity(leftTocEl, { + id: "quarto-lefttoc-toggle", + titleSelector: "#toc-title", + dismissOnClick: true, + }); + } + + // Find the first element that uses formatting in special columns + const conflictingEls = window.document.body.querySelectorAll( + '[class^="column-"], [class*=" column-"], aside, [class*="margin-caption"], [class*=" margin-caption"], [class*="margin-ref"], [class*=" margin-ref"]' + ); + + // Filter all the possibly conflicting elements into ones + // the do conflict on the left or ride side + const arrConflictingEls = Array.from(conflictingEls); + const leftSideConflictEls = arrConflictingEls.filter((el) => { + if (el.tagName === "ASIDE") { + return false; + } + return Array.from(el.classList).find((className) => { + return ( + className !== "column-body" && + className.startsWith("column-") && + !className.endsWith("right") && + !className.endsWith("container") && + className !== "column-margin" + ); + }); + }); + const rightSideConflictEls = arrConflictingEls.filter((el) => { + if (el.tagName === "ASIDE") { + return true; + } + + const hasMarginCaption = Array.from(el.classList).find((className) => { + return className == "margin-caption"; + }); + if (hasMarginCaption) { + return true; + } + + return Array.from(el.classList).find((className) => { + return ( + className !== "column-body" && + !className.endsWith("container") && + className.startsWith("column-") && + !className.endsWith("left") + ); + }); + }); + + const kOverlapPaddingSize = 10; + function toRegions(els) { + return els.map((el) => { + const boundRect = el.getBoundingClientRect(); + const top = + boundRect.top + + document.documentElement.scrollTop - + kOverlapPaddingSize; + return { + top, + bottom: top + el.scrollHeight + 2 * kOverlapPaddingSize, + }; + }); + } + + let hasObserved = false; + const visibleItemObserver = (els) => { + let visibleElements = [...els]; + const intersectionObserver = new IntersectionObserver( + (entries, _observer) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + if (visibleElements.indexOf(entry.target) === -1) { + visibleElements.push(entry.target); + } + } else { + visibleElements = visibleElements.filter((visibleEntry) => { + return visibleEntry !== entry; + }); + } + }); + + if (!hasObserved) { + hideOverlappedSidebars(); + } + hasObserved = true; + }, + {} + ); + els.forEach((el) => { + intersectionObserver.observe(el); + }); + + return { + getVisibleEntries: () => { + return visibleElements; + }, + }; + }; + + const rightElementObserver = visibleItemObserver(rightSideConflictEls); + const leftElementObserver = visibleItemObserver(leftSideConflictEls); + + const hideOverlappedSidebars = () => { + marginScrollVisibility(toRegions(rightElementObserver.getVisibleEntries())); + sidebarScrollVisiblity(toRegions(leftElementObserver.getVisibleEntries())); + if (tocLeftScrollVisibility) { + tocLeftScrollVisibility( + toRegions(leftElementObserver.getVisibleEntries()) + ); + } + }; + + window.quartoToggleReader = () => { + // Applies a slow class (or removes it) + // to update the transition speed + const slowTransition = (slow) => { + const manageTransition = (id, slow) => { + const el = document.getElementById(id); + if (el) { + if (slow) { + el.classList.add("slow"); + } else { + el.classList.remove("slow"); + } + } + }; + + manageTransition("TOC", slow); + manageTransition("quarto-sidebar", slow); + }; + const readerMode = !isReaderMode(); + setReaderModeValue(readerMode); + + // If we're entering reader mode, slow the transition + if (readerMode) { + slowTransition(readerMode); + } + highlightReaderToggle(readerMode); + hideOverlappedSidebars(); + + // If we're exiting reader mode, restore the non-slow transition + if (!readerMode) { + slowTransition(!readerMode); + } + }; + + const highlightReaderToggle = (readerMode) => { + const els = document.querySelectorAll(".quarto-reader-toggle"); + if (els) { + els.forEach((el) => { + if (readerMode) { + el.classList.add("reader"); + } else { + el.classList.remove("reader"); + } + }); + } + }; + + const setReaderModeValue = (val) => { + if (window.location.protocol !== "file:") { + window.localStorage.setItem("quarto-reader-mode", val); + } else { + localReaderMode = val; + } + }; + + const isReaderMode = () => { + if (window.location.protocol !== "file:") { + return window.localStorage.getItem("quarto-reader-mode") === "true"; + } else { + return localReaderMode; + } + }; + let localReaderMode = null; + + const tocOpenDepthStr = tocEl?.getAttribute("data-toc-expanded"); + const tocOpenDepth = tocOpenDepthStr ? Number(tocOpenDepthStr) : 1; + + // Walk the TOC and collapse/expand nodes + // Nodes are expanded if: + // - they are top level + // - they have children that are 'active' links + // - they are directly below an link that is 'active' + const walk = (el, depth) => { + // Tick depth when we enter a UL + if (el.tagName === "UL") { + depth = depth + 1; + } + + // It this is active link + let isActiveNode = false; + if (el.tagName === "A" && el.classList.contains("active")) { + isActiveNode = true; + } + + // See if there is an active child to this element + let hasActiveChild = false; + for (child of el.children) { + hasActiveChild = walk(child, depth) || hasActiveChild; + } + + // Process the collapse state if this is an UL + if (el.tagName === "UL") { + if (tocOpenDepth === -1 && depth > 1) { + // toc-expand: false + el.classList.add("collapse"); + } else if ( + depth <= tocOpenDepth || + hasActiveChild || + prevSiblingIsActiveLink(el) + ) { + el.classList.remove("collapse"); + } else { + el.classList.add("collapse"); + } + + // untick depth when we leave a UL + depth = depth - 1; + } + return hasActiveChild || isActiveNode; + }; + + // walk the TOC and expand / collapse any items that should be shown + if (tocEl) { + updateActiveLink(); + walk(tocEl, 0); + } + + // Throttle the scroll event and walk peridiocally + window.document.addEventListener( + "scroll", + throttle(() => { + if (tocEl) { + updateActiveLink(); + walk(tocEl, 0); + } + if (!isReaderMode()) { + hideOverlappedSidebars(); + } + }, 5) + ); + window.addEventListener( + "resize", + throttle(() => { + if (tocEl) { + updateActiveLink(); + walk(tocEl, 0); + } + if (!isReaderMode()) { + hideOverlappedSidebars(); + } + }, 10) + ); + hideOverlappedSidebars(); + highlightReaderToggle(isReaderMode()); +}); + +// grouped tabsets +window.addEventListener("pageshow", (_event) => { + function getTabSettings() { + const data = localStorage.getItem("quarto-persistent-tabsets-data"); + if (!data) { + localStorage.setItem("quarto-persistent-tabsets-data", "{}"); + return {}; + } + if (data) { + return JSON.parse(data); + } + } + + function setTabSettings(data) { + localStorage.setItem( + "quarto-persistent-tabsets-data", + JSON.stringify(data) + ); + } + + function setTabState(groupName, groupValue) { + const data = getTabSettings(); + data[groupName] = groupValue; + setTabSettings(data); + } + + function toggleTab(tab, active) { + const tabPanelId = tab.getAttribute("aria-controls"); + const tabPanel = document.getElementById(tabPanelId); + if (active) { + tab.classList.add("active"); + tabPanel.classList.add("active"); + } else { + tab.classList.remove("active"); + tabPanel.classList.remove("active"); + } + } + + function toggleAll(selectedGroup, selectorsToSync) { + for (const [thisGroup, tabs] of Object.entries(selectorsToSync)) { + const active = selectedGroup === thisGroup; + for (const tab of tabs) { + toggleTab(tab, active); + } + } + } + + function findSelectorsToSyncByLanguage() { + const result = {}; + const tabs = Array.from( + document.querySelectorAll(`div[data-group] a[id^='tabset-']`) + ); + for (const item of tabs) { + const div = item.parentElement.parentElement.parentElement; + const group = div.getAttribute("data-group"); + if (!result[group]) { + result[group] = {}; + } + const selectorsToSync = result[group]; + const value = item.innerHTML; + if (!selectorsToSync[value]) { + selectorsToSync[value] = []; + } + selectorsToSync[value].push(item); + } + return result; + } + + function setupSelectorSync() { + const selectorsToSync = findSelectorsToSyncByLanguage(); + Object.entries(selectorsToSync).forEach(([group, tabSetsByValue]) => { + Object.entries(tabSetsByValue).forEach(([value, items]) => { + items.forEach((item) => { + item.addEventListener("click", (_event) => { + setTabState(group, value); + toggleAll(value, selectorsToSync[group]); + }); + }); + }); + }); + return selectorsToSync; + } + + const selectorsToSync = setupSelectorSync(); + for (const [group, selectedName] of Object.entries(getTabSettings())) { + const selectors = selectorsToSync[group]; + // it's possible that stale state gives us empty selections, so we explicitly check here. + if (selectors) { + toggleAll(selectedName, selectors); + } + } +}); + +function throttle(func, wait) { + let waiting = false; + return function () { + if (!waiting) { + func.apply(this, arguments); + waiting = true; + setTimeout(function () { + waiting = false; + }, wait); + } + }; +} + +function nexttick(func) { + return setTimeout(func, 0); +} diff --git a/site_libs/quarto-html/tippy.css b/site_libs/quarto-html/tippy.css new file mode 100644 index 00000000..e6ae635c --- /dev/null +++ b/site_libs/quarto-html/tippy.css @@ -0,0 +1 @@ +.tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{position:relative;background-color:#333;color:#fff;border-radius:4px;font-size:14px;line-height:1.4;white-space:normal;outline:0;transition-property:transform,visibility,opacity}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:initial;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-7px;left:0;border-width:0 8px 8px;border-bottom-color:initial;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-width:8px 0 8px 8px;border-left-color:initial;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-7px;border-width:8px 8px 8px 0;border-right-color:initial;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{width:16px;height:16px;color:#333}.tippy-arrow:before{content:"";position:absolute;border-color:transparent;border-style:solid}.tippy-content{position:relative;padding:5px 9px;z-index:1} \ No newline at end of file diff --git a/site_libs/quarto-html/tippy.umd.min.js b/site_libs/quarto-html/tippy.umd.min.js new file mode 100644 index 00000000..ca292be3 --- /dev/null +++ b/site_libs/quarto-html/tippy.umd.min.js @@ -0,0 +1,2 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("@popperjs/core")):"function"==typeof define&&define.amd?define(["@popperjs/core"],t):(e=e||self).tippy=t(e.Popper)}(this,(function(e){"use strict";var t={passive:!0,capture:!0},n=function(){return document.body};function r(e,t,n){if(Array.isArray(e)){var r=e[t];return null==r?Array.isArray(n)?n[t]:n:r}return e}function o(e,t){var n={}.toString.call(e);return 0===n.indexOf("[object")&&n.indexOf(t+"]")>-1}function i(e,t){return"function"==typeof e?e.apply(void 0,t):e}function a(e,t){return 0===t?e:function(r){clearTimeout(n),n=setTimeout((function(){e(r)}),t)};var n}function s(e,t){var n=Object.assign({},e);return t.forEach((function(e){delete n[e]})),n}function u(e){return[].concat(e)}function c(e,t){-1===e.indexOf(t)&&e.push(t)}function p(e){return e.split("-")[0]}function f(e){return[].slice.call(e)}function l(e){return Object.keys(e).reduce((function(t,n){return void 0!==e[n]&&(t[n]=e[n]),t}),{})}function d(){return document.createElement("div")}function v(e){return["Element","Fragment"].some((function(t){return o(e,t)}))}function m(e){return o(e,"MouseEvent")}function g(e){return!(!e||!e._tippy||e._tippy.reference!==e)}function h(e){return v(e)?[e]:function(e){return o(e,"NodeList")}(e)?f(e):Array.isArray(e)?e:f(document.querySelectorAll(e))}function b(e,t){e.forEach((function(e){e&&(e.style.transitionDuration=t+"ms")}))}function y(e,t){e.forEach((function(e){e&&e.setAttribute("data-state",t)}))}function w(e){var t,n=u(e)[0];return null!=n&&null!=(t=n.ownerDocument)&&t.body?n.ownerDocument:document}function E(e,t,n){var r=t+"EventListener";["transitionend","webkitTransitionEnd"].forEach((function(t){e[r](t,n)}))}function O(e,t){for(var n=t;n;){var r;if(e.contains(n))return!0;n=null==n.getRootNode||null==(r=n.getRootNode())?void 0:r.host}return!1}var x={isTouch:!1},C=0;function T(){x.isTouch||(x.isTouch=!0,window.performance&&document.addEventListener("mousemove",A))}function A(){var e=performance.now();e-C<20&&(x.isTouch=!1,document.removeEventListener("mousemove",A)),C=e}function L(){var e=document.activeElement;if(g(e)){var t=e._tippy;e.blur&&!t.state.isVisible&&e.blur()}}var D=!!("undefined"!=typeof window&&"undefined"!=typeof document)&&!!window.msCrypto,R=Object.assign({appendTo:n,aria:{content:"auto",expanded:"auto"},delay:0,duration:[300,250],getReferenceClientRect:null,hideOnClick:!0,ignoreAttributes:!1,interactive:!1,interactiveBorder:2,interactiveDebounce:0,moveTransition:"",offset:[0,10],onAfterUpdate:function(){},onBeforeUpdate:function(){},onCreate:function(){},onDestroy:function(){},onHidden:function(){},onHide:function(){},onMount:function(){},onShow:function(){},onShown:function(){},onTrigger:function(){},onUntrigger:function(){},onClickOutside:function(){},placement:"top",plugins:[],popperOptions:{},render:null,showOnCreate:!1,touch:!0,trigger:"mouseenter focus",triggerTarget:null},{animateFill:!1,followCursor:!1,inlinePositioning:!1,sticky:!1},{allowHTML:!1,animation:"fade",arrow:!0,content:"",inertia:!1,maxWidth:350,role:"tooltip",theme:"",zIndex:9999}),k=Object.keys(R);function P(e){var t=(e.plugins||[]).reduce((function(t,n){var r,o=n.name,i=n.defaultValue;o&&(t[o]=void 0!==e[o]?e[o]:null!=(r=R[o])?r:i);return t}),{});return Object.assign({},e,t)}function j(e,t){var n=Object.assign({},t,{content:i(t.content,[e])},t.ignoreAttributes?{}:function(e,t){return(t?Object.keys(P(Object.assign({},R,{plugins:t}))):k).reduce((function(t,n){var r=(e.getAttribute("data-tippy-"+n)||"").trim();if(!r)return t;if("content"===n)t[n]=r;else try{t[n]=JSON.parse(r)}catch(e){t[n]=r}return t}),{})}(e,t.plugins));return n.aria=Object.assign({},R.aria,n.aria),n.aria={expanded:"auto"===n.aria.expanded?t.interactive:n.aria.expanded,content:"auto"===n.aria.content?t.interactive?null:"describedby":n.aria.content},n}function M(e,t){e.innerHTML=t}function V(e){var t=d();return!0===e?t.className="tippy-arrow":(t.className="tippy-svg-arrow",v(e)?t.appendChild(e):M(t,e)),t}function I(e,t){v(t.content)?(M(e,""),e.appendChild(t.content)):"function"!=typeof t.content&&(t.allowHTML?M(e,t.content):e.textContent=t.content)}function S(e){var t=e.firstElementChild,n=f(t.children);return{box:t,content:n.find((function(e){return e.classList.contains("tippy-content")})),arrow:n.find((function(e){return e.classList.contains("tippy-arrow")||e.classList.contains("tippy-svg-arrow")})),backdrop:n.find((function(e){return e.classList.contains("tippy-backdrop")}))}}function N(e){var t=d(),n=d();n.className="tippy-box",n.setAttribute("data-state","hidden"),n.setAttribute("tabindex","-1");var r=d();function o(n,r){var o=S(t),i=o.box,a=o.content,s=o.arrow;r.theme?i.setAttribute("data-theme",r.theme):i.removeAttribute("data-theme"),"string"==typeof r.animation?i.setAttribute("data-animation",r.animation):i.removeAttribute("data-animation"),r.inertia?i.setAttribute("data-inertia",""):i.removeAttribute("data-inertia"),i.style.maxWidth="number"==typeof r.maxWidth?r.maxWidth+"px":r.maxWidth,r.role?i.setAttribute("role",r.role):i.removeAttribute("role"),n.content===r.content&&n.allowHTML===r.allowHTML||I(a,e.props),r.arrow?s?n.arrow!==r.arrow&&(i.removeChild(s),i.appendChild(V(r.arrow))):i.appendChild(V(r.arrow)):s&&i.removeChild(s)}return r.className="tippy-content",r.setAttribute("data-state","hidden"),I(r,e.props),t.appendChild(n),n.appendChild(r),o(e.props,e.props),{popper:t,onUpdate:o}}N.$$tippy=!0;var B=1,H=[],U=[];function _(o,s){var v,g,h,C,T,A,L,k,M=j(o,Object.assign({},R,P(l(s)))),V=!1,I=!1,N=!1,_=!1,F=[],W=a(we,M.interactiveDebounce),X=B++,Y=(k=M.plugins).filter((function(e,t){return k.indexOf(e)===t})),$={id:X,reference:o,popper:d(),popperInstance:null,props:M,state:{isEnabled:!0,isVisible:!1,isDestroyed:!1,isMounted:!1,isShown:!1},plugins:Y,clearDelayTimeouts:function(){clearTimeout(v),clearTimeout(g),cancelAnimationFrame(h)},setProps:function(e){if($.state.isDestroyed)return;ae("onBeforeUpdate",[$,e]),be();var t=$.props,n=j(o,Object.assign({},t,l(e),{ignoreAttributes:!0}));$.props=n,he(),t.interactiveDebounce!==n.interactiveDebounce&&(ce(),W=a(we,n.interactiveDebounce));t.triggerTarget&&!n.triggerTarget?u(t.triggerTarget).forEach((function(e){e.removeAttribute("aria-expanded")})):n.triggerTarget&&o.removeAttribute("aria-expanded");ue(),ie(),J&&J(t,n);$.popperInstance&&(Ce(),Ae().forEach((function(e){requestAnimationFrame(e._tippy.popperInstance.forceUpdate)})));ae("onAfterUpdate",[$,e])},setContent:function(e){$.setProps({content:e})},show:function(){var e=$.state.isVisible,t=$.state.isDestroyed,o=!$.state.isEnabled,a=x.isTouch&&!$.props.touch,s=r($.props.duration,0,R.duration);if(e||t||o||a)return;if(te().hasAttribute("disabled"))return;if(ae("onShow",[$],!1),!1===$.props.onShow($))return;$.state.isVisible=!0,ee()&&(z.style.visibility="visible");ie(),de(),$.state.isMounted||(z.style.transition="none");if(ee()){var u=re(),p=u.box,f=u.content;b([p,f],0)}A=function(){var e;if($.state.isVisible&&!_){if(_=!0,z.offsetHeight,z.style.transition=$.props.moveTransition,ee()&&$.props.animation){var t=re(),n=t.box,r=t.content;b([n,r],s),y([n,r],"visible")}se(),ue(),c(U,$),null==(e=$.popperInstance)||e.forceUpdate(),ae("onMount",[$]),$.props.animation&&ee()&&function(e,t){me(e,t)}(s,(function(){$.state.isShown=!0,ae("onShown",[$])}))}},function(){var e,t=$.props.appendTo,r=te();e=$.props.interactive&&t===n||"parent"===t?r.parentNode:i(t,[r]);e.contains(z)||e.appendChild(z);$.state.isMounted=!0,Ce()}()},hide:function(){var e=!$.state.isVisible,t=$.state.isDestroyed,n=!$.state.isEnabled,o=r($.props.duration,1,R.duration);if(e||t||n)return;if(ae("onHide",[$],!1),!1===$.props.onHide($))return;$.state.isVisible=!1,$.state.isShown=!1,_=!1,V=!1,ee()&&(z.style.visibility="hidden");if(ce(),ve(),ie(!0),ee()){var i=re(),a=i.box,s=i.content;$.props.animation&&(b([a,s],o),y([a,s],"hidden"))}se(),ue(),$.props.animation?ee()&&function(e,t){me(e,(function(){!$.state.isVisible&&z.parentNode&&z.parentNode.contains(z)&&t()}))}(o,$.unmount):$.unmount()},hideWithInteractivity:function(e){ne().addEventListener("mousemove",W),c(H,W),W(e)},enable:function(){$.state.isEnabled=!0},disable:function(){$.hide(),$.state.isEnabled=!1},unmount:function(){$.state.isVisible&&$.hide();if(!$.state.isMounted)return;Te(),Ae().forEach((function(e){e._tippy.unmount()})),z.parentNode&&z.parentNode.removeChild(z);U=U.filter((function(e){return e!==$})),$.state.isMounted=!1,ae("onHidden",[$])},destroy:function(){if($.state.isDestroyed)return;$.clearDelayTimeouts(),$.unmount(),be(),delete o._tippy,$.state.isDestroyed=!0,ae("onDestroy",[$])}};if(!M.render)return $;var q=M.render($),z=q.popper,J=q.onUpdate;z.setAttribute("data-tippy-root",""),z.id="tippy-"+$.id,$.popper=z,o._tippy=$,z._tippy=$;var G=Y.map((function(e){return e.fn($)})),K=o.hasAttribute("aria-expanded");return he(),ue(),ie(),ae("onCreate",[$]),M.showOnCreate&&Le(),z.addEventListener("mouseenter",(function(){$.props.interactive&&$.state.isVisible&&$.clearDelayTimeouts()})),z.addEventListener("mouseleave",(function(){$.props.interactive&&$.props.trigger.indexOf("mouseenter")>=0&&ne().addEventListener("mousemove",W)})),$;function Q(){var e=$.props.touch;return Array.isArray(e)?e:[e,0]}function Z(){return"hold"===Q()[0]}function ee(){var e;return!(null==(e=$.props.render)||!e.$$tippy)}function te(){return L||o}function ne(){var e=te().parentNode;return e?w(e):document}function re(){return S(z)}function oe(e){return $.state.isMounted&&!$.state.isVisible||x.isTouch||C&&"focus"===C.type?0:r($.props.delay,e?0:1,R.delay)}function ie(e){void 0===e&&(e=!1),z.style.pointerEvents=$.props.interactive&&!e?"":"none",z.style.zIndex=""+$.props.zIndex}function ae(e,t,n){var r;(void 0===n&&(n=!0),G.forEach((function(n){n[e]&&n[e].apply(n,t)})),n)&&(r=$.props)[e].apply(r,t)}function se(){var e=$.props.aria;if(e.content){var t="aria-"+e.content,n=z.id;u($.props.triggerTarget||o).forEach((function(e){var r=e.getAttribute(t);if($.state.isVisible)e.setAttribute(t,r?r+" "+n:n);else{var o=r&&r.replace(n,"").trim();o?e.setAttribute(t,o):e.removeAttribute(t)}}))}}function ue(){!K&&$.props.aria.expanded&&u($.props.triggerTarget||o).forEach((function(e){$.props.interactive?e.setAttribute("aria-expanded",$.state.isVisible&&e===te()?"true":"false"):e.removeAttribute("aria-expanded")}))}function ce(){ne().removeEventListener("mousemove",W),H=H.filter((function(e){return e!==W}))}function pe(e){if(!x.isTouch||!N&&"mousedown"!==e.type){var t=e.composedPath&&e.composedPath()[0]||e.target;if(!$.props.interactive||!O(z,t)){if(u($.props.triggerTarget||o).some((function(e){return O(e,t)}))){if(x.isTouch)return;if($.state.isVisible&&$.props.trigger.indexOf("click")>=0)return}else ae("onClickOutside",[$,e]);!0===$.props.hideOnClick&&($.clearDelayTimeouts(),$.hide(),I=!0,setTimeout((function(){I=!1})),$.state.isMounted||ve())}}}function fe(){N=!0}function le(){N=!1}function de(){var e=ne();e.addEventListener("mousedown",pe,!0),e.addEventListener("touchend",pe,t),e.addEventListener("touchstart",le,t),e.addEventListener("touchmove",fe,t)}function ve(){var e=ne();e.removeEventListener("mousedown",pe,!0),e.removeEventListener("touchend",pe,t),e.removeEventListener("touchstart",le,t),e.removeEventListener("touchmove",fe,t)}function me(e,t){var n=re().box;function r(e){e.target===n&&(E(n,"remove",r),t())}if(0===e)return t();E(n,"remove",T),E(n,"add",r),T=r}function ge(e,t,n){void 0===n&&(n=!1),u($.props.triggerTarget||o).forEach((function(r){r.addEventListener(e,t,n),F.push({node:r,eventType:e,handler:t,options:n})}))}function he(){var e;Z()&&(ge("touchstart",ye,{passive:!0}),ge("touchend",Ee,{passive:!0})),(e=$.props.trigger,e.split(/\s+/).filter(Boolean)).forEach((function(e){if("manual"!==e)switch(ge(e,ye),e){case"mouseenter":ge("mouseleave",Ee);break;case"focus":ge(D?"focusout":"blur",Oe);break;case"focusin":ge("focusout",Oe)}}))}function be(){F.forEach((function(e){var t=e.node,n=e.eventType,r=e.handler,o=e.options;t.removeEventListener(n,r,o)})),F=[]}function ye(e){var t,n=!1;if($.state.isEnabled&&!xe(e)&&!I){var r="focus"===(null==(t=C)?void 0:t.type);C=e,L=e.currentTarget,ue(),!$.state.isVisible&&m(e)&&H.forEach((function(t){return t(e)})),"click"===e.type&&($.props.trigger.indexOf("mouseenter")<0||V)&&!1!==$.props.hideOnClick&&$.state.isVisible?n=!0:Le(e),"click"===e.type&&(V=!n),n&&!r&&De(e)}}function we(e){var t=e.target,n=te().contains(t)||z.contains(t);"mousemove"===e.type&&n||function(e,t){var n=t.clientX,r=t.clientY;return e.every((function(e){var t=e.popperRect,o=e.popperState,i=e.props.interactiveBorder,a=p(o.placement),s=o.modifiersData.offset;if(!s)return!0;var u="bottom"===a?s.top.y:0,c="top"===a?s.bottom.y:0,f="right"===a?s.left.x:0,l="left"===a?s.right.x:0,d=t.top-r+u>i,v=r-t.bottom-c>i,m=t.left-n+f>i,g=n-t.right-l>i;return d||v||m||g}))}(Ae().concat(z).map((function(e){var t,n=null==(t=e._tippy.popperInstance)?void 0:t.state;return n?{popperRect:e.getBoundingClientRect(),popperState:n,props:M}:null})).filter(Boolean),e)&&(ce(),De(e))}function Ee(e){xe(e)||$.props.trigger.indexOf("click")>=0&&V||($.props.interactive?$.hideWithInteractivity(e):De(e))}function Oe(e){$.props.trigger.indexOf("focusin")<0&&e.target!==te()||$.props.interactive&&e.relatedTarget&&z.contains(e.relatedTarget)||De(e)}function xe(e){return!!x.isTouch&&Z()!==e.type.indexOf("touch")>=0}function Ce(){Te();var t=$.props,n=t.popperOptions,r=t.placement,i=t.offset,a=t.getReferenceClientRect,s=t.moveTransition,u=ee()?S(z).arrow:null,c=a?{getBoundingClientRect:a,contextElement:a.contextElement||te()}:o,p=[{name:"offset",options:{offset:i}},{name:"preventOverflow",options:{padding:{top:2,bottom:2,left:5,right:5}}},{name:"flip",options:{padding:5}},{name:"computeStyles",options:{adaptive:!s}},{name:"$$tippy",enabled:!0,phase:"beforeWrite",requires:["computeStyles"],fn:function(e){var t=e.state;if(ee()){var n=re().box;["placement","reference-hidden","escaped"].forEach((function(e){"placement"===e?n.setAttribute("data-placement",t.placement):t.attributes.popper["data-popper-"+e]?n.setAttribute("data-"+e,""):n.removeAttribute("data-"+e)})),t.attributes.popper={}}}}];ee()&&u&&p.push({name:"arrow",options:{element:u,padding:3}}),p.push.apply(p,(null==n?void 0:n.modifiers)||[]),$.popperInstance=e.createPopper(c,z,Object.assign({},n,{placement:r,onFirstUpdate:A,modifiers:p}))}function Te(){$.popperInstance&&($.popperInstance.destroy(),$.popperInstance=null)}function Ae(){return f(z.querySelectorAll("[data-tippy-root]"))}function Le(e){$.clearDelayTimeouts(),e&&ae("onTrigger",[$,e]),de();var t=oe(!0),n=Q(),r=n[0],o=n[1];x.isTouch&&"hold"===r&&o&&(t=o),t?v=setTimeout((function(){$.show()}),t):$.show()}function De(e){if($.clearDelayTimeouts(),ae("onUntrigger",[$,e]),$.state.isVisible){if(!($.props.trigger.indexOf("mouseenter")>=0&&$.props.trigger.indexOf("click")>=0&&["mouseleave","mousemove"].indexOf(e.type)>=0&&V)){var t=oe(!1);t?g=setTimeout((function(){$.state.isVisible&&$.hide()}),t):h=requestAnimationFrame((function(){$.hide()}))}}else ve()}}function F(e,n){void 0===n&&(n={});var r=R.plugins.concat(n.plugins||[]);document.addEventListener("touchstart",T,t),window.addEventListener("blur",L);var o=Object.assign({},n,{plugins:r}),i=h(e).reduce((function(e,t){var n=t&&_(t,o);return n&&e.push(n),e}),[]);return v(e)?i[0]:i}F.defaultProps=R,F.setDefaultProps=function(e){Object.keys(e).forEach((function(t){R[t]=e[t]}))},F.currentInput=x;var W=Object.assign({},e.applyStyles,{effect:function(e){var t=e.state,n={popper:{position:t.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};Object.assign(t.elements.popper.style,n.popper),t.styles=n,t.elements.arrow&&Object.assign(t.elements.arrow.style,n.arrow)}}),X={mouseover:"mouseenter",focusin:"focus",click:"click"};var Y={name:"animateFill",defaultValue:!1,fn:function(e){var t;if(null==(t=e.props.render)||!t.$$tippy)return{};var n=S(e.popper),r=n.box,o=n.content,i=e.props.animateFill?function(){var e=d();return e.className="tippy-backdrop",y([e],"hidden"),e}():null;return{onCreate:function(){i&&(r.insertBefore(i,r.firstElementChild),r.setAttribute("data-animatefill",""),r.style.overflow="hidden",e.setProps({arrow:!1,animation:"shift-away"}))},onMount:function(){if(i){var e=r.style.transitionDuration,t=Number(e.replace("ms",""));o.style.transitionDelay=Math.round(t/10)+"ms",i.style.transitionDuration=e,y([i],"visible")}},onShow:function(){i&&(i.style.transitionDuration="0ms")},onHide:function(){i&&y([i],"hidden")}}}};var $={clientX:0,clientY:0},q=[];function z(e){var t=e.clientX,n=e.clientY;$={clientX:t,clientY:n}}var J={name:"followCursor",defaultValue:!1,fn:function(e){var t=e.reference,n=w(e.props.triggerTarget||t),r=!1,o=!1,i=!0,a=e.props;function s(){return"initial"===e.props.followCursor&&e.state.isVisible}function u(){n.addEventListener("mousemove",f)}function c(){n.removeEventListener("mousemove",f)}function p(){r=!0,e.setProps({getReferenceClientRect:null}),r=!1}function f(n){var r=!n.target||t.contains(n.target),o=e.props.followCursor,i=n.clientX,a=n.clientY,s=t.getBoundingClientRect(),u=i-s.left,c=a-s.top;!r&&e.props.interactive||e.setProps({getReferenceClientRect:function(){var e=t.getBoundingClientRect(),n=i,r=a;"initial"===o&&(n=e.left+u,r=e.top+c);var s="horizontal"===o?e.top:r,p="vertical"===o?e.right:n,f="horizontal"===o?e.bottom:r,l="vertical"===o?e.left:n;return{width:p-l,height:f-s,top:s,right:p,bottom:f,left:l}}})}function l(){e.props.followCursor&&(q.push({instance:e,doc:n}),function(e){e.addEventListener("mousemove",z)}(n))}function d(){0===(q=q.filter((function(t){return t.instance!==e}))).filter((function(e){return e.doc===n})).length&&function(e){e.removeEventListener("mousemove",z)}(n)}return{onCreate:l,onDestroy:d,onBeforeUpdate:function(){a=e.props},onAfterUpdate:function(t,n){var i=n.followCursor;r||void 0!==i&&a.followCursor!==i&&(d(),i?(l(),!e.state.isMounted||o||s()||u()):(c(),p()))},onMount:function(){e.props.followCursor&&!o&&(i&&(f($),i=!1),s()||u())},onTrigger:function(e,t){m(t)&&($={clientX:t.clientX,clientY:t.clientY}),o="focus"===t.type},onHidden:function(){e.props.followCursor&&(p(),c(),i=!0)}}}};var G={name:"inlinePositioning",defaultValue:!1,fn:function(e){var t,n=e.reference;var r=-1,o=!1,i=[],a={name:"tippyInlinePositioning",enabled:!0,phase:"afterWrite",fn:function(o){var a=o.state;e.props.inlinePositioning&&(-1!==i.indexOf(a.placement)&&(i=[]),t!==a.placement&&-1===i.indexOf(a.placement)&&(i.push(a.placement),e.setProps({getReferenceClientRect:function(){return function(e){return function(e,t,n,r){if(n.length<2||null===e)return t;if(2===n.length&&r>=0&&n[0].left>n[1].right)return n[r]||t;switch(e){case"top":case"bottom":var o=n[0],i=n[n.length-1],a="top"===e,s=o.top,u=i.bottom,c=a?o.left:i.left,p=a?o.right:i.right;return{top:s,bottom:u,left:c,right:p,width:p-c,height:u-s};case"left":case"right":var f=Math.min.apply(Math,n.map((function(e){return e.left}))),l=Math.max.apply(Math,n.map((function(e){return e.right}))),d=n.filter((function(t){return"left"===e?t.left===f:t.right===l})),v=d[0].top,m=d[d.length-1].bottom;return{top:v,bottom:m,left:f,right:l,width:l-f,height:m-v};default:return t}}(p(e),n.getBoundingClientRect(),f(n.getClientRects()),r)}(a.placement)}})),t=a.placement)}};function s(){var t;o||(t=function(e,t){var n;return{popperOptions:Object.assign({},e.popperOptions,{modifiers:[].concat(((null==(n=e.popperOptions)?void 0:n.modifiers)||[]).filter((function(e){return e.name!==t.name})),[t])})}}(e.props,a),o=!0,e.setProps(t),o=!1)}return{onCreate:s,onAfterUpdate:s,onTrigger:function(t,n){if(m(n)){var o=f(e.reference.getClientRects()),i=o.find((function(e){return e.left-2<=n.clientX&&e.right+2>=n.clientX&&e.top-2<=n.clientY&&e.bottom+2>=n.clientY})),a=o.indexOf(i);r=a>-1?a:r}},onHidden:function(){r=-1}}}};var K={name:"sticky",defaultValue:!1,fn:function(e){var t=e.reference,n=e.popper;function r(t){return!0===e.props.sticky||e.props.sticky===t}var o=null,i=null;function a(){var s=r("reference")?(e.popperInstance?e.popperInstance.state.elements.reference:t).getBoundingClientRect():null,u=r("popper")?n.getBoundingClientRect():null;(s&&Q(o,s)||u&&Q(i,u))&&e.popperInstance&&e.popperInstance.update(),o=s,i=u,e.state.isMounted&&requestAnimationFrame(a)}return{onMount:function(){e.props.sticky&&a()}}}};function Q(e,t){return!e||!t||(e.top!==t.top||e.right!==t.right||e.bottom!==t.bottom||e.left!==t.left)}return F.setDefaultProps({plugins:[Y,J,G,K],render:N}),F.createSingleton=function(e,t){var n;void 0===t&&(t={});var r,o=e,i=[],a=[],c=t.overrides,p=[],f=!1;function l(){a=o.map((function(e){return u(e.props.triggerTarget||e.reference)})).reduce((function(e,t){return e.concat(t)}),[])}function v(){i=o.map((function(e){return e.reference}))}function m(e){o.forEach((function(t){e?t.enable():t.disable()}))}function g(e){return o.map((function(t){var n=t.setProps;return t.setProps=function(o){n(o),t.reference===r&&e.setProps(o)},function(){t.setProps=n}}))}function h(e,t){var n=a.indexOf(t);if(t!==r){r=t;var s=(c||[]).concat("content").reduce((function(e,t){return e[t]=o[n].props[t],e}),{});e.setProps(Object.assign({},s,{getReferenceClientRect:"function"==typeof s.getReferenceClientRect?s.getReferenceClientRect:function(){var e;return null==(e=i[n])?void 0:e.getBoundingClientRect()}}))}}m(!1),v(),l();var b={fn:function(){return{onDestroy:function(){m(!0)},onHidden:function(){r=null},onClickOutside:function(e){e.props.showOnCreate&&!f&&(f=!0,r=null)},onShow:function(e){e.props.showOnCreate&&!f&&(f=!0,h(e,i[0]))},onTrigger:function(e,t){h(e,t.currentTarget)}}}},y=F(d(),Object.assign({},s(t,["overrides"]),{plugins:[b].concat(t.plugins||[]),triggerTarget:a,popperOptions:Object.assign({},t.popperOptions,{modifiers:[].concat((null==(n=t.popperOptions)?void 0:n.modifiers)||[],[W])})})),w=y.show;y.show=function(e){if(w(),!r&&null==e)return h(y,i[0]);if(!r||null!=e){if("number"==typeof e)return i[e]&&h(y,i[e]);if(o.indexOf(e)>=0){var t=e.reference;return h(y,t)}return i.indexOf(e)>=0?h(y,e):void 0}},y.showNext=function(){var e=i[0];if(!r)return y.show(0);var t=i.indexOf(r);y.show(i[t+1]||e)},y.showPrevious=function(){var e=i[i.length-1];if(!r)return y.show(e);var t=i.indexOf(r),n=i[t-1]||e;y.show(n)};var E=y.setProps;return y.setProps=function(e){c=e.overrides||c,E(e)},y.setInstances=function(e){m(!0),p.forEach((function(e){return e()})),o=e,m(!1),v(),l(),p=g(y),y.setProps({triggerTarget:a})},p=g(y),y},F.delegate=function(e,n){var r=[],o=[],i=!1,a=n.target,c=s(n,["target"]),p=Object.assign({},c,{trigger:"manual",touch:!1}),f=Object.assign({touch:R.touch},c,{showOnCreate:!0}),l=F(e,p);function d(e){if(e.target&&!i){var t=e.target.closest(a);if(t){var r=t.getAttribute("data-tippy-trigger")||n.trigger||R.trigger;if(!t._tippy&&!("touchstart"===e.type&&"boolean"==typeof f.touch||"touchstart"!==e.type&&r.indexOf(X[e.type])<0)){var s=F(t,f);s&&(o=o.concat(s))}}}}function v(e,t,n,o){void 0===o&&(o=!1),e.addEventListener(t,n,o),r.push({node:e,eventType:t,handler:n,options:o})}return u(l).forEach((function(e){var n=e.destroy,a=e.enable,s=e.disable;e.destroy=function(e){void 0===e&&(e=!0),e&&o.forEach((function(e){e.destroy()})),o=[],r.forEach((function(e){var t=e.node,n=e.eventType,r=e.handler,o=e.options;t.removeEventListener(n,r,o)})),r=[],n()},e.enable=function(){a(),o.forEach((function(e){return e.enable()})),i=!1},e.disable=function(){s(),o.forEach((function(e){return e.disable()})),i=!0},function(e){var n=e.reference;v(n,"touchstart",d,t),v(n,"mouseover",d),v(n,"focusin",d),v(n,"click",d)}(e)})),l},F.hideAll=function(e){var t=void 0===e?{}:e,n=t.exclude,r=t.duration;U.forEach((function(e){var t=!1;if(n&&(t=g(n)?e.reference===n:e.popper===n.popper),!t){var o=e.props.duration;e.setProps({duration:r}),e.hide(),e.state.isDestroyed||e.setProps({duration:o})}}))},F.roundArrow='',F})); + diff --git a/site_libs/quarto-listing/list.min.js b/site_libs/quarto-listing/list.min.js new file mode 100644 index 00000000..511346fc --- /dev/null +++ b/site_libs/quarto-listing/list.min.js @@ -0,0 +1,2 @@ +var List;List=function(){var t={"./src/add-async.js":function(t){t.exports=function(t){return function e(r,n,s){var i=r.splice(0,50);s=(s=s||[]).concat(t.add(i)),r.length>0?setTimeout((function(){e(r,n,s)}),1):(t.update(),n(s))}}},"./src/filter.js":function(t){t.exports=function(t){return t.handlers.filterStart=t.handlers.filterStart||[],t.handlers.filterComplete=t.handlers.filterComplete||[],function(e){if(t.trigger("filterStart"),t.i=1,t.reset.filter(),void 0===e)t.filtered=!1;else{t.filtered=!0;for(var r=t.items,n=0,s=r.length;nv.page,a=new g(t[s],void 0,n),v.items.push(a),r.push(a)}return v.update(),r}m(t.slice(0),e)}},this.show=function(t,e){return this.i=t,this.page=e,v.update(),v},this.remove=function(t,e,r){for(var n=0,s=0,i=v.items.length;s-1&&r.splice(n,1),v},this.trigger=function(t){for(var e=v.handlers[t].length;e--;)v.handlers[t][e](v);return v},this.reset={filter:function(){for(var t=v.items,e=t.length;e--;)t[e].filtered=!1;return v},search:function(){for(var t=v.items,e=t.length;e--;)t[e].found=!1;return v}},this.update=function(){var t=v.items,e=t.length;v.visibleItems=[],v.matchingItems=[],v.templater.clear();for(var r=0;r=v.i&&v.visibleItems.lengthe},innerWindow:function(t,e,r){return t>=e-r&&t<=e+r},dotted:function(t,e,r,n,s,i,a){return this.dottedLeft(t,e,r,n,s,i)||this.dottedRight(t,e,r,n,s,i,a)},dottedLeft:function(t,e,r,n,s,i){return e==r+1&&!this.innerWindow(e,s,i)&&!this.right(e,n)},dottedRight:function(t,e,r,n,s,i,a){return!t.items[a-1].values().dotted&&(e==n&&!this.innerWindow(e,s,i)&&!this.right(e,n))}};return function(e){var n=new i(t.listContainer.id,{listClass:e.paginationClass||"pagination",item:e.item||"
  • ",valueNames:["page","dotted"],searchClass:"pagination-search-that-is-not-supposed-to-exist",sortClass:"pagination-sort-that-is-not-supposed-to-exist"});s.bind(n.listContainer,"click",(function(e){var r=e.target||e.srcElement,n=t.utils.getAttribute(r,"data-page"),s=t.utils.getAttribute(r,"data-i");s&&t.show((s-1)*n+1,n)})),t.on("updated",(function(){r(n,e)})),r(n,e)}}},"./src/parse.js":function(t,e,r){t.exports=function(t){var e=r("./src/item.js")(t),n=function(r,n){for(var s=0,i=r.length;s0?setTimeout((function(){e(r,s)}),1):(t.update(),t.trigger("parseComplete"))};return t.handlers.parseComplete=t.handlers.parseComplete||[],function(){var e=function(t){for(var e=t.childNodes,r=[],n=0,s=e.length;n]/g.exec(t)){var e=document.createElement("tbody");return e.innerHTML=t,e.firstElementChild}if(-1!==t.indexOf("<")){var r=document.createElement("div");return r.innerHTML=t,r.firstElementChild}}},a=function(e,r,n){var s=void 0,i=function(e){for(var r=0,n=t.valueNames.length;r=1;)t.list.removeChild(t.list.firstChild)},function(){var r;if("function"!=typeof t.item){if(!(r="string"==typeof t.item?-1===t.item.indexOf("<")?document.getElementById(t.item):i(t.item):s()))throw new Error("The list needs to have at least one item on init otherwise you'll have to add a template.");r=n(r,t.valueNames),e=function(){return r.cloneNode(!0)}}else e=function(e){var r=t.item(e);return i(r)}}()};t.exports=function(t){return new e(t)}},"./src/utils/classes.js":function(t,e,r){var n=r("./src/utils/index-of.js"),s=/\s+/;Object.prototype.toString;function i(t){if(!t||!t.nodeType)throw new Error("A DOM element reference is required");this.el=t,this.list=t.classList}t.exports=function(t){return new i(t)},i.prototype.add=function(t){if(this.list)return this.list.add(t),this;var e=this.array();return~n(e,t)||e.push(t),this.el.className=e.join(" "),this},i.prototype.remove=function(t){if(this.list)return this.list.remove(t),this;var e=this.array(),r=n(e,t);return~r&&e.splice(r,1),this.el.className=e.join(" "),this},i.prototype.toggle=function(t,e){return this.list?(void 0!==e?e!==this.list.toggle(t,e)&&this.list.toggle(t):this.list.toggle(t),this):(void 0!==e?e?this.add(t):this.remove(t):this.has(t)?this.remove(t):this.add(t),this)},i.prototype.array=function(){var t=(this.el.getAttribute("class")||"").replace(/^\s+|\s+$/g,"").split(s);return""===t[0]&&t.shift(),t},i.prototype.has=i.prototype.contains=function(t){return this.list?this.list.contains(t):!!~n(this.array(),t)}},"./src/utils/events.js":function(t,e,r){var n=window.addEventListener?"addEventListener":"attachEvent",s=window.removeEventListener?"removeEventListener":"detachEvent",i="addEventListener"!==n?"on":"",a=r("./src/utils/to-array.js");e.bind=function(t,e,r,s){for(var o=0,l=(t=a(t)).length;o32)return!1;var a=n,o=function(){var t,r={};for(t=0;t=p;b--){var j=o[t.charAt(b-1)];if(C[b]=0===m?(C[b+1]<<1|1)&j:(C[b+1]<<1|1)&j|(v[b+1]|v[b])<<1|1|v[b+1],C[b]&d){var x=l(m,b-1);if(x<=u){if(u=x,!((c=b-1)>a))break;p=Math.max(1,2*a-c)}}}if(l(m+1,a)>u)break;v=C}return!(c<0)}},"./src/utils/get-attribute.js":function(t){t.exports=function(t,e){var r=t.getAttribute&&t.getAttribute(e)||null;if(!r)for(var n=t.attributes,s=n.length,i=0;i=48&&t<=57}function i(t,e){for(var i=(t+="").length,a=(e+="").length,o=0,l=0;o=i&&l=a?-1:l>=a&&o=i?1:i-a}i.caseInsensitive=i.i=function(t,e){return i((""+t).toLowerCase(),(""+e).toLowerCase())},Object.defineProperties(i,{alphabet:{get:function(){return e},set:function(t){r=[];var s=0;if(e=t)for(;s { + if (categoriesLoaded) { + activateCategory(category); + setCategoryHash(category); + } +}; + +window["quarto-listing-loaded"] = () => { + // Process any existing hash + const hash = getHash(); + + if (hash) { + // If there is a category, switch to that + if (hash.category) { + activateCategory(hash.category); + } + // Paginate a specific listing + const listingIds = Object.keys(window["quarto-listings"]); + for (const listingId of listingIds) { + const page = hash[getListingPageKey(listingId)]; + if (page) { + showPage(listingId, page); + } + } + } + + const listingIds = Object.keys(window["quarto-listings"]); + for (const listingId of listingIds) { + // The actual list + const list = window["quarto-listings"][listingId]; + + // Update the handlers for pagination events + refreshPaginationHandlers(listingId); + + // Render any visible items that need it + renderVisibleProgressiveImages(list); + + // Whenever the list is updated, we also need to + // attach handlers to the new pagination elements + // and refresh any newly visible items. + list.on("updated", function () { + renderVisibleProgressiveImages(list); + setTimeout(() => refreshPaginationHandlers(listingId)); + + // Show or hide the no matching message + toggleNoMatchingMessage(list); + }); + } +}; + +window.document.addEventListener("DOMContentLoaded", function (_event) { + // Attach click handlers to categories + const categoryEls = window.document.querySelectorAll( + ".quarto-listing-category .category" + ); + + for (const categoryEl of categoryEls) { + const category = categoryEl.getAttribute("data-category"); + categoryEl.onclick = () => { + activateCategory(category); + setCategoryHash(category); + }; + } + + // Attach a click handler to the category title + // (there should be only one, but since it is a class name, handle N) + const categoryTitleEls = window.document.querySelectorAll( + ".quarto-listing-category-title" + ); + for (const categoryTitleEl of categoryTitleEls) { + categoryTitleEl.onclick = () => { + activateCategory(""); + setCategoryHash(""); + }; + } + + categoriesLoaded = true; +}); + +function toggleNoMatchingMessage(list) { + const selector = `#${list.listContainer.id} .listing-no-matching`; + const noMatchingEl = window.document.querySelector(selector); + if (noMatchingEl) { + if (list.visibleItems.length === 0) { + noMatchingEl.classList.remove("d-none"); + } else { + if (!noMatchingEl.classList.contains("d-none")) { + noMatchingEl.classList.add("d-none"); + } + } + } +} + +function setCategoryHash(category) { + setHash({ category }); +} + +function setPageHash(listingId, page) { + const currentHash = getHash() || {}; + currentHash[getListingPageKey(listingId)] = page; + setHash(currentHash); +} + +function getListingPageKey(listingId) { + return `${listingId}-page`; +} + +function refreshPaginationHandlers(listingId) { + const listingEl = window.document.getElementById(listingId); + const paginationEls = listingEl.querySelectorAll( + ".pagination li.page-item:not(.disabled) .page.page-link" + ); + for (const paginationEl of paginationEls) { + paginationEl.onclick = (sender) => { + setPageHash(listingId, sender.target.getAttribute("data-i")); + showPage(listingId, sender.target.getAttribute("data-i")); + return false; + }; + } +} + +function renderVisibleProgressiveImages(list) { + // Run through the visible items and render any progressive images + for (const item of list.visibleItems) { + const itemEl = item.elm; + if (itemEl) { + const progressiveImgs = itemEl.querySelectorAll( + `img[${kProgressiveAttr}]` + ); + for (const progressiveImg of progressiveImgs) { + const srcValue = progressiveImg.getAttribute(kProgressiveAttr); + if (srcValue) { + progressiveImg.setAttribute("src", srcValue); + } + progressiveImg.removeAttribute(kProgressiveAttr); + } + } + } +} + +function getHash() { + // Hashes are of the form + // #name:value|name1:value1|name2:value2 + const currentUrl = new URL(window.location); + const hashRaw = currentUrl.hash ? currentUrl.hash.slice(1) : undefined; + return parseHash(hashRaw); +} + +const kAnd = "&"; +const kEquals = "="; + +function parseHash(hash) { + if (!hash) { + return undefined; + } + const hasValuesStrs = hash.split(kAnd); + const hashValues = hasValuesStrs + .map((hashValueStr) => { + const vals = hashValueStr.split(kEquals); + if (vals.length === 2) { + return { name: vals[0], value: vals[1] }; + } else { + return undefined; + } + }) + .filter((value) => { + return value !== undefined; + }); + + const hashObj = {}; + hashValues.forEach((hashValue) => { + hashObj[hashValue.name] = decodeURIComponent(hashValue.value); + }); + return hashObj; +} + +function makeHash(obj) { + return Object.keys(obj) + .map((key) => { + return `${key}${kEquals}${obj[key]}`; + }) + .join(kAnd); +} + +function setHash(obj) { + const hash = makeHash(obj); + window.history.pushState(null, null, `#${hash}`); +} + +function showPage(listingId, page) { + const list = window["quarto-listings"][listingId]; + if (list) { + list.show((page - 1) * list.page + 1, list.page); + } +} + +function activateCategory(category) { + // Deactivate existing categories + const activeEls = window.document.querySelectorAll( + ".quarto-listing-category .category.active" + ); + for (const activeEl of activeEls) { + activeEl.classList.remove("active"); + } + + // Activate this category + const categoryEl = window.document.querySelector( + `.quarto-listing-category .category[data-category='${category}'` + ); + if (categoryEl) { + categoryEl.classList.add("active"); + } + + // Filter the listings to this category + filterListingCategory(category); +} + +function filterListingCategory(category) { + const listingIds = Object.keys(window["quarto-listings"]); + for (const listingId of listingIds) { + const list = window["quarto-listings"][listingId]; + if (list) { + if (category === "") { + // resets the filter + list.filter(); + } else { + // filter to this category + list.filter(function (item) { + const itemValues = item.values(); + if (itemValues.categories !== null) { + const categories = itemValues.categories.split(","); + return categories.includes(category); + } else { + return false; + } + }); + } + } + } +} diff --git a/site_libs/quarto-nav/quarto-nav.js b/site_libs/quarto-nav/quarto-nav.js new file mode 100644 index 00000000..38cc4305 --- /dev/null +++ b/site_libs/quarto-nav/quarto-nav.js @@ -0,0 +1,325 @@ +const headroomChanged = new CustomEvent("quarto-hrChanged", { + detail: {}, + bubbles: true, + cancelable: false, + composed: false, +}); + +const announceDismiss = () => { + const annEl = window.document.getElementById("quarto-announcement"); + if (annEl) { + annEl.remove(); + + const annId = annEl.getAttribute("data-announcement-id"); + window.localStorage.setItem(`quarto-announce-${annId}`, "true"); + } +}; + +const announceRegister = () => { + const annEl = window.document.getElementById("quarto-announcement"); + if (annEl) { + const annId = annEl.getAttribute("data-announcement-id"); + const isDismissed = + window.localStorage.getItem(`quarto-announce-${annId}`) || false; + if (isDismissed) { + announceDismiss(); + return; + } else { + annEl.classList.remove("hidden"); + } + + const actionEl = annEl.querySelector(".quarto-announcement-action"); + if (actionEl) { + actionEl.addEventListener("click", function (e) { + e.preventDefault(); + // Hide the bar immediately + announceDismiss(); + }); + } + } +}; + +window.document.addEventListener("DOMContentLoaded", function () { + let init = false; + + announceRegister(); + + // Manage the back to top button, if one is present. + let lastScrollTop = window.pageYOffset || document.documentElement.scrollTop; + const scrollDownBuffer = 5; + const scrollUpBuffer = 35; + const btn = document.getElementById("quarto-back-to-top"); + const hideBackToTop = () => { + btn.style.display = "none"; + }; + const showBackToTop = () => { + btn.style.display = "inline-block"; + }; + if (btn) { + window.document.addEventListener( + "scroll", + function () { + const currentScrollTop = + window.pageYOffset || document.documentElement.scrollTop; + + // Shows and hides the button 'intelligently' as the user scrolls + if (currentScrollTop - scrollDownBuffer > lastScrollTop) { + hideBackToTop(); + lastScrollTop = currentScrollTop <= 0 ? 0 : currentScrollTop; + } else if (currentScrollTop < lastScrollTop - scrollUpBuffer) { + showBackToTop(); + lastScrollTop = currentScrollTop <= 0 ? 0 : currentScrollTop; + } + + // Show the button at the bottom, hides it at the top + if (currentScrollTop <= 0) { + hideBackToTop(); + } else if ( + window.innerHeight + currentScrollTop >= + document.body.offsetHeight + ) { + showBackToTop(); + } + }, + false + ); + } + + function throttle(func, wait) { + var timeout; + return function () { + const context = this; + const args = arguments; + const later = function () { + clearTimeout(timeout); + timeout = null; + func.apply(context, args); + }; + + if (!timeout) { + timeout = setTimeout(later, wait); + } + }; + } + + function headerOffset() { + // Set an offset if there is are fixed top navbar + const headerEl = window.document.querySelector("header.fixed-top"); + if (headerEl) { + return headerEl.clientHeight; + } else { + return 0; + } + } + + function footerOffset() { + const footerEl = window.document.querySelector("footer.footer"); + if (footerEl) { + return footerEl.clientHeight; + } else { + return 0; + } + } + + function dashboardOffset() { + const dashboardNavEl = window.document.getElementById( + "quarto-dashboard-header" + ); + if (dashboardNavEl !== null) { + return dashboardNavEl.clientHeight; + } else { + return 0; + } + } + + function updateDocumentOffsetWithoutAnimation() { + updateDocumentOffset(false); + } + + function updateDocumentOffset(animated) { + // set body offset + const topOffset = headerOffset(); + const bodyOffset = topOffset + footerOffset() + dashboardOffset(); + const bodyEl = window.document.body; + bodyEl.setAttribute("data-bs-offset", topOffset); + bodyEl.style.paddingTop = topOffset + "px"; + + // deal with sidebar offsets + const sidebars = window.document.querySelectorAll( + ".sidebar, .headroom-target" + ); + sidebars.forEach((sidebar) => { + if (!animated) { + sidebar.classList.add("notransition"); + // Remove the no transition class after the animation has time to complete + setTimeout(function () { + sidebar.classList.remove("notransition"); + }, 201); + } + + if (window.Headroom && sidebar.classList.contains("sidebar-unpinned")) { + sidebar.style.top = "0"; + sidebar.style.maxHeight = "100vh"; + } else { + sidebar.style.top = topOffset + "px"; + sidebar.style.maxHeight = "calc(100vh - " + topOffset + "px)"; + } + }); + + // allow space for footer + const mainContainer = window.document.querySelector(".quarto-container"); + if (mainContainer) { + mainContainer.style.minHeight = "calc(100vh - " + bodyOffset + "px)"; + } + + // link offset + let linkStyle = window.document.querySelector("#quarto-target-style"); + if (!linkStyle) { + linkStyle = window.document.createElement("style"); + linkStyle.setAttribute("id", "quarto-target-style"); + window.document.head.appendChild(linkStyle); + } + while (linkStyle.firstChild) { + linkStyle.removeChild(linkStyle.firstChild); + } + if (topOffset > 0) { + linkStyle.appendChild( + window.document.createTextNode(` + section:target::before { + content: ""; + display: block; + height: ${topOffset}px; + margin: -${topOffset}px 0 0; + }`) + ); + } + if (init) { + window.dispatchEvent(headroomChanged); + } + init = true; + } + + // initialize headroom + var header = window.document.querySelector("#quarto-header"); + if (header && window.Headroom) { + const headroom = new window.Headroom(header, { + tolerance: 5, + onPin: function () { + const sidebars = window.document.querySelectorAll( + ".sidebar, .headroom-target" + ); + sidebars.forEach((sidebar) => { + sidebar.classList.remove("sidebar-unpinned"); + }); + updateDocumentOffset(); + }, + onUnpin: function () { + const sidebars = window.document.querySelectorAll( + ".sidebar, .headroom-target" + ); + sidebars.forEach((sidebar) => { + sidebar.classList.add("sidebar-unpinned"); + }); + updateDocumentOffset(); + }, + }); + headroom.init(); + + let frozen = false; + window.quartoToggleHeadroom = function () { + if (frozen) { + headroom.unfreeze(); + frozen = false; + } else { + headroom.freeze(); + frozen = true; + } + }; + } + + window.addEventListener( + "hashchange", + function (e) { + if ( + getComputedStyle(document.documentElement).scrollBehavior !== "smooth" + ) { + window.scrollTo(0, window.pageYOffset - headerOffset()); + } + }, + false + ); + + // Observe size changed for the header + const headerEl = window.document.querySelector("header.fixed-top"); + if (headerEl && window.ResizeObserver) { + const observer = new window.ResizeObserver(() => { + setTimeout(updateDocumentOffsetWithoutAnimation, 0); + }); + observer.observe(headerEl, { + attributes: true, + childList: true, + characterData: true, + }); + } else { + window.addEventListener( + "resize", + throttle(updateDocumentOffsetWithoutAnimation, 50) + ); + } + setTimeout(updateDocumentOffsetWithoutAnimation, 250); + + // fixup index.html links if we aren't on the filesystem + if (window.location.protocol !== "file:") { + const links = window.document.querySelectorAll("a"); + for (let i = 0; i < links.length; i++) { + if (links[i].href) { + links[i].dataset.originalHref = links[i].href; + links[i].href = links[i].href.replace(/\/index\.html/, "/"); + } + } + + // Fixup any sharing links that require urls + // Append url to any sharing urls + const sharingLinks = window.document.querySelectorAll( + "a.sidebar-tools-main-item, a.quarto-navigation-tool, a.quarto-navbar-tools, a.quarto-navbar-tools-item" + ); + for (let i = 0; i < sharingLinks.length; i++) { + const sharingLink = sharingLinks[i]; + const href = sharingLink.getAttribute("href"); + if (href) { + sharingLink.setAttribute( + "href", + href.replace("|url|", window.location.href) + ); + } + } + + // Scroll the active navigation item into view, if necessary + const navSidebar = window.document.querySelector("nav#quarto-sidebar"); + if (navSidebar) { + // Find the active item + const activeItem = navSidebar.querySelector("li.sidebar-item a.active"); + if (activeItem) { + // Wait for the scroll height and height to resolve by observing size changes on the + // nav element that is scrollable + const resizeObserver = new ResizeObserver((_entries) => { + // The bottom of the element + const elBottom = activeItem.offsetTop; + const viewBottom = navSidebar.scrollTop + navSidebar.clientHeight; + + // The element height and scroll height are the same, then we are still loading + if (viewBottom !== navSidebar.scrollHeight) { + // Determine if the item isn't visible and scroll to it + if (elBottom >= viewBottom) { + navSidebar.scrollTop = elBottom; + } + + // stop observing now since we've completed the scroll + resizeObserver.unobserve(navSidebar); + } + }); + resizeObserver.observe(navSidebar); + } + } + } +}); diff --git a/site_libs/quarto-search/autocomplete.umd.js b/site_libs/quarto-search/autocomplete.umd.js new file mode 100644 index 00000000..ae0063aa --- /dev/null +++ b/site_libs/quarto-search/autocomplete.umd.js @@ -0,0 +1,3 @@ +/*! @algolia/autocomplete-js 1.11.1 | MIT License | © Algolia, Inc. and contributors | https://github.com/algolia/autocomplete */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self)["@algolia/autocomplete-js"]={})}(this,(function(e){"use strict";function t(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function n(e){for(var n=1;n=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function a(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,i,u,a=[],l=!0,c=!1;try{if(i=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;l=!1}else for(;!(l=(r=i.call(n)).done)&&(a.push(r.value),a.length!==t);l=!0);}catch(e){c=!0,o=e}finally{try{if(!l&&null!=n.return&&(u=n.return(),Object(u)!==u))return}finally{if(c)throw o}}return a}}(e,t)||c(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function l(e){return function(e){if(Array.isArray(e))return s(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||c(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function c(e,t){if(e){if("string"==typeof e)return s(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?s(e,t):void 0}}function s(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function x(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function N(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:20,n=[],r=0;r=3||2===n&&r>=4||1===n&&r>=10);function i(t,n,r){if(o&&void 0!==r){var i=r[0].__autocomplete_algoliaCredentials,u={"X-Algolia-Application-Id":i.appId,"X-Algolia-API-Key":i.apiKey};e.apply(void 0,[t].concat(D(n),[{headers:u}]))}else e.apply(void 0,[t].concat(D(n)))}return{init:function(t,n){e("init",{appId:t,apiKey:n})},setUserToken:function(t){e("setUserToken",t)},clickedObjectIDsAfterSearch:function(){for(var e=arguments.length,t=new Array(e),n=0;n0&&i("clickedObjectIDsAfterSearch",B(t),t[0].items)},clickedObjectIDs:function(){for(var e=arguments.length,t=new Array(e),n=0;n0&&i("clickedObjectIDs",B(t),t[0].items)},clickedFilters:function(){for(var t=arguments.length,n=new Array(t),r=0;r0&&e.apply(void 0,["clickedFilters"].concat(n))},convertedObjectIDsAfterSearch:function(){for(var e=arguments.length,t=new Array(e),n=0;n0&&i("convertedObjectIDsAfterSearch",B(t),t[0].items)},convertedObjectIDs:function(){for(var e=arguments.length,t=new Array(e),n=0;n0&&i("convertedObjectIDs",B(t),t[0].items)},convertedFilters:function(){for(var t=arguments.length,n=new Array(t),r=0;r0&&e.apply(void 0,["convertedFilters"].concat(n))},viewedObjectIDs:function(){for(var e=arguments.length,t=new Array(e),n=0;n0&&t.reduce((function(e,t){var n=t.items,r=k(t,A);return[].concat(D(e),D(q(N(N({},r),{},{objectIDs:(null==n?void 0:n.map((function(e){return e.objectID})))||r.objectIDs})).map((function(e){return{items:n,payload:e}}))))}),[]).forEach((function(e){var t=e.items;return i("viewedObjectIDs",[e.payload],t)}))},viewedFilters:function(){for(var t=arguments.length,n=new Array(t),r=0;r0&&e.apply(void 0,["viewedFilters"].concat(n))}}}function F(e){var t=e.items.reduce((function(e,t){var n;return e[t.__autocomplete_indexName]=(null!==(n=e[t.__autocomplete_indexName])&&void 0!==n?n:[]).concat(t),e}),{});return Object.keys(t).map((function(e){return{index:e,items:t[e],algoliaSource:["autocomplete"]}}))}function L(e){return e.objectID&&e.__autocomplete_indexName&&e.__autocomplete_queryID}function U(e){return U="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},U(e)}function M(e){return function(e){if(Array.isArray(e))return H(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(!e)return;if("string"==typeof e)return H(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return H(e,t)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function H(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&z({onItemsChange:r,items:n,insights:a,state:t}))}}),0);return{name:"aa.algoliaInsightsPlugin",subscribe:function(e){var t=e.setContext,n=e.onSelect,r=e.onActive;function l(e){t({algoliaInsightsPlugin:{__algoliaSearchParameters:W({clickAnalytics:!0},e?{userToken:e}:{}),insights:a}})}u("addAlgoliaAgent","insights-plugin"),l(),u("onUserTokenChange",l),u("getUserToken",null,(function(e,t){l(t)})),n((function(e){var t=e.item,n=e.state,r=e.event,i=e.source;L(t)&&o({state:n,event:r,insights:a,item:t,insightsEvents:[W({eventName:"Item Selected"},j({item:t,items:i.getItems().filter(L)}))]})})),r((function(e){var t=e.item,n=e.source,r=e.state,o=e.event;L(t)&&i({state:r,event:o,insights:a,item:t,insightsEvents:[W({eventName:"Item Active"},j({item:t,items:n.getItems().filter(L)}))]})}))},onStateChange:function(e){var t=e.state;c({state:t})},__autocomplete_pluginOptions:e}}function J(e,t){var n=t;return{then:function(t,r){return J(e.then(Y(t,n,e),Y(r,n,e)),n)},catch:function(t){return J(e.catch(Y(t,n,e)),n)},finally:function(t){return t&&n.onCancelList.push(t),J(e.finally(Y(t&&function(){return n.onCancelList=[],t()},n,e)),n)},cancel:function(){n.isCanceled=!0;var e=n.onCancelList;n.onCancelList=[],e.forEach((function(e){e()}))},isCanceled:function(){return!0===n.isCanceled}}}function X(e){return J(e,{isCanceled:!1,onCancelList:[]})}function Y(e,t,n){return e?function(n){return t.isCanceled?n:e(n)}:n}function Z(e,t,n,r){if(!n)return null;if(e<0&&(null===t||null!==r&&0===t))return n+e;var o=(null===t?-1:t)+e;return o<=-1||o>=n?null===r?null:0:o}function ee(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function te(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=new Array(t);n0},reshape:function(e){return e.sources}},e),{},{id:null!==(n=e.id)&&void 0!==n?n:d(),plugins:o,initialState:he({activeItemId:null,query:"",completion:null,collections:[],isOpen:!1,status:"idle",context:{}},e.initialState),onStateChange:function(t){var n;null===(n=e.onStateChange)||void 0===n||n.call(e,t),o.forEach((function(e){var n;return null===(n=e.onStateChange)||void 0===n?void 0:n.call(e,t)}))},onSubmit:function(t){var n;null===(n=e.onSubmit)||void 0===n||n.call(e,t),o.forEach((function(e){var n;return null===(n=e.onSubmit)||void 0===n?void 0:n.call(e,t)}))},onReset:function(t){var n;null===(n=e.onReset)||void 0===n||n.call(e,t),o.forEach((function(e){var n;return null===(n=e.onReset)||void 0===n?void 0:n.call(e,t)}))},getSources:function(n){return Promise.all([].concat(ye(o.map((function(e){return e.getSources}))),[e.getSources]).filter(Boolean).map((function(e){return function(e,t){var n=[];return Promise.resolve(e(t)).then((function(e){return Promise.all(e.filter((function(e){return Boolean(e)})).map((function(e){if(e.sourceId,n.includes(e.sourceId))throw new Error("[Autocomplete] The `sourceId` ".concat(JSON.stringify(e.sourceId)," is not unique."));n.push(e.sourceId);var t={getItemInputValue:function(e){return e.state.query},getItemUrl:function(){},onSelect:function(e){(0,e.setIsOpen)(!1)},onActive:O,onResolve:O};Object.keys(t).forEach((function(e){t[e].__default=!0}));var r=te(te({},t),e);return Promise.resolve(r)})))}))}(e,n)}))).then((function(e){return m(e)})).then((function(e){return e.map((function(e){return he(he({},e),{},{onSelect:function(n){e.onSelect(n),t.forEach((function(e){var t;return null===(t=e.onSelect)||void 0===t?void 0:t.call(e,n)}))},onActive:function(n){e.onActive(n),t.forEach((function(e){var t;return null===(t=e.onActive)||void 0===t?void 0:t.call(e,n)}))},onResolve:function(n){e.onResolve(n),t.forEach((function(e){var t;return null===(t=e.onResolve)||void 0===t?void 0:t.call(e,n)}))}})}))}))},navigator:he({navigate:function(e){var t=e.itemUrl;r.location.assign(t)},navigateNewTab:function(e){var t=e.itemUrl,n=r.open(t,"_blank","noopener");null==n||n.focus()},navigateNewWindow:function(e){var t=e.itemUrl;r.open(t,"_blank","noopener")}},e.navigator)})}function Se(e){return Se="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Se(e)}function je(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Pe(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=new Array(t);n=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var He,Ve,We,Ke=null,Qe=(He=-1,Ve=-1,We=void 0,function(e){var t=++He;return Promise.resolve(e).then((function(e){return We&&t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function et(e){return et="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},et(e)}var tt=["props","refresh","store"],nt=["inputElement","formElement","panelElement"],rt=["inputElement"],ot=["inputElement","maxLength"],it=["source"],ut=["item","source"];function at(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function lt(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function ft(e){var t=e.props,n=e.refresh,r=e.store,o=st(e,tt);return{getEnvironmentProps:function(e){var n=e.inputElement,o=e.formElement,i=e.panelElement;function u(e){!r.getState().isOpen&&r.pendingRequests.isEmpty()||e.target===n||!1===[o,i].some((function(t){return n=t,r=e.target,n===r||n.contains(r);var n,r}))&&(r.dispatch("blur",null),t.debug||r.pendingRequests.cancelAll())}return lt({onTouchStart:u,onMouseDown:u,onTouchMove:function(e){!1!==r.getState().isOpen&&n===t.environment.document.activeElement&&e.target!==n&&n.blur()}},st(e,nt))},getRootProps:function(e){return lt({role:"combobox","aria-expanded":r.getState().isOpen,"aria-haspopup":"listbox","aria-owns":r.getState().isOpen?r.getState().collections.map((function(e){var n=e.source;return ie(t.id,"list",n)})).join(" "):void 0,"aria-labelledby":ie(t.id,"label")},e)},getFormProps:function(e){return e.inputElement,lt({action:"",noValidate:!0,role:"search",onSubmit:function(i){var u;i.preventDefault(),t.onSubmit(lt({event:i,refresh:n,state:r.getState()},o)),r.dispatch("submit",null),null===(u=e.inputElement)||void 0===u||u.blur()},onReset:function(i){var u;i.preventDefault(),t.onReset(lt({event:i,refresh:n,state:r.getState()},o)),r.dispatch("reset",null),null===(u=e.inputElement)||void 0===u||u.focus()}},st(e,rt))},getLabelProps:function(e){return lt({htmlFor:ie(t.id,"input"),id:ie(t.id,"label")},e)},getInputProps:function(e){var i;function u(e){(t.openOnFocus||Boolean(r.getState().query))&&$e(lt({event:e,props:t,query:r.getState().completion||r.getState().query,refresh:n,store:r},o)),r.dispatch("focus",null)}var a=e||{};a.inputElement;var l=a.maxLength,c=void 0===l?512:l,s=st(a,ot),f=oe(r.getState()),p=function(e){return Boolean(e&&e.match(ue))}((null===(i=t.environment.navigator)||void 0===i?void 0:i.userAgent)||""),m=t.enterKeyHint||(null!=f&&f.itemUrl&&!p?"go":"search");return lt({"aria-autocomplete":"both","aria-activedescendant":r.getState().isOpen&&null!==r.getState().activeItemId?ie(t.id,"item-".concat(r.getState().activeItemId),null==f?void 0:f.source):void 0,"aria-controls":r.getState().isOpen?r.getState().collections.map((function(e){var n=e.source;return ie(t.id,"list",n)})).join(" "):void 0,"aria-labelledby":ie(t.id,"label"),value:r.getState().completion||r.getState().query,id:ie(t.id,"input"),autoComplete:"off",autoCorrect:"off",autoCapitalize:"off",enterKeyHint:m,spellCheck:"false",autoFocus:t.autoFocus,placeholder:t.placeholder,maxLength:c,type:"search",onChange:function(e){$e(lt({event:e,props:t,query:e.currentTarget.value.slice(0,c),refresh:n,store:r},o))},onKeyDown:function(e){!function(e){var t=e.event,n=e.props,r=e.refresh,o=e.store,i=Ze(e,Ge);if("ArrowUp"===t.key||"ArrowDown"===t.key){var u=function(){var e=oe(o.getState()),t=n.environment.document.getElementById(ie(n.id,"item-".concat(o.getState().activeItemId),null==e?void 0:e.source));t&&(t.scrollIntoViewIfNeeded?t.scrollIntoViewIfNeeded(!1):t.scrollIntoView(!1))},a=function(){var e=oe(o.getState());if(null!==o.getState().activeItemId&&e){var n=e.item,u=e.itemInputValue,a=e.itemUrl,l=e.source;l.onActive(Xe({event:t,item:n,itemInputValue:u,itemUrl:a,refresh:r,source:l,state:o.getState()},i))}};t.preventDefault(),!1===o.getState().isOpen&&(n.openOnFocus||Boolean(o.getState().query))?$e(Xe({event:t,props:n,query:o.getState().query,refresh:r,store:o},i)).then((function(){o.dispatch(t.key,{nextActiveItemId:n.defaultActiveItemId}),a(),setTimeout(u,0)})):(o.dispatch(t.key,{}),a(),u())}else if("Escape"===t.key)t.preventDefault(),o.dispatch(t.key,null),o.pendingRequests.cancelAll();else if("Tab"===t.key)o.dispatch("blur",null),o.pendingRequests.cancelAll();else if("Enter"===t.key){if(null===o.getState().activeItemId||o.getState().collections.every((function(e){return 0===e.items.length})))return void(n.debug||o.pendingRequests.cancelAll());t.preventDefault();var l=oe(o.getState()),c=l.item,s=l.itemInputValue,f=l.itemUrl,p=l.source;if(t.metaKey||t.ctrlKey)void 0!==f&&(p.onSelect(Xe({event:t,item:c,itemInputValue:s,itemUrl:f,refresh:r,source:p,state:o.getState()},i)),n.navigator.navigateNewTab({itemUrl:f,item:c,state:o.getState()}));else if(t.shiftKey)void 0!==f&&(p.onSelect(Xe({event:t,item:c,itemInputValue:s,itemUrl:f,refresh:r,source:p,state:o.getState()},i)),n.navigator.navigateNewWindow({itemUrl:f,item:c,state:o.getState()}));else if(t.altKey);else{if(void 0!==f)return p.onSelect(Xe({event:t,item:c,itemInputValue:s,itemUrl:f,refresh:r,source:p,state:o.getState()},i)),void n.navigator.navigate({itemUrl:f,item:c,state:o.getState()});$e(Xe({event:t,nextState:{isOpen:!1},props:n,query:s,refresh:r,store:o},i)).then((function(){p.onSelect(Xe({event:t,item:c,itemInputValue:s,itemUrl:f,refresh:r,source:p,state:o.getState()},i))}))}}}(lt({event:e,props:t,refresh:n,store:r},o))},onFocus:u,onBlur:O,onClick:function(n){e.inputElement!==t.environment.document.activeElement||r.getState().isOpen||u(n)}},s)},getPanelProps:function(e){return lt({onMouseDown:function(e){e.preventDefault()},onMouseLeave:function(){r.dispatch("mouseleave",null)}},e)},getListProps:function(e){var n=e||{},r=n.source,o=st(n,it);return lt({role:"listbox","aria-labelledby":ie(t.id,"label"),id:ie(t.id,"list",r)},o)},getItemProps:function(e){var i=e.item,u=e.source,a=st(e,ut);return lt({id:ie(t.id,"item-".concat(i.__autocomplete_id),u),role:"option","aria-selected":r.getState().activeItemId===i.__autocomplete_id,onMouseMove:function(e){if(i.__autocomplete_id!==r.getState().activeItemId){r.dispatch("mousemove",i.__autocomplete_id);var t=oe(r.getState());if(null!==r.getState().activeItemId&&t){var u=t.item,a=t.itemInputValue,l=t.itemUrl,c=t.source;c.onActive(lt({event:e,item:u,itemInputValue:a,itemUrl:l,refresh:n,source:c,state:r.getState()},o))}}},onMouseDown:function(e){e.preventDefault()},onClick:function(e){var a=u.getItemInputValue({item:i,state:r.getState()}),l=u.getItemUrl({item:i,state:r.getState()});(l?Promise.resolve():$e(lt({event:e,nextState:{isOpen:!1},props:t,query:a,refresh:n,store:r},o))).then((function(){u.onSelect(lt({event:e,item:i,itemInputValue:a,itemUrl:l,refresh:n,source:u,state:r.getState()},o))}))}},a)}}}function pt(e){return pt="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},pt(e)}function mt(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function vt(e){for(var t=1;t=5&&((o||!e&&5===r)&&(u.push(r,0,o,n),r=6),e&&(u.push(r,e,0,n),r=6)),o=""},l=0;l"===t?(r=1,o=""):o=t+o[0]:i?t===i?i="":o+=t:'"'===t||"'"===t?i=t:">"===t?(a(),r=1):r&&("="===t?(r=5,n=o,o=""):"/"===t&&(r<5||">"===e[l][c+1])?(a(),3===r&&(u=u[0]),r=u,(u=u[0]).push(2,0,r),r=0):" "===t||"\t"===t||"\n"===t||"\r"===t?(a(),r=2):o+=t),3===r&&"!--"===o&&(r=4,u=u[0])}return a(),u}(e)),t),arguments,[])).length>1?t:t[0]}var kt=function(e){var t=e.environment,n=t.document.createElementNS("http://www.w3.org/2000/svg","svg");n.setAttribute("class","aa-ClearIcon"),n.setAttribute("viewBox","0 0 24 24"),n.setAttribute("width","18"),n.setAttribute("height","18"),n.setAttribute("fill","currentColor");var r=t.document.createElementNS("http://www.w3.org/2000/svg","path");return r.setAttribute("d","M5.293 6.707l5.293 5.293-5.293 5.293c-0.391 0.391-0.391 1.024 0 1.414s1.024 0.391 1.414 0l5.293-5.293 5.293 5.293c0.391 0.391 1.024 0.391 1.414 0s0.391-1.024 0-1.414l-5.293-5.293 5.293-5.293c0.391-0.391 0.391-1.024 0-1.414s-1.024-0.391-1.414 0l-5.293 5.293-5.293-5.293c-0.391-0.391-1.024-0.391-1.414 0s-0.391 1.024 0 1.414z"),n.appendChild(r),n};function xt(e,t){if("string"==typeof t){var n=e.document.querySelector(t);return"The element ".concat(JSON.stringify(t)," is not in the document."),n}return t}function Nt(){for(var e=arguments.length,t=new Array(e),n=0;n2&&(u.children=arguments.length>3?Jt.call(arguments,2):n),"function"==typeof e&&null!=e.defaultProps)for(i in e.defaultProps)void 0===u[i]&&(u[i]=e.defaultProps[i]);return sn(e,u,r,o,null)}function sn(e,t,n,r,o){var i={type:e,props:t,key:n,ref:r,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==o?++Yt:o};return null==o&&null!=Xt.vnode&&Xt.vnode(i),i}function fn(e){return e.children}function pn(e,t){this.props=e,this.context=t}function mn(e,t){if(null==t)return e.__?mn(e.__,e.__.__k.indexOf(e)+1):null;for(var n;tt&&Zt.sort(nn));yn.__r=0}function bn(e,t,n,r,o,i,u,a,l,c){var s,f,p,m,v,d,y,b=r&&r.__k||on,g=b.length;for(n.__k=[],s=0;s0?sn(m.type,m.props,m.key,m.ref?m.ref:null,m.__v):m)){if(m.__=n,m.__b=n.__b+1,null===(p=b[s])||p&&m.key==p.key&&m.type===p.type)b[s]=void 0;else for(f=0;f=0;t--)if((n=e.__k[t])&&(r=On(n)))return r;return null}function _n(e,t,n){"-"===t[0]?e.setProperty(t,null==n?"":n):e[t]=null==n?"":"number"!=typeof n||un.test(t)?n:n+"px"}function Sn(e,t,n,r,o){var i;e:if("style"===t)if("string"==typeof n)e.style.cssText=n;else{if("string"==typeof r&&(e.style.cssText=r=""),r)for(t in r)n&&t in n||_n(e.style,t,"");if(n)for(t in n)r&&n[t]===r[t]||_n(e.style,t,n[t])}else if("o"===t[0]&&"n"===t[1])i=t!==(t=t.replace(/Capture$/,"")),t=t.toLowerCase()in e?t.toLowerCase().slice(2):t.slice(2),e.l||(e.l={}),e.l[t+i]=n,n?r||e.addEventListener(t,i?Pn:jn,i):e.removeEventListener(t,i?Pn:jn,i);else if("dangerouslySetInnerHTML"!==t){if(o)t=t.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if("width"!==t&&"height"!==t&&"href"!==t&&"list"!==t&&"form"!==t&&"tabIndex"!==t&&"download"!==t&&t in e)try{e[t]=null==n?"":n;break e}catch(e){}"function"==typeof n||(null==n||!1===n&&"-"!==t[4]?e.removeAttribute(t):e.setAttribute(t,n))}}function jn(e){return this.l[e.type+!1](Xt.event?Xt.event(e):e)}function Pn(e){return this.l[e.type+!0](Xt.event?Xt.event(e):e)}function wn(e,t,n,r,o,i,u,a,l){var c,s,f,p,m,v,d,y,b,g,h,O,_,S,j,P=t.type;if(void 0!==t.constructor)return null;null!=n.__h&&(l=n.__h,a=t.__e=n.__e,t.__h=null,i=[a]),(c=Xt.__b)&&c(t);try{e:if("function"==typeof P){if(y=t.props,b=(c=P.contextType)&&r[c.__c],g=c?b?b.props.value:c.__:r,n.__c?d=(s=t.__c=n.__c).__=s.__E:("prototype"in P&&P.prototype.render?t.__c=s=new P(y,g):(t.__c=s=new pn(y,g),s.constructor=P,s.render=Cn),b&&b.sub(s),s.props=y,s.state||(s.state={}),s.context=g,s.__n=r,f=s.__d=!0,s.__h=[],s._sb=[]),null==s.__s&&(s.__s=s.state),null!=P.getDerivedStateFromProps&&(s.__s==s.state&&(s.__s=an({},s.__s)),an(s.__s,P.getDerivedStateFromProps(y,s.__s))),p=s.props,m=s.state,s.__v=t,f)null==P.getDerivedStateFromProps&&null!=s.componentWillMount&&s.componentWillMount(),null!=s.componentDidMount&&s.__h.push(s.componentDidMount);else{if(null==P.getDerivedStateFromProps&&y!==p&&null!=s.componentWillReceiveProps&&s.componentWillReceiveProps(y,g),!s.__e&&null!=s.shouldComponentUpdate&&!1===s.shouldComponentUpdate(y,s.__s,g)||t.__v===n.__v){for(t.__v!==n.__v&&(s.props=y,s.state=s.__s,s.__d=!1),s.__e=!1,t.__e=n.__e,t.__k=n.__k,t.__k.forEach((function(e){e&&(e.__=t)})),h=0;h0&&void 0!==arguments[0]?arguments[0]:[];return{get:function(){return e},add:function(t){var n=e[e.length-1];(null==n?void 0:n.isHighlighted)===t.isHighlighted?e[e.length-1]={value:n.value+t.value,isHighlighted:n.isHighlighted}:e.push(t)}}}(n?[{value:n,isHighlighted:!1}]:[]);return t.forEach((function(e){var t=e.split(xn);r.add({value:t[0],isHighlighted:!0}),""!==t[1]&&r.add({value:t[1],isHighlighted:!1})})),r.get()}function Tn(e){return function(e){if(Array.isArray(e))return qn(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(!e)return;if("string"==typeof e)return qn(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return qn(e,t)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function qn(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n",""":'"',"'":"'"},Fn=new RegExp(/\w/i),Ln=/&(amp|quot|lt|gt|#39);/g,Un=RegExp(Ln.source);function Mn(e,t){var n,r,o,i=e[t],u=(null===(n=e[t+1])||void 0===n?void 0:n.isHighlighted)||!0,a=(null===(r=e[t-1])||void 0===r?void 0:r.isHighlighted)||!0;return Fn.test((o=i.value)&&Un.test(o)?o.replace(Ln,(function(e){return Rn[e]})):o)||a!==u?i.isHighlighted:a}function Hn(e){return Hn="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Hn(e)}function Vn(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Wn(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=new Array(t);n=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function ur(e){return function(e){if(Array.isArray(e))return ar(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(!e)return;if("string"==typeof e)return ar(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return ar(e,t)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function ar(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n0;if(!O.value.core.openOnFocus&&!t.query)return n;var r=Boolean(y.current||O.value.renderer.renderNoResults);return!n&&r||n},__autocomplete_metadata:{userAgents:br,options:e}}))})),j=f(n({collections:[],completion:null,context:{},isOpen:!1,query:"",activeItemId:null,status:"idle"},O.value.core.initialState)),P={getEnvironmentProps:O.value.renderer.getEnvironmentProps,getFormProps:O.value.renderer.getFormProps,getInputProps:O.value.renderer.getInputProps,getItemProps:O.value.renderer.getItemProps,getLabelProps:O.value.renderer.getLabelProps,getListProps:O.value.renderer.getListProps,getPanelProps:O.value.renderer.getPanelProps,getRootProps:O.value.renderer.getRootProps},w={setActiveItemId:S.value.setActiveItemId,setQuery:S.value.setQuery,setCollections:S.value.setCollections,setIsOpen:S.value.setIsOpen,setStatus:S.value.setStatus,setContext:S.value.setContext,refresh:S.value.refresh,navigator:S.value.navigator},I=m((function(){return Ct.bind(O.value.renderer.renderer.createElement)})),A=m((function(){return Gt({autocomplete:S.value,autocompleteScopeApi:w,classNames:O.value.renderer.classNames,environment:O.value.core.environment,isDetached:_.value,placeholder:O.value.core.placeholder,propGetters:P,setIsModalOpen:k,state:j.current,translations:O.value.renderer.translations})}));function E(){Ht(A.value.panel,{style:_.value?{}:yr({panelPlacement:O.value.renderer.panelPlacement,container:A.value.root,form:A.value.form,environment:O.value.core.environment})})}function D(e){j.current=e;var t={autocomplete:S.value,autocompleteScopeApi:w,classNames:O.value.renderer.classNames,components:O.value.renderer.components,container:O.value.renderer.container,html:I.value,dom:A.value,panelContainer:_.value?A.value.detachedContainer:O.value.renderer.panelContainer,propGetters:P,state:j.current,renderer:O.value.renderer.renderer},r=!b(e)&&!y.current&&O.value.renderer.renderNoResults||O.value.renderer.render;!function(e){var t=e.autocomplete,r=e.autocompleteScopeApi,o=e.dom,i=e.propGetters,u=e.state;Vt(o.root,i.getRootProps(n({state:u,props:t.getRootProps({})},r))),Vt(o.input,i.getInputProps(n({state:u,props:t.getInputProps({inputElement:o.input}),inputElement:o.input},r))),Ht(o.label,{hidden:"stalled"===u.status}),Ht(o.loadingIndicator,{hidden:"stalled"!==u.status}),Ht(o.clearButton,{hidden:!u.query}),Ht(o.detachedSearchButtonQuery,{textContent:u.query}),Ht(o.detachedSearchButtonPlaceholder,{hidden:Boolean(u.query)})}(t),function(e,t){var r=t.autocomplete,o=t.autocompleteScopeApi,u=t.classNames,a=t.html,l=t.dom,c=t.panelContainer,s=t.propGetters,f=t.state,p=t.components,m=t.renderer;if(f.isOpen){c.contains(l.panel)||"loading"===f.status||c.appendChild(l.panel),l.panel.classList.toggle("aa-Panel--stalled","stalled"===f.status);var v=f.collections.filter((function(e){var t=e.source,n=e.items;return t.templates.noResults||n.length>0})).map((function(e,t){var l=e.source,c=e.items;return m.createElement("section",{key:t,className:u.source,"data-autocomplete-source-id":l.sourceId},l.templates.header&&m.createElement("div",{className:u.sourceHeader},l.templates.header({components:p,createElement:m.createElement,Fragment:m.Fragment,items:c,source:l,state:f,html:a})),l.templates.noResults&&0===c.length?m.createElement("div",{className:u.sourceNoResults},l.templates.noResults({components:p,createElement:m.createElement,Fragment:m.Fragment,source:l,state:f,html:a})):m.createElement("ul",i({className:u.list},s.getListProps(n({state:f,props:r.getListProps({source:l})},o))),c.map((function(e){var t=r.getItemProps({item:e,source:l});return m.createElement("li",i({key:t.id,className:u.item},s.getItemProps(n({state:f,props:t},o))),l.templates.item({components:p,createElement:m.createElement,Fragment:m.Fragment,item:e,state:f,html:a}))}))),l.templates.footer&&m.createElement("div",{className:u.sourceFooter},l.templates.footer({components:p,createElement:m.createElement,Fragment:m.Fragment,items:c,source:l,state:f,html:a})))})),d=m.createElement(m.Fragment,null,m.createElement("div",{className:u.panelLayout},v),m.createElement("div",{className:"aa-GradientBottom"})),y=v.reduce((function(e,t){return e[t.props["data-autocomplete-source-id"]]=t,e}),{});e(n(n({children:d,state:f,sections:v,elements:y},m),{},{components:p,html:a},o),l.panel)}else c.contains(l.panel)&&c.removeChild(l.panel)}(r,t)}function C(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};l();var t=O.value.renderer,n=t.components,r=u(t,gr);g.current=qt(r,O.value.core,{components:Bt(n,(function(e){return!e.value.hasOwnProperty("__autocomplete_componentName")})),initialState:j.current},e),v(),c(),S.value.refresh().then((function(){D(j.current)}))}function k(e){requestAnimationFrame((function(){var t=O.value.core.environment.document.body.contains(A.value.detachedOverlay);e!==t&&(e?(O.value.core.environment.document.body.appendChild(A.value.detachedOverlay),O.value.core.environment.document.body.classList.add("aa-Detached"),A.value.input.focus()):(O.value.core.environment.document.body.removeChild(A.value.detachedOverlay),O.value.core.environment.document.body.classList.remove("aa-Detached")))}))}return a((function(){var e=S.value.getEnvironmentProps({formElement:A.value.form,panelElement:A.value.panel,inputElement:A.value.input});return Ht(O.value.core.environment,e),function(){Ht(O.value.core.environment,Object.keys(e).reduce((function(e,t){return n(n({},e),{},o({},t,void 0))}),{}))}})),a((function(){var e=_.value?O.value.core.environment.document.body:O.value.renderer.panelContainer,t=_.value?A.value.detachedOverlay:A.value.panel;return _.value&&j.current.isOpen&&k(!0),D(j.current),function(){e.contains(t)&&e.removeChild(t)}})),a((function(){var e=O.value.renderer.container;return e.appendChild(A.value.root),function(){e.removeChild(A.value.root)}})),a((function(){var e=p((function(e){D(e.state)}),0);return h.current=function(t){var n=t.state,r=t.prevState;(_.value&&r.isOpen!==n.isOpen&&k(n.isOpen),_.value||!n.isOpen||r.isOpen||E(),n.query!==r.query)&&O.value.core.environment.document.querySelectorAll(".aa-Panel--scrollable").forEach((function(e){0!==e.scrollTop&&(e.scrollTop=0)}));e({state:n})},function(){h.current=void 0}})),a((function(){var e=p((function(){var e=_.value;_.value=O.value.core.environment.matchMedia(O.value.renderer.detachedMediaQuery).matches,e!==_.value?C({}):requestAnimationFrame(E)}),20);return O.value.core.environment.addEventListener("resize",e),function(){O.value.core.environment.removeEventListener("resize",e)}})),a((function(){if(!_.value)return function(){};function e(e){A.value.detachedContainer.classList.toggle("aa-DetachedContainer--modal",e)}function t(t){e(t.matches)}var n=O.value.core.environment.matchMedia(getComputedStyle(O.value.core.environment.document.documentElement).getPropertyValue("--aa-detached-modal-media-query"));e(n.matches);var r=Boolean(n.addEventListener);return r?n.addEventListener("change",t):n.addListener(t),function(){r?n.removeEventListener("change",t):n.removeListener(t)}})),a((function(){return requestAnimationFrame(E),function(){}})),n(n({},w),{},{update:C,destroy:function(){l()}})},e.getAlgoliaFacets=function(e){var t=hr({transformResponse:function(e){return e.facetHits}}),r=e.queries.map((function(e){return n(n({},e),{},{type:"facet"})}));return t(n(n({},e),{},{queries:r}))},e.getAlgoliaResults=Or,Object.defineProperty(e,"__esModule",{value:!0})})); + diff --git a/site_libs/quarto-search/fuse.min.js b/site_libs/quarto-search/fuse.min.js new file mode 100644 index 00000000..adc28356 --- /dev/null +++ b/site_libs/quarto-search/fuse.min.js @@ -0,0 +1,9 @@ +/** + * Fuse.js v6.6.2 - Lightweight fuzzy-search (http://fusejs.io) + * + * Copyright (c) 2022 Kiro Risk (http://kiro.me) + * All Rights Reserved. Apache Software License 2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ +var e,t;e=this,t=function(){"use strict";function e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function t(t){for(var n=1;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&void 0!==arguments[0]?arguments[0]:1,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:3,n=new Map,r=Math.pow(10,t);return{get:function(t){var i=t.match(C).length;if(n.has(i))return n.get(i);var o=1/Math.pow(i,.5*e),c=parseFloat(Math.round(o*r)/r);return n.set(i,c),c},clear:function(){n.clear()}}}var $=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=t.getFn,i=void 0===n?I.getFn:n,o=t.fieldNormWeight,c=void 0===o?I.fieldNormWeight:o;r(this,e),this.norm=E(c,3),this.getFn=i,this.isCreated=!1,this.setIndexRecords()}return o(e,[{key:"setSources",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];this.docs=e}},{key:"setIndexRecords",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];this.records=e}},{key:"setKeys",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];this.keys=t,this._keysMap={},t.forEach((function(t,n){e._keysMap[t.id]=n}))}},{key:"create",value:function(){var e=this;!this.isCreated&&this.docs.length&&(this.isCreated=!0,g(this.docs[0])?this.docs.forEach((function(t,n){e._addString(t,n)})):this.docs.forEach((function(t,n){e._addObject(t,n)})),this.norm.clear())}},{key:"add",value:function(e){var t=this.size();g(e)?this._addString(e,t):this._addObject(e,t)}},{key:"removeAt",value:function(e){this.records.splice(e,1);for(var t=e,n=this.size();t2&&void 0!==arguments[2]?arguments[2]:{},r=n.getFn,i=void 0===r?I.getFn:r,o=n.fieldNormWeight,c=void 0===o?I.fieldNormWeight:o,a=new $({getFn:i,fieldNormWeight:c});return a.setKeys(e.map(_)),a.setSources(t),a.create(),a}function R(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.errors,r=void 0===n?0:n,i=t.currentLocation,o=void 0===i?0:i,c=t.expectedLocation,a=void 0===c?0:c,s=t.distance,u=void 0===s?I.distance:s,h=t.ignoreLocation,l=void 0===h?I.ignoreLocation:h,f=r/e.length;if(l)return f;var d=Math.abs(a-o);return u?f+d/u:d?1:f}function N(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:I.minMatchCharLength,n=[],r=-1,i=-1,o=0,c=e.length;o=t&&n.push([r,i]),r=-1)}return e[o-1]&&o-r>=t&&n.push([r,o-1]),n}var P=32;function W(e){for(var t={},n=0,r=e.length;n1&&void 0!==arguments[1]?arguments[1]:{},o=i.location,c=void 0===o?I.location:o,a=i.threshold,s=void 0===a?I.threshold:a,u=i.distance,h=void 0===u?I.distance:u,l=i.includeMatches,f=void 0===l?I.includeMatches:l,d=i.findAllMatches,v=void 0===d?I.findAllMatches:d,g=i.minMatchCharLength,y=void 0===g?I.minMatchCharLength:g,p=i.isCaseSensitive,m=void 0===p?I.isCaseSensitive:p,k=i.ignoreLocation,M=void 0===k?I.ignoreLocation:k;if(r(this,e),this.options={location:c,threshold:s,distance:h,includeMatches:f,findAllMatches:v,minMatchCharLength:y,isCaseSensitive:m,ignoreLocation:M},this.pattern=m?t:t.toLowerCase(),this.chunks=[],this.pattern.length){var b=function(e,t){n.chunks.push({pattern:e,alphabet:W(e),startIndex:t})},x=this.pattern.length;if(x>P){for(var w=0,L=x%P,S=x-L;w3&&void 0!==arguments[3]?arguments[3]:{},i=r.location,o=void 0===i?I.location:i,c=r.distance,a=void 0===c?I.distance:c,s=r.threshold,u=void 0===s?I.threshold:s,h=r.findAllMatches,l=void 0===h?I.findAllMatches:h,f=r.minMatchCharLength,d=void 0===f?I.minMatchCharLength:f,v=r.includeMatches,g=void 0===v?I.includeMatches:v,y=r.ignoreLocation,p=void 0===y?I.ignoreLocation:y;if(t.length>P)throw new Error(w(P));for(var m,k=t.length,M=e.length,b=Math.max(0,Math.min(o,M)),x=u,L=b,S=d>1||g,_=S?Array(M):[];(m=e.indexOf(t,L))>-1;){var O=R(t,{currentLocation:m,expectedLocation:b,distance:a,ignoreLocation:p});if(x=Math.min(O,x),L=m+k,S)for(var j=0;j=z;q-=1){var B=q-1,J=n[e.charAt(B)];if(S&&(_[B]=+!!J),K[q]=(K[q+1]<<1|1)&J,F&&(K[q]|=(A[q+1]|A[q])<<1|1|A[q+1]),K[q]&$&&(C=R(t,{errors:F,currentLocation:B,expectedLocation:b,distance:a,ignoreLocation:p}))<=x){if(x=C,(L=B)<=b)break;z=Math.max(1,2*b-L)}}if(R(t,{errors:F+1,currentLocation:b,expectedLocation:b,distance:a,ignoreLocation:p})>x)break;A=K}var U={isMatch:L>=0,score:Math.max(.001,C)};if(S){var V=N(_,d);V.length?g&&(U.indices=V):U.isMatch=!1}return U}(e,n,i,{location:c+o,distance:a,threshold:s,findAllMatches:u,minMatchCharLength:h,includeMatches:r,ignoreLocation:l}),p=y.isMatch,m=y.score,k=y.indices;p&&(g=!0),v+=m,p&&k&&(d=[].concat(f(d),f(k)))}));var y={isMatch:g,score:g?v/this.chunks.length:1};return g&&r&&(y.indices=d),y}}]),e}(),z=function(){function e(t){r(this,e),this.pattern=t}return o(e,[{key:"search",value:function(){}}],[{key:"isMultiMatch",value:function(e){return D(e,this.multiRegex)}},{key:"isSingleMatch",value:function(e){return D(e,this.singleRegex)}}]),e}();function D(e,t){var n=e.match(t);return n?n[1]:null}var K=function(e){a(n,e);var t=l(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){var t=e===this.pattern;return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}}],[{key:"type",get:function(){return"exact"}},{key:"multiRegex",get:function(){return/^="(.*)"$/}},{key:"singleRegex",get:function(){return/^=(.*)$/}}]),n}(z),q=function(e){a(n,e);var t=l(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){var t=-1===e.indexOf(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}}],[{key:"type",get:function(){return"inverse-exact"}},{key:"multiRegex",get:function(){return/^!"(.*)"$/}},{key:"singleRegex",get:function(){return/^!(.*)$/}}]),n}(z),B=function(e){a(n,e);var t=l(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){var t=e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}}],[{key:"type",get:function(){return"prefix-exact"}},{key:"multiRegex",get:function(){return/^\^"(.*)"$/}},{key:"singleRegex",get:function(){return/^\^(.*)$/}}]),n}(z),J=function(e){a(n,e);var t=l(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){var t=!e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}}],[{key:"type",get:function(){return"inverse-prefix-exact"}},{key:"multiRegex",get:function(){return/^!\^"(.*)"$/}},{key:"singleRegex",get:function(){return/^!\^(.*)$/}}]),n}(z),U=function(e){a(n,e);var t=l(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){var t=e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[e.length-this.pattern.length,e.length-1]}}}],[{key:"type",get:function(){return"suffix-exact"}},{key:"multiRegex",get:function(){return/^"(.*)"\$$/}},{key:"singleRegex",get:function(){return/^(.*)\$$/}}]),n}(z),V=function(e){a(n,e);var t=l(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){var t=!e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}}],[{key:"type",get:function(){return"inverse-suffix-exact"}},{key:"multiRegex",get:function(){return/^!"(.*)"\$$/}},{key:"singleRegex",get:function(){return/^!(.*)\$$/}}]),n}(z),G=function(e){a(n,e);var t=l(n);function n(e){var i,o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},c=o.location,a=void 0===c?I.location:c,s=o.threshold,u=void 0===s?I.threshold:s,h=o.distance,l=void 0===h?I.distance:h,f=o.includeMatches,d=void 0===f?I.includeMatches:f,v=o.findAllMatches,g=void 0===v?I.findAllMatches:v,y=o.minMatchCharLength,p=void 0===y?I.minMatchCharLength:y,m=o.isCaseSensitive,k=void 0===m?I.isCaseSensitive:m,M=o.ignoreLocation,b=void 0===M?I.ignoreLocation:M;return r(this,n),(i=t.call(this,e))._bitapSearch=new T(e,{location:a,threshold:u,distance:l,includeMatches:d,findAllMatches:g,minMatchCharLength:p,isCaseSensitive:k,ignoreLocation:b}),i}return o(n,[{key:"search",value:function(e){return this._bitapSearch.searchIn(e)}}],[{key:"type",get:function(){return"fuzzy"}},{key:"multiRegex",get:function(){return/^"(.*)"$/}},{key:"singleRegex",get:function(){return/^(.*)$/}}]),n}(z),H=function(e){a(n,e);var t=l(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){for(var t,n=0,r=[],i=this.pattern.length;(t=e.indexOf(this.pattern,n))>-1;)n=t+i,r.push([t,n-1]);var o=!!r.length;return{isMatch:o,score:o?0:1,indices:r}}}],[{key:"type",get:function(){return"include"}},{key:"multiRegex",get:function(){return/^'"(.*)"$/}},{key:"singleRegex",get:function(){return/^'(.*)$/}}]),n}(z),Q=[K,H,B,J,V,U,q,G],X=Q.length,Y=/ +(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/;function Z(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return e.split("|").map((function(e){for(var n=e.trim().split(Y).filter((function(e){return e&&!!e.trim()})),r=[],i=0,o=n.length;i1&&void 0!==arguments[1]?arguments[1]:{},i=n.isCaseSensitive,o=void 0===i?I.isCaseSensitive:i,c=n.includeMatches,a=void 0===c?I.includeMatches:c,s=n.minMatchCharLength,u=void 0===s?I.minMatchCharLength:s,h=n.ignoreLocation,l=void 0===h?I.ignoreLocation:h,f=n.findAllMatches,d=void 0===f?I.findAllMatches:f,v=n.location,g=void 0===v?I.location:v,y=n.threshold,p=void 0===y?I.threshold:y,m=n.distance,k=void 0===m?I.distance:m;r(this,e),this.query=null,this.options={isCaseSensitive:o,includeMatches:a,minMatchCharLength:u,findAllMatches:d,ignoreLocation:l,location:g,threshold:p,distance:k},this.pattern=o?t:t.toLowerCase(),this.query=Z(this.pattern,this.options)}return o(e,[{key:"searchIn",value:function(e){var t=this.query;if(!t)return{isMatch:!1,score:1};var n=this.options,r=n.includeMatches;e=n.isCaseSensitive?e:e.toLowerCase();for(var i=0,o=[],c=0,a=0,s=t.length;a-1&&(n.refIndex=e.idx),t.matches.push(n)}}))}function ve(e,t){t.score=e.score}function ge(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=n.includeMatches,i=void 0===r?I.includeMatches:r,o=n.includeScore,c=void 0===o?I.includeScore:o,a=[];return i&&a.push(de),c&&a.push(ve),e.map((function(e){var n=e.idx,r={item:t[n],refIndex:n};return a.length&&a.forEach((function(t){t(e,r)})),r}))}var ye=function(){function e(n){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o=arguments.length>2?arguments[2]:void 0;r(this,e),this.options=t(t({},I),i),this.options.useExtendedSearch,this._keyStore=new S(this.options.keys),this.setCollection(n,o)}return o(e,[{key:"setCollection",value:function(e,t){if(this._docs=e,t&&!(t instanceof $))throw new Error("Incorrect 'index' type");this._myIndex=t||F(this.options.keys,this._docs,{getFn:this.options.getFn,fieldNormWeight:this.options.fieldNormWeight})}},{key:"add",value:function(e){k(e)&&(this._docs.push(e),this._myIndex.add(e))}},{key:"remove",value:function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:function(){return!1},t=[],n=0,r=this._docs.length;n1&&void 0!==arguments[1]?arguments[1]:{},n=t.limit,r=void 0===n?-1:n,i=this.options,o=i.includeMatches,c=i.includeScore,a=i.shouldSort,s=i.sortFn,u=i.ignoreFieldNorm,h=g(e)?g(this._docs[0])?this._searchStringList(e):this._searchObjectList(e):this._searchLogical(e);return fe(h,{ignoreFieldNorm:u}),a&&h.sort(s),y(r)&&r>-1&&(h=h.slice(0,r)),ge(h,this._docs,{includeMatches:o,includeScore:c})}},{key:"_searchStringList",value:function(e){var t=re(e,this.options),n=this._myIndex.records,r=[];return n.forEach((function(e){var n=e.v,i=e.i,o=e.n;if(k(n)){var c=t.searchIn(n),a=c.isMatch,s=c.score,u=c.indices;a&&r.push({item:n,idx:i,matches:[{score:s,value:n,norm:o,indices:u}]})}})),r}},{key:"_searchLogical",value:function(e){var t=this,n=function(e,t){var n=(arguments.length>2&&void 0!==arguments[2]?arguments[2]:{}).auto,r=void 0===n||n,i=function e(n){var i=Object.keys(n),o=ue(n);if(!o&&i.length>1&&!se(n))return e(le(n));if(he(n)){var c=o?n[ce]:i[0],a=o?n[ae]:n[c];if(!g(a))throw new Error(x(c));var s={keyId:j(c),pattern:a};return r&&(s.searcher=re(a,t)),s}var u={children:[],operator:i[0]};return i.forEach((function(t){var r=n[t];v(r)&&r.forEach((function(t){u.children.push(e(t))}))})),u};return se(e)||(e=le(e)),i(e)}(e,this.options),r=function e(n,r,i){if(!n.children){var o=n.keyId,c=n.searcher,a=t._findMatches({key:t._keyStore.get(o),value:t._myIndex.getValueForItemAtKeyId(r,o),searcher:c});return a&&a.length?[{idx:i,item:r,matches:a}]:[]}for(var s=[],u=0,h=n.children.length;u1&&void 0!==arguments[1]?arguments[1]:{},n=t.getFn,r=void 0===n?I.getFn:n,i=t.fieldNormWeight,o=void 0===i?I.fieldNormWeight:i,c=e.keys,a=e.records,s=new $({getFn:r,fieldNormWeight:o});return s.setKeys(c),s.setIndexRecords(a),s},ye.config=I,function(){ne.push.apply(ne,arguments)}(te),ye},"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Fuse=t(); \ No newline at end of file diff --git a/site_libs/quarto-search/quarto-search.js b/site_libs/quarto-search/quarto-search.js new file mode 100644 index 00000000..d788a958 --- /dev/null +++ b/site_libs/quarto-search/quarto-search.js @@ -0,0 +1,1290 @@ +const kQueryArg = "q"; +const kResultsArg = "show-results"; + +// If items don't provide a URL, then both the navigator and the onSelect +// function aren't called (and therefore, the default implementation is used) +// +// We're using this sentinel URL to signal to those handlers that this +// item is a more item (along with the type) and can be handled appropriately +const kItemTypeMoreHref = "0767FDFD-0422-4E5A-BC8A-3BE11E5BBA05"; + +window.document.addEventListener("DOMContentLoaded", function (_event) { + // Ensure that search is available on this page. If it isn't, + // should return early and not do anything + var searchEl = window.document.getElementById("quarto-search"); + if (!searchEl) return; + + const { autocomplete } = window["@algolia/autocomplete-js"]; + + let quartoSearchOptions = {}; + let language = {}; + const searchOptionEl = window.document.getElementById( + "quarto-search-options" + ); + if (searchOptionEl) { + const jsonStr = searchOptionEl.textContent; + quartoSearchOptions = JSON.parse(jsonStr); + language = quartoSearchOptions.language; + } + + // note the search mode + if (quartoSearchOptions.type === "overlay") { + searchEl.classList.add("type-overlay"); + } else { + searchEl.classList.add("type-textbox"); + } + + // Used to determine highlighting behavior for this page + // A `q` query param is expected when the user follows a search + // to this page + const currentUrl = new URL(window.location); + const query = currentUrl.searchParams.get(kQueryArg); + const showSearchResults = currentUrl.searchParams.get(kResultsArg); + const mainEl = window.document.querySelector("main"); + + // highlight matches on the page + if (query && mainEl) { + // perform any highlighting + highlight(escapeRegExp(query), mainEl); + + // fix up the URL to remove the q query param + const replacementUrl = new URL(window.location); + replacementUrl.searchParams.delete(kQueryArg); + window.history.replaceState({}, "", replacementUrl); + } + + // function to clear highlighting on the page when the search query changes + // (e.g. if the user edits the query or clears it) + let highlighting = true; + const resetHighlighting = (searchTerm) => { + if (mainEl && highlighting && query && searchTerm !== query) { + clearHighlight(query, mainEl); + highlighting = false; + } + }; + + // Clear search highlighting when the user scrolls sufficiently + const resetFn = () => { + resetHighlighting(""); + window.removeEventListener("quarto-hrChanged", resetFn); + window.removeEventListener("quarto-sectionChanged", resetFn); + }; + + // Register this event after the initial scrolling and settling of events + // on the page + window.addEventListener("quarto-hrChanged", resetFn); + window.addEventListener("quarto-sectionChanged", resetFn); + + // Responsively switch to overlay mode if the search is present on the navbar + // Note that switching the sidebar to overlay mode requires more coordinate (not just + // the media query since we generate different HTML for sidebar overlays than we do + // for sidebar input UI) + const detachedMediaQuery = + quartoSearchOptions.type === "overlay" ? "all" : "(max-width: 991px)"; + + // If configured, include the analytics client to send insights + const plugins = configurePlugins(quartoSearchOptions); + + let lastState = null; + const { setIsOpen, setQuery, setCollections } = autocomplete({ + container: searchEl, + detachedMediaQuery: detachedMediaQuery, + defaultActiveItemId: 0, + panelContainer: "#quarto-search-results", + panelPlacement: quartoSearchOptions["panel-placement"], + debug: false, + openOnFocus: true, + plugins, + classNames: { + form: "d-flex", + }, + placeholder: language["search-text-placeholder"], + translations: { + clearButtonTitle: language["search-clear-button-title"], + detachedCancelButtonText: language["search-detached-cancel-button-title"], + submitButtonTitle: language["search-submit-button-title"], + }, + initialState: { + query, + }, + getItemUrl({ item }) { + return item.href; + }, + onStateChange({ state }) { + // If this is a file URL, note that + + // Perhaps reset highlighting + resetHighlighting(state.query); + + // If the panel just opened, ensure the panel is positioned properly + if (state.isOpen) { + if (lastState && !lastState.isOpen) { + setTimeout(() => { + positionPanel(quartoSearchOptions["panel-placement"]); + }, 150); + } + } + + // Perhaps show the copy link + showCopyLink(state.query, quartoSearchOptions); + + lastState = state; + }, + reshape({ sources, state }) { + return sources.map((source) => { + try { + const items = source.getItems(); + + // Validate the items + validateItems(items); + + // group the items by document + const groupedItems = new Map(); + items.forEach((item) => { + const hrefParts = item.href.split("#"); + const baseHref = hrefParts[0]; + const isDocumentItem = hrefParts.length === 1; + + const items = groupedItems.get(baseHref); + if (!items) { + groupedItems.set(baseHref, [item]); + } else { + // If the href for this item matches the document + // exactly, place this item first as it is the item that represents + // the document itself + if (isDocumentItem) { + items.unshift(item); + } else { + items.push(item); + } + groupedItems.set(baseHref, items); + } + }); + + const reshapedItems = []; + let count = 1; + for (const [_key, value] of groupedItems) { + const firstItem = value[0]; + reshapedItems.push({ + ...firstItem, + type: kItemTypeDoc, + }); + + const collapseMatches = quartoSearchOptions["collapse-after"]; + const collapseCount = + typeof collapseMatches === "number" ? collapseMatches : 1; + + if (value.length > 1) { + const target = `search-more-${count}`; + const isExpanded = + state.context.expanded && + state.context.expanded.includes(target); + + const remainingCount = value.length - collapseCount; + + for (let i = 1; i < value.length; i++) { + if (collapseMatches && i === collapseCount) { + reshapedItems.push({ + target, + title: isExpanded + ? language["search-hide-matches-text"] + : remainingCount === 1 + ? `${remainingCount} ${language["search-more-match-text"]}` + : `${remainingCount} ${language["search-more-matches-text"]}`, + type: kItemTypeMore, + href: kItemTypeMoreHref, + }); + } + + if (isExpanded || !collapseMatches || i < collapseCount) { + reshapedItems.push({ + ...value[i], + type: kItemTypeItem, + target, + }); + } + } + } + count += 1; + } + + return { + ...source, + getItems() { + return reshapedItems; + }, + }; + } catch (error) { + // Some form of error occurred + return { + ...source, + getItems() { + return [ + { + title: error.name || "An Error Occurred While Searching", + text: + error.message || + "An unknown error occurred while attempting to perform the requested search.", + type: kItemTypeError, + }, + ]; + }, + }; + } + }); + }, + navigator: { + navigate({ itemUrl }) { + if (itemUrl !== offsetURL(kItemTypeMoreHref)) { + window.location.assign(itemUrl); + } + }, + navigateNewTab({ itemUrl }) { + if (itemUrl !== offsetURL(kItemTypeMoreHref)) { + const windowReference = window.open(itemUrl, "_blank", "noopener"); + if (windowReference) { + windowReference.focus(); + } + } + }, + navigateNewWindow({ itemUrl }) { + if (itemUrl !== offsetURL(kItemTypeMoreHref)) { + window.open(itemUrl, "_blank", "noopener"); + } + }, + }, + getSources({ state, setContext, setActiveItemId, refresh }) { + return [ + { + sourceId: "documents", + getItemUrl({ item }) { + if (item.href) { + return offsetURL(item.href); + } else { + return undefined; + } + }, + onSelect({ + item, + state, + setContext, + setIsOpen, + setActiveItemId, + refresh, + }) { + if (item.type === kItemTypeMore) { + toggleExpanded(item, state, setContext, setActiveItemId, refresh); + + // Toggle more + setIsOpen(true); + } + }, + getItems({ query }) { + if (query === null || query === "") { + return []; + } + + const limit = quartoSearchOptions.limit; + if (quartoSearchOptions.algolia) { + return algoliaSearch(query, limit, quartoSearchOptions.algolia); + } else { + // Fuse search options + const fuseSearchOptions = { + isCaseSensitive: false, + shouldSort: true, + minMatchCharLength: 2, + limit: limit, + }; + + return readSearchData().then(function (fuse) { + return fuseSearch(query, fuse, fuseSearchOptions); + }); + } + }, + templates: { + noResults({ createElement }) { + const hasQuery = lastState.query; + + return createElement( + "div", + { + class: `quarto-search-no-results${ + hasQuery ? "" : " no-query" + }`, + }, + language["search-no-results-text"] + ); + }, + header({ items, createElement }) { + // count the documents + const count = items.filter((item) => { + return item.type === kItemTypeDoc; + }).length; + + if (count > 0) { + return createElement( + "div", + { class: "search-result-header" }, + `${count} ${language["search-matching-documents-text"]}` + ); + } else { + return createElement( + "div", + { class: "search-result-header-no-results" }, + `` + ); + } + }, + footer({ _items, createElement }) { + if ( + quartoSearchOptions.algolia && + quartoSearchOptions.algolia["show-logo"] + ) { + const libDir = quartoSearchOptions.algolia["libDir"]; + const logo = createElement("img", { + src: offsetURL( + `${libDir}/quarto-search/search-by-algolia.svg` + ), + class: "algolia-search-logo", + }); + return createElement( + "a", + { href: "http://www.algolia.com/" }, + logo + ); + } + }, + + item({ item, createElement }) { + return renderItem( + item, + createElement, + state, + setActiveItemId, + setContext, + refresh, + quartoSearchOptions + ); + }, + }, + }, + ]; + }, + }); + + window.quartoOpenSearch = () => { + setIsOpen(false); + setIsOpen(true); + focusSearchInput(); + }; + + document.addEventListener("keyup", (event) => { + const { key } = event; + const kbds = quartoSearchOptions["keyboard-shortcut"]; + const focusedEl = document.activeElement; + + const isFormElFocused = [ + "input", + "select", + "textarea", + "button", + "option", + ].find((tag) => { + return focusedEl.tagName.toLowerCase() === tag; + }); + + if ( + kbds && + kbds.includes(key) && + !isFormElFocused && + !document.activeElement.isContentEditable + ) { + event.preventDefault(); + window.quartoOpenSearch(); + } + }); + + // Remove the labeleledby attribute since it is pointing + // to a non-existent label + if (quartoSearchOptions.type === "overlay") { + const inputEl = window.document.querySelector( + "#quarto-search .aa-Autocomplete" + ); + if (inputEl) { + inputEl.removeAttribute("aria-labelledby"); + } + } + + function throttle(func, wait) { + let waiting = false; + return function () { + if (!waiting) { + func.apply(this, arguments); + waiting = true; + setTimeout(function () { + waiting = false; + }, wait); + } + }; + } + + // If the main document scrolls dismiss the search results + // (otherwise, since they're floating in the document they can scroll with the document) + window.document.body.onscroll = throttle(() => { + // Only do this if we're not detached + // Bug #7117 + // This will happen when the keyboard is shown on ios (resulting in a scroll) + // which then closed the search UI + if (!window.matchMedia(detachedMediaQuery).matches) { + setIsOpen(false); + } + }, 50); + + if (showSearchResults) { + setIsOpen(true); + focusSearchInput(); + } +}); + +function configurePlugins(quartoSearchOptions) { + const autocompletePlugins = []; + const algoliaOptions = quartoSearchOptions.algolia; + if ( + algoliaOptions && + algoliaOptions["analytics-events"] && + algoliaOptions["search-only-api-key"] && + algoliaOptions["application-id"] + ) { + const apiKey = algoliaOptions["search-only-api-key"]; + const appId = algoliaOptions["application-id"]; + + // Aloglia insights may not be loaded because they require cookie consent + // Use deferred loading so events will start being recorded when/if consent + // is granted. + const algoliaInsightsDeferredPlugin = deferredLoadPlugin(() => { + if ( + window.aa && + window["@algolia/autocomplete-plugin-algolia-insights"] + ) { + window.aa("init", { + appId, + apiKey, + useCookie: true, + }); + + const { createAlgoliaInsightsPlugin } = + window["@algolia/autocomplete-plugin-algolia-insights"]; + // Register the insights client + const algoliaInsightsPlugin = createAlgoliaInsightsPlugin({ + insightsClient: window.aa, + onItemsChange({ insights, insightsEvents }) { + const events = insightsEvents.flatMap((event) => { + // This API limits the number of items per event to 20 + const chunkSize = 20; + const itemChunks = []; + const eventItems = event.items; + for (let i = 0; i < eventItems.length; i += chunkSize) { + itemChunks.push(eventItems.slice(i, i + chunkSize)); + } + // Split the items into multiple events that can be sent + const events = itemChunks.map((items) => { + return { + ...event, + items, + }; + }); + return events; + }); + + for (const event of events) { + insights.viewedObjectIDs(event); + } + }, + }); + return algoliaInsightsPlugin; + } + }); + + // Add the plugin + autocompletePlugins.push(algoliaInsightsDeferredPlugin); + return autocompletePlugins; + } +} + +// For plugins that may not load immediately, create a wrapper +// plugin and forward events and plugin data once the plugin +// is initialized. This is useful for cases like cookie consent +// which may prevent the analytics insights event plugin from initializing +// immediately. +function deferredLoadPlugin(createPlugin) { + let plugin = undefined; + let subscribeObj = undefined; + const wrappedPlugin = () => { + if (!plugin && subscribeObj) { + plugin = createPlugin(); + if (plugin && plugin.subscribe) { + plugin.subscribe(subscribeObj); + } + } + return plugin; + }; + + return { + subscribe: (obj) => { + subscribeObj = obj; + }, + onStateChange: (obj) => { + const plugin = wrappedPlugin(); + if (plugin && plugin.onStateChange) { + plugin.onStateChange(obj); + } + }, + onSubmit: (obj) => { + const plugin = wrappedPlugin(); + if (plugin && plugin.onSubmit) { + plugin.onSubmit(obj); + } + }, + onReset: (obj) => { + const plugin = wrappedPlugin(); + if (plugin && plugin.onReset) { + plugin.onReset(obj); + } + }, + getSources: (obj) => { + const plugin = wrappedPlugin(); + if (plugin && plugin.getSources) { + return plugin.getSources(obj); + } else { + return Promise.resolve([]); + } + }, + data: (obj) => { + const plugin = wrappedPlugin(); + if (plugin && plugin.data) { + plugin.data(obj); + } + }, + }; +} + +function validateItems(items) { + // Validate the first item + if (items.length > 0) { + const item = items[0]; + const missingFields = []; + if (item.href == undefined) { + missingFields.push("href"); + } + if (!item.title == undefined) { + missingFields.push("title"); + } + if (!item.text == undefined) { + missingFields.push("text"); + } + + if (missingFields.length === 1) { + throw { + name: `Error: Search index is missing the ${missingFields[0]} field.`, + message: `The items being returned for this search do not include all the required fields. Please ensure that your index items include the ${missingFields[0]} field or use index-fields in your _quarto.yml file to specify the field names.`, + }; + } else if (missingFields.length > 1) { + const missingFieldList = missingFields + .map((field) => { + return `${field}`; + }) + .join(", "); + + throw { + name: `Error: Search index is missing the following fields: ${missingFieldList}.`, + message: `The items being returned for this search do not include all the required fields. Please ensure that your index items includes the following fields: ${missingFieldList}, or use index-fields in your _quarto.yml file to specify the field names.`, + }; + } + } +} + +let lastQuery = null; +function showCopyLink(query, options) { + const language = options.language; + lastQuery = query; + // Insert share icon + const inputSuffixEl = window.document.body.querySelector( + ".aa-Form .aa-InputWrapperSuffix" + ); + + if (inputSuffixEl) { + let copyButtonEl = window.document.body.querySelector( + ".aa-Form .aa-InputWrapperSuffix .aa-CopyButton" + ); + + if (copyButtonEl === null) { + copyButtonEl = window.document.createElement("button"); + copyButtonEl.setAttribute("class", "aa-CopyButton"); + copyButtonEl.setAttribute("type", "button"); + copyButtonEl.setAttribute("title", language["search-copy-link-title"]); + copyButtonEl.onmousedown = (e) => { + e.preventDefault(); + e.stopPropagation(); + }; + + const linkIcon = "bi-clipboard"; + const checkIcon = "bi-check2"; + + const shareIconEl = window.document.createElement("i"); + shareIconEl.setAttribute("class", `bi ${linkIcon}`); + copyButtonEl.appendChild(shareIconEl); + inputSuffixEl.prepend(copyButtonEl); + + const clipboard = new window.ClipboardJS(".aa-CopyButton", { + text: function (_trigger) { + const copyUrl = new URL(window.location); + copyUrl.searchParams.set(kQueryArg, lastQuery); + copyUrl.searchParams.set(kResultsArg, "1"); + return copyUrl.toString(); + }, + }); + clipboard.on("success", function (e) { + // Focus the input + + // button target + const button = e.trigger; + const icon = button.querySelector("i.bi"); + + // flash "checked" + icon.classList.add(checkIcon); + icon.classList.remove(linkIcon); + setTimeout(function () { + icon.classList.remove(checkIcon); + icon.classList.add(linkIcon); + }, 1000); + }); + } + + // If there is a query, show the link icon + if (copyButtonEl) { + if (lastQuery && options["copy-button"]) { + copyButtonEl.style.display = "flex"; + } else { + copyButtonEl.style.display = "none"; + } + } + } +} + +/* Search Index Handling */ +// create the index +var fuseIndex = undefined; +var shownWarning = false; + +// fuse index options +const kFuseIndexOptions = { + keys: [ + { name: "title", weight: 20 }, + { name: "section", weight: 20 }, + { name: "text", weight: 10 }, + ], + ignoreLocation: true, + threshold: 0.1, +}; + +async function readSearchData() { + // Initialize the search index on demand + if (fuseIndex === undefined) { + if (window.location.protocol === "file:" && !shownWarning) { + window.alert( + "Search requires JavaScript features disabled when running in file://... URLs. In order to use search, please run this document in a web server." + ); + shownWarning = true; + return; + } + const fuse = new window.Fuse([], kFuseIndexOptions); + + // fetch the main search.json + const response = await fetch(offsetURL("search.json")); + if (response.status == 200) { + return response.json().then(function (searchDocs) { + searchDocs.forEach(function (searchDoc) { + fuse.add(searchDoc); + }); + fuseIndex = fuse; + return fuseIndex; + }); + } else { + return Promise.reject( + new Error( + "Unexpected status from search index request: " + response.status + ) + ); + } + } + + return fuseIndex; +} + +function inputElement() { + return window.document.body.querySelector(".aa-Form .aa-Input"); +} + +function focusSearchInput() { + setTimeout(() => { + const inputEl = inputElement(); + if (inputEl) { + inputEl.focus(); + } + }, 50); +} + +/* Panels */ +const kItemTypeDoc = "document"; +const kItemTypeMore = "document-more"; +const kItemTypeItem = "document-item"; +const kItemTypeError = "error"; + +function renderItem( + item, + createElement, + state, + setActiveItemId, + setContext, + refresh, + quartoSearchOptions +) { + switch (item.type) { + case kItemTypeDoc: + return createDocumentCard( + createElement, + "file-richtext", + item.title, + item.section, + item.text, + item.href, + item.crumbs, + quartoSearchOptions + ); + case kItemTypeMore: + return createMoreCard( + createElement, + item, + state, + setActiveItemId, + setContext, + refresh + ); + case kItemTypeItem: + return createSectionCard( + createElement, + item.section, + item.text, + item.href + ); + case kItemTypeError: + return createErrorCard(createElement, item.title, item.text); + default: + return undefined; + } +} + +function createDocumentCard( + createElement, + icon, + title, + section, + text, + href, + crumbs, + quartoSearchOptions +) { + const iconEl = createElement("i", { + class: `bi bi-${icon} search-result-icon`, + }); + const titleEl = createElement("p", { class: "search-result-title" }, title); + const titleContents = [iconEl, titleEl]; + const showParent = quartoSearchOptions["show-item-context"]; + if (crumbs && showParent) { + let crumbsOut = undefined; + const crumbClz = ["search-result-crumbs"]; + if (showParent === "root") { + crumbsOut = crumbs.length > 1 ? crumbs[0] : undefined; + } else if (showParent === "parent") { + crumbsOut = crumbs.length > 1 ? crumbs[crumbs.length - 2] : undefined; + } else { + crumbsOut = crumbs.length > 1 ? crumbs.join(" > ") : undefined; + crumbClz.push("search-result-crumbs-wrap"); + } + + const crumbEl = createElement( + "p", + { class: crumbClz.join(" ") }, + crumbsOut + ); + titleContents.push(crumbEl); + } + + const titleContainerEl = createElement( + "div", + { class: "search-result-title-container" }, + titleContents + ); + + const textEls = []; + if (section) { + const sectionEl = createElement( + "p", + { class: "search-result-section" }, + section + ); + textEls.push(sectionEl); + } + const descEl = createElement("p", { + class: "search-result-text", + dangerouslySetInnerHTML: { + __html: text, + }, + }); + textEls.push(descEl); + + const textContainerEl = createElement( + "div", + { class: "search-result-text-container" }, + textEls + ); + + const containerEl = createElement( + "div", + { + class: "search-result-container", + }, + [titleContainerEl, textContainerEl] + ); + + const linkEl = createElement( + "a", + { + href: offsetURL(href), + class: "search-result-link", + }, + containerEl + ); + + const classes = ["search-result-doc", "search-item"]; + if (!section) { + classes.push("document-selectable"); + } + + return createElement( + "div", + { + class: classes.join(" "), + }, + linkEl + ); +} + +function createMoreCard( + createElement, + item, + state, + setActiveItemId, + setContext, + refresh +) { + const moreCardEl = createElement( + "div", + { + class: "search-result-more search-item", + onClick: (e) => { + // Handle expanding the sections by adding the expanded + // section to the list of expanded sections + toggleExpanded(item, state, setContext, setActiveItemId, refresh); + e.stopPropagation(); + }, + }, + item.title + ); + + return moreCardEl; +} + +function toggleExpanded(item, state, setContext, setActiveItemId, refresh) { + const expanded = state.context.expanded || []; + if (expanded.includes(item.target)) { + setContext({ + expanded: expanded.filter((target) => target !== item.target), + }); + } else { + setContext({ expanded: [...expanded, item.target] }); + } + + refresh(); + setActiveItemId(item.__autocomplete_id); +} + +function createSectionCard(createElement, section, text, href) { + const sectionEl = createSection(createElement, section, text, href); + return createElement( + "div", + { + class: "search-result-doc-section search-item", + }, + sectionEl + ); +} + +function createSection(createElement, title, text, href) { + const descEl = createElement("p", { + class: "search-result-text", + dangerouslySetInnerHTML: { + __html: text, + }, + }); + + const titleEl = createElement("p", { class: "search-result-section" }, title); + const linkEl = createElement( + "a", + { + href: offsetURL(href), + class: "search-result-link", + }, + [titleEl, descEl] + ); + return linkEl; +} + +function createErrorCard(createElement, title, text) { + const descEl = createElement("p", { + class: "search-error-text", + dangerouslySetInnerHTML: { + __html: text, + }, + }); + + const titleEl = createElement("p", { + class: "search-error-title", + dangerouslySetInnerHTML: { + __html: ` ${title}`, + }, + }); + const errorEl = createElement("div", { class: "search-error" }, [ + titleEl, + descEl, + ]); + return errorEl; +} + +function positionPanel(pos) { + const panelEl = window.document.querySelector( + "#quarto-search-results .aa-Panel" + ); + const inputEl = window.document.querySelector( + "#quarto-search .aa-Autocomplete" + ); + + if (panelEl && inputEl) { + panelEl.style.top = `${Math.round(panelEl.offsetTop)}px`; + if (pos === "start") { + panelEl.style.left = `${Math.round(inputEl.left)}px`; + } else { + panelEl.style.right = `${Math.round(inputEl.offsetRight)}px`; + } + } +} + +/* Highlighting */ +// highlighting functions +function highlightMatch(query, text) { + if (text) { + const start = text.toLowerCase().indexOf(query.toLowerCase()); + if (start !== -1) { + const startMark = ""; + const endMark = ""; + + const end = start + query.length; + text = + text.slice(0, start) + + startMark + + text.slice(start, end) + + endMark + + text.slice(end); + const startInfo = clipStart(text, start); + const endInfo = clipEnd( + text, + startInfo.position + startMark.length + endMark.length + ); + text = + startInfo.prefix + + text.slice(startInfo.position, endInfo.position) + + endInfo.suffix; + + return text; + } else { + return text; + } + } else { + return text; + } +} + +function clipStart(text, pos) { + const clipStart = pos - 50; + if (clipStart < 0) { + // This will just return the start of the string + return { + position: 0, + prefix: "", + }; + } else { + // We're clipping before the start of the string, walk backwards to the first space. + const spacePos = findSpace(text, pos, -1); + return { + position: spacePos.position, + prefix: "", + }; + } +} + +function clipEnd(text, pos) { + const clipEnd = pos + 200; + if (clipEnd > text.length) { + return { + position: text.length, + suffix: "", + }; + } else { + const spacePos = findSpace(text, clipEnd, 1); + return { + position: spacePos.position, + suffix: spacePos.clipped ? "…" : "", + }; + } +} + +function findSpace(text, start, step) { + let stepPos = start; + while (stepPos > -1 && stepPos < text.length) { + const char = text[stepPos]; + if (char === " " || char === "," || char === ":") { + return { + position: step === 1 ? stepPos : stepPos - step, + clipped: stepPos > 1 && stepPos < text.length, + }; + } + stepPos = stepPos + step; + } + + return { + position: stepPos - step, + clipped: false, + }; +} + +// removes highlighting as implemented by the mark tag +function clearHighlight(searchterm, el) { + const childNodes = el.childNodes; + for (let i = childNodes.length - 1; i >= 0; i--) { + const node = childNodes[i]; + if (node.nodeType === Node.ELEMENT_NODE) { + if ( + node.tagName === "MARK" && + node.innerText.toLowerCase() === searchterm.toLowerCase() + ) { + el.replaceChild(document.createTextNode(node.innerText), node); + } else { + clearHighlight(searchterm, node); + } + } + } +} + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string +} + +// highlight matches +function highlight(term, el) { + const termRegex = new RegExp(term, "ig"); + const childNodes = el.childNodes; + + // walk back to front avoid mutating elements in front of us + for (let i = childNodes.length - 1; i >= 0; i--) { + const node = childNodes[i]; + + if (node.nodeType === Node.TEXT_NODE) { + // Search text nodes for text to highlight + const text = node.nodeValue; + + let startIndex = 0; + let matchIndex = text.search(termRegex); + if (matchIndex > -1) { + const markFragment = document.createDocumentFragment(); + while (matchIndex > -1) { + const prefix = text.slice(startIndex, matchIndex); + markFragment.appendChild(document.createTextNode(prefix)); + + const mark = document.createElement("mark"); + mark.appendChild( + document.createTextNode( + text.slice(matchIndex, matchIndex + term.length) + ) + ); + markFragment.appendChild(mark); + + startIndex = matchIndex + term.length; + matchIndex = text.slice(startIndex).search(new RegExp(term, "ig")); + if (matchIndex > -1) { + matchIndex = startIndex + matchIndex; + } + } + if (startIndex < text.length) { + markFragment.appendChild( + document.createTextNode(text.slice(startIndex, text.length)) + ); + } + + el.replaceChild(markFragment, node); + } + } else if (node.nodeType === Node.ELEMENT_NODE) { + // recurse through elements + highlight(term, node); + } + } +} + +/* Link Handling */ +// get the offset from this page for a given site root relative url +function offsetURL(url) { + var offset = getMeta("quarto:offset"); + return offset ? offset + url : url; +} + +// read a meta tag value +function getMeta(metaName) { + var metas = window.document.getElementsByTagName("meta"); + for (let i = 0; i < metas.length; i++) { + if (metas[i].getAttribute("name") === metaName) { + return metas[i].getAttribute("content"); + } + } + return ""; +} + +function algoliaSearch(query, limit, algoliaOptions) { + const { getAlgoliaResults } = window["@algolia/autocomplete-preset-algolia"]; + + const applicationId = algoliaOptions["application-id"]; + const searchOnlyApiKey = algoliaOptions["search-only-api-key"]; + const indexName = algoliaOptions["index-name"]; + const indexFields = algoliaOptions["index-fields"]; + const searchClient = window.algoliasearch(applicationId, searchOnlyApiKey); + const searchParams = algoliaOptions["params"]; + const searchAnalytics = !!algoliaOptions["analytics-events"]; + + return getAlgoliaResults({ + searchClient, + queries: [ + { + indexName: indexName, + query, + params: { + hitsPerPage: limit, + clickAnalytics: searchAnalytics, + ...searchParams, + }, + }, + ], + transformResponse: (response) => { + if (!indexFields) { + return response.hits.map((hit) => { + return hit.map((item) => { + return { + ...item, + text: highlightMatch(query, item.text), + }; + }); + }); + } else { + const remappedHits = response.hits.map((hit) => { + return hit.map((item) => { + const newItem = { ...item }; + ["href", "section", "title", "text", "crumbs"].forEach( + (keyName) => { + const mappedName = indexFields[keyName]; + if ( + mappedName && + item[mappedName] !== undefined && + mappedName !== keyName + ) { + newItem[keyName] = item[mappedName]; + delete newItem[mappedName]; + } + } + ); + newItem.text = highlightMatch(query, newItem.text); + return newItem; + }); + }); + return remappedHits; + } + }, + }); +} + +let subSearchTerm = undefined; +let subSearchFuse = undefined; +const kFuseMaxWait = 125; + +async function fuseSearch(query, fuse, fuseOptions) { + let index = fuse; + // Fuse.js using the Bitap algorithm for text matching which runs in + // O(nm) time (no matter the structure of the text). In our case this + // means that long search terms mixed with large index gets very slow + // + // This injects a subIndex that will be used once the terms get long enough + // Usually making this subindex is cheap since there will typically be + // a subset of results matching the existing query + if (subSearchFuse !== undefined && query.startsWith(subSearchTerm)) { + // Use the existing subSearchFuse + index = subSearchFuse; + } else if (subSearchFuse !== undefined) { + // The term changed, discard the existing fuse + subSearchFuse = undefined; + subSearchTerm = undefined; + } + + // Search using the active fuse + const then = performance.now(); + const resultsRaw = await index.search(query, fuseOptions); + const now = performance.now(); + + const results = resultsRaw.map((result) => { + const addParam = (url, name, value) => { + const anchorParts = url.split("#"); + const baseUrl = anchorParts[0]; + const sep = baseUrl.search("\\?") > 0 ? "&" : "?"; + anchorParts[0] = baseUrl + sep + name + "=" + value; + return anchorParts.join("#"); + }; + + return { + title: result.item.title, + section: result.item.section, + href: addParam(result.item.href, kQueryArg, query), + text: highlightMatch(query, result.item.text), + crumbs: result.item.crumbs, + }; + }); + + // If we don't have a subfuse and the query is long enough, go ahead + // and create a subfuse to use for subsequent queries + if ( + now - then > kFuseMaxWait && + subSearchFuse === undefined && + resultsRaw.length < fuseOptions.limit + ) { + subSearchTerm = query; + subSearchFuse = new window.Fuse([], kFuseIndexOptions); + resultsRaw.forEach((rr) => { + subSearchFuse.add(rr.item); + }); + } + return results; +} diff --git a/site_libs/react-17.0.0/AUTHORS b/site_libs/react-17.0.0/AUTHORS new file mode 100644 index 00000000..770cdc8c --- /dev/null +++ b/site_libs/react-17.0.0/AUTHORS @@ -0,0 +1,696 @@ +39 <8398a7@gmail.com> +Aaron Franks +Aaron Gelter +Adam Bloomston +Adam Krebs +Adam Mark +Adam Solove +Adam Timberlake +Adam Zapletal +Ahmad Wali Sidiqi +Alan Plum +Alan Souza +Alan deLevie +Alastair Hole +Alex +Alex Boatwright +Alex Boyd +Alex Dajani +Alex Lopatin +Alex Mykyta +Alex Pien +Alex Smith +Alex Zelenskiy +Alexander Shtuchkin +Alexander Solovyov +Alexander Tseung +Alexandre Gaudencio +Alexey Raspopov +Alexey Shamrin +Ali Ukani +Andre Z Sanchez +Andreas Savvides +Andreas Svensson +Andres Kalle +Andres Suarez +Andrew Clark +Andrew Cobby +Andrew Davey +Andrew Henderson +Andrew Kulakov +Andrew Rasmussen +Andrew Sokolov +Andrew Zich +Andrey Popp <8mayday@gmail.com> +Anthony van der Hoorn +Anto Aravinth +Antonio Ruberto +Antti Ahti +Anuj Tomar +AoDev +April Arcus +Areeb Malik +Aria Buckles +Aria Stewart +Arian Faurtosh +Artem Nezvigin +Austin Wright +Ayman Osman +Baraa Hamodi +Bartosz Kaszubowski +Basarat Ali Syed +Battaile Fauber +Beau Smith +Ben Alpert +Ben Anderson +Ben Brooks +Ben Foxall +Ben Halpern +Ben Jaffe +Ben Moss +Ben Newman +Ben Ripkens +Benjamin Keen +Benjamin Leiken +Benjamin Woodruff +Benjy Cui +Bill Blanchard +Bill Fisher +Blaine Hatab +Blaine Kasten +Bob Eagan +Bob Ralian +Bob Renwick +Bobby +Bojan Mihelac +Bradley Spaulding +Brandon Bloom +Brandon Tilley +Brenard Cubacub +Brian Cooke +Brian Holt +Brian Hsu +Brian Kim +Brian Kung +Brian Reavis +Brian Rue +Bruno Škvorc +Cam Song +Cam Spiers +Cameron Chamberlain +Cameron Matheson +Carter Chung +Cassus Adam Banko +Cat Chen +Cedric Sohrauer +Cesar William Alvarenga +Changsoon Bok +Charles Marsh +Chase Adams +Cheng Lou +Chitharanjan Das +Chris Bolin +Chris Grovers +Chris Ha +Chris Rebert +Chris Sciolla +Christian Alfoni +Christian Oliff +Christian Roman +Christoffer Sawicki +Christoph Pojer +Christopher Monsanto +Clay Allsopp +Connor McSheffrey +Conor Hastings +Cory House +Cotton Hou +Craig Akimoto +Cristovao Verstraeten +Damien Pellier +Dan Abramov +Dan Fox +Dan Schafer +Daniel Carlsson +Daniel Cousens +Daniel Friesen +Daniel Gasienica +Daniel Hejl +Daniel Hejl +Daniel Lo Nigro +Daniel Mané +Daniel Miladinov +Daniel Rodgers-Pryor +Daniel Schonfeld +Danny Ben-David +Darcy +Daryl Lau +Darío Javier Cravero +Dave Galbraith +David Baker +David Ed Mellum +David Goldberg +David Granado +David Greenspan +David Hellsing +David Hu +David Khourshid +David Mininger +David Neubauer +David Percy +Dean Shi +Denis Sokolov +Deniss Jacenko +Dennis Johnson +Devon Blandin +Devon Harvey +Dmitrii Abramov +Dmitriy Rozhkov +Dmitry Blues +Dmitry Mazuro +Domenico Matteo +Don Abrams +Dongsheng Liu +Dustan Kasten +Dustin Getz +Dylan Harrington +Eduardo Garcia +Edvin Erikson +Elaine Fang +Enguerran +Eric Clemmons +Eric Eastwood +Eric Florenzano +Eric O'Connell +Eric Schoffstall +Erik Harper +Espen Hovlandsdal +Evan Coonrod +Evan Vosberg +Fabio M. Costa +Federico Rampazzo +Felipe Oliveira Carvalho +Felix Gnass +Felix Kling +Fernando Correia +Frankie Bagnardi +François-Xavier Bois +Fred Zhao +Freddy Rangel +Fyodor Ivanishchev +G Scott Olson +G. Kay Lee +Gabe Levi +Gajus Kuizinas +Gareth Nicholson +Garren Smith +Gavin McQuistin +Geert Pasteels +Geert-Jan Brits +George A Sisco III +Georgii Dolzhykov +Gilbert +Glen Mailer +Grant Timmerman +Greg Hurrell +Greg Perkins +Greg Roodt +Gregory +Guangqiang Dong +Guido Bouman +Harry Hull +Harry Marr +Harry Moreno +Harshad Sabne +Hekar Khani +Hendrik Swanepoel +Henrik Nyh +Henry Wong +Henry Zhu +Hideo Matsumoto +Hou Chia +Huang-Wei Chang +Hugo Agbonon +Hugo Jobling +Hyeock Kwon +Héliton Nordt +Ian Obermiller +Ignacio Carbajo +Igor Scekic +Ilia Pavlenkov +Ilya Shuklin +Ilyá Belsky +Ingvar Stepanyan +Irae Carvalho +Isaac Salier-Hellendag +Iurii Kucherov +Ivan Kozik +Ivan Krechetov +Ivan Vergiliev +J. Andrew Brassington +J. Renée Beach +JD Isaacks +JJ Weber +JW +Jack Zhang +Jackie Wung +Jacob Gable +Jacob Greenleaf +Jae Hun Ro +Jaeho Lee +Jaime Mingo +Jake Worth +Jakub Malinowski +James +James Brantly +James Burnett +James Friend +James Ide +James Long +James Pearce +James Seppi +James South +James Wen +Jamie Wong +Jamis Charles +Jamison Dance +Jan Hancic +Jan Kassens +Jan Raasch +Jared Forsyth +Jason +Jason Bonta +Jason Ly +Jason Miller +Jason Quense +Jason Trill +Jason Webster +Jay Jaeho Lee +Jean Lauliac +Jed Watson +Jeff Barczewski +Jeff Carpenter +Jeff Chan +Jeff Hicken +Jeff Kolesky +Jeff Morrison +Jeff Welch +Jeffrey Lin +Jeremy Fairbank +Jesse Skinner +Jignesh Kakadiya +Jim OBrien +Jim Sproch +Jimmy Jea +Jing Chen +Jinwoo Oh +Jinxiu Lee +Jiyeon Seo +Jody McIntyre +Joe Critchley +Joe Stein +Joel Auterson +Johannes Baiter +Johannes Emerich +Johannes Lumpe +John Heroy +John Ryan +John Watson +John-David Dalton +Jon Beebe +Jon Chester +Jon Hester +Jon Madison +Jon Scott Clark +Jon Tewksbury +Jonas Enlund +Jonas Gebhardt +Jonathan Hsu +Jonathan Persson +Jordan Harband +Jordan Walke +Jorrit Schippers +Joseph Nudell +Joseph Savona +Josh Bassett +Josh Duck +Josh Perez +Josh Yudaken +Joshua Evans +Joshua Go +Joshua Goldberg +Joshua Ma +João Valente +Juan Serrano +Julen Ruiz Aizpuru +Julian Viereck +Julien Bordellier +Julio Lopez +Jun Wu +Juraj Dudak +Justas Brazauskas +Justin Jaffray +Justin Robison +Justin Woo +Kale +Kamron Batman +Karl Mikkelsen +Karpich Dmitry +Keito Uchiyama +Ken Powers +Kent C. Dodds +Kevin Cheng <09chengk@gmail.com> +Kevin Coughlin +Kevin Huang +Kevin Lau +Kevin Old +Kevin Robinson +Kewei Jiang +Kier Borromeo +KimCoding +Kirk Steven Hansen +Kit Randel +Kohei TAKATA +Koo Youngmin +Krystian Karczewski +Kunal Mehta +Kurt Ruppel +Kyle Kelley +Kyle Mathews +Laurence Rowe +Laurent Etiemble +Lee Byron +Lee Jaeyoung +Lei +Leland Richardson +Leon Fedotov +Leon Yip +Leonardo YongUk Kim +Levi Buzolic +Levi McCallum +Lily +Logan Allen +Lovisa Svallingson +Ludovico Fischer +Luigy Leon +Luke Horvat +MIKAMI Yoshiyuki +Maher Beg +Manas +Marcin K. +Marcin Kwiatkowski +Marcin Szczepanski +Mariano Desanze +Marjan +Mark Anderson +Mark Funk +Mark Hintz +Mark IJbema +Mark Murphy +Mark Richardson +Mark Rushakoff +Mark Sun +Marlon Landaverde +Marshall Roch +Martin Andert +Martin Hujer +Martin Jul +Martin Konicek +Martin Mihaylov +Masaki KOBAYASHI +Mathieu M-Gosselin +Mathieu Savy +Matias Singers +Matsunoki +Matt Brookes +Matt Dunn-Rankin +Matt Harrison +Matt Huggins +Matt Stow +Matt Zabriskie +Matthew Dapena-Tretter +Matthew Herbst +Matthew Hodgson +Matthew Johnston +Matthew King +Matthew Looi +Matthew Miner +Matthias Le Brun +Matti Nelimarkka +Mattijs Kneppers +Max F. Albrecht <1@178.is> +Max Heiber +Max Stoiber +Maxi Ferreira +Maxim Abramchuk +Merrick Christensen +Mert Kahyaoğlu +Michael Chan +Michael McDermott +Michael Randers-Pehrson +Michael Ridgway +Michael Warner +Michael Wiencek +Michael Ziwisky +Michal Srb +Michelle Todd +Mihai Parparita +Mike D Pilsbury +Mike Groseclose +Mike Nordick +Mikolaj Dadela +Miles Johnson +Minwe LUO +Miorel Palii +Morhaus +Moshe Kolodny +Mouad Debbar +Murad +Murray M. Moss +Nadeesha Cabral +Naman Goel +Nate Hunzaker +Nate Lee +Nathan Smith +Nathan White +Nee <944316342@qq.com> +Neri Marschik +Nguyen Truong Duy +Nicholas Bergson-Shilcock +Nicholas Clawson +Nick Balestra +Nick Fitzgerald +Nick Gavalas +Nick Merwin +Nick Presta +Nick Raienko +Nick Thompson +Nick Williams +Niklas Boström +Ning Xia +Niole Nelson +Oiva Eskola +Oleg +Oleksii Markhovskyi +Oliver Zeigermann +Olivier Tassinari +Owen Coutts +Pablo Lacerda de Miranda +Paolo Moretti +Pascal Hartig +Patrick +Patrick Laughlin +Patrick Stapleton +Paul Benigeri +Paul Harper +Paul O’Shannessy +Paul Seiffert +Paul Shen +Pedro Nauck +Pete Hunt +Peter Blazejewicz +Peter Cottle +Peter Jaros +Peter Newnham +Petri Lehtinen +Petri Lievonen +Pieter Vanderwerff +Pouja Nikray +Prathamesh Sonpatki +Prayag Verma +Preston Parry +Rafael +Rafal Dittwald +Rainer Oviir +Rajat Sehgal +Rajiv Tirumalareddy +Ram Kaniyur +Randall Randall +Ray +Raymond Ha +Reed Loden +Remko Tronçon +Richard D. Worth +Richard Feldman +Richard Kho +Richard Littauer +Richard Livesey +Richard Wood +Rick Beerendonk +Rick Ford +Riley Tomasek +Rob Arnold +Robert Binna +Robert Knight +Robert Sedovsek +Robin Berjon +Robin Frischmann +Roman Pominov +Roman Vanesyan +Russ +Ryan Seddon +Sahat Yalkabov +Saif Hakim +Saiichi Hashimoto +Sam Beveridge +Sam Saccone +Sam Selikoff +Samy Al Zahrani +Sander Spies +Scott Burch +Scott Feeney +Sean Kinsey +Sebastian Markbåge +Sebastian McKenzie +Seoh Char +Sercan Eraslan +Serg +Sergey Generalov +Sergey Rubanov +Seyi Adebajo +Shane O'Sullivan +Shaun Trennery +ShihChi Huang +Shim Won +Shinnosuke Watanabe +Shogun Sea +Shota Kubota +Shripad K +Sibi +Simen Bekkhus +Simon Højberg +Simon Welsh +Simone Vittori +Soichiro Kawamura +Sophia Westwood +Sota Ohara +Spencer Handley +Stefan Dombrowski +Stephen Murphy +Sterling Cobb +Steve Baker <_steve_@outlook.com> +Steven Luscher +Steven Vachon +Stoyan Stefanov +Sundeep Malladi +Sunny Juneja +Sven Helmberger +Sverre Johansen +Sébastien Lorber +Sławomir Laskowski +Taeho Kim +Tay Yang Shun +Ted Kim +Tengfei Guo +Teodor Szente +Thomas Aylott +Thomas Boyt +Thomas Broadley +Thomas Reggi +Thomas Röggla +Thomas Shaddox +Thomas Shafer +ThomasCrvsr +Tienchai Wirojsaksaree +Tim Routowicz +Tim Schaub +Timothy Yung +Timur Carpeev +Tobias Reiss +Tom Duncalf +Tom Haggie +Tom Hauburger +Tom MacWright +Tom Occhino +Tomasz Kołodziejski +Tomoya Suzuki +Tony Spiro +Toru Kobayashi +Trinh Hoang Nhu +Tsung Hung +Tyler Brock +Ustin Zarubin +Vadim Chernysh +Varun Rau +Vasiliy Loginevskiy +Victor Alvarez +Victor Homyakov +Victor Koenders +Ville Immonen +Vincent Riemer +Vincent Siao +Vipul A M +Vitaly Kramskikh +Vitor Balocco +Vjeux +Volkan Unsal +Wander Wang +Wayne Larsen +WickyNilliams +Wincent Colaiuta +Wout Mertens +Xavier Morel +XuefengWu +Yakov Dalinchuk +Yasar icli +YouBao Nong +Yuichi Hagio +Yuriy Dybskiy +Yutaka Nakajima +Yuval Dekel +Zach Bruggeman +Zach Ramaekers +Zacharias +Zeke Sikelianos +Zhangjd +adraeth +arush +brafdlog +chen +clariroid +claudiopro +cutbko +davidxi +dongmeng.ldm +iamchenxin +iamdoron +iawia002 +imagentleman +koh-taka +kohashi85 +laiso +leeyoungalias +li.li +maxprafferty +rgarifullin +songawee +sugarshin +wali-s +yiminghe +youmoo +zhangjg +zwhitchcox +Árni Hermann Reynisson +元彦 +凌恒 +张敏 diff --git a/site_libs/react-17.0.0/LICENSE.txt b/site_libs/react-17.0.0/LICENSE.txt new file mode 100644 index 00000000..188fb2b0 --- /dev/null +++ b/site_libs/react-17.0.0/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2013-present, Facebook, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/site_libs/react-18.2.0/AUTHORS b/site_libs/react-18.2.0/AUTHORS new file mode 100644 index 00000000..770cdc8c --- /dev/null +++ b/site_libs/react-18.2.0/AUTHORS @@ -0,0 +1,696 @@ +39 <8398a7@gmail.com> +Aaron Franks +Aaron Gelter +Adam Bloomston +Adam Krebs +Adam Mark +Adam Solove +Adam Timberlake +Adam Zapletal +Ahmad Wali Sidiqi +Alan Plum +Alan Souza +Alan deLevie +Alastair Hole +Alex +Alex Boatwright +Alex Boyd +Alex Dajani +Alex Lopatin +Alex Mykyta +Alex Pien +Alex Smith +Alex Zelenskiy +Alexander Shtuchkin +Alexander Solovyov +Alexander Tseung +Alexandre Gaudencio +Alexey Raspopov +Alexey Shamrin +Ali Ukani +Andre Z Sanchez +Andreas Savvides +Andreas Svensson +Andres Kalle +Andres Suarez +Andrew Clark +Andrew Cobby +Andrew Davey +Andrew Henderson +Andrew Kulakov +Andrew Rasmussen +Andrew Sokolov +Andrew Zich +Andrey Popp <8mayday@gmail.com> +Anthony van der Hoorn +Anto Aravinth +Antonio Ruberto +Antti Ahti +Anuj Tomar +AoDev +April Arcus +Areeb Malik +Aria Buckles +Aria Stewart +Arian Faurtosh +Artem Nezvigin +Austin Wright +Ayman Osman +Baraa Hamodi +Bartosz Kaszubowski +Basarat Ali Syed +Battaile Fauber +Beau Smith +Ben Alpert +Ben Anderson +Ben Brooks +Ben Foxall +Ben Halpern +Ben Jaffe +Ben Moss +Ben Newman +Ben Ripkens +Benjamin Keen +Benjamin Leiken +Benjamin Woodruff +Benjy Cui +Bill Blanchard +Bill Fisher +Blaine Hatab +Blaine Kasten +Bob Eagan +Bob Ralian +Bob Renwick +Bobby +Bojan Mihelac +Bradley Spaulding +Brandon Bloom +Brandon Tilley +Brenard Cubacub +Brian Cooke +Brian Holt +Brian Hsu +Brian Kim +Brian Kung +Brian Reavis +Brian Rue +Bruno Škvorc +Cam Song +Cam Spiers +Cameron Chamberlain +Cameron Matheson +Carter Chung +Cassus Adam Banko +Cat Chen +Cedric Sohrauer +Cesar William Alvarenga +Changsoon Bok +Charles Marsh +Chase Adams +Cheng Lou +Chitharanjan Das +Chris Bolin +Chris Grovers +Chris Ha +Chris Rebert +Chris Sciolla +Christian Alfoni +Christian Oliff +Christian Roman +Christoffer Sawicki +Christoph Pojer +Christopher Monsanto +Clay Allsopp +Connor McSheffrey +Conor Hastings +Cory House +Cotton Hou +Craig Akimoto +Cristovao Verstraeten +Damien Pellier +Dan Abramov +Dan Fox +Dan Schafer +Daniel Carlsson +Daniel Cousens +Daniel Friesen +Daniel Gasienica +Daniel Hejl +Daniel Hejl +Daniel Lo Nigro +Daniel Mané +Daniel Miladinov +Daniel Rodgers-Pryor +Daniel Schonfeld +Danny Ben-David +Darcy +Daryl Lau +Darío Javier Cravero +Dave Galbraith +David Baker +David Ed Mellum +David Goldberg +David Granado +David Greenspan +David Hellsing +David Hu +David Khourshid +David Mininger +David Neubauer +David Percy +Dean Shi +Denis Sokolov +Deniss Jacenko +Dennis Johnson +Devon Blandin +Devon Harvey +Dmitrii Abramov +Dmitriy Rozhkov +Dmitry Blues +Dmitry Mazuro +Domenico Matteo +Don Abrams +Dongsheng Liu +Dustan Kasten +Dustin Getz +Dylan Harrington +Eduardo Garcia +Edvin Erikson +Elaine Fang +Enguerran +Eric Clemmons +Eric Eastwood +Eric Florenzano +Eric O'Connell +Eric Schoffstall +Erik Harper +Espen Hovlandsdal +Evan Coonrod +Evan Vosberg +Fabio M. Costa +Federico Rampazzo +Felipe Oliveira Carvalho +Felix Gnass +Felix Kling +Fernando Correia +Frankie Bagnardi +François-Xavier Bois +Fred Zhao +Freddy Rangel +Fyodor Ivanishchev +G Scott Olson +G. Kay Lee +Gabe Levi +Gajus Kuizinas +Gareth Nicholson +Garren Smith +Gavin McQuistin +Geert Pasteels +Geert-Jan Brits +George A Sisco III +Georgii Dolzhykov +Gilbert +Glen Mailer +Grant Timmerman +Greg Hurrell +Greg Perkins +Greg Roodt +Gregory +Guangqiang Dong +Guido Bouman +Harry Hull +Harry Marr +Harry Moreno +Harshad Sabne +Hekar Khani +Hendrik Swanepoel +Henrik Nyh +Henry Wong +Henry Zhu +Hideo Matsumoto +Hou Chia +Huang-Wei Chang +Hugo Agbonon +Hugo Jobling +Hyeock Kwon +Héliton Nordt +Ian Obermiller +Ignacio Carbajo +Igor Scekic +Ilia Pavlenkov +Ilya Shuklin +Ilyá Belsky +Ingvar Stepanyan +Irae Carvalho +Isaac Salier-Hellendag +Iurii Kucherov +Ivan Kozik +Ivan Krechetov +Ivan Vergiliev +J. Andrew Brassington +J. Renée Beach +JD Isaacks +JJ Weber +JW +Jack Zhang +Jackie Wung +Jacob Gable +Jacob Greenleaf +Jae Hun Ro +Jaeho Lee +Jaime Mingo +Jake Worth +Jakub Malinowski +James +James Brantly +James Burnett +James Friend +James Ide +James Long +James Pearce +James Seppi +James South +James Wen +Jamie Wong +Jamis Charles +Jamison Dance +Jan Hancic +Jan Kassens +Jan Raasch +Jared Forsyth +Jason +Jason Bonta +Jason Ly +Jason Miller +Jason Quense +Jason Trill +Jason Webster +Jay Jaeho Lee +Jean Lauliac +Jed Watson +Jeff Barczewski +Jeff Carpenter +Jeff Chan +Jeff Hicken +Jeff Kolesky +Jeff Morrison +Jeff Welch +Jeffrey Lin +Jeremy Fairbank +Jesse Skinner +Jignesh Kakadiya +Jim OBrien +Jim Sproch +Jimmy Jea +Jing Chen +Jinwoo Oh +Jinxiu Lee +Jiyeon Seo +Jody McIntyre +Joe Critchley +Joe Stein +Joel Auterson +Johannes Baiter +Johannes Emerich +Johannes Lumpe +John Heroy +John Ryan +John Watson +John-David Dalton +Jon Beebe +Jon Chester +Jon Hester +Jon Madison +Jon Scott Clark +Jon Tewksbury +Jonas Enlund +Jonas Gebhardt +Jonathan Hsu +Jonathan Persson +Jordan Harband +Jordan Walke +Jorrit Schippers +Joseph Nudell +Joseph Savona +Josh Bassett +Josh Duck +Josh Perez +Josh Yudaken +Joshua Evans +Joshua Go +Joshua Goldberg +Joshua Ma +João Valente +Juan Serrano +Julen Ruiz Aizpuru +Julian Viereck +Julien Bordellier +Julio Lopez +Jun Wu +Juraj Dudak +Justas Brazauskas +Justin Jaffray +Justin Robison +Justin Woo +Kale +Kamron Batman +Karl Mikkelsen +Karpich Dmitry +Keito Uchiyama +Ken Powers +Kent C. Dodds +Kevin Cheng <09chengk@gmail.com> +Kevin Coughlin +Kevin Huang +Kevin Lau +Kevin Old +Kevin Robinson +Kewei Jiang +Kier Borromeo +KimCoding +Kirk Steven Hansen +Kit Randel +Kohei TAKATA +Koo Youngmin +Krystian Karczewski +Kunal Mehta +Kurt Ruppel +Kyle Kelley +Kyle Mathews +Laurence Rowe +Laurent Etiemble +Lee Byron +Lee Jaeyoung +Lei +Leland Richardson +Leon Fedotov +Leon Yip +Leonardo YongUk Kim +Levi Buzolic +Levi McCallum +Lily +Logan Allen +Lovisa Svallingson +Ludovico Fischer +Luigy Leon +Luke Horvat +MIKAMI Yoshiyuki +Maher Beg +Manas +Marcin K. +Marcin Kwiatkowski +Marcin Szczepanski +Mariano Desanze +Marjan +Mark Anderson +Mark Funk +Mark Hintz +Mark IJbema +Mark Murphy +Mark Richardson +Mark Rushakoff +Mark Sun +Marlon Landaverde +Marshall Roch +Martin Andert +Martin Hujer +Martin Jul +Martin Konicek +Martin Mihaylov +Masaki KOBAYASHI +Mathieu M-Gosselin +Mathieu Savy +Matias Singers +Matsunoki +Matt Brookes +Matt Dunn-Rankin +Matt Harrison +Matt Huggins +Matt Stow +Matt Zabriskie +Matthew Dapena-Tretter +Matthew Herbst +Matthew Hodgson +Matthew Johnston +Matthew King +Matthew Looi +Matthew Miner +Matthias Le Brun +Matti Nelimarkka +Mattijs Kneppers +Max F. Albrecht <1@178.is> +Max Heiber +Max Stoiber +Maxi Ferreira +Maxim Abramchuk +Merrick Christensen +Mert Kahyaoğlu +Michael Chan +Michael McDermott +Michael Randers-Pehrson +Michael Ridgway +Michael Warner +Michael Wiencek +Michael Ziwisky +Michal Srb +Michelle Todd +Mihai Parparita +Mike D Pilsbury +Mike Groseclose +Mike Nordick +Mikolaj Dadela +Miles Johnson +Minwe LUO +Miorel Palii +Morhaus +Moshe Kolodny +Mouad Debbar +Murad +Murray M. Moss +Nadeesha Cabral +Naman Goel +Nate Hunzaker +Nate Lee +Nathan Smith +Nathan White +Nee <944316342@qq.com> +Neri Marschik +Nguyen Truong Duy +Nicholas Bergson-Shilcock +Nicholas Clawson +Nick Balestra +Nick Fitzgerald +Nick Gavalas +Nick Merwin +Nick Presta +Nick Raienko +Nick Thompson +Nick Williams +Niklas Boström +Ning Xia +Niole Nelson +Oiva Eskola +Oleg +Oleksii Markhovskyi +Oliver Zeigermann +Olivier Tassinari +Owen Coutts +Pablo Lacerda de Miranda +Paolo Moretti +Pascal Hartig +Patrick +Patrick Laughlin +Patrick Stapleton +Paul Benigeri +Paul Harper +Paul O’Shannessy +Paul Seiffert +Paul Shen +Pedro Nauck +Pete Hunt +Peter Blazejewicz +Peter Cottle +Peter Jaros +Peter Newnham +Petri Lehtinen +Petri Lievonen +Pieter Vanderwerff +Pouja Nikray +Prathamesh Sonpatki +Prayag Verma +Preston Parry +Rafael +Rafal Dittwald +Rainer Oviir +Rajat Sehgal +Rajiv Tirumalareddy +Ram Kaniyur +Randall Randall +Ray +Raymond Ha +Reed Loden +Remko Tronçon +Richard D. Worth +Richard Feldman +Richard Kho +Richard Littauer +Richard Livesey +Richard Wood +Rick Beerendonk +Rick Ford +Riley Tomasek +Rob Arnold +Robert Binna +Robert Knight +Robert Sedovsek +Robin Berjon +Robin Frischmann +Roman Pominov +Roman Vanesyan +Russ +Ryan Seddon +Sahat Yalkabov +Saif Hakim +Saiichi Hashimoto +Sam Beveridge +Sam Saccone +Sam Selikoff +Samy Al Zahrani +Sander Spies +Scott Burch +Scott Feeney +Sean Kinsey +Sebastian Markbåge +Sebastian McKenzie +Seoh Char +Sercan Eraslan +Serg +Sergey Generalov +Sergey Rubanov +Seyi Adebajo +Shane O'Sullivan +Shaun Trennery +ShihChi Huang +Shim Won +Shinnosuke Watanabe +Shogun Sea +Shota Kubota +Shripad K +Sibi +Simen Bekkhus +Simon Højberg +Simon Welsh +Simone Vittori +Soichiro Kawamura +Sophia Westwood +Sota Ohara +Spencer Handley +Stefan Dombrowski +Stephen Murphy +Sterling Cobb +Steve Baker <_steve_@outlook.com> +Steven Luscher +Steven Vachon +Stoyan Stefanov +Sundeep Malladi +Sunny Juneja +Sven Helmberger +Sverre Johansen +Sébastien Lorber +Sławomir Laskowski +Taeho Kim +Tay Yang Shun +Ted Kim +Tengfei Guo +Teodor Szente +Thomas Aylott +Thomas Boyt +Thomas Broadley +Thomas Reggi +Thomas Röggla +Thomas Shaddox +Thomas Shafer +ThomasCrvsr +Tienchai Wirojsaksaree +Tim Routowicz +Tim Schaub +Timothy Yung +Timur Carpeev +Tobias Reiss +Tom Duncalf +Tom Haggie +Tom Hauburger +Tom MacWright +Tom Occhino +Tomasz Kołodziejski +Tomoya Suzuki +Tony Spiro +Toru Kobayashi +Trinh Hoang Nhu +Tsung Hung +Tyler Brock +Ustin Zarubin +Vadim Chernysh +Varun Rau +Vasiliy Loginevskiy +Victor Alvarez +Victor Homyakov +Victor Koenders +Ville Immonen +Vincent Riemer +Vincent Siao +Vipul A M +Vitaly Kramskikh +Vitor Balocco +Vjeux +Volkan Unsal +Wander Wang +Wayne Larsen +WickyNilliams +Wincent Colaiuta +Wout Mertens +Xavier Morel +XuefengWu +Yakov Dalinchuk +Yasar icli +YouBao Nong +Yuichi Hagio +Yuriy Dybskiy +Yutaka Nakajima +Yuval Dekel +Zach Bruggeman +Zach Ramaekers +Zacharias +Zeke Sikelianos +Zhangjd +adraeth +arush +brafdlog +chen +clariroid +claudiopro +cutbko +davidxi +dongmeng.ldm +iamchenxin +iamdoron +iawia002 +imagentleman +koh-taka +kohashi85 +laiso +leeyoungalias +li.li +maxprafferty +rgarifullin +songawee +sugarshin +wali-s +yiminghe +youmoo +zhangjg +zwhitchcox +Árni Hermann Reynisson +元彦 +凌恒 +张敏 diff --git a/site_libs/react-18.2.0/LICENSE.txt b/site_libs/react-18.2.0/LICENSE.txt new file mode 100644 index 00000000..188fb2b0 --- /dev/null +++ b/site_libs/react-18.2.0/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2013-present, Facebook, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/site_libs/react-18.2.0/react-dom.min.js b/site_libs/react-18.2.0/react-dom.min.js new file mode 100644 index 00000000..4578fc9b --- /dev/null +++ b/site_libs/react-18.2.0/react-dom.min.js @@ -0,0 +1,267 @@ +/** + * @license React + * react-dom.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +(function(){/* + Modernizr 3.0.0pre (Custom Build) | MIT +*/ +'use strict';(function(Q,mb){"object"===typeof exports&&"undefined"!==typeof module?mb(exports,require("react")):"function"===typeof define&&define.amd?define(["exports","react"],mb):(Q=Q||self,mb(Q.ReactDOM={},Q.React))})(this,function(Q,mb){function n(a){for(var b="https://reactjs.org/docs/error-decoder.html?invariant="+a,c=1;cb}return!1}function Y(a,b,c,d,e,f,g){this.acceptsBooleans=2===b||3===b||4===b;this.attributeName=d;this.attributeNamespace=e;this.mustUseProperty=c;this.propertyName=a;this.type=b;this.sanitizeURL=f;this.removeEmptyString=g}function $d(a,b,c,d){var e=R.hasOwnProperty(b)?R[b]:null;if(null!==e?0!==e.type:d||!(2h||e[g]!==f[h]){var k="\n"+e[g].replace(" at new "," at ");a.displayName&&k.includes("")&&(k=k.replace("",a.displayName));return k}while(1<=g&&0<=h)}break}}}finally{ce=!1,Error.prepareStackTrace=c}return(a=a?a.displayName||a.name:"")?bc(a): +""}function gj(a){switch(a.tag){case 5:return bc(a.type);case 16:return bc("Lazy");case 13:return bc("Suspense");case 19:return bc("SuspenseList");case 0:case 2:case 15:return a=be(a.type,!1),a;case 11:return a=be(a.type.render,!1),a;case 1:return a=be(a.type,!0),a;default:return""}}function de(a){if(null==a)return null;if("function"===typeof a)return a.displayName||a.name||null;if("string"===typeof a)return a;switch(a){case Bb:return"Fragment";case Cb:return"Portal";case ee:return"Profiler";case fe:return"StrictMode"; +case ge:return"Suspense";case he:return"SuspenseList"}if("object"===typeof a)switch(a.$$typeof){case gg:return(a.displayName||"Context")+".Consumer";case hg:return(a._context.displayName||"Context")+".Provider";case ie:var b=a.render;a=a.displayName;a||(a=b.displayName||b.name||"",a=""!==a?"ForwardRef("+a+")":"ForwardRef");return a;case je:return b=a.displayName||null,null!==b?b:de(a.type)||"Memo";case Ta:b=a._payload;a=a._init;try{return de(a(b))}catch(c){}}return null}function hj(a){var b=a.type; +switch(a.tag){case 24:return"Cache";case 9:return(b.displayName||"Context")+".Consumer";case 10:return(b._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return a=b.render,a=a.displayName||a.name||"",b.displayName||(""!==a?"ForwardRef("+a+")":"ForwardRef");case 7:return"Fragment";case 5:return b;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return de(b);case 8:return b===fe?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler"; +case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if("function"===typeof b)return b.displayName||b.name||null;if("string"===typeof b)return b}return null}function Ua(a){switch(typeof a){case "boolean":case "number":case "string":case "undefined":return a;case "object":return a;default:return""}}function ig(a){var b=a.type;return(a=a.nodeName)&&"input"===a.toLowerCase()&&("checkbox"===b||"radio"=== +b)}function ij(a){var b=ig(a)?"checked":"value",c=Object.getOwnPropertyDescriptor(a.constructor.prototype,b),d=""+a[b];if(!a.hasOwnProperty(b)&&"undefined"!==typeof c&&"function"===typeof c.get&&"function"===typeof c.set){var e=c.get,f=c.set;Object.defineProperty(a,b,{configurable:!0,get:function(){return e.call(this)},set:function(a){d=""+a;f.call(this,a)}});Object.defineProperty(a,b,{enumerable:c.enumerable});return{getValue:function(){return d},setValue:function(a){d=""+a},stopTracking:function(){a._valueTracker= +null;delete a[b]}}}}function Pc(a){a._valueTracker||(a._valueTracker=ij(a))}function jg(a){if(!a)return!1;var b=a._valueTracker;if(!b)return!0;var c=b.getValue();var d="";a&&(d=ig(a)?a.checked?"true":"false":a.value);a=d;return a!==c?(b.setValue(a),!0):!1}function Qc(a){a=a||("undefined"!==typeof document?document:void 0);if("undefined"===typeof a)return null;try{return a.activeElement||a.body}catch(b){return a.body}}function ke(a,b){var c=b.checked;return E({},b,{defaultChecked:void 0,defaultValue:void 0, +value:void 0,checked:null!=c?c:a._wrapperState.initialChecked})}function kg(a,b){var c=null==b.defaultValue?"":b.defaultValue,d=null!=b.checked?b.checked:b.defaultChecked;c=Ua(null!=b.value?b.value:c);a._wrapperState={initialChecked:d,initialValue:c,controlled:"checkbox"===b.type||"radio"===b.type?null!=b.checked:null!=b.value}}function lg(a,b){b=b.checked;null!=b&&$d(a,"checked",b,!1)}function le(a,b){lg(a,b);var c=Ua(b.value),d=b.type;if(null!=c)if("number"===d){if(0===c&&""===a.value||a.value!= +c)a.value=""+c}else a.value!==""+c&&(a.value=""+c);else if("submit"===d||"reset"===d){a.removeAttribute("value");return}b.hasOwnProperty("value")?me(a,b.type,c):b.hasOwnProperty("defaultValue")&&me(a,b.type,Ua(b.defaultValue));null==b.checked&&null!=b.defaultChecked&&(a.defaultChecked=!!b.defaultChecked)}function mg(a,b,c){if(b.hasOwnProperty("value")||b.hasOwnProperty("defaultValue")){var d=b.type;if(!("submit"!==d&&"reset"!==d||void 0!==b.value&&null!==b.value))return;b=""+a._wrapperState.initialValue; +c||b===a.value||(a.value=b);a.defaultValue=b}c=a.name;""!==c&&(a.name="");a.defaultChecked=!!a._wrapperState.initialChecked;""!==c&&(a.name=c)}function me(a,b,c){if("number"!==b||Qc(a.ownerDocument)!==a)null==c?a.defaultValue=""+a._wrapperState.initialValue:a.defaultValue!==""+c&&(a.defaultValue=""+c)}function Db(a,b,c,d){a=a.options;if(b){b={};for(var e=0;e>>=0;return 0===a?32:31-(rj(a)/sj|0)|0}function hc(a){switch(a&-a){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return a& +4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return a&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return a}}function Vc(a,b){var c=a.pendingLanes;if(0===c)return 0;var d=0,e=a.suspendedLanes,f=a.pingedLanes,g=c&268435455;if(0!==g){var h=g&~e;0!==h?d=hc(h):(f&=g,0!==f&&(d=hc(f)))}else g=c&~e,0!==g?d=hc(g):0!==f&&(d=hc(f));if(0===d)return 0;if(0!==b&&b!==d&&0===(b&e)&& +(e=d&-d,f=b&-b,e>=f||16===e&&0!==(f&4194240)))return b;0!==(d&4)&&(d|=c&16);b=a.entangledLanes;if(0!==b)for(a=a.entanglements,b&=d;0c;c++)b.push(a); +return b}function ic(a,b,c){a.pendingLanes|=b;536870912!==b&&(a.suspendedLanes=0,a.pingedLanes=0);a=a.eventTimes;b=31-ta(b);a[b]=c}function vj(a,b){var c=a.pendingLanes&~b;a.pendingLanes=b;a.suspendedLanes=0;a.pingedLanes=0;a.expiredLanes&=b;a.mutableReadLanes&=b;a.entangledLanes&=b;b=a.entanglements;var d=a.eventTimes;for(a=a.expirationTimes;0=b)return{node:c,offset:b-a};a=d}a:{for(;c;){if(c.nextSibling){c=c.nextSibling;break a}c=c.parentNode}c=void 0}c=$g(c)}}function bh(a,b){return a&&b?a===b?!0:a&&3===a.nodeType?!1:b&&3===b.nodeType?bh(a,b.parentNode):"contains"in a?a.contains(b):a.compareDocumentPosition?!!(a.compareDocumentPosition(b)&16):!1:!1}function ch(){for(var a=window,b=Qc();b instanceof a.HTMLIFrameElement;){try{var c="string"===typeof b.contentWindow.location.href}catch(d){c=!1}if(c)a=b.contentWindow;else break; +b=Qc(a.document)}return b}function Ie(a){var b=a&&a.nodeName&&a.nodeName.toLowerCase();return b&&("input"===b&&("text"===a.type||"search"===a.type||"tel"===a.type||"url"===a.type||"password"===a.type)||"textarea"===b||"true"===a.contentEditable)}function Uj(a){var b=ch(),c=a.focusedElem,d=a.selectionRange;if(b!==c&&c&&c.ownerDocument&&bh(c.ownerDocument.documentElement,c)){if(null!==d&&Ie(c))if(b=d.start,a=d.end,void 0===a&&(a=b),"selectionStart"in c)c.selectionStart=b,c.selectionEnd=Math.min(a,c.value.length); +else if(a=(b=c.ownerDocument||document)&&b.defaultView||window,a.getSelection){a=a.getSelection();var e=c.textContent.length,f=Math.min(d.start,e);d=void 0===d.end?f:Math.min(d.end,e);!a.extend&&f>d&&(e=d,d=f,f=e);e=ah(c,f);var g=ah(c,d);e&&g&&(1!==a.rangeCount||a.anchorNode!==e.node||a.anchorOffset!==e.offset||a.focusNode!==g.node||a.focusOffset!==g.offset)&&(b=b.createRange(),b.setStart(e.node,e.offset),a.removeAllRanges(),f>d?(a.addRange(b),a.extend(g.node,g.offset)):(b.setEnd(g.node,g.offset), +a.addRange(b)))}b=[];for(a=c;a=a.parentNode;)1===a.nodeType&&b.push({element:a,left:a.scrollLeft,top:a.scrollTop});"function"===typeof c.focus&&c.focus();for(c=0;cMb||(a.current=Se[Mb],Se[Mb]=null,Mb--)} +function y(a,b,c){Mb++;Se[Mb]=a.current;a.current=b}function Nb(a,b){var c=a.type.contextTypes;if(!c)return cb;var d=a.stateNode;if(d&&d.__reactInternalMemoizedUnmaskedChildContext===b)return d.__reactInternalMemoizedMaskedChildContext;var e={},f;for(f in c)e[f]=b[f];d&&(a=a.stateNode,a.__reactInternalMemoizedUnmaskedChildContext=b,a.__reactInternalMemoizedMaskedChildContext=e);return e}function ea(a){a=a.childContextTypes;return null!==a&&void 0!==a}function th(a,b,c){if(J.current!==cb)throw Error(n(168)); +y(J,b);y(S,c)}function uh(a,b,c){var d=a.stateNode;b=b.childContextTypes;if("function"!==typeof d.getChildContext)return c;d=d.getChildContext();for(var e in d)if(!(e in b))throw Error(n(108,hj(a)||"Unknown",e));return E({},c,d)}function ld(a){a=(a=a.stateNode)&&a.__reactInternalMemoizedMergedChildContext||cb;qb=J.current;y(J,a);y(S,S.current);return!0}function vh(a,b,c){var d=a.stateNode;if(!d)throw Error(n(169));c?(a=uh(a,b,qb),d.__reactInternalMemoizedMergedChildContext=a,w(S),w(J),y(J,a)):w(S); +y(S,c)}function wh(a){null===La?La=[a]:La.push(a)}function kk(a){md=!0;wh(a)}function db(){if(!Te&&null!==La){Te=!0;var a=0,b=z;try{var c=La;for(z=1;a>=g;e-=g;Ma=1<<32-ta(b)+e|c<q?(v=l,l=null):v=l.sibling;var A=r(e,l,h[q],k);if(null===A){null===l&&(l=v);break}a&&l&&null===A.alternate&&b(e,l);g=f(A,g,q);null===m?n=A:m.sibling=A;m=A;l=v}if(q===h.length)return c(e,l),D&&rb(e,q),n;if(null===l){for(;qv?(A=q,q=null):A=q.sibling;var x=r(e,q,t.value,k);if(null===x){null===q&&(q=A);break}a&&q&&null===x.alternate&&b(e,q);g=f(x,g,v);null===l?m=x:l.sibling=x;l=x;q=A}if(t.done)return c(e,q),D&&rb(e,v),m; +if(null===q){for(;!t.done;v++,t=h.next())t=u(e,t.value,k),null!==t&&(g=f(t,g,v),null===l?m=t:l.sibling=t,l=t);D&&rb(e,v);return m}for(q=d(e,q);!t.done;v++,t=h.next())t=p(q,e,v,t.value,k),null!==t&&(a&&null!==t.alternate&&q.delete(null===t.key?v:t.key),g=f(t,g,v),null===l?m=t:l.sibling=t,l=t);a&&q.forEach(function(a){return b(e,a)});D&&rb(e,v);return m}function w(a,d,f,h){"object"===typeof f&&null!==f&&f.type===Bb&&null===f.key&&(f=f.props.children);if("object"===typeof f&&null!==f){switch(f.$$typeof){case xd:a:{for(var k= +f.key,m=d;null!==m;){if(m.key===k){k=f.type;if(k===Bb){if(7===m.tag){c(a,m.sibling);d=e(m,f.props.children);d.return=a;a=d;break a}}else if(m.elementType===k||"object"===typeof k&&null!==k&&k.$$typeof===Ta&&Kh(k)===m.type){c(a,m.sibling);d=e(m,f.props);d.ref=vc(a,m,f);d.return=a;a=d;break a}c(a,m);break}else b(a,m);m=m.sibling}f.type===Bb?(d=ub(f.props.children,a.mode,h,f.key),d.return=a,a=d):(h=wd(f.type,f.key,f.props,null,a.mode,h),h.ref=vc(a,d,f),h.return=a,a=h)}return g(a);case Cb:a:{for(m=f.key;null!== +d;){if(d.key===m)if(4===d.tag&&d.stateNode.containerInfo===f.containerInfo&&d.stateNode.implementation===f.implementation){c(a,d.sibling);d=e(d,f.children||[]);d.return=a;a=d;break a}else{c(a,d);break}else b(a,d);d=d.sibling}d=hf(f,a.mode,h);d.return=a;a=d}return g(a);case Ta:return m=f._init,w(a,d,m(f._payload),h)}if(cc(f))return x(a,d,f,h);if(ac(f))return F(a,d,f,h);vd(a,f)}return"string"===typeof f&&""!==f||"number"===typeof f?(f=""+f,null!==d&&6===d.tag?(c(a,d.sibling),d=e(d,f),d.return=a,a=d): +(c(a,d),d=gf(f,a.mode,h),d.return=a,a=d),g(a)):c(a,d)}return w}function vb(a){if(a===wc)throw Error(n(174));return a}function jf(a,b){y(xc,b);y(yc,a);y(Ea,wc);a=b.nodeType;switch(a){case 9:case 11:b=(b=b.documentElement)?b.namespaceURI:oe(null,"");break;default:a=8===a?b.parentNode:b,b=a.namespaceURI||null,a=a.tagName,b=oe(b,a)}w(Ea);y(Ea,b)}function Tb(a){w(Ea);w(yc);w(xc)}function Mh(a){vb(xc.current);var b=vb(Ea.current);var c=oe(b,a.type);b!==c&&(y(yc,a),y(Ea,c))}function kf(a){yc.current===a&& +(w(Ea),w(yc))}function yd(a){for(var b=a;null!==b;){if(13===b.tag){var c=b.memoizedState;if(null!==c&&(c=c.dehydrated,null===c||"$?"===c.data||"$!"===c.data))return b}else if(19===b.tag&&void 0!==b.memoizedProps.revealOrder){if(0!==(b.flags&128))return b}else if(null!==b.child){b.child.return=b;b=b.child;continue}if(b===a)break;for(;null===b.sibling;){if(null===b.return||b.return===a)return null;b=b.return}b.sibling.return=b.return;b=b.sibling}return null}function lf(){for(var a=0;ac?c:4;a(!0);var d=uf.transition;uf.transition={};try{a(!1),b()}finally{z=c,uf.transition=d}}function di(){return sa().memoizedState}function rk(a,b, +c){var d=hb(a);c={lane:d,action:c,hasEagerState:!1,eagerState:null,next:null};if(ei(a))fi(b,c);else if(c=Ch(a,b,c,d),null!==c){var e=Z();ya(c,a,d,e);gi(c,b,d)}}function pk(a,b,c){var d=hb(a),e={lane:d,action:c,hasEagerState:!1,eagerState:null,next:null};if(ei(a))fi(b,e);else{var f=a.alternate;if(0===a.lanes&&(null===f||0===f.lanes)&&(f=b.lastRenderedReducer,null!==f))try{var g=b.lastRenderedState,h=f(g,c);e.hasEagerState=!0;e.eagerState=h;if(ua(h,g)){var k=b.interleaved;null===k?(e.next=e,cf(b)): +(e.next=k.next,k.next=e);b.interleaved=e;return}}catch(m){}finally{}c=Ch(a,b,e,d);null!==c&&(e=Z(),ya(c,a,d,e),gi(c,b,d))}}function ei(a){var b=a.alternate;return a===C||null!==b&&b===C}function fi(a,b){zc=Bd=!0;var c=a.pending;null===c?b.next=b:(b.next=c.next,c.next=b);a.pending=b}function gi(a,b,c){if(0!==(c&4194240)){var d=b.lanes;d&=a.pendingLanes;c|=d;b.lanes=c;xe(a,c)}}function Ub(a,b){try{var c="",d=b;do c+=gj(d),d=d.return;while(d);var e=c}catch(f){e="\nError generating stack: "+f.message+ +"\n"+f.stack}return{value:a,source:b,stack:e,digest:null}}function vf(a,b,c){return{value:a,source:null,stack:null!=c?c:null,digest:null!=b?b:null}}function wf(a,b){try{console.error(b.value)}catch(c){setTimeout(function(){throw c;})}}function hi(a,b,c){c=Pa(-1,c);c.tag=3;c.payload={element:null};var d=b.value;c.callback=function(){Ed||(Ed=!0,xf=d);wf(a,b)};return c}function ii(a,b,c){c=Pa(-1,c);c.tag=3;var d=a.type.getDerivedStateFromError;if("function"===typeof d){var e=b.value;c.payload=function(){return d(e)}; +c.callback=function(){wf(a,b)}}var f=a.stateNode;null!==f&&"function"===typeof f.componentDidCatch&&(c.callback=function(){wf(a,b);"function"!==typeof d&&(null===ib?ib=new Set([this]):ib.add(this));var c=b.stack;this.componentDidCatch(b.value,{componentStack:null!==c?c:""})});return c}function ji(a,b,c){var d=a.pingCache;if(null===d){d=a.pingCache=new sk;var e=new Set;d.set(b,e)}else e=d.get(b),void 0===e&&(e=new Set,d.set(b,e));e.has(c)||(e.add(c),a=tk.bind(null,a,b,c),b.then(a,a))}function ki(a){do{var b; +if(b=13===a.tag)b=a.memoizedState,b=null!==b?null!==b.dehydrated?!0:!1:!0;if(b)return a;a=a.return}while(null!==a);return null}function li(a,b,c,d,e){if(0===(a.mode&1))return a===b?a.flags|=65536:(a.flags|=128,c.flags|=131072,c.flags&=-52805,1===c.tag&&(null===c.alternate?c.tag=17:(b=Pa(-1,1),b.tag=2,eb(c,b,1))),c.lanes|=1),a;a.flags|=65536;a.lanes=e;return a}function aa(a,b,c,d){b.child=null===a?mi(b,null,c,d):Vb(b,a.child,c,d)}function ni(a,b,c,d,e){c=c.render;var f=b.ref;Sb(b,e);d=of(a,b,c,d,f, +e);c=pf();if(null!==a&&!ha)return b.updateQueue=a.updateQueue,b.flags&=-2053,a.lanes&=~e,Qa(a,b,e);D&&c&&Ue(b);b.flags|=1;aa(a,b,d,e);return b.child}function oi(a,b,c,d,e){if(null===a){var f=c.type;if("function"===typeof f&&!yf(f)&&void 0===f.defaultProps&&null===c.compare&&void 0===c.defaultProps)return b.tag=15,b.type=f,pi(a,b,f,d,e);a=wd(c.type,null,d,b,b.mode,e);a.ref=b.ref;a.return=b;return b.child=a}f=a.child;if(0===(a.lanes&e)){var g=f.memoizedProps;c=c.compare;c=null!==c?c:qc;if(c(g,d)&&a.ref=== +b.ref)return Qa(a,b,e)}b.flags|=1;a=gb(f,d);a.ref=b.ref;a.return=b;return b.child=a}function pi(a,b,c,d,e){if(null!==a){var f=a.memoizedProps;if(qc(f,d)&&a.ref===b.ref)if(ha=!1,b.pendingProps=d=f,0!==(a.lanes&e))0!==(a.flags&131072)&&(ha=!0);else return b.lanes=a.lanes,Qa(a,b,e)}return zf(a,b,c,d,e)}function qi(a,b,c){var d=b.pendingProps,e=d.children,f=null!==a?a.memoizedState:null;if("hidden"===d.mode)if(0===(b.mode&1))b.memoizedState={baseLanes:0,cachePool:null,transitions:null},y(Ga,ba),ba|=c; +else{if(0===(c&1073741824))return a=null!==f?f.baseLanes|c:c,b.lanes=b.childLanes=1073741824,b.memoizedState={baseLanes:a,cachePool:null,transitions:null},b.updateQueue=null,y(Ga,ba),ba|=a,null;b.memoizedState={baseLanes:0,cachePool:null,transitions:null};d=null!==f?f.baseLanes:c;y(Ga,ba);ba|=d}else null!==f?(d=f.baseLanes|c,b.memoizedState=null):d=c,y(Ga,ba),ba|=d;aa(a,b,e,c);return b.child}function ri(a,b){var c=b.ref;if(null===a&&null!==c||null!==a&&a.ref!==c)b.flags|=512,b.flags|=2097152}function zf(a, +b,c,d,e){var f=ea(c)?qb:J.current;f=Nb(b,f);Sb(b,e);c=of(a,b,c,d,f,e);d=pf();if(null!==a&&!ha)return b.updateQueue=a.updateQueue,b.flags&=-2053,a.lanes&=~e,Qa(a,b,e);D&&d&&Ue(b);b.flags|=1;aa(a,b,c,e);return b.child}function si(a,b,c,d,e){if(ea(c)){var f=!0;ld(b)}else f=!1;Sb(b,e);if(null===b.stateNode)Fd(a,b),Hh(b,c,d),ff(b,c,d,e),d=!0;else if(null===a){var g=b.stateNode,h=b.memoizedProps;g.props=h;var k=g.context,m=c.contextType;"object"===typeof m&&null!==m?m=qa(m):(m=ea(c)?qb:J.current,m=Nb(b, +m));var l=c.getDerivedStateFromProps,n="function"===typeof l||"function"===typeof g.getSnapshotBeforeUpdate;n||"function"!==typeof g.UNSAFE_componentWillReceiveProps&&"function"!==typeof g.componentWillReceiveProps||(h!==d||k!==m)&&Ih(b,g,d,m);fb=!1;var r=b.memoizedState;g.state=r;td(b,d,g,e);k=b.memoizedState;h!==d||r!==k||S.current||fb?("function"===typeof l&&(ef(b,c,l,d),k=b.memoizedState),(h=fb||Gh(b,c,h,d,r,k,m))?(n||"function"!==typeof g.UNSAFE_componentWillMount&&"function"!==typeof g.componentWillMount|| +("function"===typeof g.componentWillMount&&g.componentWillMount(),"function"===typeof g.UNSAFE_componentWillMount&&g.UNSAFE_componentWillMount()),"function"===typeof g.componentDidMount&&(b.flags|=4194308)):("function"===typeof g.componentDidMount&&(b.flags|=4194308),b.memoizedProps=d,b.memoizedState=k),g.props=d,g.state=k,g.context=m,d=h):("function"===typeof g.componentDidMount&&(b.flags|=4194308),d=!1)}else{g=b.stateNode;Dh(a,b);h=b.memoizedProps;m=b.type===b.elementType?h:xa(b.type,h);g.props= +m;n=b.pendingProps;r=g.context;k=c.contextType;"object"===typeof k&&null!==k?k=qa(k):(k=ea(c)?qb:J.current,k=Nb(b,k));var p=c.getDerivedStateFromProps;(l="function"===typeof p||"function"===typeof g.getSnapshotBeforeUpdate)||"function"!==typeof g.UNSAFE_componentWillReceiveProps&&"function"!==typeof g.componentWillReceiveProps||(h!==n||r!==k)&&Ih(b,g,d,k);fb=!1;r=b.memoizedState;g.state=r;td(b,d,g,e);var x=b.memoizedState;h!==n||r!==x||S.current||fb?("function"===typeof p&&(ef(b,c,p,d),x=b.memoizedState), +(m=fb||Gh(b,c,m,d,r,x,k)||!1)?(l||"function"!==typeof g.UNSAFE_componentWillUpdate&&"function"!==typeof g.componentWillUpdate||("function"===typeof g.componentWillUpdate&&g.componentWillUpdate(d,x,k),"function"===typeof g.UNSAFE_componentWillUpdate&&g.UNSAFE_componentWillUpdate(d,x,k)),"function"===typeof g.componentDidUpdate&&(b.flags|=4),"function"===typeof g.getSnapshotBeforeUpdate&&(b.flags|=1024)):("function"!==typeof g.componentDidUpdate||h===a.memoizedProps&&r===a.memoizedState||(b.flags|= +4),"function"!==typeof g.getSnapshotBeforeUpdate||h===a.memoizedProps&&r===a.memoizedState||(b.flags|=1024),b.memoizedProps=d,b.memoizedState=x),g.props=d,g.state=x,g.context=k,d=m):("function"!==typeof g.componentDidUpdate||h===a.memoizedProps&&r===a.memoizedState||(b.flags|=4),"function"!==typeof g.getSnapshotBeforeUpdate||h===a.memoizedProps&&r===a.memoizedState||(b.flags|=1024),d=!1)}return Af(a,b,c,d,f,e)}function Af(a,b,c,d,e,f){ri(a,b);var g=0!==(b.flags&128);if(!d&&!g)return e&&vh(b,c,!1), +Qa(a,b,f);d=b.stateNode;uk.current=b;var h=g&&"function"!==typeof c.getDerivedStateFromError?null:d.render();b.flags|=1;null!==a&&g?(b.child=Vb(b,a.child,null,f),b.child=Vb(b,null,h,f)):aa(a,b,h,f);b.memoizedState=d.state;e&&vh(b,c,!0);return b.child}function ti(a){var b=a.stateNode;b.pendingContext?th(a,b.pendingContext,b.pendingContext!==b.context):b.context&&th(a,b.context,!1);jf(a,b.containerInfo)}function ui(a,b,c,d,e){Qb();Ye(e);b.flags|=256;aa(a,b,c,d);return b.child}function Bf(a){return{baseLanes:a, +cachePool:null,transitions:null}}function vi(a,b,c){var d=b.pendingProps,e=G.current,f=!1,g=0!==(b.flags&128),h;(h=g)||(h=null!==a&&null===a.memoizedState?!1:0!==(e&2));if(h)f=!0,b.flags&=-129;else if(null===a||null!==a.memoizedState)e|=1;y(G,e&1);if(null===a){Xe(b);a=b.memoizedState;if(null!==a&&(a=a.dehydrated,null!==a))return 0===(b.mode&1)?b.lanes=1:"$!"===a.data?b.lanes=8:b.lanes=1073741824,null;g=d.children;a=d.fallback;return f?(d=b.mode,f=b.child,g={mode:"hidden",children:g},0===(d&1)&&null!== +f?(f.childLanes=0,f.pendingProps=g):f=Gd(g,d,0,null),a=ub(a,d,c,null),f.return=b,a.return=b,f.sibling=a,b.child=f,b.child.memoizedState=Bf(c),b.memoizedState=Cf,a):Df(b,g)}e=a.memoizedState;if(null!==e&&(h=e.dehydrated,null!==h))return vk(a,b,g,d,h,e,c);if(f){f=d.fallback;g=b.mode;e=a.child;h=e.sibling;var k={mode:"hidden",children:d.children};0===(g&1)&&b.child!==e?(d=b.child,d.childLanes=0,d.pendingProps=k,b.deletions=null):(d=gb(e,k),d.subtreeFlags=e.subtreeFlags&14680064);null!==h?f=gb(h,f):(f= +ub(f,g,c,null),f.flags|=2);f.return=b;d.return=b;d.sibling=f;b.child=d;d=f;f=b.child;g=a.child.memoizedState;g=null===g?Bf(c):{baseLanes:g.baseLanes|c,cachePool:null,transitions:g.transitions};f.memoizedState=g;f.childLanes=a.childLanes&~c;b.memoizedState=Cf;return d}f=a.child;a=f.sibling;d=gb(f,{mode:"visible",children:d.children});0===(b.mode&1)&&(d.lanes=c);d.return=b;d.sibling=null;null!==a&&(c=b.deletions,null===c?(b.deletions=[a],b.flags|=16):c.push(a));b.child=d;b.memoizedState=null;return d} +function Df(a,b,c){b=Gd({mode:"visible",children:b},a.mode,0,null);b.return=a;return a.child=b}function Hd(a,b,c,d){null!==d&&Ye(d);Vb(b,a.child,null,c);a=Df(b,b.pendingProps.children);a.flags|=2;b.memoizedState=null;return a}function vk(a,b,c,d,e,f,g){if(c){if(b.flags&256)return b.flags&=-257,d=vf(Error(n(422))),Hd(a,b,g,d);if(null!==b.memoizedState)return b.child=a.child,b.flags|=128,null;f=d.fallback;e=b.mode;d=Gd({mode:"visible",children:d.children},e,0,null);f=ub(f,e,g,null);f.flags|=2;d.return= +b;f.return=b;d.sibling=f;b.child=d;0!==(b.mode&1)&&Vb(b,a.child,null,g);b.child.memoizedState=Bf(g);b.memoizedState=Cf;return f}if(0===(b.mode&1))return Hd(a,b,g,null);if("$!"===e.data){d=e.nextSibling&&e.nextSibling.dataset;if(d)var h=d.dgst;d=h;f=Error(n(419));d=vf(f,d,void 0);return Hd(a,b,g,d)}h=0!==(g&a.childLanes);if(ha||h){d=O;if(null!==d){switch(g&-g){case 4:e=2;break;case 16:e=8;break;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:e= +32;break;case 536870912:e=268435456;break;default:e=0}e=0!==(e&(d.suspendedLanes|g))?0:e;0!==e&&e!==f.retryLane&&(f.retryLane=e,Oa(a,e),ya(d,a,e,-1))}Ef();d=vf(Error(n(421)));return Hd(a,b,g,d)}if("$?"===e.data)return b.flags|=128,b.child=a.child,b=wk.bind(null,a),e._reactRetry=b,null;a=f.treeContext;fa=Ka(e.nextSibling);la=b;D=!0;wa=null;null!==a&&(na[oa++]=Ma,na[oa++]=Na,na[oa++]=sb,Ma=a.id,Na=a.overflow,sb=b);b=Df(b,d.children);b.flags|=4096;return b}function wi(a,b,c){a.lanes|=b;var d=a.alternate; +null!==d&&(d.lanes|=b);bf(a.return,b,c)}function Ff(a,b,c,d,e){var f=a.memoizedState;null===f?a.memoizedState={isBackwards:b,rendering:null,renderingStartTime:0,last:d,tail:c,tailMode:e}:(f.isBackwards=b,f.rendering=null,f.renderingStartTime=0,f.last=d,f.tail=c,f.tailMode=e)}function xi(a,b,c){var d=b.pendingProps,e=d.revealOrder,f=d.tail;aa(a,b,d.children,c);d=G.current;if(0!==(d&2))d=d&1|2,b.flags|=128;else{if(null!==a&&0!==(a.flags&128))a:for(a=b.child;null!==a;){if(13===a.tag)null!==a.memoizedState&& +wi(a,c,b);else if(19===a.tag)wi(a,c,b);else if(null!==a.child){a.child.return=a;a=a.child;continue}if(a===b)break a;for(;null===a.sibling;){if(null===a.return||a.return===b)break a;a=a.return}a.sibling.return=a.return;a=a.sibling}d&=1}y(G,d);if(0===(b.mode&1))b.memoizedState=null;else switch(e){case "forwards":c=b.child;for(e=null;null!==c;)a=c.alternate,null!==a&&null===yd(a)&&(e=c),c=c.sibling;c=e;null===c?(e=b.child,b.child=null):(e=c.sibling,c.sibling=null);Ff(b,!1,e,c,f);break;case "backwards":c= +null;e=b.child;for(b.child=null;null!==e;){a=e.alternate;if(null!==a&&null===yd(a)){b.child=e;break}a=e.sibling;e.sibling=c;c=e;e=a}Ff(b,!0,c,null,f);break;case "together":Ff(b,!1,null,null,void 0);break;default:b.memoizedState=null}return b.child}function Fd(a,b){0===(b.mode&1)&&null!==a&&(a.alternate=null,b.alternate=null,b.flags|=2)}function Qa(a,b,c){null!==a&&(b.dependencies=a.dependencies);ra|=b.lanes;if(0===(c&b.childLanes))return null;if(null!==a&&b.child!==a.child)throw Error(n(153));if(null!== +b.child){a=b.child;c=gb(a,a.pendingProps);b.child=c;for(c.return=b;null!==a.sibling;)a=a.sibling,c=c.sibling=gb(a,a.pendingProps),c.return=b;c.sibling=null}return b.child}function xk(a,b,c){switch(b.tag){case 3:ti(b);Qb();break;case 5:Mh(b);break;case 1:ea(b.type)&&ld(b);break;case 4:jf(b,b.stateNode.containerInfo);break;case 10:var d=b.type._context,e=b.memoizedProps.value;y(rd,d._currentValue);d._currentValue=e;break;case 13:d=b.memoizedState;if(null!==d){if(null!==d.dehydrated)return y(G,G.current& +1),b.flags|=128,null;if(0!==(c&b.child.childLanes))return vi(a,b,c);y(G,G.current&1);a=Qa(a,b,c);return null!==a?a.sibling:null}y(G,G.current&1);break;case 19:d=0!==(c&b.childLanes);if(0!==(a.flags&128)){if(d)return xi(a,b,c);b.flags|=128}e=b.memoizedState;null!==e&&(e.rendering=null,e.tail=null,e.lastEffect=null);y(G,G.current);if(d)break;else return null;case 22:case 23:return b.lanes=0,qi(a,b,c)}return Qa(a,b,c)}function Dc(a,b){if(!D)switch(a.tailMode){case "hidden":b=a.tail;for(var c=null;null!== +b;)null!==b.alternate&&(c=b),b=b.sibling;null===c?a.tail=null:c.sibling=null;break;case "collapsed":c=a.tail;for(var d=null;null!==c;)null!==c.alternate&&(d=c),c=c.sibling;null===d?b||null===a.tail?a.tail=null:a.tail.sibling=null:d.sibling=null}}function W(a){var b=null!==a.alternate&&a.alternate.child===a.child,c=0,d=0;if(b)for(var e=a.child;null!==e;)c|=e.lanes|e.childLanes,d|=e.subtreeFlags&14680064,d|=e.flags&14680064,e.return=a,e=e.sibling;else for(e=a.child;null!==e;)c|=e.lanes|e.childLanes, +d|=e.subtreeFlags,d|=e.flags,e.return=a,e=e.sibling;a.subtreeFlags|=d;a.childLanes=c;return b}function yk(a,b,c){var d=b.pendingProps;Ve(b);switch(b.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return W(b),null;case 1:return ea(b.type)&&(w(S),w(J)),W(b),null;case 3:d=b.stateNode;Tb();w(S);w(J);lf();d.pendingContext&&(d.context=d.pendingContext,d.pendingContext=null);if(null===a||null===a.child)pd(b)?b.flags|=4:null===a||a.memoizedState.isDehydrated&&0===(b.flags& +256)||(b.flags|=1024,null!==wa&&(Gf(wa),wa=null));yi(a,b);W(b);return null;case 5:kf(b);var e=vb(xc.current);c=b.type;if(null!==a&&null!=b.stateNode)zk(a,b,c,d,e),a.ref!==b.ref&&(b.flags|=512,b.flags|=2097152);else{if(!d){if(null===b.stateNode)throw Error(n(166));W(b);return null}a=vb(Ea.current);if(pd(b)){d=b.stateNode;c=b.type;var f=b.memoizedProps;d[Da]=b;d[uc]=f;a=0!==(b.mode&1);switch(c){case "dialog":B("cancel",d);B("close",d);break;case "iframe":case "object":case "embed":B("load",d);break; +case "video":case "audio":for(e=0;e\x3c/script>",a=a.removeChild(a.firstChild)):"string"===typeof d.is?a=g.createElement(c,{is:d.is}):(a=g.createElement(c),"select"===c&&(g=a,d.multiple?g.multiple=!0:d.size&&(g.size=d.size))):a=g.createElementNS(a,c);a[Da]=b;a[uc]=d;Ak(a,b,!1,!1);b.stateNode=a;a:{g=qe(c,d);switch(c){case "dialog":B("cancel",a);B("close",a);e=d;break;case "iframe":case "object":case "embed":B("load",a);e=d;break; +case "video":case "audio":for(e=0;eHf&&(b.flags|=128,d=!0,Dc(f,!1),b.lanes=4194304)}else{if(!d)if(a=yd(g),null!==a){if(b.flags|=128,d=!0,c=a.updateQueue,null!==c&&(b.updateQueue=c,b.flags|=4),Dc(f,!0),null===f.tail&&"hidden"===f.tailMode&&!g.alternate&&!D)return W(b),null}else 2*P()-f.renderingStartTime>Hf&&1073741824!==c&&(b.flags|= +128,d=!0,Dc(f,!1),b.lanes=4194304);f.isBackwards?(g.sibling=b.child,b.child=g):(c=f.last,null!==c?c.sibling=g:b.child=g,f.last=g)}if(null!==f.tail)return b=f.tail,f.rendering=b,f.tail=b.sibling,f.renderingStartTime=P(),b.sibling=null,c=G.current,y(G,d?c&1|2:c&1),b;W(b);return null;case 22:case 23:return ba=Ga.current,w(Ga),d=null!==b.memoizedState,null!==a&&null!==a.memoizedState!==d&&(b.flags|=8192),d&&0!==(b.mode&1)?0!==(ba&1073741824)&&(W(b),b.subtreeFlags&6&&(b.flags|=8192)):W(b),null;case 24:return null; +case 25:return null}throw Error(n(156,b.tag));}function Ck(a,b,c){Ve(b);switch(b.tag){case 1:return ea(b.type)&&(w(S),w(J)),a=b.flags,a&65536?(b.flags=a&-65537|128,b):null;case 3:return Tb(),w(S),w(J),lf(),a=b.flags,0!==(a&65536)&&0===(a&128)?(b.flags=a&-65537|128,b):null;case 5:return kf(b),null;case 13:w(G);a=b.memoizedState;if(null!==a&&null!==a.dehydrated){if(null===b.alternate)throw Error(n(340));Qb()}a=b.flags;return a&65536?(b.flags=a&-65537|128,b):null;case 19:return w(G),null;case 4:return Tb(), +null;case 10:return af(b.type._context),null;case 22:case 23:return ba=Ga.current,w(Ga),null;case 24:return null;default:return null}}function Wb(a,b){var c=a.ref;if(null!==c)if("function"===typeof c)try{c(null)}catch(d){H(a,b,d)}else c.current=null}function If(a,b,c){try{c()}catch(d){H(a,b,d)}}function Dk(a,b){Jf=Zc;a=ch();if(Ie(a)){if("selectionStart"in a)var c={start:a.selectionStart,end:a.selectionEnd};else a:{c=(c=a.ownerDocument)&&c.defaultView||window;var d=c.getSelection&&c.getSelection(); +if(d&&0!==d.rangeCount){c=d.anchorNode;var e=d.anchorOffset,f=d.focusNode;d=d.focusOffset;try{c.nodeType,f.nodeType}catch(M){c=null;break a}var g=0,h=-1,k=-1,m=0,t=0,u=a,r=null;b:for(;;){for(var p;;){u!==c||0!==e&&3!==u.nodeType||(h=g+e);u!==f||0!==d&&3!==u.nodeType||(k=g+d);3===u.nodeType&&(g+=u.nodeValue.length);if(null===(p=u.firstChild))break;r=u;u=p}for(;;){if(u===a)break b;r===c&&++m===e&&(h=g);r===f&&++t===d&&(k=g);if(null!==(p=u.nextSibling))break;u=r;r=u.parentNode}u=p}c=-1===h||-1===k?null: +{start:h,end:k}}else c=null}c=c||{start:0,end:0}}else c=null;Kf={focusedElem:a,selectionRange:c};Zc=!1;for(l=b;null!==l;)if(b=l,a=b.child,0!==(b.subtreeFlags&1028)&&null!==a)a.return=b,l=a;else for(;null!==l;){b=l;try{var x=b.alternate;if(0!==(b.flags&1024))switch(b.tag){case 0:case 11:case 15:break;case 1:if(null!==x){var w=x.memoizedProps,z=x.memoizedState,A=b.stateNode,v=A.getSnapshotBeforeUpdate(b.elementType===b.type?w:xa(b.type,w),z);A.__reactInternalSnapshotBeforeUpdate=v}break;case 3:var q= +b.stateNode.containerInfo;1===q.nodeType?q.textContent="":9===q.nodeType&&q.documentElement&&q.removeChild(q.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(n(163));}}catch(M){H(b,b.return,M)}a=b.sibling;if(null!==a){a.return=b.return;l=a;break}l=b.return}x=Ai;Ai=!1;return x}function Gc(a,b,c){var d=b.updateQueue;d=null!==d?d.lastEffect:null;if(null!==d){var e=d=d.next;do{if((e.tag&a)===a){var f=e.destroy;e.destroy=void 0;void 0!==f&&If(b,c,f)}e=e.next}while(e!==d)}} +function Id(a,b){b=b.updateQueue;b=null!==b?b.lastEffect:null;if(null!==b){var c=b=b.next;do{if((c.tag&a)===a){var d=c.create;c.destroy=d()}c=c.next}while(c!==b)}}function Lf(a){var b=a.ref;if(null!==b){var c=a.stateNode;switch(a.tag){case 5:a=c;break;default:a=c}"function"===typeof b?b(a):b.current=a}}function Bi(a){var b=a.alternate;null!==b&&(a.alternate=null,Bi(b));a.child=null;a.deletions=null;a.sibling=null;5===a.tag&&(b=a.stateNode,null!==b&&(delete b[Da],delete b[uc],delete b[Me],delete b[Ek], +delete b[Fk]));a.stateNode=null;a.return=null;a.dependencies=null;a.memoizedProps=null;a.memoizedState=null;a.pendingProps=null;a.stateNode=null;a.updateQueue=null}function Ci(a){return 5===a.tag||3===a.tag||4===a.tag}function Di(a){a:for(;;){for(;null===a.sibling;){if(null===a.return||Ci(a.return))return null;a=a.return}a.sibling.return=a.return;for(a=a.sibling;5!==a.tag&&6!==a.tag&&18!==a.tag;){if(a.flags&2)continue a;if(null===a.child||4===a.tag)continue a;else a.child.return=a,a=a.child}if(!(a.flags& +2))return a.stateNode}}function Mf(a,b,c){var d=a.tag;if(5===d||6===d)a=a.stateNode,b?8===c.nodeType?c.parentNode.insertBefore(a,b):c.insertBefore(a,b):(8===c.nodeType?(b=c.parentNode,b.insertBefore(a,c)):(b=c,b.appendChild(a)),c=c._reactRootContainer,null!==c&&void 0!==c||null!==b.onclick||(b.onclick=kd));else if(4!==d&&(a=a.child,null!==a))for(Mf(a,b,c),a=a.sibling;null!==a;)Mf(a,b,c),a=a.sibling}function Nf(a,b,c){var d=a.tag;if(5===d||6===d)a=a.stateNode,b?c.insertBefore(a,b):c.appendChild(a); +else if(4!==d&&(a=a.child,null!==a))for(Nf(a,b,c),a=a.sibling;null!==a;)Nf(a,b,c),a=a.sibling}function jb(a,b,c){for(c=c.child;null!==c;)Ei(a,b,c),c=c.sibling}function Ei(a,b,c){if(Ca&&"function"===typeof Ca.onCommitFiberUnmount)try{Ca.onCommitFiberUnmount(Uc,c)}catch(h){}switch(c.tag){case 5:X||Wb(c,b);case 6:var d=T,e=za;T=null;jb(a,b,c);T=d;za=e;null!==T&&(za?(a=T,c=c.stateNode,8===a.nodeType?a.parentNode.removeChild(c):a.removeChild(c)):T.removeChild(c.stateNode));break;case 18:null!==T&&(za? +(a=T,c=c.stateNode,8===a.nodeType?Re(a.parentNode,c):1===a.nodeType&&Re(a,c),nc(a)):Re(T,c.stateNode));break;case 4:d=T;e=za;T=c.stateNode.containerInfo;za=!0;jb(a,b,c);T=d;za=e;break;case 0:case 11:case 14:case 15:if(!X&&(d=c.updateQueue,null!==d&&(d=d.lastEffect,null!==d))){e=d=d.next;do{var f=e,g=f.destroy;f=f.tag;void 0!==g&&(0!==(f&2)?If(c,b,g):0!==(f&4)&&If(c,b,g));e=e.next}while(e!==d)}jb(a,b,c);break;case 1:if(!X&&(Wb(c,b),d=c.stateNode,"function"===typeof d.componentWillUnmount))try{d.props= +c.memoizedProps,d.state=c.memoizedState,d.componentWillUnmount()}catch(h){H(c,b,h)}jb(a,b,c);break;case 21:jb(a,b,c);break;case 22:c.mode&1?(X=(d=X)||null!==c.memoizedState,jb(a,b,c),X=d):jb(a,b,c);break;default:jb(a,b,c)}}function Fi(a){var b=a.updateQueue;if(null!==b){a.updateQueue=null;var c=a.stateNode;null===c&&(c=a.stateNode=new Gk);b.forEach(function(b){var d=Hk.bind(null,a,b);c.has(b)||(c.add(b),b.then(d,d))})}}function Aa(a,b,c){c=b.deletions;if(null!==c)for(var d=0;de&&(e=g);d&=~f}d=e;d=P()-d;d=(120>d?120:480>d?480:1080>d?1080:1920>d?1920:3E3>d?3E3:4320>d?4320:1960*Nk(d/1960))-d;if(10a?16:a;if(null===lb)var d=!1;else{a=lb;lb=null;Qd=0;if(0!==(p&6))throw Error(n(331));var e=p;p|=4;for(l=a.current;null!==l;){var f=l,g=f.child;if(0!==(l.flags&16)){var h=f.deletions;if(null!==h){for(var k=0;kP()-Of?xb(a,0):Sf|=c);ia(a,b)}function Ui(a,b){0===b&&(0===(a.mode&1)?b=1:(b=Rd,Rd<<=1,0===(Rd&130023424)&&(Rd=4194304)));var c=Z();a=Oa(a,b);null!==a&&(ic(a,b,c),ia(a,c))}function wk(a){var b=a.memoizedState,c=0;null!==b&&(c=b.retryLane);Ui(a,c)}function Hk(a,b){var c=0;switch(a.tag){case 13:var d=a.stateNode;var e=a.memoizedState;null!==e&&(c=e.retryLane); +break;case 19:d=a.stateNode;break;default:throw Error(n(314));}null!==d&&d.delete(b);Ui(a,c)}function Ni(a,b){return xh(a,b)}function Uk(a,b,c,d){this.tag=a;this.key=c;this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null;this.index=0;this.ref=null;this.pendingProps=b;this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null;this.mode=d;this.subtreeFlags=this.flags=0;this.deletions=null;this.childLanes=this.lanes=0;this.alternate=null}function yf(a){a= +a.prototype;return!(!a||!a.isReactComponent)}function Vk(a){if("function"===typeof a)return yf(a)?1:0;if(void 0!==a&&null!==a){a=a.$$typeof;if(a===ie)return 11;if(a===je)return 14}return 2}function gb(a,b){var c=a.alternate;null===c?(c=pa(a.tag,b,a.key,a.mode),c.elementType=a.elementType,c.type=a.type,c.stateNode=a.stateNode,c.alternate=a,a.alternate=c):(c.pendingProps=b,c.type=a.type,c.flags=0,c.subtreeFlags=0,c.deletions=null);c.flags=a.flags&14680064;c.childLanes=a.childLanes;c.lanes=a.lanes;c.child= +a.child;c.memoizedProps=a.memoizedProps;c.memoizedState=a.memoizedState;c.updateQueue=a.updateQueue;b=a.dependencies;c.dependencies=null===b?null:{lanes:b.lanes,firstContext:b.firstContext};c.sibling=a.sibling;c.index=a.index;c.ref=a.ref;return c}function wd(a,b,c,d,e,f){var g=2;d=a;if("function"===typeof a)yf(a)&&(g=1);else if("string"===typeof a)g=5;else a:switch(a){case Bb:return ub(c.children,e,f,b);case fe:g=8;e|=8;break;case ee:return a=pa(12,c,b,e|2),a.elementType=ee,a.lanes=f,a;case ge:return a= +pa(13,c,b,e),a.elementType=ge,a.lanes=f,a;case he:return a=pa(19,c,b,e),a.elementType=he,a.lanes=f,a;case Vi:return Gd(c,e,f,b);default:if("object"===typeof a&&null!==a)switch(a.$$typeof){case hg:g=10;break a;case gg:g=9;break a;case ie:g=11;break a;case je:g=14;break a;case Ta:g=16;d=null;break a}throw Error(n(130,null==a?a:typeof a,""));}b=pa(g,c,b,e);b.elementType=a;b.type=d;b.lanes=f;return b}function ub(a,b,c,d){a=pa(7,a,d,b);a.lanes=c;return a}function Gd(a,b,c,d){a=pa(22,a,d,b);a.elementType= +Vi;a.lanes=c;a.stateNode={isHidden:!1};return a}function gf(a,b,c){a=pa(6,a,null,b);a.lanes=c;return a}function hf(a,b,c){b=pa(4,null!==a.children?a.children:[],a.key,b);b.lanes=c;b.stateNode={containerInfo:a.containerInfo,pendingChildren:null,implementation:a.implementation};return b}function Wk(a,b,c,d,e){this.tag=b;this.containerInfo=a;this.finishedWork=this.pingCache=this.current=this.pendingChildren=null;this.timeoutHandle=-1;this.callbackNode=this.pendingContext=this.context=null;this.callbackPriority= +0;this.eventTimes=we(0);this.expirationTimes=we(-1);this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0;this.entanglements=we(0);this.identifierPrefix=d;this.onRecoverableError=e;this.mutableSourceEagerHydrationData=null}function Vf(a,b,c,d,e,f,g,h,k,m){a=new Wk(a,b,c,h,k);1===b?(b=1,!0===f&&(b|=8)):b=0;f=pa(3,null,null,b);a.current=f;f.stateNode=a;f.memoizedState={element:d,isDehydrated:c,cache:null,transitions:null, +pendingSuspenseBoundaries:null};df(f);return a}function Xk(a,b,c){var d=3