Source code for qarp.blocks._primitives.reflection_block
import math
from .._block import SimpleBlock
[docs]
class ReflectionBlock(SimpleBlock):
r"""Reflection about ``|0…0⟩``: ``2|0⟩⟨0| - I`` on n qubits.
Built as ``-1 · X^n · MCZ · X^n``: the X-sandwich turns the MCZ's
"phase −1 on ``|11…1⟩``" into "phase −1 on ``|00…0⟩``", and the global
GPhase(π) flips the overall sign so the ``|0⟩`` subspace gets +1 (and
everything else gets −1 — i.e. ``2|0⟩⟨0| − I``).
Args:
n_qubits: number of qubits of the circuit block
name: name of the block
"""
def __init__(self, n_qubits: int, name: str = "Reflection"):
super().__init__(n_qubits, name=name)
[docs]
def build_vanilla(self) -> None:
if self.n_qubits < 1:
raise ValueError("ReflectionBlock requires n_qubits >= 1")
if self.n_qubits == 1:
# 2|0⟩⟨0| − I = diag(+1, −1) = Z. MCZ requires ≥2 qubits, so
# short-circuit the X-sandwich and emit Z directly.
self.z(0)
return
# Global phase of −1 (= e^{iπ}) flips the sign on the whole register.
self.gphase(math.pi)
all_q = list(range(self.n_qubits))
# X-sandwich the MCZ — bulk emit each X layer.
self.x(all_q)
# MCZ takes [c0, …, c_{n-1}, t]: the last qubit is the target,
# all preceding are controls. For the symmetric "phase -1 on |11…1⟩"
# interpretation we just pass all qubits.
self.mcz(all_q)
self.x(all_q)