| Title: | Directed Causal Network Enumeration and Simulation | 
| Version: | 0.1.0 | 
| Description: | Enumerate orientation-consistent directed networks from an undirected or partially directed skeleton, detect feedback loops, summarize topology, and simulate node dynamics via stochastic differential equations. | 
| License: | GPL-3 | 
| URL: | https://github.com/KyuriP/causalnet | 
| BugReports: | https://github.com/KyuriP/causalnet/issues | 
| Encoding: | UTF-8 | 
| RoxygenNote: | 7.3.2 | 
| VignetteBuilder: | knitr | 
| Imports: | stats, ggplot2, tidyr, scales, cowplot | 
| Suggests: | testthat (≥ 3.0.0), dplyr, knitr, rmarkdown | 
| Config/testthat/edition: | 3 | 
| NeedsCompilation: | no | 
| Packaged: | 2025-09-01 16:03:58 UTC; Kyuri1 | 
| Author: | Kyuri Park [aut, cre] | 
| Maintainer: | Kyuri Park <kyurheep@gmail.com> | 
| Repository: | CRAN | 
| Date/Publication: | 2025-09-05 21:00:10 UTC | 
Detect Unique Feedback Loops in a Directed Network
Description
Detects all directed cycles (including 2-node loops) and returns each as a unique set of nodes (ignores order and entry point).
Usage
detect_feedback_loops(adj_matrix, include_self_loops = FALSE, use_names = TRUE)
Arguments
| adj_matrix | Square directed adjacency (non-zero = edge). | 
| include_self_loops | Logical; include 1-node self-loops (default FALSE). | 
| use_names | Logical; return node names if available (default TRUE). | 
Value
List of unique loops, each as a sorted vector (names if available, else indices).
Generate Directed Networks Consistent with Constraints
Description
Enumerate all directed adjacency matrices that are consistent with a given undirected skeleton and optional direction constraints. Enumeration can optionally include bidirected edges and display a simple progress bar.
Usage
generate_directed_networks(
  adj_matrix,
  allow_bidirectional = TRUE,
  fixed_edges = NULL,
  max_networks = Inf,
  show_progress = interactive()
)
Arguments
| adj_matrix | Symmetric binary (0/1) adjacency matrix giving the
undirected skeleton. Only pairs with  | 
| allow_bidirectional | Logical. If  | 
| fixed_edges | Numeric matrix the same size as  
 Constraints on pairs not present in the skeleton are ignored. | 
| max_networks | Integer. Maximum number of networks to return. Use to cap
output size when constraints are loose and the search space is large.
Default:  | 
| show_progress | Logical. Show a text progress bar during enumeration.
Default:  | 
Details
If the skeleton has m undirected edges, the number of
orientation-consistent digraphs is at most 2^m when
allow_bidirectional = FALSE and 3^m when TRUE
(before applying constraints). Consider setting max_networks
for exploratory use.
Value
A list of unique directed 0/1 adjacency matrices, each with the same
dimensions and dimnames as adj_matrix.
See Also
detect_feedback_loops, summarize_network_metrics
Examples
skel <- matrix(0, 3, 3); skel[upper.tri(skel)] <- 1; skel <- skel + t(skel)
colnames(skel) <- rownames(skel) <- paste0("X", 1:3)
out <- generate_directed_networks(skel, allow_bidirectional = TRUE)
length(out)
# Force X1 -> X2 and X2 <-> X3:
F <- matrix(NA_real_, 3, 3, dimnames = dimnames(skel))
F["X1", "X2"] <- 1
F["X2", "X3"] <- 2
out2 <- generate_directed_networks(skel, fixed_edges = F)
length(out2)
Generate Sample Parameters for Node Dynamics
Description
Returns a list of simulation parameters (domain-agnostic: nodes can be any variables). If a parameter vector is not supplied, values are sampled i.i.d. from a uniform range.
Usage
get_sample_parameters(
  n_nodes,
  beta_range = c(-1.5, -1),
  alpha_range = c(0.05, 0.3),
  delta_range = c(1, 5),
  sigma_range = c(0.01, 0.1),
  beta = NULL,
  alpha_self = NULL,
  delta = NULL,
  sigma = NULL,
  nodes = NULL
)
Arguments
| n_nodes | Integer number of nodes. | 
| beta_range | Length-2 numeric range for baseline/exogenous drive (used if  | 
| alpha_range | Length-2 numeric range for self-activation (used if  | 
| delta_range | Length-2 numeric range for nonlinear amplification (used if  | 
| sigma_range | Length-2 numeric range for noise SD (used if  | 
| beta,alpha_self,delta,sigma | Optional fixed numeric vectors. If length-1, recycled to  | 
| nodes | Optional character vector of node names (length  | 
Value
A named list with elements beta, alpha_self, delta, sigma (each length n_nodes).
Plot Dynamics with Optional Stress Shading
Description
Visualizes node/variable dynamics over time using ggplot2, with optional stress intervals and customizable styling.
Usage
plot_dynamics(
  S,
  stress_windows = NULL,
  title = "Dynamics",
  colors = NULL,
  legend_labels = NULL,
  show_lines = FALSE,
  line_width = 0.8,
  line_alpha = 1,
  base_size = 14,
  label_stress = TRUE,
  stress_label = "Stress Period",
  stress_fill = "gray60",
  stress_alpha = 0.2,
  stress_line_color = "gray40",
  y_label = "Level",
  legend_position = "right",
  y_limits = NULL
)
Arguments
| S | Matrix (time x variables) of simulated states. If  | 
| stress_windows | Optional list of numeric  | 
| title | Plot title. | 
| colors | Optional vector of line colors (length = #variables). | 
| legend_labels | Optional vector of legend labels (length = #variables). | 
| show_lines | If TRUE, draw dashed vertical lines instead of shaded rectangles. | 
| line_width | Line width for trajectories. | 
| line_alpha | Line transparency (0–1). | 
| base_size | Base font size for theme. | 
| label_stress | If TRUE and using shading, label each stress window. | 
| stress_label | Text label (length 1 or length = #windows). | 
| stress_fill | Fill color for shaded windows. | 
| stress_alpha | Alpha for shaded windows. | 
| stress_line_color | Color for dashed lines (if  | 
| y_label | Y-axis label. | 
| legend_position | Legend position (e.g.,  | 
| y_limits | Optional numeric length-2 vector for y-axis limits. | 
Value
A ggplot object.
Generate ggplot objects summarizing network metrics
Description
Produces a list of ggplot2 objects visualizing summary metrics across a list of directed networks.
Usage
plot_network_metrics(
  summary_df,
  n_bins = 6,
  fill_colors = c("skyblue", "darkgreen", "orange", "lightcoral"),
  base_size = 14,
  return_grid = TRUE
)
Arguments
| summary_df | Data frame from  | 
| n_bins | Number of histogram bins (default = 6). | 
| fill_colors | Optional vector of 4 fill colors. | 
| base_size | Base font size for plots (default = 14). | 
| return_grid | If TRUE, returns cowplot grid; otherwise, returns list of plots. | 
Value
A cowplot grid or a named list of ggplot2 objects.
Simulate network state dynamics via SDEs (nonlinear, linear, or custom)
Description
Simulates the evolution of node states in a directed network using an Euler–Maruyama discretization of stochastic differential equations (SDEs). Choose the built-in nonlinear model, a linear alternative, or provide a custom update function.
Usage
simulate_dynamics(
  adj_matrix,
  params,
  t_max = 100,
  dt = 0.1,
  S0 = NULL,
  model_type = "nonlinear",
  model_fn = NULL,
  stress_event = NULL,
  boundary = c("auto", "reflect", "clamp", "none"),
  clamp = NULL
)
Arguments
| adj_matrix | Numeric matrix (square; directed adjacency). Interpreted as i -> j. | 
| params | Named list of model parameters.
For  
 For  | 
| t_max | Total simulated time (must be > 0). | 
| dt | Time step (must be > 0). The output has  | 
| S0 | Optional numeric vector of initial states (length = n). Defaults to 0.01. | 
| model_type | One of  | 
| model_fn | Optional function with signature
 | 
| stress_event | Optional function  | 
| boundary | One of  
 | 
| clamp | Either  | 
Details
Direction convention. By default adj[i, j] = 1 encodes a directed edge
i -> j. Under this convention, the incoming input to node j is the
dot product of column j with the current state; in vector form
t(adj) %*% state. If your internal convention differs, transpose accordingly.
Integration uses Euler–Maruyama. The per-step diffusion term is added
as \sigma \sqrt{dt}\,Z with Z \sim \mathcal{N}(0, I) (component-wise),
i.e., sigma * sqrt(dt) * rnorm(n).
Value
Numeric matrix of states over time (rows = time steps, cols = nodes).
The time vector is attached as attr(result, "time").
Boundary handling
-  Reflecting avoids “sticky” edges by bouncing trajectories back inside the range, which is useful for bounded variables on [0,1].
-  Clamping is numerically simple but can create artificial absorbing states at the limits. 
- For smoothly bounded dynamics, consider modeling on an unbounded latent scale and applying a link (e.g., logistic) instead of hard post-step bounds. 
Examples
set.seed(1)
net <- matrix(c(0,1,0,0,
                0,0,1,0,
                0,0,0,1,
                1,0,0,0), 4, byrow = TRUE)
# Linear model, automatic boundary selection ("none" because no clamp supplied)
p_lin <- list(beta = rep(0.8, 4), alpha_self = rep(0.2, 4), sigma = rep(0.05, 4))
S1 <- simulate_dynamics(net, p_lin, model_type = "linear", boundary = "auto", t_max = 5, dt = 0.01)
# Linear model with a finite box -> "auto" switches to clamp on [0, 5]
S2 <- simulate_dynamics(net, p_lin, model_type = "linear",
                        boundary = "auto", clamp = c(0, 5), t_max = 5, dt = 0.01)
# Nonlinear model -> "auto" uses reflecting boundaries on [0,1]
p_nl <- list(beta = rep(0.2, 4), alpha_self = rep(0.2, 4),
             delta = rep(0.5, 4), sigma = rep(0.05, 4))
S3 <- simulate_dynamics(
  net, p_nl, model_type = "nonlinear",
  boundary = "auto", t_max = 5, dt = 0.01
)
Summarize Directed Network List
Description
Compute feedback loop and topology metrics for a list of directed networks.
Usage
summarize_network_metrics(net_list)
Arguments
| net_list | A list of directed adjacency matrices (can be from any source). | 
Value
A data frame with one row per network and the following columns:
- net_id 
- n_nodes 
- n_edges 
- num_loops (number of unique feedback loops) 
- sigma_total (sum of SDs of in/out degrees) 
- node_overlap_score 
- avg_loop_size