metacat 0.2.1

metacat: a categorical theorem prover
Documentation
use hexpr::{Operation, Signature};
use open_hypergraphs::lax::{Hyperedge, Hypergraph, OpenHypergraph};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Dual<A> {
    Fwd(A),
    Rev(A),
}

impl<A> Dual<A> {
    fn dual(self) -> Self {
        match self {
            Self::Fwd(a) => Self::Rev(a),
            Self::Rev(a) => Self::Fwd(a),
        }
    }
}

pub fn into_fwd<O, A>(f: OpenHypergraph<O, A>) -> OpenHypergraph<O, Dual<A>> {
    f.map_edges(Dual::Fwd)
}

pub fn into_rev<O, A: Clone>(f: OpenHypergraph<O, A>) -> OpenHypergraph<O, Dual<A>> {
    dual(f.map_edges(Dual::Fwd))
}

pub fn dual<O, A: Clone>(f: OpenHypergraph<O, Dual<A>>) -> OpenHypergraph<O, Dual<A>> {
    let OpenHypergraph {
        sources,
        targets,
        hypergraph:
            Hypergraph {
                nodes,
                edges,
                adjacency,
                quotient,
            },
    } = f;

    let adj = adjacency
        .into_iter()
        .map(|Hyperedge { sources, targets }| Hyperedge {
            sources: targets,
            targets: sources,
        })
        .collect();

    OpenHypergraph {
        sources: targets,
        targets: sources,
        hypergraph: Hypergraph {
            nodes,
            edges: edges.into_iter().map(|e| e.dual()).collect(),
            adjacency: adj,
            quotient,
        },
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct DualSig<S>(S);

impl<S: Signature> Signature for DualSig<S> {
    type Arr = Dual<S::Arr>;
    type Obj = S::Obj;
    type Error = S::Error;

    fn try_parse_op(&self, op: &Operation) -> Result<Self::Arr, Self::Error> {
        Ok(Dual::Fwd(self.0.try_parse_op(op)?))
    }

    fn profile(&self, op: &Self::Arr) -> (Vec<Option<Self::Obj>>, Vec<Option<Self::Obj>>) {
        match op {
            Dual::Fwd(op) => self.0.profile(op),
            Dual::Rev(op) => {
                let (s, t) = self.0.profile(op);
                (t, s)
            }
        }
    }
}

impl<T: std::fmt::Display> std::fmt::Display for Dual<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Dual::Fwd(x) => write!(f, "fwd({x})"),
            Dual::Rev(x) => write!(f, "rev({x})"),
        }
    }
}