Skip to content

Inversion

Inversion is the operation of taking a function \(f\) implemented by some unitary \(U_{f}\) to the function implemented by \(U_{f} ^{\dagger}\). Many quantum algorithms take the form \(U^{\dagger} V U\), in which \(U\) implements some computation. \(V\) uses the results of \(U\) to arrive at the final result. Then, the no-longer necessary intermediate result of \(U\) is uncomputed to release qubits for future use. Hence, the inversion of general functions is critical in implementing many algorithms.

Note that calls to inverted functions do not necessarily release hardware resources. Suppose the implementation of \(U\) requires extra qubits, assumed to begin at state \(|z=0\rangle\), but are not released at the end (i.e., do not end at \(|0\rangle\)). Acting on some states, \(U^ {\dagger}\) might not return the qubits starting at zero to the initial zero state. This is because the Hilbert space of the result is larger than that of the input (due to the added qubits at zero). Therefore, there must be states with sources for which \(|z \neq 0 \rangle\). The states on which to operate are unknown, so you cannot assume \(U^ {\dagger}\) releases qubits. As a result, you must identify the released qubit manually.

Mathematically, \(U_{f}|x, z \rangle\) computes \(f(x)\) only on the subspace for which \(|z \rangle\) are indeed zero qubits. Inversion of \(f\) is properly defined only on \(Im{f}\). The unitary operator is inverted, however, on the entire resulting Hilbert space. Hence, it is not guaranteed that \(U_{f} ^{\dagger}\) computes \(f^{-1}\).

Usage

You can invert any function on the Classiq platform, built-in or not. To get the inverse version, when calling the function, set the is_inverse flag to True. Match the incoming and outgoing wires to the inputs and outputs of the inverted function, switching the roles of the inputs and outputs. The following example shows negation followed by its inverse. Note that the "negated" result register switches its role from output to input.

{
  "functions": [
    {
      "name": "main",
      "body": [
          {
            "function": "Negation",
            "function_params": { "arg": { "size": 3 } },
            "outputs": { "negated": "inner_wire_name" }
          },
          {
            "function": "Negation",
            "function_params": { "arg": { "size": 3 } },
            "is_inverse": true,
            "inputs": { "negated": "inner_wire_name" }
          }
      ]
    }
  ]
}
from classiq import Model, RegisterUserInput
from classiq.builtin_functions import Negation

arg = RegisterUserInput(size=3, is_signed=True)
params = Negation(arg=arg, inplace=True)

model = Model()
x = model.Negation(params=params)
model.Negation(params=params, is_inverse=True, in_wires=x)