Source code for qolumbina.programs.hidden_subgroup_problem.simon

# The original version of the following code is sourced from Qiskit circuit library:
# https://github.com/qiskit-community/qiskit-textbook/blob/main/content/ch-algorithms/simon.ipynb
# https://github.com/qiskit-community/qiskit-textbook/blob/main/qiskit-textbook-src/qiskit_textbook/tools/__init__.py
#
# Original repository link:
# https://github.com/qiskit-community/qiskit-textbook
#
# 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):
# - Structural reorganization:
#   - For uniformity across benchmarks, the inherent class is changed from `QuantumAlgorithm` to `QuantumCircuit`.
#   - Delete measurement- and postprocessing-related code to focus on circuit construction.
# - Input validation:
#   - Ensure `b` is a valid bitstring of length `n`
# - Dependency decoupling:
#   - Copy `simon_oracle`to eliminate dependency on external repositories.
#
# This code is part of Qiskit.
#
# (C) Copyright IBM 2018, 2021.
#
# 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.
"""
Simon's algorithm.
"""

import operator  # pylint: disable=unused-import
from typing import Optional, Union, Dict, Any
import numpy as np
from sympy import Matrix, mod_inverse

from qiskit import QuantumCircuit
 
# pylint: disable=invalid-name

# ---------- benchmark registration ----------
from ..benchmark_registry import register_benchmark
from pathlib import Path
@register_benchmark(
    Path(__file__).stem,
    family=Path(__file__).resolve().parent.name,
    description="Simon's algorithm for hidden bitstring finding",
    class_name="Simon",
    source={
        "repo": "https://github.com/qiskit-community/qiskit-textbook",
        "file": "content/ch-algorithms/simon.ipynb",
        "language": "Qiskit",
        "available_doc": True
    },
    testability_refactoring=[
        "Dependency decoupling",
        "Structure reorganization",
        "Input validation"
    ] 
)
def create_simon(b: str, if_barrier: bool = True) -> QuantumCircuit:
    return Simon(b=b, if_barrier=if_barrier)


[docs] class Simon(QuantumCircuit): r""" Simon's algorithm circuit. Finds the hidden bitstring `b` for a function `f` such that `f(x) = f(y)` iff `x = y` or `x = y xor b`, where `xor` is bitwise XOR. This circuit implements the quantum part of Simon's algorithm, which finds bitstrings `y` such that `b . y = 0 (mod 2)`. The full algorithm requires classical postprocessing to find `b` from these bitstrings. """ def __init__(self, b: str, if_barrier: bool = True, name: str | None = None) -> None: """ Args: b: The hidden bitstring :math:`b`. if_barrier: Whether to include barriers in the circuit. name: Optional name for the circuit. Raises: ValueError: If `b` is not a valid bitstring with elements '0' and '1'. """ if any(bit not in '01' for bit in b): raise ValueError("b must be a bitstring of length n") n = len(b) super().__init__(2*n, name=name or "Simon") self._n = n self._b = b self._if_barrier = if_barrier self._build()
[docs] def simon_oracle(self, b: str) -> QuantumCircuit: r""" Returns a Simon oracle for bitstring b """ b = b[::-1] # reverse b for easy iteration n = len(b) qc = QuantumCircuit(n*2) # Do copy; |x>|0> -> |x>|x> for q in range(n): qc.cx(q, q+n) if '1' not in b: return qc # 1:1 mapping, so just exit i = b.find('1') # index of first non-zero bit in b # Do |x> -> |s.x> on condition that q_i is 1 for q in range(n): if b[q] == '1': qc.cx(i, (q)+n) return qc
def _build(self) -> None: """Build the Simon circuit.""" simon_circuit = QuantumCircuit(self._n * 2) # Apply Hadamard gates before querying the oracle simon_circuit.h(range(self._n)) # Apply barrier for visual separation if self._if_barrier: simon_circuit.barrier() simon_circuit.compose(self.simon_oracle(self._b), inplace=True) # Apply barrier for visual separation if self._if_barrier: simon_circuit.barrier() # Apply Hadamard gates to the input register simon_circuit.h(range(self._n)) self.compose(simon_circuit, inplace=True)