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

docs: Add builder module docs + example #853

Merged
merged 3 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
87 changes: 86 additions & 1 deletion src/builder.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,89 @@
//! Tools for building valid HUGRs.
//! Utilities for building valid HUGRs.
//!
//! This module includes various tools for building HUGRs.
//!
//! Depending on the type of HUGR you want to build, you may want to use one of
//! the following builders:
//!
//! - [ModuleBuilder]: For building a module with function declarations and
//! definitions.
//! - [DFGBuilder]: For building a Dataflow Graph.
//! - [FunctionBuilder]: A `DFGBuilder` specialised in defining functions with a
//! Dataflow Graph.
//! - [CFGBuilder]: For building a Control Flow Graph.
//! - [ConditionalBuilder]: For building a Conditional node.
//! - [TailLoopBuilder]: For building a TailLoop node.
//!
//! Additionally, the [CircuitBuilder] provides an alternative to the
//! [DFGBuilder] when working with circuits, some inputs of operations directly
//! correspond to some outputs and operations can be directly appended using
//! unit indices.
//!
//! # Example
//!
//! The following example shows how to build a simple HUGR module with a generic
//! dataflow graph, a control flow graph, and a circuit.
//!
//! ```rust
//! # use hugr::Hugr;
//! # use hugr::builder::{BuildError, BuildHandle, Container, DFGBuilder, Dataflow, DataflowHugr, ModuleBuilder, DataflowSubContainer, HugrBuilder};
//! use hugr::extension::prelude::BOOL_T;
//! use hugr::std_extensions::logic::{NotOp, LOGIC_REG};
//! use hugr::types::FunctionType;
//!
//! # fn doctest() -> Result<(), BuildError> {
//! let hugr = {
//! let mut module_builder = ModuleBuilder::new();
//!
//! // Add a `main` function with signature `bool -> bool`.
//! //
//! // This block returns a handle to the built function.
//! let _dfg_handle = {
//! let mut dfg = module_builder.define_function(
//! "main",
//! FunctionType::new(vec![BOOL_T], vec![BOOL_T]).into(),
//! )?;
//!
//! // Get the wires from the function inputs.
//! let [w] = dfg.input_wires_arr();
//!
//! // Add an operation connected to the input wire, and get the new dangling wires.
//! let [w] = dfg.add_dataflow_op(NotOp, [w])?.outputs_arr();
//!
//! // Finish the function, connecting some wires to the output.
//! dfg.finish_with_outputs([w])
//! }?;
//!
//! // Add a similar function, using the circuit builder interface.
//! let _circuit_handle = {
//! let mut dfg = module_builder.define_function(
//! "circuit",
//! FunctionType::new(vec![BOOL_T, BOOL_T], vec![BOOL_T, BOOL_T]).into(),
//! )?;
//! let mut circuit = dfg.as_circuit(dfg.input_wires());
//!
//! // Add multiple operations, indicating only the wire index.
//! circuit.append(NotOp, [0])?.append(NotOp, [1])?;
//!
//! // Finish the circuit, and return the dfg after connecting its outputs.
//! let outputs = circuit.finish();
//! dfg.finish_with_outputs(outputs)
//! }?;
//!
//! // Finish building the hugr, consuming the builder.
//! //
//! // Requires a registry with all the extensions used in the module.
//! module_builder.finish_hugr(&LOGIC_REG)
//! }?;
//!
//! // The built HUGR is always valid.
//! hugr.validate(&LOGIC_REG).unwrap_or_else(|e| {
//! panic!("Hugr validation failed: {e}");
//! });
//! # Ok(())
//! # }
//! # doctest().unwrap();
//! ```
//!
use thiserror::Error;

Expand Down
2 changes: 1 addition & 1 deletion src/builder/build_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ pub trait Dataflow: Container {

/// For the vector of `wires`, produce a `CircuitBuilder` where ops can be
/// added using indices in to the vector.
fn as_circuit(&mut self, wires: Vec<Wire>) -> CircuitBuilder<Self> {
fn as_circuit(&mut self, wires: impl IntoIterator<Item = Wire>) -> CircuitBuilder<Self> {
CircuitBuilder::new(wires, self)
}
}
Expand Down
9 changes: 6 additions & 3 deletions src/builder/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,11 @@ pub enum CircuitBuildError {
impl<'a, T: Dataflow + ?Sized> CircuitBuilder<'a, T> {
/// Construct a new [`CircuitBuilder`] from a vector of incoming wires and the
/// builder for the graph
pub fn new(wires: Vec<Wire>, builder: &'a mut T) -> Self {
Self { wires, builder }
pub fn new(wires: impl IntoIterator<Item = Wire>, builder: &'a mut T) -> Self {
Self {
wires: wires.into_iter().collect(),
builder,
}
}

/// Number of wires tracked, upper bound of valid wire indices
Expand Down Expand Up @@ -188,7 +191,7 @@ mod test {
|mut f_build| {
let [q0, q1, angle]: [Wire; 3] = f_build.input_wires_arr();

let mut linear = f_build.as_circuit(vec![q0, q1]);
let mut linear = f_build.as_circuit([q0, q1]);

let measure_out = linear
.append(cx_gate(), [0, 1])?
Expand Down
2 changes: 1 addition & 1 deletion src/hugr/rewrite/simple_replace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ pub(in crate::hugr::rewrite) mod test {
fn test_replace_cx_cross() {
let q_row: Vec<Type> = vec![QB, QB];
let mut builder = DFGBuilder::new(FunctionType::new(q_row.clone(), q_row)).unwrap();
let mut circ = builder.as_circuit(builder.input_wires().collect());
let mut circ = builder.as_circuit(builder.input_wires());
circ.append(cx_gate(), [0, 1]).unwrap();
circ.append(cx_gate(), [1, 0]).unwrap();
let wires = circ.finish();
Expand Down