CQCL / tket2

Version 2 of the TKET quantum compiler
http://crates.io/crates/tket2
Apache License 2.0
27 stars 6 forks source link

guppy definition → tket2 circuits #303

Closed aborgna-q closed 3 months ago

aborgna-q commented 7 months ago

Compile guppy programs and wrap them into a tket2.Circuit.

We should be able to support something like the following:

guppy.load(quantum)

@guppy
def teleport(src: Qubit, tgt: Qubit) -> Qubit:
   # Create ancilla and entangle it with src and tgt
   tmp = Qubit()
   tmp, tgt = cx(h(tmp), tgt)
   src, tmp = cx(src, tmp)
   # Apply classical corrections
   if measure(h(src)):
      tgt = z(tgt)
   if measure(tmp):
      tgt = x(tgt)
   return tgt

# Implicitly compiles the module, and returns a Tk2Circuit
t2c = Circuit(teleport)
aborgna-q commented 7 months ago

Loading from in-memory guppy modules is actually quite simple, as we can just module.compile().to_json() to get the Hugr. For loading a file, we can copy guppy-runner's implementation, https://github.com/CQCL/guppy-runner/blob/e824c9186c52c995c58b9f46e6416bc8465c8d89/guppy_runner/compile/guppy_compiler.py#L62-L72

Currently the main blocker is that guppy-defined hugrs are always modules, which contain function, which contain CFGs, which may contain any number of basic blocks (with DFG code).

Getting a (DFG-rooted) circuit from there will require some rewriting to inline and flatten the structure.

aborgna-q commented 6 months ago

There's some work on this in branch ci/guppy-hugrs.

Currently you can pass a GuppyModule directly to Tk2Circuit::new, but as it translates the whole module, you are left with a HUGR with a Module root (which is an invalid circuit).

With the changes from https://github.com/CQCL/guppylang/pull/179 we should be able to process a function declaration instead, so a similar code could be used to produce DFG-rooted hugrs.

It should then work something like:

guppy.load(quantum)

@guppy
def teleport(src: Qubit, tgt: Qubit) -> Qubit:
   # Create ancilla and entangle it with src and tgt
   tmp = Qubit()
   tmp, tgt = cx(h(tmp), tgt)
   src, tmp = cx(src, tmp)
   # Apply classical corrections
   if measure(h(src)):
      tgt = z(tgt)
   if measure(tmp):
      tgt = x(tgt)
   return tgt

# Implicitly compiles the module, and returns a Tk2Circuit
t2c = Tk2Circuit(teleport)

We'll also need guppy to generate the correct custom operations (either tket2's, or wrapped Tk1Ops).

aborgna-q commented 3 months ago

This will probably be implemented by guppy instead. The first alpha release includes some conversion utilities, mostly going through serialization.