Source code for qolumbina.programs.comparator.less_than_phase
# 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 import QuantumCircuit
# ---------- 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 (phase version)",
class_name="LessThanPhase",
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_phase(
input_qubits: int,
integer: int,
name: str | None = None
):
return LessThanPhase(input_qubits=input_qubits, integer=integer, name=name)
[docs]
class LessThanPhase(QuantumCircuit):
r"""
Less-than comparator oracle (phase version).
Acts on :math:`n` qubits and applies a phase flip 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`.
"""
if integer < 0 or integer >= 2 ** input_qubits:
raise ValueError("integer must be in [0, 2**input_qubits)")
super().__init__(input_qubits, name=name or "LessThanPhase")
self._input_integer = integer
self._input_qubits = input_qubits
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.qubits
n = len(qs)
mb = self._int_as_bool_array(self._input_integer, n)
# The raw code in the Q# version is only self.x(qs[n - 1]), which could contain a bug.
# highest bit
if mb[n - 1]:
self.x(qs[n - 1])
self.z(qs[n - 1])
self.x(qs[n - 1])
else:
self.x(qs[n - 1])
for i in reversed(range(n - 1)):
if mb[i]:
self.x(qs[i])
# emulate MCZ via H-MCX-H
self.h(qs[i])
self.mcx(qs[i + 1 : n], qs[i])
self.h(qs[i])
self.x(qs[i])
else:
self.x(qs[i])
for i in range(n):
if not mb[i]:
self.x(qs[i])