From 24027ee6f175cd67d7037862e627d76bcf7a1457 Mon Sep 17 00:00:00 2001
From: Divyanshu Singh <55018955+divshacker@users.noreply.github.com>
Date: Thu, 13 Jun 2024 20:10:59 +0530
Subject: [PATCH 1/3] New Algorithm - Bernstein-Vazirani (#55)
---
docs/source/example_bernstein_vazirani.ipynb | 211 +++++++++++++++++++
qlasskit/algorithms/__init__.py | 1 +
qlasskit/algorithms/bernsteinvazirani.py | 73 +++++++
test/algo/test_bernstein_vazirani.py | 69 ++++++
4 files changed, 354 insertions(+)
create mode 100644 docs/source/example_bernstein_vazirani.ipynb
create mode 100644 qlasskit/algorithms/bernsteinvazirani.py
create mode 100644 test/algo/test_bernstein_vazirani.py
diff --git a/docs/source/example_bernstein_vazirani.ipynb b/docs/source/example_bernstein_vazirani.ipynb
new file mode 100644
index 00000000..a7c4fee8
--- /dev/null
+++ b/docs/source/example_bernstein_vazirani.ipynb
@@ -0,0 +1,211 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Bernstein Vazirani algorithm\n",
+ "Bernstein-Vazirani algorithm, first introduced in [Quantum Complexity Theory by Ethan Bernstein and Umesh Vazirani](https://epubs.siam.org/doi/10.1137/S0097539796300921), can be seen as an extension of the Deutsch-Jozsa algorithm. It showed that there can be advantages in using a quantum computer as a computational tool for more complex problems than the Deutsch-Jozsa problem."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### The Bernstein-Vazirani Problem \n",
+ "\n",
+ "We are given a black-box function $f$, which takes as input a string of bits ($x$), and returns either $0$ or $1$, that is:\n",
+ "$$f(\\{x_0,x_1,x_2,...\\}) \\rightarrow 0 \\textrm{ or } 1 \\textrm{ where } x_n \\textrm{ is }0 \\textrm{ or } 1 $$ \n",
+ "\n",
+ "The function is guaranteed to return the bitwise product of the input with some string, $s$. In other words, given an input $x$, $f(x) = s \\cdot x \\, \\text{(mod 2)}$. We are expected to find $s$. "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### The Qlasskit implementation of Bernstein Vazirani Algorithm"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Defining Oracle with secret string =`14` which binary equivalent is `1110`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from qlasskit import qlassf, Qint, Qint2,Qint4\n",
+ "\n",
+ "@qlassf\n",
+ "def oracle(x: Qint[4]) -> bool:\n",
+ " s=Qint4(14)\n",
+ " return ((x[0]&s[0])^(x[1]&s[1])^(x[2]&s[2])^(x[3]&s[3]))\n",
+ " "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Printing the circuit formed in Qiskit draw format"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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",
+ "text/plain": [
+ "