Nothing
#' MICMAC Analysis
#'
#' Performs MICMAC (Cross-Impact Matrix Multiplication Applied to Classification)
#' analysis on a reachability matrix to classify elements based on their driving
#' power and dependence power.
#'
#' @param reach_matrix A square reachability matrix (n x n) with 0/1 entries,
#' typically computed using \code{\link{compute_reachability}}.
#'
#' @return An object of class \code{micmac_result}, which is a data frame with:
#' \itemize{
#' \item \code{node}: node index
#' \item \code{label}: node label (from matrix dimnames or numeric)
#' \item \code{driving_power}: number of elements this node can reach
#' \item \code{dependence_power}: number of elements that can reach this node
#' \item \code{cluster}: classification into one of four clusters
#' }
#'
#' The four clusters are:
#' \describe{
#' \item{I - Autonomous}{Low driving power, low dependence. Disconnected from system.}
#' \item{II - Dependent}{Low driving power, high dependence. Outcomes/results.}
#' \item{III - Linkage}{High driving power, high dependence. Unstable, key connectors.}
#' \item{IV - Independent}{High driving power, low dependence. Root causes/drivers.}
#' }
#'
#' @details
#' MICMAC analysis is a complementary technique to ISM that helps identify the
#' key drivers and dependent variables in a system.
#'
#' \strong{Driving Power}: The number of elements that a given element can reach
#' (row sum of reachability matrix).
#'
#' \strong{Dependence Power}: The number of elements that can reach a given element
#' (column sum of reachability matrix).
#'
#' Elements are classified into four clusters based on whether their driving and
#' dependence powers are above or below the median values.
#'
#' @references
#' Duperrin, J. C., & Godet, M. (1973). Methode de hierarchisation des elements
#' d'un systeme. Rapport economique du CEA, R-45-41.
#'
#' Warfield, J. N. (1974). Developing interconnection matrices in structural
#' modeling. \emph{IEEE Transactions on Systems, Man, and Cybernetics},
#' SMC-4(1), 81-87. \doi{10.1109/TSMC.1974.5408524}
#'
#' @seealso
#' \code{\link{plot_micmac}} for visualization,
#' \code{\link{compute_reachability}} for computing reachability matrices,
#' \code{\link{level_partitioning}} for hierarchical decomposition.
#'
#' @export
#' @examples
#' # Create adjacency matrix
#' adj <- matrix(c(0, 1, 0, 0, 0,
#' 0, 0, 1, 0, 0,
#' 0, 0, 0, 1, 1,
#' 0, 0, 0, 0, 0,
#' 0, 0, 0, 0, 0), nrow = 5, byrow = TRUE)
#' rownames(adj) <- colnames(adj) <- paste0("F", 1:5)
#'
#' # Compute reachability and MICMAC
#' reach <- compute_reachability(adj)
#' micmac <- micmac_analysis(reach)
#' print(micmac)
#'
#' # View cluster distribution
#' table(micmac$cluster)
micmac_analysis <- function(reach_matrix) {
# Input validation
if (!is.matrix(reach_matrix)) {
stop("Input must be a matrix", call. = FALSE)
}
if (nrow(reach_matrix) != ncol(reach_matrix)) {
stop("Matrix must be square", call. = FALSE)
}
n <- nrow(reach_matrix)
# Get labels
labels <- rownames(reach_matrix)
if (is.null(labels)) {
labels <- as.character(seq_len(n))
}
# Calculate driving power (row sums) and dependence power (column sums)
driving_power <- rowSums(reach_matrix)
dependence_power <- colSums(reach_matrix)
# Calculate thresholds (median values)
driving_threshold <- stats::median(driving_power)
dependence_threshold <- stats::median(dependence_power)
# Classify into clusters
cluster <- character(n)
for (i in seq_len(n)) {
high_driving <- driving_power[i] >= driving_threshold
high_dependence <- dependence_power[i] >= dependence_threshold
if (!high_driving && !high_dependence) {
cluster[i] <- "I - Autonomous"
} else if (!high_driving && high_dependence) {
cluster[i] <- "II - Dependent"
} else if (high_driving && high_dependence) {
cluster[i] <- "III - Linkage"
} else {
cluster[i] <- "IV - Independent"
}
}
result <- data.frame(
node = seq_len(n),
label = labels,
driving_power = driving_power,
dependence_power = dependence_power,
cluster = cluster,
stringsAsFactors = FALSE
)
# Add attributes for plotting
attr(result, "driving_threshold") <- driving_threshold
attr(result, "dependence_threshold") <- dependence_threshold
class(result) <- c("micmac_result", "data.frame")
return(result)
}
#' Print MICMAC Results
#'
#' @param x An object of class \code{micmac_result}
#' @param ... Additional arguments (ignored)
#'
#' @return Invisibly returns the input object
#'
#' @export
#' @method print micmac_result
print.micmac_result <- function(x, ...) {
cat("MICMAC Analysis Results\n")
cat("=======================\n\n")
# Print cluster summary
cluster_counts <- table(x$cluster)
cat("Cluster Distribution:\n")
for (cl in names(cluster_counts)) {
cat(sprintf(" %s: %d elements\n", cl, cluster_counts[cl]))
}
cat("\nThresholds:\n")
cat(sprintf(" Driving Power: %.1f\n", attr(x, "driving_threshold")))
cat(sprintf(" Dependence Power: %.1f\n", attr(x, "dependence_threshold")))
cat("\nElement Details:\n")
print.data.frame(x, row.names = FALSE)
invisible(x)
}
#' Plot MICMAC Diagram
#'
#' Creates a scatter plot showing the MICMAC classification of elements based
#' on their driving power and dependence power.
#'
#' @param micmac_result An object of class \code{micmac_result} from
#' \code{\link{micmac_analysis}}.
#' @param show_labels Logical. If \code{TRUE} (default), show node labels on the plot.
#' @param main Title for the plot. Default is "MICMAC Analysis".
#' @param ... Additional arguments passed to \code{plot}.
#'
#' @return Invisibly returns the micmac_result object.
#'
#' @details
#' The plot is divided into four quadrants:
#' \describe{
#' \item{Quadrant I (bottom-left)}{Autonomous variables - weak drivers, weak dependence}
#' \item{Quadrant II (bottom-right)}{Dependent variables - weak drivers, strong dependence}
#' \item{Quadrant III (top-right)}{Linkage variables - strong drivers, strong dependence}
#' \item{Quadrant IV (top-left)}{Independent variables - strong drivers, weak dependence}
#' }
#'
#' @seealso
#' \code{\link{micmac_analysis}} for computing MICMAC results.
#'
#' @export
#' @examples
#' adj <- matrix(c(0, 1, 0, 0, 0,
#' 0, 0, 1, 0, 0,
#' 0, 0, 0, 1, 1,
#' 0, 0, 0, 0, 0,
#' 0, 0, 0, 0, 0), nrow = 5, byrow = TRUE)
#' rownames(adj) <- colnames(adj) <- paste0("F", 1:5)
#'
#' reach <- compute_reachability(adj)
#' micmac <- micmac_analysis(reach)
#' plot_micmac(micmac)
plot_micmac <- function(micmac_result,
show_labels = TRUE,
main = "MICMAC Analysis",
...) {
if (!inherits(micmac_result, "micmac_result")) {
stop("Input must be a micmac_result object from micmac_analysis()", call. = FALSE)
}
# Get thresholds
driving_threshold <- attr(micmac_result, "driving_threshold")
dependence_threshold <- attr(micmac_result, "dependence_threshold")
# Cluster colors
cluster_colors <- c(
"I - Autonomous" = "#999999",
"II - Dependent" = "#E69F00",
"III - Linkage" = "#56B4E9",
"IV - Independent" = "#009E73"
)
# Set up plot
old_par <- graphics::par(mar = c(5, 5, 4, 2))
on.exit(graphics::par(old_par))
x_range <- range(micmac_result$dependence_power)
y_range <- range(micmac_result$driving_power)
# Add some padding
x_pad <- diff(x_range) * 0.1
y_pad <- diff(y_range) * 0.1
graphics::plot(
micmac_result$dependence_power,
micmac_result$driving_power,
xlim = c(x_range[1] - x_pad, x_range[2] + x_pad),
ylim = c(y_range[1] - y_pad, y_range[2] + y_pad),
xlab = "Dependence Power",
ylab = "Driving Power",
main = main,
pch = 19,
cex = 1.5,
col = cluster_colors[micmac_result$cluster],
...
)
# Add threshold lines
graphics::abline(h = driving_threshold, lty = 2, col = "gray50")
graphics::abline(v = dependence_threshold, lty = 2, col = "gray50")
# Add quadrant labels
x_mid <- mean(x_range)
y_mid <- mean(y_range)
graphics::text(x_range[1], y_range[2], "IV\nIndependent",
adj = c(0, 1), col = "gray40", cex = 0.8)
graphics::text(x_range[2], y_range[2], "III\nLinkage",
adj = c(1, 1), col = "gray40", cex = 0.8)
graphics::text(x_range[1], y_range[1], "I\nAutonomous",
adj = c(0, 0), col = "gray40", cex = 0.8)
graphics::text(x_range[2], y_range[1], "II\nDependent",
adj = c(1, 0), col = "gray40", cex = 0.8)
# Add labels if requested
if (show_labels) {
graphics::text(
micmac_result$dependence_power,
micmac_result$driving_power,
labels = micmac_result$label,
pos = 3,
cex = 0.8
)
}
# Add legend
graphics::legend(
"topright",
legend = names(cluster_colors),
col = cluster_colors,
pch = 19,
cex = 0.8,
bg = "white"
)
invisible(micmac_result)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.