Skip to content
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
5 changes: 3 additions & 2 deletions hugr-core/src/hugr/persistent/parents_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
extension::ExtensionRegistry,
hugr::{
internal::HugrInternals,
views::{ExtractionResult, render::RenderConfig},
views::{ExtractionResult, render},
},
ops::OpType,
};
Expand Down Expand Up @@ -196,7 +196,8 @@ impl HugrView for ParentsView<'_> {
unimplemented!()
}

fn mermaid_string_with_config(&self, _config: RenderConfig<Self::Node>) -> String {
#[allow(deprecated)]
fn mermaid_string_with_config(&self, _config: render::RenderConfig<Self::Node>) -> String {
unimplemented!()
}

Expand Down
95 changes: 43 additions & 52 deletions hugr-core/src/hugr/persistent/trait_impls.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::HashMap;

use itertools::{Either, Itertools};
use portgraph::render::{DotFormat, MermaidFormat};
use portgraph::render::MermaidFormat;

use crate::{
Direction, Hugr, HugrView, Node, Port,
Expand All @@ -10,7 +10,7 @@ use crate::{
internal::HugrInternals,
views::{
ExtractionResult,
render::{self, RenderConfig},
render::{self, MermaidFormatter, NodeLabel},
},
},
};
Expand Down Expand Up @@ -242,35 +242,49 @@ impl HugrView for PersistentHugr {
.flat_map(move |port| self.linked_ports(node, port).map(|(opp_node, _)| opp_node))
}

fn mermaid_string(&self) -> String {
self.mermaid_string_with_config(RenderConfig {
node_indices: true,
port_offsets_in_edges: true,
type_labels_in_edges: true,
entrypoint: Some(self.entrypoint()),
})
#[allow(deprecated)]
fn mermaid_string_with_config(&self, config: render::RenderConfig<Self::Node>) -> String {
self.mermaid_string_with_formatter(MermaidFormatter::from_render_config(config, self))
}

fn mermaid_string_with_config(&self, config: RenderConfig<Self::Node>) -> String {
fn mermaid_string_with_formatter(&self, formatter: MermaidFormatter<Self>) -> String {
// Extract a concrete HUGR for displaying
let (hugr, node_map) = self.apply_all();

// Map config accordingly
let config = RenderConfig {
entrypoint: config.entrypoint.map(|n| node_map[&n]),
node_indices: config.node_indices,
port_offsets_in_edges: config.port_offsets_in_edges,
type_labels_in_edges: config.type_labels_in_edges,
};

// Render the extracted HUGR but map the node indices back to the
// original patch node IDs
let inv_node_map: HashMap<_, _> = node_map.into_iter().map(|(k, v)| (v, k)).collect();
let fmt_node_index = |n: portgraph::NodeIndex| format!("{:?}", inv_node_map[&n.into()]);
let entrypoint = formatter.entrypoint().map(|n| node_map[&n]);
let node_labels = match formatter.node_labels() {
NodeLabel::None => NodeLabel::None,
NodeLabel::Numeric => {
// replace node labels with patch node IDs
let node_labels_map: HashMap<_, _> = node_map
.into_iter()
.map(|(k, v)| (v, format!("{:?}", k)))
.collect();
NodeLabel::Custom(node_labels_map)
}
NodeLabel::Custom(labels) => {
// rekey labels to the extracted HUGR node IDs
let labels = labels
.iter()
.map(|(k, v)| (node_map[k], v.clone()))
.collect();
NodeLabel::Custom(labels)
}
};

// Map config accordingly
let config = MermaidFormatter::new(&hugr)
.with_entrypoint(entrypoint)
.with_node_labels(node_labels)
.with_port_offsets(formatter.port_offsets())
.with_type_labels(formatter.type_labels());

hugr.graph
.mermaid_format()
.with_hierarchy(&hugr.hierarchy)
.with_node_style(render::node_style(&hugr, config, fmt_node_index))
.with_node_style(render::node_style(&hugr, config.clone()))
.with_edge_style(render::edge_style(&hugr, config))
.finish()
}
Expand All @@ -279,26 +293,7 @@ impl HugrView for PersistentHugr {
where
Self: Sized,
{
// Extract a concrete HUGR for displaying
let (hugr, node_map) = self.apply_all();

// Map config accordingly
let config = RenderConfig {
entrypoint: Some(node_map[&self.entrypoint()]),
..RenderConfig::default()
};

// Render the extracted HUGR but map the node indices back to the
// original patch node IDs
let inv_node_map: HashMap<_, _> = node_map.into_iter().map(|(k, v)| (v, k)).collect();
let fmt_node_index = |n: portgraph::NodeIndex| format!("{:?}", inv_node_map[&n.into()]);
hugr.graph
.dot_format()
.with_hierarchy(&hugr.hierarchy)
.with_node_style(render::node_style(&hugr, config, fmt_node_index))
.with_port_style(render::port_style(&hugr, config))
.with_edge_style(render::edge_style(&hugr, config))
.finish()
unimplemented!("use mermaid_string instead")
}

fn extensions(&self) -> &crate::extension::ExtensionRegistry {
Expand Down Expand Up @@ -351,19 +346,15 @@ mod tests {
.try_extract_hugr([commit1, commit2, commit4])
.unwrap();

let mermaid_str = hugr.mermaid_string_with_config(RenderConfig {
node_indices: false,
entrypoint: Some(hugr.entrypoint()),
..Default::default()
});
let mermaid_str = hugr
.mermaid_format()
.with_node_labels(NodeLabel::None)
.finish();
let extracted_hugr = hugr.to_hugr();
let exp_str = extracted_hugr
.mermaid_string_with_config(RenderConfig {
node_indices: false,
entrypoint: Some(extracted_hugr.entrypoint()),
..Default::default()
})
.to_string();
.mermaid_format()
.with_node_labels(NodeLabel::None)
.finish();

assert_eq!(mermaid_str, exp_str);
}
Expand Down
77 changes: 58 additions & 19 deletions hugr-core/src/hugr/views.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ use std::borrow::Cow;
use std::collections::HashMap;

pub use self::petgraph::PetgraphWrapper;
use self::render::RenderConfig;
#[allow(deprecated)]
use self::render::{MermaidFormatter, RenderConfig};
pub use rerooted::Rerooted;
pub use root_checked::{InvalidSignature, RootCheckable, RootChecked, check_tag};
pub use sibling_subgraph::SiblingSubgraph;
Expand Down Expand Up @@ -385,7 +386,9 @@ pub trait HugrView: HugrInternals {
///
/// For a more detailed representation, use the [`HugrView::dot_string`]
/// format instead.
fn mermaid_string(&self) -> String;
fn mermaid_string(&self) -> String {
self.mermaid_string_with_formatter(self.mermaid_format())
}

/// Return the mermaid representation of the underlying hierarchical graph.
///
Expand All @@ -394,8 +397,51 @@ pub trait HugrView: HugrInternals {
///
/// For a more detailed representation, use the [`HugrView::dot_string`]
/// format instead.
#[deprecated(note = "Use `mermaid_format` instead")]
#[allow(deprecated)]
fn mermaid_string_with_config(&self, config: RenderConfig<Self::Node>) -> String;

/// Return the mermaid representation of the underlying hierarchical graph
/// according to the provided [`MermaidFormatter`] formatting options.
///
/// The hierarchy is represented using subgraphs. Edges are labelled with
/// their source and target ports.
///
/// For a more detailed representation, use the [`HugrView::dot_string`]
/// format instead.
///
/// ## Deprecation of [`RenderConfig`]
/// While the deprecated [HugrView::mermaid_string_with_config] exists, this
/// will by default try to convert the formatter options to a [`RenderConfig`],
/// but this may panic if the configuration is not supported. Users are
/// encouraged to provide an implementation of this method overriding the default
/// and no longer rely on [HugrView::mermaid_string_with_config].
fn mermaid_string_with_formatter(&self, formatter: MermaidFormatter<Self>) -> String {
#[allow(deprecated)]
let config = match RenderConfig::try_from(formatter) {
Ok(config) => config,
Err(e) => {
panic!("Unsupported format option: {}", e);
}
};
#[allow(deprecated)]
self.mermaid_string_with_config(config)
}

/// Construct a mermaid representation of the underlying hierarchical graph.
///
/// Options can be set on the returned [`MermaidFormatter`] struct, before
/// generating the String with [`MermaidFormatter::finish`].
///
/// The hierarchy is represented using subgraphs. Edges are labelled with
/// their source and target ports.
///
/// For a more detailed representation, use the [`HugrView::dot_string`]
/// format instead.
fn mermaid_format(&self) -> MermaidFormatter<Self> {
MermaidFormatter::new(self).with_entrypoint(self.entrypoint())
}

/// Return the graphviz representation of the underlying graph and hierarchy side by side.
///
/// For a simpler representation, use the [`HugrView::mermaid_string`] format instead.
Expand Down Expand Up @@ -629,38 +675,31 @@ impl HugrView for Hugr {
self.graph.all_neighbours(node.into_portgraph()).map_into()
}

fn mermaid_string(&self) -> String {
self.mermaid_string_with_config(RenderConfig {
node_indices: true,
port_offsets_in_edges: true,
type_labels_in_edges: true,
entrypoint: Some(self.entrypoint()),
})
#[allow(deprecated)]
fn mermaid_string_with_config(&self, config: RenderConfig) -> String {
self.mermaid_string_with_formatter(MermaidFormatter::from_render_config(config, self))
}

fn mermaid_string_with_config(&self, config: RenderConfig) -> String {
fn mermaid_string_with_formatter(&self, formatter: MermaidFormatter<Self>) -> String {
self.graph
.mermaid_format()
.with_hierarchy(&self.hierarchy)
.with_node_style(render::node_style(self, config, |n| n.index().to_string()))
.with_edge_style(render::edge_style(self, config))
.with_node_style(render::node_style(self, formatter.clone()))
.with_edge_style(render::edge_style(self, formatter))
.finish()
}

fn dot_string(&self) -> String
where
Self: Sized,
{
let config = RenderConfig {
entrypoint: Some(self.entrypoint()),
..RenderConfig::default()
};
let formatter = MermaidFormatter::new(self).with_entrypoint(self.entrypoint());
self.graph
.dot_format()
.with_hierarchy(&self.hierarchy)
.with_node_style(render::node_style(self, config, |n| n.index().to_string()))
.with_port_style(render::port_style(self, config))
.with_edge_style(render::edge_style(self, config))
.with_node_style(render::node_style(self, formatter.clone()))
.with_port_style(render::port_style(self))
.with_edge_style(render::edge_style(self, formatter))
.finish()
}

Expand Down
2 changes: 2 additions & 0 deletions hugr-core/src/hugr/views/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ macro_rules! hugr_view_methods {
fn neighbours(&self, node: Self::Node, dir: crate::Direction) -> impl Iterator<Item = Self::Node> + Clone;
fn all_neighbours(&self, node: Self::Node) -> impl Iterator<Item = Self::Node> + Clone;
fn mermaid_string(&self) -> String;
#[allow(deprecated)]
fn mermaid_string_with_config(&self, config: crate::hugr::views::render::RenderConfig<Self::Node>) -> String;
fn mermaid_string_with_formatter(&self, #[into] formatter: crate::hugr::views::render::MermaidFormatter<Self>) -> String;
fn dot_string(&self) -> String;
fn static_source(&self, node: Self::Node) -> Option<Self::Node>;
fn static_targets(&self, node: Self::Node) -> Option<impl Iterator<Item = (Self::Node, crate::IncomingPort)>>;
Expand Down
Loading
Loading