Bernstein Vazirani Algorithm is an extended version of Deutsch’s problem. This algorithm is versatile in quantum key distribution. The algorithm determines a bit string. Using a boolean valued function, the algorithm determines the values of the function. The algorithm starts with n qubits in the |0> state. Hadamard gate is applied to the n qubits. The boolean valued function is queried using phase queries. The resulting state is measured.
Q# project and solution is created using the following commands.
dotnet new console -lang Q# --output Bernstein
Visual Studio Code is used to open the project. The project will have two files Driver.cs (C# driver) and Operations.qs (Q# ). The Operations.qs is renamed as Quantum.qs.
The code snippet below shows the Quantum.qs after adding the operation Execute Bernstein Vazirani algorithm.
namespace Bernstein {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Canon;
// GetFourierSamplingParity Operation
/// # Summary
/// ParityViaFourierSampling implements the Bernstein-Vazirani quantum algorithm.
/// # Parameters
/// ## Uf
/// A quantum operation that implements |𝑥〉|𝑦〉 ↦ |𝑥〉|𝑦 ⊕ 𝑓(𝑥)〉,
/// where 𝑓 is a Boolean function that implements a parity Σᵢ 𝑟ᵢ 𝑥ᵢ.
/// ## n
/// The number of bits of the input register |𝑥〉.
///
/// # Returns
/// An array of type `Bool[]` that contains the parity 𝑟⃗ = (𝑟₀, …, 𝑟ₙ₋₁).
///
operation GetFourierSamplingParity (Uf : (Qubit[] => Unit), n : Int) : Bool[] {
mutable resultArray = new Result[n];
using (qubits = Qubit[n + 1]) {
X(qubits[n]);
ApplyToEach(H, qubits);
Uf(qubits);
ApplyToEach(H, qubits[0 .. n - 1]);
for (idx in 0 .. n - 1) {
set resultArray[idx] = MResetZ(qubits[idx]);
}
Reset(qubits[n]);
}
Message($"measure: {resultArray}");
return BoolArrFromResultArr(resultArray);
}
// ExecuteParityImpl Operation
operation ExecuteParityImpl (pattern : Bool[], qs : Qubit[]) : Unit {
let n = Length(pattern);
if (Length(qs) != n + 1) {
fail "Length of qs should be equal to pattern length + 1.";
}
for (idx in 0 .. n - 1) {
if (pattern[idx]) {
Controlled X([qs[idx]], qs[n]);
}
}
}
/// ExecuteParity function
/// # Summary
/// an operation implementing a unitary 𝑈
/// # Parameters
/// ## pattern
/// The bitstring 𝑟⃗ used to define the function 𝑓.
///
/// # Returns
/// An operation implementing 𝑈.
function ExecuteParity (pattern : Bool[]) : (Qubit[] => Unit) {
return ExecuteParityImpl(pattern, _);
}
// ExecuteBernsteinVaziraniAlgorithm Operation
operation ExecuteBernsteinVaziraniAlgorithm (nQubits : Int, patternInt : Int) : Int {
let pattern = BoolArrFromPositiveInt(patternInt, nQubits);
let result = GetFourierSamplingParity(ExecuteParity(pattern), nQubits);
return PositiveIntFromBoolArr(result);
}
}
The Driver file will have the following code to execute Bernstein Vazrani Algorithm.
/////////////////////////////////////////////////////////////////////
// This file contains the driver class.
//////////////////////////////////////////////////////////////////////
using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.Simulators;
using System;
using System.Linq;
namespace Bernstein
{
class Driver
{
static void Main(string[] args)
{
var sim = new QuantumSimulator(throwOnReleasingQubitsNotInZeroState: true);
const int nQubits = 4;
foreach (var parity in Enumerable.Range(0, 1 << nQubits))
{
var measuredParity = ExecuteBernsteinVaziraniAlgorithm.Run(sim, nQubits, parity).Result;
if (measuredParity != parity)
{
throw new Exception($"Measured parity {measuredParity}, but expected {parity}.");
}
}
System.Console.WriteLine("All parities are measured!");
}
}
}
Run the following commands to execute the project in Visual Studio Code:
^F5
In the terminal, you can execute the build by running the command below.
dotnet run
The screenshot of the output is attached below:
