Qualtran
Qualtran copied to clipboard
PyZX and Qualtran integration
PyZX is one of the widely used open source libraries for expressing and optimizing quantum circuits using ZX diagrams. ZX diagrams are also a useful representation of quantum circuits for compiling into surface codes using lattice surgery. It'll be useful for us to have an integration of Qualtran and PyZX so we can convert Qualtran bloqs to PyZX graphs, potentially apply rewrite rules and optimizations using ZX calculus and convert the resulting circuit back to a Qualtran bloq (or hand it over to lower level tools like TQEC)
This issue is to track integration of Qualtran and PyZX.
Some useful links:
- https://github.com/zxcalc/pyzx
- https://arxiv.org/abs/1904.04735
Hi! I'd like to contribute to this.
I am also interested in contributing to this.
@anurudhp @dobbse42 Thanks for your interest! Would the two of you like to collaborate and come up with a design doc / prototype implementation for the integration and present it at the Qualtran sync in 2 weeks on February 6th ?
Happy to work together! I will be preparing the design doc next week and will share it here, and can present it in the upcoming sync.
Sounds good, if you want to create and share the link to a design doc @anurudhp we can coordinate there.
Hi @anurudhp @dobbse42 ! I don't know if it's a bit late, but I'd love to contribute as well. If its ok for me to join, could you share the doc? Thanks!
I will also be contributing to this as part of my 20% project.
Thanks for the interest! Here is my WIP design doc: https://docs.google.com/document/d/1iT2wSk9XqHpf-YLxduY3VNSKZt_8s11xMas7xXXKAcY/edit?usp=sharing . If you already have some ideas you want to share, please feel free to request comment access and add your thoughts there!
I will polish it and present it in the upcoming sync. We can then discuss how to split tasks to implement it.
Thanks! I also wrote a design doc. Feel free to leave any comments.
I like your Qualtran.simulation.tensor approach from your doc. Let's discuss the pros and cons of both.
Both of the options above seem reasonable for converting from qualtran to PyZX for the purposes of optimization, but it is also desirable to be able to convert back from PyZX to qualtran and have some of the bloq structure preserved, i.e. only applying PyZX rewrites within a bloq rather than on the entire circuit. We could probably add label attributes to gates corresponding to bloq names such that users could specify a filter function when using PyZX's rewrite tools (see the matchf parameter in many of the functions on this page). This would also allow us to look for labels when converting a PyZX circuit back to qualtran, and construct bloqs from this. I am unsure how we would go about verifying the correctness of bloqs specified by labels on gates in a PyZX circuit, or even if we should. Actually reconstructing a bloq would hopefully just amount to applying the specified gates in the specified order, but I would imagine there are some special cases which we need to handle carefully (e.g. MBUC, see Anurudh's design doc).
This should be compatible with whatever method we decide to implement for going from qualtran to PyZX.
To summarize, I'll send in the first PR by Monday, which will contain the basic skeleton to generate PyZX Circuits, and I'll create a list of tasks for the integration, that people can take up one by one. When I do so, please also feel free to suggest tasks I've missed out, or new features that are useful/interesting.
@anurudhp, I looked at your PR for PyZX (https://github.com/quantumlib/Qualtran/pull/1550) again and also looked at code in https://github.com/zxcalc/pyzx/blob/master/pyzx/circuit/gates.py once again.
The Tl;dr is that I think we should directly target the zx.Graph representation instead of converting to zx.Circuit representation. There is really no added complexity of directly converting to zx.Graph and it helps us save the trouble of dealing with zx.Circuit and custom defined zx.Gates for the scenarios where want to support bloqs with custom ZX graphs.
The detailed explanation is follows:
-
For us, it's better to add a new protocol
Bloq.as_zx_graphto theBloqbase class instead ofBloq.as_zx_gates. The API of theas_zx_graphcould be (almost) the same as theto_graphmethod on theZXGatebase class . We could also introduce qualtran native abstractions forBaseGraph[VT,ET]andTargetMapper[VT]if we wish to reduce the coupling between the libraries, but for now it's probably okay to have this coupling (similar to howBloq.as_cirq_op()is coupled tocirqabstractions. The only additional thing we'd also need to pass toBloq.as_zx_graph()would be a qubit manager and input / output registers, similar to theas_cirq_op. The mapping of qubit registers to the layout is managed by theTargetMapperand its a fairly simple thing. -
Once we have the same interface, for simple bloqs like
CNOTetc., that have a simple decomposition in terms of the corresponding ZXGates, we can simply construct an instance of the corresponding ZXGate with the known qubit values and callzx_gate.to_graph(g, q_mapper, c_mapper). This function mutates the state ofg, q_mapper, c_mapper. -
For bloqs where we want to provide users with a way to specify a custom ZX graph, users can override the
as_zx_graphmethod to directly modify the state of the graphg.
In both the cases, we need the same API. The way it's done right now, we'd maintain both as_zx_gates and eventually have a as_zx_graph and then use a custom type BloqAsZXGate to wrap the bloq with a custom as_zx_graph in an instance of type ZXGate so it can be used in a ZXCircuit. This entire layer of dealing with a ZXCircuit is not needed IMO and can be completely skipped. We can go directly from Bloq to its ZX graph representation.