Skip to content

Sketch out resources + extension mechanism, update CustomType #186

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

Merged
merged 63 commits into from
Jul 7, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
cb7d892
Remove unused EdgeKind::Resource
acl-cqc Jun 20, 2023
2e46435
Add src/types/type_arg.rs; declare HInt = u8; update extension spec w…
acl-cqc Jun 20, 2023
5c38679
Move OpDef into resource.rs
acl-cqc Jun 20, 2023
768186f
TypeParam
acl-cqc Jun 20, 2023
6a791d0
TypeParam can be a ResourceSet
acl-cqc Jun 20, 2023
be533e8
Remove Eq for LeafOp and from various Errors entailed by that
acl-cqc Jun 20, 2023
6f32b4a
Rewrite OpDef; OpaqueOp wraps OpDef; remove one CustomOp
acl-cqc Jun 20, 2023
94270ab
OpaqueOp -> ResourceOp
acl-cqc Jun 20, 2023
9d975be
Separate CustomOp(ExternalOp) with Rc<OpDef> from UnknownOp<OpaqueOp>
acl-cqc Jun 20, 2023
a5aab3c
OpaqueOp Signature in an Option
acl-cqc Jun 21, 2023
32789f8
ExternalOp::eq compare args, don't impl Eq
acl-cqc Jun 21, 2023
c13509e
Remove old CustomOp, now unused
acl-cqc Jun 21, 2023
fd54ace
Flat two-level namespacing - Resource + op-name
acl-cqc Jun 21, 2023
cfcc55e
Implement resolve_external_ops; Resource contains Rc<OpDef>, serializ…
acl-cqc Jun 21, 2023
d9bb37f
Merge origin/main into sketch/resources, make LeafOf::UnknownOp a struct
acl-cqc Jun 21, 2023
a1ebf02
Make CustomOp also a struct
acl-cqc Jun 21, 2023
bd0f5b1
make tuple variants again and fix serialization recursion
ss2165 Jun 21, 2023
0aabce2
Merge 'origin/main' into HEAD and remove HInt
acl-cqc Jun 21, 2023
b94c1d2
Combine LeafOp::{CustomOp,UnknownOp}, make ExternalOp an enum, fix serde
acl-cqc Jun 21, 2023
ab6b9dd
Merge remote-tracking branch 'origin/main' into sketch/resources; Rc-…
acl-cqc Jun 26, 2023
e35ef58
Various learnings from clippy
acl-cqc Jun 26, 2023
67f2a0a
TypeParam allow any ClassicType; TypeArgValue use ConstValue
acl-cqc Jun 26, 2023
fe9dcef
{type_arg=>op_param}::{TypeParam=>OpParam,TypeArgValue=>OpArg}
acl-cqc Jun 26, 2023
01251de
Add back type_param::{TypeParam,TypeArg}; use in TypeDef + split from…
acl-cqc Jun 26, 2023
a4b0170
Remove OpArg/OpParam, just use TypeArg/TypeParam
acl-cqc Jun 26, 2023
efe7fab
Update CustomType
acl-cqc Jun 26, 2023
7d7184f
RestoreEq-ness for ops, including ExternalOp
acl-cqc Jun 26, 2023
da9bd1f
tweaks
acl-cqc Jun 27, 2023
8b757c9
Cache description in OpaqueOp
acl-cqc Jun 27, 2023
dd988f6
Don't serialize OpaqueOp description; publicize OpaqueOp::new
acl-cqc Jun 27, 2023
bc44593
Revert spec wrt. args - "Int" but no "Opaque"
acl-cqc Jun 27, 2023
c551a8e
fix spec bracketting
acl-cqc Jun 27, 2023
b6f4edc
TODO in serializing OpDef's already done
acl-cqc Jun 27, 2023
36a9c2f
Serialize node signature onlyfor customfuncs
acl-cqc Jun 27, 2023
d44db52
CustomType c'tor: take Into<SmolStr>; add const fn new_simple w/out p…
acl-cqc Jun 30, 2023
d298e17
Merge 'origin/main' into sketch/resources, update OpaqueOp::new
acl-cqc Jun 30, 2023
9dfc773
Reinstate params(); hide id; remove obsolete TODO
acl-cqc Jul 3, 2023
62f14b6
Merge remote-tracking branch 'origin/main' into sketch/resources
acl-cqc Jul 3, 2023
27b1d32
Two-stage into() is easier using .custom_type()
acl-cqc Jul 3, 2023
039bd9d
Comment ExternalOp::Opaque
acl-cqc Jul 3, 2023
4dd0c8b
ExternalOp::Resource Break out struct ResourceOp, cache Signature
acl-cqc Jul 3, 2023
600766b
qualify_name: '/' -> '.'
acl-cqc Jul 3, 2023
b5b7620
clippy
acl-cqc Jul 3, 2023
8cc4815
Serialize OpaqueOp::description
acl-cqc Jul 3, 2023
cbeadb7
Serde serialization: enable features=["rc"]
acl-cqc Jul 4, 2023
bcab91d
Use &[TypeArg] not &Vec<TypeArg>
acl-cqc Jul 4, 2023
2b79270
Some docs
acl-cqc Jul 5, 2023
0b13226
OpDef::signature -> compute_signature, remove obsolete comment
acl-cqc Jul 5, 2023
a3a4b45
Add ResourceOp::new
acl-cqc Jul 5, 2023
9d56a53
Some more review comments
acl-cqc Jul 5, 2023
52a5534
check_arg => check_type_arg, TypeArgError
acl-cqc Jul 6, 2023
8ca2b7d
add CustomOpError with which resolve_extension_ops can fail
acl-cqc Jul 6, 2023
c0e74eb
Resource and TypeDef are Clone
acl-cqc Jul 6, 2023
eb6ee7b
LowerFunc: remove None, wrap in Option
acl-cqc Jul 6, 2023
08311b8
And doc SignatureFunc
acl-cqc Jul 6, 2023
d20f304
ops pub mod custom; missing docs; pass description into OpaqueOp::new
acl-cqc Jul 6, 2023
39eb159
Merge remote-tracking branch 'origin/main' into sketch/resources
acl-cqc Jul 7, 2023
0d34eee
clippy
acl-cqc Jul 7, 2023
8be5c30
(WIP/trial) Rename check-coverage pass
acl-cqc Jul 7, 2023
b556674
pub LowerFunc; single with_lowering method
acl-cqc Jul 7, 2023
d7bade1
fmt, doc
acl-cqc Jul 7, 2023
564a33d
fix doc
acl-cqc Jul 7, 2023
6abce77
Allow multiple LowerFunc's
acl-cqc Jul 7, 2023
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
35 changes: 24 additions & 11 deletions specification/hugr.md
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ resources:
types:
- name: QubitVector
# Opaque types can take type arguments, with specified names
args: [["size", u64]]
args: [["size", Int]]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed all the u64s to Int to reflect what's in ClassicType and TypeParam - and the general policy that the difference between signed and unsigned is in the operations, not the bits flowing around the wires of the Hugr.

However, there is an argument that the specification here is not just about the (signedness-independent) serialized form of the parameters, but also an instruction as to how int constants should be parsed / treated by the frontend. If this is left as Int, then some other data somewhere needs to tell any frontend that the value should be unsigned...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any cases where we actually want signed semantics in the uses of Int in the core, or should we just say that it's always unsigned (and maybe rename to Nat or something)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I admit I haven't seen a use for a signed int in a type yet.

operations:
- name: measure
description: "measure a qubit"
Expand Down Expand Up @@ -741,9 +741,9 @@ resources:
- name: MatMul
description: "Multiply matrices of statically-known size"
args: # per-node values passed to type-scheme-interpreter and used in signature
- i: U64
- j: U64
- k: U64
- i: Int
- j: Int
- k: Int
signature:
inputs: [["a", Array<i>(Array<j>(F64))], ["b", Array<j>(Array<k>(F64))]]
outputs: [[null, Array<i>(Array<k>(F64))]]
Expand All @@ -752,7 +752,7 @@ resources:
- name: max_float
description: "Variable number of inputs"
args:
- n: U64
- n: Int
signature:
# Where an element of a signature has three subelements, the third is the number of repeats
inputs: [[null, F64, n]] # (defaulting to 1 if omitted)
Expand All @@ -761,19 +761,30 @@ resources:
description: "Concatenate two arrays. Resource provides a compute_signature implementation."
args:
- t: Type # Classic or Quantum
- i: U64
- j: U64
- i: Int
- j: Int
# inputs could be: Array<i>(t), Array<j>(t)
# outputs would be, in principle: Array<i+j>(t)
# - but default type scheme interpreter does not support such addition
# Hence, no signature block => will look up a compute_signature in registry.
- name: GraphOp
description: "Involves running an argument Graph. E.g. run it some variable number of times."
args:
- r: ResourceSet
signature:
inputs: [[null, Graph[r](Int -> Int)], ["arg", Int]
outputs: [[null, Int]]
resources: r # Indicates that running this operation also invokes resources r
```

The declaration of the `args` uses a language that is a distinct, simplified
form of the [Type System](#type-system) - writing terminals that appear in the YAML in quotes,
the value of each member of `args` is given by the following production:
```
TypeParam ::= "Type" | "ClassicType" | "F64" | "U64" | "I64" | "Opaque"(name, ...) | "List"(TypeParam)
TypeParam ::= "Type" | "ClassicType"
| "F64" | "Int"
| "Opaque"(name, ...) | "List"(TypeParam)
| "ResourceSet"
```

**Implementation note** Reading this format into Rust is made easy by `serde` and
Expand All @@ -782,9 +793,11 @@ Serialization section). It is also trivial to serialize these
definitions in to the overall HUGR serialization format.

Note the only required fields are `name` and `description`. `signature` is optional, but if present
must have children `inputs` and `outputs`, each lists. The optional `misc` field is used for arbitrary
YAML, which is read in as-is and passed to compiler passes and (if no `signature` is present) the
`compute_signature` function; e.g. a pass can use the `basis` information to perform commutation.
must have children `inputs` and `outputs`, each lists, and may have `resources`.

The optional `misc` field is used for arbitrary YAML, which is read in as-is and passed to compiler
passes and (if no `signature` is present) the`compute_signature` function; e.g. a pass can use the `basis` information to perform commutation.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the conclusion of the discussion was that data in misc would not be used to compute signature?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC we said that if you wanted statically-known floats then you could put that in misc if you didn't want Static wires to every node. But I don't recall saying that misc couldn't affect signature. misc is a fairly generic mechanism to say "I want to reuse the same (Rust) code for different ops, I can express the difference with data" - I don't see why that shouldn't include/allow reusing Rust code that computes type signatures.


The optional `args` field can be used to specify the types of static+const arguments to each operation
---for example the matrix needed to define an SU2 operation. If `args` are not specified
then it is assumed empty.
Expand Down
2 changes: 1 addition & 1 deletion src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub use conditional::{CaseBuilder, ConditionalBuilder};
mod circuit_builder;
pub use circuit_builder::{AppendWire, CircuitBuilder};

#[derive(Debug, Clone, PartialEq, Eq, Error)]
#[derive(Debug, Clone, PartialEq, Error)]
/// Error while building the HUGR.
pub enum BuildError {
/// The constructed HUGR is invalid.
Expand Down
39 changes: 21 additions & 18 deletions src/extensions/rotation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ use std::ops::{Add, Div, Mul, Neg, Sub};
use cgmath::num_traits::ToPrimitive;
use num_rational::Rational64;
use smol_str::SmolStr;
use std::collections::HashMap;

#[cfg(feature = "pyo3")]
use pyo3::prelude::*;

use crate::ops::constant::CustomConst;
use crate::ops::CustomOp;
use crate::resource::ResourceSet;
use crate::types::{ClassicType, CustomType, Signature, SimpleType, TypeRow};
use crate::resource::{CustomSignatureFunc, OpDef, ResourceSet, SignatureError};
use crate::types::{type_arg::TypeArgValue, ClassicType, CustomType, SimpleType, TypeRow};
use crate::Resource;

pub const fn resource_id() -> SmolStr {
Expand All @@ -27,7 +27,13 @@ pub fn resource() -> Resource {
resource.add_type(Type::Angle.into());
resource.add_type(Type::Quaternion.into());

resource.add_opaque_op(AngleAdd.into());
resource.add_op(OpDef::new_with_custom_sig(
"AngleAdd".into(),
"".into(),
vec![],
HashMap::default(),
AngleAdd,
));
resource
}

Expand Down Expand Up @@ -90,20 +96,17 @@ impl CustomConst for Constant {
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct AngleAdd;

#[typetag::serde]
impl CustomOp for AngleAdd {
fn name(&self) -> SmolStr {
"AngleAdd".into()
}

fn signature(&self) -> Signature {
// TODO: Is there a way to make this static? The Opaque simple type requires initializing a Box...
Signature::new_linear(vec![SimpleType::Classic(Type::Angle.classic_type())])
}

fn resources(&self) -> &ResourceSet {
// TODO: Don't return a reference? We need to initialize the resource set.
todo!()
/// When we have a YAML type-scheme interpreter, we'll be able to use that;
/// there is no need for a binary compute_signature for a case this simple.
impl CustomSignatureFunc for AngleAdd {
fn compute_signature(
&self,
_name: &SmolStr,
_arg_values: &Vec<TypeArgValue>,
_misc: &HashMap<String, serde_yaml::Value>,
) -> Result<(TypeRow, TypeRow, ResourceSet), SignatureError> {
let t: TypeRow = vec![SimpleType::Classic(Type::Angle.classic_type())].into();
Ok((t.clone(), t, ResourceSet::default()))
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/hugr/serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ struct SerHugrV0 {
}

/// Errors that can occur while serializing a HUGR.
#[derive(Debug, Clone, PartialEq, Eq, Error)]
#[derive(Debug, Clone, PartialEq, Error)]
pub enum HUGRSerializationError {
/// Unexpected hierarchy error.
#[error("Failed to attach child to parent: {0:?}.")]
Expand Down
4 changes: 2 additions & 2 deletions src/hugr/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ impl<'a> ValidationContext<'a> {
}

/// Errors that can occur while validating a Hugr.
#[derive(Debug, Clone, PartialEq, Eq, Error)]
#[derive(Debug, Clone, PartialEq, Error)]
#[allow(missing_docs)]
pub enum ValidationError {
/// The root node of the Hugr is not a root in the hierarchy.
Expand Down Expand Up @@ -753,7 +753,7 @@ pub enum ValidationError {
}

/// Errors related to the inter-graph edge validations.
#[derive(Debug, Clone, PartialEq, Eq, Error)]
#[derive(Debug, Clone, PartialEq, Error)]
#[allow(missing_docs)]
pub enum InterGraphEdgeError {
/// Inter-Graph edges can only carry classical data.
Expand Down
6 changes: 2 additions & 4 deletions src/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

pub mod constant;
pub mod controlflow;
pub mod custom;
mod custom;
pub mod dataflow;
pub mod handle;
pub mod leaf;
Expand All @@ -12,8 +12,6 @@ pub mod validate;
use crate::types::{EdgeKind, Signature, SignatureDescription};
use crate::{Direction, Port};

pub use custom::{CustomOp, OpDef, OpaqueOp};

use portgraph::NodeIndex;
use smol_str::SmolStr;

Expand All @@ -27,7 +25,7 @@ pub use leaf::LeafOp;
pub use module::{AliasDeclare, AliasDef, Declare, Def, Module};

#[enum_dispatch(OpTrait, OpName, ValidateOp)]
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
/// The concrete operation types for a node in the HUGR.
// TODO: Link the NodeHandles to the OpType.
#[non_exhaustive]
Expand Down
Loading