open_hypergraphs/lax/var/
var.rs

1use crate::lax::hypergraph::*;
2use crate::lax::open_hypergraph::*;
3
4use std::cell::RefCell;
5use std::rc::Rc;
6
7// Given a set of operation labels (i.e., edge labels),
8// distinguish one as the type of "Vars".
9// A `Var` will typically be a `1 → N` map representing copying.
10// However, it can more generally be any `M → N` operation.
11pub trait HasVar {
12    /// get the label for the "Var" operation
13    fn var() -> Self;
14}
15
16#[derive(Clone, Debug)]
17pub struct Var<O, A> {
18    pub state: Rc<RefCell<OpenHypergraph<O, A>>>,
19    pub edge_id: EdgeId,
20    pub label: O,
21}
22
23/// Vars can be created when the set of edge labels has a 'Copy' operation.
24impl<O: Clone, A: HasVar> Var<O, A> {
25    pub fn new(state: Rc<RefCell<OpenHypergraph<O, A>>>, default_node_label: O) -> Self {
26        let (edge_id, _) = state.borrow_mut().new_operation(A::var(), vec![], vec![]);
27        Var {
28            state,
29            edge_id,
30            label: default_node_label,
31        }
32    }
33
34    /// Create a new source node of this Var
35    pub fn new_source(&self) -> NodeId {
36        self.state
37            .borrow_mut()
38            .add_edge_source(self.edge_id, self.label.clone())
39    }
40
41    /// Create a new target node of this Var
42    pub fn new_target(&self) -> NodeId {
43        self.state
44            .borrow_mut()
45            .add_edge_target(self.edge_id, self.label.clone())
46    }
47}
48
49pub type BuildResult<O, A> = Result<OpenHypergraph<O, A>, Rc<RefCell<OpenHypergraph<O, A>>>>;
50
51/// Construct an [`OpenHypergraph`] from a function taking an empty OpenHypergraph,
52/// and returning two lists of [`Var`]s corresponding to *sources* and *targets*.
53pub fn build<F, O: Clone, A: HasVar>(f: F) -> BuildResult<O, A>
54where
55    F: Fn(&Rc<RefCell<OpenHypergraph<O, A>>>) -> (Vec<Var<O, A>>, Vec<Var<O, A>>),
56{
57    let state = Rc::new(RefCell::new(OpenHypergraph::<O, A>::empty()));
58    {
59        let (s, t) = f(&state);
60        state.borrow_mut().sources = s.iter().map(|x| x.new_source()).collect();
61        state.borrow_mut().targets = t.iter().map(|x| x.new_target()).collect();
62    }
63    Rc::try_unwrap(state).map(|f| f.into_inner())
64}