This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.
Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.
The tutorial explains how to execute and use the FCM package on the “book_example.xlsx” example. The tutorial aims to walk through some of the main functions in the package and to show their interdependencies to consistently compute the core components of the fuzzy cognitive maps.
Let’s start with initiating an object for storing current data set.
library(FCM)
init_matrix <- list(data = NULL)
We need to input the file. It could be done by using the following code, which reads the matrix from the 4th sheet of the example file.
library(xlsx)
dataRow <- read.xlsx('book_example.xlsx',sheetIndex = 4, startRow=1, endRow=8)
After inputting the matrix we assign the input matrix to the variable mat1
as follows.
mat1<-data.matrix(dataRow[,seq(2, 8)], rownames.force = NA)
Let’s look at the obtained matrix.
mat1
X1 X2 X3 X4 X5 X6 X7
[1,] 0.0 0.0 0.6 0.9 0.0 0.0 0.0
[2,] 0.1 0.0 0.0 0.0 0.0 0.0 0.0
[3,] 0.0 0.7 0.0 0.0 0.9 0.0 0.0
[4,] 0.0 0.0 0.0 0.0 0.0 0.0 0.9
[5,] 0.0 0.0 0.0 0.0 0.0 -0.9 -0.9
[6,] -0.3 0.0 0.0 0.0 0.0 0.0 0.0
[7,] 0.0 0.0 0.0 0.0 0.0 0.8 0.0
Let’s name the rows of the matrix.
rownames(mat1) <- rownames(mat1, do.NULL = FALSE, prefix = "f_")
mat1
X1 X2 X3 X4 X5 X6 X7
f_1 0.0 0.0 0.6 0.9 0.0 0.0 0.0
f_2 0.1 0.0 0.0 0.0 0.0 0.0 0.0
f_3 0.0 0.7 0.0 0.0 0.9 0.0 0.0
f_4 0.0 0.0 0.0 0.0 0.0 0.0 0.9
f_5 0.0 0.0 0.0 0.0 0.0 -0.9 -0.9
f_6 -0.3 0.0 0.0 0.0 0.0 0.0 0.0
f_7 0.0 0.0 0.0 0.0 0.0 0.8 0.0
Now the matrix has row and column names. Further, we fill the init_matrix
“data” with the values from mat1
.
init_matrix$data <- mat1
summary(init_matrix)
Length Class Mode
data 49 -none- numeric
Now, let’s initiate some parameters in order to calculate the transitive matrix. In the case of “min t-norm”, “drastic sum” and make lists of s- and t-norms:
tnorm <- min_tnorm(0.5,0.3)
tnorm
[1] 0.3
snormElement <- get_snorm('Drastic Sum')(0.3,0.7,0,0)
snormElement
[1] 1
snormMatrix <-get_snorm('Drastic Sum')(0.3,0.7)
snormMatrix
[1] 1
And make lists of t- and s-norm functions.
tnorm_functions <- list(min_tnorm = min_tnorm,
hamacher_product_tnorm = hamacher_product_tnorm,
algebraic_product_tnorm = algebraic_product_tnorm,
einstein_product_tnorm = einstein_product_tnorm,
bounded_difference_tnorm = bounded_difference_tnorm,
drastic_product_tnorm = drastic_product_tnorm,
parameterized_mean_intersection_operator_tnorm = parameterized_mean_intersection_operator_tnorm,
dubois_intersection_operator_tnorm = dubois_intersection_operator_tnorm,
hamacher_intersection_operator_tnorm = hamacher_intersection_operator_tnorm,
yager_intersection_operator_tnorm = yager_intersection_operator_tnorm)
snorm_functions <- list(drastic_sum_snorm = get_snorm("Drastic Sum"),
bounded_sum_snorm = get_snorm("Bounded Sum"),
einstein_sum_snorm = get_snorm("Einstein Sum"),
algebraic_sum_snorm = get_snorm("Algebraic Sum"),
hamacher_sum_snorm = get_snorm("Hamacher Sum"),
max_snorm = get_snorm("Max"),
hamacher_union_operator_snorm = get_snorm("Hamacher-union operator"),
yager_union_operator_snorm = get_snorm("Yager-union operator"))
Now, we are able to calculate the “eigen numbers” and “positive matrix”. This, in turn, allows us to calculate respective transitive closure matrix.
eigen_numbers <- eigen_module(init_matrix$data)
positive_matrix <- positive_matrix_calc(init_matrix$data)
matrix <- transitive_closure(positive_matrix, tnorm_functions, tnorm, snorm_functions, snormElement, snormMatrix,
gammaTnormMean=0.05, algaTnorm=0.1, gammaTnorm=0.02, piTnorm=0.2)
transitive_matrix <- matrix
We have calculated the transitive matrix. Let’s check whether it is not null.
!is.null(transitive_matrix)
[1] TRUE
Once we have done the above steps, we can check whether the matrix is indeed transitive.
tr_maximum_check <- multiply_matrix(transitive_matrix, transitive_matrix, tnorm_functions, tnorm, snorm_functions, snormElement,
gammaTnormMean, algaTnorm, gammaTnorm, piTnorm,
gammaSnormElement, piSnormElement)
aa <- transitive_matrix - tr_maximum_check
if (sum(aa < -0.00001) == 0 ) 'yes' else 'no'
[1] "yes"
We concluded that matrix is a transitive one.
Now, we can calculate the joined transitive matrix.
transitive_matrix_joined <- matrix_transitive_join(transitive_matrix, snorm_functions, snormElement,gammaSnorm, piSnorm)
transitive_matrix_joined
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
[1,] 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1
[2,] 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1
[3,] 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1
[4,] 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1
[5,] 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1
[6,] 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1
[7,] 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1
[,14]
[1,] -1
[2,] -1
[3,] -1
[4,] -1
[5,] -1
[6,] -1
[7,] -1
For an init_matrix$data
we may present the graph of nodes using the qgraph
library.
library(qgraph)
Registered S3 methods overwritten by 'htmltools':
method from
print.html tools:rstudio
print.shiny.tag tools:rstudio
print.shiny.tag.list tools:rstudio
Registered S3 method overwritten by 'htmlwidgets':
method from
print.htmlwidget tools:rstudio
Registered S3 method overwritten by 'data.table':
method from
print.data.table
qgraph(init_matrix$data,edge.labels=TRUE)
Let’s calculate the impulse data for our initial matrix.
m2 <- matrix(cbind(0), ncol = 1, nrow = nrow(init_matrix$data))
colnames(m2) <- c("x")
DF = m2
For the step impulse of 10, the impulse data will be as follows:
stepImpulse <- 10
DF <- DF[,'x']
k <- DF
for(i in 1:stepImpulse)
{
k <- t(init_matrix$data) %*% k
i <- i+1
DF <- cbind(DF, round(k, 5))
}
colnames(DF) <- c('x', 1:stepImpulse)
data_impulse <- DF
data.frame(data_impulse)
The corresponding plot for the obtained impulse data is shown below.
matplot(t(data_impulse),type = "l", xlab = NULL, ylab = "Impulse")
legend("topright", inset=0, legend=c(1:nrow(data_impulse)), pch=1, col=c(1:nrow(data_impulse)), horiz=TRUE)
To calculate the direct task, the control vector should be identified.
finalvector <- length(which(colSums(init_matrix$data == 0) == ncol(init_matrix$data)))
DF_control_vector <- finalvector
DF_control_vector
[1] 0
Since the value of DF_control_vector
is 0, there aren’t any control vectors in data.
Therefore, the direct solution matrix is NULL as well.
Let’s obtain the DF_goal_vector to calculate the reverse task.
if (!is.null(init_matrix$data)) {
finalvector <- length(which(rowSums(init_matrix$data == 0) == nrow(init_matrix$data)))
if (finalvector > 0)
data.frame(N = rep(0, finalvector),
G = rep(0, finalvector),
stringsAsFactors = FALSE)
}
DF_goal_vector <- finalvector
DF_goal_vector
[1] 0
The same as for direct task, the reverse task control vector is absent as well as the corresponding solution matrix.
Let’s look at the consonanse plot for recently calculated transitive_matrix_joined
. For that purpose we should firstly use cross_consonanse
function.
c_mat <- cross_consonanse(transitive_matrix_joined)
borderCut = 0.7
c_cut <- ifelse(c_mat<borderCut,0,1)
qgraph(c_cut,edge.labels=TRUE,title="Consonance")
Very similarly to consonanse we can obtain the dissonanse plot.
d_mat <- cross_dissonanse(transitive_matrix_joined)
d_cut <- ifelse(d_mat<borderCut,0,1)
qgraph(d_cut,edge.labels=TRUE,title="Dissonance")
Positive influence calculation in almost identical to the previous ones.
p_mat <- cross_positive_influence(transitive_matrix_joined)
p_cut <- ifelse(p_mat<borderCut,0,1)
qgraph(p_cut,edge.labels=TRUE,title="Positive influence")
Finally, we can plot the negative influence.
n_mat <- cross_negative_influence(transitive_matrix_joined)
n_cut <- ifelse(abs(n_mat)<borderCut,0,1)
qgraph(n_cut,edge.labels=TRUE,title="Negative influence")
We can also present the consonanse / dissonanse information in the table.
consonanse_dissonanse <- consonanse_dissonanse(transitive_matrix_joined)
data.frame(consonanse_dissonanse)
We can now calculate IK positive for the calculated above transitive joined matrix. As for parameters, from
and to
are set manually.
from = 1
to = 1
IKPositive <- ik_pos_maximum(transitive_matrix_joined, init_matrix$data, from, to)
data.frame(IKPositive)
Very similarly to the previous section, we can now calculate IK negative with the same parameters and present the results as a data frame.
IKNegative <- ik_neg_maximum(transitive_matrix_joined, init_matrix$data,from,to)
data.frame(IKNegative)
So far, for the given book example matrix we were managed to calculate transitive matrix, check whether it is transitive to verify the correctness of the calculations. Furthemore, for the respective transitive matrix we allowed to get calculate and plot netword data in the form of nodes, impulse, direct and reverse tasks, consonanse/dissonanse plots and the respective consonanse table, positive and negative influence plots as well as the IK positive and negative.
During the tutorial we manually assigned some values to the parameters. For the purpose of the further research, you may try different values and compare the obtained results.
To conclude, using the FCM package we are able to calculate different components which further could be used as a core for a separate application.