| 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