--- title: "Extending fcaR: Equivalence Rules for Implications" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Extending fcaR: Equivalence Rules for Implications} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 5, warning = FALSE ) ``` # Introduction In this vignette, we present a way to extend the functionalities provided in the `fcaR` package: define new operations on an `ImplicationSet`. First, we load the `fcaR` package by: ```{r setup} library(fcaR) ``` Let us use the `planets` dataset included in the package: ```{r} fc <- FormalContext$new(planets) fc$find_implications() ``` # The Registry In `fcaR`, we have decided to use a `registry` from the `registry` package to store the operations that can be performed on an `ImplicationSet`. Currently, its purpose is to store equivalence rules, that is, methods that obtain equivalent `ImplicationSet`s from one given. This registry is called `equivalencesRegistry` and one can inspect its contents by: ```{r} equivalencesRegistry$get_entry_names() ``` These names correspond to the methods that are added to the registry by default, and are used to index those methods. Every method is accompanied by a description, so we can see its definition: ```{r} equivalencesRegistry$get_entry("Composition") ``` We can even use abbreviated names to refer to the method: ```{r} equivalencesRegistry$get_entry("comp") ``` # Use of the Rules As explained in the vignette corresponding to `ImplicationSet`s, we can use any of these methods by using the `apply_rules()` method in the `ImplicationSet`: ```{r eval = FALSE} fc$implications$apply_rules(c("comp", "simp")) ``` # Definition of New Equivalence Rules The way to extend the functionality in `fcaR` is to define new equivalence operators and include them in the registry. In order to add a new method, we use: ```{r eval = FALSE} equivalencesRegistry$set_entry(method = "Method name", fun = method_function, description = "Method description") ``` where `method_function()` must be a function with the following scheme: ```{r eval = FALSE} method_function <- function(LHS, RHS, attributes) { # LHS and RHS are the sparse matrices of the left-hand and # right-hand sides of the implications # attributes is the vector of attribute names # The three arguments are mandatory # Perform operations on LHS and RHS # ... # Must return a list with two components: lhs and rhs return(list(lhs = LHS, rhs = RHS)) } ``` The `method_function()` function must be defined before adding the method to the registry. Once the method is added, it can be executed by using the corresponding call to `apply_rules()`. # An Example Let us define an operator which randomly reorders the implications. Evidently, this operation provides an equivalent `ImplicationSet`. In this case, we begin by defining the method function: ```{r} random_reorder <- function(LHS, RHS, attributes) { # Remember: attributes are in rows, implications are # in columns. # Random order for columns: o <- sample(ncol(LHS), ncol(LHS)) # Return the reordered implications return(list(lhs = LHS[, o], rhs = RHS[, o])) } ``` Once we have defined the function, we add the method to the registry: ```{r} equivalencesRegistry$set_entry(method = "Randomize", fun = random_reorder, description = "Randomize the order of the implications.") ``` If we inspect the registry, we obtain the list of the methods, including the one we have just inserted: ```{r} equivalencesRegistry$get_entry_names() ``` We can apply the new method: ```{r} # Original implications fc$implications ``` ```{r} # Apply the randomize method fc$implications$apply_rules("randomize") ``` ```{r} # Reordered implications fc$implications ```