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)