hugr_persistent/
lib.rs

1#![doc(hidden)] // TODO: remove when stable
2
3//! Persistent data structure for HUGR mutations.
4//!
5//! This crate provides a persistent data structure [`PersistentHugr`] that
6//! implements [`HugrView`](hugr_core::HugrView); mutations to the data are
7//! stored persistently as a set of [`Commit`]s along with the dependencies
8//! between the commits.
9//!
10//! As a result of persistency, the entire mutation history of a HUGR can be
11//! traversed and references to previous versions of the data remain valid even
12//! as the HUGR graph is "mutated" by applying patches: the patches are in
13//! effect added to the history as new commits.
14//!
15//! The data structure underlying [`PersistentHugr`], which stores the history
16//! of all commits, is [`CommitStateSpace`]. Multiple [`PersistentHugr`] can be
17//! stored within a single [`CommitStateSpace`], which allows for the efficient
18//! exploration of the space of all possible graph rewrites.
19//!
20//! ## Overlapping commits
21//!
22//! In general, [`CommitStateSpace`] may contain overlapping commits. Such
23//! mutations are mutually exclusive as they modify the same nodes. It is
24//! therefore not possible to apply all commits in a [`CommitStateSpace`]
25//! simultaneously. A [`PersistentHugr`] on the other hand always corresponds to
26//! a subgraph of a [`CommitStateSpace`] that is guaranteed to contain only
27//! non-overlapping, compatible commits. By applying all commits in a
28//! [`PersistentHugr`], we can materialize a [`Hugr`](hugr_core::Hugr).
29//! Traversing the materialized HUGR is equivalent to using the
30//! [`HugrView`](hugr_core::HugrView) implementation of the corresponding
31//! [`PersistentHugr`].
32//!
33//! ## Summary of data types
34//!
35//! - [`Commit`] A modification to a [`Hugr`](hugr_core::Hugr) (currently a
36//!   [`SimpleReplacement`](hugr_core::SimpleReplacement)) that forms the atomic
37//!   unit of change for a [`PersistentHugr`] (like a commit in git). This is a
38//!   reference-counted value that is cheap to clone and will be freed when the
39//!   last reference is dropped.
40//! - [`PersistentHugr`] A data structure that implements
41//!   [`HugrView`][hugr_core::HugrView] and can be used as a drop-in replacement
42//!   for a [`Hugr`][hugr_core::Hugr] for read-only access and mutations through
43//!   the [`PatchVerification`](hugr_core::hugr::patch::PatchVerification) and
44//!   [`Patch`](hugr_core::hugr::Patch) traits. Mutations are stored as a
45//!   history of commits. Unlike [`CommitStateSpace`], it maintains the
46//!   invariant that all contained commits are compatible with eachother.
47//! - [`CommitStateSpace`] Stores commits, recording the dependencies between
48//!   them. Includes the base HUGR and any number of possibly incompatible
49//!   (overlapping) commits. Unlike a [`PersistentHugr`], a state space can
50//!   contain mutually exclusive commits.
51//!
52//! ## Usage
53//!
54//! A [`PersistentHugr`] can be created from a base HUGR using
55//! [`PersistentHugr::with_base`]. Replacements can then be applied to it
56//! using [`PersistentHugr::add_replacement`]. Alternatively, if you already
57//! have a populated state space, use [`PersistentHugr::try_new`] to create a
58//! new HUGR with those commits.
59//!
60//! Add a sequence of commits to a state space by merging a [`PersistentHugr`]
61//! into it using [`CommitStateSpace::extend`] or directly using
62//! [`CommitStateSpace::try_add_commit`].
63//!
64//! To obtain a [`PersistentHugr`] from your state space, use
65//! [`CommitStateSpace::try_extract_hugr`]. A [`PersistentHugr`] can always be
66//! materialized into a [`Hugr`][hugr_core::Hugr] type using
67//! [`PersistentHugr::to_hugr`].
68
69mod parents_view;
70mod persistent_hugr;
71mod resolver;
72pub mod state_space;
73pub mod subgraph;
74mod trait_impls;
75pub mod walker;
76mod wire;
77
78pub use persistent_hugr::{Commit, PersistentHugr};
79pub use resolver::{PointerEqResolver, Resolver, SerdeHashResolver};
80pub use state_space::{CommitId, CommitStateSpace, InvalidCommit, PatchNode};
81pub use subgraph::PinnedSubgraph;
82pub use walker::Walker;
83pub use wire::PersistentWire;
84
85/// A replacement operation that can be applied to a [`PersistentHugr`].
86pub type PersistentReplacement = hugr_core::SimpleReplacement<PatchNode>;
87
88use persistent_hugr::find_conflicting_node;
89use state_space::CommitData;
90
91pub mod serial {
92    //! Serialized formats for commits, state spaces and persistent HUGRs.
93    pub use super::persistent_hugr::serial::*;
94    pub use super::state_space::serial::*;
95}
96
97#[cfg(test)]
98mod tests;