Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow non-references in the wrappers #105

Merged
merged 6 commits into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 29 additions & 21 deletions src/view/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,22 @@ pub type LinkFilter<Ctx> = fn(PortIndex, &Ctx) -> bool;
/// For the special case of filtering out nodes only, the type alias
/// [`NodeFiltered`] is provided, along with [`NodeFiltered::new_node_filtered`].
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct FilteredGraph<'a, G, FN, FP, Context = ()> {
graph: &'a G,
pub struct FilteredGraph<G, FN, FP, Context = ()> {
graph: G,
node_filter: FN,
link_filter: FP,
context: Context,
}

/// A wrapper around a portgraph that filters out nodes.
pub type NodeFiltered<'a, G, FN, Context = ()> =
FilteredGraph<'a, G, FN, LinkFilter<Context>, Context>;
pub type NodeFiltered<G, FN, Context = ()> = FilteredGraph<G, FN, LinkFilter<Context>, Context>;

impl<'a, G, FN, FP, Ctx> FilteredGraph<'a, G, FN, FP, Ctx> {
impl<G, FN, FP, Ctx> FilteredGraph<G, FN, FP, Ctx>
where
G: Clone,
{
/// Create a new node filtered portgraph.
pub fn new(graph: &'a G, node_filter: FN, link_filter: FP, context: Ctx) -> Self {
pub fn new(graph: G, node_filter: FN, link_filter: FP, context: Ctx) -> Self {
Self {
graph,
node_filter,
Expand All @@ -52,20 +54,26 @@ impl<'a, G, FN, FP, Ctx> FilteredGraph<'a, G, FN, FP, Ctx> {
&self.context
}

pub(super) fn graph(&self) -> &'a G {
self.graph
pub(super) fn graph(&self) -> G {
self.graph.clone()
}
}

impl<'a, G, F, Ctx> NodeFiltered<'a, G, F, Ctx> {
impl<G, F, Ctx> NodeFiltered<G, F, Ctx>
where
G: Clone,
{
/// Create a new node filtered portgraph.
pub fn new_node_filtered(graph: &'a G, node_filter: F, context: Ctx) -> Self {
pub fn new_node_filtered(graph: G, node_filter: F, context: Ctx) -> Self {
Self::new(graph, node_filter, |_, _| true, context)
}
}

/// Filter functions used on the items of the [`FilteredGraph`] iterators.
impl<G, Ctx> FilteredGraph<'_, G, NodeFilter<Ctx>, LinkFilter<Ctx>, Ctx> {
impl<G, Ctx> FilteredGraph<G, NodeFilter<Ctx>, LinkFilter<Ctx>, Ctx>
where
G: Clone,
{
/// Node filter used for the iterators
fn node_filter(node: &NodeIndex, ctx: &FilteredGraphCtx<G, Ctx>) -> bool
where
Expand Down Expand Up @@ -103,12 +111,12 @@ impl<G, Ctx> FilteredGraph<'_, G, NodeFilter<Ctx>, LinkFilter<Ctx>, Ctx> {
}

/// The full context used for the iterators
fn as_context(&self) -> FilteredGraphCtx<G, Ctx>
fn as_context(&self) -> FilteredGraphCtx<'_, G, Ctx>
where
G: PortView,
{
FilteredGraphCtx::new(
self.graph,
self.graph.clone(),
self.node_filter,
self.link_filter,
&self.context,
Expand All @@ -121,7 +129,7 @@ impl<G, Ctx> FilteredGraph<'_, G, NodeFilter<Ctx>, LinkFilter<Ctx>, Ctx> {
/// This is a named struct to make the iterator signatures more readable.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct FilteredGraphCtx<'a, G, Ctx> {
pub(self) graph: &'a G,
pub(self) graph: G,
pub(self) node_filter: NodeFilter<Ctx>,
pub(self) link_filter: LinkFilter<Ctx>,
pub(self) context: &'a Ctx,
Expand All @@ -130,7 +138,7 @@ pub struct FilteredGraphCtx<'a, G, Ctx> {
impl<'a, G, Ctx> FilteredGraphCtx<'a, G, Ctx> {
/// Create a new context.
pub(self) fn new(
graph: &'a G,
graph: G,
node_filter: NodeFilter<Ctx>,
link_filter: LinkFilter<Ctx>,
context: &'a Ctx,
Expand All @@ -149,9 +157,9 @@ pub type FilteredGraphIter<'a, G, Ctx, I> = FilterWithCtx<I, FilteredGraphCtx<'a
/// Filtered + mapped iterator wrapper used by [`FilteredGraph`].
pub type MapFilteredGraphIter<'a, G, Ctx, I, O> = MapWithCtx<I, FilteredGraphCtx<'a, G, Ctx>, O>;

impl<G, Ctx> PortView for FilteredGraph<'_, G, NodeFilter<Ctx>, LinkFilter<Ctx>, Ctx>
impl<G, Ctx> PortView for FilteredGraph<G, NodeFilter<Ctx>, LinkFilter<Ctx>, Ctx>
where
G: PortView,
G: PortView + Clone,
{
type Nodes<'a> = FilteredGraphIter<'a, G, Ctx, <G as PortView>::Nodes<'a>>
where
Expand Down Expand Up @@ -235,9 +243,9 @@ where
}
}

impl<G, Ctx> LinkView for FilteredGraph<'_, G, NodeFilter<Ctx>, LinkFilter<Ctx>, Ctx>
impl<G, Ctx> LinkView for FilteredGraph<G, NodeFilter<Ctx>, LinkFilter<Ctx>, Ctx>
where
G: LinkView,
G: LinkView + Clone,
{
type LinkEndpoint = G::LinkEndpoint;

Expand Down Expand Up @@ -304,9 +312,9 @@ where
}
}

impl<G, Ctx> MultiView for FilteredGraph<'_, G, NodeFilter<Ctx>, LinkFilter<Ctx>, Ctx>
impl<G, Ctx> MultiView for FilteredGraph<G, NodeFilter<Ctx>, LinkFilter<Ctx>, Ctx>
where
G: MultiView,
G: MultiView + Clone,
{
type NodeSubports<'a> = FilteredGraphIter<'a, G, Ctx, <G as MultiView>::NodeSubports<'a>>
where
Expand Down
8 changes: 4 additions & 4 deletions src/view/petgraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,17 +258,17 @@ macro_rules! impl_visit_sparse {

impl_petgraph_traits!(PortGraph);
impl_petgraph_traits!(MultiPortGraph);
impl_petgraph_traits!(NodeFiltered<'a, G, NodeFilter<Ctx>, Ctx>, ['a, G, Ctx]
impl_petgraph_traits!(NodeFiltered<G, NodeFilter<Ctx>, Ctx>, ['a, G, Ctx]
where
G: LinkView,
G: LinkView + Clone,
<G as LinkView>::LinkEndpoint: Eq
);

impl_visit_dense!(PortGraph);
impl_visit_dense!(MultiPortGraph);
impl_visit_sparse!(NodeFiltered<'a, G, NodeFilter<Ctx>, Ctx>, ['a, G, Ctx]
impl_visit_sparse!(NodeFiltered<G, NodeFilter<Ctx>, Ctx>, ['a, G, Ctx]
where
G: LinkView,
G: LinkView + Clone,
<G as LinkView>::LinkEndpoint: Eq
);

Expand Down
18 changes: 12 additions & 6 deletions src/view/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@ type RegionCallback<'g> = fn(NodeIndex, &RegionContext<'g>) -> bool;
///
/// [`Region`] does not implement `Sync` as it uses a [`RefCell`] to cache the
/// node filtering.
pub type Region<'g, G> = NodeFiltered<'g, G, RegionCallback<'g>, RegionContext<'g>>;
pub type Region<'g, G> = NodeFiltered<G, RegionCallback<'g>, RegionContext<'g>>;

impl<'a, G> Region<'a, G> {
impl<'a, G> Region<'a, G>
where
G: Clone,
{
/// Create a new region view including all the descendants of the root node.
pub fn new_region(graph: &'a G, hierarchy: &'a Hierarchy, root: NodeIndex) -> Self {
pub fn new_region(graph: G, hierarchy: &'a Hierarchy, root: NodeIndex) -> Self {
let region_filter: RegionCallback<'a> =
|node, context| node == context.root() || context.is_descendant(node);
Self::new_node_filtered(graph, region_filter, RegionContext::new(hierarchy, root))
Expand Down Expand Up @@ -92,11 +95,14 @@ type FlatRegionCallback<'g> = fn(NodeIndex, &FlatRegionContext<'g>) -> bool;
/// View of a portgraph containing only a root node and its direct children in a [`Hierarchy`].
///
/// For a view of all descendants, see [`Region`].
pub type FlatRegion<'g, G> = NodeFiltered<'g, G, FlatRegionCallback<'g>, FlatRegionContext<'g>>;
pub type FlatRegion<'g, G> = NodeFiltered<G, FlatRegionCallback<'g>, FlatRegionContext<'g>>;

impl<'a, G> FlatRegion<'a, G> {
impl<'a, G> FlatRegion<'a, G>
where
G: Clone,
{
/// Create a new region view including all the descendants of the root node.
pub fn new_flat_region(graph: &'a G, hierarchy: &'a Hierarchy, root: NodeIndex) -> Self {
pub fn new_flat_region(graph: G, hierarchy: &'a Hierarchy, root: NodeIndex) -> Self {
let region_filter: FlatRegionCallback<'a> = |node, context| {
let (hierarchy, root) = context;
node == *root || hierarchy.parent(node) == Some(*root)
Expand Down
15 changes: 9 additions & 6 deletions src/view/subgraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ type PortCallback = fn(PortIndex, &SubgraphContext) -> bool;
///
/// At initialisation, this performs a one-off expensive computation (linear in
/// the size of the subgraph) to determine the nodes that are in the subgraph.
pub type Subgraph<'g, G> = FilteredGraph<'g, G, NodeCallback, PortCallback, SubgraphContext>;
pub type Subgraph<G> = FilteredGraph<G, NodeCallback, PortCallback, SubgraphContext>;

/// Internal context used in the [`Subgraph`] adaptor.
#[derive(Debug, Clone)]
Expand All @@ -54,7 +54,10 @@ pub struct SubgraphContext {
outputs: Vec<PortIndex>,
}

impl<'a, G: LinkView> Subgraph<'a, G> {
impl<G: LinkView> Subgraph<G>
where
G: Clone,
{
/// Create a new subgraph view of `graph`.
///
/// ### Arguments
Expand All @@ -64,7 +67,7 @@ impl<'a, G: LinkView> Subgraph<'a, G> {
/// and outgoing ports are outgoing boundary edges.
///
/// This initialisation is linear in the size of the subgraph.
pub fn new_subgraph(graph: &'a G, boundary: impl IntoIterator<Item = PortIndex>) -> Self {
pub fn new_subgraph(graph: G, boundary: impl IntoIterator<Item = PortIndex>) -> Self {
let mut inputs = Vec::new();
let mut outputs = Vec::new();

Expand All @@ -76,7 +79,7 @@ impl<'a, G: LinkView> Subgraph<'a, G> {
p
});

let (nodes, ports) = traverse_subgraph(graph, boundary);
let (nodes, ports) = traverse_subgraph(graph.clone(), boundary);
let context = SubgraphContext {
nodes: nodes.into_iter().collect(),
ports: ports.into_iter().collect(),
Expand All @@ -98,7 +101,7 @@ impl<'a, G: LinkView> Subgraph<'a, G> {
}

/// Whether the subgraph is convex, using a pre-existing checker.
pub fn is_convex_with_checker(&self, checker: &mut ConvexChecker<&G>) -> bool {
pub fn is_convex_with_checker(&self, checker: &mut ConvexChecker<G>) -> bool {
checker.is_convex(
self.nodes_iter(),
self.context().inputs.iter().copied(),
Expand All @@ -112,7 +115,7 @@ impl<'a, G: LinkView> Subgraph<'a, G> {
/// Start just inside the boundaries and follow each edge that is not itself
/// a boundary.
fn traverse_subgraph<G: LinkView>(
graph: &G,
graph: G,
boundary: impl IntoIterator<Item = PortIndex>,
) -> (BTreeSet<NodeIndex>, BTreeSet<PortIndex>) {
// Nodes within subgraph
Expand Down