# Quantum device fidelity benchmark in Q#

### Introduction

Over last few years, we are facing a quantum computer race where the main challenge is to build efficient and reliable qubits. All players regularly announce their roadmap, a major breakthrough or quantum supremacy.

One of the most important aspects is being able to characterize and measure the quality and fidelity of different quantum devices, as there is a direct effect on the quantum algorithm results.

### The benchmark

For this benchmark, I have implemented Hidden-Shift (HS) and Bernstein–Vazirani (BV) algorithms, with qubit and shot count input parameters. Actually, Azure quantum is restricted to Microsoft’s key partners and customers, so it has not been possible for me to run this benchmark on a real quantum computer, but the module could be easily modified to implement Azure APIs. So the benchmark can only be executed on a quantum simulator (for the moment), meaning that it is not subject to noise and other undesired effects, wich is exactly what we want to evaluate. For having a real quantum computer behaviour, I have introduced the possibility to simulate noise.

### More details

Both algorithms take an input : a bit string for BV algorithm and a shift for HS algorithm, so each algorithm can be run with 2N possible inputs, where N is the number of qubits, by measuring the circuit output we should retrieve the input data. The benchmark runs X times all 2N possible inputs, where X is the shot count and N the qubit count, finally, a fidelity rate is computed from results and a graph is plotted and saved as image.

### The code

Hidden-Shift and Bernstein–Vazirani circuits are implemented in the qsharp_circuit.qs file, below the BV circuit :

``````operation BVCircuit(QubitCount : Int, ShiftIndex : Int, UseNoise : Bool) : Int {
mutable bits = new Result;
set bits = Padded(QubitCount+1, Zero, bits);
using(qubits = Qubit[QubitCount+1]) {

if (UseNoise) {
using(auxiliary = Qubit()) {
H(auxiliary);
for ((index, basis) in Zipped(RangeAsIntArray (0..QubitCount-1), [PauliX, PauliY, PauliZ])) {
Controlled ApplyPauli([auxiliary], ([basis], [qubits[index]]));
}
Reset(auxiliary);
}
}

X(qubits[QubitCount]);
H(qubits[QubitCount]);

for (i in 0..QubitCount-1) {

let TwoPowQubitIndex = 2^(i);

H(qubits[i]);

if (i < QubitCount) {
if ( (TwoPowQubitIndex &&& ShiftIndex) == TwoPowQubitIndex ) {
CNOT(qubits[i], qubits[QubitCount]);
}
}

H(qubits[i]);

}

H(qubits[QubitCount]);

for (i in 0..QubitCount-1) {
set bits w/= i <- MResetZ(qubits[i]);
}

ResetAll(qubits);

}
return ResultArrayAsInt(bits);
}``````

An operation is implemented to run the circuit X times, where X is the shot count :

``````operation RunBVCircuit(Shots : Int, QubitCount : Int, ShiftIndex : Int, UseNoise : Bool) : Int[] {
mutable results = new Int[Shots];
for (i in 0..Shots - 1) {
set results w/= i <- BVCircuit(QubitCount, ShiftIndex, UseNoise);
}
return results;
}``````

The RunBVCircuit returns an array of int containing the result of each shot, post-treated by the qsharp_run_benchmark.py file. This file contains two python functions wich run BV or HS circuit. Each function works on the same way : it creates a 2D array of 2N length containging results of Q# operation.

### Running the benchmark

The benchmark can be run very simply by running the main qsharp_benchmark.py script :

``````from qsharp_modules.qsharp_run_benchmark import *

QuBitCount = 4
Shots = 1024
UseNoise = False

BV_fidelity = RunBVBenchmark(QuBitCount, Shots, UseNoise)
print('Fidelity rate with Bernstein–Vazirani Algorithm : {:.4f}'.format(BV_fidelity))

HS_fidelity = RunHSBenchmark(QuBitCount, Shots, UseNoise)
print('Fidelity rate with Hidden-Shift Algorithm : {:.4f}'.format(HS_fidelity))``````

### Results

The fidelity rate is shown :

``````Fidelity rate with Bernstein–Vazirani Algorithm : 0.5018
Fidelity rate with Hidden-Shift Algorithm : 0.4969``````

And graph are plotted in 3D and saved to file. As example for BV benchmark :