== and != methods for caugi objects so cg1 == cg2 returns a single
logical comparing graph content (class, nodes, edges, simple) rather than
session identity.@graph_class = "MPDAG" instead of
"PDAG". This affects the result of meek_closure() and
generate_graph(class = "CPDAG"). Predicates and verbs defined on PDAGs
(is_pdag(), mutate_caugi(), etc.) continue to accept MPDAGs unchanged.Fix dag_from_pdag() failing with `from`, `edge`, `to` must be equal length. when a sink had multiple undirected neighbors (#298).
Fixed a bug causing a partially undirected (--o) edges to
be plotted as undirected edges.
caugi_layout_circle() and a "circle" method for caugi_layout() that
places nodes evenly along the perimeter of a circle (#108).list_caugi_edges() function to list all available edge types."MPDAG" graph class support across constructor, class
mutation, and class resolution. class = "AUTO" now resolves Meek-closed
PDAGs to "MPDAG".exogenize() is now implemented in Rust for DAGs, which reduces overhead on larger graphs.normalize_latent_structure() is now implemented in Rust for DAGs for faster latent normalization workflows.minimal_d_separator() is renamed to minimal_separator() and now supports
ADMG and AG inputs (previously DAG-only), returning a minimal m-separator.
Implemented via the unified linear-time algorithm of van der Zander &
Liśkiewicz (UAI 2020). The old name minimal_d_separator() remains as a
deprecated alias.m_separated() on ADMGs: moralization now marries every pair in
pa(v) ∪ sp(v), not just pa(v). The old code missed moral edges from
bidirected co-parents and gave false positives (e.g. claimed Z ⊥ Y | X for
Z -> X -> Y, X <-> Y).is_valid_adjustment_admg() and all_adjustment_sets_admg() to verify
the GAC's m-separation condition in the proper backdoor graph rather than
via a per-neighbour decomposition. The old check trivially accepted neighbours
of X that were themselves in Z, so it falsely classified {C} as a valid
adjustment set in the M-bias ADMG C -> X, C <-> X, C -> Y, C <-> Y, X -> Y
(#277).normalize_latent_structure(), which normalizes the latent structure of a
DAG while preserving the marginal model over observed variables.minimal_d_separator(), which computes a minimal d-separator between
sets of nodes in a DAG, with support for mandatory inclusions and restrictions.posteriors() query function, which is the dual of anteriors(). It
returns all nodes reachable by following paths where every edge is either
undirected or directed away from the source node. For DAGs, posteriors()
equals descendants(). For PDAGs and AGs, it includes both descendants and
nodes reachable via undirected edges.ancestors(), anteriors(), descendants(), and posteriors().
This can be set globally with caugi_options() or locally with the
open = TRUE/FALSE argument. The default remains open = TRUE.is_mpdag() query to check whether a PDAG is closed under Meek's
orientation rules (R1-R4), and meek_closure() to orient all implied edges
until Meek closure.caugi_options() now supports nested key drilling: multiple unnamed arguments
traverse nested options (e.g., caugi_options("plot", "tier_style", "fill")).simple, graph_class, nodes, edges) are sourced from the session.
@.state, @name_index_map, @built,
and @ptr now warn on access and return NULL.build and state in
caugi() now warn and are ignored.inplace parameter in verb functions (add_edges(), remove_edges(),
set_edges(), add_nodes(), remove_nodes()). All graph modifications now use
copy-on-write semantics for consistency with R conventions. The parameter is
deprecated and ignored with a warning.all.equal and compare_proxy methods for caugi objects to support
graph-content comparison in tests.asp parameter to plot() for controlling the aspect ratio. When asp = 1,
the plot respects equal units on both axes, preserving the layout
coordinates. Works like base R's asp parameter (y/x aspect ratio) (#195).pdag_to_dag() function that generates a random DAG consistent with a
given CPDAG/PDAG structure if possible (#201).plot() to use incorrect layout if node names were not
in the same order as in the graph object (#198).set_edges() so that it correctly replaces symmetric edges in
simple graphs.all in districts() has been deprecated. Use districts()
without arguments to get all districts.-->),
bidirected (<->), and undirected (---) edges while satisfying ancestral
graph constraints. New functions: is_ag(), is_mag().mode argument to neighbors()/neighbours() to filter neighbors by edge
direction or type ("all", "in", "out", "undirected", "bidirected",
"partial"). This is a structural query, and not a semantic query!neighbors() now supports class = "UNKNOWN" graphs, including mode-based
filtering.simulate_data() that enables simulation from DAGs using SEMs. Standard
linear Gaussian SEMs are defaults, but more importantly custom SEMs are
available."AUTO" parameter for class in caugi objects. This automatically
picks the graph class in order DAG, UG, PDAG, ADMG, AG.is_ag() and is_mag() and m-separation
for AGs.exogenize() function that exogenizes variables for any graph type.
Current implementation is written in R, but it is so simple that it might be
preferable over a Rust implementation. This might be changed later.latent_project() function that does latent projection from DAGs to
ADMGs.write_caugi(), read_caugi(), caugi_serialize(), and
caugi_deserialize(). The format is a versioned JSON schema that captures
graph structure, class, and optional metadata (comments and tags).plot() method for visualizing graphs using various layout algorithms.
The plot is rendered using grid graphics and returns a caugi_plot object
that can be customized with node_style, edge_style, and label_style
arguments. The plot() method accepts layouts as strings, functions, or
pre-computed data.frames.caugi_layout() function to compute node coordinates for graph
visualization.caugi_layout_sugiyama(),
caugi_layout_fruchterman_reingold(), caugi_layout_kamada_kawai(),
caugi_layout_bipartite(), and caugi_layout_tiered(). Each function
provides an API for its specific algorithm.to_dot() and write_dot() functions for exporting caugi graphs to DOT
(graphviz) format. The resulting object is a new S7 class, caugi_export,
which has a knit_print() method for rendering DOT graphs in R Markdown and
Quarto documents.to_graphml, write_graphml,
read_graphml, to_mermaid, write_mermaid, and read_mermaid+ and |
for horizontal arrangement, / for vertical stacking. Compositions can be
nested arbitrarily (e.g., (p1 + p2) / p3).caugi_options() function for setting global defaults for plot
appearance, including composition spacing and default styles for nodes,
edges, labels, and titles.caugi_default_options() function to query or reset to package default options.is_caugi() validation calls internally.caugi_layout_tiered() now returns a tier column and orientation attribute in the layout data.frame, allowing plot() to automatically use tier information without requiring the tiers argument to be passed again.index_name_map parameter from internal .cg_state() function.is_cpdag function that returns TRUE on non-complete PDAGs.shd returning positive values for equivalent graphs given in shuffled order.is_admg(), spouses(), districts(),
and m_separated() (generalization of d-separation for graphs with bidirected
edges).is_valid_adjustment_admg() and all_adjustment_sets_admg() implementing
the Generalized Adjustment Criterion.mutate_caugi() function that allows conversion from one graph type to
another.caugi objects.edges_df argument to caugi() for easier construction from
existing data frames containing the columns from, edge, and to.as_adjacency() and as_igraph() to support bidirected edges.as_caugi() documentation to include "ADMG" as a valid class type for
conversion.caugi.org/.CONTRIBUTING.md.README rewrite.lockBinding and unlockBinding in the package to
silence R CMD check notes.mutate_caugi function that allows conversion from one graph type to another.edges_df argument to caugi for easier construction from existing data frames containing the columns from, edge, and to.caugi in a package vignette to use new conversion functionality.CONTRIBUTING.md to github.as_caugi.dplyr and tibble.data.table.data.tables.caugi.