Quantum Transformations – Implementation

The Driver file will have the following code to execute BayesianPhaseEstimation.

Code Snippet : Driver C# Example

using Microsoft.Quantum.Simulation.Simulators;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PhaseEstimation
{
    class Program
    {

        static void Main(string[] args)
        {


            var sim = new QuantumSimulator(throwOnReleasingQubitsNotInZeroState: true);

            const Double eigenphaseValue = 0.344;


            System.Console.WriteLine("Phase Estimation checking  Likelihood ");
            GetPhaseEstimationIteration.Run(sim).Wait();


            System.Console.WriteLine("Bayesian Phase Estimation w/ Explicit Grid:");
            var estimate = GetBayesianPhaseEstimation.Run(sim, eigenphaseValue).Result;
            System.Console.WriteLine($"Expected value {eigenphaseValue}, estimated value {estimate}.");


            

        }
    }
}

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:

Quantum Transformations -Phase Estimation

 This sample introduces iterative phase estimation, as well as the algorithms for processing the results of iterative phase estimation that are provided with Q#.

    In phase estimation, one is concerned with learning the *eigenvalues*

    of a unitary operator U. In particular, suppose that U is unknown, but

    that we have access to U as an oracle. That is, we can call U as an

    operation on a register of our choice, but cannot introspect into its

    source code. Suppose as well that we also have access to an operation

    which prepares a state |φ〉 such that U|φ〉 = e^{i φ} |φ〉 for some φ

    that we would like to learn. Given these resources, we can learn φ by

    applying either quantum or iterative phase estimation.

   Before proceeding further, it’s helpful to take a moment to discuss

   how to represent the phase estimation oracle U in our Q# programs.

   The most straightforward representation is for any phase estimation

   operation to take as an input a value of type

   (Qubit[] => () : Controlled), representing an operation that acts on

     an array of qubits and that can be controlled.

    To implement U^m for some power m, we can use an operation of this form inside of a for loop. This precludes, however, if we have a more

  efficient implementation that would let us “fast forward.”

 By the no fast-forwarding theorem [https://arxiv.org/abs/0908.4398],

  this cannot be done in general, such that if we only have oracular

  access to U, we preclude significant opportunities for improvements.

  A more general approach is thus to take an operation of type

   ((Int, Qubit[]) => () : Controlled) representing U(m) ≔ U^m.

   For oracular access to U, we write out the same for loop here, or use

   the OperationPow function in the canon, while we remain compatible with speedups in special cases.

   As a further generalization, we can instead consider that U is not

   a single unitary at all, but a family of unitaries parameterized by

   time, |ψ(t)〉 = U(t) |ψ(0)〉. If these unitaries compose as U(t + s) =

   U(t) U(s), then we can write that U(t) = e^{-i H t} for some operator

   H, making this model ideal for application to Hamiltonian simulation.

   In particular, we now have that |φ〉 is an eigenstate of H as well,

   such that H|φ〉 = -φ|φ〉. Thus, phase estimation expressed in this form

   learns the energy of a particular eigenstate of a Hamiltonian.

   This generalization is represented in Q# as an operation of the type

   ((Double, Qubit[]) => () : Controlled).

     For the rest of this sample, we follow the continuous-time convention.

   In the iterative case, one learns φ by using

   a single additional qubit to turn phase estimation into a classical

   statistical problem.

   Given an operation representing U and an operation representing

   preparation of |φ〉, we can implement each step of iterative phase estimation by preparing a control qubit in the |+〉 state, controlling the application of U(t) for some t : Double, and then measuring the control qubit in the X basis.

The final measurement from a single step follows a sinusoidal

  *likelihood function*, such that iterative phase estimation is readily

   amenable to analysis by well-known methods such as Bayesian inference, as we will detail below. For now, we define the phase estimation step itself. In practice, it can help dramatically improve numerical stability of some algorithms if we also rotate the control qubit before using it

    to control U. We thus include an additional input to allow

    for this.    

Having checked that the phase estimation iteration does indeed follow

the likelihood function we expected, we can proceed to learn the

 phase. For this sample, we will follow the Bayesian formalism, and

  will attempt to find the posterior distribution

    Pr(φ | data) = Pr(data | φ) Pr(φ) / Pr(data),

    where Pr(φ) is the prior distribution over φ, where Pr(data | φ) is the

    likelihood function that we tested in the previous step, and where

    Pr(data) = ∫ Pr(data | φ) Pr(φ) dφ is a normalization factor.

    For simplicity, we will take Pr(φ) = 1 over the interval [0, 1] as our

     prior.

    The estimate ̂φ can then be found by integrating over the posterior,

        ̂φ ≔ ∫ φ Pr(φ | data) dφ.

     We will use an explicit grid method, in which we discretize the prior

    and posterior at each φ, effectively replacing the integrals above

    with the trapezoidal rule.

     It’s helpful in writing up Bayesian phase estimation with the explicit

     grid method to first define a couple utility functions.

Next Blog article will have the implementation in Q#.

Hybrid Algorithms

Hybrid Algorithms perform quantum state preparation and measurement.  They determine the ground state eigenvector and eigen value of a Hermitian Operator.

The hybrid quantum algorithms are enumerated in the following list.

  • Quantum Approximate Optimization Algorithm
  • Variational Quantum Eigen Solver

Grover’s Algorithm

Grover’s Algorithm is related to searching an unstructured database with entries. Classical algorithms for searching n entries will be O(n) queries. The grover’s algorithm requires only O(square root of n).  Bohmian mechanics based non local hidden quantum computer can perform the search in O(cube root of n) queries.

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 the Quantum.qs after adding the operation Set and StateTest.

namespace Grovers
{
    open Microsoft.Quantum.Primitive;
    open Microsoft.Quantum.Canon;

    // GetDataFromInts Operation 
    /// # Summary
    /// Database oracle `D` constructed from classical database.
    /// 
    /// # Parameters
    /// ## markedElements
    /// Indices to marked elements in database.
    /// ## markedQubit
    /// Qubit that indicated whether database element is marked.
    /// ## databaseRegister
    /// A register of n qubits initially in the |00…0〉 state.
    /// 
    operation GetDataFromInts(markedElements : Int[],  markedQubit: Qubit, databaseRegister: Qubit[]) : Unit
    {
        body(...) {
            let nMarked = Length(markedElements);
            for (idxMarked in 0..nMarked - 1) {
                // Note: As X accepts a Qubit, and ControlledOnInt only 
                // accepts Qubit[], we use ApplyToEachCA(X, _) which accepts 
                // Qubit[] even though the target is only 1 Qubit.
                (ControlledOnInt(markedElements[idxMarked], ApplyToEachCA(X, _)))(databaseRegister, [markedQubit]);
            }
        }	
        adjoint auto;
        controlled auto;
        adjoint controlled auto;
    }

    // SetupGroverStateOracle Operation
    /// # Summary
    /// Preparation of start state from database oracle and oracle `U` that 
    /// creates a uniform superposition over database indices.
    /// 
    /// # Parameters
    /// ## markedElements
    /// Indices to marked elements in database.
    /// ## idxMarkedQubit
    /// Index to `MarkedQubit`.
    /// ## startQubits
    /// The collection of the n+1 qubits `MarkedQubit` and `databaseRegister`
    /// initially in the |00…0〉 state.
    /// 
    operation SetupGroverStateOracleImpl(markedElements : Int[], idxMarkedQubit: Int , startQubits: Qubit[]) : Unit
    {
        body(...) {
            let flagQubit = startQubits[idxMarkedQubit];
            let databaseRegister = Exclude([idxMarkedQubit], startQubits);
            ApplyToEachCA(H, databaseRegister);      
            GetDataFromInts(markedElements, flagQubit, databaseRegister);

             }
        adjoint auto;
        controlled auto;
        adjoint controlled auto;
    }

    /// # Summary
    /// `StateOracle` type for the preparation of a start state that has a 
    /// marked qubit entangled with some desired state in the database 
    /// register.
    ///
    /// # Parameters
    /// ## markedElements
    /// Indices to marked elements in database.
    ///
    /// # Returns
    /// A `StateOracle` type with signature 
    /// ((Int, Qubit[]) => (): Adjoint, Controlled).
    function SetupGroverStateOracle(markedElements : Int[]) : StateOracle
    {
        return StateOracle(SetupGroverStateOracleImpl(markedElements, _, _));
    }

    // Execute Search function
    /// # Summary
    /// Grover's search algorithm using library functions.
    ///
    /// # Parameters
    /// ## markedElements
    /// Indices to marked elements in database.
    /// ## nIterations
    /// Number of iterations of the Grover iteration to apply.
    /// ## idxMarkedQubit
    /// Index to `MarkedQubit`.
    ///
    /// # Returns
    /// Unitary implementing Grover's search algorithm.
    ///
 
    function ExecuteSearch( markedElements: Int[], nIterations: Int, idxMarkedQubit: Int) : (Qubit[] => Unit : Adjoint, Controlled)
    {
        return AmpAmpByOracle(nIterations, SetupGroverStateOracle(markedElements), idxMarkedQubit);
    }
    
    // ExecuteGroversAlgorithm Operation
    /// # Summary
    /// Performs quantum search for the marked elements and returns an index
    /// to the found element in integer format. 
    ///
    /// # Parameters
    /// ## markedElements
    /// Indices to marked elements in database.
    /// ## nIterations
    /// Number of applications of the Grover iterate (RS · RM).
    /// ## nDatabaseQubits
    /// Number of qubits in the database register. 
    ///
    /// # Returns
    /// Measurement outcome of marked Qubit and measurement outcomes of 
    /// the database register converted to an integer.
    operation ExecuteGroversAlgorithm( markedElements: Int[], nIterations : Int, nDatabaseQubits : Int) : (Result,Int) {
        body(...){            
            mutable resultSuccess = Zero;
            mutable numberElement = 0;            
            using (qubits = Qubit[nDatabaseQubits+1]) {                                
                let markedQubit = qubits[0];                
                let databaseRegister = qubits[1..nDatabaseQubits];

                
                (ExecuteSearch( markedElements, nIterations, 0))(qubits);                
                set resultSuccess = M(markedQubit);
                               let resultElement = MultiM(databaseRegister);
                set numberElement = PositiveIntFromResultArr(resultElement);
                               ResetAll(qubits);
            }

            return (resultSuccess, numberElement);
        }
    }
}
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 Grovers Algorithm.

using System;
using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.Simulators;

namespace Grovers
{
    class Driver
    {
        static void Main(string[] args)
        {
                        int successfulCnt = ExecuteSearchAlgorithm(100,20);
            successfulCnt = ExecuteSearchAlgorithm(100, 3);
            successfulCnt = ExecuteSearchAlgorithm(100, 2);
            successfulCnt = ExecuteSearchAlgorithm(100, 1);
            successfulCnt = ExecuteSearchAlgorithm(100, 0);
        }

        static int ExecuteSearchAlgorithm(int repeats, int groverIterations)
        {
            int successfulCount = 0;
            using (var sim = new QuantumSimulator(throwOnReleasingQubitsNotInZeroState: true))
            {
                 
                int nDatabaseQubits = 8;
                var databaseSize = Math.Pow(2.0, nDatabaseQubits);
                QArray<long> markedElements = new QArray<long>() {23};//{ 0, 39, 101, 234 }};                
                int nIterations = groverIterations;
                for (int i = 0; i < repeats; ++i)
                {                      
                    var task = ExecuteGroversAlgorithm.Run(sim, markedElements, nIterations, nDatabaseQubits);
                    var result = task.Result;
                    if (result.Item1 == Result.One)
                    {
                        successfulCount++;
                    }
                }
            }
            Console.WriteLine(
                $"Grover-Iterations {groverIterations}: {successfulCount} of {repeats} had the desired result.");
            return successfulCount;
        }
    }
}

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:

Driver code

BQP Algorithms

BQP algorithms are bounded error and quantum polynomial time algorithms.  These algorithms are related to a class of decision problems executable on quantum computer in polynomial time.

Bounded-error, quantum, polynomial time algorithms  are listed below.

  • Computing Knot invariants
  • Quantum Simulation

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:

Deutsch-Jozsa Algorithm

Deutsch Jozsa Algorithm is related to implementation of a function 

f : {0,1}m -> {0,1} on a black box quantum computer known as an oracle.  The algorithm was proposed by  David Deutsch and Richard Jozsa in 1992.  Richard Cleve, Artur Ekert, Chiara Macchiavello and Michele Mosca improved it in 1998. The pseudo code for the algorithm is shown below.

  • The initial state is n+1 bit state  |0> bits |1>  .
  • Hadamard transform is applied to each bit 
  • quantum oracle function is applied
  • For every x, possibilities of 0 or 1 is tested.

Q#  project  and solution is created using the following commands.

dotnet new console -lang Q# --output Deutsch

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 Set and StateTest.

namespace DeutschJozsaAlgorithm {
    
    open Microsoft.Quantum.Primitive;
    open Microsoft.Quantum.Canon;   
    /// IsConstantBooleanFunction Operation 
    /// # Summary
    /// The operation `CheckConstantBooleanFunction` answers this question by returning the
    /// Boolean value `true` if the function is constant and `false` if it is not. Note
    /// that the promise that the function is either constant or balanced is assumed.
    ///
    /// # Parameters
    /// ## Uf
    /// A quantum operation that implements |𝑥〉|𝑦〉 ↦ |𝑥〉|𝑦 ⊕ 𝑓(𝑥)〉,
    /// where 𝑓 is a Boolean function, 𝑥 is an 𝑛 bit register and 𝑦 is a single qubit.
    /// ## n
    /// The number of bits of the input register |𝑥〉.
    ///
    /// # Return
    /// A boolean value `true` that indicates that the function is constant and `false`
    /// that indicates that the function is balanced.
    ///
   operation CheckConstantBooleanFunction (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]);
        }
        
        
        return ForAll(IsResultZero, resultArray);
    }
    
    

    
    
    operation ExecuteDeutschJozsaAlgorithm (nQubits : Int, markedElements : Int[]) : Bool {
        
        return CheckConstantBooleanFunction(GetBooleanFunctionFromMarkedElements(nQubits, markedElements), nQubits);
    }
    
    operation GetBooleanFunctionFromMarkedElementsImpl (n : Int, markedElements : Int[], qs : Qubit[]) : Unit {
       
       let target = qs[Length(qs) - 1];
       let inputs = qs[0 .. Length(qs) - 2];
       
       
       let nMarked = Length(markedElements);
       
       for (idxMarked in 0 .. nMarked - 1) {
           

           (ControlledOnInt(markedElements[idxMarked], ApplyToEachCA(X, _)))(inputs, [target]);
       }
   }


   
   
   /// # Summary
   /// Constructs an operation representing a query to a boolean function
   /// # Parameters
   /// ## nQubits
   /// The number of qubits to be used in representing the query operation.
   /// ## markedElements
   /// An array of the elements {𝑘ᵢ} for which 𝑓 should return 1.
   ///
   /// # Return
   /// An operation representing the unitary 𝑈 |𝑧〉 |𝑘〉 = |𝑧 ⊕ 𝑥ₖ〉 |𝑘〉.
   function GetBooleanFunctionFromMarkedElements (nQubits : Int, markedElements : Int[]) : (Qubit[] => Unit) {
       
       return GetBooleanFunctionFromMarkedElementsImpl(nQubits, markedElements, _);
   }
   
     
     
     
   
    
    
    
}

The Driver file will have the following code to execute DeutschJozsaAlgorithm.

/////////////////////////////////////////////////////////////////////
// This file contains the driver class.
//////////////////////////////////////////////////////////////////////

using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.Simulators;
using System;


namespace DeutschJozsaAlgorithm
{
    class Driver
    {
     

        static void Main(string[] args)
        {
           
            var sim = new QuantumSimulator(throwOnReleasingQubitsNotInZeroState: true);         
            var balancedTestCase = new QArray<long> { 1, 2 }; 
            if (ExecuteDeutschJozsaAlgorithm.Run(sim, 2, balancedTestCase).Result)
            {
                throw new Exception("Both the test cases  are constant!");
            }

            var constantTestCase = new QArray<long> { 0, 1, 2, 3, 4, 5, 6, 7 };
            if (!ExecuteDeutschJozsaAlgorithm.Run(sim, 3, constantTestCase).Result)
            {
                throw new Exception("All test cases are balanced!");
            }
            System.Console.WriteLine("constant and balanced functions - success");

           
           

          

        }
    }
}

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:

Quantum algorithms

Quantum Algorithm is related to an algorithms executed on a realistic model of quantum computation. It is a step by step procedure for solving a problem on a quantum computer. This chapter will explain about the major quantum algorithms developed for different purposes. There are mainly four approaches in developing algorithms, Quantum Fourier Transform, Quantum walk, BQP (bounded-error, quantum, polynomial time) and classical hybrid. We will discuss the following group of algorithms and their mathematical formulation with the code samples.

  • Quantum Fourier Transform
  • Quantum Walk Algorithms
  • BQP Algorithms
  • Amplitude Amplification Algorithms
  • Hybrid Algorithms

Quantum Fourier Transform

The quantum fourier transform is similar to discrete fourier transform and is implemented in quantum algorithms.  A polynomial number of quantum gates are used for implementing quantum fourier transform on a quantum computer. The following algorithms are based on quantum fourier transform.

  • Quantum Phase Estimation Algorithm
  • Shor’s Algorithm
  • Hidden Subgroup problem
  • Boson Sampling Problem
  • Estimating Gauss Sums
  • Fourier Fishing 
  • Fourier checking
  • Simon’s Algorithm
  • Deutsch-Jozsa Algorithm
  • Bernstein–Vazirani Algorithm

Q# – Function Objects

A delegate in C# is like a function object in C++. The delegate object can be passed to a code. Delegate encapsulates a reference to a method inside the object.  The referenced method is executed during runtime. A Test FunctionObject is shown below.

public delegate void TestFunctionObject();using System;

using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.Simulators;

namespace Hello
{
    class Driver
    {
        public static void ParameterFunction()
        {
            Console.WriteLine("Invoked by Delegate");
        }
        static void Main(string[] args)
        {

            TestFunctionObject testFunction = new TestFunctionObject(ParameterFunction);
            testFunction();

        }

    }

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: