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])