ラベル Q# の投稿を表示しています。 すべての投稿を表示
ラベル Q# の投稿を表示しています。 すべての投稿を表示

2021年7月12日月曜日

Phase estimation

 Since we have the inverse QFFT, we can move to the phase estimation.

In the example, we are going to estimate the eigenvalues of the following matrix:
.

This matrix (or operator) can be written as a tensor product of 
and
.



.

This matrix is obviously unitary and can be used as the U operator in the diagram.
This matrix must be used with a control qubit, and I created a new "operation" matrixOperation in the following code.
The results agree with the example, and it seems that no need to repeat the measurement many times. The following table shows the number of measured bit strings out of 1,000 trials.


BTW, MS-Q# has QFT function which is "Adjoint"able (invertible), and the results are completely identical to mine. And also, I realize that the R1 gate should also take Adjoint, and I should use it instead of multiplying -1.0 to theta.

namespace phaseEstimation {
    open Microsoft.Quantum.Canon;
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Convert;
    open Microsoft.Quantum.Arrays;
    open Microsoft.Quantum.Measurement;
    open Microsoft.Quantum.Math;
    open Microsoft.Quantum.Arithmetic as Arithmetic;
    
    @EntryPoint()
    operation SayHello() : Unit {
        let nQubit = 3; // Number of control qubits
        let maxNum = PowI(2,nQubit);
        mutable counts = new Int[maxNum];
        mutable theta  = new Double[maxNum];
        mutable revSeq = new Int[nQubit];

        for iQubit in 0..(nQubit-1){
            set theta w/= iQubit <- calcTheta(IntAsDouble(iQubit+1));
        }

        for iQubit in 0..(nQubit-1){
            set revSeq w/= iQubit <- nQubit-1-iQubit;
        }
        for trial in 1..1000 {
        use  (resultBits,vec) = (Qubit[nQubit],Qubit[2]) {
            ApplyToEach(Reset,resultBits); // Zero-clear the control qubits
            ApplyToEach(H,resultBits);

            //X(vec[0]);
            //X(vec[1]);

            for iQubit in 0..(nQubit-1){
                (Controlled matrixOperation)([resultBits[iQubit]],(iQubit,vec));
            }

            // Start Inverse QFFT
            let numLoopSwap = Floor(IntAsDouble(nQubit)*0.5);

            for iQubit in revSeq{
                for jQubit in 0..(nQubit-1)-iQubit-1{
                    let kQubit = revSeq[(nQubit-1)-jQubit];
                    let controlQubit = nQubit-kQubit-1;
                    let rotationIndex= nQubit-(kQubit+iQubit)-1;
                    (Controlled R1)([resultBits[controlQubit]],(-1.0*theta[rotationIndex],resultBits[iQubit]));
                }
                H(resultBits[iQubit]);
            }
            //for iQubit in 0..(numLoopSwap-1) {
            //    SWAP(resultBits[iQubit],resultBits[nQubit-1-iQubit]);
            //}              
            //let register = Arithmetic.BigEndian(resultBits);
            //(Adjoint QFT)(register);         
            let res = MultiM(resultBits);
            let bit = ResultArrayAsInt(res);
            set counts w/= bit <- counts[bit]+ 1;
            ResetAll(resultBits);
            ResetAll(vec);
        }
        }
        for j in 0..(maxNum-1)  {
           Message(IntAsString(counts[j]));
        }
    }
    function calcTheta(l : Double) : Double {
        return 2.0*PI()/(PowD(2.0,l));
    }
    operation matrixOperation(iQubit : Int, q : Qubit[]): Unit is Ctl{
       //Message(IntAsString(iQubit)+" "+IntAsString(PowI(2,iQubit)));
        for i in 0..(PowI(2,iQubit)-1){
            S(q[0]);
            T(q[1]);
        }
        return ();
    }
}

2021年5月1日土曜日

Inverse QFT

Based on the last QFT , I tried the inverse QFT.

I got the result of  [640, 654, 573, 666, 615, 601, 635, 654, 616, 603, 646, 602, 629, 605, 593, 668].
This means that the initial state of QFFT is recovered by iQFFT.

The codes of QFT and iQFT are as follows (as far as I understand).



namespace QFT_naive {
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Measurement;
open Microsoft.Quantum.Math;
@EntryPoint()
operation SayHello() : Unit {
let nQubit = 4;
let maxNum = PowI(2,nQubit);
mutable counts = new Int[maxNum];
mutable theta = new Double[maxNum];
mutable revSeq = new Int[nQubit];

for iQubit in 0..(nQubit-1){
set theta w/= iQubit <- calcTheta(IntAsDouble(iQubit+1));
}

for iQubit in 0..(nQubit-1){
set revSeq w/= iQubit <- nQubit-1-iQubit;
}
for trial in 1..10000 {
use input = Qubit[nQubit] {
// 1/sqrt(8) (|000> + |001> + ,,, + |111>)
for iQubit in 0..(nQubit-1){
H(input[iQubit]);
}

// Star QFT
for iQubit in 0..(nQubit-1){
H(input[iQubit]);
for jQubit in 1..(nQubit-1-iQubit){
(Controlled R1)([input[jQubit+iQubit]],(theta[jQubit],input[iQubit]));
}

}

let numLoopSwap = Floor(IntAsDouble(nQubit)*0.5);
for iQubit in 0..(numLoopSwap-1) {
SWAP(input[iQubit],input[nQubit-1-iQubit]);
}
// Start Inverse QFFT
for iQubit in 0..(numLoopSwap-1) {
SWAP(input[iQubit],input[nQubit-1-iQubit]);
}
for iQubit in revSeq{
for jQubit in 0..(nQubit-1)-iQubit-1{
let kQubit = revSeq[(nQubit-1)-jQubit];
let controlQubit = nQubit-kQubit-1;
let rotationIndex= nQubit-(kQubit+iQubit)-1;
(Controlled R1)([input[controlQubit]],(-1.0*theta[rotationIndex],input[iQubit]));
}
H(input[iQubit]);
}
let res = MultiM(input);
let bit = ResultArrayAsInt(res);
set counts w/= bit <- counts[bit]+ 1;
ResetAll(input);
}
}
for j in 0..(maxNum-1) {
Message(IntAsString(counts[j]));
}
}
function calcTheta(l : Double) : Double {
return 2.0*PI()/(PowD(2.0,l));
}
}


2021年3月21日日曜日

QFT part 5: adjustable number of qubits

As continued from QFT part 4 , the number of qubits is now adjustable.

NQubit = 3 and 4 are working correctly.

I think I made a mistake and updated on 1st of May, 2021.

namespace QFT_naive {
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Measurement;
open Microsoft.Quantum.Math;
@EntryPoint()
operation SayHello() : Unit {
let nQubit = 4;
let maxNum = PowI(2,nQubit);
mutable counts = new Int[maxNum];
mutable theta = new Double[maxNum];

for iQubit in 0..(nQubit-1){
set theta w/= iQubit <- calcTheta(IntAsDouble(iQubit+1));
}

for trian in 1..1000 {
use input = Qubit[nQubit] {
// 1/sqrt(8) (|000> + |001> + ,,, + |111>)
for iQubit in 0..(nQubit-1){
H(input[iQubit]);
}

// Star QFT
for iQubit in 0..(nQubit-1){
H(input[iQubit]);
for jQubit in 1..(nQubit-1-iQubit){
(Controlled R1)([input[jQubit+iQubit]],(theta[jQubit],input[iQubit]));
}
}
//H(input[0]);
//(Controlled R1)([input[1]],(theta[1],input[0]));
//(Controlled R1)([input[2]],(theta[2],input[0]));
//H(input[1]);
//(Controlled R1)([input[2]],(theta[1],input[1]));

//H(input[2]);

let numLoopSwap = Floor(IntAsDouble(nQubit)*0.5);


for iQubit in 0..(numLoopSwap-1) {
SWAP(input[iQubit],input[nQubit-1-iQubit]);
}
//SWAP(input[2],input[0]);

let res = MultiM(input);
let bit = ResultArrayAsInt(res);
set counts w/= bit <- counts[bit]+ 1;
ResetAll(input);
}
}
for j in 0..(maxNum-1) {
Message(IntAsString(counts[j]));
}
}
function calcTheta(l : Double) : Double {
return 2.0*PI()/(PowD(2.0,l));
}
}


2021年3月14日日曜日

QFT part 4: Using R1 gate, instead of S and T.

Since I do want to extend the number of qubits from three to more, I have re-written the code with R1 gate, in stead of S and T.

Lessons learned: Functions and operations can be defined. Here a function which returns Double is created. Operations might be used for qubits. Not sure now.

namespace QFT_naive {
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Measurement;
open Microsoft.Quantum.Math;
@EntryPoint()
operation SayHello() : Unit {
mutable counts = new Int[8];

let theta_1 = calcTheta(1.0);
let theta_2 = calcTheta(2.0);
let theta_3 = calcTheta(3.0);

for trian in 1..1000 {
use input = Qubit[3] {
// 1/sqrt(8) (|000> + |001> + ,,, + |111>)
H(input[0]);
H(input[1]);
H(input[2]);

// Star QFT
// R1 = Z, R2=S, R3=T
H(input[0]);
//(Controlled S)([input[1]],input[0]);
//(Controlled T)([input[2]],input[0]);
(Controlled R1)([input[1]],(theta_2,input[0]));
(Controlled R1)([input[2]],(theta_3,input[0]));

H(input[1]);
//(Controlled S)([input[2]],input[1]);
(Controlled R1)([input[2]],(theta_2,input[1]));

H(input[2]);

SWAP(input[2],input[0]);

let res = MultiM(input);
let bit = ResultArrayAsInt(res);
set counts w/= bit <- counts[bit]+ 1;
ResetAll(input);
}
}
for j in 0..7 {
Message(IntAsString(counts[j]));
}
}
function calcTheta(l : Double) : Double {
return 2.0*PI()/(PowD(2.0,l));
}
}


 

2021年3月7日日曜日

QFT part 3. With ResultArrayAsInt and MultiM.

Still playing around QFFT. Improved the last one with ResultArrayAsInt and MultiM.
Those allow me to shorten the code a bit, and may allow me to go the 4 qubit case.

One thing I am not quite sure is, which end is the LSB?
I suspect 0 is the LSB, but no clue.

namespace QFT_naive {
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Measurement;

@EntryPoint()
operation SayHello() : Unit {
Message("qFFT");
mutable counts = new Int[8];

for trian in 1..1000 {
use input = Qubit[3] {
// 1/sqrt(8) (|000> + |001> + ,,, + |111>)
H(input[0]);
H(input[1]);
H(input[2]);

// Star QFT
// R1 = Z, R2=S, R3=T
H(input[0]);
(Controlled S)([input[1]],input[0]);
(Controlled T)([input[2]],input[0]);

H(input[1]);
(Controlled S)([input[2]],input[1]);

H(input[2]);

SWAP(input[2],input[0]);

let res = MultiM(input);
let bit = ResultArrayAsInt(res);
set counts w/= bit <- counts[bit]+ 1;
ResetAll(input);
}
}
for j in 0..7 {
Message(IntAsString(counts[j]));
}
}
}



I think 0 is LSB because when I modify the code as follows; 5th element (namely 100=4) of "count" has "1000"

mutable res = MultiM(input);
set res w/= 2 <- One;
let bit = ResultArrayAsInt(res);

2021年1月31日日曜日

Q# without VS code

 Not sure the reason, but I cannot install Q# template with newly install Ubuntu 20.04 and VS code.
I have just learned that CLI also works.

% dotnet new console -lang Q# -o [ProjectName] % cd [ProjectName]
% dotnet build % dotnet run

I needed to install .NET-SDK 3.1, instead of 5.0.

2020年11月6日金曜日

Quantum Fourier Transform (QFT) on Q# (3 qubits) Part2

 QFT with three qubits is implemented in Q#.
The last post was to initialize the original state (entangled over three qubits).
I feel the measurement part should be as this post (the last one is incorrect).

Formulation is;
https://dojo.qulacs.org/ja/latest/notebooks/2.3_quantum_Fourier_transform.html#

The result is;
|000>: 1000, others: 0.
This agrees with the result of the above site :)!

namespace QFT_naive {
    open Microsoft.Quantum.Canon;
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Convert;
    open Microsoft.Quantum.Arrays;
    

    @EntryPoint()
    operation SayHello() : Unit {
        Message("Hello quantum world!");
        mutable counts = new Int[8];
        mutable nres0 = 0;
        mutable nres1 = 0;
        mutable nres2 = 0;

        for(trian in 1..1000){
        using ( (input) = (Qubit[3] ) ){
            // 1/sqrt(8) (|000> + |001> + ,,, + |111>)
            H(input[0]);
            H(input[1]);
            H(input[2]);

            // Star QFT
            // R1 = Z, R2=S, R3=T
            H(input[0]);
            (Controlled S)([input[1]],input[0]);
            (Controlled T)([input[2]],input[0]);

            H(input[1]);
            (Controlled S)([input[2]],input[1]);

            H(input[2]);

            SWAP(input[2],input[0]);
            //CNOT(input[0], input[2]);
            //CNOT(input[2], input[0]);
            //CNOT(input[0], input[2]);

            // Start Measuring
            let res0 = M(input[0]);
            let res1 = M(input[1]);
            let res2 = M(input[2]);
            if (res0 == Zero){
                set nres0 = 0;
            }else{
                set nres0 = 1;
            }
            if (res1 == Zero){
                set nres1 = 0;
            }else{
                set nres1 = 1;
            }
            if (res2 == Zero){
                set nres2 = 0;
            }else{
                set nres2 = 1;
            }
            let bit = nres0 + nres1*2 + nres2*4;
            set counts w/= bit <- counts[bit]+ 1;
            ResetAll(input);
        }
        }
        for (j in 0..7) {
           Message(IntAsString(counts[j]));
        }
    }
}

2020年10月23日金曜日

Quantum Fourier Transform (QFT) Part 1

I'm trying to implement Quantum Fourier Transform (QFT), not from "Quantum Algorithm Implementations for Beginners" but Quantum Dojo (https://dojo.qulacs.org/ja/latest/notebooks/2.3_quantum_Fourier_transform.html# ).
That's because "Beginners" does not explain the algorithm in detail.

Quantum Dojo's one needs the computation of  1/sqrt(8)(|000>+|001>+,,,+|111> (in 3 qubits case), which is not clear in Q#.

I think this could be formed by applying the Adamard Gate for all qubits, and in order to make sure that I am correct, I have implemented the following code.

The results are:117, 107, 125, 138, 128, 144, 133, 108.
Although there are errors because of random numbers, in general looks OK.

namespace QFT_naive {
    open Microsoft.Quantum.Canon;
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Convert;
    open Microsoft.Quantum.Arrays;
    

    @EntryPoint()
    operation SayHello() : Unit {
        Message("Hello quantum world!");
        mutable counts = new Int[8];
        mutable nres0 = 0;
        mutable nres1 = 0;
        mutable nres2 = 0;

        for(trian in 1..1000){
        using ( (input) = (Qubit[3] ) ){
            // 1/sqrt(8) (|000> + |001> + ,,, + |111>)
            H(input[0]);
            H(input[1]);
            H(input[2]);

            let res0 = M(input[0]);
            let res1 = M(input[1]);
            let res2 = M(input[2]);
            if (res0 == Zero){
                set nres0 = 1;
            }else{
                set nres0 = 0;
            }
            if (res1 == Zero){
                set nres1 = 1;
            }else{
                set nres1 = 0;
            }
            if (res2 == Zero){
                set nres2 = 1;
            }else{
                set nres2 = 0;
            }
            let bit = nres0 + nres1*2 + nres2*4;
            set counts w/= bit <- counts[bit]+ 1;
            ResetAll(input);
        }
        }
        for (j in 0..7) {
           Message(IntAsString(counts[j]));
        }
    }
}

2020年10月16日金曜日

With NEW SDK "Rewriting sample codes in Quantum Algorithm Implementations for Beginners (Bell state)"

 Since the new SDK does not use Driver.cs, the Bell state example needs to be rewritten without the C# part.

Now you only need to write Program.qs, and the example looks like,
Result is |00> 500, |01> 0, |10> 0, |11> 500. Looks still valid.

namespace QFT_naive {
    open Microsoft.Quantum.Canon;
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Convert;
    

    @EntryPoint()
    operation SayHello() : Unit {
        Message("Hello quantum world!");
        mutable n00 = 0;
        mutable n01 = 0;
        mutable n10 = 0;
        mutable n11 = 0;

        for(trian in 1..1000){
        using ( (qubit0, qubit1) = (Qubit(), Qubit()) ){
            H(qubit0);
            CNOT(qubit0,qubit1);

            let res0 = M(qubit0);
            let res1 = M(qubit1);

            if(res0 == Zero){
                if(res1 == Zero){
                    set n00 += 1;
                }else{
                    set n01 += 1;
                }
            }else{
                if(res1 == Zero){
                    set n10 += 1;
                }else{
                    set n11 += 1;
                }

            }
            Reset(qubit0);
            Reset(qubit1);
        }
        }
        Message(IntAsString(n00));
        Message(IntAsString(n01));
        Message(IntAsString(n10));
        Message(IntAsString(n11));
    }
}

2020年8月4日火曜日

List of gates available in Q#

I always lose the list of Q#, and so, I would like to put it as memo here.

https://docs.microsoft.com/en-us/qsharp/api/qsharp/microsoft.quantum.intrinsic

Grover's algorithm (Algorithm 1, in Section 2)

Continuation of Q# practice (Bell state).
Grover's algorithm described in Section 2, Algorithm 1.
In this example, Oracle is expressed just with Toffoli (CCNOT) gate, and this is not a general implementation, as far as I understand.

In the literature, they constructed CCNOT with natively supported gates, but Q# has it, and I just used it (control and ancillary are a bit confusing to me though).

By running my sample code the numbers of measurements observed in 1000 trials are;
00:0, 01:0, 10:0, 11:1000
Unlike the previous one, the result is completely the same as the theory.

I feel I should split Q# and C# parts in a better way.
In any case, I am getting used to it, hopefully.

Sample codes are;
Q# (Program.qs)
/// # Summary
/// 
namespace Grover {

    open Microsoft.Quantum.Canon;
    open Microsoft.Quantum.Intrinsic;
    

    operation Grover() : (Int,Int,Int,Int) {
        Message("This is Q# implementation of Algorithm 1 in Quantum Algorithm Implementaions for Beginners");

        mutable n00 = 0;
        mutable n01 = 0;
        mutable n10 = 0;
        mutable n11 = 0;

        for(trial in 1..1000){
        using ( (qubit0, qubit1, qubit2) = (Qubit(), Qubit(),Qubit()) ){
            // qubit0: ancillar
            // qubit1, 2: x1, x2

            //Initializaiton
            X(qubit0);
            H(qubit0);
            H(qubit1);
            H(qubit2);
            // qubit0 is called ancillar, looking at the following site and the article, it should be the target
            // https://quantumcomputing.stackexchange.com/questions/3943/how-do-you-implement-the-toffoli-gate-using-only-single-qubit-and-cnot-gates
            CCNOT(qubit1,qubit2,qubit0); //Toffoli gate

            // Grover diffusion operator
            H(qubit1);
            X(qubit1);
            H(qubit1);

            H(qubit2);
            X(qubit2);

            CNOT(qubit2,qubit1);

            H(qubit1);
            X(qubit1);
            H(qubit1);

            X(qubit2);
            H(qubit2);

            let res0 = M(qubit1);
            let res1 = M(qubit2);
            if(res0 == Zero){
                if(res1 == Zero){
                    set n00 += 1;
                }else{
                    set n01 += 1;
                }
            }else{
                if(res1 == Zero){
                    set n10 += 1;
                }else{
                    set n11 += 1;
                }

            }
            Reset(qubit0);
            Reset(qubit1);
            Reset(qubit2);
        }
        }
        return(n00,n01,n10,n11);
    }
}



C# (Driver.cs)
using System;

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

namespace Grover
{
    class Driver
    {
        static void Main(string[] args)
        {
            
            using (var qsim = new QuantumSimulator())
            {
                long a,b,c,d;
                (a,b,c,d) = Grover.Run(qsim).Result;
                Console.WriteLine("{0},{1},{2},{3}",a,b,c,d);
            }
        }
    }
}

2020年7月17日金曜日

Rewriting sample codes in Quantum Algorithm Implementations for Beginners (Bell state)

I have changed the strategy of learning Quantum algorithms.
Now, I am following  "Quantum Algorithm Implementations for Beginners".

The first trial is to construct Bell state and check if the understanding is correct.
By running my sample code the numbers of measurements observed in 1000 trials are;
|00>:494, |01>:0, |10>:0, |11>:506
There is a good agreement with the textbook

A sample code is;
Q# (Program.qs)
namespace Bell2 {

    open Microsoft.Quantum.Canon;
    open Microsoft.Quantum.Intrinsic;
    
    operation Bell() : (Int,Int,Int,Int) {
        Message("Hello quantum world!");

        mutable n00 = 0;
        mutable n01 = 0;
        mutable n10 = 0;
        mutable n11 = 0;

        for(trian in 1..1000){
        using ( (qubit0, qubit1) = (Qubit(), Qubit()) ){
            H(qubit0);
            CNOT(qubit0,qubit1);

            let res0 = M(qubit0);
            let res1 = M(qubit1);

            if(res0 == Zero){
                if(res1 == Zero){
                    set n00 += 1;
                }else{
                    set n01 += 1;
                }
            }else{
                if(res1 == Zero){
                    set n10 += 1;
                }else{
                    set n11 += 1;
                }

            }
            Reset(qubit0);
            Reset(qubit1);
        }
        }

        //Message("00:#, 01:#, 10:#, 11:#");
        return(n00,n01,n10,n11);
    }
}

C# (Driver.cs)

using System;

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

namespace Bell2
{
    class Driver
    {
        static void Main(string[] args)
        {
            using (var qsim = new QuantumSimulator())
            {
            long a,b,c,d;
            (a,b,c,d) = Bell.Run(qsim).Result;
            Console.WriteLine("{0},{1},{2},{3}",a,b,c,d);
            }

            
        }
    }
}

Otherwise, files are created automatically when one creates a new project, namely,
  • Go to View -> Command Palette
  • Select Q#: Create New Project
  • Select Standalone console application
  • Navigate to the location on the file system where you would like to create the application
  • Click on the Open new project... button, once the project has been created

2020年3月16日月曜日

Q# + C# on Ubuntu 18.04

職場の計算機が使えないので、Q#勉強用の環境をLinuxに構築。
VS Codeはインストールできているとして、C#の環境は以下で簡単に構築可能。

https://docs.microsoft.com/ja-jp/dotnet/core/install/linux-package-manager-ubuntu-1804

2020年2月3日月曜日