Reflection#

reflection(qargs, state_function=None, args=(), kwargs={}, phase=3.141592653589793, reflection_indices=None)[source]#

Applies a reflection around a state \(\ket{\psi}\) of (multiple) QuantumVariables, i.e., applies the operator

\[R = ((1-e^{i\phi})\ket{\psi}\bra{\psi}-\mathbb I) = U((1-e^{i\phi})\ket{0}\bra{0}-I)U^{\dagger},\]

where \(\ket{\psi} = U\ket{0}\).

Parameters:
qargsQuantumVariable | QuantumArray | list[QuantumVariable | QuantumArray]

The (list of) QuantumVariables representing the state to apply the reflection on.

state_functionfunction, optional

A Python function state_function(*qargs, *args, **kwargs) preparing the state \(\ket{\psi}\) in variables qargs around which to reflect. By default, the reflection is performed around the \(\ket{0}\) state.

argstuple, optional

Additional arguments for the state function.

kwargsdict, optional

Keyword arguments for the state function.

phasefloat or sympy.Symbol, optional

Specifies the phase shift. The default is \(\pi\).

refection_indiceslist[int], optional

A list of indices indicating with respect to which variables the reflection is performed. This is used for oblivious amplitude amplification. Indices correspond to the flattened qargs, e.g., if qargs = QuantumArray(QuantumFloat(3), (6,)), reflection_indices=[0,1,2,3] corresponds to the first four variables in the array. By default, the reflection is performed with respect to all variables in qargs.

Examples

We prepare a QuantumVariable in state \(\ket{1}^{\otimes n}\), and reflect around the GHZ state \(\frac{1}{\sqrt{2}}(\ket{0}^{\otimes n} + \ket{1}^{\otimes n})\). The resulting state is \(\ket{0}^{\otimes n}\).

from qrisp import QuantumVariable, QuantumArray, h, x, cx, reflection

def ghz(qv):
    h(qv[0])

    for i in range(1, qv.size):
        cx(qv[0], qv[i])

# Prepare |1> state
qv = QuantumVariable(5)
x(qv)
print(qv)
# {'11111': 1.0}

# Reflection around GHZ state
reflection(qv, ghz)
print(qv)
# {'00000': 1.0}

The refletion can also be applied to lists of QuantumVariables and QuantumArrays:

from qrisp import QuantumVariable, QuantumArray, h, x, cx, reflection, multi_measurement

def ghz(qv, qa):
    h(qv[0])

    for i in range(1, qv.size):
        cx(qv[0], qv[i])

    for var in qa:
        for i in range(var.size):
            cx(qv[0], var[i])

# Prepare |1> state
qv = QuantumVariable(5)
qa = QuantumArray(QuantumVariable(3), shape=(3,))
x(qv)
x(qa)
print(multi_measurement([qv, qa]))
# {('11111', OutcomeArray(['111', '111', '111'], dtype=object)): 1.0}

# Reflection around GHZ state
reflection([qv, qa], ghz)
print(multi_measurement([qv, qa]))
# {('00000', OutcomeArray(['000', '000', '000'], dtype=object)): 1.0}

Addtional arguments can be passed to the state function:

from qrisp import QuantumVariable, QuantumArray, h, x, cx, ry, reflection

def perturbed_ghz(qv, a, b):
    h(qv[0])
    ry(a, qv[1])
    ry(b, qv[2])

    for i in range(1, qv.size):
        cx(qv[0], qv[i])

# Prepare |1> state
qv = QuantumVariable(5)
x(qv)
reflection(qv, perturbed_ghz, args=(0.1, 0.1))
print(qv)
# {'00000': 0.9900599999999998,'01000': 0.0024799999999999996,'00100': 0.0024799999999999996,'11011': 0.0024799999999999996,'10111': 0.0024799999999999996,'11111': 1.9999999999999998e-05}