Dagger¶
with dagger: applies the inverse of its body. If the body performs \(U_1\) followed by \(U_2\), the dagger block performs \(U_2^\dagger\) followed by \(U_1^\dagger\).
from guppylang import guppy
from guppylang.std.builtins import control, dagger
from guppylang.std.quantum import h, qubit, s, x
@guppy
def sx_dg(q: qubit) -> None:
with dagger:
s(q)
h(q)
sx_dg.check()
For instance, the previous program corresponds to the sequence of operations is equivalent to:
sdg q;
h q;
Forbidden operations in dagger blocks¶
Dagger blocks have the same qubit-operation restrictions as control blocks and cannot contain control flow.
@guppy
def branch_in_dagger(q: qubit, flag: bool) -> None:
with dagger:
if flag:
h(q)
branch_in_dagger.check()
Error: Invalid expression in dagger (at <In[2]>:4:8)
|
2 | def branch_in_dagger(q: qubit, flag: bool) -> None:
3 | with dagger:
4 | if flag:
| ^^^^^^^^
5 | h(q)
| ^^^^^^^^^^^^^^^^ Branch found in a dagger context
Note:
|
2 | def branch_in_dagger(q: qubit, flag: bool) -> None:
3 | with dagger:
| ------ dagger modifier is used here
Help: Control flow statements (e.g. loops and branches) are not allowed in
daggered contexts.
Guppy compilation failed due to 1 previous error
@guppy
def loop_in_dagger(q: qubit) -> None:
with dagger:
for _ in range(2):
h(q)
loop_in_dagger.check()
Error: Invalid expression in dagger (at <In[3]>:4:8)
|
2 | def loop_in_dagger(q: qubit) -> None:
3 | with dagger:
4 | for _ in range(2):
| ^^^^^^^^^^^^^^^^^^
5 | h(q)
| ^^^^^^^^^^^^^^^^ Loop found in a dagger context
Note:
|
2 | def loop_in_dagger(q: qubit) -> None:
3 | with dagger:
| ------ dagger modifier is used here
Help: Control flow statements (e.g. loops and branches) are not allowed in
daggered contexts.
Guppy compilation failed due to 1 previous error
They also cannot perform observable classical effects such as output, panic, or exit: reversing the quantum operations must not change when those effects occur.
from guppylang.std.builtins import output
@guppy
def output_in_dagger(value: bool) -> None:
with dagger:
output("value", value)
output_in_dagger.check()
Error: Dagger constraint violation (at <In[4]>:6:8)
|
4 | def output_in_dagger(value: bool) -> None:
5 | with dagger:
6 | output("value", value)
| ^^^^^^^^^^^^^^^^^^^^^^ This function cannot be called in a daggerable context
| because it is not daggerable itself
Guppy compilation failed due to 1 previous error
Combining dagger and controls¶
Modifiers compose. This example is a doubly controlled inverse of h followed by s:
@guppy
def doubly_controlled_inverse(c0: qubit, c1: qubit, q: qubit) -> None:
with control(c0):
with dagger:
with control(c1):
h(q)
s(q)
doubly_controlled_inverse.check()
Resolving one modifier at a time gives this sequence:
Source: h q; s q;
Push control c1: ctrl @ h c1, q; ctrl @ s c1, q;
Resolve dagger: ctrl @ sdg c1, q; ctrl @ h c1, q;
Push control c0: ctrl(2) @ sdg c0, c1, q;
ctrl(2) @ h c0, c1, q;