From 57d7543d66dba9b1e708876c226701cffb8b1e56 Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Wed, 6 Sep 2023 14:34:39 +0100 Subject: [PATCH 1/8] Implement petgraph traits on Hugr --- src/hugr/views.rs | 1 + src/hugr/views/hierarchy.rs | 15 +-- src/hugr/views/{hierarchy => }/petgraph.rs | 138 ++++++++++++++++++++- 3 files changed, 141 insertions(+), 13 deletions(-) rename src/hugr/views/{hierarchy => }/petgraph.rs (65%) diff --git a/src/hugr/views.rs b/src/hugr/views.rs index 0db5d39d0..6495390f5 100644 --- a/src/hugr/views.rs +++ b/src/hugr/views.rs @@ -1,6 +1,7 @@ //! Read-only access into HUGR graphs and subgraphs. pub mod hierarchy; +pub mod petgraph; pub mod sibling; #[cfg(test)] diff --git a/src/hugr/views/hierarchy.rs b/src/hugr/views/hierarchy.rs index 76d67ecff..e5f1bded7 100644 --- a/src/hugr/views/hierarchy.rs +++ b/src/hugr/views/hierarchy.rs @@ -14,8 +14,6 @@ //! interchangeably. They implement [`HugrView`] as well as petgraph's _visit_ //! traits. -pub mod petgraph; - use std::iter; use ::petgraph::visit as pv; @@ -27,6 +25,8 @@ use crate::ops::handle::NodeHandle; use crate::ops::OpTrait; use crate::{hugr::NodeType, hugr::OpType, Direction, Hugr, Node, Port}; +use super::petgraph::PetgraphHugr; + use super::{sealed::HugrInternals, HugrView, NodeMetadata}; type FlatRegionGraph<'g> = portgraph::view::FlatRegion<'g, &'g MultiPortGraph>; @@ -406,16 +406,7 @@ where } /// A common trait for views of a HUGR hierarchical subgraph. -pub trait HierarchyView<'a>: - HugrView - + pv::GraphBase - + pv::GraphProp - + pv::NodeCount - + pv::NodeIndexable - + pv::EdgeCount - + pv::Visitable - + pv::GetAdjacencyMatrix - + pv::Visitable +pub trait HierarchyView<'a>: HugrView + PetgraphHugr where for<'g> &'g Self: pv::IntoNeighborsDirected + pv::IntoNodeIdentifiers, { diff --git a/src/hugr/views/hierarchy/petgraph.rs b/src/hugr/views/petgraph.rs similarity index 65% rename from src/hugr/views/hierarchy/petgraph.rs rename to src/hugr/views/petgraph.rs index 29de1506f..0e24b96e7 100644 --- a/src/hugr/views/hierarchy/petgraph.rs +++ b/src/hugr/views/petgraph.rs @@ -6,12 +6,141 @@ use crate::hugr::HugrView; use crate::ops::handle::NodeHandle; use crate::ops::OpType; use crate::types::EdgeKind; -use crate::{Node, Port}; +use crate::{Hugr, Node, Port}; use context_iterators::{ContextIterator, IntoContextIterator, MapWithCtx}; use petgraph::visit as pv; use portgraph::NodeIndex; +/// A trait grouping the multiple petgraph traits implemented on Hugrs +// +// TODO: We could just require these in `HugrView`. +pub trait PetgraphHugr: + HugrView + + pv::GraphBase + + pv::GraphProp + + pv::NodeCount + + pv::NodeIndexable + + pv::EdgeCount + + pv::Visitable + + pv::GetAdjacencyMatrix + + pv::Visitable +where + for<'g> &'g Self: pv::IntoNeighborsDirected + pv::IntoNodeIdentifiers, +{ +} + +impl pv::GraphBase for Hugr { + type NodeId = Node; + type EdgeId = ((Node, Port), (Node, Port)); +} + +impl pv::GraphProp for Hugr { + type EdgeType = petgraph::Directed; +} + +impl pv::NodeCount for Hugr { + fn node_count(&self) -> usize { + HugrView::node_count(self) + } +} + +impl pv::NodeIndexable for Hugr { + fn node_bound(&self) -> usize { + HugrView::node_count(self) + } + + fn to_index(&self, ix: Self::NodeId) -> usize { + ix.index.into() + } + + fn from_index(&self, ix: usize) -> Self::NodeId { + NodeIndex::new(ix).into() + } +} + +impl pv::EdgeCount for Hugr { + fn edge_count(&self) -> usize { + HugrView::edge_count(self) + } +} + +impl pv::Data for Hugr { + type NodeWeight = OpType; + type EdgeWeight = EdgeKind; +} + +impl<'g> pv::IntoNodeIdentifiers for &'g Hugr { + type NodeIdentifiers = ::Nodes<'g>; + + fn node_identifiers(self) -> Self::NodeIdentifiers { + self.nodes() + } +} + +impl<'g> pv::IntoNodeReferences for &'g Hugr { + type NodeRef = HugrNodeRef<'g>; + type NodeReferences = MapWithCtx<::Nodes<'g>, Self, HugrNodeRef<'g>>; + + fn node_references(self) -> Self::NodeReferences { + self.nodes() + .with_context(self) + .map_with_context(|n, &hugr| HugrNodeRef::from_node(n, hugr)) + } +} + +impl<'g> pv::IntoNeighbors for &'g Hugr { + type Neighbors = ::Neighbours<'g>; + + fn neighbors(self, n: Self::NodeId) -> Self::Neighbors { + self.output_neighbours(n) + } +} + +impl<'g> pv::IntoNeighborsDirected for &'g Hugr { + type NeighborsDirected = ::Neighbours<'g>; + + fn neighbors_directed( + self, + n: Self::NodeId, + d: petgraph::Direction, + ) -> Self::NeighborsDirected { + self.neighbours(n, d.into()) + } +} + +impl pv::Visitable for Hugr { + type Map = std::collections::HashSet; + + fn visit_map(&self) -> Self::Map { + std::collections::HashSet::new() + } + + fn reset_map(&self, map: &mut Self::Map) { + map.clear(); + } +} + +impl pv::GetAdjacencyMatrix for Hugr { + type AdjMatrix = std::collections::HashSet<(Self::NodeId, Self::NodeId)>; + + fn adjacency_matrix(&self) -> Self::AdjMatrix { + let mut matrix = std::collections::HashSet::new(); + for node in self.nodes() { + for neighbour in self.output_neighbours(node) { + matrix.insert((node, neighbour)); + } + } + matrix + } + + fn is_adjacent(&self, matrix: &Self::AdjMatrix, a: Self::NodeId, b: Self::NodeId) -> bool { + matrix.contains(&(a, b)) + } +} + +impl PetgraphHugr for Hugr {} + macro_rules! impl_region_petgraph_traits { ($hugr:ident) => { impl<'a, Root, Base> pv::GraphBase for $hugr<'a, Root, Base> @@ -177,6 +306,13 @@ macro_rules! impl_region_petgraph_traits { matrix.contains(&(a, b)) } } + + impl<'a, Root, Base> PetgraphHugr for $hugr<'a, Root, Base> + where + Root: NodeHandle, + Base: HugrInternals + HugrView, + { + } }; } From 88cafb21cfa1b8ec18e0fa37a801cc3507bf3d53 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Thu, 7 Sep 2023 11:07:34 +0100 Subject: [PATCH 2/8] feat: properly parametrize macro (#501) I couldn't work out how to do the lifetimes in IntoNodeReferences so had to pull that out. But, well, I think the objections here are pretty obvious... The line count is pretty good though!! --- src/hugr/views/petgraph.rs | 207 ++++++++----------------------------- 1 file changed, 41 insertions(+), 166 deletions(-) diff --git a/src/hugr/views/petgraph.rs b/src/hugr/views/petgraph.rs index 0e24b96e7..c9ff22a3c 100644 --- a/src/hugr/views/petgraph.rs +++ b/src/hugr/views/petgraph.rs @@ -30,54 +30,6 @@ where { } -impl pv::GraphBase for Hugr { - type NodeId = Node; - type EdgeId = ((Node, Port), (Node, Port)); -} - -impl pv::GraphProp for Hugr { - type EdgeType = petgraph::Directed; -} - -impl pv::NodeCount for Hugr { - fn node_count(&self) -> usize { - HugrView::node_count(self) - } -} - -impl pv::NodeIndexable for Hugr { - fn node_bound(&self) -> usize { - HugrView::node_count(self) - } - - fn to_index(&self, ix: Self::NodeId) -> usize { - ix.index.into() - } - - fn from_index(&self, ix: usize) -> Self::NodeId { - NodeIndex::new(ix).into() - } -} - -impl pv::EdgeCount for Hugr { - fn edge_count(&self) -> usize { - HugrView::edge_count(self) - } -} - -impl pv::Data for Hugr { - type NodeWeight = OpType; - type EdgeWeight = EdgeKind; -} - -impl<'g> pv::IntoNodeIdentifiers for &'g Hugr { - type NodeIdentifiers = ::Nodes<'g>; - - fn node_identifiers(self) -> Self::NodeIdentifiers { - self.nodes() - } -} - impl<'g> pv::IntoNodeReferences for &'g Hugr { type NodeRef = HugrNodeRef<'g>; type NodeReferences = MapWithCtx<::Nodes<'g>, Self, HugrNodeRef<'g>>; @@ -89,91 +41,48 @@ impl<'g> pv::IntoNodeReferences for &'g Hugr { } } -impl<'g> pv::IntoNeighbors for &'g Hugr { - type Neighbors = ::Neighbours<'g>; - - fn neighbors(self, n: Self::NodeId) -> Self::Neighbors { - self.output_neighbours(n) - } -} - -impl<'g> pv::IntoNeighborsDirected for &'g Hugr { - type NeighborsDirected = ::Neighbours<'g>; - - fn neighbors_directed( - self, - n: Self::NodeId, - d: petgraph::Direction, - ) -> Self::NeighborsDirected { - self.neighbours(n, d.into()) - } -} - -impl pv::Visitable for Hugr { - type Map = std::collections::HashSet; - - fn visit_map(&self) -> Self::Map { - std::collections::HashSet::new() - } - - fn reset_map(&self, map: &mut Self::Map) { - map.clear(); - } -} - -impl pv::GetAdjacencyMatrix for Hugr { - type AdjMatrix = std::collections::HashSet<(Self::NodeId, Self::NodeId)>; +macro_rules! impl_petgraph_into_noderefs { + ($hugr:ident) => { + impl<'g, 'a, Root, Base> pv::IntoNodeReferences for &'g $hugr<'a, Root, Base> + where + Root: NodeHandle, + 'g: 'a, + Base: HugrInternals + HugrView, + { + type NodeRef = HugrNodeRef<'a>; + type NodeReferences = + MapWithCtx<<$hugr<'a, Root, Base> as HugrView>::Nodes<'a>, Self, HugrNodeRef<'a>>; - fn adjacency_matrix(&self) -> Self::AdjMatrix { - let mut matrix = std::collections::HashSet::new(); - for node in self.nodes() { - for neighbour in self.output_neighbours(node) { - matrix.insert((node, neighbour)); + fn node_references(self) -> Self::NodeReferences { + self.nodes() + .with_context(self) + .map_with_context(|n, &hugr| HugrNodeRef::from_node(n, hugr)) } } - matrix - } - - fn is_adjacent(&self, matrix: &Self::AdjMatrix, a: Self::NodeId, b: Self::NodeId) -> bool { - matrix.contains(&(a, b)) - } + }; } -impl PetgraphHugr for Hugr {} - macro_rules! impl_region_petgraph_traits { - ($hugr:ident) => { - impl<'a, Root, Base> pv::GraphBase for $hugr<'a, Root, Base> - where - Root: NodeHandle, - Base: HugrInternals + HugrView, + ($hugr:ident < $($l:lifetime,)? $($v:ident $(:$b:tt $(+ $b2:tt)*)?),* > ) => { + impl <$($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::GraphBase for $hugr<$($l,)? $($v),*> { type NodeId = Node; type EdgeId = ((Node, Port), (Node, Port)); } - impl<'a, Root, Base> pv::GraphProp for $hugr<'a, Root, Base> - where - Root: NodeHandle, - Base: HugrInternals + HugrView, + impl <$($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::GraphProp for $hugr<$($l,)? $($v),*> { type EdgeType = petgraph::Directed; } - impl<'a, Root, Base> pv::NodeCount for $hugr<'a, Root, Base> - where - Root: NodeHandle, - Base: HugrInternals + HugrView, + impl <$($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::NodeCount for $hugr<$($l,)? $($v),*> { fn node_count(&self) -> usize { HugrView::node_count(self) } } - impl<'a, Root, Base> pv::NodeIndexable for $hugr<'a, Root, Base> - where - Root: NodeHandle, - Base: HugrInternals + HugrView, + impl <$($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::NodeIndexable for $hugr<$($l,)? $($v),*> { fn node_bound(&self) -> usize { HugrView::node_count(self) @@ -188,72 +97,40 @@ macro_rules! impl_region_petgraph_traits { } } - impl<'a, Root, Base> pv::EdgeCount for $hugr<'a, Root, Base> - where - Root: NodeHandle, - Base: HugrInternals + HugrView, + impl <$($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::EdgeCount for $hugr<$($l,)? $($v),*> { fn edge_count(&self) -> usize { HugrView::edge_count(self) } } - impl<'a, Root, Base> pv::Data for $hugr<'a, Root, Base> - where - Root: NodeHandle, - Base: HugrInternals + HugrView, + impl <$($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::Data for $hugr<$($l,)? $($v),*> { type NodeWeight = OpType; type EdgeWeight = EdgeKind; } - impl<'g, 'a, Root, Base> pv::IntoNodeIdentifiers for &'g $hugr<'a, Root, Base> - where - Root: NodeHandle, - Base: HugrInternals + HugrView, + impl <'g, $($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::IntoNodeIdentifiers for &'g $hugr<$($l,)? $($v),*> { - type NodeIdentifiers = <$hugr<'a, Root, Base> as HugrView>::Nodes<'g>; + type NodeIdentifiers = <$hugr<$($l,)? $($v),*> as HugrView>::Nodes<'g>; fn node_identifiers(self) -> Self::NodeIdentifiers { self.nodes() } } - impl<'g, 'a, Root, Base> pv::IntoNodeReferences for &'g $hugr<'a, Root, Base> - where - Root: NodeHandle, - 'g: 'a, - Base: HugrInternals + HugrView, - { - type NodeRef = HugrNodeRef<'a>; - type NodeReferences = - MapWithCtx<<$hugr<'a, Root, Base> as HugrView>::Nodes<'a>, Self, HugrNodeRef<'a>>; - - fn node_references(self) -> Self::NodeReferences { - self.nodes() - .with_context(self) - .map_with_context(|n, &hugr| HugrNodeRef::from_node(n, hugr)) - } - } - - impl<'g, 'a, Root, Base> pv::IntoNeighbors for &'g $hugr<'a, Root, Base> - where - Root: NodeHandle, - Base: HugrInternals + HugrView, + impl <'g, $($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::IntoNeighbors for &'g $hugr<$($l,)? $($v),*> { - type Neighbors = <$hugr<'a, Root, Base> as HugrView>::Neighbours<'g>; + type Neighbors = <$hugr<$($l,)? $($v),*> as HugrView>::Neighbours<'g>; fn neighbors(self, n: Self::NodeId) -> Self::Neighbors { self.output_neighbours(n) } } - impl<'g, 'a, Root, Base> pv::IntoNeighborsDirected for &'g $hugr<'a, Root, Base> - where - Root: NodeHandle, - Base: HugrInternals + HugrView, + impl <'g, $($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::IntoNeighborsDirected for &'g $hugr<$($l,)? $($v),*> { - type NeighborsDirected = <$hugr<'a, Root, Base> as HugrView>::Neighbours<'g>; + type NeighborsDirected = <$hugr<$($l,)? $($v),*> as HugrView>::Neighbours<'g>; fn neighbors_directed( self, @@ -264,10 +141,7 @@ macro_rules! impl_region_petgraph_traits { } } - impl<'a, Root, Base> pv::Visitable for $hugr<'a, Root, Base> - where - Root: NodeHandle, - Base: HugrInternals + HugrView, + impl <$($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::Visitable for $hugr<$($l,)? $($v),*> { type Map = std::collections::HashSet; @@ -280,10 +154,7 @@ macro_rules! impl_region_petgraph_traits { } } - impl<'a, Root, Base> pv::GetAdjacencyMatrix for $hugr<'a, Root, Base> - where - Root: NodeHandle, - Base: HugrInternals + HugrView, + impl <$($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::GetAdjacencyMatrix for $hugr<$($l,)? $($v),*> { type AdjMatrix = std::collections::HashSet<(Self::NodeId, Self::NodeId)>; @@ -307,17 +178,21 @@ macro_rules! impl_region_petgraph_traits { } } - impl<'a, Root, Base> PetgraphHugr for $hugr<'a, Root, Base> - where - Root: NodeHandle, - Base: HugrInternals + HugrView, + impl <$($l,)? $($v $(:$b $(+ $b2)*)?),*> PetgraphHugr for $hugr<$($l,)? $($v),*> { } }; } -impl_region_petgraph_traits!(SiblingGraph); -impl_region_petgraph_traits!(DescendantsGraph); +#[rustfmt::skip] +impl_region_petgraph_traits!(Hugr<>); + +impl_petgraph_into_noderefs!(SiblingGraph); +impl_petgraph_into_noderefs!(DescendantsGraph); +impl_region_petgraph_traits!(SiblingGraph<'a, Root: NodeHandle, Base: HugrInternals + HugrView>); +impl_region_petgraph_traits!( + DescendantsGraph<'a, Root: NodeHandle, Base: HugrInternals + HugrView> +); /// Reference to a Hugr node and its associated OpType. #[derive(Debug, Clone, Copy)] From 6042928e047e80a28f9344167edef184415f908d Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Thu, 7 Sep 2023 11:10:09 +0100 Subject: [PATCH 3/8] feat: remove rustfmt(skip) in petgraph macro --- src/hugr/views/petgraph.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/hugr/views/petgraph.rs b/src/hugr/views/petgraph.rs index c9ff22a3c..cc12ab980 100644 --- a/src/hugr/views/petgraph.rs +++ b/src/hugr/views/petgraph.rs @@ -63,6 +63,9 @@ macro_rules! impl_petgraph_into_noderefs { } macro_rules! impl_region_petgraph_traits { + ($hugr:ident) => { + impl_region_petgraph_traits!($hugr<>); + }; ($hugr:ident < $($l:lifetime,)? $($v:ident $(:$b:tt $(+ $b2:tt)*)?),* > ) => { impl <$($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::GraphBase for $hugr<$($l,)? $($v),*> { @@ -185,7 +188,7 @@ macro_rules! impl_region_petgraph_traits { } #[rustfmt::skip] -impl_region_petgraph_traits!(Hugr<>); +impl_region_petgraph_traits!(Hugr); impl_petgraph_into_noderefs!(SiblingGraph); impl_petgraph_into_noderefs!(DescendantsGraph); From ec041490e354647b2cea67a8d31956d55d625234 Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Thu, 7 Sep 2023 11:37:15 +0100 Subject: [PATCH 4/8] Implement petgraph only on a wrappers Fix ambiguous import --- src/hugr/validate.rs | 7 +- src/hugr/views.rs | 16 +- src/hugr/views/descendants.rs | 4 +- src/hugr/views/petgraph.rs | 360 +++++++++++++++++++--------------- src/hugr/views/sibling.rs | 4 +- 5 files changed, 216 insertions(+), 175 deletions(-) diff --git a/src/hugr/validate.rs b/src/hugr/validate.rs index 5e4438fee..a5a3b33b9 100644 --- a/src/hugr/validate.rs +++ b/src/hugr/validate.rs @@ -22,6 +22,7 @@ use crate::ops::{OpTag, OpTrait, OpType, ValidateOp}; use crate::types::{EdgeKind, Type}; use crate::{Direction, Hugr, Node, Port}; +use super::views::petgraph::PetgraphWrapper; use super::views::{HierarchyView, HugrView, SiblingGraph}; use super::NodeType; @@ -99,7 +100,8 @@ impl<'a, 'b> ValidationContext<'a, 'b> { /// The results of this computation should be cached in `self.dominators`. /// We don't do it here to avoid mutable borrows. fn compute_dominator(&self, parent: Node) -> Dominators { - let region: SiblingGraph = SiblingGraph::new(self.hugr, parent); + let region: PetgraphWrapper = + PetgraphWrapper::new(SiblingGraph::new(self.hugr, parent)); let entry_node = self.hugr.children(parent).next().unwrap(); dominators::simple_fast(®ion, entry_node) } @@ -364,7 +366,8 @@ impl<'a, 'b> ValidationContext<'a, 'b> { return Ok(()); }; - let region: SiblingGraph = SiblingGraph::new(self.hugr, parent); + let region: PetgraphWrapper = + PetgraphWrapper::new(SiblingGraph::new(self.hugr, parent)); let postorder = Topo::new(®ion); let nodes_visited = postorder.iter(®ion).filter(|n| *n != parent).count(); let node_count = self.hugr.children(parent).count(); diff --git a/src/hugr/views.rs b/src/hugr/views.rs index c05313569..b146316aa 100644 --- a/src/hugr/views.rs +++ b/src/hugr/views.rs @@ -8,6 +8,7 @@ pub mod sibling_subgraph; #[cfg(test)] mod tests; +pub use self::petgraph::PetgraphWrapper; pub use descendants::DescendantsGraph; pub use sibling::SiblingGraph; pub use sibling_subgraph::SiblingSubgraph; @@ -22,7 +23,6 @@ use crate::ops::handle::NodeHandle; use crate::ops::{FuncDecl, FuncDefn, OpName, OpTag, OpType, DFG}; use crate::types::{EdgeKind, FunctionType}; use crate::{Direction, Node, Port}; -use ::petgraph::visit as pv; /// A trait for inspecting HUGRs. /// For end users we intend this to be superseded by region-specific APIs. @@ -232,19 +232,7 @@ pub trait HugrView: sealed::HugrInternals { } /// A common trait for views of a HUGR hierarchical subgraph. -pub trait HierarchyView<'a>: - HugrView - + pv::GraphBase - + pv::GraphProp - + pv::NodeCount - + pv::NodeIndexable - + pv::EdgeCount - + pv::Visitable - + pv::GetAdjacencyMatrix - + pv::Visitable -where - for<'g> &'g Self: pv::IntoNeighborsDirected + pv::IntoNodeIdentifiers, -{ +pub trait HierarchyView<'a>: HugrView { /// The base from which the subgraph is derived. type Base; diff --git a/src/hugr/views/descendants.rs b/src/hugr/views/descendants.rs index cf0262be3..508517f40 100644 --- a/src/hugr/views/descendants.rs +++ b/src/hugr/views/descendants.rs @@ -21,8 +21,8 @@ type RegionGraph<'g> = portgraph::view::Region<'g, &'g MultiPortGraph>; /// its immediate children. Prefer using [`SiblingGraph`] when possible, /// as it is more efficient. /// -/// Implements the [`HierarchyView`] trait, as well as [`HugrView`] and petgraph's -/// _visit_ traits, so can be used interchangeably with [`SiblingGraph`]. +/// Implements the [`HierarchyView`] trait, as well as [`HugrView`], it can be +/// used interchangeably with [`SiblingGraph`]. /// /// [`SiblingGraph`]: super::SiblingGraph pub struct DescendantsGraph<'g, Root = Node, Base = Hugr> diff --git a/src/hugr/views/petgraph.rs b/src/hugr/views/petgraph.rs index 85eddb2ca..59b152f8e 100644 --- a/src/hugr/views/petgraph.rs +++ b/src/hugr/views/petgraph.rs @@ -1,201 +1,251 @@ //! Implementations of petgraph's traits for Hugr Region views. -use super::{DescendantsGraph, SiblingGraph}; -use crate::hugr::views::sealed::HugrInternals; use crate::hugr::HugrView; -use crate::ops::handle::NodeHandle; use crate::ops::OpType; use crate::types::EdgeKind; -use crate::{Hugr, Node, Port}; +use crate::{Node, Port}; use context_iterators::{ContextIterator, IntoContextIterator, MapWithCtx}; +use delegate::delegate; use petgraph::visit as pv; use portgraph::NodeIndex; -/// A trait grouping the multiple petgraph traits implemented on Hugrs -// -// TODO: We could just require these in `HugrView`. -pub trait PetgraphHugr: - HugrView - + pv::GraphBase - + pv::GraphProp - + pv::NodeCount - + pv::NodeIndexable - + pv::EdgeCount - + pv::Visitable - + pv::GetAdjacencyMatrix - + pv::Visitable +use super::sealed::HugrInternals; + +/// Wrapper for a HugrView that implements petgraph's traits. +/// +/// It can be used to apply petgraph's algorithms to a Hugr. +#[derive(Debug, Clone, Copy)] +pub struct PetgraphWrapper { + hugr: T, +} + +impl PetgraphWrapper where - for<'g> &'g Self: pv::IntoNeighborsDirected + pv::IntoNodeIdentifiers, + T: HugrView, { + /// Wrap a HugrView in a PetgraphWrapper. + pub fn new(hugr: T) -> Self { + Self { hugr } + } } -impl<'g> pv::IntoNodeReferences for &'g Hugr { - type NodeRef = HugrNodeRef<'g>; - type NodeReferences = MapWithCtx<::Nodes<'g>, Self, HugrNodeRef<'g>>; +impl pv::GraphBase for PetgraphWrapper +where + T: HugrView, +{ + type NodeId = Node; + type EdgeId = ((Node, Port), (Node, Port)); +} - fn node_references(self) -> Self::NodeReferences { - self.nodes() - .with_context(self) - .map_with_context(|n, &hugr| HugrNodeRef::from_node(n, hugr)) - } +impl pv::GraphProp for PetgraphWrapper +where + T: HugrView, +{ + type EdgeType = petgraph::Directed; } -macro_rules! impl_petgraph_into_noderefs { - ($hugr:ident) => { - impl<'g, 'a, Root, Base> pv::IntoNodeReferences for &'g $hugr<'a, Root, Base> - where - Root: NodeHandle, - 'g: 'a, - Base: HugrInternals + HugrView, - { - type NodeRef = HugrNodeRef<'a>; - type NodeReferences = - MapWithCtx<<$hugr<'a, Root, Base> as HugrView>::Nodes<'a>, Self, HugrNodeRef<'a>>; +impl pv::NodeCount for PetgraphWrapper +where + T: HugrView, +{ + fn node_count(&self) -> usize { + HugrView::node_count(self) + } +} - fn node_references(self) -> Self::NodeReferences { - self.nodes() - .with_context(self) - .map_with_context(|n, &hugr| HugrNodeRef::from_node(n, hugr)) - } - } - }; -} - -macro_rules! impl_region_petgraph_traits { - ($hugr:ident) => { - impl_region_petgraph_traits!($hugr<>); - }; - ($hugr:ident < $($l:lifetime,)? $($v:ident $(:$b:tt $(+ $b2:tt)*)?),* > ) => { - impl <$($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::GraphBase for $hugr<$($l,)? $($v),*> - { - type NodeId = Node; - type EdgeId = ((Node, Port), (Node, Port)); - } +impl pv::NodeIndexable for PetgraphWrapper +where + T: HugrView, +{ + fn node_bound(&self) -> usize { + HugrView::node_count(self) + } - impl <$($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::GraphProp for $hugr<$($l,)? $($v),*> - { - type EdgeType = petgraph::Directed; - } + fn to_index(&self, ix: Self::NodeId) -> usize { + ix.index.into() + } - impl <$($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::NodeCount for $hugr<$($l,)? $($v),*> - { - fn node_count(&self) -> usize { - HugrView::node_count(self) - } - } + fn from_index(&self, ix: usize) -> Self::NodeId { + NodeIndex::new(ix).into() + } +} - impl <$($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::NodeIndexable for $hugr<$($l,)? $($v),*> - { - fn node_bound(&self) -> usize { - HugrView::node_count(self) - } +impl pv::EdgeCount for PetgraphWrapper +where + T: HugrView, +{ + fn edge_count(&self) -> usize { + HugrView::edge_count(self) + } +} - fn to_index(&self, ix: Self::NodeId) -> usize { - ix.index.into() - } +impl pv::Data for PetgraphWrapper +where + T: HugrView, +{ + type NodeWeight = OpType; + type EdgeWeight = EdgeKind; +} - fn from_index(&self, ix: usize) -> Self::NodeId { - NodeIndex::new(ix).into() - } - } +impl<'g, T> pv::IntoNodeReferences for &'g PetgraphWrapper +where + T: HugrView, +{ + type NodeRef = HugrNodeRef<'g>; + type NodeReferences = MapWithCtx<::Nodes<'g>, Self, HugrNodeRef<'g>>; - impl <$($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::EdgeCount for $hugr<$($l,)? $($v),*> - { - fn edge_count(&self) -> usize { - HugrView::edge_count(self) - } - } + fn node_references(self) -> Self::NodeReferences { + self.nodes() + .with_context(self) + .map_with_context(|n, &hugr| HugrNodeRef::from_node(n, hugr)) + } +} - impl <$($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::Data for $hugr<$($l,)? $($v),*> - { - type NodeWeight = OpType; - type EdgeWeight = EdgeKind; - } +impl<'g, T> pv::IntoNodeIdentifiers for &'g PetgraphWrapper +where + T: HugrView, +{ + type NodeIdentifiers = ::Nodes<'g>; - impl <'g, $($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::IntoNodeIdentifiers for &'g $hugr<$($l,)? $($v),*> - { - type NodeIdentifiers = <$hugr<$($l,)? $($v),*> as HugrView>::Nodes<'g>; + fn node_identifiers(self) -> Self::NodeIdentifiers { + self.nodes() + } +} - fn node_identifiers(self) -> Self::NodeIdentifiers { - self.nodes() - } - } +impl<'g, T> pv::IntoNeighbors for &'g PetgraphWrapper +where + T: HugrView, +{ + type Neighbors = ::Neighbours<'g>; - impl <'g, $($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::IntoNeighbors for &'g $hugr<$($l,)? $($v),*> - { - type Neighbors = <$hugr<$($l,)? $($v),*> as HugrView>::Neighbours<'g>; + fn neighbors(self, n: Self::NodeId) -> Self::Neighbors { + self.output_neighbours(n) + } +} - fn neighbors(self, n: Self::NodeId) -> Self::Neighbors { - self.output_neighbours(n) - } - } +impl<'g, T> pv::IntoNeighborsDirected for &'g PetgraphWrapper +where + T: HugrView, +{ + type NeighborsDirected = ::Neighbours<'g>; + + fn neighbors_directed( + self, + n: Self::NodeId, + d: petgraph::Direction, + ) -> Self::NeighborsDirected { + self.neighbours(n, d.into()) + } +} - impl <'g, $($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::IntoNeighborsDirected for &'g $hugr<$($l,)? $($v),*> - { - type NeighborsDirected = <$hugr<$($l,)? $($v),*> as HugrView>::Neighbours<'g>; +impl pv::Visitable for PetgraphWrapper +where + T: HugrView, +{ + type Map = std::collections::HashSet; - fn neighbors_directed( - self, - n: Self::NodeId, - d: petgraph::Direction, - ) -> Self::NeighborsDirected { - self.neighbours(n, d.into()) - } - } + fn visit_map(&self) -> Self::Map { + std::collections::HashSet::new() + } - impl <$($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::Visitable for $hugr<$($l,)? $($v),*> - { - type Map = std::collections::HashSet; + fn reset_map(&self, map: &mut Self::Map) { + map.clear(); + } +} - fn visit_map(&self) -> Self::Map { - std::collections::HashSet::new() - } +impl pv::GetAdjacencyMatrix for PetgraphWrapper +where + T: HugrView, +{ + type AdjMatrix = std::collections::HashSet<(Self::NodeId, Self::NodeId)>; - fn reset_map(&self, map: &mut Self::Map) { - map.clear(); + fn adjacency_matrix(&self) -> Self::AdjMatrix { + let mut matrix = std::collections::HashSet::new(); + for node in self.nodes() { + for neighbour in self.output_neighbours(node) { + matrix.insert((node, neighbour)); } } + matrix + } - impl <$($l,)? $($v $(:$b $(+ $b2)*)?),*> pv::GetAdjacencyMatrix for $hugr<$($l,)? $($v),*> - { - type AdjMatrix = std::collections::HashSet<(Self::NodeId, Self::NodeId)>; - - fn adjacency_matrix(&self) -> Self::AdjMatrix { - let mut matrix = std::collections::HashSet::new(); - for node in self.nodes() { - for neighbour in self.output_neighbours(node) { - matrix.insert((node, neighbour)); - } - } - matrix - } + fn is_adjacent(&self, matrix: &Self::AdjMatrix, a: Self::NodeId, b: Self::NodeId) -> bool { + matrix.contains(&(a, b)) + } +} - fn is_adjacent( - &self, - matrix: &Self::AdjMatrix, - a: Self::NodeId, - b: Self::NodeId, - ) -> bool { - matrix.contains(&(a, b)) - } +impl HugrInternals for PetgraphWrapper +where + T: HugrView, +{ + type Portgraph<'p> = ::Portgraph<'p> + where + Self: 'p; + + delegate! { + to self.hugr { + fn portgraph(&self) -> Self::Portgraph<'_>; + fn base_hugr(&self) -> &crate::Hugr; + fn root_node(&self) -> Node; } + } +} - impl <$($l,)? $($v $(:$b $(+ $b2)*)?),*> PetgraphHugr for $hugr<$($l,)? $($v),*> - { +impl HugrView for PetgraphWrapper +where + T: HugrView, +{ + type RootHandle = T::RootHandle; + + type Nodes<'a> = T::Nodes<'a> + where + Self: 'a; + + type NodePorts<'a> = T::NodePorts<'a> + where + Self: 'a; + + type Children<'a> = T::Children<'a> + where + Self: 'a; + + type Neighbours<'a> = T::Neighbours<'a> + where + Self: 'a; + + type PortLinks<'a> = T::PortLinks<'a> + where + Self: 'a; + + type NodeConnections<'a> = T::NodeConnections<'a> + where + Self: 'a; + + delegate! { + to self.hugr { + fn contains_node(&self, node: Node) -> bool; + fn get_parent(&self, node: Node) -> Option; + fn get_optype(&self, node: Node) -> &OpType; + fn get_nodetype(&self, node: Node) -> &crate::hugr::NodeType; + fn get_metadata(&self, node: Node) -> &crate::hugr::NodeMetadata; + fn node_count(&self) -> usize; + fn edge_count(&self) -> usize; + fn nodes(&self) -> Self::Nodes<'_>; + fn node_ports(&self, node: Node, dir: crate::Direction) -> Self::NodePorts<'_>; + fn all_node_ports(&self, node: Node) -> Self::NodePorts<'_>; + fn linked_ports(&self, node: Node, port: Port) -> Self::PortLinks<'_>; + fn node_connections(&self, node: Node, other: Node) -> Self::NodeConnections<'_>; + fn num_ports(&self, node: Node, dir: crate::Direction) -> usize; + fn children(&self, node: Node) -> Self::Children<'_>; + fn neighbours(&self, node: Node, dir: crate::Direction) -> Self::Neighbours<'_>; + fn all_neighbours(&self, node: Node) -> Self::Neighbours<'_>; + fn get_io(&self, node: Node) -> Option<[Node; 2]>; + fn get_function_type(&self) -> Option<&crate::types::FunctionType>; } - }; + } } -impl_region_petgraph_traits!(Hugr); - -impl_petgraph_into_noderefs!(SiblingGraph); -impl_petgraph_into_noderefs!(DescendantsGraph); -impl_region_petgraph_traits!(SiblingGraph<'a, Root: NodeHandle, Base: HugrInternals + HugrView>); -impl_region_petgraph_traits!( - DescendantsGraph<'a, Root: NodeHandle, Base: HugrInternals + HugrView> -); - /// Reference to a Hugr node and its associated OpType. #[derive(Debug, Clone, Copy)] pub struct HugrNodeRef<'a> { diff --git a/src/hugr/views/sibling.rs b/src/hugr/views/sibling.rs index 84532831a..86bc142d3 100644 --- a/src/hugr/views/sibling.rs +++ b/src/hugr/views/sibling.rs @@ -21,8 +21,8 @@ type FlatRegionGraph<'g> = portgraph::view::FlatRegion<'g, &'g MultiPortGraph>; /// /// See [`DescendantsGraph`] for a view that includes all descendants of the root. /// -/// Implements the [`HierarchyView`] trait, as well as [`HugrView`] and petgraph's -/// _visit_ traits, so can be used interchangeably with [`DescendantsGraph`]. +/// Implements the [`HierarchyView`] trait, as well as [`HugrView`], it can be +/// used interchangeably with [`DescendantsGraph`]. /// /// [`DescendantsGraph`]: super::DescendantsGraph pub struct SiblingGraph<'g, Root = Node, Base = Hugr> From 4e130ba1d057f9bff255bcc35626c721d297856c Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Thu, 7 Sep 2023 13:12:06 +0100 Subject: [PATCH 5/8] Wrap over references to HugrViews instead --- src/hugr/validate.rs | 14 +++++++------- src/hugr/views/petgraph.rs | 36 ++++++++++++++++++------------------ 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/hugr/validate.rs b/src/hugr/validate.rs index a5a3b33b9..d2c96cbc8 100644 --- a/src/hugr/validate.rs +++ b/src/hugr/validate.rs @@ -100,10 +100,10 @@ impl<'a, 'b> ValidationContext<'a, 'b> { /// The results of this computation should be cached in `self.dominators`. /// We don't do it here to avoid mutable borrows. fn compute_dominator(&self, parent: Node) -> Dominators { - let region: PetgraphWrapper = - PetgraphWrapper::new(SiblingGraph::new(self.hugr, parent)); + let region = SiblingGraph::new(self.hugr, parent); + let graph: PetgraphWrapper = PetgraphWrapper::new(®ion); let entry_node = self.hugr.children(parent).next().unwrap(); - dominators::simple_fast(®ion, entry_node) + dominators::simple_fast(&graph, entry_node) } /// Check the constraints on a single node. @@ -366,10 +366,10 @@ impl<'a, 'b> ValidationContext<'a, 'b> { return Ok(()); }; - let region: PetgraphWrapper = - PetgraphWrapper::new(SiblingGraph::new(self.hugr, parent)); - let postorder = Topo::new(®ion); - let nodes_visited = postorder.iter(®ion).filter(|n| *n != parent).count(); + let region = SiblingGraph::new(self.hugr, parent); + let graph: PetgraphWrapper = PetgraphWrapper::new(®ion); + let postorder = Topo::new(&graph); + let nodes_visited = postorder.iter(&graph).filter(|n| *n != parent).count(); let node_count = self.hugr.children(parent).count(); if nodes_visited != node_count { return Err(ValidationError::NotADag { diff --git a/src/hugr/views/petgraph.rs b/src/hugr/views/petgraph.rs index 59b152f8e..8198cd853 100644 --- a/src/hugr/views/petgraph.rs +++ b/src/hugr/views/petgraph.rs @@ -16,21 +16,21 @@ use super::sealed::HugrInternals; /// /// It can be used to apply petgraph's algorithms to a Hugr. #[derive(Debug, Clone, Copy)] -pub struct PetgraphWrapper { - hugr: T, +pub struct PetgraphWrapper<'a, T> { + hugr: &'a T, } -impl PetgraphWrapper +impl<'a, T> PetgraphWrapper<'a, T> where T: HugrView, { /// Wrap a HugrView in a PetgraphWrapper. - pub fn new(hugr: T) -> Self { + pub fn new(hugr: &'a T) -> Self { Self { hugr } } } -impl pv::GraphBase for PetgraphWrapper +impl<'a, T> pv::GraphBase for PetgraphWrapper<'a, T> where T: HugrView, { @@ -38,14 +38,14 @@ where type EdgeId = ((Node, Port), (Node, Port)); } -impl pv::GraphProp for PetgraphWrapper +impl<'a, T> pv::GraphProp for PetgraphWrapper<'a, T> where T: HugrView, { type EdgeType = petgraph::Directed; } -impl pv::NodeCount for PetgraphWrapper +impl<'a, T> pv::NodeCount for PetgraphWrapper<'a, T> where T: HugrView, { @@ -54,7 +54,7 @@ where } } -impl pv::NodeIndexable for PetgraphWrapper +impl<'a, T> pv::NodeIndexable for PetgraphWrapper<'a, T> where T: HugrView, { @@ -71,7 +71,7 @@ where } } -impl pv::EdgeCount for PetgraphWrapper +impl<'a, T> pv::EdgeCount for PetgraphWrapper<'a, T> where T: HugrView, { @@ -80,7 +80,7 @@ where } } -impl pv::Data for PetgraphWrapper +impl<'a, T> pv::Data for PetgraphWrapper<'a, T> where T: HugrView, { @@ -88,7 +88,7 @@ where type EdgeWeight = EdgeKind; } -impl<'g, T> pv::IntoNodeReferences for &'g PetgraphWrapper +impl<'g, 'a, T> pv::IntoNodeReferences for &'g PetgraphWrapper<'a, T> where T: HugrView, { @@ -102,7 +102,7 @@ where } } -impl<'g, T> pv::IntoNodeIdentifiers for &'g PetgraphWrapper +impl<'g, 'a, T> pv::IntoNodeIdentifiers for &'g PetgraphWrapper<'a, T> where T: HugrView, { @@ -113,7 +113,7 @@ where } } -impl<'g, T> pv::IntoNeighbors for &'g PetgraphWrapper +impl<'g, 'a, T> pv::IntoNeighbors for &'g PetgraphWrapper<'a, T> where T: HugrView, { @@ -124,7 +124,7 @@ where } } -impl<'g, T> pv::IntoNeighborsDirected for &'g PetgraphWrapper +impl<'g, 'a, T> pv::IntoNeighborsDirected for &'g PetgraphWrapper<'a, T> where T: HugrView, { @@ -139,7 +139,7 @@ where } } -impl pv::Visitable for PetgraphWrapper +impl<'a, T> pv::Visitable for PetgraphWrapper<'a, T> where T: HugrView, { @@ -154,7 +154,7 @@ where } } -impl pv::GetAdjacencyMatrix for PetgraphWrapper +impl<'a, T> pv::GetAdjacencyMatrix for PetgraphWrapper<'a, T> where T: HugrView, { @@ -175,7 +175,7 @@ where } } -impl HugrInternals for PetgraphWrapper +impl<'a, T> HugrInternals for PetgraphWrapper<'a, T> where T: HugrView, { @@ -192,7 +192,7 @@ where } } -impl HugrView for PetgraphWrapper +impl<'g, T> HugrView for PetgraphWrapper<'g, T> where T: HugrView, { From fea5d58946396734ea2ed44dd9513ea2b2359d98 Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Thu, 7 Sep 2023 15:35:26 +0100 Subject: [PATCH 6/8] Don't implement HugrView on the wrapper --- src/hugr/views/petgraph.rs | 95 +++++--------------------------------- 1 file changed, 11 insertions(+), 84 deletions(-) diff --git a/src/hugr/views/petgraph.rs b/src/hugr/views/petgraph.rs index 8198cd853..3a22e5262 100644 --- a/src/hugr/views/petgraph.rs +++ b/src/hugr/views/petgraph.rs @@ -6,12 +6,9 @@ use crate::types::EdgeKind; use crate::{Node, Port}; use context_iterators::{ContextIterator, IntoContextIterator, MapWithCtx}; -use delegate::delegate; use petgraph::visit as pv; use portgraph::NodeIndex; -use super::sealed::HugrInternals; - /// Wrapper for a HugrView that implements petgraph's traits. /// /// It can be used to apply petgraph's algorithms to a Hugr. @@ -50,7 +47,7 @@ where T: HugrView, { fn node_count(&self) -> usize { - HugrView::node_count(self) + HugrView::node_count(self.hugr) } } @@ -59,7 +56,7 @@ where T: HugrView, { fn node_bound(&self) -> usize { - HugrView::node_count(self) + HugrView::node_count(self.hugr) } fn to_index(&self, ix: Self::NodeId) -> usize { @@ -76,7 +73,7 @@ where T: HugrView, { fn edge_count(&self) -> usize { - HugrView::edge_count(self) + HugrView::edge_count(self.hugr) } } @@ -96,9 +93,10 @@ where type NodeReferences = MapWithCtx<::Nodes<'g>, Self, HugrNodeRef<'g>>; fn node_references(self) -> Self::NodeReferences { - self.nodes() + self.hugr + .nodes() .with_context(self) - .map_with_context(|n, &hugr| HugrNodeRef::from_node(n, hugr)) + .map_with_context(|n, &wrapper| HugrNodeRef::from_node(n, wrapper.hugr)) } } @@ -109,7 +107,7 @@ where type NodeIdentifiers = ::Nodes<'g>; fn node_identifiers(self) -> Self::NodeIdentifiers { - self.nodes() + self.hugr.nodes() } } @@ -120,7 +118,7 @@ where type Neighbors = ::Neighbours<'g>; fn neighbors(self, n: Self::NodeId) -> Self::Neighbors { - self.output_neighbours(n) + self.hugr.output_neighbours(n) } } @@ -135,7 +133,7 @@ where n: Self::NodeId, d: petgraph::Direction, ) -> Self::NeighborsDirected { - self.neighbours(n, d.into()) + self.hugr.neighbours(n, d.into()) } } @@ -162,8 +160,8 @@ where fn adjacency_matrix(&self) -> Self::AdjMatrix { let mut matrix = std::collections::HashSet::new(); - for node in self.nodes() { - for neighbour in self.output_neighbours(node) { + for node in self.hugr.nodes() { + for neighbour in self.hugr.output_neighbours(node) { matrix.insert((node, neighbour)); } } @@ -175,77 +173,6 @@ where } } -impl<'a, T> HugrInternals for PetgraphWrapper<'a, T> -where - T: HugrView, -{ - type Portgraph<'p> = ::Portgraph<'p> - where - Self: 'p; - - delegate! { - to self.hugr { - fn portgraph(&self) -> Self::Portgraph<'_>; - fn base_hugr(&self) -> &crate::Hugr; - fn root_node(&self) -> Node; - } - } -} - -impl<'g, T> HugrView for PetgraphWrapper<'g, T> -where - T: HugrView, -{ - type RootHandle = T::RootHandle; - - type Nodes<'a> = T::Nodes<'a> - where - Self: 'a; - - type NodePorts<'a> = T::NodePorts<'a> - where - Self: 'a; - - type Children<'a> = T::Children<'a> - where - Self: 'a; - - type Neighbours<'a> = T::Neighbours<'a> - where - Self: 'a; - - type PortLinks<'a> = T::PortLinks<'a> - where - Self: 'a; - - type NodeConnections<'a> = T::NodeConnections<'a> - where - Self: 'a; - - delegate! { - to self.hugr { - fn contains_node(&self, node: Node) -> bool; - fn get_parent(&self, node: Node) -> Option; - fn get_optype(&self, node: Node) -> &OpType; - fn get_nodetype(&self, node: Node) -> &crate::hugr::NodeType; - fn get_metadata(&self, node: Node) -> &crate::hugr::NodeMetadata; - fn node_count(&self) -> usize; - fn edge_count(&self) -> usize; - fn nodes(&self) -> Self::Nodes<'_>; - fn node_ports(&self, node: Node, dir: crate::Direction) -> Self::NodePorts<'_>; - fn all_node_ports(&self, node: Node) -> Self::NodePorts<'_>; - fn linked_ports(&self, node: Node, port: Port) -> Self::PortLinks<'_>; - fn node_connections(&self, node: Node, other: Node) -> Self::NodeConnections<'_>; - fn num_ports(&self, node: Node, dir: crate::Direction) -> usize; - fn children(&self, node: Node) -> Self::Children<'_>; - fn neighbours(&self, node: Node, dir: crate::Direction) -> Self::Neighbours<'_>; - fn all_neighbours(&self, node: Node) -> Self::Neighbours<'_>; - fn get_io(&self, node: Node) -> Option<[Node; 2]>; - fn get_function_type(&self) -> Option<&crate::types::FunctionType>; - } - } -} - /// Reference to a Hugr node and its associated OpType. #[derive(Debug, Clone, Copy)] pub struct HugrNodeRef<'a> { From 9887c8dc0afc54380dca952da86a952fbfd7b56e Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Thu, 7 Sep 2023 15:37:32 +0100 Subject: [PATCH 7/8] HugrView::as_petgraph --- src/hugr/views.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/hugr/views.rs b/src/hugr/views.rs index b146316aa..576342fef 100644 --- a/src/hugr/views.rs +++ b/src/hugr/views.rs @@ -181,6 +181,15 @@ pub trait HugrView: sealed::HugrInternals { /// type. Otherwise return None. fn get_function_type(&self) -> Option<&FunctionType>; + /// Return a wrapper over the view that can be used in petgraph algorithms. + #[inline] + fn as_petgraph(&self) -> PetgraphWrapper<'_, Self> + where + Self: Sized, + { + PetgraphWrapper::new(self) + } + /// Return dot string showing underlying graph and hierarchy side by side. fn dot_string(&self) -> String { let hugr = self.base_hugr(); From 8d74be43afccbfdfbdc62442bf69dfd018e4efb3 Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Thu, 7 Sep 2023 16:40:44 +0100 Subject: [PATCH 8/8] Drop redundant constructor --- src/hugr/validate.rs | 16 ++++++++-------- src/hugr/views.rs | 2 +- src/hugr/views/petgraph.rs | 12 +----------- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/hugr/validate.rs b/src/hugr/validate.rs index 1707c3bf1..67016ac5f 100644 --- a/src/hugr/validate.rs +++ b/src/hugr/validate.rs @@ -22,7 +22,6 @@ use crate::ops::{OpTag, OpTrait, OpType, ValidateOp}; use crate::types::{EdgeKind, Type}; use crate::{Direction, Hugr, Node, Port}; -use super::views::petgraph::PetgraphWrapper; use super::views::{HierarchyView, HugrView, SiblingGraph}; use super::NodeType; @@ -100,10 +99,9 @@ impl<'a, 'b> ValidationContext<'a, 'b> { /// The results of this computation should be cached in `self.dominators`. /// We don't do it here to avoid mutable borrows. fn compute_dominator(&self, parent: Node) -> Dominators { - let region = SiblingGraph::new(self.hugr, parent); - let graph: PetgraphWrapper = PetgraphWrapper::new(®ion); + let region: SiblingGraph = SiblingGraph::new(self.hugr, parent); let entry_node = self.hugr.children(parent).next().unwrap(); - dominators::simple_fast(&graph, entry_node) + dominators::simple_fast(®ion.as_petgraph(), entry_node) } /// Check the constraints on a single node. @@ -366,10 +364,12 @@ impl<'a, 'b> ValidationContext<'a, 'b> { return Ok(()); }; - let region = SiblingGraph::new(self.hugr, parent); - let graph: PetgraphWrapper = PetgraphWrapper::new(®ion); - let postorder = Topo::new(&graph); - let nodes_visited = postorder.iter(&graph).filter(|n| *n != parent).count(); + let region: SiblingGraph = SiblingGraph::new(self.hugr, parent); + let postorder = Topo::new(®ion.as_petgraph()); + let nodes_visited = postorder + .iter(®ion.as_petgraph()) + .filter(|n| *n != parent) + .count(); let node_count = self.hugr.children(parent).count(); if nodes_visited != node_count { return Err(ValidationError::NotADag { diff --git a/src/hugr/views.rs b/src/hugr/views.rs index 576342fef..f26bfb3e9 100644 --- a/src/hugr/views.rs +++ b/src/hugr/views.rs @@ -187,7 +187,7 @@ pub trait HugrView: sealed::HugrInternals { where Self: Sized, { - PetgraphWrapper::new(self) + PetgraphWrapper { hugr: self } } /// Return dot string showing underlying graph and hierarchy side by side. diff --git a/src/hugr/views/petgraph.rs b/src/hugr/views/petgraph.rs index 3a22e5262..751b3ac4f 100644 --- a/src/hugr/views/petgraph.rs +++ b/src/hugr/views/petgraph.rs @@ -14,17 +14,7 @@ use portgraph::NodeIndex; /// It can be used to apply petgraph's algorithms to a Hugr. #[derive(Debug, Clone, Copy)] pub struct PetgraphWrapper<'a, T> { - hugr: &'a T, -} - -impl<'a, T> PetgraphWrapper<'a, T> -where - T: HugrView, -{ - /// Wrap a HugrView in a PetgraphWrapper. - pub fn new(hugr: &'a T) -> Self { - Self { hugr } - } + pub(crate) hugr: &'a T, } impl<'a, T> pv::GraphBase for PetgraphWrapper<'a, T>