Source code for qolumbina.programs.comparator.less_than_qubit

# This code is developed through cross-language conversion from 
# https://github.com/MgcosA/Code_of_Testing_Oracle_Quantum_Program_Article/blob/master/qolumbina/programs/LessThan.qs
# 
# In detail, the raw program is written in Q#, and we rewrite it in Qiskit.

from qiskit.circuit import QuantumCircuit, QuantumRegister
import warnings

# ---------- benchmark registration ----------
from ..benchmark_registry import register_benchmark
from pathlib import Path
@register_benchmark(
    Path(__file__).stem,
    family=Path(__file__).resolve().parent.name,
    description="Less-than comparator oracle (qubit version)",
    class_name="LessThanQubit",
    source={
        "repo": "https://github.com/MgcosA/Code_of_Testing_Oracle_Quantum_Program_Article/blob/master/",
        "file": "qolumbina/programs/LessThan.qs",
        "language": "Q#",
        "available_doc": True
    },
    testability_refactoring=[
        "Cross-language translation", 
        "Structure reorganization",
        "Input validation"
    ]     
)
def create_less_than_qubit(input_qubits, integer):
    return LessThanQubit(input_qubits=input_qubits, integer=integer)

[docs] class LessThanQubit(QuantumCircuit): r""" Less-than comparator oracle (qubit version). Acts on :math:`n` input qubits and 1 target qubit. Flips the target qubit when :math:`x < m`. """ def __init__(self, input_qubits: int, integer: int, name: str | None = None): r""" Args: input_qubits: The number of input qubits for comparison, i.e., :math:`n`. integer: The integer :math:`k` to compare with, should be in the range of :math:`[0, 2^n)`. name: The name of the circuit. Raises: ValueError: If ``integer`` is negative or not less than :math:`2^n`. """ # ---------- configuration check ---------- if integer < 0 or integer >= 2 ** input_qubits: warnings.warn( "integer should range in [0, 2**input_qubits) to ensure correct behavior", UserWarning, stacklevel=2, ) self._input_integer = integer self._input_qubits = input_qubits # ---------- registers ---------- q_input = QuantumRegister(input_qubits, "q") q_target = QuantumRegister(1, "target") super().__init__(q_input, q_target, name=name or "LessThan") # q_target is the last qubit (MSB) # ---------- build circuit ---------- self._build() # ---------- utilities ---------- @staticmethod def _int_as_bool_array(m: int, n: int) -> list[bool]: return [(m >> i) & 1 == 1 for i in range(n)] # ---------- build ---------- def _build(self) -> None: qs = self.qregs[0] qtarget = self.qregs[1][0] n = len(qs) mb = self._int_as_bool_array(self._input_integer, n) # -------- highest bit -------- if mb[n - 1]: self.x(qs[n - 1]) self.cx(qs[n - 1], qtarget) self.x(qs[n - 1]) else: self.x(qs[n - 1]) # -------- remaining bits -------- for i in reversed(range(n - 1)): if mb[i]: self.x(qs[i]) # multi-controlled X on target self.mcx(qs[i : n], qtarget) self.x(qs[i]) else: self.x(qs[i]) # -------- uncompute X for mb[i] == 0 -------- for i in range(n): if not mb[i]: self.x(qs[i])