Source code for qolumbina.programs.comparator.integer_comparator_greedy
# The original version of the following code is sourced from Qiskit circuit library:
# https://github.com/Qiskit/qiskit/blob/stable/2.3/qiskit/circuit/library/arithmetic/integer_comparator.py
# https://github.com/Qiskit/qiskit/blob/stable/2.3/qiskit/synthesis/arithmetic/comparators/compare_greedy.py
#
# Original repository link:
# https://github.com/Qiskit/qiskit/tree/f14e0b29a484795034447ea5bfb637fe845c194f
#
# This program is adapted for use as a benchmark in controlled software testing experiments.
# Modifications made to the original code include (for Apache License 2.0):
# - Refactored to unify the inherent class as QuantumCircuit
# - Decoupled from Qiskit dependencies where applicable
#
# This code is part of Qiskit.
#
# (C) Copyright IBM 2017, 2020.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
from __future__ import annotations
import warnings
from typing import List, Optional
import numpy as np
from qiskit.circuit 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=(
f"Implement an integer comparison based on value-by-value comparison, "
f"where this version stores the comparison result in a target qubit."
),
class_name="IntegerComparatorGreedy",
source={
"repo": "https://github.com/Qiskit/qiskit/tree/f14e0b29a484795034447ea5bfb637fe845c194f",
"file": "qiskit/circuit/library/arithmetic/integer_comparator.py",
"language": "Qiskit",
"available_doc": True
},
testability_refactoring=[
"Structure reorganization",
"Dependency decoupling",
]
)
def create_integer_comparator_greedy(
num_state_qubits: int,
integer: int,
geq: bool = True,
label: str | None = None
):
return IntegerComparatorGreedy(
num_state_qubits=num_state_qubits, value=integer, geq=geq, label=label
)
[docs]
class IntegerComparatorGreedy(QuantumCircuit):
r"""Perform a :math:`\geq` (or :math:`<`) on a qubit register against a classical integer.
This operator compares basis states :math:`|i\rangle_n` against a classically given integer
:math:`L` of fixed value and flips a target qubit if :math:`i \geq L`
(or :math:`<` depending on the parameter ``geq``):
.. math::
|i\rangle_n |0\rangle \mapsto |i\rangle_n |i \geq L\rangle
"""
def __init__(
self, num_state_qubits: int, value: int, geq: bool = True, label: str | None = None
):
r"""
Args:
num_state_qubits: The number of qubits in the registers.
value: The value :math:`L` to compre to.
geq: If ``True`` compute :math:`i \geq L`, otherwise compute :math:`i < L`.
label: An optional label for the gate.
"""
if num_state_qubits <= 0:
raise ValueError("num_state_qubits must be positive")
super().__init__(num_state_qubits + 1, name="IntComp" or label)
self.value = value
self.geq = geq
self._build()
[docs]
def synth_integer_comparator_greedy(
self, num_state_qubits: int, value: int, geq: bool = True
) -> QuantumCircuit:
r"""Implement an integer comparison based on value-by-value comparison.
For ``value`` smaller than ``2 ** (num_state_qubits - 1)`` this circuit implements
``value`` multi-controlled gates with control states 0, 1, ..., ``value - 1``, such that
the target qubit is flipped if the qubit state represents any of the allowed values.
For ``value`` larger than that, ``geq`` is flipped. This implementation can
require an exponential number of gates. If auxiliary qubits are available, the implementation
provided by :func:`.synth_integer_comparator_2s` is more efficient.
Args:
num_state_qubits: The number of qubits encoding the value to compare to.
value: The value to compare to.
geq: If ``True`` flip the target bit if the qubit state is :math:`\geq` than the value,
otherwise implement :math:`<`.
Returns:
A circuit implementing the integer comparator.
"""
circuit = QuantumCircuit(num_state_qubits + 1)
if value <= 0: # condition always satisfied for non-positive values
if geq: # otherwise the condition is never satisfied
circuit.x(num_state_qubits)
return circuit
# make sure to always choose the comparison where we have to place less than
# (2 ** n)/2 MCX gates
value = int(np.ceil(value))
if (value < 2 ** (num_state_qubits - 1) and geq) or (
value > 2 ** (num_state_qubits - 1) and not geq
):
geq = not geq
circuit.x(num_state_qubits)
if geq:
accepted_values = range(value, 2**num_state_qubits)
else:
accepted_values = range(0, value)
for accepted_value in accepted_values:
circuit.mcx(list(range(num_state_qubits)), num_state_qubits, ctrl_state=accepted_value)
return circuit
def _build(self):
subcircuit = self.synth_integer_comparator_greedy(self.num_qubits - 1, self.value, self.geq)
self.compose(subcircuit, inplace=True)