* Update the katas to use QDK 0.6.1905.301.
* Add mechanism to verify that the reference solutions actually solve all tasks of a Notebook correctly.

Co-Authored-By: Bettina Heim <34236215+bettinaheim@users.noreply.github.com>
Co-Authored-By: Andres Paz <anpaz@microsoft.com>
This commit is contained in:
bettinaheim 2019-05-03 16:46:04 -07:00 коммит произвёл Mariia Mykhailova
Родитель df491c9844
Коммит 7519eb3f74
77 изменённых файлов: 1639 добавлений и 1855 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -17,6 +17,7 @@ Tests/build
# test outputs
TestResults/
*.qxe
Check.ipynb
# Random VS files
*.suo

Просмотреть файл

@ -7,9 +7,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Canon" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Standard" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />

Просмотреть файл

@ -36,7 +36,7 @@
"metadata": {},
"outputs": [],
"source": [
"%package Microsoft.Quantum.Katas::0.5.1904.1302"
"%package Microsoft.Quantum.Katas::0.6.1905.301"
]
},
{
@ -46,13 +46,13 @@
"> The package versions in the output of the cell above should always match. If you are running the Notebooks locally and the versions do not match, please install the IQ# version that matches the version of the `Microsoft.Quantum.Katas` package.\n",
"> <details>\n",
"> <summary><u>How to install the right IQ# version</u></summary>\n",
"> For example, if the version of `Microsoft.Quantum.Katas` package above is 0.5.1904.1302, the installation steps are as follows:\n",
"> For example, if the version of `Microsoft.Quantum.Katas` package above is 0.6.1905.301, the installation steps are as follows:\n",
">\n",
"> 1. Stop the kernel.\n",
"> 2. Uninstall the existing version of IQ#:\n",
"> dotnet tool uninstall microsoft.quantum.iqsharp -g\n",
"> 3. Install the matching version:\n",
"> dotnet tool install microsoft.quantum.iqsharp -g --version 0.5.1904.1302\n",
"> dotnet tool install microsoft.quantum.iqsharp -g --version 0.6.1905.301\n",
"> 4. Reinstall the kernel:\n",
"> dotnet iqsharp install\n",
"> 5. Restart the Notebook.\n",
@ -94,17 +94,12 @@
"source": [
"%kata T11_StateFlip_Test \n",
"\n",
"operation StateFlip (q : Qubit) : Unit {\n",
"operation StateFlip (q : Qubit) : Unit is Adj {\n",
" // The Pauli X gate will change the |0⟩ state to the |1⟩ state and vice versa.\n",
" // Type X(q);\n",
" // Then run the cell using Ctrl/⌘+Enter.\n",
"\n",
" body (...) {\n",
" // The Pauli X gate will change the |0⟩ state to the |1⟩ state and vice versa.\n",
" // Type X(q);\n",
" // Then run the cell using Ctrl/⌘+Enter.\n",
"\n",
" // ...\n",
" }\n",
"\n",
" adjoint self;\n",
" // ...\n",
"}"
]
},
@ -134,13 +129,8 @@
"source": [
"%kata T12_BasisChange_Test \n",
"\n",
"operation BasisChange (q : Qubit) : Unit {\n",
" \n",
" body (...) {\n",
" // ...\n",
" }\n",
"\n",
" adjoint self;\n",
"operation BasisChange (q : Qubit) : Unit is Adj {\n",
" // ...\n",
"}"
]
},
@ -163,13 +153,8 @@
"source": [
"%kata T13_SignFlip_Test \n",
"\n",
"operation SignFlip (q : Qubit) : Unit {\n",
"\n",
" body (...) {\n",
" // ...\n",
" }\n",
"\n",
" adjoint self;\n",
"operation SignFlip (q : Qubit) : Unit is Adj {\n",
" // ...\n",
"}"
]
},
@ -190,7 +175,7 @@
"- If the qubit is in superposition, change its state according to the effect on basis vectors.\n",
"\n",
"> This is the first operation in this kata that is not self-adjoint, i.e., applying it for a second time\n",
"> does not return the qubit to the original state. `adjoint invert` means that Q# can compute the operation \n",
"> does not return the qubit to the original state. `is Adj` means that Q# can compute the operation \n",
"> that returns the qubit to the original state automatically."
]
},
@ -202,13 +187,8 @@
"source": [
"%kata T14_AmplitudeChange_Test\n",
"\n",
"operation AmplitudeChange (q : Qubit, α : Double) : Unit {\n",
"\n",
" body (...) {\n",
" // ...\n",
" }\n",
"\n",
" adjoint invert;\n",
"operation AmplitudeChange (q : Qubit, α : Double) : Unit is Adj {\n",
" // ...\n",
"}\n"
]
},
@ -231,13 +211,8 @@
"source": [
"%kata T15_PhaseFlip_Test\n",
"\n",
"operation PhaseFlip (q : Qubit) : Unit {\n",
" \n",
" body (...) {\n",
" // ...\n",
" }\n",
" \n",
" adjoint invert;\n",
"operation PhaseFlip (q : Qubit) : Unit is Adj { \n",
" // ...\n",
"}\n",
"\n"
]
@ -267,13 +242,8 @@
"source": [
"%kata T16_PhaseChange_Test\n",
"\n",
"operation PhaseChange (q : Qubit, α : Double) : Unit {\n",
" \n",
" body (...) {\n",
" // ...\n",
" }\n",
" \n",
" adjoint invert;\n",
"operation PhaseChange (q : Qubit, α : Double) : Unit is Adj {\n",
" // ...\n",
"}\n"
]
},
@ -296,13 +266,9 @@
"source": [
"%kata T17_BellStateChange1_Test\n",
"\n",
"operation BellStateChange1 (qs : Qubit[]) : Unit {\n",
"operation BellStateChange1 (qs : Qubit[]) : Unit is Adj {\n",
" \n",
" body (...) {\n",
" // ...\n",
" }\n",
" \n",
" adjoint invert;\n",
" // ...\n",
"}\n"
]
},
@ -325,13 +291,9 @@
"source": [
"%kata T18_BellStateChange2_Test\n",
"\n",
"operation BellStateChange2 (qs : Qubit[]) : Unit {\n",
"operation BellStateChange2 (qs : Qubit[]) : Unit is Adj {\n",
" \n",
" body (...) {\n",
" // ...\n",
" }\n",
" \n",
" adjoint invert;\n",
" // ...\n",
"}\n"
]
},
@ -354,13 +316,9 @@
"source": [
"%kata T19_BellStateChange3_Test\n",
"\n",
"operation BellStateChange3 (qs : Qubit[]) : Unit {\n",
"operation BellStateChange3 (qs : Qubit[]) : Unit is Adj {\n",
" \n",
" body (...) {\n",
" // ...\n",
" }\n",
" \n",
" adjoint invert;\n",
" // ...\n",
"}\n"
]
},
@ -451,7 +409,7 @@
"\n",
"**Goal:** Change the two-qubit state to $\\alpha |00\\rangle + \\color{red}\\gamma |01\\rangle + \\color{red}\\beta |10\\rangle + \\delta |11\\rangle$.\n",
"\n",
"> This task can be solved using one primitive gate; as an exercise, try to express the solution using several (possibly controlled) Pauli gates."
"> This task can be solved using one intrinsic gate; as an exercise, try to express the solution using several (possibly controlled) Pauli gates."
]
},
{

Просмотреть файл

@ -10,7 +10,7 @@
namespace Quantum.Kata.BasicGates {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
@ -72,27 +72,19 @@ namespace Quantum.Kata.BasicGates {
// If the qubit is in state |0⟩, change its state to cos(alpha)*|0⟩ + sin(alpha)*|1⟩.
// If the qubit is in state |1⟩, change its state to -sin(alpha)*|0⟩ + cos(alpha)*|1⟩.
// If the qubit is in superposition, change its state according to the effect on basis vectors.
operation AmplitudeChange_Reference (q : Qubit, alpha : Double) : Unit {
body (...) {
Ry(2.0 * alpha, q);
}
adjoint invert;
operation AmplitudeChange_Reference (q : Qubit, alpha : Double) : Unit
is Adj {
Ry(2.0 * alpha, q);
}
// Task 1.5. Phase flip
// Input: A qubit in state |ψ⟩ = α |0⟩ + β |1⟩.
// Goal: Change the qubit state to α |0⟩ + iβ |1⟩ (flip the phase of |1⟩ component of the superposition).
operation PhaseFlip_Reference (q : Qubit) : Unit {
body (...) {
S(q);
// alternatively Rz(0.5 * PI(), q);
}
adjoint invert;
operation PhaseFlip_Reference (q : Qubit) : Unit
is Adj {
S(q);
// alternatively Rz(0.5 * PI(), q);
}
@ -104,54 +96,38 @@ namespace Quantum.Kata.BasicGates {
// If the qubit is in state |0⟩, don't change its state.
// If the qubit is in state |1⟩, change its state to exp(i*alpha)|1⟩.
// If the qubit is in superposition, change its state according to the effect on basis vectors.
operation PhaseChange_Reference (q : Qubit, alpha : Double) : Unit {
body (...) {
Rz(alpha, q);
}
adjoint invert;
operation PhaseChange_Reference (q : Qubit, alpha : Double) : Unit
is Adj {
Rz(alpha, q);
}
// Task 1.7. Bell state change - 1
// Input: Two entangled qubits in Bell state |Φ⁺⟩ = (|00⟩ + |11⟩) / sqrt(2).
// Goal: Change the two-qubit state to |Φ⁻⟩ = (|00⟩ - |11⟩) / sqrt(2).
operation BellStateChange1_Reference (qs : Qubit[]) : Unit {
body (...) {
Z(qs[0]);
// alternatively Z(qs[1]);
}
adjoint invert;
operation BellStateChange1_Reference (qs : Qubit[]) : Unit
is Adj {
Z(qs[0]);
// alternatively Z(qs[1]);
}
// Task 1.8. Bell state change - 2
// Input: Two entangled qubits in Bell state |Φ⁺⟩ = (|00⟩ + |11⟩) / sqrt(2).
// Goal: Change the two-qubit state to |Ψ⁺⟩ = (|01⟩ + |10⟩) / sqrt(2).
operation BellStateChange2_Reference (qs : Qubit[]) : Unit {
body (...) {
X(qs[0]);
// alternatively X(qs[1]);
}
adjoint invert;
operation BellStateChange2_Reference (qs : Qubit[]) : Unit
is Adj {
X(qs[0]);
// alternatively X(qs[1]);
}
// Task 1.9. Bell state change - 3
// Input: Two entangled qubits in Bell state |Φ⁺⟩ = (|00⟩ + |11⟩) / sqrt(2).
// Goal: Change the two-qubit state to |Ψ⁻⟩ = (|01⟩ - |10⟩) / sqrt(2).
operation BellStateChange3_Reference (qs : Qubit[]) : Unit {
body (...) {
Y(qs[0]);
}
adjoint invert;
operation BellStateChange3_Reference (qs : Qubit[]) : Unit
is Adj {
Y(qs[0]);
}

Просмотреть файл

@ -3,7 +3,7 @@
namespace Quantum.Kata.BasicGates {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
@ -94,26 +94,18 @@ namespace Quantum.Kata.BasicGates {
// If the qubit is in state |0⟩, change its state to cos(alpha)*|0⟩ + sin(alpha)*|1⟩.
// If the qubit is in state |1⟩, change its state to -sin(alpha)*|0⟩ + cos(alpha)*|1⟩.
// If the qubit is in superposition, change its state according to the effect on basis vectors.
operation AmplitudeChange (q : Qubit, alpha : Double) : Unit {
body (...) {
// ...
}
adjoint invert;
operation AmplitudeChange (q : Qubit, alpha : Double) : Unit
is Adj {
// ...
}
// Task 1.5. Phase flip
// Input: A qubit in state |ψ⟩ = α |0⟩ + β |1⟩.
// Goal: Change the qubit state to α |0⟩ + iβ |1⟩ (flip the phase of |1⟩ component of the superposition).
operation PhaseFlip (q : Qubit) : Unit {
body (...) {
// ...
}
adjoint invert;
operation PhaseFlip (q : Qubit) : Unit
is Adj {
// ...
}
@ -125,52 +117,36 @@ namespace Quantum.Kata.BasicGates {
// If the qubit is in state |0⟩, don't change its state.
// If the qubit is in state |1⟩, change its state to exp(i*alpha)|1⟩.
// If the qubit is in superposition, change its state according to the effect on basis vectors.
operation PhaseChange (q : Qubit, alpha : Double) : Unit {
body (...) {
// ...
}
adjoint invert;
operation PhaseChange (q : Qubit, alpha : Double) : Unit
is Adj {
// ...
}
// Task 1.7. Bell state change - 1
// Input: Two entangled qubits in Bell state |Φ⁺⟩ = (|00⟩ + |11⟩) / sqrt(2).
// Goal: Change the two-qubit state to |Φ⁻⟩ = (|00⟩ - |11⟩) / sqrt(2).
operation BellStateChange1 (qs : Qubit[]) : Unit {
body (...) {
// ...
}
adjoint invert;
operation BellStateChange1 (qs : Qubit[]) : Unit
is Adj {
// ...
}
// Task 1.8. Bell state change - 2
// Input: Two entangled qubits in Bell state |Φ⁺⟩ = (|00⟩ + |11⟩) / sqrt(2).
// Goal: Change the two-qubit state to |Ψ⁺⟩ = (|01⟩ + |10⟩) / sqrt(2).
operation BellStateChange2 (qs : Qubit[]) : Unit {
body (...) {
// ...
}
adjoint invert;
operation BellStateChange2 (qs : Qubit[]) : Unit
is Adj {
// ...
}
// Task 1.9. Bell state change - 3
// Input: Two entangled qubits in Bell state |Φ⁺⟩ = (|00⟩ + |11⟩) / sqrt(2).
// Goal: Change the two-qubit state to |Ψ⁻⟩ = (|01⟩ - |10⟩) / sqrt(2).
operation BellStateChange3 (qs : Qubit[]) : Unit {
body (...) {
// ...
}
adjoint invert;
operation BellStateChange3 (qs : Qubit[]) : Unit
is Adj {
// ...
}

Просмотреть файл

@ -9,65 +9,59 @@
namespace Quantum.Kata.BasicGates {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Extensions.Testing;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
open Microsoft.Quantum.Diagnostics;
// ------------------------------------------------------
// helper wrapper to represent operation on one qubit as an operation on an array of qubits
operation ArrayWrapperOperation (op : (Qubit => Unit : Adjoint), qs : Qubit[]) : Unit {
body (...) {
op(qs[0]);
}
adjoint (...) {
Adjoint op(qs[0]);
}
operation ArrayWrapperOperation (op : (Qubit => Unit is Adj), qs : Qubit[]) : Unit
is Adj {
op(qs[0]);
}
// ------------------------------------------------------
operation T11_StateFlip_Test () : Unit {
AssertOperationsEqualReferenced(ArrayWrapperOperation(StateFlip, _), ArrayWrapperOperation(StateFlip_Reference, _), 1);
AssertOperationsEqualReferenced(1, ArrayWrapperOperation(StateFlip, _), ArrayWrapperOperation(StateFlip_Reference, _));
}
// ------------------------------------------------------
operation T12_BasisChange_Test () : Unit {
AssertOperationsEqualReferenced(ArrayWrapperOperation(BasisChange, _), ArrayWrapperOperation(BasisChange_Reference, _), 1);
AssertOperationsEqualReferenced(1, ArrayWrapperOperation(BasisChange, _), ArrayWrapperOperation(BasisChange_Reference, _));
}
// ------------------------------------------------------
operation T13_SignFlip_Test () : Unit {
AssertOperationsEqualReferenced(ArrayWrapperOperation(SignFlip, _), ArrayWrapperOperation(SignFlip_Reference, _), 1);
AssertOperationsEqualReferenced(1, ArrayWrapperOperation(SignFlip, _), ArrayWrapperOperation(SignFlip_Reference, _));
}
// ------------------------------------------------------
operation T14_AmplitudeChange_Test () : Unit {
for (i in 0 .. 36) {
let alpha = ((2.0 * PI()) * ToDouble(i)) / 36.0;
AssertOperationsEqualReferenced(ArrayWrapperOperation(AmplitudeChange(_, alpha), _), ArrayWrapperOperation(AmplitudeChange_Reference(_, alpha), _), 1);
let alpha = ((2.0 * PI()) * IntAsDouble(i)) / 36.0;
AssertOperationsEqualReferenced(1, ArrayWrapperOperation(AmplitudeChange(_, alpha), _), ArrayWrapperOperation(AmplitudeChange_Reference(_, alpha), _));
}
}
// ------------------------------------------------------
operation T15_PhaseFlip_Test () : Unit {
AssertOperationsEqualReferenced(ArrayWrapperOperation(PhaseFlip, _), ArrayWrapperOperation(PhaseFlip_Reference, _), 1);
AssertOperationsEqualReferenced(1, ArrayWrapperOperation(PhaseFlip, _), ArrayWrapperOperation(PhaseFlip_Reference, _));
}
// ------------------------------------------------------
operation T16_PhaseChange_Test () : Unit {
for (i in 0 .. 36) {
let alpha = ((2.0 * PI()) * ToDouble(i)) / 36.0;
AssertOperationsEqualReferenced(ArrayWrapperOperation(PhaseChange(_, alpha), _), ArrayWrapperOperation(PhaseChange_Reference(_, alpha), _), 1);
let alpha = ((2.0 * PI()) * IntAsDouble(i)) / 36.0;
AssertOperationsEqualReferenced(1, ArrayWrapperOperation(PhaseChange(_, alpha), _), ArrayWrapperOperation(PhaseChange_Reference(_, alpha), _));
}
}
@ -77,24 +71,21 @@ namespace Quantum.Kata.BasicGates {
// 1 - |Φ⁻⟩ = (|00⟩ - |11⟩) / sqrt(2)
// 2 - |Ψ⁺⟩ = (|01⟩ + |10⟩) / sqrt(2)
// 3 - |Ψ⁻⟩ = (|01⟩ - |10⟩) / sqrt(2)
operation StatePrep_BellState (qs : Qubit[], state : Int) : Unit {
operation StatePrep_BellState (qs : Qubit[], state : Int) : Unit
is Adj {
body (...) {
H(qs[0]);
CNOT(qs[0], qs[1]);
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]);
}
if (state / 2 == 1) {
X(qs[1]);
}
// now we have |00⟩ + |11⟩ - modify it based on state arg
if (state % 2 == 1) {
// negative phase
Z(qs[1]);
}
if (state / 2 == 1) {
X(qs[1]);
}
adjoint invert;
}
@ -153,7 +144,7 @@ namespace Quantum.Kata.BasicGates {
// we need to create an input state |A⟩ and check that the output state is correct
using (qs = Qubit[2]) {
for (i in 0 .. 36) {
let alpha = ((2.0 * PI()) * ToDouble(i)) / 36.0;
let alpha = ((2.0 * PI()) * IntAsDouble(i)) / 36.0;
// prepare A state
StatePrep_A(alpha, qs[0]);
@ -215,20 +206,20 @@ namespace Quantum.Kata.BasicGates {
operation T23_TwoQubitGate3_Test () : Unit {
AssertOperationsEqualReferenced(SwapWrapper, TwoQubitGate3_Reference, 2);
AssertOperationsEqualReferenced(TwoQubitGate3, TwoQubitGate3_Reference, 2);
AssertOperationsEqualReferenced(2, SwapWrapper, TwoQubitGate3_Reference);
AssertOperationsEqualReferenced(2, TwoQubitGate3, TwoQubitGate3_Reference);
}
// ------------------------------------------------------
operation T24_ToffoliGate_Test () : Unit {
AssertOperationsEqualReferenced(ToffoliGate, ToffoliGate_Reference, 3);
AssertOperationsEqualReferenced(3, ToffoliGate, ToffoliGate_Reference);
}
// ------------------------------------------------------
operation T25_FredkinGate_Test () : Unit {
AssertOperationsEqualReferenced(FredkinGate, FredkinGate_Reference, 3);
AssertOperationsEqualReferenced(3, FredkinGate, FredkinGate_Reference);
}
}

Просмотреть файл

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
@ -7,9 +7,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Canon" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Standard" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />

Просмотреть файл

@ -43,35 +43,26 @@ namespace Quantum.Kata.CHSHGame {
//////////////////////////////////////////////////////////////////
// Task 2.1. Entangled pair
operation CreateEntangledPair_Reference (qs : Qubit[]) : Unit {
body (...) {
H(qs[0]);
CNOT(qs[0], qs[1]);
}
adjoint invert;
operation CreateEntangledPair_Reference (qs : Qubit[]) : Unit
is Adj {
H(qs[0]);
CNOT(qs[0], qs[1]);
}
// Task 2.2. Alice's quantum strategy
operation AliceQuantum_Reference (bit : Bool, qubit : Qubit) : Bool {
if (bit) {
// Measure in sign basis if bit is 1
return BoolFromResult(Measure([PauliX], [qubit]));
} else {
// Measure in computational basis if bit is 0
return BoolFromResult(Measure([PauliZ], [qubit]));
}
// Measure in sign basis if bit is 1, and
// measure in computational basis if bit is 0
let basis = bit ? PauliX | PauliZ;
return BoolFromResult(Measure([basis], [qubit]));
}
// Task 2.3. Rotate Bob's qubit
operation RotateBobQubit_Reference (clockwise : Bool, qubit : Qubit) : Unit {
if (clockwise) {
Ry(-2.0 * PI() / 8.0, qubit);
} else {
Ry(2.0 * PI() / 8.0, qubit);
}
let angle = 2.0 * PI() / 8.0;
Ry(clockwise ? -angle | angle, qubit);
}
@ -85,20 +76,18 @@ namespace Quantum.Kata.CHSHGame {
// Task 2.5. Play the CHSH game
operation PlayQuantumCHSH_Reference (askAlice : (Qubit => Bool),
askBob : (Qubit => Bool)) : (Bool, Bool) {
mutable aliceResult = false;
mutable bobResult = false;
using ((aliceQubit, bobQubit) = (Qubit(), Qubit())) {
CreateEntangledPair_Reference([aliceQubit, bobQubit]);
set aliceResult = askAlice(aliceQubit);
set bobResult = askBob(bobQubit);
let aliceResult = askAlice(aliceQubit);
let bobResult = askBob(bobQubit);
Reset(aliceQubit);
Reset(bobQubit);
return (aliceResult, bobResult);
}
return (aliceResult, bobResult);
}
}

Просмотреть файл

@ -3,6 +3,7 @@
namespace Quantum.Kata.CHSHGame {
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Primitive;
@ -75,7 +76,7 @@ namespace Quantum.Kata.CHSHGame {
operation CreateEntangledPair (qs : Qubit[]) : Unit {
// The following lines enforce the constraints on the input that you are given.
// You don't need to modify them. Feel free to remove them, this won't cause your code to fail.
AssertIntEqual(Length(qs), 2, "The array should have exactly 2 qubits.");
EqualityFactI(Length(qs), 2, "The array should have exactly 2 qubits.");
// ...
fail "Task 2.1 not implemented yet";

Просмотреть файл

@ -9,16 +9,16 @@
namespace Quantum.Kata.CHSHGame {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Math;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Extensions.Testing;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Diagnostics;
operation T11_WinCondition_Test () : Unit {
for (i in 0..1 <<< 4 - 1) {
let bits = BoolArrFromPositiveInt(i, 4);
AssertBoolEqual(
EqualityFactB(
WinCondition(bits[0], bits[1], bits[2], bits[3]),
(bits[0] and bits[1]) == (bits[2] != bits[3]),
$"Win condition is wrong for X = {bits[0]}, Y = {bits[1]}, A = {bits[2]}, " +
@ -38,16 +38,16 @@ namespace Quantum.Kata.CHSHGame {
set wins = wins + 1;
}
}
Message($"Win rate {ToDouble(wins) / 1000.}");
Message($"Win rate {IntAsDouble(wins) / 1000.}");
AssertBoolEqual(wins >= 700, true,
EqualityFactB(wins >= 700, true,
"Alice and Bob's classical strategy is not optimal");
}
// ------------------------------------------------------
operation AssertEqualOnZeroState (N : Int, taskImpl : (Qubit[] => Unit),
refImpl : (Qubit[] => Unit : Adjoint)) : Unit {
refImpl : (Qubit[] => Unit is Adj)) : Unit {
using (qs = Qubit[N]) {
// apply operation that needs to be tested
taskImpl(qs);
@ -70,20 +70,20 @@ namespace Quantum.Kata.CHSHGame {
// ------------------------------------------------------
operation T22_AliceQuantum_Test () : Unit {
using (q = Qubit()) {
AssertBoolEqual(AliceQuantum(false, q), false, "|0⟩ not measured as false");
EqualityFactB(AliceQuantum(false, q), false, "|0⟩ not measured as false");
Reset(q);
X(q);
AssertBoolEqual(AliceQuantum(false, q), true, "|1⟩ not measured as true");
EqualityFactB(AliceQuantum(false, q), true, "|1⟩ not measured as true");
Reset(q);
H(q);
AssertBoolEqual(AliceQuantum(true, q), false, "|+⟩ is not measured as false");
EqualityFactB(AliceQuantum(true, q), false, "|+⟩ is not measured as false");
Reset(q);
X(q);
H(q);
AssertBoolEqual(AliceQuantum(true, q), true, "|-⟩ is not measured as true");
EqualityFactB(AliceQuantum(true, q), true, "|-⟩ is not measured as true");
Reset(q);
}
}
@ -94,18 +94,16 @@ namespace Quantum.Kata.CHSHGame {
op(qs[0]);
}
operation QubitToRegisterOperationA (op : (Qubit => Unit : Adjoint), qs : Qubit[]) : Unit {
body (...) {
op(qs[0]);
}
adjoint auto;
operation QubitToRegisterOperationA (op : (Qubit => Unit is Adj), qs : Qubit[]) : Unit
is Adj {
op(qs[0]);
}
operation T23_RotateBobQubit_Test () : Unit {
AssertOperationsEqualReferenced(QubitToRegisterOperation(RotateBobQubit(true, _), _),
QubitToRegisterOperationA(Ry(-2.0 * PI() / 8.0, _), _), 1);
AssertOperationsEqualReferenced(QubitToRegisterOperation(RotateBobQubit(false, _), _),
QubitToRegisterOperationA(Ry(2.0 * PI() / 8.0, _), _), 1);
AssertOperationsEqualReferenced(1, QubitToRegisterOperation(RotateBobQubit(true, _), _),
QubitToRegisterOperationA(Ry(-2.0 * PI() / 8.0, _), _));
AssertOperationsEqualReferenced(1, QubitToRegisterOperation(RotateBobQubit(false, _), _),
QubitToRegisterOperationA(Ry(2.0 * PI() / 8.0, _), _));
}
@ -113,21 +111,21 @@ namespace Quantum.Kata.CHSHGame {
operation T24_BobQuantum_Test () : Unit {
using (q = Qubit()) {
RotateBobQubit_Reference(false, q);
AssertBoolEqual(BobQuantum(false, q), false, "π/8 from |0⟩ not measured as false");
EqualityFactB(BobQuantum(false, q), false, "π/8 from |0⟩ not measured as false");
Reset(q);
X(q);
RotateBobQubit_Reference(false, q);
AssertBoolEqual(BobQuantum(false, q), true, "π/8 from |1⟩ not measured as true");
EqualityFactB(BobQuantum(false, q), true, "π/8 from |1⟩ not measured as true");
Reset(q);
RotateBobQubit_Reference(true, q);
AssertBoolEqual(BobQuantum(true, q), false, "-π/8 from |0⟩ not measured as false");
EqualityFactB(BobQuantum(true, q), false, "-π/8 from |0⟩ not measured as false");
Reset(q);
X(q);
RotateBobQubit_Reference(true, q);
AssertBoolEqual(BobQuantum(true, q), true, "-π/8 from |1⟩ not measured as true");
EqualityFactB(BobQuantum(true, q), true, "-π/8 from |1⟩ not measured as true");
Reset(q);
}
}
@ -144,7 +142,7 @@ namespace Quantum.Kata.CHSHGame {
set wins = wins + 1;
}
}
AssertAlmostEqualTol(ToDouble(wins) / 10000., 0.85, 0.01);
EqualityWithinToleranceFact(IntAsDouble(wins) / 10000., 0.85, 0.01);
}
}

Просмотреть файл

@ -6,9 +6,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Canon" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Standard" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />

Просмотреть файл

@ -34,7 +34,7 @@
"metadata": {},
"outputs": [],
"source": [
"%package Microsoft.Quantum.Katas::0.5.1904.1302"
"%package Microsoft.Quantum.Katas::0.6.1905.301"
]
},
{
@ -44,13 +44,13 @@
"> The package versions in the output of the cell above should always match. If you are running the Notebooks locally and the versions do not match, please install the IQ# version that matches the version of the `Microsoft.Quantum.Katas` package.\n",
"> <details>\n",
"> <summary><u>How to install the right IQ# version</u></summary>\n",
"> For example, if the version of `Microsoft.Quantum.Katas` package above is 0.5.1904.1302, the installation steps are as follows:\n",
"> For example, if the version of `Microsoft.Quantum.Katas` package above is 0.6.1905.301, the installation steps are as follows:\n",
">\n",
"> 1. Stop the kernel.\n",
"> 2. Uninstall the existing version of IQ#:\n",
"> dotnet tool uninstall microsoft.quantum.iqsharp -g\n",
"> 3. Install the matching version:\n",
"> dotnet tool install microsoft.quantum.iqsharp -g --version 0.5.1904.1302\n",
"> dotnet tool install microsoft.quantum.iqsharp -g --version 0.6.1905.301\n",
"> 4. Reinstall the kernel:\n",
"> dotnet iqsharp install\n",
"> 5. Restart the Notebook.\n",
@ -169,10 +169,12 @@
"source": [
"%kata T13_Oracle_Kth_Qubit_Test \n",
"\n",
"open Microsoft.Quantum.Diagnostics;\n",
"\n",
"operation Oracle_Kth_Qubit (x : Qubit[], y : Qubit, k : Int) : Unit {\n",
" // The following line enforces the constraints on the value of k that you are given.\n",
" // You don't need to modify it. Feel free to remove it, this won't cause your code to fail.\n",
" AssertBoolEqual(0 <= k and k < Length(x), true, \"k should be between 0 and N-1, inclusive\");\n",
" EqualityFactB(0 <= k and k < Length(x), true, \"k should be between 0 and N-1, inclusive\");\n",
"\n",
" // ...\n",
"}"
@ -234,10 +236,12 @@
"source": [
"%kata T15_Oracle_ProductFunction_Test\n",
"\n",
"open Microsoft.Quantum.Diagnostics;\n",
"\n",
"operation Oracle_ProductFunction (x : Qubit[], y : Qubit, r : Int[]) : Unit {\n",
" // The following line enforces the constraint on the input arrays.\n",
" // You don't need to modify it. Feel free to remove it, this won't cause your code to fail.\n",
" AssertIntEqual(Length(x), Length(r), \"Arrays should have the same length\");\n",
" EqualityFactI(Length(x), Length(r), \"Arrays should have the same length\");\n",
"\n",
" // ...\n",
"}"
@ -272,10 +276,12 @@
"source": [
"%kata T16_Oracle_ProductWithNegationFunction_Test\n",
"\n",
"open Microsoft.Quantum.Diagnostics;\n",
"\n",
"operation Oracle_ProductWithNegationFunction (x : Qubit[], y : Qubit, r : Int[]) : Unit {\n",
" // The following line enforces the constraint on the input arrays.\n",
" // You don't need to modify it. Feel free to remove it, this won't cause your code to fail.\n",
" AssertIntEqual(Length(x), Length(r), \"Arrays should have the same length\");\n",
" EqualityFactI(Length(x), Length(r), \"Arrays should have the same length\");\n",
"\n",
" // ...\n",
"}"
@ -311,11 +317,13 @@
"source": [
"%kata T17_Oracle_HammingWithPrefix_Test\n",
"\n",
"open Microsoft.Quantum.Diagnostics;\n",
"\n",
"operation Oracle_HammingWithPrefix (x : Qubit[], y : Qubit, prefix : Int[]) : Unit {\n",
" // The following line enforces the constraint on the input arrays.\n",
" // You don't need to modify it. Feel free to remove it, this won't cause your code to fail.\n",
" let K = Length(prefix);\n",
" AssertBoolEqual(1 <= K and K <= Length(x), true, \"K should be between 1 and N, inclusive\");\n",
" EqualityFactB(1 <= K and K <= Length(x), true, \"K should be between 1 and N, inclusive\");\n",
"\n",
" // ...\n",
"}"
@ -349,10 +357,12 @@
"source": [
"%kata T18_Oracle_MajorityFunction_Test\n",
"\n",
"open Microsoft.Quantum.Diagnostics;\n",
"\n",
"operation Oracle_MajorityFunction (x : Qubit[], y : Qubit) : Unit {\n",
" // The following line enforces the constraint on the input array.\n",
" // You don't need to modify it. Feel free to remove it, this won't cause your code to fail.\n",
" AssertBoolEqual(3 == Length(x), true, \"x should have exactly 3 qubits\");\n",
" EqualityFactI(3, Length(x), \"x should have exactly 3 qubits\");\n",
"\n",
" // ...\n",
"}"
@ -446,9 +456,11 @@
"metadata": {},
"outputs": [],
"source": [
"open Microsoft.Quantum.Diagnostics;\n",
"\n",
"operation Run_DeutschJozsa_Algorithm () : String {\n",
" // You can use AssertBoolEqual function to assert that the return value of DJ_Algorithm operation matches the expected value\n",
" AssertBoolEqual(DJ_Algorithm(4, Oracle_Zero), true, \"f(x) = 0 not identified as constant\");\n",
" // You can use EqualityFactB function to represent the invariant that the return value of DJ_Algorithm operation matches the expected value\n",
" EqualityFactB(DJ_Algorithm(4, Oracle_Zero), true, \"f(x) = 0 not identified as constant\");\n",
" \n",
" // Run the algorithm for the rest of the oracles\n",
" // ...\n",
@ -532,20 +544,20 @@
"metadata": {},
"outputs": [],
"source": [
"// Start by implementing a function AreIntArraysEqual \n",
"// Start by implementing a function AllEqualityFactI \n",
"// to check the results of applying the algorithm to each oracle in a uniform manner.\n",
"function AreIntArraysEqual(actual : Int[], expected : Int[]) : Bool {\n",
"function AllEqualityFactI(actual : Int[], expected : Int[]) : Bool {\n",
" // Check that array lengths are equal\n",
" // ...\n",
" \n",
" // Check that the corresponding elements of the arrays are equal\n",
" // ...\n",
" fail \"AreIntArraysEqual is not implemented\";\n",
" fail \"AllEqualityFactI is not implemented\";\n",
"}\n",
"\n",
"operation Run_BernsteinVazirani_Algorithm () : String {\n",
" // Now use AreIntArraysEqual to verify the results of the algorithm\n",
" if (not AreIntArraysEqual(BV_Algorithm(3, Oracle_Zero), [0, 0, 0])) {\n",
" // Now use AllEqualityFactI to verify the results of the algorithm\n",
" if (not AllEqualityFactI(BV_Algorithm(3, Oracle_Zero), [0, 0, 0])) {\n",
" return \"Incorrect result for f(x) = 0\";\n",
" }\n",
" \n",

Просмотреть файл

@ -10,7 +10,9 @@
namespace Quantum.Kata.DeutschJozsaAlgorithm {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
@ -23,15 +25,11 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// 1) N qubits in arbitrary state |x⟩ (input register)
// 2) a qubit in arbitrary state |y⟩ (output qubit)
// Goal: transform state |x, y⟩ into state |x, y ⊕ f(x)⟩ (⊕ is addition modulo 2).
operation Oracle_Zero_Reference (x : Qubit[], y : Qubit) : Unit {
body (...) {
// Since f(x) = 0 for all values of x, |y ⊕ f(x)⟩ = |y⟩.
// This means that the operation doesn't need to do any transformation to the inputs.
// Build the project and run the tests to see that T01_Oracle_Zero_Test test passes.
}
adjoint invert;
operation Oracle_Zero_Reference (x : Qubit[], y : Qubit) : Unit
is Adj {
// Since f(x) = 0 for all values of x, |y ⊕ f(x)⟩ = |y⟩.
// This means that the operation doesn't need to do any transformation to the inputs.
// Build the project and run the tests to see that T01_Oracle_Zero_Test test passes.
}
@ -40,15 +38,11 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// 1) N qubits in arbitrary state |x⟩ (input register)
// 2) a qubit in arbitrary state |y⟩ (output qubit)
// Goal: transform state |x, y⟩ into state |x, y ⊕ f(x)⟩ (⊕ is addition modulo 2).
operation Oracle_One_Reference (x : Qubit[], y : Qubit) : Unit {
body (...) {
// Since f(x) = 1 for all values of x, |y ⊕ f(x)⟩ = |y ⊕ 1⟩ = |NOT y⟩.
// This means that the operation needs to flip qubit y (i.e. transform |0⟩ to |1⟩ and vice versa).
X(y);
}
adjoint invert;
operation Oracle_One_Reference (x : Qubit[], y : Qubit) : Unit
is Adj {
// Since f(x) = 1 for all values of x, |y ⊕ f(x)⟩ = |y ⊕ 1⟩ = |NOT y⟩.
// This means that the operation needs to flip qubit y (i.e. transform |0⟩ to |1⟩ and vice versa).
X(y);
}
@ -58,14 +52,10 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// 2) a qubit in arbitrary state |y⟩ (output qubit)
// 3) 0-based index of the qubit from input register (0 <= k < N)
// Goal: transform state |x, y⟩ into state |x, y ⊕ xₖ⟩ (⊕ is addition modulo 2).
operation Oracle_Kth_Qubit_Reference (x : Qubit[], y : Qubit, k : Int) : Unit {
body (...) {
AssertBoolEqual(0 <= k and k < Length(x), true, "k should be between 0 and N-1, inclusive");
CNOT(x[k], y);
}
adjoint invert;
operation Oracle_Kth_Qubit_Reference (x : Qubit[], y : Qubit, k : Int) : Unit
is Adj {
EqualityFactB(0 <= k and k < Length(x), true, "k should be between 0 and N-1, inclusive");
CNOT(x[k], y);
}
@ -74,17 +64,13 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// 1) N qubits in arbitrary state |x⟩ (input register)
// 2) a qubit in arbitrary state |y⟩ (output qubit)
// Goal: transform state |x, y⟩ into state |x, y ⊕ f(x)⟩ (⊕ is addition modulo 2).
operation Oracle_OddNumberOfOnes_Reference (x : Qubit[], y : Qubit) : Unit {
body (...) {
// Hint: f(x) can be represented as x_0 ⊕ x_1 ⊕ ... ⊕ x_(N-1)
for (i in 0 .. Length(x) - 1) {
CNOT(x[i], y);
}
// alternative solution: ApplyToEachA(CNOT(_, y), x);
operation Oracle_OddNumberOfOnes_Reference (x : Qubit[], y : Qubit) : Unit
is Adj {
// Hint: f(x) can be represented as x_0 ⊕ x_1 ⊕ ... ⊕ x_(N-1)
for (q in x) {
CNOT(q, y);
}
adjoint invert;
// alternative solution: ApplyToEachA(CNOT(_, y), x);
}
@ -97,21 +83,17 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// Goal: transform state |x, y⟩ into state |x, y ⊕ f(x)⟩ (⊕ is addition modulo 2).
// Note: the functions featured in tasks 1.1, 1.3 and 1.4 are special cases of this function.
operation Oracle_ProductFunction_Reference (x : Qubit[], y : Qubit, r : Int[]) : Unit {
body (...) {
// The following line enforces the constraint on the input arrays.
// You don't need to modify it. Feel free to remove it, this won't cause your code to fail.
AssertIntEqual(Length(x), Length(r), "Arrays should have the same length");
operation Oracle_ProductFunction_Reference (x : Qubit[], y : Qubit, r : Int[]) : Unit
is Adj {
// The following line enforces the constraint on the input arrays.
// You don't need to modify it. Feel free to remove it, this won't cause your code to fail.
EqualityFactI(Length(x), Length(r), "Arrays should have the same length");
for (i in 0 .. Length(x) - 1) {
if (r[i] == 1) {
CNOT(x[i], y);
}
for (i in IndexRange(x)) {
if (r[i] == 1) {
CNOT(x[i], y);
}
}
adjoint invert;
}
@ -122,26 +104,22 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// 3) a bit vector of length N represented as Int[]
// You are guaranteed that the qubit array and the bit vector have the same length.
// Goal: transform state |x, y⟩ into state |x, y ⊕ f(x)⟩ (⊕ is addition modulo 2).
operation Oracle_ProductWithNegationFunction_Reference (x : Qubit[], y : Qubit, r : Int[]) : Unit {
body (...) {
// The following line enforces the constraint on the input arrays.
// You don't need to modify it. Feel free to remove it, this won't cause your code to fail.
AssertIntEqual(Length(x), Length(r), "Arrays should have the same length");
operation Oracle_ProductWithNegationFunction_Reference (x : Qubit[], y : Qubit, r : Int[]) : Unit
is Adj {
// The following line enforces the constraint on the input arrays.
// You don't need to modify it. Feel free to remove it, this won't cause your code to fail.
EqualityFactI(Length(x), Length(r), "Arrays should have the same length");
for (i in 0 .. Length(x) - 1) {
if (r[i] == 1) {
CNOT(x[i], y);
} else {
// do a 0-controlled NOT
X(x[i]);
CNOT(x[i], y);
X(x[i]);
}
for (i in IndexRange(x)) {
if (r[i] == 1) {
CNOT(x[i], y);
} else {
// do a 0-controlled NOT
X(x[i]);
CNOT(x[i], y);
X(x[i]);
}
}
adjoint invert;
}
@ -154,40 +132,36 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// A prefix of length k of a state |x⟩ = |x₁, ..., xₙ⟩ is the state of its first k qubits |x₁, ..., xₖ⟩.
// For example, a prefix of length 2 of a state |0110⟩ is 01.
operation Oracle_HammingWithPrefix_Reference (x : Qubit[], y : Qubit, prefix : Int[]) : Unit {
body (...) {
// The following line enforces the constraint on the input arrays.
// You don't need to modify it. Feel free to remove it, this won't cause your code to fail.
let P = Length(prefix);
AssertBoolEqual(1 <= P and P <= Length(x), true, "P should be between 1 and N, inclusive");
operation Oracle_HammingWithPrefix_Reference (x : Qubit[], y : Qubit, prefix : Int[]) : Unit
is Adj {
// The following line enforces the constraint on the input arrays.
// You don't need to modify it. Feel free to remove it, this won't cause your code to fail.
let P = Length(prefix);
EqualityFactB(1 <= P and P <= Length(x), true, "P should be between 1 and N, inclusive");
// Hint: the first part of the function is the same as in task 1.4
for (i in 0 .. Length(x) - 1) {
CNOT(x[i], y);
}
// Hint: the first part of the function is the same as in task 1.4
for (q in x) {
CNOT(q, y);
}
// add check for prefix as a multicontrolled NOT
// true bits of r correspond to 1-controls, false bits - to 0-controls
for (i in 0 .. P - 1) {
// add check for prefix as a multicontrolled NOT
// true bits of r correspond to 1-controls, false bits - to 0-controls
for (i in 0 .. P - 1) {
if (prefix[i] == 0) {
X(x[i]);
}
}
Controlled X(x[0 .. P - 1], y);
// uncompute changes done to input register
for (i in 0 .. P - 1) {
if (prefix[i] == 0) {
X(x[i]);
}
if (prefix[i] == 0) {
X(x[i]);
}
}
Controlled X(x[0 .. P - 1], y);
// uncompute changes done to input register
for (i in 0 .. P - 1) {
if (prefix[i] == 0) {
X(x[i]);
}
}
adjoint invert;
}
@ -196,20 +170,16 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// 1) 3 qubits in arbitrary state |x⟩ (input register)
// 2) a qubit in arbitrary state |y⟩ (output qubit)
// Goal: transform state |x, y⟩ into state |x, y ⊕ f(x)⟩ (⊕ is addition modulo 2).
operation Oracle_MajorityFunction_Reference (x : Qubit[], y : Qubit) : Unit {
body (...) {
// The following line enforces the constraint on the input array.
// You don't need to modify it. Feel free to remove it, this won't cause your code to fail.
AssertBoolEqual(3 == Length(x), true, "x should have exactly 3 qubits");
operation Oracle_MajorityFunction_Reference (x : Qubit[], y : Qubit) : Unit
is Adj {
// The following line enforces the constraint on the input array.
// You don't need to modify it. Feel free to remove it, this won't cause your code to fail.
EqualityFactB(3 == Length(x), true, "x should have exactly 3 qubits");
// Hint: represent f(x) in terms of AND and ⊕ operations
CCNOT(x[0], x[1], y);
CCNOT(x[0], x[2], y);
CCNOT(x[1], x[2], y);
}
adjoint invert;
// Hint: represent f(x) in terms of AND and ⊕ operations
CCNOT(x[0], x[1], y);
CCNOT(x[0], x[2], y);
CCNOT(x[1], x[2], y);
}
@ -225,15 +195,11 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// 1) create an equal superposition of all basis vectors from |0...0⟩ to |1...1⟩ on query register
// (i.e. state (|0...0⟩ + ... + |1...1⟩) / sqrt(2^N) )
// 2) create |-⟩ state (|-⟩ = (|0⟩ - |1⟩) / sqrt(2)) on answer register
operation BV_StatePrep_Reference (query : Qubit[], answer : Qubit) : Unit {
body (...) {
ApplyToEachA(H, query);
X(answer);
H(answer);
}
adjoint invert;
operation BV_StatePrep_Reference (query : Qubit[], answer : Qubit) : Unit
is Adj {
ApplyToEachA(H, query);
X(answer);
H(answer);
}
@ -252,9 +218,7 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// |10...0⟩|0⟩ = |10...0⟩|r₀⟩, |010...0⟩|0⟩ = |010...0⟩|r₁⟩ and so on.
// Quantum computing allows to perform this task in just one call to the oracle; try to implement this algorithm.
operation BV_Algorithm_Reference (N : Int, Uf : ((Qubit[], Qubit) => Unit)) : Int[] {
mutable r = new Int[N];
// allocate N qubits for input register and 1 qubit for output
using ((x, y) = (Qubit[N], Qubit())) {
@ -269,18 +233,18 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// measure all qubits of the input register;
// the result of each measurement is converted to an Int
mutable r = new Int[N];
for (i in 0 .. N - 1) {
if (M(x[i]) != Zero) {
set r[i] = 1;
set r w/= i <- 1;
}
}
// before releasing the qubits make sure they are all in |0⟩ state
ResetAll(x);
Reset(y);
return r;
}
return r;
}
@ -339,11 +303,7 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// Output:
// A bit vector r which generates the same oracle as the one you are given
operation Noname_Algorithm_Reference (N : Int, Uf : ((Qubit[], Qubit) => Unit)) : Int[] {
// Declare a Bool array in which the result will be stored;
// the array has to be mutable to allow updating its elements.
mutable r = new Int[N];
using ((x, y) = (Qubit[N], Qubit())) {
// apply oracle to qubits in all 0 state
Uf(x, y);
@ -356,19 +316,22 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// now y = Σᵢ 𝑟ᵢ
// Declare an Int array in which the result will be stored;
// the variable has to be mutable to allow updating it.
mutable r = new Int[N];
// measure the output register
let m = M(y);
if (m == One) {
// adjust parity of bit vector r
set r[0] = 1;
set r w/= 0 <- 1;
}
// before releasing the qubits make sure they are all in |0⟩ state
ResetAll(x);
Reset(y);
return r;
}
return r;
}
}

Просмотреть файл

@ -3,7 +3,8 @@
namespace Quantum.Kata.DeutschJozsaAlgorithm {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
@ -70,7 +71,7 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
operation Oracle_Kth_Qubit (x : Qubit[], y : Qubit, k : Int) : Unit {
// The following line enforces the constraints on the value of k that you are given.
// You don't need to modify it. Feel free to remove it, this won't cause your code to fail.
AssertBoolEqual(0 <= k and k < Length(x), true, "k should be between 0 and N-1, inclusive");
EqualityFactB(0 <= k and k < Length(x), true, "k should be between 0 and N-1, inclusive");
// ...
}
@ -100,7 +101,7 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
operation Oracle_ProductFunction (x : Qubit[], y : Qubit, r : Int[]) : Unit {
// The following line enforces the constraint on the input arrays.
// You don't need to modify it. Feel free to remove it, this won't cause your code to fail.
AssertIntEqual(Length(x), Length(r), "Arrays should have the same length");
EqualityFactI(Length(x), Length(r), "Arrays should have the same length");
// ...
}
@ -116,7 +117,7 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
operation Oracle_ProductWithNegationFunction (x : Qubit[], y : Qubit, r : Int[]) : Unit {
// The following line enforces the constraint on the input arrays.
// You don't need to modify it. Feel free to remove it, this won't cause your code to fail.
AssertIntEqual(Length(x), Length(r), "Arrays should have the same length");
EqualityFactI(Length(x), Length(r), "Arrays should have the same length");
// ...
}
@ -135,7 +136,7 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// The following line enforces the constraint on the input arrays.
// You don't need to modify it. Feel free to remove it, this won't cause your code to fail.
let P = Length(prefix);
AssertBoolEqual(1 <= P and P <= Length(x), true, "P should be between 1 and N, inclusive");
EqualityFactB(1 <= P and P <= Length(x), true, "P should be between 1 and N, inclusive");
// Hint: the first part of the function is the same as in task 1.4
@ -156,7 +157,7 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
operation Oracle_MajorityFunction (x : Qubit[], y : Qubit) : Unit {
// The following line enforces the constraint on the input array.
// You don't need to modify it. Feel free to remove it, this won't cause your code to fail.
AssertBoolEqual(3 == Length(x), true, "x should have exactly 3 qubits");
EqualityFactB(3 == Length(x), true, "x should have exactly 3 qubits");
// Hint: represent f(x) in terms of AND and ⊕ operations
@ -176,13 +177,9 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// 1) create an equal superposition of all basis vectors from |0...0⟩ to |1...1⟩ on query register
// (i.e. state (|0...0⟩ + ... + |1...1⟩) / sqrt(2^N) )
// 2) create |-⟩ state (|-⟩ = (|0⟩ - |1⟩) / sqrt(2)) on answer register
operation BV_StatePrep (query : Qubit[], answer : Qubit) : Unit {
body (...) {
operation BV_StatePrep (query : Qubit[], answer : Qubit) : Unit
is Adj {
// ...
}
adjoint invert;
}
@ -203,7 +200,7 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
operation BV_Algorithm (N : Int, Uf : ((Qubit[], Qubit) => Unit)) : Int[] {
// Declare an Int array in which the result will be stored;
// the array has to be mutable to allow updating its elements.
// the variable has to be mutable to allow updating it.
mutable r = new Int[N];
// ...
@ -226,7 +223,7 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// You might want to use something like the following:
// let oracle = Oracle_ProductFunction(_, _, [...your bit vector here...]);
// Hint: use AssertIntArrayEqual function to assert that the return value of BV_Algorithm operation
// Hint: use AllEqualityFactI function to assert that the return value of BV_Algorithm operation
// matches the expected value (i.e. the bit vector passed to Oracle_ProductFunction).
// BV_Test appears in the list of unit tests for the solution; run it to verify your code.
@ -278,7 +275,7 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// Hint: you will need to use partial application to test ones such as Oracle_Kth_Qubit and Oracle_ProductFunction;
// see task 2.3 for a description of how to do that.
// Hint: use AssertBoolEqual function to assert that the return value of DJ_Algorithm operation matches the expected value
// Hint: use EqualityFactB function to assert that the return value of DJ_Algorithm operation matches the expected value
// DJ_Test appears in the list of unit tests for the solution; run it to verify your code.
@ -306,7 +303,7 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// it just needs to produce equivalent results.
// Declare an Int array in which the result will be stored;
// the array has to be mutable to allow updating its elements.
// the variable has to be mutable to allow updating it.
mutable r = new Int[N];
// ...

Просмотреть файл

@ -9,9 +9,10 @@
namespace Quantum.Kata.DeutschJozsaAlgorithm {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Testing;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Diagnostics;
open Quantum.Kata.Utils;
@ -24,26 +25,22 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// ------------------------------------------------------
operation ApplyOracleA (qs : Qubit[], oracle : ((Qubit[], Qubit) => Unit : Adjoint)) : Unit {
body (...) {
let N = Length(qs);
oracle(qs[0 .. N - 2], qs[N - 1]);
}
adjoint invert;
operation ApplyOracleA (qs : Qubit[], oracle : ((Qubit[], Qubit) => Unit is Adj)) : Unit
is Adj {
let N = Length(qs);
oracle(qs[0 .. N - 2], qs[N - 1]);
}
// ------------------------------------------------------
operation AssertTwoOraclesAreEqual (nQubits : Range,
oracle1 : ((Qubit[], Qubit) => Unit),
oracle2 : ((Qubit[], Qubit) => Unit : Adjoint)) : Unit {
oracle2 : ((Qubit[], Qubit) => Unit is Adj)) : Unit {
let sol = ApplyOracle(_, oracle1);
let refSol = ApplyOracleA(_, oracle2);
for (i in nQubits) {
AssertOperationsEqualReferenced(sol, refSol, i + 1);
AssertOperationsEqualReferenced(i + 1, sol, refSol);
}
}
@ -85,7 +82,7 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// ------------------------------------------------------
operation AssertTwoOraclesWithIntAreEqual (r : Int[],
oracle1 : ((Qubit[], Qubit, Int[]) => Unit),
oracle2 : ((Qubit[], Qubit, Int[]) => Unit : Adjoint)) : Unit {
oracle2 : ((Qubit[], Qubit, Int[]) => Unit is Adj)) : Unit {
AssertTwoOraclesAreEqual(Length(r) .. Length(r), oracle1(_, _, r), oracle2(_, _, r));
}
@ -102,7 +99,7 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// the mask with all 0's corresponds to Oracle_Zero
for (i in 0 .. L - 1) {
set r[i] = 0;
set r w/= i <- 0;
}
for (i in 2 .. L) {
@ -111,9 +108,7 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// the mask with only the K-th element set to 1 corresponds to Oracle_Kth_Qubit
for (i in 0 .. L - 1) {
set r[i] = 1;
AssertTwoOraclesAreEqual(L .. L, Oracle_ProductFunction(_, _, r), Oracle_Kth_Qubit_Reference(_, _, i));
set r[i] = 0;
AssertTwoOraclesAreEqual(L .. L, Oracle_ProductFunction(_, _, r w/ i <- 1), Oracle_Kth_Qubit_Reference(_, _, i));
}
set r = [1, 0, 1, 0, 1, 0];
@ -184,7 +179,7 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
}
// ------------------------------------------------------
function AssertIntArrayEqual (actual : Int[], expected : Int[], message : String) : Unit {
function AllEqualityFactI (actual : Int[], expected : Int[], message : String) : Unit {
let n = Length(actual);
if (n != Length(expected)) {
@ -202,12 +197,12 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// ------------------------------------------------------
function IntArrFromPositiveInt (n : Int, bits : Int) : Int[] {
let rbool = BoolArrFromPositiveInt(n, bits);
let rbool = IntAsBoolArray(n, bits);
mutable r = new Int[bits];
for (i in 0 .. bits - 1) {
if (rbool[i]) {
set r[i] = 1;
set r w/= i <- 1;
}
}
@ -218,10 +213,10 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// ------------------------------------------------------
operation AssertBVAlgorithmWorks (r : Int[]) : Unit {
let oracle = Oracle_ProductFunction_Reference(_, _, r);
AssertIntArrayEqual(BV_Algorithm(Length(r), oracle), r, "Bernstein-Vazirani algorithm failed");
AllEqualityFactI(BV_Algorithm(Length(r), oracle), r, "Bernstein-Vazirani algorithm failed");
let nu = GetOracleCallsCount(oracle);
AssertBoolEqual(nu <= 1, true, $"You are allowed to call the oracle at most once, and you called it {nu} times");
EqualityFactB(nu <= 1, true, $"You are allowed to call the oracle at most once, and you called it {nu} times");
}
@ -244,10 +239,10 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// ------------------------------------------------------
operation AssertDJAlgorithmWorks (N : Int, oracle : ((Qubit[], Qubit) => Unit), expected : Bool, msg : String) : Unit {
AssertBoolEqual(DJ_Algorithm(N, oracle), expected, msg);
EqualityFactB(DJ_Algorithm(N, oracle), expected, msg);
let nu = GetOracleCallsCount(oracle);
AssertBoolEqual(nu <= 1, true, $"You are allowed to call the oracle at most once, and you called it {nu} times");
EqualityFactB(nu <= 1, true, $"You are allowed to call the oracle at most once, and you called it {nu} times");
}
@ -284,11 +279,11 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
// check that the oracle was called once (later it will be called again by test harness)
let nu = GetOracleCallsCount(givenOracle);
AssertBoolEqual(nu <= 1, true, $"You are allowed to call the oracle at most once, and you called it {nu} times");
EqualityFactB(nu <= 1, true, $"You are allowed to call the oracle at most once, and you called it {nu} times");
// check that the oracle obtained from r
// is equivalent to the oracle obtained from return value
AssertIntEqual(Length(res), Length(r), "Returned bit vector must have the same length as the oracle input.");
EqualityFactI(Length(res), Length(r), "Returned bit vector must have the same length as the oracle input.");
let resOracle = Oracle_ProductWithNegationFunction_Reference(_, _, res);
AssertTwoOraclesAreEqual(Length(r) .. Length(r), givenOracle, resOracle);
}
@ -318,3 +313,4 @@ namespace Quantum.Kata.DeutschJozsaAlgorithm {
AssertNonameAlgorithmWorks([1, 0, 1, 0, 1, 0]);
}
}

Просмотреть файл

@ -42,7 +42,7 @@ ENV PATH=$PATH:${HOME}/dotnet:${HOME}/.dotnet/tools \
DOTNET_ROOT=${HOME}/dotnet
# install IQSharp
RUN dotnet tool install -g Microsoft.Quantum.IQSharp --version 0.5.1904.1302
RUN dotnet tool install -g Microsoft.Quantum.IQSharp --version 0.6.1905.301
RUN dotnet iqsharp install --user --path-to-tool="$(which dotnet-iqsharp)"
# Make sure the contents of our repo are in ${HOME}

Просмотреть файл

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
@ -7,9 +7,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Canon" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Standard" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />

Просмотреть файл

@ -10,9 +10,9 @@
namespace Quantum.Kata.GHZGame {
open Microsoft.Quantum.Math;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
//////////////////////////////////////////////////////////////////
@ -42,7 +42,7 @@ namespace Quantum.Kata.GHZGame {
operation PlayClassicalGHZ_Reference (strategy : (Bool => Bool), inputs : Bool[]) : Bool[] {
mutable results = new Bool[Length(inputs)];
for (i in 0..Length(inputs) - 1) {
set results[i] = strategy(inputs[i]);
set results w/= i <- strategy(inputs[i]);
}
return results;
}
@ -53,23 +53,21 @@ namespace Quantum.Kata.GHZGame {
//////////////////////////////////////////////////////////////////
// Task 2.1. Entangled triple
operation CreateEntangledTriple_Reference (qs : Qubit[]) : Unit {
body (...) {
X(qs[0]);
X(qs[1]);
operation CreateEntangledTriple_Reference (qs : Qubit[]) : Unit
is Adj {
X(qs[0]);
X(qs[1]);
H(qs[0]);
H(qs[1]);
// At this point we have (|000⟩ - |010⟩ - |100⟩ + |110⟩) / 2
H(qs[0]);
H(qs[1]);
// At this point we have (|000⟩ - |010⟩ - |100⟩ + |110⟩) / 2
// Flip the sign of the last term
Controlled Z([qs[0]], qs[1]);
// Flip the sign of the last term
Controlled Z([qs[0]], qs[1]);
// Flip the state of the last qubit for the two middle terms
(ControlledOnBitString([false, true], X))([qs[0], qs[1]], qs[2]);
(ControlledOnBitString([true, false], X))([qs[0], qs[1]], qs[2]);
}
adjoint auto;
// Flip the state of the last qubit for the two middle terms
(ControlledOnBitString([false, true], X))([qs[0], qs[1]], qs[2]);
(ControlledOnBitString([true, false], X))([qs[0], qs[1]], qs[2]);
}
@ -84,19 +82,18 @@ namespace Quantum.Kata.GHZGame {
// Task 2.3. Play the GHZ game using the quantum strategy
operation PlayQuantumGHZ_Reference (strategies : (Qubit => Bool)[]) : Bool[] {
mutable abc = new Bool[3];
using (qs = Qubit[3]) {
CreateEntangledTriple_Reference(qs);
mutable abc = new Bool[3];
for (i in 0..2) {
set abc[i] = strategies[i](qs[i]);
set abc w/= i <- strategies[i](qs[i]);
}
ResetAll(qs);
return abc;
}
return abc;
}
}

Просмотреть файл

@ -9,10 +9,11 @@
namespace Quantum.Kata.GHZGame {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Math;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Testing;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Diagnostics;
// All possible starting bits (r, s and t) that the referee can give
// to Alice, Bob and Charlie.
@ -27,7 +28,7 @@ namespace Quantum.Kata.GHZGame {
for (rst in RefereeBits()) {
for (i in 0..1 <<< 3 - 1) {
let abc = BoolArrFromPositiveInt(i, 3);
AssertBoolEqual(
EqualityFactB(
WinCondition(rst, abc),
WinCondition_Reference(rst, abc),
$"Win condition is wrong for rst={rst}, abc={abc}");
@ -47,17 +48,17 @@ namespace Quantum.Kata.GHZGame {
set wins = wins + 1;
}
}
return ToDouble(wins) / ToDouble(N);
return IntAsDouble(wins) / IntAsDouble(N);
}
operation T12_RandomClassical_Test () : Unit {
AssertAlmostEqualTol(GetClassicalStrategySuccessRate(10000, RandomClassicalStrategy), 0.5, 0.02);
EqualityWithinToleranceFact(GetClassicalStrategySuccessRate(10000, RandomClassicalStrategy), 0.5, 0.02);
}
// ------------------------------------------------------
operation T13_BestClassical_Test () : Unit {
AssertAlmostEqualTol(GetClassicalStrategySuccessRate(10000, BestClassicalStrategy), 0.75, 0.02);
EqualityWithinToleranceFact(GetClassicalStrategySuccessRate(10000, BestClassicalStrategy), 0.75, 0.02);
}
@ -74,7 +75,7 @@ namespace Quantum.Kata.GHZGame {
for (mode in 0..3) {
let result = PlayClassicalGHZ(TestStrategy(_, mode), rst);
let expected = PlayClassicalGHZ_Reference(TestStrategy(_, mode), rst);
AssertBoolArrayEqual(result, expected, $"Unexpected result for rst={rst}");
AllEqualityFactB(result, expected, $"Unexpected result for rst={rst}");
}
}
}
@ -83,7 +84,7 @@ namespace Quantum.Kata.GHZGame {
// Part II. Quantum GHZ
//////////////////////////////////////////////////////////////////
operation AssertEqualOnZeroState (N : Int, taskImpl : (Qubit[] => Unit), refImpl : (Qubit[] => Unit : Adjoint)) : Unit {
operation AssertEqualOnZeroState (N : Int, taskImpl : (Qubit[] => Unit), refImpl : (Qubit[] => Unit is Adj)) : Unit {
using (qs = Qubit[N]) {
// apply operation that needs to be tested
taskImpl(qs);
@ -104,20 +105,20 @@ namespace Quantum.Kata.GHZGame {
// ------------------------------------------------------
operation T22_QuantumStrategy_Test () : Unit {
using (q = Qubit()) {
AssertBoolEqual(QuantumStrategy(false, q), false, "|0⟩ not measured as false");
EqualityFactB(QuantumStrategy(false, q), false, "|0⟩ not measured as false");
Reset(q);
X(q);
AssertBoolEqual(QuantumStrategy(false, q), true, "|1⟩ not measured as true");
EqualityFactB(QuantumStrategy(false, q), true, "|1⟩ not measured as true");
Reset(q);
H(q);
AssertBoolEqual(QuantumStrategy(true, q), false, "|+⟩ is not measured as false");
EqualityFactB(QuantumStrategy(true, q), false, "|+⟩ is not measured as false");
Reset(q);
X(q);
H(q);
AssertBoolEqual(QuantumStrategy(true, q), true, "|-⟩ is not measured as true");
EqualityFactB(QuantumStrategy(true, q), true, "|-⟩ is not measured as true");
Reset(q);
}
}
@ -129,7 +130,7 @@ namespace Quantum.Kata.GHZGame {
let rst = (RefereeBits())[RandomInt(Length(RefereeBits()))];
let strategies = [QuantumStrategy(rst[0], _), QuantumStrategy(rst[1], _), QuantumStrategy(rst[2], _)];
let abc = PlayQuantumGHZ(strategies);
AssertBoolEqual(WinCondition_Reference(rst, abc), true,
EqualityFactB(WinCondition_Reference(rst, abc), true,
$"Quantum strategy lost: for rst={rst} the players returned abc={abc}");
}
}

Просмотреть файл

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
@ -7,9 +7,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Canon" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Standard" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />

Просмотреть файл

@ -10,90 +10,74 @@
namespace Quantum.Kata.GroversAlgorithm {
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
//////////////////////////////////////////////////////////////////
// Part I. Oracles for Grover's Search
//////////////////////////////////////////////////////////////////
// Task 1.1. The |11...1⟩ oracle
operation Oracle_AllOnes_Reference (queryRegister : Qubit[], target : Qubit) : Unit {
body (...) {
Controlled X(queryRegister, target);
}
adjoint invert;
operation Oracle_AllOnes_Reference (queryRegister : Qubit[], target : Qubit) : Unit
is Adj {
Controlled X(queryRegister, target);
}
// Task 1.2. The |1010...⟩ oracle
operation Oracle_AlternatingBits_Reference (queryRegister : Qubit[], target : Qubit) : Unit {
body (...) {
// flip the bits in odd (0-based positions),
// so that the condition for flipping the state of the target qubit is "query register is in 1...1 state"
FlipOddPositionBits_Reference(queryRegister);
Controlled X(queryRegister, target);
Adjoint FlipOddPositionBits_Reference(queryRegister);
}
adjoint invert;
operation Oracle_AlternatingBits_Reference (queryRegister : Qubit[], target : Qubit) : Unit
is Adj {
// flip the bits in odd (0-based positions),
// so that the condition for flipping the state of the target qubit is "query register is in 1...1 state"
FlipOddPositionBits_Reference(queryRegister);
Controlled X(queryRegister, target);
Adjoint FlipOddPositionBits_Reference(queryRegister);
}
operation FlipOddPositionBits_Reference (register : Qubit[]) : Unit {
operation FlipOddPositionBits_Reference (register : Qubit[]) : Unit
is Adj {
body (...) {
// iterate over elements in odd positions (indexes are 0-based)
for (i in 1 .. 2 .. Length(register) - 1) {
X(register[i]);
}
// iterate over elements in odd positions (indexes are 0-based)
for (i in 1 .. 2 .. Length(register) - 1) {
X(register[i]);
}
adjoint invert;
}
// Task 1.3. Arbitrary bit pattern oracle
operation Oracle_ArbitraryPattern_Reference (queryRegister : Qubit[], target : Qubit, pattern : Bool[]) : Unit {
body (...) {
(ControlledOnBitString(pattern, X))(queryRegister, target);
}
adjoint invert;
operation Oracle_ArbitraryPattern_Reference (queryRegister : Qubit[], target : Qubit, pattern : Bool[]) : Unit
is Adj {
(ControlledOnBitString(pattern, X))(queryRegister, target);
}
// Task 1.4*. Oracle converter
operation OracleConverterImpl_Reference (markingOracle : ((Qubit[], Qubit) => Unit : Adjoint), register : Qubit[]) : Unit {
operation OracleConverterImpl_Reference (markingOracle : ((Qubit[], Qubit) => Unit is Adj), register : Qubit[]) : Unit
is Adj {
body (...) {
using (target = Qubit()) {
// Put the target into the |-⟩ state
X(target);
H(target);
using (target = Qubit()) {
// Put the target into the |-⟩ state
X(target);
H(target);
// Apply the marking oracle; since the target is in the |-⟩ state,
// flipping the target if the register satisfies the oracle condition will apply a -1 factor to the state
markingOracle(register, target);
// Apply the marking oracle; since the target is in the |-⟩ state,
// flipping the target if the register satisfies the oracle condition will apply a -1 factor to the state
markingOracle(register, target);
// Put the target back into |0⟩ so we can return it
H(target);
X(target);
}
// Put the target back into |0⟩ so we can return it
H(target);
X(target);
}
adjoint invert;
}
function OracleConverter_Reference (markingOracle : ((Qubit[], Qubit) => Unit : Adjoint)) : (Qubit[] => Unit : Adjoint) {
function OracleConverter_Reference (markingOracle : ((Qubit[], Qubit) => Unit is Adj)) : (Qubit[] => Unit is Adj) {
return OracleConverterImpl_Reference(markingOracle, _);
}
@ -103,19 +87,16 @@ namespace Quantum.Kata.GroversAlgorithm {
//////////////////////////////////////////////////////////////////
// Task 2.1. The Hadamard transform
operation HadamardTransform_Reference (register : Qubit[]) : Unit {
operation HadamardTransform_Reference (register : Qubit[]) : Unit
is Adj {
body (...) {
ApplyToEachA(H, register);
ApplyToEachA(H, register);
// ApplyToEach is a library routine that is equivalent to the following code:
// let nQubits = Length(register);
// for (idxQubit in 0..nQubits - 1) {
// H(register[idxQubit]);
// }
}
adjoint invert;
// ApplyToEach is a library routine that is equivalent to the following code:
// let nQubits = Length(register);
// for (idxQubit in 0..nQubits - 1) {
// H(register[idxQubit]);
// }
}
@ -149,16 +130,13 @@ namespace Quantum.Kata.GroversAlgorithm {
// Task 2.3. The Grover iteration
operation GroverIteration_Reference (register : Qubit[], oracle : (Qubit[] => Unit : Adjoint)) : Unit {
operation GroverIteration_Reference (register : Qubit[], oracle : (Qubit[] => Unit is Adj)) : Unit
is Adj {
body (...) {
oracle(register);
HadamardTransform_Reference(register);
ConditionalPhaseFlip_Reference(register);
HadamardTransform_Reference(register);
}
adjoint invert;
oracle(register);
HadamardTransform_Reference(register);
ConditionalPhaseFlip_Reference(register);
HadamardTransform_Reference(register);
}
@ -167,18 +145,15 @@ namespace Quantum.Kata.GroversAlgorithm {
//////////////////////////////////////////////////////////////////
// Task 3.1. Grover's search
operation GroversSearch_Reference (register : Qubit[], oracle : ((Qubit[], Qubit) => Unit : Adjoint), iterations : Int) : Unit {
operation GroversSearch_Reference (register : Qubit[], oracle : ((Qubit[], Qubit) => Unit is Adj), iterations : Int) : Unit
is Adj {
body (...) {
let phaseOracle = OracleConverter_Reference(oracle);
HadamardTransform_Reference(register);
let phaseOracle = OracleConverter_Reference(oracle);
HadamardTransform_Reference(register);
for (i in 1 .. iterations) {
GroverIteration_Reference(register, phaseOracle);
}
for (i in 1 .. iterations) {
GroverIteration_Reference(register, phaseOracle);
}
adjoint invert;
}
}

Просмотреть файл

@ -3,9 +3,10 @@
namespace Quantum.Kata.GroversAlgorithm {
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
@ -18,7 +19,7 @@ namespace Quantum.Kata.GroversAlgorithm {
// It covers the following topics:
// - writing oracles for Grover's search,
// - performing steps of the algorithm, and
// - putting it all together: Grover's search algorithm.
// - putting it all together: Grover's search algorithm.
// Each task is wrapped in one operation preceded by the description of the task.
// Each task (except tasks in which you have to write a test) has a unit test associated with it,
@ -94,7 +95,7 @@ namespace Quantum.Kata.GroversAlgorithm {
body (...) {
// The following line enforces the constraint on the input arrays.
// You don't need to modify it. Feel free to remove it, this won't cause your code to fail.
AssertIntEqual(Length(queryRegister), Length(pattern), "Arrays should have the same length");
EqualityFactI(Length(queryRegister), Length(pattern), "Arrays should have the same length");
// ...
}
@ -113,7 +114,7 @@ namespace Quantum.Kata.GroversAlgorithm {
// but it is often easier to write a marking oracle for a given condition. This transformation
// allows to convert one type of oracle into the other. The transformation is described at
// https://en.wikipedia.org/wiki/Grover%27s_algorithm, section "Description of Uω".
function OracleConverter (markingOracle : ((Qubit[], Qubit) => Unit : Adjoint)) : (Qubit[] => Unit : Adjoint) {
function OracleConverter (markingOracle : ((Qubit[], Qubit) => Unit is Adj)) : (Qubit[] => Unit is Adj) {
// Hint: Remember that you can define auxiliary operations.
@ -135,13 +136,9 @@ namespace Quantum.Kata.GroversAlgorithm {
//
// Note: If the register started in the |0...0⟩ state, this operation
// will prepare an equal superposition of all 2^N basis states.
operation HadamardTransform (register : Qubit[]) : Unit {
body (...) {
// ...
}
adjoint invert;
operation HadamardTransform (register : Qubit[]) : Unit
is Adj {
// ...
}
@ -152,19 +149,16 @@ namespace Quantum.Kata.GroversAlgorithm {
// If the register is in state |0...0⟩, leave it unchanged.
// If the register is in any other basis state, multiply its phase by -1.
// Note: This operation implements operator 2|0...0⟩⟨0...0| - I.
operation ConditionalPhaseFlip (register : Qubit[]) : Unit {
body (...) {
// Hint 1: Note that quantum states are defined up to a global phase.
// Thus the state obtained as a result of this operation is the same
// as the state obtained by flipping the sign of only the |0...0⟩ state.
operation ConditionalPhaseFlip (register : Qubit[]) : Unit
is Adj {
// Hint 1: Note that quantum states are defined up to a global phase.
// Thus the state obtained as a result of this operation is the same
// as the state obtained by flipping the sign of only the |0...0⟩ state.
// Hint 2: You can use the same trick as in the oracle converter task.
// Hint 2: You can use the same trick as in the oracle converter task.
// ...
}
adjoint invert;
// ...
}
@ -174,19 +168,16 @@ namespace Quantum.Kata.GroversAlgorithm {
// 2) a phase-flipping oracle that takes an N-qubit register and flips
// the phase of the state if the register is in the desired state.
// Goal: Perform one Grover iteration.
operation GroverIteration (register : Qubit[], oracle : (Qubit[] => Unit : Adjoint)) : Unit {
operation GroverIteration (register : Qubit[], oracle : (Qubit[] => Unit is Adj)) : Unit
is Adj {
body (...) {
// Hint: A Grover iteration consists of 4 steps:
// 1) apply the oracle
// 2) apply the Hadamard transform
// 3) perform a conditional phase shift
// 4) apply the Hadamard transform again
// Hint: A Grover iteration consists of 4 steps:
// 1) apply the oracle
// 2) apply the Hadamard transform
// 3) perform a conditional phase shift
// 4) apply the Hadamard transform again
// ...
}
adjoint invert;
// ...
}
@ -204,8 +195,8 @@ namespace Quantum.Kata.GroversAlgorithm {
//
// Note: The number of iterations is passed as a parameter because it is defined by the nature of the problem
// and is easier to configure/calculate outside the search algorithm itself (for example, in the driver).
operation GroversSearch (register : Qubit[], oracle : ((Qubit[], Qubit) => Unit : Adjoint), iterations : Int) : Unit {
// ...
operation GroversSearch (register : Qubit[], oracle : ((Qubit[], Qubit) => Unit is Adj), iterations : Int) : Unit {
// ...
}
@ -214,16 +205,17 @@ namespace Quantum.Kata.GroversAlgorithm {
// to find the marked elements of the search space.
// This task is not covered by a test and allows you to experiment with running the algorithm.
operation E2E_GroversSearch_Test () : Unit {
// Hint 1: To check whether the algorithm found the correct answer (i.e., an answer marked as 1 by the oracle),
// you can apply the oracle once more to the register after you've measured it and an ancilla qubit,
// which will calculate the function of the answer found by the algorithm.
// Hint 2: Experiment with the number of iterations to see how it affects
// the probability of the algorithm finding the correct answer.
// Hint 1: To check whether the algorithm found the correct answer (i.e., an answer marked as 1 by the oracle),
// you can apply the oracle once more to the register after you've measured it and an ancilla qubit,
// which will calculate the function of the answer found by the algorithm.
// Hint 3: You can use the Message function to write the results to the console.
// Hint 2: Experiment with the number of iterations to see how it affects
// the probability of the algorithm finding the correct answer.
// ...
// Hint 3: You can use the Message function to write the results to the console.
// ...
}
}

Просмотреть файл

@ -9,30 +9,27 @@
namespace Quantum.Kata.GroversAlgorithm {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Extensions.Testing;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
// ------------------------------------------------------
// helper wrapper to represent oracle operation on input and output registers as an operation on an array of qubits
operation QubitArrayWrapperOperation (op : ((Qubit[], Qubit) => Unit : Adjoint), qs : Qubit[]) : Unit {
body (...) {
op(Most(qs), Tail(qs));
}
adjoint invert;
operation QubitArrayWrapperOperation (op : ((Qubit[], Qubit) => Unit is Adj), qs : Qubit[]) : Unit
is Adj {
op(Most(qs), Tail(qs));
}
// ------------------------------------------------------
// helper wrapper to test for operation equality on various register sizes
operation AssertRegisterOperationsEqual (testOp : (Qubit[] => Unit), refOp : (Qubit[] => Unit : Adjoint)) : Unit {
operation AssertRegisterOperationsEqual (testOp : (Qubit[] => Unit), refOp : (Qubit[] => Unit is Adj)) : Unit {
for (n in 2 .. 10) {
AssertOperationsEqualReferenced(testOp, refOp, n);
AssertOperationsEqualReferenced(n, testOp, refOp);
}
}
@ -59,7 +56,7 @@ namespace Quantum.Kata.GroversAlgorithm {
let pattern = BoolArrFromPositiveInt(RandomIntPow2(n), n);
let testOp = QubitArrayWrapperOperation(Oracle_ArbitraryPattern(_, _, pattern), _);
let refOp = QubitArrayWrapperOperation(Oracle_ArbitraryPattern_Reference(_, _, pattern), _);
AssertOperationsEqualReferenced(testOp, refOp, n + 1);
AssertOperationsEqualReferenced(n + 1, testOp, refOp);
}
}
@ -71,7 +68,7 @@ namespace Quantum.Kata.GroversAlgorithm {
let markingOracle = Oracle_ArbitraryPattern_Reference(_, _, pattern);
let phaseOracleRef = OracleConverter_Reference(markingOracle);
let phaseOracleSol = OracleConverter(markingOracle);
AssertOperationsEqualReferenced(phaseOracleSol, phaseOracleRef, n);
AssertOperationsEqualReferenced(n, phaseOracleSol, phaseOracleRef);
}
}
@ -96,7 +93,7 @@ namespace Quantum.Kata.GroversAlgorithm {
let flipOracle = OracleConverter_Reference(markingOracle);
let testOp = GroverIteration(_, flipOracle);
let refOp = GroverIteration_Reference(_, flipOracle);
AssertOperationsEqualReferenced(testOp, refOp, n);
AssertOperationsEqualReferenced(n, testOp, refOp);
}
}
@ -108,7 +105,7 @@ namespace Quantum.Kata.GroversAlgorithm {
let markingOracle = Oracle_ArbitraryPattern_Reference(_, _, pattern);
let testOp = GroversSearch(_, markingOracle, 4);
let refOp = GroversSearch_Reference(_, markingOracle, 4);
AssertOperationsEqualReferenced(testOp, refOp, n);
AssertOperationsEqualReferenced(n, testOp, refOp);
}
}

Просмотреть файл

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
@ -7,9 +7,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Canon" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Standard" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />

Просмотреть файл

@ -10,10 +10,11 @@
namespace Quantum.Kata.JointMeasurements {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Characterization;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
// Task 1. Single-qubit measurement

Просмотреть файл

@ -3,10 +3,10 @@
namespace Quantum.Kata.JointMeasurements {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
//////////////////////////////////////////////////////////////////

Просмотреть файл

@ -9,16 +9,16 @@
namespace Quantum.Kata.JointMeasurements {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Extensions.Testing;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
// "Framework" operation for testing multi-qubit tasks for distinguishing states of an array of qubits
// with Int return
operation DistinguishStates_MultiQubit (Nqubit : Int, Nstate : Int, statePrep : ((Qubit[], Int, Double) => Unit : Adjoint), testImpl : (Qubit[] => Int), preserveState : Bool) : Unit {
operation DistinguishStates_MultiQubit (Nqubit : Int, Nstate : Int, statePrep : ((Qubit[], Int, Double) => Unit is Adj), testImpl : (Qubit[] => Int), preserveState : Bool) : Unit {
let nTotal = 100;
mutable nOk = 0;
@ -36,7 +36,7 @@ namespace Quantum.Kata.JointMeasurements {
// get the solution's answer and verify that it's a match
let ans = testImpl(qs);
if (ans == state) {
set nOk = nOk + 1;
set nOk += 1;
}
if (preserveState) {
@ -50,29 +50,26 @@ namespace Quantum.Kata.JointMeasurements {
}
}
AssertIntEqual(nOk, nTotal, $"{nTotal - nOk} test runs out of {nTotal} returned incorrect state.");
EqualityFactI(nOk, nTotal, $"{nTotal - nOk} test runs out of {nTotal} returned incorrect state.");
}
// ------------------------------------------------------
operation StatePrep_ParityMeasurement (qs : Qubit[], state : Int, alpha : Double) : Unit {
operation StatePrep_ParityMeasurement (qs : Qubit[], state : Int, alpha : Double) : Unit
is Adj {
body (...) {
// prep cos(alpha) * |0..0⟩ + sin(alpha) * |1..1⟩
Ry(2.0 * alpha, qs[0]);
for (i in 1 .. Length(qs) - 1) {
CNOT(qs[0], qs[i]);
}
// prep cos(alpha) * |0..0⟩ + sin(alpha) * |1..1⟩
Ry(2.0 * alpha, qs[0]);
for (i in 1 .. Length(qs) - 1) {
CNOT(qs[0], qs[i]);
}
if (state == 1) {
// flip the state of the last half of the qubits
for (i in 0 .. Length(qs) / 2 - 1) {
X(qs[i]);
}
if (state == 1) {
// flip the state of the last half of the qubits
for (i in 0 .. Length(qs) / 2 - 1) {
X(qs[i]);
}
}
adjoint invert;
}
@ -95,46 +92,38 @@ namespace Quantum.Kata.JointMeasurements {
// ------------------------------------------------------
operation StatePrep_WState_Arbitrary (qs : Qubit[]) : Unit {
operation StatePrep_WState_Arbitrary (qs : Qubit[]) : Unit
is Adj + Ctl {
body (...) {
let N = Length(qs);
let N = Length(qs);
if (N == 1) {
// base case of recursion: |1⟩
X(qs[0]);
}
else {
// |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⟩
let theta = ArcSin(1.0 / Sqrt(ToDouble(N)));
Ry(2.0 * theta, qs[0]);
// do a zero-controlled W-state generation for qubits 1..N-1
X(qs[0]);
Controlled StatePrep_WState_Arbitrary(qs[0 .. 0], qs[1 .. N - 1]);
X(qs[0]);
}
if (N == 1) {
// base case of recursion: |1⟩
X(qs[0]);
}
else {
// |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⟩
let theta = ArcSin(1.0 / Sqrt(IntAsDouble(N)));
Ry(2.0 * theta, qs[0]);
// do a zero-controlled W-state generation for qubits 1..N-1
X(qs[0]);
Controlled StatePrep_WState_Arbitrary(qs[0 .. 0], qs[1 .. N - 1]);
X(qs[0]);
}
adjoint invert;
controlled distribute;
controlled adjoint distribute;
}
operation StatePrep_GHZOrWState (qs : Qubit[], state : Int, alpha : Double) : Unit {
operation StatePrep_GHZOrWState (qs : Qubit[], state : Int, alpha : Double) : Unit
is Adj {
body (...) {
if (state == 0) {
StatePrep_ParityMeasurement(qs, 0, alpha);
} else {
StatePrep_WState_Arbitrary(qs);
}
if (state == 0) {
StatePrep_ParityMeasurement(qs, 0, alpha);
} else {
StatePrep_WState_Arbitrary(qs);
}
adjoint invert;
}
@ -146,22 +135,19 @@ namespace Quantum.Kata.JointMeasurements {
// ------------------------------------------------------
operation StatePrep_DifferentBasis (qs : Qubit[], state : Int, alpha : Double) : Unit {
operation StatePrep_DifferentBasis (qs : Qubit[], state : Int, alpha : Double) : Unit
is Adj {
body (...) {
// prep cos(alpha) * |00⟩ + sin(alpha) * |11⟩
Ry(2.0 * alpha, qs[0]);
CNOT(qs[0], qs[1]);
// prep cos(alpha) * |00⟩ + sin(alpha) * |11⟩
Ry(2.0 * alpha, qs[0]);
CNOT(qs[0], qs[1]);
if (state == 1) {
X(qs[1]);
}
// convert to X basis
ApplyToEachA(H, qs);
if (state == 1) {
X(qs[1]);
}
adjoint invert;
// convert to X basis
ApplyToEachA(H, qs);
}
@ -172,13 +158,9 @@ namespace Quantum.Kata.JointMeasurements {
// ------------------------------------------------------
// prepare state |A⟩ = cos(α) * |0⟩ + sin(α) * |1⟩
operation StatePrep_A (alpha : Double, q : Qubit) : Unit {
body (...) {
Ry(2.0 * alpha, q);
}
adjoint invert;
operation StatePrep_A (alpha : Double, q : Qubit) : Unit
is Adj {
Ry(2.0 * alpha, q);
}
@ -189,7 +171,7 @@ namespace Quantum.Kata.JointMeasurements {
using (qs = Qubit[2]) {
for (i in 0 .. 36) {
let alpha = ((2.0 * PI()) * ToDouble(i)) / 36.0;
let alpha = ((2.0 * PI()) * IntAsDouble(i)) / 36.0;
// prepare A state
StatePrep_A(alpha, qs[0]);
@ -221,8 +203,8 @@ namespace Quantum.Kata.JointMeasurements {
operation T07_ControlledX_General_Test () : Unit {
// In this task the gate is supposed to work on all inputs, so we can compare the unitary to CNOT.
AssertOperationsEqualReferenced(CNOTWrapper, ControlledX_General_Reference, 2);
AssertOperationsEqualReferenced(ControlledX_General, ControlledX_General_Reference, 2);
AssertOperationsEqualReferenced(2, CNOTWrapper, ControlledX_General_Reference);
AssertOperationsEqualReferenced(2, ControlledX_General, ControlledX_General_Reference);
}
}

Просмотреть файл

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
@ -7,9 +7,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Canon" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Standard" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />

Просмотреть файл

@ -32,7 +32,7 @@
"metadata": {},
"outputs": [],
"source": [
"%package Microsoft.Quantum.Katas::0.5.1904.1302"
"%package Microsoft.Quantum.Katas::0.6.1905.301"
]
},
{
@ -42,13 +42,13 @@
"> The package versions in the output of the cell above should always match. If you are running the Notebooks locally and the versions do not match, please install the IQ# version that matches the version of the `Microsoft.Quantum.Katas` package.\n",
"> <details>\n",
"> <summary><u>How to install the right IQ# version</u></summary>\n",
"> For example, if the version of `Microsoft.Quantum.Katas` package above is 0.5.1904.1302, the installation steps are as follows:\n",
"> For example, if the version of `Microsoft.Quantum.Katas` package above is 0.6.1905.301, the installation steps are as follows:\n",
">\n",
"> 1. Stop the kernel.\n",
"> 2. Uninstall the existing version of IQ#:\n",
"> dotnet tool uninstall microsoft.quantum.iqsharp -g\n",
"> 3. Install the matching version:\n",
"> dotnet tool install microsoft.quantum.iqsharp -g --version 0.5.1904.1302\n",
"> dotnet tool install microsoft.quantum.iqsharp -g --version 0.6.1905.301\n",
"> 4. Reinstall the kernel:\n",
"> dotnet iqsharp install\n",
"> 5. Restart the Notebook.\n",

Просмотреть файл

@ -10,10 +10,12 @@
namespace Quantum.Kata.Measurements {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Measurement;
open Microsoft.Quantum.Arithmetic;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
//////////////////////////////////////////////////////////////////
@ -139,7 +141,7 @@ namespace Quantum.Kata.Measurements {
for (q in qs) {
if (M(q) == One) {
set countOnes = countOnes + 1;
set countOnes += 1;
}
}
@ -165,7 +167,7 @@ namespace Quantum.Kata.Measurements {
for (q in qs) {
if (M(q) == One) {
set countOnes = countOnes + 1;
set countOnes += 1;
}
}
@ -429,7 +431,6 @@ namespace Quantum.Kata.Measurements {
// |+⟩ | std | 0 | 1/2 | 1/2
// |0⟩ | had | 1/2 | 0 | 1/2
// |+⟩ | had | 0 | 0 | 1
mutable output = 0;
let basis = RandomInt(2);
// randomize over std and had
@ -437,28 +438,16 @@ namespace Quantum.Kata.Measurements {
// use standard basis
let result = M(q);
if (result == One) {
// this can only arise if the state was |+⟩
set output = 1;
}
else {
set output = -1;
}
// result is One only if the state was |+⟩
return result == One ? 1 | -1;
}
else {
// use Hadamard basis
H(q);
let result = M(q);
if (result == One) {
// this can only arise if the state was |0⟩
set output = 0;
}
else {
set output = -1;
}
// result is One only if the state was |0⟩
return result == One ? 0 | -1;
}
return output;
}
@ -468,7 +457,7 @@ namespace Quantum.Kata.Measurements {
// |A⟩ = 1/sqrt(2) (|0⟩ + |1⟩),
// |B⟩ = 1/sqrt(2) (|0⟩ + ω |1⟩),
// |C⟩ = 1/sqrt(2) (|0⟩ + ω² |1⟩).
// where ω = exp(2π/3) denotes a primitive, complex 3rd root of unity.
// where ω = exp(2π/3) denotes a primitive, complex 3rd root of unity.
// Output: 1 or 2 if qubit was in the |A⟩ state,
// 0 or 2 if qubit was in the |B⟩ state,
// 0 or 1 if qubit was in the |C⟩ state.
@ -489,7 +478,6 @@ namespace Quantum.Kata.Measurements {
// a 4x4 unitary. Using the "Rader trick" we can now block decompose the 3x3 DFT and obtain two
// 2x2 blocks which we can then implement using controlled single qubit gates. We present
// the final resulting circuit without additional commentary.
mutable output = 0;
let alpha = ArcCos(Sqrt(2.0 / 3.0));
using (a = Qubit()) {
@ -510,20 +498,18 @@ namespace Quantum.Kata.Measurements {
// dispatch on the cases
if (res0 == Zero and res1 == Zero) {
set output = 0;
return 0;
}
elif (res0 == One and res1 == Zero) {
set output = 1;
return 1;
}
elif (res0 == Zero and res1 == One) {
set output = 2;
return 2;
}
else {
// this should never occur
set output = 3;
return 3;
}
}
return output;
}
}

Просмотреть файл

@ -3,10 +3,10 @@
namespace Quantum.Kata.Measurements {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
//////////////////////////////////////////////////////////////////
@ -270,7 +270,7 @@ namespace Quantum.Kata.Measurements {
// |A⟩ = 1/sqrt(2) (|0⟩ + |1⟩),
// |B⟩ = 1/sqrt(2) (|0⟩ + ω |1⟩),
// |C⟩ = 1/sqrt(2) (|0⟩ + ω² |1⟩),
// where ω = exp(2iπ/3) denotes a primitive, complex 3rd root of unity.
// where ω = exp(2iπ/3) denotes a primitive, complex 3rd root of unity.
// Output: 1 or 2 if the qubit was in the |A⟩ state,
// 0 or 2 if the qubit was in the |B⟩ state,
// 0 or 1 if the qubit was in the |C⟩ state.

Просмотреть файл

@ -9,11 +9,11 @@
namespace Quantum.Kata.Measurements {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Extensions.Testing;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
open Quantum.Kata.Utils;
@ -38,7 +38,7 @@ namespace Quantum.Kata.Measurements {
// 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;
set nOk += 1;
}
// we're not checking the state of the qubit after the operation
@ -46,15 +46,13 @@ namespace Quantum.Kata.Measurements {
}
}
AssertIntEqual(nOk, nTotal, $"{nTotal - nOk} test runs out of {nTotal} returned incorrect state.");
EqualityFactI(nOk, nTotal, $"{nTotal - nOk} test runs out of {nTotal} returned incorrect state.");
}
// ------------------------------------------------------
operation StatePrep_IsQubitOne (q : Qubit, state : Int) : Unit {
if (state == 0) {
// convert |0⟩ to |0⟩
} else {
if (state != 0) {
// convert |0⟩ to |1⟩
X(q);
}
@ -70,7 +68,7 @@ namespace Quantum.Kata.Measurements {
operation T102_InitializeQubit_Test () : Unit {
using (qs = Qubit[1]) {
for (i in 0 .. 36) {
let alpha = ((2.0 * PI()) * ToDouble(i)) / 36.0;
let alpha = ((2.0 * PI()) * IntAsDouble(i)) / 36.0;
Ry(2.0 * alpha, qs[0]);
// Test Task 1
@ -126,7 +124,7 @@ namespace Quantum.Kata.Measurements {
DistinguishTwoStates_OneQubit(StatePrep_IsQubitPlus, IsQubitA(PI() / 4.0, _));
for (i in 0 .. 10) {
let alpha = (PI() * ToDouble(i)) / 10.0;
let alpha = (PI() * IntAsDouble(i)) / 10.0;
DistinguishTwoStates_OneQubit(StatePrep_IsQubitA(alpha, _, _), IsQubitA(alpha, _));
}
}
@ -158,12 +156,12 @@ namespace Quantum.Kata.Measurements {
// get the solution's answer and verify that it's a match
let ans = testImpl(qs);
if (ans == state) {
set nOk = nOk + 1;
set nOk += 1;
}
// 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}");
EqualityFactB(nm <= 1, true, $"You are allowed to do at most one measurement, and you did {nm}");
}
// we're not checking the state of the qubit after the operation
@ -171,7 +169,7 @@ namespace Quantum.Kata.Measurements {
}
}
AssertIntEqual(nOk, nTotal, $"{nTotal - nOk} test runs out of {nTotal} returned incorrect state.");
EqualityFactI(nOk, nTotal, $"{nTotal - nOk} test runs out of {nTotal} returned incorrect state.");
}
@ -221,11 +219,8 @@ namespace Quantum.Kata.Measurements {
operation StatePrep_TwoBitstringsMeasurement (qs : Qubit[], bits1 : Bool[], bits2 : Bool[], state : Int) : Unit {
if (state == 0) {
StatePrep_Bitstring(qs, bits1);
} else {
StatePrep_Bitstring(qs, bits2);
}
let bits = state == 0 ? bits1 | bits2;
StatePrep_Bitstring(qs, bits);
}
@ -243,31 +238,25 @@ namespace Quantum.Kata.Measurements {
// ------------------------------------------------------
operation WState_Arbitrary_Reference (qs : Qubit[]) : Unit {
body (...) {
let N = Length(qs);
operation WState_Arbitrary_Reference (qs : Qubit[]) : Unit
is Adj + Ctl {
let N = Length(qs);
if (N == 1) {
// base case of recursion: |1⟩
X(qs[0]);
} else {
// |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⟩
let theta = ArcSin(1.0 / Sqrt(ToDouble(N)));
Ry(2.0 * theta, qs[0]);
if (N == 1) {
// base case of recursion: |1⟩
X(qs[0]);
} else {
// |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⟩
let theta = ArcSin(1.0 / Sqrt(IntAsDouble(N)));
Ry(2.0 * theta, qs[0]);
// do a zero-controlled W-state generation for qubits 1..N-1
X(qs[0]);
Controlled WState_Arbitrary_Reference(qs[0 .. 0], qs[1 .. N - 1]);
X(qs[0]);
}
// do a zero-controlled W-state generation for qubits 1..N-1
X(qs[0]);
Controlled WState_Arbitrary_Reference(qs[0 .. 0], qs[1 .. N - 1]);
X(qs[0]);
}
adjoint invert;
controlled distribute;
controlled adjoint distribute;
}
@ -289,16 +278,13 @@ namespace Quantum.Kata.Measurements {
// ------------------------------------------------------
operation GHZ_State_Reference (qs : Qubit[]) : Unit {
operation GHZ_State_Reference (qs : Qubit[]) : Unit
is Adj {
body (...) {
H(qs[0]);
for (i in 1 .. Length(qs) - 1) {
CNOT(qs[0], qs[i]);
}
H(qs[0]);
for (i in 1 .. Length(qs) - 1) {
CNOT(qs[0], qs[i]);
}
adjoint invert;
}
@ -393,23 +379,20 @@ namespace Quantum.Kata.Measurements {
// ------------------------------------------------------
operation StatePrep_ThreeQubitMeasurement (qs : Qubit[], state : Int) : Unit {
operation StatePrep_ThreeQubitMeasurement (qs : Qubit[], state : Int) : Unit
is Adj {
body (...) {
WState_Arbitrary_Reference(qs);
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]);
}
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 {
@ -423,9 +406,7 @@ namespace Quantum.Kata.Measurements {
operation StatePrep_IsQubitZeroOrPlus (q : Qubit, state : Int) : Unit {
if (state == 0) {
// convert |0⟩ to |0⟩
} else {
if (state != 0) {
// convert |0⟩ to |+⟩
H(q);
}
@ -449,7 +430,7 @@ namespace Quantum.Kata.Measurements {
// 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;
set nOk += 1;
}
// we're not checking the state of the qubit after the operation
@ -457,7 +438,7 @@ namespace Quantum.Kata.Measurements {
}
}
if (ToDouble(nOk) < threshold * ToDouble(nTotal)) {
if (IntAsDouble(nOk) < threshold * IntAsDouble(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}%.";
}
}
@ -504,15 +485,15 @@ namespace Quantum.Kata.Measurements {
// keep track of the number of inconclusive answers given
if (ans == -1) {
set nInconc = nInconc + 1;
set nInconc += 1;
}
if (ans == 0 and state == 0) {
set nConclOne = nConclOne + 1;
set nConclOne += 1;
}
if (ans == 1 and state == 1) {
set nConclPlus = nConclPlus + 1;
set nConclPlus += 1;
}
// check if upon conclusive result the answer is actually correct
@ -525,15 +506,15 @@ namespace Quantum.Kata.Measurements {
}
}
if (ToDouble(nInconc) > thresholdInconcl * ToDouble(nTotal)) {
if (IntAsDouble(nInconc) > thresholdInconcl * IntAsDouble(nTotal)) {
fail $"{nInconc} test runs out of {nTotal} returned inconclusive which does not meet the required threshold of at most {thresholdInconcl * 100.0}%.";
}
if (ToDouble(nConclOne) < thresholdConcl * ToDouble(nTotal)) {
if (IntAsDouble(nConclOne) < thresholdConcl * IntAsDouble(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}%.";
}
if (ToDouble(nConclPlus) < thresholdConcl * ToDouble(nTotal)) {
if (IntAsDouble(nConclPlus) < thresholdConcl * IntAsDouble(nTotal)) {
fail $"Only {nConclPlus} test runs out of {nTotal} returned conclusive |+> which does not meet the required threshold of at least {thresholdConcl * 100.0}%.";
}
}

Просмотреть файл

@ -114,7 +114,7 @@ namespace Quantum.Kata.PhaseEstimation
return base.Apply();
}
public override QArray<Qubit> Apply(long count)
public override IQArray<Qubit> Apply(long count)
{
_sim._qubitsAllocated += count;
if (_sim._qubitsAllocated > _sim._maxQubitsAllocated)
@ -140,7 +140,7 @@ namespace Quantum.Kata.PhaseEstimation
base.Apply(q);
}
public override void Apply(QArray<Qubit> qubits)
public override void Apply(IQArray<Qubit> qubits)
{
_sim._qubitsAllocated -= qubits.Length;
base.Apply(qubits);

Просмотреть файл

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
@ -7,9 +7,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Canon" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Standard" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />

Просмотреть файл

@ -10,11 +10,15 @@
namespace Quantum.Kata.PhaseEstimation {
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Extensions.Testing;
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Measurement;
open Microsoft.Quantum.Characterization;
open Microsoft.Quantum.Arithmetic;
open Microsoft.Quantum.Oracles;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
//////////////////////////////////////////////////////////////////
@ -22,39 +26,32 @@ namespace Quantum.Kata.PhaseEstimation {
//////////////////////////////////////////////////////////////////
// Task 1.1. Inputs to QPE: eigenstates of Z/S/T gates.
operation Eigenstates_ZST_Reference (q : Qubit, state : Int) : Unit {
operation Eigenstates_ZST_Reference (q : Qubit, state : Int) : Unit
is Adj {
body (...) {
if (state == 1) {
X(q);
}
if (state == 1) {
X(q);
}
adjoint auto;
}
// ------------------------------------------------------
operation UnitaryPowerImpl_Reference (U : (Qubit => Unit : Adjoint, Controlled), power : Int, q : Qubit) : Unit {
body (...) {
for (i in 1..power) {
U(q);
}
operation UnitaryPowerImpl_Reference (U : (Qubit => Unit is Adj + Ctl), power : Int, q : Qubit) : Unit
is Adj + Ctl {
for (i in 1..power) {
U(q);
}
adjoint auto;
controlled auto;
controlled adjoint auto;
}
// Task 1.2. Inputs to QPE: powers of Z/S/T gates.
function UnitaryPower_Reference (U : (Qubit => Unit : Adjoint, Controlled), power : Int) : (Qubit => Unit : Adjoint, Controlled) {
function UnitaryPower_Reference (U : (Qubit => Unit is Adj + Ctl), power : Int) : (Qubit => Unit is Adj + Ctl) {
return UnitaryPowerImpl_Reference(U, power, _);
}
// ------------------------------------------------------
// Task 1.3. Validate inputs to QPE
operation AssertIsEigenstate_Reference (U : (Qubit => Unit), P : (Qubit => Unit : Adjoint)) : Unit {
operation AssertIsEigenstate_Reference (U : (Qubit => Unit), P : (Qubit => Unit is Adj)) : Unit {
using (q = Qubit()) {
// Prepare the state |ψ⟩
P(q);
@ -69,22 +66,17 @@ namespace Quantum.Kata.PhaseEstimation {
// ------------------------------------------------------
operation Oracle_Reference (U : (Qubit => Unit : Adjoint, Controlled), power : Int, target : Qubit[]) : Unit {
body (...) {
for (i in 1 .. power) {
U(target[0]);
}
operation Oracle_Reference (U : (Qubit => Unit is Adj + Ctl), power : Int, target : Qubit[]) : Unit
is Adj + Ctl{
for (i in 1 .. power) {
U(target[0]);
}
adjoint auto;
controlled auto;
controlled adjoint auto;
}
// Task 1.4. QPE for single-qubit unitaries
operation QPE_Reference (U : (Qubit => Unit : Adjoint, Controlled), P : (Qubit => Unit : Adjoint), n : Int) : Double {
operation QPE_Reference (U : (Qubit => Unit is Adj + Ctl), P : (Qubit => Unit is Adj), n : Int) : Double {
// Construct a phase estimation oracle from the unitary
let oracle = DiscreteOracle(Oracle_Reference(U, _, _));
mutable phase = -1.0;
// Allocate qubits to hold the eigenstate of U and the phase in a big endian register
using ((eigenstate, phaseRegister) = (Qubit[1], Qubit[n])) {
let phaseRegisterBE = BigEndian(phaseRegister);
@ -93,13 +85,12 @@ namespace Quantum.Kata.PhaseEstimation {
// Call library
QuantumPhaseEstimation(oracle, eigenstate, phaseRegisterBE);
// Read out the phase
set phase = ToDouble(MeasureIntegerBE(phaseRegisterBE)) / ToDouble(1 <<< n);
let phase = IntAsDouble(MeasureIntegerBE(phaseRegisterBE)) / IntAsDouble(1 <<< n);
ResetAll(eigenstate);
ResetAll(phaseRegister);
return phase;
}
return phase;
}
@ -108,80 +99,70 @@ namespace Quantum.Kata.PhaseEstimation {
//////////////////////////////////////////////////////////////////
// Task 2.1. Single-bit phase estimation
operation SingleBitPE_Reference (U : (Qubit => Unit : Adjoint, Controlled), P : (Qubit => Unit : Adjoint)) : Int {
mutable eigenvalue = 0;
operation SingleBitPE_Reference (U : (Qubit => Unit is Adj + Ctl), P : (Qubit => Unit is Adj)) : Int {
using ((control, eigenstate) = (Qubit(), Qubit())) {
// prepare the eigenstate |ψ⟩
P(eigenstate);
H(control);
(Controlled U)([control], eigenstate);
Controlled U([control], eigenstate);
H(control);
set eigenvalue = M(control) == Zero ? 1 | -1;
let eigenvalue = M(control) == Zero ? 1 | -1;
ResetAll([control, eigenstate]);
return eigenvalue;
}
return eigenvalue;
}
// Task 2.2. Two bit phase estimation
operation TwoBitPE_Reference (U : (Qubit => Unit : Adjoint, Controlled), P : (Qubit => Unit : Adjoint)) : Double {
operation TwoBitPE_Reference (U : (Qubit => Unit is Adj + Ctl), P : (Qubit => Unit is Adj)) : Double {
// Start by using the same circuit as in task 2.1.
// For eigenvalues +1 and -1, it produces measurement results Zero and One, respectively, 100% of the time;
// for eigenvalues +i and -i, it produces both results with 50% probability, so a different circuit is required.
mutable (nZero, nOne) = (0, 0);
using ((control, eigenstate) = (Qubit(), Qubit())) {
// prepare the eigenstate |ψ⟩
P(eigenstate);
mutable (measuredZero, measuredOne) = (false, false);
mutable iter = 0;
repeat {
set iter = iter + 1;
set iter += 1;
H(control);
(Controlled U)([control], eigenstate);
Controlled U([control], eigenstate);
H(control);
if (MResetZ(control) == Zero) {
set nZero = nZero + 1;
} else {
set nOne = nOne + 1;
}
// repeat the loop until we get both Zero and One measurement outcomes
// or until we're reasonably certain that we won't get a different outcome
} until (iter == 10 or nZero > 0 and nOne > 0)
let meas = MResetZ(control);
set (measuredZero, measuredOne) = (meas == Zero, meas == One);
}
// repeat the loop until we get both Zero and One measurement outcomes
// or until we're reasonably certain that we won't get a different outcome
until (iter == 10 or measuredZero and measuredOne)
fixup {}
Reset(eigenstate);
}
if (nOne == 0) {
// all measurements yielded Zero => eigenvalue +1
return 0.0;
}
if (nZero == 0) {
// all measurements yielded One => eigenvalue -1
return 0.5;
if (not measuredZero or not measuredOne) {
return measuredOne ? 0.5 | 0.0;
}
}
// To distinguish between eigenvalues i and -i, we need a circuit with an extra S gate on control qubit
mutable eigenvalue = -1.0;
using ((control, eigenstate) = (Qubit(), Qubit())) {
// prepare the eigenstate |ψ⟩
P(eigenstate);
H(control);
(Controlled U)([control], eigenstate);
Controlled U([control], eigenstate);
S(control);
H(control);
set eigenvalue = MResetZ(control) == Zero ? 0.75 | 0.25;
let eigenvalue = MResetZ(control) == Zero ? 0.75 | 0.25;
Reset(eigenstate);
return eigenvalue;
}
return eigenvalue;
}
}

Просмотреть файл

@ -3,12 +3,12 @@
namespace Quantum.Kata.PhaseEstimation {
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Extensions.Testing;
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Diagnostics;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
//////////////////////////////////////////////////////////////////
// Welcome!
@ -41,13 +41,9 @@ namespace Quantum.Kata.PhaseEstimation {
// Goal:
// Prepare one of the eigenstates of Z gate (which are the same as eigenstates of S or T gates):
// eigenstate |0⟩ if state = 0, or eigenstate |1⟩ if state = 1.
operation Eigenstates_ZST (q : Qubit, state : Int) : Unit {
body (...) {
// ...
}
adjoint auto;
operation Eigenstates_ZST (q : Qubit, state : Int) : Unit
is Adj {
// ...
}
@ -57,7 +53,7 @@ namespace Quantum.Kata.PhaseEstimation {
// 2) a positive integer power.
// Output:
// A single-qubit unitary equal to U raised to the given power.
function UnitaryPower (U : (Qubit => Unit : Adjoint, Controlled), power : Int) : (Qubit => Unit : Adjoint, Controlled) {
function UnitaryPower (U : (Qubit => Unit is Adj + Ctl), power : Int) : (Qubit => Unit is Adj + Ctl) {
// Hint: Remember that you can define auxiliary operations.
// ...
@ -76,7 +72,7 @@ namespace Quantum.Kata.PhaseEstimation {
// Goal:
// Assert that the given state is an eigenstate of the given unitary,
// i.e., do nothing if it is, and throw an exception if it is not.
operation AssertIsEigenstate (U : (Qubit => Unit), P : (Qubit => Unit : Adjoint)) : Unit {
operation AssertIsEigenstate (U : (Qubit => Unit), P : (Qubit => Unit is Adj)) : Unit {
// ...
}
@ -90,7 +86,7 @@ namespace Quantum.Kata.PhaseEstimation {
// Output:
// The phase of the eigenvalue that corresponds to the eigenstate |ψ⟩, with n bits of precision.
// The phase should be between 0 and 1.
operation QPE (U : (Qubit => Unit : Adjoint, Controlled), P : (Qubit => Unit : Adjoint), n : Int) : Double {
operation QPE (U : (Qubit => Unit is Adj + Ctl), P : (Qubit => Unit is Adj), n : Int) : Double {
// ...
return -1.0;
}
@ -138,7 +134,7 @@ namespace Quantum.Kata.PhaseEstimation {
// The eigenvalue which corresponds to the eigenstate |ψ⟩ (+1 or -1).
//
// You are allowed to allocate exactly two qubits and call Controlled U exactly once.
operation SingleBitPE (U : (Qubit => Unit : Adjoint, Controlled), P : (Qubit => Unit : Adjoint)) : Int {
operation SingleBitPE (U : (Qubit => Unit is Adj + Ctl), P : (Qubit => Unit is Adj)) : Int {
// Note: It is possible to use the QPE implementation from task 1.4 to solve this task,
// but we suggest you implement the circuit by hand for the sake of learning.
@ -158,7 +154,7 @@ namespace Quantum.Kata.PhaseEstimation {
// The returned value has to be accurate within the absolute error of 0.001.
//
// You are allowed to allocate exactly two qubits and call Controlled U multiple times.
operation TwoBitPE (U : (Qubit => Unit : Adjoint, Controlled), P : (Qubit => Unit : Adjoint)) : Double {
operation TwoBitPE (U : (Qubit => Unit is Adj + Ctl), P : (Qubit => Unit is Adj)) : Double {
// Hint: Start by applying the same circuit as in task 2.1.
// What are the possible outcomes for each eigenvalue?
// What eigenvalues you can and can not distinguish using this circuit?

Просмотреть файл

@ -9,18 +9,18 @@
namespace Quantum.Kata.PhaseEstimation {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Extensions.Testing;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
//////////////////////////////////////////////////////////////////
// Part I. Quantum phase estimation (QPE)
//////////////////////////////////////////////////////////////////
operation AssertEqualOnZeroState1 (testImpl : (Qubit => Unit), refImpl : (Qubit => Unit : Adjoint)) : Unit {
operation AssertEqualOnZeroState1 (testImpl : (Qubit => Unit), refImpl : (Qubit => Unit is Adj)) : Unit {
using (q = Qubit()) {
// apply operation that needs to be tested
testImpl(q);
@ -42,23 +42,17 @@ namespace Quantum.Kata.PhaseEstimation {
// ------------------------------------------------------
// helper wrapper to represent operation on one qubit as an operation on an array of qubits
operation ArrayWrapperOperation1 (op : (Qubit => Unit : Adjoint, Controlled), qs : Qubit[]) : Unit {
body (...) {
op(qs[0]);
}
adjoint auto;
controlled auto;
controlled adjoint auto;
operation ArrayWrapperOperation1 (op : (Qubit => Unit is Adj + Ctl), qs : Qubit[]) : Unit
is Adj + Ctl {
op(qs[0]);
}
operation T12_UnitaryPower_Test () : Unit {
for (U in [Z, S, T]) {
for (power in 1..5) {
AssertOperationsEqualReferenced(ArrayWrapperOperation1(UnitaryPower(U, power), _),
ArrayWrapperOperation1(UnitaryPower_Reference(U, power), _), 1);
AssertOperationsEqualReferenced(1, ArrayWrapperOperation1(UnitaryPower(U, power), _),
ArrayWrapperOperation1(UnitaryPower_Reference(U, power), _));
}
}
}
@ -78,14 +72,14 @@ namespace Quantum.Kata.PhaseEstimation {
// ------------------------------------------------------
operation T14_QPE_Test () : Unit {
AssertAlmostEqualTol(QPE(Z, I, 1), 0.0, 0.25);
AssertAlmostEqualTol(QPE(Z, X, 1), 0.5, 0.25);
EqualityWithinToleranceFact(QPE(Z, I, 1), 0.0, 0.25);
EqualityWithinToleranceFact(QPE(Z, X, 1), 0.5, 0.25);
AssertAlmostEqualTol(QPE(S, I, 2), 0.0, 0.125);
AssertAlmostEqualTol(QPE(S, X, 2), 0.25, 0.125);
EqualityWithinToleranceFact(QPE(S, I, 2), 0.0, 0.125);
EqualityWithinToleranceFact(QPE(S, X, 2), 0.25, 0.125);
AssertAlmostEqualTol(QPE(T, I, 3), 0.0, 0.0625);
AssertAlmostEqualTol(QPE(T, X, 3), 0.125, 0.0625);
EqualityWithinToleranceFact(QPE(T, I, 3), 0.0, 0.0625);
EqualityWithinToleranceFact(QPE(T, X, 3), 0.125, 0.0625);
}
@ -93,18 +87,18 @@ namespace Quantum.Kata.PhaseEstimation {
// Part II. Iterative phase estimation
//////////////////////////////////////////////////////////////////
operation Test1BitPEOnOnePair(U : (Qubit => Unit : Adjoint, Controlled), P : (Qubit => Unit : Adjoint), expected : Int) : Unit {
operation Test1BitPEOnOnePair(U : (Qubit => Unit is Adj + Ctl), P : (Qubit => Unit is Adj), expected : Int) : Unit {
ResetQubitCount();
ResetOracleCallsCount();
let actual = SingleBitPE(U, P);
AssertIntEqual(actual, expected, $"Unexpected return for ({U}, {P}): expected {expected}, got {actual}");
EqualityFactI(actual, expected, $"Unexpected return for ({U}, {P}): expected {expected}, got {actual}");
let nq = GetMaxQubitCount();
AssertIntEqual(nq, 2, $"You are allowed to allocate exactly 2 qubits, and you allocated {nq}");
EqualityFactI(nq, 2, $"You are allowed to allocate exactly 2 qubits, and you allocated {nq}");
let nu = GetOracleCallsCount(Controlled U);
AssertIntEqual(nu, 1, $"You are allowed to call Controlled U exactly once, and you called it {nu} times");
EqualityFactI(nu, 1, $"You are allowed to call Controlled U exactly once, and you called it {nu} times");
}
operation T21_SingleBitPE_Test () : Unit {
@ -116,14 +110,14 @@ namespace Quantum.Kata.PhaseEstimation {
// ------------------------------------------------------
operation Test2BitPEOnOnePair(U : (Qubit => Unit : Adjoint, Controlled), P : (Qubit => Unit : Adjoint), expected : Double) : Unit {
operation Test2BitPEOnOnePair(U : (Qubit => Unit is Adj + Ctl), P : (Qubit => Unit is Adj), expected : Double) : Unit {
ResetQubitCount();
let actual = TwoBitPE(U, P);
AssertAlmostEqualTol(actual, expected, 0.001);
EqualityWithinToleranceFact(actual, expected, 0.001);
let nq = GetMaxQubitCount();
AssertIntEqual(nq, 2, $"You are allowed to allocate exactly 2 qubits, and you allocated {nq}");
EqualityFactI(nq, 2, $"You are allowed to allocate exactly 2 qubits, and you allocated {nq}");
}
operation T22_TwoBitPE_Test () : Unit {

Просмотреть файл

@ -10,9 +10,9 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Canon" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Standard" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />

Просмотреть файл

@ -10,7 +10,8 @@
namespace Quantum.Kata.QEC_BitFlipCode {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
@ -21,13 +22,9 @@ namespace Quantum.Kata.QEC_BitFlipCode {
// Task 2. Encoding Codewords
operation Encode_Reference (register : Qubit[]) : Unit {
body (...) {
ApplyToEachA(CNOT(Head(register), _), Rest(register));
}
adjoint invert;
operation Encode_Reference (register : Qubit[]) : Unit
is Adj {
ApplyToEachA(CNOT(Head(register), _), Rest(register));
}

Просмотреть файл

@ -3,7 +3,7 @@
namespace Quantum.Kata.QEC_BitFlipCode {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;

Просмотреть файл

@ -9,12 +9,13 @@
namespace Quantum.Kata.QEC_BitFlipCode {
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Extensions.Bitwise;
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Extensions.Testing;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
open Microsoft.Quantum.Bitwise;
//////////////////////////////////////////////////////////////////////////
@ -29,23 +30,20 @@ namespace Quantum.Kata.QEC_BitFlipCode {
}
operation StatePrep_Bitmask (qs : Qubit[], bits : Int) : Unit {
operation StatePrep_Bitmask (qs : Qubit[], bits : Int) : Unit
is Adj {
body (...) {
if (bits / 4 == 1) {
X(qs[0]);
}
if ((bits / 2) % 2 == 1) {
X(qs[1]);
}
if (bits % 2 == 1) {
X(qs[2]);
}
if (bits / 4 == 1) {
X(qs[0]);
}
if ((bits / 2) % 2 == 1) {
X(qs[1]);
}
if (bits % 2 == 1) {
X(qs[2]);
}
adjoint invert;
}
@ -65,33 +63,30 @@ namespace Quantum.Kata.QEC_BitFlipCode {
}
operation StatePrep_TwoBitmasks (qs : Qubit[], bits1 : Int[], bits2 : Int[]) : Unit {
operation StatePrep_TwoBitmasks (qs : Qubit[], bits1 : Int[], bits2 : Int[]) : Unit
is Adj {
body (...) {
let firstDiff = FindFirstDiff_Reference(bits1, bits2);
H(qs[firstDiff]);
let firstDiff = FindFirstDiff_Reference(bits1, bits2);
H(qs[firstDiff]);
for (i in 0 .. Length(qs) - 1) {
if (bits1[i] == bits2[i]) {
if (bits1[i] == 1) {
for (i in 0 .. Length(qs) - 1) {
if (bits1[i] == bits2[i]) {
if (bits1[i] == 1) {
X(qs[i]);
}
} else {
if (i > firstDiff) {
CNOT(qs[firstDiff], qs[i]);
if (bits1[i] != bits1[firstDiff]) {
X(qs[i]);
}
} else {
if (i > firstDiff) {
CNOT(qs[firstDiff], qs[i]);
if (bits1[i] != bits1[firstDiff]) {
X(qs[i]);
}
}
}
}
}
adjoint invert;
}
operation TestParityOnState (statePrep : (Qubit[] => Unit : Adjoint), parity : Int, stateStr : String) : Unit {
operation TestParityOnState (statePrep : (Qubit[] => Unit is Adj), parity : Int, stateStr : String) : Unit {
using (register = Qubit[3]) {
// prepare basis state to test on
@ -99,7 +94,7 @@ namespace Quantum.Kata.QEC_BitFlipCode {
let res = MeasureParity(register);
// check that the returned parity is correct
AssertBoolEqual(res == Zero, parity == 0, $"Failed on {stateStr}.");
EqualityFactB(res == Zero, parity == 0, $"Failed on {stateStr}.");
// check that the state has not been modified
Adjoint statePrep(register);
@ -138,9 +133,9 @@ namespace Quantum.Kata.QEC_BitFlipCode {
//////////////////////////////////////////////////////////////////////////
operation AssertEqualOnZeroState (
statePrep : (Qubit[] => Unit : Adjoint),
statePrep : (Qubit[] => Unit is Adj),
testImpl : (Qubit[] => Unit),
refImpl : (Qubit[] => Unit : Adjoint)) : Unit {
refImpl : (Qubit[] => Unit is Adj)) : Unit {
using (qs = Qubit[3]) {
// prepare state
statePrep(qs);
@ -158,19 +153,15 @@ namespace Quantum.Kata.QEC_BitFlipCode {
}
operation StatePrep_Rotate (qs : Qubit[], alpha : Double) : Unit {
body (...) {
Ry(2.0 * alpha, qs[0]);
}
adjoint invert;
operation StatePrep_Rotate (qs : Qubit[], alpha : Double) : Unit
is Adj {
Ry(2.0 * alpha, qs[0]);
}
operation T02_Encode_Test () : Unit {
for (i in 0 .. 36) {
let alpha = ((2.0 * PI()) * ToDouble(i)) / 36.0;
let alpha = ((2.0 * PI()) * IntAsDouble(i)) / 36.0;
AssertEqualOnZeroState(StatePrep_Rotate(_, alpha), Encode, Encode_Reference);
}
}
@ -180,31 +171,28 @@ namespace Quantum.Kata.QEC_BitFlipCode {
// Task 03
//////////////////////////////////////////////////////////////////////////
operation StatePrep_WithError (qs : Qubit[], alpha : Double, hasError : Bool) : Unit {
operation StatePrep_WithError (qs : Qubit[], alpha : Double, hasError : Bool) : Unit
is Adj {
body (...) {
StatePrep_Rotate(qs, alpha);
Encode_Reference(qs);
StatePrep_Rotate(qs, alpha);
Encode_Reference(qs);
if (hasError) {
X(qs[0]);
}
if (hasError) {
X(qs[0]);
}
adjoint invert;
}
operation T03_DetectErrorOnLeftQubit_Test () : Unit {
using (register = Qubit[3]) {
for (i in 0 .. 36) {
let alpha = ((2.0 * PI()) * ToDouble(i)) / 36.0;
let alpha = ((2.0 * PI()) * IntAsDouble(i)) / 36.0;
StatePrep_WithError(register, alpha, false);
AssertResultEqual(DetectErrorOnLeftQubit(register), Zero, "Failed on a state without X error.");
EqualityFactR(DetectErrorOnLeftQubit(register), Zero, "Failed on a state without X error.");
Adjoint StatePrep_WithError(register, alpha, false);
AssertAllZero(register);
StatePrep_WithError(register, alpha, true);
AssertResultEqual(DetectErrorOnLeftQubit(register), One, "Failed on a state with X error.");
EqualityFactR(DetectErrorOnLeftQubit(register), One, "Failed on a state with X error.");
Adjoint StatePrep_WithError(register, alpha, true);
AssertAllZero(register);
}
@ -217,7 +205,7 @@ namespace Quantum.Kata.QEC_BitFlipCode {
//////////////////////////////////////////////////////////////////////////
operation BindErrorCorrectionRoundImpl (
encoder : (Qubit[] => Unit : Adjoint),
encoder : (Qubit[] => Unit is Adj),
error : Pauli[],
logicalOp : (Qubit[] => Unit),
correction : (Qubit[] => Unit),
@ -246,7 +234,7 @@ namespace Quantum.Kata.QEC_BitFlipCode {
function BindErrorCorrectionRound (
encoder : (Qubit[] => Unit : Adjoint),
encoder : (Qubit[] => Unit is Adj),
error : Pauli[],
logicalOp : (Qubit[] => Unit),
correction : (Qubit[] => Unit)) : (Qubit[] => Unit) {
@ -269,7 +257,7 @@ namespace Quantum.Kata.QEC_BitFlipCode {
let errors = PauliErrors();
for (idxError in 0 .. 1) {
AssertOperationsEqualReferenced(partialBind(errors[idxError]), NoOp<Qubit[]>, 1);
AssertOperationsEqualReferenced(1, partialBind(errors[idxError]), NoOp<Qubit[]>);
}
}
@ -295,7 +283,7 @@ namespace Quantum.Kata.QEC_BitFlipCode {
statePrep(Head(register));
Encode_Reference(register);
ApplyPauli(errors[idxError], register);
AssertIntEqual(DetectErrorOnAnyQubit(register), idxError, $"Failed on state with {errorStr}.");
EqualityFactI(DetectErrorOnAnyQubit(register), idxError, $"Failed on state with {errorStr}.");
ApplyPauli(errors[idxError], register);
Adjoint Encode_Reference(register);
Adjoint statePrep(Head(register));
@ -316,7 +304,7 @@ namespace Quantum.Kata.QEC_BitFlipCode {
for (idxError in 0 .. Length(errors) - 1) {
Message($"Task 06: Testing on {errors[idxError]}...");
AssertOperationsEqualReferenced(partialBind(errors[idxError]), NoOp<Qubit[]>, 1);
AssertOperationsEqualReferenced(1, partialBind(errors[idxError]), NoOp<Qubit[]>);
}
}
@ -332,7 +320,7 @@ namespace Quantum.Kata.QEC_BitFlipCode {
for (idxError in 0 .. Length(errors) - 1) {
Message($"Task 07: Testing on {errors[idxError]}...");
AssertOperationsEqualReferenced(partialBind(errors[idxError]), ApplyPauli([PauliX], _), 1);
AssertOperationsEqualReferenced(1, partialBind(errors[idxError]), ApplyPauli([PauliX], _));
}
}
@ -348,7 +336,7 @@ namespace Quantum.Kata.QEC_BitFlipCode {
for (idxError in 0 .. Length(errors) - 1) {
Message($"Task 08: Testing on {errors[idxError]}...");
AssertOperationsEqualReferenced(partialBind(errors[idxError]), ApplyToEachA(Z, _), 1);
AssertOperationsEqualReferenced(1, partialBind(errors[idxError]), ApplyToEachA(Z, _));
}
}

Просмотреть файл

@ -10,7 +10,7 @@
namespace Quantum.Kata.SimonsAlgorithm {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
@ -19,69 +19,57 @@ namespace Quantum.Kata.SimonsAlgorithm {
//////////////////////////////////////////////////////////////////
// Task 1.1. f(x) = x₀ ⊕ ... ⊕ xₙ₋₁ (parity of the number of bits set to 1)
operation Oracle_CountBits_Reference (x : Qubit[], y : Qubit) : Unit {
operation Oracle_CountBits_Reference (x : Qubit[], y : Qubit) : Unit
is Adj {
body (...) {
let N = Length(x);
let N = Length(x);
for (i in 0 .. N - 1) {
CNOT(x[i], y);
}
for (i in 0 .. N - 1) {
CNOT(x[i], y);
}
adjoint invert;
}
// Task 1.2. Bitwise right shift
operation Oracle_BitwiseRightShift_Reference (x : Qubit[], y : Qubit[]) : Unit {
operation Oracle_BitwiseRightShift_Reference (x : Qubit[], y : Qubit[]) : Unit
is Adj {
body (...) {
let N = Length(x);
let N = Length(x);
for (i in 1 .. N - 1) {
CNOT(x[i - 1], y[i]);
}
for (i in 1 .. N - 1) {
CNOT(x[i - 1], y[i]);
}
adjoint invert;
}
// Task 1.3. Linear operator
operation Oracle_OperatorOutput_Reference (x : Qubit[], y : Qubit, A : Int[]) : Unit {
operation Oracle_OperatorOutput_Reference (x : Qubit[], y : Qubit, A : Int[]) : Unit
is Adj {
body (...) {
let N = Length(x);
let N = Length(x);
for (i in 0 .. N - 1) {
if (A[i] == 1) {
CNOT(x[i], y);
}
for (i in 0 .. N - 1) {
if (A[i] == 1) {
CNOT(x[i], y);
}
}
adjoint invert;
}
// Task 1.4. Multidimensional linear operator
operation Oracle_MultidimensionalOperatorOutput_Reference (x : Qubit[], y : Qubit[], A : Int[][]) : Unit {
operation Oracle_MultidimensionalOperatorOutput_Reference (x : Qubit[], y : Qubit[], A : Int[][]) : Unit
is Adj {
body (...) {
let N1 = Length(y);
let N2 = Length(x);
let N1 = Length(y);
let N2 = Length(x);
for (i in 0 .. N1 - 1) {
for (j in 0 .. N2 - 1) {
if ((A[i])[j] == 1) {
CNOT(x[j], y[i]);
}
for (i in 0 .. N1 - 1) {
for (j in 0 .. N2 - 1) {
if ((A[i])[j] == 1) {
CNOT(x[j], y[i]);
}
}
}
adjoint invert;
}
@ -90,21 +78,15 @@ namespace Quantum.Kata.SimonsAlgorithm {
//////////////////////////////////////////////////////////////////
// Task 2.1. State preparation for Simon's algorithm
operation SA_StatePrep_Reference (query : Qubit[]) : Unit {
body (...) {
ApplyToEachA(H, query);
}
adjoint invert;
operation SA_StatePrep_Reference (query : Qubit[]) : Unit
is Adj {
ApplyToEachA(H, query);
}
// Task 2.2. Quantum part of Simon's algorithm
operation Simon_Algorithm_Reference (N : Int, Uf : ((Qubit[], Qubit[]) => Unit)) : Int[] {
mutable j = new Int[N];
// allocate input and answer registers with N qubits each
using ((x, y) = (Qubit[N], Qubit[N])) {
// prepare qubits in the right state
@ -118,18 +100,18 @@ namespace Quantum.Kata.SimonsAlgorithm {
// measure all qubits of the input register;
// the result of each measurement is converted to an Int
mutable j = new Int[N];
for (i in 0 .. N - 1) {
if (M(x[i]) == One) {
set j[i] = 1;
set j w/= i <- 1;
}
}
// before releasing the qubits make sure they are all in |0⟩ states
ResetAll(x);
ResetAll(y);
return j;
}
return j;
}
}

Просмотреть файл

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
@ -7,9 +7,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Canon" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Standard" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />

Просмотреть файл

@ -3,7 +3,8 @@
namespace Quantum.Kata.SimonsAlgorithm {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
@ -29,13 +30,9 @@ namespace Quantum.Kata.SimonsAlgorithm {
// 1) N qubits in an arbitrary state |x⟩
// 2) a qubit in an arbitrary state |y⟩
// Goal: Transform state |x, y⟩ into |x, y ⊕ x_0 ⊕ x_1 ... ⊕ x_{n-1}⟩ (⊕ is addition modulo 2).
operation Oracle_CountBits (x : Qubit[], y : Qubit) : Unit {
body (...) {
// ...
}
adjoint invert;
operation Oracle_CountBits (x : Qubit[], y : Qubit) : Unit
is Adj {
// ...
}
@ -45,13 +42,9 @@ namespace Quantum.Kata.SimonsAlgorithm {
// 2) N qubits in an arbitrary state |y⟩
// Goal: Transform state |x, y⟩ into |x, y ⊕ f(x)⟩, where f is bitwise right shift function, i.e.,
// |y ⊕ f(x)⟩ = |y_0, y_1 ⊕ x_0, y_2 ⊕ x_1, ..., y_{n-1} ⊕ x_{n-2}⟩ (⊕ is addition modulo 2).
operation Oracle_BitwiseRightShift (x : Qubit[], y : Qubit[]) : Unit {
body (...) {
// ...
}
adjoint invert;
operation Oracle_BitwiseRightShift (x : Qubit[], y : Qubit[]) : Unit
is Adj {
// ...
}
@ -62,17 +55,14 @@ namespace Quantum.Kata.SimonsAlgorithm {
// 3) a 1xN binary matrix (represented as an Int[]) describing operator A
// (see https://en.wikipedia.org/wiki/Transformation_matrix )
// Goal: Transform state |x, y⟩ into |x, y ⊕ A(x) ⟩ (⊕ is addition modulo 2).
operation Oracle_OperatorOutput (x : Qubit[], y : Qubit, A : Int[]) : Unit {
operation Oracle_OperatorOutput (x : Qubit[], y : Qubit, A : Int[]) : Unit
is Adj {
body (...) {
// The following line enforces the constraint on the input arrays.
// You don't need to modify it. Feel free to remove it, this won't cause your code to fail.
AssertIntEqual(Length(x), Length(A), "Arrays x and A should have the same length");
// The following line enforces the constraint on the input arrays.
// You don't need to modify it. Feel free to remove it, this won't cause your code to fail.
EqualityFactI(Length(x), Length(A), "Arrays x and A should have the same length");
// ...
}
adjoint invert;
// ...
}
@ -86,18 +76,15 @@ namespace Quantum.Kata.SimonsAlgorithm {
// the second dimension (columns) - the input register,
// i.e., A[r][c] (element in r-th row and c-th column) corresponds to x[c] and y[r].
// Goal: Transform state |x, y⟩ into |x, y ⊕ A(x) ⟩ (⊕ is addition modulo 2).
operation Oracle_MultidimensionalOperatorOutput (x : Qubit[], y : Qubit[], A : Int[][]) : Unit {
operation Oracle_MultidimensionalOperatorOutput (x : Qubit[], y : Qubit[], A : Int[][]) : Unit
is Adj {
body (...) {
// The following lines enforce the constraints on the input arrays.
// You don't need to modify it. Feel free to remove it, this won't cause your code to fail.
AssertIntEqual(Length(x), Length(A[0]), "Arrays x and A[0] should have the same length");
AssertIntEqual(Length(y), Length(A), "Arrays y and A should have the same length");
// The following lines enforce the constraints on the input arrays.
// You don't need to modify them. Feel free to remove them, this won't cause your code to fail.
EqualityFactI(Length(x), Length(A[0]), "Arrays x and A[0] should have the same length");
EqualityFactI(Length(y), Length(A), "Arrays y and A should have the same length");
// ...
}
adjoint invert;
// ...
}
@ -110,13 +97,9 @@ namespace Quantum.Kata.SimonsAlgorithm {
// 1) N qubits in |0⟩ state (query register)
// Goal: create an equal superposition of all basis vectors from |0...0⟩ to |1...1⟩ on query register
// (i.e. the state (|0...0⟩ + ... + |1...1⟩) / sqrt(2^N)).
operation SA_StatePrep (query : Qubit[]) : Unit {
body (...) {
// ...
}
adjoint invert;
operation SA_StatePrep (query : Qubit[]) : Unit
is Adj {
// ...
}
@ -143,7 +126,7 @@ namespace Quantum.Kata.SimonsAlgorithm {
operation Simon_Algorithm (N : Int, Uf : ((Qubit[], Qubit[]) => Unit)) : Int[] {
// Declare an Int array in which the result will be stored;
// the array has to be mutable to allow updating its elements.
// the variable has to be mutable to allow updating it.
mutable b = new Int[N];
// ...

Просмотреть файл

@ -46,20 +46,18 @@ namespace Q22
public BooleanVector Kernel => new BooleanVector(kernel);
public QArray<QArray<long>> Transformation => new QArray<QArray<long>>(
public IQArray<IQArray<long>> Transformation => new QArray<IQArray<long>>(
transformation.Select(
vector => new QArray<long>(vector)));
public QArray<QArray<long>> ExtendedTransformation
public IQArray<IQArray<long>> ExtendedTransformation
{
get
{
var array = new QArray<QArray<long>>(
transformation.Select(
vector => new QArray<long>(vector)))
{
new QArray<long>(transformation.Last())
};
var array = (IQArray<IQArray<long>>)new QArray<IQArray<long>>(
transformation.Select(vector => new QArray<long>(vector))
);
array = QArray<IQArray<long>>.Add (array, new QArray<IQArray<long>>(new QArray<long>(transformation.Last())));
return array;
}
}
@ -114,7 +112,7 @@ namespace Q22
var sim = new OracleCounterSimulator();
var len = instance.Kernel.Count;
var saver = new List<QArray<long>>();
var saver = new List<IQArray<long>>();
for (int i = 0; i < len * 4; ++i)
{

Просмотреть файл

@ -9,44 +9,36 @@
namespace Quantum.Kata.SimonsAlgorithm {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Testing;
open Microsoft.Quantum.Diagnostics;
// ------------------------------------------------------
operation ApplyOracleA (qs : Qubit[], oracle : ((Qubit[], Qubit) => Unit : Adjoint)) : Unit {
body (...) {
let N = Length(qs);
oracle(qs[0 .. N - 2], qs[N - 1]);
}
adjoint invert;
operation ApplyOracleA (qs : Qubit[], oracle : ((Qubit[], Qubit) => Unit is Adj)) : Unit
is Adj {
let N = Length(qs);
oracle(qs[0 .. N - 2], qs[N - 1]);
}
operation ApplyOracleWithOutputArrA (qs : Qubit[], oracle : ((Qubit[], Qubit[]) => Unit : Adjoint), outputSize : Int) : Unit {
body (...) {
let N = Length(qs);
oracle(qs[0 .. (N - 1) - outputSize], qs[N - outputSize .. N - 1]);
}
adjoint invert;
operation ApplyOracleWithOutputArrA (qs : Qubit[], oracle : ((Qubit[], Qubit[]) => Unit is Adj), outputSize : Int) : Unit
is Adj {
let N = Length(qs);
oracle(qs[0 .. (N - 1) - outputSize], qs[N - outputSize .. N - 1]);
}
// ------------------------------------------------------
operation AssertTwoOraclesAreEqual (
nQubits : Range,
oracle1 : ((Qubit[], Qubit) => Unit : Adjoint),
oracle2 : ((Qubit[], Qubit) => Unit : Adjoint)) : Unit {
oracle1 : ((Qubit[], Qubit) => Unit is Adj),
oracle2 : ((Qubit[], Qubit) => Unit is Adj)) : Unit {
let sol = ApplyOracleA(_, oracle1);
let refSol = ApplyOracleA(_, oracle2);
for (i in nQubits) {
AssertOperationsEqualReferenced(sol, refSol, i + 1);
AssertOperationsEqualReferenced(i+1, sol, refSol);
}
}
@ -54,11 +46,11 @@ namespace Quantum.Kata.SimonsAlgorithm {
operation AssertTwoOraclesWithOutputArrAreEqual (
inputSize : Int,
outputSize : Int,
oracle1 : ((Qubit[], Qubit[]) => Unit : Adjoint),
oracle2 : ((Qubit[], Qubit[]) => Unit : Adjoint)) : Unit {
oracle1 : ((Qubit[], Qubit[]) => Unit is Adj),
oracle2 : ((Qubit[], Qubit[]) => Unit is Adj)) : Unit {
let sol = ApplyOracleWithOutputArrA(_, oracle1, outputSize);
let refSol = ApplyOracleWithOutputArrA(_, oracle2, outputSize);
AssertOperationsEqualReferenced(sol, refSol, inputSize + outputSize);
AssertOperationsEqualReferenced(inputSize + outputSize, sol, refSol);
}
@ -77,7 +69,7 @@ namespace Quantum.Kata.SimonsAlgorithm {
// ------------------------------------------------------
operation AssertTwoOraclesWithIntArrAreEqual (A : Int[], oracle1 : ((Qubit[], Qubit, Int[]) => Unit : Adjoint), oracle2 : ((Qubit[], Qubit, Int[]) => Unit : Adjoint)) : Unit {
operation AssertTwoOraclesWithIntArrAreEqual (A : Int[], oracle1 : ((Qubit[], Qubit, Int[]) => Unit is Adj), oracle2 : ((Qubit[], Qubit, Int[]) => Unit is Adj)) : Unit {
AssertTwoOraclesAreEqual(Length(A) .. Length(A), oracle1(_, _, A), oracle2(_, _, A));
}
@ -109,8 +101,8 @@ namespace Quantum.Kata.SimonsAlgorithm {
// ------------------------------------------------------
operation AssertTwoOraclesWithIntMatrixAreEqual (
A : Int[][],
oracle1 : ((Qubit[], Qubit[], Int[][]) => Unit : Adjoint),
oracle2 : ((Qubit[], Qubit[], Int[][]) => Unit : Adjoint)) : Unit {
oracle1 : ((Qubit[], Qubit[], Int[][]) => Unit is Adj),
oracle2 : ((Qubit[], Qubit[], Int[][]) => Unit is Adj)) : Unit {
let inputSize = Length(A[0]);
let outputSize = Length(A);
AssertTwoOraclesWithOutputArrAreEqual(inputSize, outputSize, oracle1(_, _, A), oracle2(_, _, A));
@ -119,11 +111,11 @@ namespace Quantum.Kata.SimonsAlgorithm {
operation AssertTwoOraclesWithDifferentOutputsAreEqual (
inputSize : Int,
oracle1 : ((Qubit[], Qubit[]) => Unit : Adjoint),
oracle2 : ((Qubit[], Qubit) => Unit : Adjoint)) : Unit {
oracle1 : ((Qubit[], Qubit[]) => Unit is Adj),
oracle2 : ((Qubit[], Qubit) => Unit is Adj)) : Unit {
let sol = ApplyOracleWithOutputArrA(_, oracle1, 1);
let refSol = ApplyOracleA(_, oracle2);
AssertOperationsEqualReferenced(sol, refSol, inputSize + 1);
AssertOperationsEqualReferenced(inputSize + 1, sol, refSol);
}

Просмотреть файл

@ -114,7 +114,7 @@ namespace Quantum.Kata.GroversAlgorithm
return base.Apply();
}
public override QArray<Qubit> Apply(long count)
public override IQArray<Qubit> Apply(long count)
{
_sim._qubitsAllocated += count;
if (_sim._qubitsAllocated > _sim._maxQubitsAllocated)
@ -140,7 +140,7 @@ namespace Quantum.Kata.GroversAlgorithm
base.Apply(q);
}
public override void Apply(QArray<Qubit> qubits)
public override void Apply(IQArray<Qubit> qubits)
{
_sim._qubitsAllocated -= qubits.Length;
base.Apply(qubits);

Просмотреть файл

@ -10,10 +10,12 @@
namespace Quantum.Kata.GroversAlgorithm {
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Measurement;
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
//////////////////////////////////////////////////////////////////
@ -21,160 +23,123 @@ namespace Quantum.Kata.GroversAlgorithm {
//////////////////////////////////////////////////////////////////
// Task 1.1. The AND oracle: f(x) = x₀ ∧ x₁
operation Oracle_And_Reference_2 (queryRegister : Qubit[], target : Qubit) : Unit {
body (...) {
CCNOT(queryRegister[0], queryRegister[1], target);
}
adjoint auto;
operation Oracle_And_Reference_2 (queryRegister : Qubit[], target : Qubit) : Unit
is Adj {
CCNOT(queryRegister[0], queryRegister[1], target);
}
// AND oracle for an arbitrary number of qubits in query register
operation Oracle_And_Reference (queryRegister : Qubit[], target : Qubit) : Unit {
body (...) {
Controlled X(queryRegister, target);
}
adjoint auto;
operation Oracle_And_Reference (queryRegister : Qubit[], target : Qubit) : Unit
is Adj {
Controlled X(queryRegister, target);
}
// ------------------------------------------------------
// Task 1.2. The OR oracle: f(x) = x₀ x₁
operation Oracle_Or_Reference_2 (queryRegister : Qubit[], target : Qubit) : Unit {
body (...) {
// x₀ x₁ = ¬ (¬x₀ ∧ ¬x₁)
// First, flip target if both qubits are in |0⟩ state
X(queryRegister[0]);
X(queryRegister[1]);
CCNOT(queryRegister[0], queryRegister[1], target);
// Return query register to the starting state
X(queryRegister[0]);
X(queryRegister[1]);
// Then flip target again to get negation
X(target);
}
adjoint auto;
operation Oracle_Or_Reference_2 (queryRegister : Qubit[], target : Qubit) : Unit
is Adj {
// x₀ x₁ = ¬ (¬x₀ ∧ ¬x₁)
// First, flip target if both qubits are in |0⟩ state
X(queryRegister[0]);
X(queryRegister[1]);
CCNOT(queryRegister[0], queryRegister[1], target);
// Return query register to the starting state
X(queryRegister[0]);
X(queryRegister[1]);
// Then flip target again to get negation
X(target);
}
// OR oracle for an arbitrary number of qubits in query register
operation Oracle_Or_Reference (queryRegister : Qubit[], target : Qubit) : Unit {
body (...) {
// x₀ x₁ = ¬ (¬x₀ ∧ ¬x₁)
// First, flip target if both qubits are in |0⟩ state
(ControlledOnInt(0, X))(queryRegister, target);
// Then flip target again to get negation
X(target);
}
adjoint auto;
operation Oracle_Or_Reference (queryRegister : Qubit[], target : Qubit) : Unit
is Adj {
// x₀ x₁ = ¬ (¬x₀ ∧ ¬x₁)
// First, flip target if both qubits are in |0⟩ state
(ControlledOnInt(0, X))(queryRegister, target);
// Then flip target again to get negation
X(target);
}
// ------------------------------------------------------
// Task 1.3. The XOR oracle: f(x) = x₀ ⊕ x₁
operation Oracle_Xor_Reference_2 (queryRegister : Qubit[], target : Qubit) : Unit {
body (...) {
CNOT(queryRegister[0], target);
CNOT(queryRegister[1], target);
}
adjoint auto;
operation Oracle_Xor_Reference_2 (queryRegister : Qubit[], target : Qubit) : Unit
is Adj {
CNOT(queryRegister[0], target);
CNOT(queryRegister[1], target);
}
// XOR oracle for an arbitrary number of qubits in query register
operation Oracle_Xor_Reference (queryRegister : Qubit[], target : Qubit) : Unit {
body (...) {
ApplyToEachA(CNOT(_, target), queryRegister);
}
adjoint auto;
operation Oracle_Xor_Reference (queryRegister : Qubit[], target : Qubit) : Unit
is Adj {
ApplyToEachA(CNOT(_, target), queryRegister);
}
// Alternative solution to task 1.3, based on representation as a 2-SAT problem
operation Oracle_Xor_2SAT (queryRegister : Qubit[], target : Qubit) : Unit {
body (...) {
// x₀ ⊕ x₁ = (x₀ x₁) ∧ (¬x₀ ¬x₁)
// Allocate 2 ancilla qubits to store results of clause evaluation
using ((a1, a2) = (Qubit(), Qubit())) {
// The first clause is exactly the Or oracle
Oracle_Or_Reference(queryRegister, a1);
// The second clause is the Or oracle, applied to negations of the variables
WithA(ApplyToEachA(X, _), Oracle_Or_Reference(_, a2), queryRegister);
// To calculate the final answer, apply the And oracle with the ancilla qubits as inputs
Oracle_And_Reference([a1, a2], target);
// Uncompute the values of the ancillas before releasing them (no measuring!)
Adjoint WithA(ApplyToEachA(X, _), Oracle_Or_Reference(_, a2), queryRegister);
Adjoint Oracle_Or_Reference(queryRegister, a1);
}
operation Oracle_Xor_2SAT (queryRegister : Qubit[], target : Qubit) : Unit
is Adj {
// x₀ ⊕ x₁ = (x₀ x₁) ∧ (¬x₀ ¬x₁)
// Allocate 2 auxillary qubits to store results of clause evaluation
using ((a1, a2) = (Qubit(), Qubit())) {
// The first clause is exactly the Or oracle
Oracle_Or_Reference(queryRegister, a1);
// The second clause is the Or oracle, applied to negations of the variables
WithA(ApplyToEachA(X, _), Oracle_Or_Reference(_, a2), queryRegister);
// To calculate the final answer, apply the And oracle with the ancilla qubits as inputs
Oracle_And_Reference([a1, a2], target);
// Uncompute the values of the ancillas before releasing them (no measuring!)
Adjoint WithA(ApplyToEachA(X, _), Oracle_Or_Reference(_, a2), queryRegister);
Adjoint Oracle_Or_Reference(queryRegister, a1);
}
adjoint auto;
}
// ------------------------------------------------------
// Task 1.4. Alternating bits oracle: f(x) = (x₀ ⊕ x₁) ∧ (x₁ ⊕ x₂) ∧ ... ∧ (xₙ₋₂ ⊕ xₙ₋₁)
operation Oracle_AlternatingBits_Reference (queryRegister : Qubit[], target : Qubit) : Unit {
operation Oracle_AlternatingBits_Reference (queryRegister : Qubit[], target : Qubit) : Unit
is Adj {
body (...) {
// Allocate N-1 qubits to store results of clauses evaluation
let N = Length(queryRegister);
using (anc = Qubit[N-1]) {
// Evaluate all XOR clauses (using XOR oracle)
for (i in 0..N-2) {
Oracle_Xor_Reference(queryRegister[i..i+1], anc[i]);
}
// Allocate N-1 qubits to store results of clauses evaluation
let N = Length(queryRegister);
using (anc = Qubit[N-1]) {
// Evaluate all XOR clauses (using XOR oracle)
for (i in 0..N-2) {
Oracle_Xor_Reference(queryRegister[i..i+1], anc[i]);
}
// Evaluate the overall formula as an AND oracle (can use reference depending on the implementation)
Controlled X(anc, target);
// Evaluate the overall formula as an AND oracle (can use reference depending on the implementation)
Controlled X(anc, target);
// Uncompute
for (i in 0..N-2) {
Adjoint Oracle_Xor_Reference(queryRegister[i..i+1], anc[i]);
}
// Uncompute
for (i in 0..N-2) {
Adjoint Oracle_Xor_Reference(queryRegister[i..i+1], anc[i]);
}
}
adjoint auto;
}
// Answer-based solution for alternating bits oracle
operation FlipAlternatingPositionBits_Reference (register : Qubit[], firstIndex : Int) : Unit {
operation FlipAlternatingPositionBits_Reference (register : Qubit[], firstIndex : Int) : Unit
is Adj {
body (...) {
// iterate over elements in every second position, starting with firstIndex (indexes are 0-based)
for (i in firstIndex .. 2 .. Length(register) - 1) {
X(register[i]);
}
// iterate over elements in every second position, starting with firstIndex (indexes are 0-based)
for (i in firstIndex .. 2 .. Length(register) - 1) {
X(register[i]);
}
adjoint auto;
}
operation Oracle_AlternatingBits_Answer (queryRegister : Qubit[], target : Qubit) : Unit {
operation Oracle_AlternatingBits_Answer (queryRegister : Qubit[], target : Qubit) : Unit
is Adj {
body (...) {
// similar to task 1.2 from GroversAlgorithm kata:
// first mark the state with 1s in even positions (starting with the first qubit, index 0),
// then mark the state with 1s in odd positions
for (firstIndex in 0..1) {
FlipAlternatingPositionBits_Reference(queryRegister, firstIndex);
Controlled X(queryRegister, target);
Adjoint FlipAlternatingPositionBits_Reference(queryRegister, firstIndex);
}
// similar to task 1.2 from GroversAlgorithm kata:
// first mark the state with 1s in even positions (starting with the first qubit, index 0),
// then mark the state with 1s in odd positions
for (firstIndex in 0..1) {
FlipAlternatingPositionBits_Reference(queryRegister, firstIndex);
Controlled X(queryRegister, target);
Adjoint FlipAlternatingPositionBits_Reference(queryRegister, firstIndex);
}
adjoint auto;
}
// ------------------------------------------------------
@ -191,9 +156,9 @@ namespace Quantum.Kata.GroversAlgorithm {
let (index, isTrue) = clause[varIndex];
// Add the variable used in the clause to the list of variables which we'll need to call the OR oracle
let qt = queryRegister[index];
set qubits[varIndex] = queryRegister[index];
set qubits w/= varIndex <- queryRegister[index];
// If the negation of the variable is present in the formula, mark the qubit as needing a flip
set flip[varIndex] = not isTrue;
set flip w/= varIndex <- not isTrue;
}
// Actually calculate the clause (flip the necessary qubits, call OR oracle, flip them back)
@ -207,14 +172,10 @@ namespace Quantum.Kata.GroversAlgorithm {
// Task 1.5. 2-SAT problem oracle: f(x) = ∧ᵢ (yᵢ₀ yᵢ₁), yᵢₖ = either xᵢₖ or ¬xᵢₖ
operation Oracle_2SAT_Reference (queryRegister : Qubit[],
target : Qubit,
problem : (Int, Bool)[][]) : Unit {
body (...) {
problem : (Int, Bool)[][]) : Unit
is Adj {
// This is exactly the upcoming task 1.6, so using the general SAT oracle
Oracle_SAT_Reference(queryRegister, target, problem);
}
adjoint auto;
}
@ -222,18 +183,15 @@ namespace Quantum.Kata.GroversAlgorithm {
// Task 1.6. General SAT problem oracle: f(x) = ∧ᵢ (∨ₖ yᵢₖ), yᵢₖ = either xᵢₖ or ¬xᵢₖ
operation Oracle_SAT_Reference (queryRegister : Qubit[],
target : Qubit,
problem : (Int, Bool)[][]) : Unit {
problem : (Int, Bool)[][]) : Unit
is Adj {
body (...) {
// Similar to task 1.4.
// Allocate qubits to store results of clauses evaluation
using (anc = Qubit[Length(problem)]) {
// Compute clauses, evaluate the overall formula as an AND oracle (can use reference depending on the implementation) and uncompute
WithA(EvaluateOrClauses(queryRegister, _, problem), Controlled X(_, target), anc);
}
// Similar to task 1.4.
// Allocate qubits to store results of clauses evaluation
using (anc = Qubit[Length(problem)]) {
// Compute clauses, evaluate the overall formula as an AND oracle (can use reference depending on the implementation) and uncompute
WithA(EvaluateOrClauses(queryRegister, _, problem), Controlled X(_, target), anc);
}
adjoint auto;
}
@ -241,30 +199,29 @@ namespace Quantum.Kata.GroversAlgorithm {
// Part II. Using Grover's algorithm for problems with multiple solutions
//////////////////////////////////////////////////////////////////
operation OracleConverterImpl_Reference (markingOracle : ((Qubit[], Qubit) => Unit : Adjoint), register : Qubit[]) : Unit {
body (...) {
using (target = Qubit()) {
// Put the target into the |-⟩ state
X(target);
H(target);
operation OracleConverterImpl_Reference (markingOracle : ((Qubit[], Qubit) => Unit is Adj), register : Qubit[]) : Unit
is Adj {
using (target = Qubit()) {
// Put the target into the |-⟩ state
X(target);
H(target);
// Apply the marking oracle; since the target is in the |-⟩ state,
// flipping the target if the register satisfies the oracle condition will apply a -1 factor to the state
markingOracle(register, target);
// Apply the marking oracle; since the target is in the |-⟩ state,
// flipping the target if the register satisfies the oracle condition will apply a -1 factor to the state
markingOracle(register, target);
// Put the target back into |0⟩ so we can return it
H(target);
X(target);
}
// Put the target back into |0⟩ so we can return it
H(target);
X(target);
}
adjoint invert;
}
function OracleConverter_Reference (markingOracle : ((Qubit[], Qubit) => Unit : Adjoint)) : (Qubit[] => Unit : Adjoint) {
function OracleConverter_Reference (markingOracle : ((Qubit[], Qubit) => Unit is Adj)) : (Qubit[] => Unit is Adj) {
return OracleConverterImpl_Reference(markingOracle, _);
}
operation GroversAlgorithm_Loop (register : Qubit[], oracle : ((Qubit[], Qubit) => Unit : Adjoint), iterations : Int) : Unit {
operation GroversAlgorithm_Loop (register : Qubit[], oracle : ((Qubit[], Qubit) => Unit is Adj), iterations : Int) : Unit {
let phaseOracle = OracleConverter_Reference(oracle);
ApplyToEach(H, register);
@ -280,7 +237,7 @@ namespace Quantum.Kata.GroversAlgorithm {
// Task 2.2. Universal implementation of Grover's algorithm
operation GroversAlgorithm_Reference (N : Int, oracle : ((Qubit[], Qubit) => Unit : Adjoint)) : Bool[] {
operation GroversAlgorithm_Reference (N : Int, oracle : ((Qubit[], Qubit) => Unit is Adj)) : Bool[] {
// In this task you don't know the optimal number of iterations upfront,
// so it makes sense to try different numbers of iterations.
// This way, even if you don't hit the "correct" number of iterations on one of your tries,
@ -305,7 +262,7 @@ namespace Quantum.Kata.GroversAlgorithm {
ResetAll(register);
} until (correct or iter > 100) // the fail-safe to avoid going into an infinite loop
fixup {
set iter = iter * 2;
set iter *= 2;
}
if (not correct) {
fail "Failed to find an answer";

Просмотреть файл

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
@ -7,9 +7,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Canon" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Standard" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />

Просмотреть файл

@ -3,10 +3,11 @@
namespace Quantum.Kata.GroversAlgorithm {
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
//////////////////////////////////////////////////////////////////
@ -47,13 +48,9 @@ namespace Quantum.Kata.GroversAlgorithm {
// Leave the query register in the same state it started in.
// Stretch goal: Can you implement the oracle so that it would work
// for queryRegister containing an arbitrary number of qubits?
operation Oracle_And (queryRegister : Qubit[], target : Qubit) : Unit {
body (...) {
// ...
}
adjoint auto;
operation Oracle_And (queryRegister : Qubit[], target : Qubit) : Unit
is Adj {
// ...
}
@ -67,13 +64,9 @@ namespace Quantum.Kata.GroversAlgorithm {
// Leave the query register in the same state it started in.
// Stretch goal: Can you implement the oracle so that it would work
// for queryRegister containing an arbitrary number of qubits?
operation Oracle_Or (queryRegister : Qubit[], target : Qubit) : Unit {
body (...) {
// ...
}
adjoint auto;
operation Oracle_Or (queryRegister : Qubit[], target : Qubit) : Unit
is Adj {
// ...
}
@ -87,13 +80,9 @@ namespace Quantum.Kata.GroversAlgorithm {
// Leave the query register in the same state it started in.
// Stretch goal: Can you implement the oracle so that it would work
// for queryRegister containing an arbitrary number of qubits?
operation Oracle_Xor (queryRegister : Qubit[], target : Qubit) : Unit {
body (...) {
// ...
}
adjoint auto;
operation Oracle_Xor (queryRegister : Qubit[], target : Qubit) : Unit
is Adj {
// ...
}
@ -108,13 +97,9 @@ namespace Quantum.Kata.GroversAlgorithm {
// |10101...⟩ and |01010...⟩
// It is possible (and quite straightforward) to implement this oracle based on this observation;
// however, for the purposes of learning to write oracles to solve SAT problems we recommend using the representation above.
operation Oracle_AlternatingBits (queryRegister : Qubit[], target : Qubit) : Unit {
body (...) {
// ...
}
adjoint auto;
operation Oracle_AlternatingBits (queryRegister : Qubit[], target : Qubit) : Unit
is Adj {
// ...
}
@ -149,13 +134,9 @@ namespace Quantum.Kata.GroversAlgorithm {
// Leave the query register in the same state it started in.
operation Oracle_2SAT (queryRegister : Qubit[],
target : Qubit,
problem : (Int, Bool)[][]) : Unit {
body (...) {
problem : (Int, Bool)[][]) : Unit
is Adj {
// ...
}
adjoint auto;
}
@ -183,13 +164,9 @@ namespace Quantum.Kata.GroversAlgorithm {
// Leave the query register in the same state it started in.
operation Oracle_SAT (queryRegister : Qubit[],
target : Qubit,
problem : (Int, Bool)[][]) : Unit {
body (...) {
// ...
}
adjoint auto;
problem : (Int, Bool)[][]) : Unit
is Adj {
// ...
}
@ -227,7 +204,7 @@ namespace Quantum.Kata.GroversAlgorithm {
// in a way that would be robust to accidental failures, but you knew the optimal number of iterations
// (the number that minimizes the probability of such failure).
// In this task you also need to make your implementation robust to not knowing the optimal number of iterations.
operation GroversAlgorithm (N : Int, oracle : ((Qubit[], Qubit) => Unit : Adjoint)) : Bool[] {
operation GroversAlgorithm (N : Int, oracle : ((Qubit[], Qubit) => Unit is Adj)) : Bool[] {
// ...
return new Bool[N];
}

Просмотреть файл

@ -9,30 +9,27 @@
namespace Quantum.Kata.GroversAlgorithm {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Extensions.Testing;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
// ------------------------------------------------------
// helper wrapper to represent oracle operation on input and output registers as an operation on an array of qubits
operation QubitArrayWrapperOperation (op : ((Qubit[], Qubit) => Unit : Adjoint), qs : Qubit[]) : Unit {
body (...) {
op(Most(qs), Tail(qs));
}
adjoint invert;
operation QubitArrayWrapperOperation (op : ((Qubit[], Qubit) => Unit is Adj), qs : Qubit[]) : Unit
is Adj {
op(Most(qs), Tail(qs));
}
// ------------------------------------------------------
// helper wrapper to test for operation equality on various register sizes
operation AssertRegisterOperationsEqual (testOp : (Qubit[] => Unit), refOp : (Qubit[] => Unit : Adjoint)) : Unit {
operation AssertRegisterOperationsEqual (testOp : (Qubit[] => Unit), refOp : (Qubit[] => Unit is Adj)) : Unit {
for (n in 2 .. 10) {
AssertOperationsEqualReferenced(testOp, refOp, n);
AssertOperationsEqualReferenced(n, testOp, refOp);
}
}
@ -77,7 +74,7 @@ namespace Quantum.Kata.GroversAlgorithm {
let testOp = QubitArrayWrapperOperation(Oracle_And, _);
let refOp = QubitArrayWrapperOperation(Oracle_And_Reference, _);
AssertOperationsEqualReferenced(testOp, refOp, 3);
AssertOperationsEqualReferenced(3, testOp, refOp);
}
@ -91,7 +88,7 @@ namespace Quantum.Kata.GroversAlgorithm {
let testOp = QubitArrayWrapperOperation(Oracle_Or, _);
let refOp = QubitArrayWrapperOperation(Oracle_Or_Reference, _);
AssertOperationsEqualReferenced(testOp, refOp, 3);
AssertOperationsEqualReferenced(3, testOp, refOp);
}
@ -105,7 +102,7 @@ namespace Quantum.Kata.GroversAlgorithm {
let testOp = QubitArrayWrapperOperation(Oracle_Xor, _);
let refOp = QubitArrayWrapperOperation(Oracle_Xor_Reference, _);
AssertOperationsEqualReferenced(testOp, refOp, 3);
AssertOperationsEqualReferenced(3, testOp, refOp);
}
@ -126,7 +123,7 @@ namespace Quantum.Kata.GroversAlgorithm {
for (n in 2 .. 5) {
AssertOracleImplementsFunction(n, Oracle_AlternatingBits, AlternatingBits);
AssertOperationsEqualReferenced(testOp, refOp, n + 1);
AssertOperationsEqualReferenced(n + 1, testOp, refOp);
}
}
@ -153,12 +150,14 @@ namespace Quantum.Kata.GroversAlgorithm {
let nVar = RandomInt(5) + 3;
let nClause = RandomInt(2 * nVar) + 1;
mutable problem = new (Int, Bool)[][nClause];
for (j in 0..nClause-1) {
mutable nVarInClause = is2SAT ? 2 | (RandomInt(4) + 1);
if (nVarInClause > nVar) {
set nVarInClause = nVar;
}
set problem[j] = new (Int, Bool)[nVarInClause];
mutable problemRow = new (Int, Bool)[nVarInClause];
mutable usedVariables = new Bool[nVar];
// Make sure variables in each clause are distinct
for (k in 0..nVarInClause-1) {
@ -167,32 +166,30 @@ namespace Quantum.Kata.GroversAlgorithm {
set nextInd = RandomInt(nVar);
} until (not usedVariables[nextInd])
fixup {}
set problem[j][k] = (nextInd, RandomInt(2) > 0);
set usedVariables[nextInd] = true;
set problemRow w/= k <- (nextInd, RandomInt(2) > 0);
set usedVariables w/= nextInd <- true;
}
set problem w/= j <- problemRow;
}
return (nVar, problem);
}
operation Run2SATTests (oracle : ((Qubit[], Qubit, (Int, Bool)[][]) => Unit : Adjoint)) : Unit {
operation Run2SATTests (oracle : ((Qubit[], Qubit, (Int, Bool)[][]) => Unit is Adj)) : Unit {
// Cross-tests:
// OR oracle
AssertOperationsEqualReferenced(
AssertOperationsEqualReferenced(3,
QubitArrayWrapperOperation(oracle(_, _, [[(0, true), (1, true)]]), _),
QubitArrayWrapperOperation(Oracle_Or_Reference, _),
3);
QubitArrayWrapperOperation(Oracle_Or_Reference, _));
// XOR oracle
AssertOperationsEqualReferenced(
AssertOperationsEqualReferenced(3,
QubitArrayWrapperOperation(oracle(_, _, [[(0, true), (1, true)], [(1, false), (0, false)]]), _),
QubitArrayWrapperOperation(Oracle_Xor_Reference, _),
3);
QubitArrayWrapperOperation(Oracle_Xor_Reference, _));
// AlternatingBits oracle for 3 qubits
AssertOperationsEqualReferenced(
AssertOperationsEqualReferenced(4,
QubitArrayWrapperOperation(oracle(_, _, [[(1, false), (2, false)], [(0, true), (1, true)], [(1, false), (0, false)], [(2, true), (1, true)]]), _),
QubitArrayWrapperOperation(Oracle_AlternatingBits_Reference, _),
4);
QubitArrayWrapperOperation(Oracle_AlternatingBits_Reference, _));
// Standalone tests
for (i in 1..10) {
@ -201,10 +198,9 @@ namespace Quantum.Kata.GroversAlgorithm {
AssertOracleImplementsFunction(nVar, oracle(_, _, problem), F_SAT(_, problem));
AssertOperationsEqualReferenced(
AssertOperationsEqualReferenced(nVar + 1,
QubitArrayWrapperOperation(oracle(_, _, problem), _),
QubitArrayWrapperOperation(Oracle_SAT_Reference(_, _, problem), _),
nVar + 1
QubitArrayWrapperOperation(Oracle_SAT_Reference(_, _, problem), _)
);
}
}
@ -226,10 +222,9 @@ namespace Quantum.Kata.GroversAlgorithm {
AssertOracleImplementsFunction(nVar, Oracle_SAT(_, _, problem), F_SAT(_, problem));
AssertOperationsEqualReferenced(
AssertOperationsEqualReferenced(nVar + 1,
QubitArrayWrapperOperation(Oracle_SAT(_, _, problem), _),
QubitArrayWrapperOperation(Oracle_SAT_Reference(_, _, problem), _),
nVar + 1
QubitArrayWrapperOperation(Oracle_SAT_Reference(_, _, problem), _)
);
}
}

Просмотреть файл

@ -10,31 +10,28 @@
namespace Quantum.Kata.SuperdenseCoding {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
// Task 1. Entangled pair
operation CreateEntangledPair_Reference (qs : Qubit[]) : Unit {
operation CreateEntangledPair_Reference (qs : Qubit[]) : Unit
is Adj {
body (...) {
// The easiest way to create an entangled pair is to start with
// applying a Hadamard transformation to one of the qubits:
H(qs[0]);
// The easiest way to create an entangled pair is to start with
// applying a Hadamard transformation to one of the qubits:
H(qs[0]);
// This has left us in state:
// ((|0⟩ + |1⟩) / sqrt(2)) ⊗ |0⟩
// This has left us in state:
// ((|0⟩ + |1⟩) / sqrt(2)) ⊗ |0⟩
// Now, if we flip the second qubit conditioned on the state
// of the first one, we get that the states of the two qubits will always match.
CNOT(qs[0], qs[1]);
// So we ended up in the state:
// (|00⟩ + |11⟩) / sqrt(2)
//
// Which is the required Bell pair |Φ⁺⟩
}
adjoint invert;
// Now, if we flip the second qubit conditioned on the state
// of the first one, we get that the states of the two qubits will always match.
CNOT(qs[0], qs[1]);
// So we ended up in the state:
// (|00⟩ + |11⟩) / sqrt(2)
//
// Which is the required Bell pair |Φ⁺⟩
}
@ -62,9 +59,6 @@ namespace Quantum.Kata.SuperdenseCoding {
// Task 3. Decode the message (Bob's task)
operation DecodeMessageFromQubits_Reference (qBob : Qubit, qAlice : Qubit) : Bool[] {
// Declare a Bool array in which the result will be stored;
// the array has to be mutable to allow updating its elements.
mutable decoded_bits = new Bool[2];
// Time to get our state back, by performing transformations as follows.
// Notice that it's important to keep the order right. The qubits that are
@ -83,16 +77,12 @@ namespace Quantum.Kata.SuperdenseCoding {
// |Ψ⁻⟩ = (|01⟩ - |10⟩) / sqrt(2) ---> |11⟩
// So we can retrieve the encoded bits just by measuring.
set decoded_bits[0] = M(qAlice) == One;
set decoded_bits[1] = M(qBob) == One;
return decoded_bits;
return [M(qAlice) == One, M(qBob) == One];
}
// Task 4. Superdense coding protocol end-to-end
operation SuperdenseCodingProtocol_Reference (message : Bool[]) : Bool[] {
mutable decoded_bits = new Bool[2];
// Get a temporary qubit register for the protocol run.
using (qs = Qubit[2]) {
@ -111,13 +101,12 @@ namespace Quantum.Kata.SuperdenseCoding {
// STEP 3:
// Bob receives the qubit from Alice and can now
// manipulate and measure both qubits to get the encoded data.
set decoded_bits = DecodeMessageFromQubits_Reference(qs[1], qs[0]);
let decoded_bits = DecodeMessageFromQubits_Reference(qs[1], qs[0]);
// Make sure that we return qubits back in 0 state.
// Make sure that we return qubits back in 0 state before returning the decoded bits.
ResetAll(qs);
return decoded_bits;
}
return decoded_bits;
}
}

Просмотреть файл

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
@ -7,9 +7,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Canon" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Standard" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />

Просмотреть файл

@ -3,7 +3,8 @@
namespace Quantum.Kata.SuperdenseCoding {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
@ -42,7 +43,7 @@ namespace Quantum.Kata.SuperdenseCoding {
operation CreateEntangledPair (qs : Qubit[]) : Unit {
// The following lines enforce the constraints on the input that you are given.
// You don't need to modify them. Feel free to remove them, this won't cause your code to fail.
AssertIntEqual(Length(qs), 2, "The array should have exactly 2 qubits.");
EqualityFactI(Length(qs), 2, "The array should have exactly 2 qubits.");
// ...
}
@ -76,7 +77,7 @@ namespace Quantum.Kata.SuperdenseCoding {
// The state of the qubits in the end of the operation doesn't matter.
operation DecodeMessageFromQubits (qBob : Qubit, qAlice : Qubit) : Bool[] {
// Declare a Bool array in which the result will be stored;
// the array has to be mutable to allow updating its elements.
// the variable has to be mutable to allow updating it.
mutable decoded_bits = new Bool[2];
// ...

Просмотреть файл

@ -9,13 +9,13 @@
namespace Quantum.Kata.SuperdenseCoding {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Testing;
open Microsoft.Quantum.Diagnostics;
// ------------------------------------------------------
operation AssertEqualOnZeroState (N : Int, taskImpl : (Qubit[] => Unit), refImpl : (Qubit[] => Unit : Adjoint)) : Unit {
operation AssertEqualOnZeroState (N : Int, taskImpl : (Qubit[] => Unit), refImpl : (Qubit[] => Unit is Adj)) : Unit {
using (qs = Qubit[N]) {
// apply operation that needs to be tested
taskImpl(qs);
@ -39,18 +39,16 @@ namespace Quantum.Kata.SuperdenseCoding {
// Helper operation that runs superdense coding protocol using two building blocks
// specified as first two parameters.
operation ComposeProtocol (encodeOp : ((Qubit, Bool[]) => Unit), decodeOp : ((Qubit, Qubit) => Bool[]), message : Bool[]) : Bool[] {
mutable result = new Bool[2];
using (qs = Qubit[2]) {
CreateEntangledPair_Reference(qs);
encodeOp(qs[0], message);
set result = decodeOp(qs[1], qs[0]);
let result = decodeOp(qs[1], qs[0]);
// Make sure that we return qubits back in 0 state.
ResetAll(qs);
return result;
}
return result;
}
@ -58,18 +56,16 @@ namespace Quantum.Kata.SuperdenseCoding {
// Helper operation that runs superdense coding protocol (specified by protocolOp)
// on all possible input values and verifies that decoding result matches the inputs
operation TestProtocol (protocolOp : (Bool[] => Bool[])) : Unit {
mutable data = new Bool[2];
// Loop over the 4 possible combinations of two bits
for (n in 0 .. 3) {
set data[0] = 1 == n / 2;
set data[1] = 1 == n % 2;
let data = [1 == n / 2, 1 == n % 2];
for (iter in 1 .. 100) {
let result = protocolOp(data);
// Now test if the bits were transfered correctly.
AssertBoolArrayEqual(result, data, $"The message {data} was transfered incorrectly as {result}");
AllEqualityFactB(result, data, $"The message {data} was transfered incorrectly as {result}");
}
}
}

Просмотреть файл

@ -10,36 +10,31 @@
namespace Quantum.Kata.Superposition {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Measurement;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
// Task 1. Plus state
// Input: a qubit in |0⟩ state (stored in an array of length 1).
// Goal: create a |+⟩ state on this qubit (|+⟩ = (|0⟩ + |1⟩) / sqrt(2)).
operation PlusState_Reference (qs : Qubit[]) : Unit {
body (...) {
H(qs[0]);
}
adjoint invert;
operation PlusState_Reference (qs : Qubit[]) : Unit
is Adj {
H(qs[0]);
}
// Task 2. Minus state
// Input: a qubit in |0⟩ state (stored in an array of length 1).
// Goal: create a |-⟩ state on this qubit (|-⟩ = (|0⟩ - |1⟩) / sqrt(2)).
operation MinusState_Reference (qs : Qubit[]) : Unit {
body (...) {
X(qs[0]);
H(qs[0]);
}
adjoint invert;
operation MinusState_Reference (qs : Qubit[]) : Unit
is Adj {
X(qs[0]);
H(qs[0]);
}
@ -48,71 +43,58 @@ namespace Quantum.Kata.Superposition {
// 1) a qubit in |0⟩ state (stored in an array of length 1).
// 2) angle alpha, in radians, represented as Double
// Goal: create a cos(alpha) * |0⟩ + sin(alpha) * |1⟩ state on this qubit.
operation UnequalSuperposition_Reference (qs : Qubit[], alpha : Double) : Unit {
body (...) {
// Hint: Experiment with rotation gates from Microsoft.Quantum.Primitive
Ry(2.0 * alpha, qs[0]);
}
adjoint invert;
operation UnequalSuperposition_Reference (qs : Qubit[], alpha : Double) : Unit
is Adj {
// Hint: Experiment with rotation gates from Microsoft.Quantum.Primitive
Ry(2.0 * alpha, qs[0]);
}
// Task 4. Superposition of all basis vectors on two qubits
operation AllBasisVectors_TwoQubits_Reference (qs : Qubit[]) : Unit {
body (...) {
// Since a Hadamard gate will change |0⟩ into |+⟩ = (|0⟩ + |1⟩)/sqrt(2)
// And the desired state is just a tensor product |+⟩|+⟩, we can apply
// a Hadamard transformation to each qubit.
H(qs[0]);
H(qs[1]);
}
adjoint invert;
operation AllBasisVectors_TwoQubits_Reference (qs : Qubit[]) : Unit
is Adj {
// Since a Hadamard gate will change |0⟩ into |+⟩ = (|0⟩ + |1⟩)/sqrt(2)
// And the desired state is just a tensor product |+⟩|+⟩, we can apply
// a Hadamard transformation to each qubit.
H(qs[0]);
H(qs[1]);
}
// Task 5. Superposition of basis vectors with phases
operation AllBasisVectorsWithPhases_TwoQubits_Reference (qs : Qubit[]) : Unit {
operation AllBasisVectorsWithPhases_TwoQubits_Reference (qs : Qubit[]) : Unit
is Adj {
body (...) {
// Question:
// Is this state separable?
// Question:
// Is this state separable?
// Answer:
// Yes. It is. We can see that:
// ((|0⟩ - |1⟩) / sqrt(2)) ⊗ ((|0⟩ + i*|1⟩) / sqrt(2)) is equal to the desired
// state, so we can create it by doing operations on each qubit independently.
// Answer:
// Yes. It is. We can see that:
// ((|0⟩ - |1⟩) / sqrt(2)) ⊗ ((|0⟩ + i*|1⟩) / sqrt(2)) is equal to the desired
// state, so we can create it by doing operations on each qubit independently.
// We can see that the first qubit is in state |-⟩ and the second in state |i⟩,
// so the transformations that we need are:
// We can see that the first qubit is in state |-⟩ and the second in state |i⟩,
// so the transformations that we need are:
// Qubit 0 is taken into |+⟩ and then z-rotated into |-⟩.
H(qs[0]);
Z(qs[0]);
// Qubit 0 is taken into |+⟩ and then z-rotated into |-⟩.
H(qs[0]);
Z(qs[0]);
// Qubit 1 is taken into |+⟩ and then z-rotated into |i⟩.
H(qs[1]);
S(qs[1]);
}
adjoint invert;
// Qubit 1 is taken into |+⟩ and then z-rotated into |i⟩.
H(qs[1]);
S(qs[1]);
}
// Task 6. Bell state
// Input: two qubits in |00⟩ state (stored in an array of length 2).
// Goal: create a Bell state |Φ⁺⟩ = (|00⟩ + |11⟩) / sqrt(2) on these qubits.
operation BellState_Reference (qs : Qubit[]) : Unit {
body (...) {
H(qs[0]);
CNOT(qs[0], qs[1]);
}
adjoint invert;
operation BellState_Reference (qs : Qubit[]) : Unit
is Adj {
H(qs[0]);
CNOT(qs[0], qs[1]);
}
@ -125,40 +107,34 @@ namespace Quantum.Kata.Superposition {
// 1: |Φ⁻⟩ = (|00⟩ - |11⟩) / sqrt(2)
// 2: |Ψ⁺⟩ = (|01⟩ + |10⟩) / sqrt(2)
// 3: |Ψ⁻⟩ = (|01⟩ - |10⟩) / sqrt(2)
operation AllBellStates_Reference (qs : Qubit[], index : Int) : Unit {
operation AllBellStates_Reference (qs : Qubit[], index : Int) : Unit
is Adj {
body (...) {
H(qs[0]);
CNOT(qs[0], qs[1]);
H(qs[0]);
CNOT(qs[0], qs[1]);
// now we have |00⟩ + |11⟩ - modify it based on index arg
if (index % 2 == 1) {
// negative phase
Z(qs[1]);
}
if (index / 2 == 1) {
X(qs[1]);
}
// now we have |00⟩ + |11⟩ - modify it based on index arg
if (index % 2 == 1) {
// negative phase
Z(qs[1]);
}
if (index / 2 == 1) {
X(qs[1]);
}
adjoint invert;
}
// Task 8. Greenberger–Horne–Zeilinger state
// Input: N qubits in |0...0⟩ state.
// Goal: create a GHZ state (|0...0⟩ + |1...1⟩) / sqrt(2) on these qubits.
operation GHZ_State_Reference (qs : Qubit[]) : Unit {
operation GHZ_State_Reference (qs : Qubit[]) : Unit
is Adj {
body (...) {
H(qs[0]);
H(qs[0]);
for (i in 1 .. Length(qs) - 1) {
CNOT(qs[0], qs[i]);
}
for (q in Rest(qs)) {
CNOT(qs[0], q);
}
adjoint invert;
}
@ -166,15 +142,12 @@ namespace Quantum.Kata.Superposition {
// Input: N qubits in |0...0⟩ state.
// Goal: create an equal superposition of all basis vectors from |0...0⟩ to |1...1⟩
// (i.e. state (|0...0⟩ + ... + |1...1⟩) / sqrt(2^N) ).
operation AllBasisVectorsSuperposition_Reference (qs : Qubit[]) : Unit {
operation AllBasisVectorsSuperposition_Reference (qs : Qubit[]) : Unit
is Adj {
body (...) {
for (i in 0 .. Length(qs) - 1) {
H(qs[i]);
}
for (q in qs) {
H(q);
}
adjoint invert;
}
@ -182,20 +155,17 @@ namespace Quantum.Kata.Superposition {
// Task 10. |00⟩ + |01⟩ + |10⟩ state
// Input: 2 qubits in |00⟩ state.
// Goal: create the state (|00⟩ + |01⟩ + |10⟩) / sqrt(3) on these qubits.
operation ThreeStates_TwoQubits_Reference (qs : Qubit[]) : Unit {
operation ThreeStates_TwoQubits_Reference (qs : Qubit[]) : Unit
is Adj {
body (...) {
// Follow Niel's answer at https://quantumcomputing.stackexchange.com/a/2313/
// Follow Niel's answer at https://quantumcomputing.stackexchange.com/a/2313/
// Rotate first qubit to (sqrt(2) |0⟩ + |1⟩) / sqrt(3) (task 1.4 from BasicGates kata)
let theta = ArcSin(1.0 / Sqrt(3.0));
Ry(2.0 * theta, qs[0]);
// Rotate first qubit to (sqrt(2) |0⟩ + |1⟩) / sqrt(3) (task 1.4 from BasicGates kata)
let theta = ArcSin(1.0 / Sqrt(3.0));
Ry(2.0 * theta, qs[0]);
// Split the state sqrt(2) |0⟩ ⊗ |0⟩ into |00⟩ + |01⟩
(ControlledOnInt(0, H))([qs[0]], qs[1]);
}
adjoint auto;
// Split the state sqrt(2) |0⟩ ⊗ |0⟩ into |00⟩ + |01⟩
(ControlledOnInt(0, H))([qs[0]], qs[1]);
}
// Alternative solution, based on post-selection
@ -226,24 +196,21 @@ namespace Quantum.Kata.Superposition {
// You are guaranteed that the qubit array and the bit string have the same length.
// You are guaranteed that the first bit of the bit string is true.
// Example: for bit string = [true, false] the qubit state required is (|00⟩ + |10⟩) / sqrt(2).
operation ZeroAndBitstringSuperposition_Reference (qs : Qubit[], bits : Bool[]) : Unit {
operation ZeroAndBitstringSuperposition_Reference (qs : Qubit[], bits : Bool[]) : Unit
is Adj {
body (...) {
AssertIntEqual(Length(bits), Length(qs), "Arrays should have the same length");
AssertBoolEqual(bits[0], true, "First bit of the input bit string should be set to true");
EqualityFactI(Length(bits), Length(qs), "Arrays should have the same length");
EqualityFactB(bits[0], true, "First bit of the input bit string should be set to true");
// Hadamard first qubit
H(qs[0]);
// Hadamard first qubit
H(qs[0]);
// iterate through the bit string and CNOT to qubits corresponding to true bits
for (i in 1 .. Length(qs) - 1) {
if (bits[i]) {
CNOT(qs[0], qs[i]);
}
// iterate through the bit string and CNOT to qubits corresponding to true bits
for (i in 1 .. Length(qs) - 1) {
if (bits[i]) {
CNOT(qs[0], qs[i]);
}
}
adjoint invert;
}
@ -270,35 +237,32 @@ namespace Quantum.Kata.Superposition {
}
operation TwoBitstringSuperposition_Reference (qs : Qubit[], bits1 : Bool[], bits2 : Bool[]) : Unit {
operation TwoBitstringSuperposition_Reference (qs : Qubit[], bits1 : Bool[], bits2 : Bool[]) : Unit
is Adj {
body (...) {
// find the index of the first bit at which the bit strings are different
let firstDiff = FindFirstDiff_Reference(bits1, bits2);
// find the index of the first bit at which the bit strings are different
let firstDiff = FindFirstDiff_Reference(bits1, bits2);
// Hadamard corresponding qubit to create superposition
H(qs[firstDiff]);
// Hadamard corresponding qubit to create superposition
H(qs[firstDiff]);
// iterate through the bit strings again setting the final state of qubits
for (i in 0 .. Length(qs) - 1) {
if (bits1[i] == bits2[i]) {
// if two bits are the same apply X or nothing
if (bits1[i]) {
// iterate through the bit strings again setting the final state of qubits
for (i in 0 .. Length(qs) - 1) {
if (bits1[i] == bits2[i]) {
// if two bits are the same apply X or nothing
if (bits1[i]) {
X(qs[i]);
}
} else {
// if two bits are different, set their difference using CNOT
if (i > firstDiff) {
CNOT(qs[firstDiff], qs[i]);
if (bits1[i] != bits1[firstDiff]) {
X(qs[i]);
}
} else {
// if two bits are different, set their difference using CNOT
if (i > firstDiff) {
CNOT(qs[firstDiff], qs[i]);
if (bits1[i] != bits1[firstDiff]) {
X(qs[i]);
}
}
}
}
}
adjoint invert;
}
@ -312,36 +276,33 @@ namespace Quantum.Kata.Superposition {
// bit values false and true correspond to |0⟩ and |1⟩ states.
//
// Goal: create an equal superposition of the four basis states given by the bit strings.
operation FourBitstringSuperposition_Reference (qs : Qubit[], bits : Bool[][]) : Unit {
body (...) {
let N = Length(qs);
operation FourBitstringSuperposition_Reference (qs : Qubit[], bits : Bool[][]) : Unit
is Adj {
let N = Length(qs);
using (anc = Qubit[2]) {
// Put two ancillas into equal superposition of 2-qubit basis states
ApplyToEachA(H, anc);
using (anc = Qubit[2]) {
// Put two ancillas into equal superposition of 2-qubit basis states
ApplyToEachA(H, anc);
// Set up the right pattern on the main qubits with control on ancillas
for (i in 0 .. 3) {
for (j in 0 .. N - 1) {
if ((bits[i])[j]) {
(ControlledOnInt(i, X))(anc, qs[j]);
}
}
}
// Uncompute the ancillas, using patterns on main qubits as control
for (i in 0 .. 3) {
if (i % 2 == 1) {
(ControlledOnBitString(bits[i], X))(qs, anc[0]);
}
if (i / 2 == 1) {
(ControlledOnBitString(bits[i], X))(qs, anc[1]);
// Set up the right pattern on the main qubits with control on ancillas
for (i in 0 .. 3) {
for (j in 0 .. N - 1) {
if ((bits[i])[j]) {
(ControlledOnInt(i, X))(anc, qs[j]);
}
}
}
// Uncompute the ancillas, using patterns on main qubits as control
for (i in 0 .. 3) {
if (i % 2 == 1) {
(ControlledOnBitString(bits[i], X))(qs, anc[0]);
}
if (i / 2 == 1) {
(ControlledOnBitString(bits[i], X))(qs, anc[1]);
}
}
}
adjoint auto;
}
@ -351,36 +312,33 @@ namespace Quantum.Kata.Superposition {
// Goal: create a W state (https://en.wikipedia.org/wiki/W_state) on these qubits.
// W state is an equal superposition of all basis states on N qubits of Hamming weight 1.
// Example: for N = 4, W state is (|1000⟩ + |0100⟩ + |0010⟩ + |0001⟩) / 2.
operation WState_PowerOfTwo_Reference (qs : Qubit[]) : Unit {
operation WState_PowerOfTwo_Reference (qs : Qubit[]) : Unit
is Adj {
body (...) {
let N = Length(qs);
let N = Length(qs);
if (N == 1) {
// base of recursion: |1⟩
X(qs[0]);
} else {
let K = N / 2;
if (N == 1) {
// base of recursion: |1⟩
X(qs[0]);
} else {
let K = N / 2;
// create W state on the first K qubits
WState_PowerOfTwo_Reference(qs[0 .. K - 1]);
// create W state on the first K qubits
WState_PowerOfTwo_Reference(qs[0 .. K - 1]);
// the next K qubits are in |0...0⟩ state
// allocate ancilla in |+⟩ state
using (anc = Qubit[1]) {
H(anc[0]);
// the next K qubits are in |0...0⟩ state
// allocate ancilla in |+⟩ state
using (anc = Qubit()) {
H(anc);
for (i in 0 .. K - 1) {
Controlled SWAP(anc, (qs[i], qs[i + K]));
}
for (i in K .. N - 1) {
CNOT(qs[i], anc[0]);
}
for (i in 0 .. K - 1) {
Controlled SWAP([anc], (qs[i], qs[i + K]));
}
for (i in K .. N - 1) {
CNOT(qs[i], anc);
}
}
}
adjoint invert;
}
@ -392,31 +350,26 @@ namespace Quantum.Kata.Superposition {
// Example: for N = 3, W state is (|100⟩ + |010⟩ + |001⟩) / sqrt(3).
// general solution based on rotations and recursive application of controlled generation routine
operation WState_Arbitrary_Reference (qs : Qubit[]) : Unit {
operation WState_Arbitrary_Reference (qs : Qubit[]) : Unit
is Adj + Ctl {
body (...) {
let N = Length(qs);
let N = Length(qs);
if (N == 1) {
// base case of recursion: |1⟩
X(qs[0]);
} else {
// |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⟩
let theta = ArcSin(1.0 / Sqrt(ToDouble(N)));
Ry(2.0 * theta, qs[0]);
if (N == 1) {
// base case of recursion: |1⟩
X(qs[0]);
} else {
// |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⟩
let theta = ArcSin(1.0 / Sqrt(IntAsDouble(N)));
Ry(2.0 * theta, qs[0]);
// do a zero-controlled W-state generation for qubits 1..N-1
X(qs[0]);
Controlled WState_Arbitrary_Reference(qs[0 .. 0], qs[1 .. N - 1]);
X(qs[0]);
}
// do a zero-controlled W-state generation for qubits 1..N-1
X(qs[0]);
Controlled WState_Arbitrary_Reference(qs[0 .. 0], qs[1 .. N - 1]);
X(qs[0]);
}
adjoint invert;
controlled distribute;
controlled adjoint distribute;
}
@ -432,21 +385,18 @@ namespace Quantum.Kata.Superposition {
// Given a qubit in |0⟩ state and a denominator N,
// transform the qubit to state sqrt((N-1) / N) |0⟩ + sqrt(1/N) |1⟩.
operation FractionSuperposition(denominator : Int, q : Qubit) : Unit {
body (...) {
if (denominator == 1) {
X(q);
} else {
// represent the target state as cos(theta) * |0⟩ + sin(theta) * |1⟩, as in task 1.3
let denom = ToDouble(denominator);
let num = denom - 1.0;
let theta = ArcCos(Sqrt(num / denom));
Ry(2.0 * theta, q);
}
operation FractionSuperposition(denominator : Int, q : Qubit) : Unit
is Adj + Ctl {
if (denominator == 1) {
X(q);
} else {
// represent the target state as cos(theta) * |0⟩ + sin(theta) * |1⟩, as in task 1.3
let denom = IntAsDouble(denominator);
let num = denom - 1.0;
let theta = ArcCos(Sqrt(num / denom));
Ry(2.0 * theta, q);
}
adjoint invert;
controlled distribute;
controlled adjoint distribute;
}
@ -463,7 +413,7 @@ namespace Quantum.Kata.Superposition {
mutable P = 1;
for (i in 1 .. 6) {
if (P < N) {
set P = P * 2;
set P *= 2;
}
}

Просмотреть файл

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
@ -7,9 +7,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Canon" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Standard" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />

Просмотреть файл

@ -33,7 +33,7 @@
"metadata": {},
"outputs": [],
"source": [
"%package Microsoft.Quantum.Katas::0.5.1904.1302"
"%package Microsoft.Quantum.Katas::0.6.1905.301"
]
},
{
@ -43,13 +43,13 @@
"> The package versions in the output of the cell above should always match. If you are running the Notebooks locally and the versions do not match, please install the IQ# version that matches the version of the `Microsoft.Quantum.Katas` package.\n",
"> <details>\n",
"> <summary><u>How to install the right IQ# version</u></summary>\n",
"> For example, if the version of `Microsoft.Quantum.Katas` package above is 0.5.1904.1302, the installation steps are as follows:\n",
"> For example, if the version of `Microsoft.Quantum.Katas` package above is 0.6.1905.301, the installation steps are as follows:\n",
">\n",
"> 1. Stop the kernel.\n",
"> 2. Uninstall the existing version of IQ#:\n",
"> dotnet tool uninstall microsoft.quantum.iqsharp -g\n",
"> 3. Install the matching version:\n",
"> dotnet tool install microsoft.quantum.iqsharp -g --version 0.5.1904.1302\n",
"> dotnet tool install microsoft.quantum.iqsharp -g --version 0.6.1905.301\n",
"> 4. Reinstall the kernel:\n",
"> dotnet iqsharp install\n",
"> 5. Restart the Notebook.\n",
@ -125,7 +125,7 @@
"<br/>\n",
"<details>\n",
" <summary>Need a hint? Click here</summary>\n",
" Experiment with rotation gates from Microsoft.Quantum.Primitive namespace.\n",
" Experiment with rotation gates from Microsoft.Quantum.Intrinsic namespace.\n",
" Note that all rotation operators rotate the state by <i>half</i> of its angle argument.\n",
"</details>"
]
@ -321,7 +321,7 @@
"<br/>\n",
"<details>\n",
" <summary>Need a hint? Click here</summary>\n",
" If you need trigonometric functions, you can find them in Microsoft.Quantum.Extensions.Math namespace; you'll need to add <pre>open Microsoft.Quantum.Extensions.Math;</pre> to the code before the operation definition.\n",
" If you need trigonometric functions, you can find them in Microsoft.Quantum.Math namespace; you'll need to add <pre>open Microsoft.Quantum.Math;</pre> to the code before the operation definition.\n",
"</details>"
]
},
@ -480,7 +480,7 @@
"<br/>\n",
"<details>\n",
" <summary>Need a hint? Click here</summary>\n",
" You can modify the signature of the given operation to specify its controlled variant.\n",
" You can modify the signature of the given operation to specify its controlled specialization.\n",
"</details>"
]
},

Просмотреть файл

@ -3,11 +3,12 @@
namespace Quantum.Kata.Superposition {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
//////////////////////////////////////////////////////////////////
// Welcome!
@ -69,7 +70,7 @@ namespace Quantum.Kata.Superposition {
operation AllBasisVectors_TwoQubits (qs : Qubit[]) : Unit {
// The following lines enforce the constraints on the input that you are given.
// You don't need to modify them. Feel free to remove them, this won't cause your code to fail.
AssertIntEqual(Length(qs), 2, "The array should have exactly 2 qubits.");
EqualityFactI(Length(qs), 2, "The array should have exactly 2 qubits.");
// ...
}
@ -81,7 +82,7 @@ namespace Quantum.Kata.Superposition {
operation AllBasisVectorsWithPhases_TwoQubits (qs : Qubit[]) : Unit {
// The following lines enforce the constraints on the input that you are given.
// You don't need to modify them. Feel free to remove them, this won't cause your code to fail.
AssertIntEqual(Length(qs), 2, "The array should have exactly 2 qubits.");
EqualityFactI(Length(qs), 2, "The array should have exactly 2 qubits.");
// Hint: Is this state separable?
// ...
@ -149,8 +150,8 @@ namespace Quantum.Kata.Superposition {
operation ZeroAndBitstringSuperposition (qs : Qubit[], bits : Bool[]) : Unit {
// The following lines enforce the constraints on the input that you are given.
// You don't need to modify them. Feel free to remove them, this won't cause your code to fail.
AssertIntEqual(Length(bits), Length(qs), "Arrays should have the same length");
AssertBoolEqual(bits[0], true, "First bit of the input bit string should be set to true");
EqualityFactI(Length(bits), Length(qs), "Arrays should have the same length");
EqualityFactB(bits[0], true, "First bit of the input bit string should be set to true");
// ...
}

Просмотреть файл

@ -9,15 +9,15 @@
namespace Quantum.Kata.Superposition {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Extensions.Testing;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
// ------------------------------------------------------
operation AssertEqualOnZeroState (N : Int, testImpl : (Qubit[] => Unit), refImpl : (Qubit[] => Unit : Adjoint)) : Unit {
operation AssertEqualOnZeroState (N : Int, testImpl : (Qubit[] => Unit), refImpl : (Qubit[] => Unit is Adj)) : Unit {
using (qs = Qubit[N]) {
// apply operation that needs to be tested
testImpl(qs);
@ -53,7 +53,7 @@ namespace Quantum.Kata.Superposition {
AssertEqualOnZeroState(1, UnequalSuperposition(_, 0.75 * PI()), MinusState_Reference);
for (i in 1 .. 36) {
let alpha = ((2.0 * PI()) * ToDouble(i)) / 36.0;
let alpha = ((2.0 * PI()) * IntAsDouble(i)) / 36.0;
AssertEqualOnZeroState(1, UnequalSuperposition(_, alpha), UnequalSuperposition_Reference(_, alpha));
}
}
@ -182,7 +182,7 @@ namespace Quantum.Kata.Superposition {
repeat {
mutable ok = true;
for (i in 0 .. 3) {
set numbers[i] = RandomInt(1 <<< N);
set numbers w/= i <- RandomInt(1 <<< N);
for (j in 0 .. i - 1) {
if (numbers[i] == numbers[j]) {
set ok = false;
@ -195,7 +195,7 @@ namespace Quantum.Kata.Superposition {
// convert numbers to bit strings
for (i in 0 .. 3) {
set bits[i] = BoolArrFromPositiveInt(numbers[i], N);
set bits w/= i <- IntAsBoolArray(numbers[i], N);
}
AssertEqualOnZeroState(N, FourBitstringSuperposition(_, bits), FourBitstringSuperposition_Reference(_, bits));

Просмотреть файл

@ -9,10 +9,11 @@
namespace Quantum.Kata.Teleportation {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Preparation;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
//////////////////////////////////////////////////////////////////
@ -20,14 +21,10 @@ namespace Quantum.Kata.Teleportation {
//////////////////////////////////////////////////////////////////
// Task 1.1. Entangled pair
operation Entangle_Reference (qAlice : Qubit, qBob : Qubit) : Unit {
body (...) {
H(qAlice);
CNOT(qAlice, qBob);
}
adjoint invert;
operation Entangle_Reference (qAlice : Qubit, qBob : Qubit) : Unit
is Adj {
H(qAlice);
CNOT(qAlice, qBob);
}
@ -63,17 +60,16 @@ namespace Quantum.Kata.Teleportation {
// Task 1.5. Prepare the message specified and send it (Alice's task)
operation PrepareAndSendMessage_Reference (qAlice : Qubit, basis : Pauli, state : Bool) : (Bool, Bool) {
mutable classicalBits = (false, false);
using (qs = Qubit[1]) {
if (state) {
X(qs[0]);
}
PrepareQubit(basis, qs[0]);
set classicalBits = SendMessage_Reference(qAlice, qs[0]);
let classicalBits = SendMessage_Reference(qAlice, qs[0]);
Reset(qs[0]);
return classicalBits;
}
return classicalBits;
}
@ -151,25 +147,22 @@ namespace Quantum.Kata.Teleportation {
//////////////////////////////////////////////////////////////////
// Task 4.1. Entangled trio
operation EntangleThreeQubits_Reference (qAlice : Qubit, qBob : Qubit, qCharlie : Qubit) : Unit {
operation EntangleThreeQubits_Reference (qAlice : Qubit, qBob : Qubit, qCharlie : Qubit) : Unit
is Adj {
body (...) {
H(qAlice);
H(qBob);
X(qCharlie);
H(qAlice);
H(qBob);
X(qCharlie);
CCNOT(qAlice, qBob, qCharlie);
CCNOT(qAlice, qBob, qCharlie);
X(qAlice);
X(qBob);
X(qAlice);
X(qBob);
CCNOT(qAlice, qBob, qCharlie);
CCNOT(qAlice, qBob, qCharlie);
X(qAlice);
X(qBob);
}
adjoint invert;
X(qAlice);
X(qBob);
}

Просмотреть файл

@ -3,10 +3,10 @@
namespace Quantum.Kata.Teleportation {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
//////////////////////////////////////////////////////////////////

Просмотреть файл

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
@ -7,9 +7,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Canon" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Standard" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />

Просмотреть файл

@ -9,9 +9,9 @@
namespace Quantum.Kata.Teleportation {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Testing;
open Microsoft.Quantum.Diagnostics;
// ------------------------------------------------------
@ -79,7 +79,7 @@ namespace Quantum.Kata.Teleportation {
// which makes testing easier.
operation TeleportTestHelper (
teleportOp : ((Qubit, Qubit, Qubit) => Unit),
setupPsiOp : (Qubit => Unit : Adjoint)) : Unit {
setupPsiOp : (Qubit => Unit is Adj)) : Unit {
using (qs = Qubit[3]) {
let qMessage = qs[0];
@ -169,7 +169,7 @@ namespace Quantum.Kata.Teleportation {
StatePrep_BellState(qAlice, qBob, 0);
let classicalBits = prepareAndSendMessageOp(qAlice, basis, sentState);
let receivedState = reconstructAndMeasureMessageOp(qBob, classicalBits, basis);
AssertBoolEqual(receivedState, sentState, $"Sent and received states were not equal for {sentState} eigenstate in {basis} basis.");
EqualityFactB(receivedState, sentState, $"Sent and received states were not equal for {sentState} eigenstate in {basis} basis.");
ResetAll([qAlice, qBob]);
}
}

Просмотреть файл

@ -111,7 +111,7 @@ namespace Quantum.Kata.UnitaryPatterns
return base.Apply();
}
public override QArray<Qubit> Apply(long count)
public override IQArray<Qubit> Apply(long count)
{
_sim._qubitsAllocated += count;
if (_sim._qubitsAllocated > _sim._maxQubitsAllocated)
@ -137,7 +137,7 @@ namespace Quantum.Kata.UnitaryPatterns
base.Apply(q);
}
public override void Apply(QArray<Qubit> qubits)
public override void Apply(IQArray<Qubit> qubits)
{
_sim._qubitsAllocated -= qubits.Length;
base.Apply(qubits);

Просмотреть файл

@ -10,10 +10,11 @@
namespace Quantum.Kata.UnitaryPatterns {
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
// Task 1. Main diagonal
@ -78,20 +79,17 @@ namespace Quantum.Kata.UnitaryPatterns {
// Task 10. Increasing blocks
operation IncreasingBlocks_Reference (qs : Qubit[]) : Unit {
body (...) {
let N = Length(qs);
// for N = 1, we need an identity
if (N > 1) {
// do the bottom-right quarter
ApplyToEachCA(Controlled H([Tail(qs)], _), Most(qs));
// do the top-left quarter by calling the same operation recursively
(ControlledOnInt(0, IncreasingBlocks_Reference))([Tail(qs)], Most(qs));
}
operation IncreasingBlocks_Reference (qs : Qubit[]) : Unit
is Adj + Ctl {
let N = Length(qs);
// for N = 1, we need an identity
if (N > 1) {
// do the bottom-right quarter
ApplyToEachCA(Controlled H([Tail(qs)], _), Most(qs));
// do the top-left quarter by calling the same operation recursively
(ControlledOnInt(0, IncreasingBlocks_Reference))([Tail(qs)], Most(qs));
}
adjoint auto;
controlled auto;
controlled adjoint auto;
}
@ -116,27 +114,25 @@ namespace Quantum.Kata.UnitaryPatterns {
operation Decrement (qs : Qubit[]) : Unit {
X(qs[0]);
for (i in 1..Length(qs)-1) {
(Controlled X)(qs[0..i-1], qs[i]);
Controlled X(qs[0..i-1], qs[i]);
}
}
// Helper operation: antidiagonal
operation Reflect (qs : Qubit[]) : Unit {
body (...) {
ApplyToEachC(X, qs);
}
controlled auto;
operation Reflect (qs : Qubit[]) : Unit
is Ctl {
ApplyToEachC(X, qs);
}
// Main operation for Task 13
operation TIE_Fighter_Reference (qs : Qubit[]) : Unit {
let n = Length(qs);
X(qs[n-1]);
(Controlled Reflect)([qs[n-1]], qs[0..(n-2)]);
Controlled Reflect([qs[n-1]], qs[0..(n-2)]);
X(qs[n-1]);
Decrement(qs[0..(n-2)]);
H(qs[n-1]);
(Controlled Reflect)([qs[n-1]], qs[0..(n-2)]);
Controlled Reflect([qs[n-1]], qs[0..(n-2)]);
}
@ -152,7 +148,7 @@ namespace Quantum.Kata.UnitaryPatterns {
CNOT(qs[2], qs[0]);
CCNOT(qs[0], qs[2], qs[1]);
X(qs[2]);
(Controlled H)([qs[2]], qs[1]);
Controlled H([qs[2]], qs[1]);
X(qs[2]);
H(qs[0]);
CNOT(qs[1], qs[2]);
@ -173,64 +169,63 @@ namespace Quantum.Kata.UnitaryPatterns {
// Helper function for Embed_2x2_Operator: performs a Clifford to implement a base change
// that maps basis states index1 to 111...10 and index2 to 111...11 (in big endian notation, i.e., LSB in qs[n-1])
operation Embedding_Perm (index1 : Int, index2 : Int, qs : Qubit[]) : Unit {
body (...) {
let n = Length(qs);
let bits1 = BoolArrFromPositiveInt(index1, n);
let bits2 = BoolArrFromPositiveInt(index2, n);
// find the index of the first bit at which the bit strings are different
let diff = FirstDiff(bits1, bits2);
operation Embedding_Perm (index1 : Int, index2 : Int, qs : Qubit[]) : Unit
is Adj {
// we care only about 2 inputs: basis state of bits1 and bits2
let n = Length(qs);
let bits1 = BoolArrFromPositiveInt(index1, n);
let bits2 = BoolArrFromPositiveInt(index2, n);
// find the index of the first bit at which the bit strings are different
let diff = FirstDiff(bits1, bits2);
// make sure that the state corresponding to bits1 has qs[diff] set to |0⟩
if (bits1[diff]) {
X(qs[diff]);
}
// we care only about 2 inputs: basis state of bits1 and bits2
// make sure that the state corresponding to bits1 has qs[diff] set to |0⟩
if (bits1[diff]) {
X(qs[diff]);
}
// iterate through the bit strings again, setting the final state of qubits
for (i in 0..n-1) {
if (bits1[i] == bits2[i]) {
// if two bits are the same, set both to 1 using X or nothing
// iterate through the bit strings again, setting the final state of qubits
for (i in 0..n-1) {
if (bits1[i] == bits2[i]) {
// if two bits are the same, set both to 1 using X or nothing
if (not bits1[i]) {
X(qs[i]);
}
} else {
// if two bits are different, set both to 1 using CNOT
if (i > diff) {
if (not bits1[i]) {
X(qs[i]);
X(qs[diff]);
CNOT(qs[diff], qs[i]);
X(qs[diff]);
}
} else {
// if two bits are different, set both to 1 using CNOT
if (i > diff) {
if (not bits1[i]) {
X(qs[diff]);
CNOT(qs[diff], qs[i]);
X(qs[diff]);
}
if (not bits2[i]) {
CNOT(qs[diff], qs[i]);
}
if (not bits2[i]) {
CNOT(qs[diff], qs[i]);
}
}
}
// move the differing bit to the last qubit
if (diff < n-1) {
SWAP(qs[n-1], qs[diff]);
}
}
adjoint auto;
// move the differing bit to the last qubit
if (diff < n-1) {
SWAP(qs[n-1], qs[diff]);
}
}
// Helper function: apply the 2x2 unitary operator at the sub-matrix given by indices for 2 rows/columns
operation Embed_2x2_Operator (U : (Qubit => Unit : Controlled), index1 : Int, index2 : Int, qs : Qubit[]) : Unit {
operation Embed_2x2_Operator (U : (Qubit => Unit is Ctl), index1 : Int, index2 : Int, qs : Qubit[]) : Unit {
Embedding_Perm(index1, index2, qs);
(Controlled U)(Most(qs), Tail(qs));
(Adjoint Embedding_Perm)(index1, index2, qs);
Controlled U(Most(qs), Tail(qs));
Adjoint Embedding_Perm(index1, index2, qs);
}
// Putting everything together: the target pattern is produced by a sequence of controlled H gates.
operation Hessenberg_Matrix_Reference (qs : Qubit[]) : Unit {
let n = Length(qs);
for (i in 2^n-2..-1..0) {
for (i in 2^n-2..-1..0) {
Embed_2x2_Operator(H, i, i+1, qs);
}
}

Просмотреть файл

@ -3,10 +3,11 @@
namespace Quantum.Kata.UnitaryPatterns {
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
//////////////////////////////////////////////////////////////////
// Welcome!
@ -288,7 +289,7 @@ namespace Quantum.Kata.UnitaryPatterns {
// ..X..X..
// XX....XX
// XX....XX
operation Creeper (qs : Qubit[]) : Unit {
operation Creeper (qs : Qubit[]) : Unit {
// ...
}

Просмотреть файл

@ -9,12 +9,12 @@
namespace Quantum.Kata.UnitaryPatterns {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Arithmetic;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Convert;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Extensions.Testing;
open Microsoft.Quantum.Extensions.Diagnostics;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
// ------------------------------------------------------
@ -45,20 +45,16 @@ namespace Quantum.Kata.UnitaryPatterns {
op(qs);
// Make sure the solution didn't use any measurements
AssertIntEqual(GetOracleCallsCount(M), 0, "You are not allowed to use measurements in this task");
AssertIntEqual(GetOracleCallsCount(Measure), 0, "You are not allowed to use measurements in this task");
EqualityFactI(GetOracleCallsCount(M), 0, "You are not allowed to use measurements in this task");
EqualityFactI(GetOracleCallsCount(Measure), 0, "You are not allowed to use measurements in this task");
// Test that the result matches the k-th column
// DumpMachine($"C:/Tmp/dump{N}_{k}.txt");
for (j in 0 .. size - 1) {
let nonZero = pattern(size, j, k);
if (nonZero) {
AssertProbInt(j, 0.5 + ε, LittleEndian(qs), 0.5);
}
else {
AssertProbInt(j, 0.0, LittleEndian(qs), ε);
}
let (expected, tol) = nonZero ? (0.5 + ε, 0.5) | (0.0, ε);
AssertProbInt(j, expected, LittleEndian(qs), tol);
}
ResetAll(qs);
@ -285,10 +281,7 @@ namespace Quantum.Kata.UnitaryPatterns {
[ false, false, true, false, false, true, false, false],
[ true, true, false, false, false, false, true, true],
[ true, true, false, false, false, false, true, true] ];
if (size != 8) {
return false;
}
return A[row][col];
return size != 8 ? false | A[row][col];
}

Просмотреть файл

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
@ -7,9 +7,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Canon" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Standard" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />

Просмотреть файл

@ -0,0 +1,51 @@
# Script to validate Jupyter notebooks.
#
# This function takes a folder with Katas. Copies the corresponding
# jupyter notebook into a "Check.ipynb" that replaces the %kata magic
# with a %check_kata magic that runs the kata not with the user-supplied code
# but with the Reference implementation.
# If the execution fails or has warnings, the execution of the notebook
# will fail.
function validate {
Param($folder)
pushd $folder
# Name of the notebook that will be used for checking katas.
$CheckNotebook = 'Check.ipynb'
# Make sure old versions are removed.
if (Test-Path $CheckNotebook) {
Remove-Item $CheckNotebook
}
# Find the name of the kata's notebook.
$Notebook = (Get-ChildItem *.ipynb)
Write-Host "Checking notebook $Notebook."
# convert %kata to %check_kata. run Jupyter nbconvert to execute the kata.
(Get-Content $Notebook -Raw) | ForEach-Object { $_.replace('%kata', '%check_kata') } | Set-Content $CheckNotebook -NoNewline
jupyter nbconvert $CheckNotebook --execute --ExecutePreprocessor.timeout=120
# if jupyter returns an error code, return that this notebook is invalid:
$invalid = ($LastExitCode -ne 0)
Write-Host "Result: " $LastExitCode
popd
return $invalid
}
# List of Katas to verify:
$errors = $false
$errors = (validate ..\Measurements) -or $errors
$errors = (validate ..\BasicGates) -or $errors
$errors = (validate ..\Superposition) -or $errors
$errors = (validate ..\DeutschJozsaAlgorithm) -or $errors
$result = 0
if ($errors) {
Write-Host "##vso[task.logissue type=error;]Validation errors for Jupyter notebooks."
$result = 1
}
exit($result)

Просмотреть файл

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.6.1905.301" />
</ItemGroup>
</Project>

Просмотреть файл

@ -119,7 +119,7 @@ namespace Microsoft.Quantum.Katas
return base.Apply();
}
public override QArray<Qubit> Apply(long count)
public override IQArray<Qubit> Apply(long count)
{
_sim._qubitsAllocated += count;
if (_sim._qubitsAllocated > _sim._maxQubitsAllocated)
@ -148,7 +148,7 @@ namespace Microsoft.Quantum.Katas
base.Apply(q);
}
public override void Apply(QArray<Qubit> qubits)
public override void Apply(IQArray<Qubit> qubits)
{
_sim._qubitsAllocated -= qubits.Length;
base.Apply(qubits);

Просмотреть файл

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
@ -9,7 +9,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Canon" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.Standard" Version="0.6.1905.301" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.6.1905.301" />
</ItemGroup>
</Project>

Просмотреть файл

@ -3,9 +3,10 @@
namespace Quantum.DumpUnitary
{
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Extensions.Diagnostics;
open Microsoft.Quantum.Diagnostics;
operation DumpUnitaryToFiles (N : Int, unitary : (Qubit[] => Unit)) : Unit {
let size = 1 <<< N;

Просмотреть файл

@ -0,0 +1,203 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System;
using System.Linq;
using Microsoft.Extensions.Logging;
using Microsoft.Jupyter.Core;
using Microsoft.Quantum.IQSharp;
using Microsoft.Quantum.IQSharp.Common;
using Microsoft.Quantum.Simulation.Common;
using Microsoft.Quantum.Simulation.Core;
namespace Microsoft.Quantum.Katas
{
public class CheckKataMagic : MagicSymbol
{
/// <summary>
/// IQ# Magic that checks that the reference implementation of a Kata's test runs successfully.
/// </summary>
public CheckKataMagic(IOperationResolver resolver, ICompilerService compiler, ILogger<KataMagic> logger)
{
this.Name = $"%check_kata";
this.Documentation = new Documentation() { Summary = "Checks the resference implementaiton of a single kata's test." };
this.Kind = SymbolKind.Magic;
this.Execute = this.Run;
this.Resolver = resolver;
this.Compiler = compiler;
this.Logger = logger;
}
/// <summary>
/// The Resolver lets us find compiled Q# operations from the workspace
/// </summary>
protected IOperationResolver Resolver { get; }
/// <summary>
/// The list of user-defined Q# code snippets from the notebook.
/// </summary>
protected ICompilerService Compiler { get; }
protected ILogger<KataMagic> Logger { get; }
/// <summary>
/// What this Magic does when triggered. It will:
/// - find the Test to execute based on the provided name,
/// - semi-compile the code after to identify the name of the operation with the user's answer.
/// - call simulate to execute the test.
/// </summary>
public virtual ExecutionResult Run(string input, IChannel channel)
{
channel = channel.WithNewLines();
// Expect exactly two arguments, the name of the Kata and the user's answer (code).
var args = input?.Split(new char[] { ' ', '\n', '\t' }, 2);
if (args == null || args.Length != 2)
{
channel.Stderr("Invalid parameters. Usage: `%kata Test \"Q# operation\"`");
return ExecuteStatus.Error.ToExecutionResult();
}
var name = args[0];
var code = args[1];
var test = FindTest(name);
if (test == null)
{
channel.Stderr($"Invalid test name: {name}");
return ExecuteStatus.Error.ToExecutionResult();
}
var userAnswer = Compile(code, channel);
if (userAnswer == null) { return ExecuteStatus.Error.ToExecutionResult(); }
return Simulate(test, userAnswer, channel)
? "Success!".ToExecutionResult()
: ExecuteStatus.Error.ToExecutionResult();
}
/// <summary>
/// Compiles the given code. Checks there is only one operation defined in the code,
/// and returns its corresponding OperationInfo
/// </summary>
public virtual string Compile(string code, IChannel channel)
{
try
{
var result = Compiler.IdentifyElements(code);
// Gets the names of all the operations found for this snippet
var opsNames =
result
.Where(e => e.IsQsCallable)
.Select(e => e.ToFullName().WithoutNamespace(Microsoft.Quantum.IQSharp.Snippets.SNIPPETS_NAMESPACE))
.OrderBy(o => o)
.ToArray();
if (opsNames.Length > 1)
{
channel.Stdout("Expecting only one Q# operation in code. Using the first one");
}
return opsNames.First();
}
catch (CompilationErrorsException c)
{
foreach (var m in c.Errors) channel.Stderr(m);
return null;
}
catch (Exception e)
{
Logger?.LogWarning(e, "Unexpected error.");
channel.Stderr(e.Message);
return null;
}
}
/// <summary>
/// Executes the given test by replacing the userAnswer with its reference implementation.
/// It is expected that the test will succeed with no warnings.
/// </summary>
public virtual bool Simulate(OperationInfo test, string userAnswer, IChannel channel)
{
// The skeleton answer used to compile the workspace
var skeletonAnswer = FindSkeletonAnswer(test, userAnswer);
if (skeletonAnswer == null)
{
channel.Stderr($"Invalid task name: {userAnswer}");
return false;
}
// The reference implementation
var referenceAnswer = FindReferenceImplementation(test, userAnswer);
if (referenceAnswer == null)
{
channel.Stderr($"Reference answer not found: {userAnswer}");
return false;
}
try
{
var qsim = CreateSimulator();
var hasWarnings = false;
qsim.DisableLogToConsole();
qsim.Register(skeletonAnswer.RoslynType, referenceAnswer.RoslynType, typeof(ICallable));
qsim.OnLog += (msg) =>
{
hasWarnings = msg?.StartsWith("[WARNING]") ?? hasWarnings;
channel.Stdout(msg);
};
var value = test.RunAsync(qsim, null).Result;
if (qsim is IDisposable dis) { dis.Dispose(); }
return !hasWarnings;
}
catch (AggregateException agg)
{
foreach (var e in agg.InnerExceptions) { channel.Stderr(e.Message); }
channel.Stderr($"Try again!");
return false;
}
catch (Exception e)
{
channel.Stderr(e.Message);
channel.Stderr($"Try again!");
return false;
}
}
/// <summary>
/// Creates the instance of the simulator to use to run the test
/// (for now always CounterSimulator from the same package).
/// </summary>
public virtual SimulatorBase CreateSimulator() =>
new CounterSimulator();
/// <summary>
/// Returns the OperationInfo for the test to run.
/// </summary>
public virtual OperationInfo FindTest(string testName) =>
Resolver.Resolve(testName);
/// <summary>
/// Returns the original shell for the test's answer in the workspace for the given userAnswer.
/// It does this by finding another operation with the same name as the `userAnswer` but in the
/// test's namespace
/// </summary>
public virtual OperationInfo FindSkeletonAnswer(OperationInfo test, string userAnswer) =>
Resolver.Resolve($"{test.Header.QualifiedName.Namespace.Value}.{userAnswer}");
/// <summary>
/// Returns the reference implementation for the test's answer in the workspace for the given userAnswer.
/// It does this by finding another operation with the same name as the `userAnswer` but in the
/// test's namespace and with <c>_Reference</c> added to the userAnswer's name.
/// </summary>
public virtual OperationInfo FindReferenceImplementation(OperationInfo test, string userAnswer) =>
Resolver.Resolve($"{test.Header.QualifiedName.Namespace.Value}.{userAnswer}_Reference");
}
}

Просмотреть файл

@ -20,7 +20,7 @@ namespace Microsoft.Quantum.Katas
public KataMagic(IOperationResolver resolver, ISnippets snippets, ILogger<KataMagic> logger)
{
this.Name = $"%kata";
this.Documentation = new Documentation() { Summary = "Executes a single kata.", Full = "## Executes a single kata.\n##Usage: \n%kata Test \"q# operation\"" };
this.Documentation = new Documentation() { Summary = "Executes a single test.", Full = "## Executes a single test.\n##Usage: \n%kata Test \"q# operation\"" };
this.Kind = SymbolKind.Magic;
this.Execute = this.Run;
@ -43,9 +43,9 @@ namespace Microsoft.Quantum.Katas
/// <summary>
/// What this Magic does when triggered. It will:
/// - find the Kata to execute based on the Kata name,
/// - find the Test to execute based on the given name,
/// - compile the code after found after the name as the user's answer.
/// - run (simulate) the kata.
/// - run (simulate) the test and report its result.
/// </summary>
public virtual ExecutionResult Run(string input, IChannel channel)
{
@ -62,8 +62,8 @@ namespace Microsoft.Quantum.Katas
var name = args[0];
var code = args[1];
var kata = FindKata(name);
if (kata == null)
var test = FindTest(name);
if (test == null)
{
channel.Stderr($"Invalid test name: {name}");
return ExecuteStatus.Error.ToExecutionResult();
@ -72,7 +72,7 @@ namespace Microsoft.Quantum.Katas
var userAnswer = Compile(code, channel);
if (userAnswer == null) { return ExecuteStatus.Error.ToExecutionResult(); }
return Simulate(kata, userAnswer, channel)
return Simulate(test, userAnswer, channel)
? "Success!".ToExecutionResult()
: ExecuteStatus.Error.ToExecutionResult();
}
@ -123,10 +123,10 @@ namespace Microsoft.Quantum.Katas
/// (by calling `FindRawAnswer`) and replace its implementation with the userAnswer
/// in the simulator.
/// </summary>
public virtual bool Simulate(OperationInfo kata, OperationInfo userAnswer, IChannel channel)
public virtual bool Simulate(OperationInfo test, OperationInfo userAnswer, IChannel channel)
{
var rawAnswer = FindRawAnswer(kata, userAnswer);
if (rawAnswer == null)
var skeletonAnswer = FindSkeletonAnswer(test, userAnswer);
if (skeletonAnswer == null)
{
channel.Stderr($"Invalid task: {userAnswer.FullName}");
return false;
@ -137,10 +137,10 @@ namespace Microsoft.Quantum.Katas
var qsim = CreateSimulator();
qsim.DisableLogToConsole();
qsim.Register(rawAnswer.RoslynType, userAnswer.RoslynType, typeof(ICallable));
qsim.Register(skeletonAnswer.RoslynType, userAnswer.RoslynType, typeof(ICallable));
qsim.OnLog += channel.Stdout;
var value = kata.RunAsync(qsim, null).Result;
var value = test.RunAsync(qsim, null).Result;
if (qsim is IDisposable dis) { dis.Dispose(); }
@ -161,25 +161,25 @@ namespace Microsoft.Quantum.Katas
}
/// <summary>
/// Creates the instance of the simulator to use to run the Kata
/// Creates the instance of the simulator to use to run the Test
/// (for now always CounterSimulator from the same package).
/// </summary>
public virtual SimulatorBase CreateSimulator() =>
new CounterSimulator();
/// <summary>
/// Returns the OperationInfo for the Kata to run.
/// Returns the OperationInfo with the Test to run based on the given name.
/// </summary>
public virtual OperationInfo FindKata(string kataName) =>
Resolver.Resolve(kataName);
public virtual OperationInfo FindTest(string testName) =>
Resolver.Resolve(testName);
/// <summary>
/// Returns the original shell for the Kata's answer in the workspace for the given userAnswer.
/// Returns the original shell for the test's answer in the workspace for the given userAnswer.
/// It does this by finding another operation with the same name as the `userAnswer` but in the
/// Kata's namespace
/// test's namespace
/// </summary>
public virtual OperationInfo FindRawAnswer(OperationInfo kata, OperationInfo userAnswer) =>
Resolver.Resolve($"{kata.Header.QualifiedName.Namespace.Value}.{userAnswer.FullName}");
public virtual OperationInfo FindSkeletonAnswer(OperationInfo test, OperationInfo userAnswer) =>
Resolver.Resolve($"{test.Header.QualifiedName.Namespace.Value}.{userAnswer.FullName}");
}
}

Просмотреть файл

@ -18,7 +18,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.Jupyter.Core" Version="1.1.13141" />
<PackageReference Include="Microsoft.Quantum.IQSharp.Core" Version="0.5.1904.1302" />
<PackageReference Include="Microsoft.Quantum.IQSharp.Core" Version="0.6.1905.301" />
</ItemGroup>
<ItemGroup>