Bernstein–Vazirani Algorithm

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:

Leave a comment