2018-10-30 18:48:56 +03:00
// Copyright (c) Microsoft Corporation. All rights reserved.
2018-07-12 02:35:59 +03:00
// Licensed under the MIT license.
//////////////////////////////////////////////////////////////////////
2018-10-30 18:48:56 +03:00
// This file contains testing harness for all tasks.
2018-07-12 02:35:59 +03:00
// You should not modify anything in this file.
// The tasks themselves can be found in Tasks.qs file.
//////////////////////////////////////////////////////////////////////
2018-10-30 18:48:56 +03:00
namespace Quantum.Kata.Measurements {
2018-07-12 02:35:59 +03:00
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Extensions.Testing;
2018-10-30 18:48:56 +03:00
2019-04-26 01:57:30 +03:00
open Quantum.Kata.Utils;
2018-07-12 02:35:59 +03:00
//////////////////////////////////////////////////////////////////
2018-10-30 18:48:56 +03:00
2018-07-12 02:35:59 +03:00
// "Framework" operation for testing single-qubit tasks for distinguishing states of one qubit
// with Bool return
2018-10-30 18:48:56 +03:00
operation DistinguishTwoStates_OneQubit (statePrep : ((Qubit, Int) => Unit), testImpl : (Qubit => Bool)) : Unit {
let nTotal = 100;
mutable nOk = 0;
2018-07-12 02:35:59 +03:00
2018-10-30 18:48:56 +03:00
using (qs = Qubit[1]) {
for (i in 1 .. nTotal) {
// get a random bit to define whether qubit will be in a state corresponding to true return (1) or to false one (0)
// state = 0 false return
// state = 1 true return
let state = RandomIntPow2(1);
// do state prep: convert |0⟩ to outcome with false return or to outcome with true return depending on state
statePrep(qs[0], state);
// get the solution's answer and verify that it's a match
let ans = testImpl(qs[0]);
if (ans == (state == 1)) {
set nOk = nOk + 1;
2018-07-12 02:35:59 +03:00
}
2018-10-30 18:48:56 +03:00
// we're not checking the state of the qubit after the operation
Reset(qs[0]);
2018-07-12 02:35:59 +03:00
}
}
2018-10-30 18:48:56 +03:00
AssertIntEqual(nOk, nTotal, $"{nTotal - nOk} test runs out of {nTotal} returned incorrect state.");
2018-07-12 02:35:59 +03:00
}
2018-10-30 18:48:56 +03:00
2018-07-12 02:35:59 +03:00
// ------------------------------------------------------
2018-10-30 18:48:56 +03:00
operation StatePrep_IsQubitOne (q : Qubit, state : Int) : Unit {
if (state == 0) {
// convert |0⟩ to |0⟩
} else {
// convert |0⟩ to |1⟩
X(q);
2018-07-12 02:35:59 +03:00
}
}
2018-10-30 18:48:56 +03:00
operation T101_IsQubitOne_Test () : Unit {
DistinguishTwoStates_OneQubit(StatePrep_IsQubitOne, IsQubitOne);
2018-07-12 02:35:59 +03:00
}
2018-10-30 18:48:56 +03:00
2018-10-17 02:41:22 +03:00
// ------------------------------------------------------
2018-10-30 18:48:56 +03:00
operation T102_InitializeQubit_Test () : Unit {
using (qs = Qubit[1]) {
for (i in 0 .. 36) {
let alpha = ((2.0 * PI()) * ToDouble(i)) / 36.0;
Ry(2.0 * alpha, qs[0]);
// Test Task 1
InitializeQubit(qs[0]);
// Confirm that the state is |0⟩.
AssertAllZero(qs);
2018-10-17 02:41:22 +03:00
}
}
}
2018-10-30 18:48:56 +03:00
2018-07-12 02:35:59 +03:00
// ------------------------------------------------------
2018-10-30 18:48:56 +03:00
operation StatePrep_IsQubitPlus (q : Qubit, state : Int) : Unit {
if (state == 0) {
// convert |0⟩ to |-⟩
X(q);
H(q);
} else {
// convert |0⟩ to |+⟩
H(q);
2018-07-12 02:35:59 +03:00
}
}
2018-10-30 18:48:56 +03:00
operation T103_IsQubitPlus_Test () : Unit {
DistinguishTwoStates_OneQubit(StatePrep_IsQubitPlus, IsQubitPlus);
2018-07-12 02:35:59 +03:00
}
2018-10-30 18:48:56 +03:00
2018-07-12 02:35:59 +03:00
// ------------------------------------------------------
2018-10-30 18:48:56 +03:00
// |A⟩ = cos(alpha) * |0⟩ + sin(alpha) * |1⟩,
2018-08-06 20:56:25 +03:00
// |B⟩ = - sin(alpha) * |0⟩ + cos(alpha) * |1⟩.
2018-10-30 18:48:56 +03:00
operation StatePrep_IsQubitA (alpha : Double, q : Qubit, state : Int) : Unit {
if (state == 0) {
// convert |0⟩ to |B⟩
X(q);
Ry(2.0 * alpha, q);
} else {
// convert |0⟩ to |A⟩
Ry(2.0 * alpha, q);
2018-07-12 02:35:59 +03:00
}
}
2018-10-30 18:48:56 +03:00
operation T104_IsQubitA_Test () : Unit {
// cross-test
// alpha = 0.0 or PI() => !isQubitOne
// alpha = PI() / 2.0 => isQubitOne
DistinguishTwoStates_OneQubit(StatePrep_IsQubitOne, IsQubitA(PI() / 2.0, _));
// alpha = PI() / 4.0 => isQubitPlus
DistinguishTwoStates_OneQubit(StatePrep_IsQubitPlus, IsQubitA(PI() / 4.0, _));
for (i in 0 .. 10) {
let alpha = (PI() * ToDouble(i)) / 10.0;
DistinguishTwoStates_OneQubit(StatePrep_IsQubitA(alpha, _, _), IsQubitA(alpha, _));
2018-07-12 02:35:59 +03:00
}
}
2018-10-30 18:48:56 +03:00
2018-07-12 02:35:59 +03:00
// ------------------------------------------------------
2018-10-30 18:48:56 +03:00
2018-07-12 02:35:59 +03:00
// "Framework" operation for testing multi-qubit tasks for distinguishing states of an array of qubits
// with Int return
2019-04-26 01:57:30 +03:00
operation DistinguishStates_MultiQubit (Nqubit : Int,
Nstate : Int,
statePrep : ((Qubit[], Int) => Unit),
testImpl : (Qubit[] => Int),
measurementsPerRun : Int) : Unit {
2018-10-30 18:48:56 +03:00
let nTotal = 100;
mutable nOk = 0;
2018-07-12 02:35:59 +03:00
2018-10-30 18:48:56 +03:00
using (qs = Qubit[Nqubit]) {
for (i in 1 .. nTotal) {
// get a random integer to define the state of the qubits
let state = RandomInt(Nstate);
// do state prep: convert |0...0⟩ to outcome with return equal to state
statePrep(qs, state);
2019-04-26 01:57:30 +03:00
if (measurementsPerRun > 0) {
ResetOracleCallsCount();
}
2018-10-30 18:48:56 +03:00
// get the solution's answer and verify that it's a match
let ans = testImpl(qs);
if (ans == state) {
set nOk = nOk + 1;
2018-07-12 02:35:59 +03:00
}
2019-04-26 01:57:30 +03:00
// if we have a max number of measurements per solution run specified, check that it is not exceeded
if (measurementsPerRun > 0) {
let nm = GetOracleCallsCount(M) + GetOracleCallsCount(Measure);
AssertBoolEqual(nm <= 1, true, $"You are allowed to do at most one measurement, and you did {nm}");
}
2018-10-30 18:48:56 +03:00
// we're not checking the state of the qubit after the operation
ResetAll(qs);
2018-07-12 02:35:59 +03:00
}
}
2018-10-30 18:48:56 +03:00
AssertIntEqual(nOk, nTotal, $"{nTotal - nOk} test runs out of {nTotal} returned incorrect state.");
2018-07-12 02:35:59 +03:00
}
2018-10-30 18:48:56 +03:00
2018-07-12 02:35:59 +03:00
// ------------------------------------------------------
2018-10-30 18:48:56 +03:00
operation StatePrep_ZeroZeroOrOneOne (qs : Qubit[], state : Int) : Unit {
if (state == 1) {
// |11⟩
X(qs[0]);
X(qs[1]);
2018-07-12 02:35:59 +03:00
}
}
2018-10-30 18:48:56 +03:00
operation T105_ZeroZeroOrOneOne_Test () : Unit {
2019-04-26 01:57:30 +03:00
DistinguishStates_MultiQubit(2, 2, StatePrep_ZeroZeroOrOneOne, ZeroZeroOrOneOne, 0);
2018-07-12 02:35:59 +03:00
}
2018-10-30 18:48:56 +03:00
2018-07-12 02:35:59 +03:00
// ------------------------------------------------------
2018-10-30 18:48:56 +03:00
operation StatePrep_BasisStateMeasurement (qs : Qubit[], state : Int) : Unit {
if (state / 2 == 1) {
// |10⟩ or |11⟩
X(qs[0]);
2018-07-12 02:35:59 +03:00
}
2018-10-30 18:48:56 +03:00
if (state % 2 == 1) {
// |01⟩ or |11⟩
X(qs[1]);
2018-07-12 02:35:59 +03:00
}
}
2018-10-30 18:48:56 +03:00
operation T106_BasisStateMeasurement_Test () : Unit {
2019-04-26 01:57:30 +03:00
DistinguishStates_MultiQubit(2, 4, StatePrep_BasisStateMeasurement, BasisStateMeasurement, 0);
2018-10-30 18:48:56 +03:00
}
2018-07-12 02:35:59 +03:00
// ------------------------------------------------------
2018-10-30 18:48:56 +03:00
operation StatePrep_Bitstring (qs : Qubit[], bits : Bool[]) : Unit {
for (i in 0 .. Length(qs) - 1) {
if (bits[i]) {
X(qs[i]);
2018-07-12 02:35:59 +03:00
}
}
}
2018-10-30 18:48:56 +03:00
operation StatePrep_TwoBitstringsMeasurement (qs : Qubit[], bits1 : Bool[], bits2 : Bool[], state : Int) : Unit {
if (state == 0) {
StatePrep_Bitstring(qs, bits1);
} else {
StatePrep_Bitstring(qs, bits2);
2018-07-12 02:35:59 +03:00
}
}
2018-10-30 18:48:56 +03:00
2019-04-26 01:57:30 +03:00
operation CheckTwoBitstringsMeasurement (b1 : Bool[], b2 : Bool[]) : Unit {
DistinguishStates_MultiQubit(Length(b1), 2, StatePrep_TwoBitstringsMeasurement(_, b1, b2, _), TwoBitstringsMeasurement(_, b1, b2), 1);
}
2018-10-30 18:48:56 +03:00
operation T107_TwoBitstringsMeasurement_Test () : Unit {
2019-04-26 01:57:30 +03:00
CheckTwoBitstringsMeasurement([false, true], [true, false]);
CheckTwoBitstringsMeasurement([true, true, false], [false, true, true]);
CheckTwoBitstringsMeasurement([false, true, true, false], [false, true, true, true]);
CheckTwoBitstringsMeasurement([true, false, false, false], [true, false, true, true]);
2018-07-12 02:35:59 +03:00
}
2018-10-30 18:48:56 +03:00
2018-07-12 02:35:59 +03:00
// ------------------------------------------------------
2018-10-30 18:48:56 +03:00
operation WState_Arbitrary_Reference (qs : Qubit[]) : Unit {
body (...) {
2018-07-12 02:35:59 +03:00
let N = Length(qs);
2018-10-30 18:48:56 +03:00
2018-07-12 02:35:59 +03:00
if (N == 1) {
2018-08-06 20:56:25 +03:00
// base case of recursion: |1⟩
2018-07-12 02:35:59 +03:00
X(qs[0]);
} else {
2018-08-06 20:56:25 +03:00
// |W_N> = |0⟩|W_(N-1)> + |1⟩|0...0⟩
// do a rotation on the first qubit to split it into |0⟩ and |1⟩ with proper weights
// |0⟩ -> sqrt((N-1)/N) |0⟩ + 1/sqrt(N) |1⟩
2018-07-12 02:35:59 +03:00
let theta = ArcSin(1.0 / Sqrt(ToDouble(N)));
Ry(2.0 * theta, qs[0]);
2018-10-30 18:48:56 +03:00
2018-07-12 02:35:59 +03:00
// do a zero-controlled W-state generation for qubits 1..N-1
X(qs[0]);
2018-10-30 18:48:56 +03:00
Controlled WState_Arbitrary_Reference(qs[0 .. 0], qs[1 .. N - 1]);
2018-07-12 02:35:59 +03:00
X(qs[0]);
}
}
2018-10-30 18:48:56 +03:00
adjoint invert;
controlled distribute;
controlled adjoint distribute;
2018-07-12 02:35:59 +03:00
}
2018-10-30 18:48:56 +03:00
operation StatePrep_AllZerosOrWState (qs : Qubit[], state : Int) : Unit {
if (state == 1) {
// prep W state
WState_Arbitrary_Reference(qs);
2018-07-12 02:35:59 +03:00
}
}
2018-10-30 18:48:56 +03:00
operation T108_AllZerosOrWState_Test () : Unit {
for (i in 2 .. 6) {
2019-04-26 01:57:30 +03:00
DistinguishStates_MultiQubit(i, 2, StatePrep_AllZerosOrWState, AllZerosOrWState, 0);
2018-07-12 02:35:59 +03:00
}
}
2018-10-30 18:48:56 +03:00
2018-07-12 02:35:59 +03:00
// ------------------------------------------------------
2018-10-30 18:48:56 +03:00
operation GHZ_State_Reference (qs : Qubit[]) : Unit {
body (...) {
2018-07-12 02:35:59 +03:00
H(qs[0]);
2018-10-30 18:48:56 +03:00
for (i in 1 .. Length(qs) - 1) {
2018-07-12 02:35:59 +03:00
CNOT(qs[0], qs[i]);
}
}
2018-10-30 18:48:56 +03:00
adjoint invert;
2018-07-12 02:35:59 +03:00
}
2018-10-30 18:48:56 +03:00
operation StatePrep_GHZOrWState (qs : Qubit[], state : Int) : Unit {
if (state == 0) {
// prep GHZ state
GHZ_State_Reference(qs);
} else {
// prep W state
WState_Arbitrary_Reference(qs);
2018-07-12 02:35:59 +03:00
}
}
2018-10-30 18:48:56 +03:00
operation T109_GHZOrWState_Test () : Unit {
for (i in 2 .. 6) {
2019-04-26 01:57:30 +03:00
DistinguishStates_MultiQubit(i, 2, StatePrep_GHZOrWState, GHZOrWState, 0);
2018-07-12 02:35:59 +03:00
}
}
2018-10-30 18:48:56 +03:00
2018-07-12 02:35:59 +03:00
// ------------------------------------------------------
2018-08-06 20:56:25 +03:00
// 0 - |Φ⁺⟩ = (|00⟩ + |11⟩) / sqrt(2)
// 1 - |Φ⁻⟩ = (|00⟩ - |11⟩) / sqrt(2)
// 2 - |Ψ⁺⟩ = (|01⟩ + |10⟩) / sqrt(2)
// 3 - |Ψ⁻⟩ = (|01⟩ - |10⟩) / sqrt(2)
2018-10-30 18:48:56 +03:00
operation StatePrep_BellState (qs : Qubit[], state : Int) : Unit {
H(qs[0]);
CNOT(qs[0], qs[1]);
// now we have |00⟩ + |11⟩ - modify it based on state arg
if (state % 2 == 1) {
// negative phase
Z(qs[1]);
2018-07-12 02:35:59 +03:00
}
2018-10-30 18:48:56 +03:00
if (state / 2 == 1) {
X(qs[1]);
2018-07-12 02:35:59 +03:00
}
}
2018-10-30 18:48:56 +03:00
operation T110_BellState_Test () : Unit {
2019-04-26 01:57:30 +03:00
DistinguishStates_MultiQubit(2, 4, StatePrep_BellState, BellState, 0);
2018-10-30 18:48:56 +03:00
}
2018-07-12 02:35:59 +03:00
// ------------------------------------------------------
2018-08-06 20:56:25 +03:00
// 0 - (|00⟩ + |01⟩ + |10⟩ + |11⟩) / 2
// 1 - (|00⟩ - |01⟩ + |10⟩ - |11⟩) / 2
// 2 - (|00⟩ + |01⟩ - |10⟩ - |11⟩) / 2
// 3 - (|00⟩ - |01⟩ - |10⟩ + |11⟩) / 2
2018-10-30 18:48:56 +03:00
operation StatePrep_TwoQubitState (qs : Qubit[], state : Int) : Unit {
// start with state prep of basis vectors
StatePrep_BasisStateMeasurement(qs, state);
H(qs[0]);
H(qs[1]);
2018-07-12 02:35:59 +03:00
}
2018-10-30 18:48:56 +03:00
2019-04-26 01:57:30 +03:00
operation T111_TwoQubitState_Test () : Unit {
DistinguishStates_MultiQubit(2, 4, StatePrep_TwoQubitState, TwoQubitState, 0);
}
2018-07-12 02:35:59 +03:00
// ------------------------------------------------------
2018-08-06 20:56:25 +03:00
// 0 - ( |00⟩ - |01⟩ - |10⟩ - |11⟩) / 2
// 1 - (-|00⟩ + |01⟩ - |10⟩ - |11⟩) / 2
// 2 - (-|00⟩ - |01⟩ + |10⟩ - |11⟩) / 2
// 3 - (-|00⟩ - |01⟩ - |10⟩ + |11⟩) / 2
2018-10-30 18:48:56 +03:00
operation StatePrep_TwoQubitStatePartTwo (qs : Qubit[], state : Int) : Unit {
// start with state prep of basis vectors
StatePrep_BasisStateMeasurement(qs, state);
// now apply all gates for unitary in reference impl (in reverse + adjoint)
ApplyToEach(X, qs);
Controlled Z([qs[0]], qs[1]);
ApplyToEach(X, qs);
ApplyToEach(H, qs);
ApplyToEach(X, qs);
Controlled Z([qs[0]], qs[1]);
ApplyToEach(X, qs);
SWAP(qs[0], qs[1]);
2018-07-12 02:35:59 +03:00
}
2018-10-30 18:48:56 +03:00
operation T112_TwoQubitStatePartTwo_Test () : Unit {
2019-04-26 01:57:30 +03:00
DistinguishStates_MultiQubit(2, 4, StatePrep_TwoQubitStatePartTwo, TwoQubitStatePartTwo, 0);
2018-07-12 02:35:59 +03:00
}
2018-10-30 18:48:56 +03:00
2019-04-20 20:16:25 +03:00
// ------------------------------------------------------
operation StatePrep_ThreeQubitMeasurement (qs : Qubit[], state : Int) : Unit {
body (...) {
WState_Arbitrary_Reference(qs);
if (state == 0) {
// prep 1/sqrt(3) ( |100⟩ + ω |010⟩ + ω² |001⟩ )
R1(2.0 * PI() / 3.0, qs[1]);
R1(4.0 * PI() / 3.0, qs[2]);
} else {
// prep 1/sqrt(3) ( |100⟩ + ω² |010⟩ + ω |001⟩ )
R1(4.0 * PI() / 3.0, qs[1]);
R1(2.0 * PI() / 3.0, qs[2]);
}
}
adjoint invert;
}
operation T113_ThreeQubitMeasurement_Test () : Unit {
2019-04-26 01:57:30 +03:00
DistinguishStates_MultiQubit(3, 2, StatePrep_ThreeQubitMeasurement, ThreeQubitMeasurement, 0);
2019-04-20 20:16:25 +03:00
}
2018-07-12 02:35:59 +03:00
//////////////////////////////////////////////////////////////////
2019-04-26 01:57:30 +03:00
// Part II*. Discriminating Nonorthogonal States
//////////////////////////////////////////////////////////////////
2018-10-30 18:48:56 +03:00
operation StatePrep_IsQubitZeroOrPlus (q : Qubit, state : Int) : Unit {
if (state == 0) {
// convert |0⟩ to |0⟩
} else {
// convert |0⟩ to |+⟩
H(q);
2018-07-12 02:35:59 +03:00
}
}
2018-10-17 02:41:22 +03:00
2018-10-30 18:48:56 +03:00
2018-07-12 02:35:59 +03:00
// "Framework" operation for testing multi-qubit tasks for distinguishing states of an array of qubits
// with Int return. Framework tests against a threshold parameter for the fraction of runs that must succeed.
2018-10-30 18:48:56 +03:00
operation DistinguishStates_MultiQubit_Threshold (Nqubit : Int, Nstate : Int, threshold : Double, statePrep : ((Qubit, Int) => Unit), testImpl : (Qubit => Bool)) : Unit {
let nTotal = 1000;
mutable nOk = 0;
using (qs = Qubit[Nqubit]) {
for (i in 1 .. nTotal) {
// get a random integer to define the state of the qubits
let state = RandomInt(Nstate);
// do state prep: convert |0⟩ to outcome with return equal to state
statePrep(qs[0], state);
// get the solution's answer and verify that it's a match
let ans = testImpl(qs[0]);
if (ans == (state == 0)) {
set nOk = nOk + 1;
2018-07-12 02:35:59 +03:00
}
2018-10-30 18:48:56 +03:00
// we're not checking the state of the qubit after the operation
ResetAll(qs);
2018-07-12 02:35:59 +03:00
}
}
2018-10-30 18:48:56 +03:00
if (ToDouble(nOk) < threshold * ToDouble(nTotal)) {
fail $"{nTotal - nOk} test runs out of {nTotal} returned incorrect state which does not meet the required threshold of at least {threshold * 100.0}%.";
}
2018-07-12 02:35:59 +03:00
}
2018-10-30 18:48:56 +03:00
2018-07-12 02:35:59 +03:00
2019-04-26 01:57:30 +03:00
operation T201_IsQubitZeroOrPlus_Test () : Unit {
DistinguishStates_MultiQubit_Threshold(1, 2, 0.8, StatePrep_IsQubitZeroOrPlus, IsQubitPlusOrZero);
}
// ------------------------------------------------------
2018-07-12 02:35:59 +03:00
// "Framework" operation for testing multi-qubit tasks for distinguishing states of an array of qubits
// with Int return. Framework tests against a threshold parameter for the fraction of runs that must succeed.
// Framework tests in the USD scenario, i.e., it is allowed to respond "inconclusive" (with some probability)
2018-10-30 18:48:56 +03:00
// up to given threshold, but it is never allowed to err if an actual conclusive response is given.
operation USD_DistinguishStates_MultiQubit_Threshold (Nqubit : Int, Nstate : Int, thresholdInconcl : Double, thresholdConcl : Double, statePrep : ((Qubit, Int) => Unit), testImpl : (Qubit => Int)) : Unit {
let nTotal = 10000;
// counts total inconclusive answers
mutable nInconc = 0;
// counts total conclusive |0⟩ state identifications
mutable nConclOne = 0;
// counts total conclusive |+> state identifications
mutable nConclPlus = 0;
using (qs = Qubit[Nqubit]) {
for (i in 1 .. nTotal) {
// get a random integer to define the state of the qubits
let state = RandomInt(Nstate);
// do state prep: convert |0⟩ to outcome with return equal to state
statePrep(qs[0], state);
// get the solution's answer and verify that it's a match
let ans = testImpl(qs[0]);
// check that the answer is actually in allowed range
2019-04-16 05:02:38 +03:00
if (ans < -1 or ans > 1) {
2018-10-30 18:48:56 +03:00
fail $"state {state} led to invalid response {ans}.";
2018-07-12 02:35:59 +03:00
}
2018-10-30 18:48:56 +03:00
// keep track of the number of inconclusive answers given
if (ans == -1) {
set nInconc = nInconc + 1;
}
2019-04-16 05:02:38 +03:00
if (ans == 0 and state == 0) {
2018-10-30 18:48:56 +03:00
set nConclOne = nConclOne + 1;
}
2019-04-16 05:02:38 +03:00
if (ans == 1 and state == 1) {
2018-10-30 18:48:56 +03:00
set nConclPlus = nConclPlus + 1;
}
// check if upon conclusive result the answer is actually correct
2019-04-16 05:02:38 +03:00
if (ans == 0 and state == 1 or ans == 1 and state == 0) {
2018-10-30 18:48:56 +03:00
fail $"state {state} led to incorrect conclusive response {ans}.";
}
// we're not checking the state of the qubit after the operation
ResetAll(qs);
2018-07-12 02:35:59 +03:00
}
}
2018-10-30 18:48:56 +03:00
if (ToDouble(nInconc) > thresholdInconcl * ToDouble(nTotal)) {
fail $"{nInconc} test runs out of {nTotal} returned inconclusive which does not meet the required threshold of at most {thresholdInconcl * 100.0}%.";
2018-07-12 02:35:59 +03:00
}
2018-10-30 18:48:56 +03:00
if (ToDouble(nConclOne) < thresholdConcl * ToDouble(nTotal)) {
fail $"Only {nConclOne} test runs out of {nTotal} returned conclusive |0⟩ which does not meet the required threshold of at least {thresholdConcl * 100.0}%.";
2018-07-12 02:35:59 +03:00
}
2018-10-30 18:48:56 +03:00
if (ToDouble(nConclPlus) < thresholdConcl * ToDouble(nTotal)) {
fail $"Only {nConclPlus} test runs out of {nTotal} returned conclusive |+> which does not meet the required threshold of at least {thresholdConcl * 100.0}%.";
}
}
operation T202_IsQubitZeroOrPlusSimpleUSD_Test () : Unit {
USD_DistinguishStates_MultiQubit_Threshold(1, 2, 0.8, 0.1, StatePrep_IsQubitZeroOrPlus, IsQubitPlusZeroOrInconclusiveSimpleUSD);
2018-07-12 02:35:59 +03:00
}
2018-10-30 18:48:56 +03:00
2019-04-20 20:16:25 +03:00
// ------------------------------------------------------
operation StatePrep_IsQubitNotInABC (q : Qubit, state : Int) : Unit {
let alpha = (2.0 * PI()) / 3.0;
H(q);
if (state == 0) {
// convert |0⟩ to 1/sqrt(2) (|0⟩ + |1⟩)
}
elif (state == 1) {
// convert |0⟩ to 1/sqrt(2) (|0⟩ + ω |1⟩), where ω = exp(2iπ/3)
R1(alpha, q);
}
else {
// convert |0⟩ to 1/sqrt(2) (|0⟩ + ω² |1⟩), where ω = exp(2iπ/3)
R1(2.0 * alpha, q);
}
}
// "Framework" operation for testing multi-qubit tasks for distinguishing states of an array of qubits
// with Int return. Framework tests instances of the Peres/Wootters game. In this game, one of three
// "trine" states is presented and the algorithm must answer with a label that does not correspond
// to one of the label of the input state.
operation ABC_DistinguishStates_MultiQubit_Threshold (Nqubit : Int, Nstate : Int, statePrep : ((Qubit, Int) => Unit), testImpl : (Qubit => Int)) : Unit {
let nTotal = 1000;
using (qs = Qubit[Nqubit]) {
for (i in 1 .. nTotal) {
// get a random integer to define the state of the qubits
let state = RandomInt(Nstate);
// do state prep: convert |0⟩ to outcome with return equal to state
statePrep(qs[0], state);
// get the solution's answer and verify that it's a match
let ans = testImpl(qs[0]);
// check that the value of ans is 0, 1 or 2
if (ans < 0 or ans > 2) {
fail "You can not return any value other than 0, 1 or 2.";
}
// check if upon conclusive result the answer is actually correct
if (ans == state) {
fail $"State {state} led to incorrect conclusive response {ans}.";
}
// we're not checking the state of the qubit after the operation
ResetAll(qs);
}
}
}
operation T203_IsQubitNotInABC_Test () : Unit {
ABC_DistinguishStates_MultiQubit_Threshold(1, 3, StatePrep_IsQubitNotInABC, IsQubitNotInABC);
}
2018-10-30 18:48:56 +03:00
}