Replies: 3 comments 3 replies
-
Alternative (?)Resurrect the idea of type Module = Hugr<RootModule>;
type Dfg = Hugr<RootDfg>; etc. Conversion to/from model is only implemented on This convention would need to be re-encoded in the python, but i don't think that's too bad because the actual number of roots is constrained nicely. I'm not sure whether this actually meets your requirements so let me know. |
Beta Was this translation helpful? Give feedback.
-
I am not sure I really follow what the portgraph change does - is the portgraph-root an ancestor of the hugr/dfg-root, or what? Can you give examples of how allowing the two roots to be different address which use cases? |
Beta Was this translation helpful? Give feedback.
-
So without arguing about the portgraph change - I think the uses we have for non-module-rooted Hugrs ATM are good and it would be nice to continue supporting them. I am less clear why packages and hugr-model need the Hugr to be Module-rooted. Bearing in mind all declarations (FuncDecl, FuncDefn, etc., perhaps OpDecl in future) are scoped, they could go anywhere, even inside another root. So the fact that guppy happens to produce a Module is happenstance. Is it not possible to extend hugr-model to support non-Module-root? And then if OpDecl happens (extensions are declared inside Hugrs rather than outside) then that resolves the package problem too. A lot of "if"s there. But in the meantime, Seyon's suggestion of parametrization by root type seems good, would that fix things for now?? |
Beta Was this translation helpful? Give feedback.
-
This proposal tries to simplify the split between how we use runtime hugrs internally here and in tket2 vs how they are serialized, bundled as packages, and emitted by guppy. See #1554.
TLDR: Splitting the hugr root from the portgraph hierarchy root would make the code more straightforward.
The state of things
We seem to be moving towards only supporting module-rooted hugrs;
hugr-model
is designed with this in mind. With the current impl, non-module hugrs will need to be wrapped in a module before being serialized.This however clashes with how we use hugr internally,
hugr-py
andhugr-rs
can define hugrs with any kind of root.HugrView
interface, which can have arbitrary root types.We don't want the serialization format and the in-memory one to diverge semantically, so if we can only store module-rooted graphs then the runtime values should follow suit.
Module-hugrs + region pointers?
If we go with restricting the hugrs to always contain a module at the top, then we should adapt the rest of the code to work with that.
This could be a module-hugr plus a pointer to a node, but we then have to decide what happens with extraneous nodes and edges. It could be a way to—say— replace some nodes with a call to a newly defined function in the module, but that may be outside the scope
SimpleReplace
.All in all, I think this could work for our usecases. It also has good implications in terms of runtime...
Module-hugrs structs + region pointers?
Lets say we split the
root
field in the hugr definition,With this, we can still define e.g. "Dfg-hugr"s as ones where the
root
points to a DFG, independently of what the portgraph root is.This is similar to
DescendantView
, except that:HugrView::node_count
,nodes
,linked_ports
, etc. all take into account the external nodes and edges.HugrMut
, it can be mutated.The current
HugrView
definition requires all nodes to be descendants of theroot
, soDescendantView
has to check whether a node is in the hierarchy tree on each operation.The
DescendantView
filtering is implemented at theportgraph
level with aNodeFiltered
graph adapter which computes the nodes that should be included on-the-fly by traversing the hierarchy and storing them in aHashMap
for caching. This hashmap gets thrown away on any hugr mutation introduces contention between concurrent accesses.The restriction of not containing out-of-tree nodes in a
HugrView
is due to keeping reachability from the root to all nodes. Splitting the portgraph root from the view root means we can relax that restriction.Doing away with the node filtering should have a big impact on performance.
Implementation guide
🦀 rust:
hugr-rs::Hugr
: Split theportgraph_root
from the hugr'sroot
node pointer as described above.hugr-rs::HugrView
: No code changes required, but relax the constraint of only including descendant nodes from the root. The hierarchical root can be accessed viaView::base_hugr
hugr-rs::HugrMut
: Mostly unchanged.insert_hugr
needs to be redefined. Most current uses should callinsert_from_view
instead (maybe with an owned variant?).SimpleReplacement
: The replacement is still restricted to dfg-hugrs (or function defs). Possibly we should add the restriction that the root is a direct definition in the module, and no other definitions are present.DescendantsGraph
could be removed entirely, and replaced with the more flexible&Hugr
(or even mutable refs).SiblingGraph
was there to provide more performant filtered views when children were not required. We may be able to remove it too.DfgBuilder
. Should not require other changes.root
.- Loading packages would be simplified too, we could drop the patchy conversion between hugrs and module-rooted packages we do currently.
🐍 python:
Hugr
: Add amodule_root
parameterinsert_hugr
will require some update to only insert the descendants nodes.DfgBase
builder.NodePointer
. That would either need inheritance, or redefiningNodePointer
as a protocol.📜
hugr-model
:Alternatives
We could still allow non-module hugrs in the in-memory representation.
Serialization roundtrips would need some metadata to know when to wrap/unwrap the non-module nodes (and some way to encode the root node id in a serialization-stable way).
We could define some extra layer on top of a hugr to accomodate the "hugr+pointer" structures curretly required by tket2, guppy, and packages. This would be similar to what's proposed here, but would add yet another different structure that's almost but not quite a
Hugr
, so it would complicate the API without much benefit.Beta Was this translation helpful? Give feedback.
All reactions