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: Export the core data structures to a model representation #1414

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

zrho
Copy link
Contributor

@zrho zrho commented Aug 12, 2024

This PR introduces a draft for the hugr-model data structures together with a function to export a Hugr into this format.

@zrho zrho changed the title Draft: Export to text format feat: Export to text format Aug 12, 2024
@zrho zrho changed the title feat: Export to text format feat: Export the core data structures to a model representation Aug 15, 2024
Copy link

codecov bot commented Aug 15, 2024

Codecov Report

Attention: Patch coverage is 0% with 266 lines in your changes missing coverage. Please review.

Project coverage is 86.44%. Comparing base (67f0668) to head (2d4b341).

Files Patch % Lines
hugr-core/src/export.rs 0.00% 266 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1414      +/-   ##
==========================================
- Coverage   87.55%   86.44%   -1.11%     
==========================================
  Files         119      120       +1     
  Lines       20781    21047     +266     
  Branches    18053    18319     +266     
==========================================
  Hits        18194    18194              
- Misses       1802     2068     +266     
  Partials      785      785              
Flag Coverage Δ
python 90.61% <ø> (ø)
rust 85.82% <0.00%> (-1.27%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

@acl-cqc acl-cqc left a comment

Choose a reason for hiding this comment

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

Thanks, Lukas - a few thoughts.

Presumably if we go with a system of "constraints", in order to express the expressible parts of binary compute_signature, we'll also need to use the hugr-model for serializaiton of extension sets...

hugr: &'a Hugr,
/// The module that is being built.
module: model::Module,
/// Mapping from ports to edge indices.
Copy link
Contributor

Choose a reason for hiding this comment

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

This makes sense after I've looked at get_edge_id but a bit more explanation here would help: this is where people will look for docs first!

hugr-core/src/export.rs Show resolved Hide resolved
TypeArg::BoundedNat { n } => ctx.make_term(model::Term::Nat(*n)),
TypeArg::String { arg } => ctx.make_term(model::Term::Str(arg.into())),
TypeArg::Sequence { elems } => {
// For now we assume that the sequence is meant to be a list.
Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, yah this is the tricky bit. I admit that none of the options seem great here.

  1. Add an ExtensionRegistry to the Context. This doesn't seem to bad, but (although I think necessary) is not sufficient - you also need to pass a TypeParam around, with recursive calls passing an inner TypeParam obtained by destructuring the outer one (panic if TypeParam and TypeArg doesn't correspond, as this should have been detected by validate). Two possible ways:
    • add a TypeParam to the Context, or
    • (I suspect better) define a new trait export-with-TypeParam
  2. Change TypeArg to distinguish between List and Tuple
  3. Change the model not to distinguish between List and Tuple.

(1.) works, has least fallout elsewhere, but is the greatest "yeuch" here. (2.) is most disruptive to existing code. I'll leave you to think about (3.)...

One could argue that if we aren't prepared to make such awkward format conversions as (1.), then the model has failed in its primary purpose of decoupling serialization format from core/Rust-struct representation

Copy link
Contributor

Choose a reason for hiding this comment

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

👍

@@ -0,0 +1,5 @@
//! The data model of the HUGR intermediate representation.
//! This crate defines data structures that capture the structure of a HUGR graph and
//! all its associated information in a form that can be stored on disk. The data structures
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: does anyone still use "disk"s nowadays? :)

perhaps something like "in a form designed for simple and efficient serialization, rather than traversal or modification"??? Or we could say this is for serialization, storage and interchange?

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 think it's used metaphorically, like the floppy disk symbol meaning "save" although it's most likely not being saved on a floppy disk.

/// The name of the term.
pub name: Symbol,
/// Arguments to the term.
pub args: TinyVec<[TermId; 3]>,
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar comment about triples

}

pub fn make_term(&mut self, term: model::Term) -> model::TermId {
let index = self.module.terms.len();
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this the place to do hash-consing?? (I.e. look for an existing Term that matches the suppiled, and if so then return that TermId rather than pushing)

Copy link
Member

Choose a reason for hiding this comment

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

It will be useful to associate ids with uses, i.e be able to trace problems back to the source by figuring out which instance of a term we're looking at. I'm looking in to hashconsing at serialisation time, and preserving all the ids that point to the same term. We can apply this to the model separately without changing the model behaviour I think.

Copy link
Member

Choose a reason for hiding this comment

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

have experimented with doing hashconsing here: e4ef7be
I think it's worthwhile.

//!
//! # Terms
//!
//! Terms form a meta language that is used to describe types, parameters and metadata that
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a design point that has probably been addressed elsewhere, but do we really want structured metadata like this?

Ok, I can see many use cases for metadata which does contain....Hugr-defined things. But not necessarily Terms - maybe Hugrs or NodeId's or other things. And, how is unstructured metadata represented? (I see that a MetaItem contains exactly one Term, I haven't seen the alternative - am I looking in the wrong place?)

Copy link
Member

Choose a reason for hiding this comment

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

@zrho made the point that if what we want is unstructured json you can just use the "string" metadata type always. I personally favour structure only enough structure in metadata to allow for reserved key names we can check for, and fully unstructured payloads.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you want unstructured metadata, you can still put it into a string. Structured metadata allows validation via typechecking.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah OK yes String is good, right


/// The type of the port.
///
/// This must be a term of type `Type`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Also, will be the same for all Ports with the same edge

/// Constraints on the parameters of the scheme.
///
/// All parameters are available as variables within the constraints.
/// The constraints must be terms of type `Constraint`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Right - I'm puzzled here. I don't see any enum Term variants that have type Constraint; I see only one for the type of Constraints, and I can't understand how that would be used. Am I missing something, looking at this the wrong way, or is this just WIP?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is all a big WIP.

Copy link
Collaborator

@aborgna-q aborgna-q left a comment

Choose a reason for hiding this comment

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

Some housekeeping needed when adding a new package:

  • Add a README. Just copy the template from the other crates.
  • Add this to release-plz.toml. We'll still need to do some manual deployment before the next hugr-core release, as release-plz does not have permission to create new packages.
    [[package]]
    name = "hugr-cli"
    release = true
    Also add it to the changelog_include for hugr
  • Add the new directory it to .github/change-filters.yml

edition.workspace = true
homepage.workspace = true
repository.workspace = true
license.workspace = true
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
license.workspace = true
license.workspace = true
readme = "README.md"
documentation = "https://docs.rs/hugr-model/"
description = "Serializable model for Quantinuum's HUGR"
keywords = ["Quantum", "Quantinuum"]
categories = ["compilers"]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants