qrisp.gate_wrap#
- gate_wrap(*args, permeability=None, is_qfree=None, name=None, verify=False)[source]#
Decorator to bundle up the quantum instructions of a function into a single gate object. Bundled gate objects can help debugging as it allows for a more clear QuantumCircuit visualisation.
Furthermore, bundling up functions is relevant for Qrisps uncomputation algorithm. When bundling up for uncomputation, this decorator provides the means to annotate the gate objects with information about its permeability and qfree-ness. For further information about these concepts check the uncomputation documentation. Specifying this information allows to skip the computationally costly automatic determination at runtime.
Note that the specified information is not checked for correctness as this would defy the purpose.
A shorthand for
gate_wrap(permeability = "args", is_qfree = True)
is thelifted
decorator.Warning
Using
gate_wrap
without specifying permeability andqfree
-ness on functions processing a lot of qubits, can causes long compile times, since the unitaries of these gates have to be determined numerically.Warning
Incorrect information about permeability and
qfree
-ness can yield incorrect compilation results. If you are unsure, use theverify
keyword on a small scale first.- Parameters:
- permeabilitystring or list, optional
Specify the permeability behavior of the function. When given “args”, it is assumed that the gate is permeable only on the qubits of the arguments. When given “full”, it is assumed that the gate is permeable on every qubit it acts on (i.e. also the result). When given a list of integers it is assumed, that the gate is permeable on the qubits of the arguments corresponding to the integers. The default is None.
- is_qfreebool, optional
Specify the qfree-ness of the function. The default is None.
- namestring, optional
String which will be used for naming the gate object. The default is None.
- verifybool, optional
If set to
True
, the specified information about permeability andqfree
-ness will be checked numerically. The default isFalse
.
Examples
We create a simple function wrapping up multiple gates:
from qrisp import QuantumVariable, cx, x, h, z, gate_wrap @gate_wrap def example_function(a, b): cx(a,b) x(a) cx(b,a) h(b) a = QuantumVariable(3) b = QuantumVariable(3) example_function(a, b)
>>> print(a.qs)
QuantumCircuit: -------------- ┌───────────────────┐ b.0: ┤0 ├ │ │ b.1: ┤1 ├ │ │ b.2: ┤2 ├ │ example_function │ a.0: ┤3 ├ │ │ a.1: ┤4 ├ │ │ a.2: ┤5 ├ └───────────────────┘ Live QuantumVariables: --------------------- QuantumVariable a QuantumVariable b
>>> print(a.qs.transpile())
┌───┐ ┌───┐ b.0: ┤ X ├─────────────────■──┤ H ├────────── └─┬─┘┌───┐ │ └───┘┌───┐ b.1: ──┼──┤ X ├────────────┼────■──┤ H ├───── │ └─┬─┘┌───┐ │ │ └───┘┌───┐ b.2: ──┼────┼──┤ X ├───────┼────┼────■──┤ H ├ │ │ └─┬─┘┌───┐┌─┴─┐ │ │ └───┘ a.0: ──■────┼────┼──┤ X ├┤ X ├──┼────┼─────── │ │ ├───┤└───┘┌─┴─┐ │ a.1: ───────■────┼──┤ X ├─────┤ X ├──┼─────── │ ├───┤ └───┘┌─┴─┐ a.2: ────────────■──┤ X ├──────────┤ X ├───── └───┘ └───┘
In the next example, we create a function that performs no quantum gates and specify that it is qfree and permeable on the second argument but not on the first.
from qrisp import QuantumCircuit @gate_wrap(permeability = [1], is_qfree = True) def example_function(arg_0, arg_1): res = QuantumVariable(1) #Append an identity gate res.qs.append(QuantumCircuit(3).to_gate(), [arg_0, arg_1, res]) return res qv_0 = QuantumVariable(1) qv_1 = QuantumVariable(1) res = example_function(qv_0, qv_1)
>>> print(qv_0.qs)
QuantumCircuit: -------------- ┌───────────────────┐ qv_0.0: ┤0 ├ │ │ qv_1.0: ┤1 example_function ├ │ │ res.0: ┤2 ├ └───────────────────┘ Live QuantumVariables: --------------------- QuantumVariable qv_0 QuantumVariable qv_1 QuantumVariable res
>>> qv_1.uncompute() >>> print(qv_0.qs)
QuantumCircuit: -------------- ┌───────────────────┐ qv_0.0: ┤0 ├ │ │ qv_1.0: ┤1 example_function ├ │ │ res.0: ┤2 ├ └───────────────────┘ Live QuantumVariables: --------------------- QuantumVariable qv_0 QuantumVariable res
Since
arg_1
is marked as permeable, there are no further gates required for uncomputation. The situation is different for the other two QuantumVariables, where #the qubits are not marked as permeable.>>> qv_0.uncompute(do_it = False) >>> res.uncompute() >>> print(qv_0.qs)
QuantumCircuit: -------------- ┌───────────────────┐┌──────────────────────┐ qv_0.0: ┤0 ├┤0 ├ │ ││ │ qv_1.0: ┤1 example_function ├┤1 example_function_dg ├ │ ││ │ res.0: ┤2 ├┤2 ├ └───────────────────┘└──────────────────────┘ Live QuantumVariables: ---------------------