Update to 0.15 syntax, batch 3 (#593)
This commit is contained in:
Родитель
606afd2b7a
Коммит
2e99984bce
|
@ -74,17 +74,16 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
operation Oracle_Xor_2SAT (queryRegister : Qubit[], target : Qubit) : Unit is Adj {
|
||||
// x₀ ⊕ x₁ = (x₀ ∨ x₁) ∧ (¬x₀ ∨ ¬x₁)
|
||||
// Allocate 2 auxiliary qubits to store results of clause evaluation
|
||||
using ((a1, a2) = (Qubit(), Qubit())) {
|
||||
within {
|
||||
// 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
|
||||
ApplyWithA(ApplyToEachA(X, _), Oracle_Or_Reference(_, a2), queryRegister);
|
||||
}
|
||||
apply {
|
||||
// To calculate the final answer, apply the And oracle with the ancilla qubits as inputs
|
||||
Oracle_And_Reference([a1, a2], target);
|
||||
}
|
||||
use (a1, a2) = (Qubit(), Qubit());
|
||||
within {
|
||||
// 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
|
||||
ApplyWithA(ApplyToEachA(X, _), Oracle_Or_Reference(_, a2), queryRegister);
|
||||
}
|
||||
apply {
|
||||
// To calculate the final answer, apply the And oracle with the ancilla qubits as inputs
|
||||
Oracle_And_Reference([a1, a2], target);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,25 +95,24 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
|
||||
// Allocate N-1 qubits to store results of clauses evaluation
|
||||
let N = Length(queryRegister);
|
||||
using (anc = Qubit[N-1]) {
|
||||
within {
|
||||
// Evaluate all XOR clauses (using XOR oracle) and uncompute after
|
||||
for (i in 0..N-2) {
|
||||
Oracle_Xor_Reference(queryRegister[i..i+1], anc[i]);
|
||||
}
|
||||
}
|
||||
apply {
|
||||
// Evaluate the overall formula as an AND oracle (can use reference depending on the implementation)
|
||||
Controlled X(anc, target);
|
||||
use anc = Qubit[N-1];
|
||||
within {
|
||||
// Evaluate all XOR clauses (using XOR oracle) and uncompute after
|
||||
for i in 0..N-2 {
|
||||
Oracle_Xor_Reference(queryRegister[i..i+1], anc[i]);
|
||||
}
|
||||
}
|
||||
apply {
|
||||
// Evaluate the overall formula as an AND oracle (can use reference depending on the implementation)
|
||||
Controlled X(anc, target);
|
||||
}
|
||||
}
|
||||
|
||||
// Answer-based solution for alternating bits oracle
|
||||
operation FlipAlternatingPositionBits_Reference (register : Qubit[], firstIndex : Int) : Unit is Adj {
|
||||
|
||||
// iterate over elements in every second position, starting with firstIndex (indexes are 0-based)
|
||||
for (i in firstIndex .. 2 .. Length(register) - 1) {
|
||||
for i in firstIndex .. 2 .. Length(register) - 1 {
|
||||
X(register[i]);
|
||||
}
|
||||
}
|
||||
|
@ -124,7 +122,7 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
// 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) {
|
||||
for firstIndex in 0..1 {
|
||||
within {
|
||||
FlipAlternatingPositionBits_Reference(queryRegister, firstIndex);
|
||||
}
|
||||
|
@ -139,7 +137,7 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
function GetClauseQubits (queryRegister : Qubit[], clause : (Int, Bool)[]) : (Qubit[], Bool[]) {
|
||||
mutable clauseQubits = new Qubit[Length(clause)];
|
||||
mutable flip = new Bool[Length(clause)];
|
||||
for (varIndex in 0 .. Length(clause) - 1) {
|
||||
for varIndex in 0 .. Length(clause) - 1 {
|
||||
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
|
||||
set clauseQubits w/= varIndex <- queryRegister[index];
|
||||
|
@ -173,7 +171,7 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
ancillaRegister : Qubit[],
|
||||
problem : (Int, Bool)[][],
|
||||
clauseOracle : ((Qubit[], Qubit, (Int, Bool)[]) => Unit is Adj)) : Unit is Adj {
|
||||
for (clauseIndex in 0..Length(problem)-1) {
|
||||
for clauseIndex in 0..Length(problem)-1 {
|
||||
clauseOracle(queryRegister, ancillaRegister[clauseIndex], problem[clauseIndex]);
|
||||
}
|
||||
}
|
||||
|
@ -184,14 +182,13 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
problem : (Int, Bool)[][]) : Unit is Adj {
|
||||
// Similar to task 1.4.
|
||||
// Allocate qubits to store results of clauses evaluation
|
||||
using (ancillaRegister = Qubit[Length(problem)]) {
|
||||
// Compute clauses, evaluate the overall formula as an AND oracle (can use reference depending on the implementation) and uncompute
|
||||
within {
|
||||
EvaluateOrClauses(queryRegister, ancillaRegister, problem, Oracle_SATClause_Reference);
|
||||
}
|
||||
apply {
|
||||
Controlled X(ancillaRegister, target);
|
||||
}
|
||||
use ancillaRegister = Qubit[Length(problem)];
|
||||
// Compute clauses, evaluate the overall formula as an AND oracle (can use reference depending on the implementation) and uncompute
|
||||
within {
|
||||
EvaluateOrClauses(queryRegister, ancillaRegister, problem, Oracle_SATClause_Reference);
|
||||
}
|
||||
apply {
|
||||
Controlled X(ancillaRegister, target);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,7 +207,7 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
// "Exactly one |1⟩" oracle for an arbitrary number of qubits in query register
|
||||
operation Oracle_Exactly1One_Reference (queryRegister : Qubit[], target : Qubit) : Unit is Adj {
|
||||
mutable bits = new Bool[Length(queryRegister)];
|
||||
for (i in 0..Length(queryRegister) - 1) {
|
||||
for i in 0..Length(queryRegister) - 1 {
|
||||
// Iterate over all possible bit strings which have exactly one bit set to 1
|
||||
// and perform a controlled X with each of these bit strings as control
|
||||
(ControlledOnBitString(bits w/ i <- true, X))(queryRegister, target);
|
||||
|
@ -238,14 +235,13 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
target : Qubit,
|
||||
problem : (Int, Bool)[][]) : Unit is Adj {
|
||||
// similar to task 1.7
|
||||
using (ancillaRegister = Qubit[Length(problem)]) {
|
||||
// Compute clauses, evaluate the overall formula as an AND oracle (can use reference depending on the implementation) and uncompute
|
||||
within {
|
||||
EvaluateOrClauses(queryRegister, ancillaRegister, problem, Oracle_Exactly1OneClause_Reference);
|
||||
}
|
||||
apply {
|
||||
Controlled X(ancillaRegister, target);
|
||||
}
|
||||
use ancillaRegister = Qubit[Length(problem)];
|
||||
// Compute clauses, evaluate the overall formula as an AND oracle (can use reference depending on the implementation) and uncompute
|
||||
within {
|
||||
EvaluateOrClauses(queryRegister, ancillaRegister, problem, Oracle_Exactly1OneClause_Reference);
|
||||
}
|
||||
apply {
|
||||
Controlled X(ancillaRegister, target);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -257,17 +253,16 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
|
||||
operation OracleConverterImpl_Reference (markingOracle : ((Qubit[], Qubit) => Unit is Adj), register : Qubit[]) : Unit is Adj {
|
||||
|
||||
using (target = Qubit()) {
|
||||
within {
|
||||
// Put the target into the |-⟩ state, perform the apply functionality, then put back into |0⟩ so we can return it
|
||||
X(target);
|
||||
H(target);
|
||||
}
|
||||
apply {
|
||||
// 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);
|
||||
}
|
||||
use target = Qubit();
|
||||
within {
|
||||
// Put the target into the |-⟩ state, perform the apply functionality, then put back into |0⟩ so we can return it
|
||||
X(target);
|
||||
H(target);
|
||||
}
|
||||
apply {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -278,7 +273,7 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
operation GroversAlgorithm_Loop (register : Qubit[], oracle : ((Qubit[], Qubit) => Unit is Adj), iterations : Int) : Unit {
|
||||
let phaseOracle = OracleConverter_Reference(oracle);
|
||||
ApplyToEach(H, register);
|
||||
for (i in 1 .. iterations) {
|
||||
for i in 1 .. iterations {
|
||||
phaseOracle(register);
|
||||
within {
|
||||
ApplyToEachA(H, register);
|
||||
|
@ -301,27 +296,26 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
// This solution tries numbers of iterations that are powers of 2;
|
||||
// this is not the only valid solution, since a lot of sequences will eventually yield the answer.
|
||||
mutable answer = new Bool[N];
|
||||
using ((register, output) = (Qubit[N], Qubit())) {
|
||||
mutable correct = false;
|
||||
mutable iter = 1;
|
||||
repeat {
|
||||
Message($"Trying search with {iter} iterations");
|
||||
GroversAlgorithm_Loop(register, oracle, iter);
|
||||
let res = MultiM(register);
|
||||
// to check whether the result is correct, apply the oracle to the register plus ancilla after measurement
|
||||
oracle(register, output);
|
||||
if (MResetZ(output) == One) {
|
||||
set correct = true;
|
||||
set answer = ResultArrayAsBoolArray(res);
|
||||
}
|
||||
ResetAll(register);
|
||||
} until (correct or iter > 100) // the fail-safe to avoid going into an infinite loop
|
||||
fixup {
|
||||
set iter *= 2;
|
||||
}
|
||||
if (not correct) {
|
||||
fail "Failed to find an answer";
|
||||
use (register, output) = (Qubit[N], Qubit());
|
||||
mutable correct = false;
|
||||
mutable iter = 1;
|
||||
repeat {
|
||||
Message($"Trying search with {iter} iterations");
|
||||
GroversAlgorithm_Loop(register, oracle, iter);
|
||||
let res = MultiM(register);
|
||||
// to check whether the result is correct, apply the oracle to the register plus ancilla after measurement
|
||||
oracle(register, output);
|
||||
if (MResetZ(output) == One) {
|
||||
set correct = true;
|
||||
set answer = ResultArrayAsBoolArray(res);
|
||||
}
|
||||
ResetAll(register);
|
||||
} until (correct or iter > 100) // the fail-safe to avoid going into an infinite loop
|
||||
fixup {
|
||||
set iter *= 2;
|
||||
}
|
||||
if (not correct) {
|
||||
fail "Failed to find an answer";
|
||||
}
|
||||
Message($"{answer}");
|
||||
return answer;
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
// ------------------------------------------------------
|
||||
// helper wrapper to test for operation equality on various register sizes
|
||||
operation AssertRegisterOperationsEqual (testOp : (Qubit[] => Unit), refOp : (Qubit[] => Unit is Adj)) : Unit {
|
||||
for (n in 2 .. 10) {
|
||||
for n in 2 .. 10 {
|
||||
AssertOperationsEqualReferenced(n, testOp, refOp);
|
||||
}
|
||||
}
|
||||
|
@ -39,27 +39,26 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
|
||||
operation AssertOracleImplementsFunction (N : Int, oracle : ((Qubit[], Qubit) => Unit), f : (Bool[] -> Bool)) : Unit {
|
||||
let size = 1 <<< N;
|
||||
using ((qs, target) = (Qubit[N], Qubit())) {
|
||||
for (k in 0 .. size - 1) {
|
||||
// Prepare k-th bit vector
|
||||
let binary = IntAsBoolArray(k, N);
|
||||
use (qs, target) = (Qubit[N], Qubit());
|
||||
for k in 0 .. size - 1 {
|
||||
// Prepare k-th bit vector
|
||||
let binary = IntAsBoolArray(k, N);
|
||||
|
||||
//Message($"{k}/{N} = {binary}");
|
||||
// binary is little-endian notation, so the second vector tried has qubit 0 in state 1 and the rest in state 0
|
||||
ApplyPauliFromBitString(PauliX, true, binary, qs);
|
||||
//Message($"{k}/{N} = {binary}");
|
||||
// binary is little-endian notation, so the second vector tried has qubit 0 in state 1 and the rest in state 0
|
||||
ApplyPauliFromBitString(PauliX, true, binary, qs);
|
||||
|
||||
// Apply the operation
|
||||
oracle(qs, target);
|
||||
// Apply the operation
|
||||
oracle(qs, target);
|
||||
|
||||
// Check that the result is what we'd expect to measure
|
||||
let val = f(binary);
|
||||
AssertQubit(val ? One | Zero, target);
|
||||
Reset(target);
|
||||
// Check that the result is what we'd expect to measure
|
||||
let val = f(binary);
|
||||
AssertQubit(val ? One | Zero, target);
|
||||
Reset(target);
|
||||
|
||||
// Check that the query qubits are still in the same state
|
||||
ApplyPauliFromBitString(PauliX, true, binary, qs);
|
||||
AssertAllZero(qs);
|
||||
}
|
||||
// Check that the query qubits are still in the same state
|
||||
ApplyPauliFromBitString(PauliX, true, binary, qs);
|
||||
AssertAllZero(qs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,7 +110,7 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
|
||||
// ------------------------------------------------------
|
||||
function AlternatingBits (args : Bool[]) : Bool {
|
||||
for (i in 0..Length(args)-2) {
|
||||
for i in 0..Length(args)-2 {
|
||||
if (args[i] == args[i+1]) {
|
||||
return false;
|
||||
}
|
||||
|
@ -124,7 +123,7 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
let testOp = QubitArrayWrapperOperation(Oracle_AlternatingBits, _);
|
||||
let refOp = QubitArrayWrapperOperation(Oracle_AlternatingBits_Reference, _);
|
||||
|
||||
for (n in 2 .. 5) {
|
||||
for n in 2 .. 5 {
|
||||
AssertOracleImplementsFunction(n, Oracle_AlternatingBits, AlternatingBits);
|
||||
|
||||
AssertOperationsEqualReferenced(n + 1, testOp, refOp);
|
||||
|
@ -141,7 +140,7 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
|
||||
function SATClauseAsString (clause : (Int, Bool)[]) : String {
|
||||
mutable ret = SATVariableAsString(clause[0]);
|
||||
for (ind in 1 .. Length(clause) - 1) {
|
||||
for ind in 1 .. Length(clause) - 1 {
|
||||
set ret = ret + " ∨ " + SATVariableAsString(clause[ind]);
|
||||
}
|
||||
return ret;
|
||||
|
@ -149,7 +148,7 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
|
||||
function SATInstanceAsString (instance : (Int, Bool)[][]) : String {
|
||||
mutable ret = "(" + SATClauseAsString(instance[0]) + ")";
|
||||
for (ind in 1 .. Length(instance) - 1) {
|
||||
for ind in 1 .. Length(instance) - 1 {
|
||||
set ret = ret + " ∧ (" + SATClauseAsString(instance[ind]) + ")";
|
||||
}
|
||||
return ret;
|
||||
|
@ -159,7 +158,7 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
// ------------------------------------------------------
|
||||
// Evaluate one clause of the SAT formula
|
||||
function F_SATClause (args : Bool[], clause : (Int, Bool)[]) : Bool {
|
||||
for ((index, isTrue) in clause) {
|
||||
for (index, isTrue) in clause {
|
||||
if (isTrue == args[index]) {
|
||||
// one true literal is sufficient for the clause to be true
|
||||
return true;
|
||||
|
@ -178,7 +177,7 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
mutable clause = new (Int, Bool)[nVarInClause];
|
||||
mutable usedVariables = new Bool[nVar];
|
||||
// Make sure variables in the clause are distinct
|
||||
for (k in 0 .. nVarInClause - 1) {
|
||||
for k in 0 .. nVarInClause - 1 {
|
||||
mutable nextInd = -1;
|
||||
repeat {
|
||||
set nextInd = DrawRandomInt(0, nVar - 1);
|
||||
|
@ -192,7 +191,7 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
|
||||
@Test("QuantumSimulator")
|
||||
operation T15_Oracle_SATClause () : Unit {
|
||||
for (i in 1..10) {
|
||||
for i in 1..10 {
|
||||
let nVar = DrawRandomInt(3, 7);
|
||||
let clause = Generate_SAT_Clause(nVar, i);
|
||||
|
||||
|
@ -210,7 +209,7 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
|
||||
// ------------------------------------------------------
|
||||
function F_SAT (args : Bool[], problem : (Int, Bool)[][]) : Bool {
|
||||
for (clause in problem) {
|
||||
for clause in problem {
|
||||
// One clause can invalidate the whole formula
|
||||
if (not F_SATClause(args, clause)) {
|
||||
return false;
|
||||
|
@ -222,7 +221,7 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
operation GenerateSATInstance (nVar : Int, nClause : Int, nTerms : Int) : (Int, Bool)[][] {
|
||||
mutable problem = new (Int, Bool)[][nClause];
|
||||
|
||||
for (j in 0..nClause-1) {
|
||||
for j in 0..nClause-1 {
|
||||
set problem w/= j <- Generate_SAT_Clause(nVar, nTerms);
|
||||
}
|
||||
return problem;
|
||||
|
@ -257,7 +256,7 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
RunCrossTests(Oracle_SAT);
|
||||
|
||||
// General SAT instances for 3..6 variables
|
||||
for (nVar in 3 .. 6) {
|
||||
for nVar in 3 .. 6 {
|
||||
let problem = GenerateSATInstance(nVar, nVar - 1, -1);
|
||||
Message($"Testing k-SAT instance ({nVar}, {SATInstanceAsString(problem)})...");
|
||||
|
||||
|
@ -278,7 +277,7 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
// ------------------------------------------------------
|
||||
function F_Exactly1One (args : Bool[]) : Bool {
|
||||
mutable nOnes = 0;
|
||||
for (element in args) {
|
||||
for element in args {
|
||||
if (element) {
|
||||
set nOnes += 1;
|
||||
}
|
||||
|
@ -300,7 +299,7 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
// Evaluate one clause of the SAT formula
|
||||
function F_Exactly1SATClause (args : Bool[], clause : (Int, Bool)[]) : Bool {
|
||||
mutable nOnes = 0;
|
||||
for ((index, isTrue) in clause) {
|
||||
for (index, isTrue) in clause {
|
||||
if (isTrue == args[index]) {
|
||||
// count the number of true literals
|
||||
set nOnes += 1;
|
||||
|
@ -310,7 +309,7 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
}
|
||||
|
||||
function F_Exactly1_SAT (args : Bool[], problem : (Int, Bool)[][]) : Bool {
|
||||
for (clause in problem) {
|
||||
for clause in problem {
|
||||
// One clause can invalidate the whole formula
|
||||
if (not F_Exactly1SATClause(args, clause)) {
|
||||
return false;
|
||||
|
@ -322,7 +321,7 @@ namespace Quantum.Kata.GroversAlgorithm {
|
|||
@Test("QuantumSimulator")
|
||||
operation T22_Oracle_Exactly1SAT () : Unit {
|
||||
// General SAT instances for 2..6 variables
|
||||
for (nVar in 2..6) {
|
||||
for nVar in 2..6 {
|
||||
let problem = GenerateSATInstance(nVar, nVar - 1, 3);
|
||||
Message($"Testing exactly-1 3-SAT instance ({nVar}, {SATInstanceAsString(problem)})...");
|
||||
|
||||
|
|
|
@ -349,18 +349,17 @@
|
|||
"\n",
|
||||
"operation Oracle_AlternatingBits (queryRegister : Qubit[], target : Qubit) : Unit is Adj {\n",
|
||||
" let N = Length(queryRegister);\n",
|
||||
" using (auxiliaryRegister = Qubit[N-1]) {\n",
|
||||
" // Find the XOR of all pairs of consecutive qubits and store the result in auxiliaryRegister\n",
|
||||
" within {\n",
|
||||
" for (i in 0 .. N-2) {\n",
|
||||
" Oracle_Xor(queryRegister[i .. i+1], auxiliaryRegister[i]);\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" // Use the And oracle on auxiliaryRegister to get the answer\n",
|
||||
" apply {\n",
|
||||
" Oracle_And(auxiliaryRegister, target); \n",
|
||||
" use auxiliaryRegister = Qubit[N-1];\n",
|
||||
" // Find the XOR of all pairs of consecutive qubits and store the result in auxiliaryRegister\n",
|
||||
" within {\n",
|
||||
" for i in 0 .. N-2 {\n",
|
||||
" Oracle_Xor(queryRegister[i .. i+1], auxiliaryRegister[i]);\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" // Use the And oracle on auxiliaryRegister to get the answer\n",
|
||||
" apply {\n",
|
||||
" Oracle_And(auxiliaryRegister, target); \n",
|
||||
" }\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
|
@ -391,7 +390,7 @@
|
|||
" let N = Length(queryRegister);\n",
|
||||
" // Find the XOR of all pairs of consecutive qubits and store the result in queryRegister itself\n",
|
||||
" within {\n",
|
||||
" for(i in 0 .. N-2) {\n",
|
||||
" for i in 0 .. N-2 {\n",
|
||||
" CNOT(queryRegister[i+1], queryRegister[i]);\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
|
@ -476,7 +475,7 @@
|
|||
"// Find all qubits which are variables in clause\n",
|
||||
"function GetClauseQubits (queryRegister : Qubit[], clause: (Int,Bool)[]) : Qubit[] {\n",
|
||||
" mutable clauseQubits = new Qubit[0];\n",
|
||||
" for ((index, _) in clause) {\n",
|
||||
" for (index, _) in clause {\n",
|
||||
" set clauseQubits += [queryRegister[index]];\n",
|
||||
" }\n",
|
||||
" return clauseQubits;\n",
|
||||
|
@ -496,7 +495,7 @@
|
|||
"operation Oracle_SATClause (queryRegister : Qubit[], target : Qubit, clause : (Int, Bool)[]) : Unit is Adj {\n",
|
||||
" within {\n",
|
||||
" // Flip all qubits which are in negated form in the SAT clause.\n",
|
||||
" for ((index, positive) in clause) {\n",
|
||||
" for (index, positive) in clause {\n",
|
||||
" if (not positive) {\n",
|
||||
" X(queryRegister[index]);\n",
|
||||
" }\n",
|
||||
|
@ -542,7 +541,7 @@
|
|||
"operation Oracle_SATClause (queryRegister : Qubit[], target : Qubit, clause : (Int, Bool)[]) : Unit is Adj {\n",
|
||||
" // Flip all qubits which are in negated form in the SAT clause.\n",
|
||||
" within {\n",
|
||||
" for (term in clause) {\n",
|
||||
" for term in clause {\n",
|
||||
" // If Snd(term) is false, apply X gate, otherwise apply I (do nothing).\n",
|
||||
" (Snd(term)? I | X)(queryRegister[Fst(term)]);\n",
|
||||
" }\n",
|
||||
|
@ -629,18 +628,17 @@
|
|||
"%kata T16_Oracle_SAT \n",
|
||||
"\n",
|
||||
"operation Oracle_SAT (queryRegister : Qubit[], target : Qubit, problem : (Int, Bool)[][]) : Unit is Adj {\n",
|
||||
" using (auxiliaryRegister = Qubit[Length(problem)]) {\n",
|
||||
" // Compute the clauses.\n",
|
||||
" within {\n",
|
||||
" for (i in 0 .. Length(problem) - 1) {\n",
|
||||
" Oracle_SATClause(queryRegister, auxiliaryRegister[i], problem[i]);\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" // Evaluate the overall formula using an AND oracle.\n",
|
||||
" apply {\n",
|
||||
" Oracle_And(auxiliaryRegister, target);\n",
|
||||
" use auxiliaryRegister = Qubit[Length(problem)];\n",
|
||||
" // Compute the clauses.\n",
|
||||
" within {\n",
|
||||
" for i in 0 .. Length(problem) - 1 {\n",
|
||||
" Oracle_SATClause(queryRegister, auxiliaryRegister[i], problem[i]);\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" // Evaluate the overall formula using an AND oracle.\n",
|
||||
" apply {\n",
|
||||
" Oracle_And(auxiliaryRegister, target);\n",
|
||||
" }\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
|
@ -716,7 +714,7 @@
|
|||
"%kata T21_Oracle_Exactly1One \n",
|
||||
"\n",
|
||||
"operation Oracle_Exactly1One (queryRegister : Qubit[], target : Qubit) : Unit is Adj {\n",
|
||||
" for (i in 0 .. Length(queryRegister) - 1) {\n",
|
||||
" for i in 0 .. Length(queryRegister) - 1 {\n",
|
||||
" (ControlledOnInt(2^i, X))(queryRegister, target);\n",
|
||||
" }\n",
|
||||
"}"
|
||||
|
@ -778,7 +776,7 @@
|
|||
" \n",
|
||||
"operation Oracle_Exactly1OneSATClause (queryRegister : Qubit[], target : Qubit, clause : (Int, Bool)[]) : Unit is Adj {\n",
|
||||
" within {\n",
|
||||
" for ((index, positive) in clause) {\n",
|
||||
" for (index, positive) in clause {\n",
|
||||
" if (not positive) {\n",
|
||||
" X(queryRegister[index]);\n",
|
||||
" }\n",
|
||||
|
@ -811,18 +809,17 @@
|
|||
"%kata T22_Oracle_Exactly1SAT \n",
|
||||
"\n",
|
||||
"operation Oracle_Exactly1_3SAT (queryRegister : Qubit[], target : Qubit, problem : (Int, Bool)[][]) : Unit is Adj {\n",
|
||||
" using (auxiliaryRegister = Qubit[Length(problem)]) {\n",
|
||||
" // Compute the clauses.\n",
|
||||
" within {\n",
|
||||
" for (i in 0 .. Length(problem) - 1) {\n",
|
||||
" Oracle_Exactly1OneSATClause(queryRegister, auxiliaryRegister[i], problem[i]);\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" // Evaluate the overall formula using an AND oracle.\n",
|
||||
" apply {\n",
|
||||
" Oracle_And(auxiliaryRegister, target);\n",
|
||||
" use auxiliaryRegister = Qubit[Length(problem)];\n",
|
||||
" // Compute the clauses.\n",
|
||||
" within {\n",
|
||||
" for i in 0 .. Length(problem) - 1 {\n",
|
||||
" Oracle_Exactly1OneSATClause(queryRegister, auxiliaryRegister[i], problem[i]);\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" // Evaluate the overall formula using an AND oracle.\n",
|
||||
" apply {\n",
|
||||
" Oracle_And(auxiliaryRegister, target);\n",
|
||||
" }\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
|
@ -869,17 +866,16 @@
|
|||
"outputs": [],
|
||||
"source": [
|
||||
"operation Oracle_Converter (markingOracle : ((Qubit[], Qubit) => Unit is Adj), register : Qubit[]) : Unit is Adj {\n",
|
||||
" using (target = Qubit()) {\n",
|
||||
" // Put the target into the |-⟩ state and later revert the state\n",
|
||||
" within { \n",
|
||||
" X(target);\n",
|
||||
" H(target); \n",
|
||||
" }\n",
|
||||
" // Apply the marking oracle; since the target is in the |-⟩ state,\n",
|
||||
" // flipping the target if the register satisfies the oracle condition will apply a -1 factor to the state\n",
|
||||
" apply { \n",
|
||||
" markingOracle(register, target);\n",
|
||||
" }\n",
|
||||
" use target = Qubit();\n",
|
||||
" // Put the target into the |-⟩ state and later revert the state\n",
|
||||
" within { \n",
|
||||
" X(target);\n",
|
||||
" H(target); \n",
|
||||
" }\n",
|
||||
" // Apply the marking oracle; since the target is in the |-⟩ state,\n",
|
||||
" // flipping the target if the register satisfies the oracle condition will apply a -1 factor to the state\n",
|
||||
" apply { \n",
|
||||
" markingOracle(register, target);\n",
|
||||
" }\n",
|
||||
"}"
|
||||
]
|
||||
|
@ -904,7 +900,7 @@
|
|||
" let phaseOracle = Oracle_Converter(oracle, _);\n",
|
||||
" ApplyToEach(H, register);\n",
|
||||
"\n",
|
||||
" for (_ in 1 .. numIterations) {\n",
|
||||
" for _ in 1 .. numIterations {\n",
|
||||
" phaseOracle(register);\n",
|
||||
" within{\n",
|
||||
" ApplyToEachA(H, register);\n",
|
||||
|
@ -950,24 +946,23 @@
|
|||
" \n",
|
||||
" // Try different numbers of iterations.\n",
|
||||
" let numIterations = 1;\n",
|
||||
" using ((register, output) = (Qubit[N], Qubit())) {\n",
|
||||
" Message($\"Trying search with {numIterations} iterations\");\n",
|
||||
" GroversLoop(register, oracle, numIterations);\n",
|
||||
" \n",
|
||||
" // Measure the result.\n",
|
||||
" let res = MultiM(register);\n",
|
||||
" \n",
|
||||
" // Apply the oracle to the register after measurement to check whether the result is correct. \n",
|
||||
" oracle(register, output);\n",
|
||||
" \n",
|
||||
" if (MResetZ(output) == One) {\n",
|
||||
" let answer = ResultArrayAsBoolArray(res);\n",
|
||||
" Message($\"Found Answer: {answer}\");\n",
|
||||
" } else {\n",
|
||||
" Message(\"Failed to find an answer. Try again!\");\n",
|
||||
" }\n",
|
||||
" ResetAll(register); \n",
|
||||
" use (register, output) = (Qubit[N], Qubit());\n",
|
||||
" Message($\"Trying search with {numIterations} iterations\");\n",
|
||||
" GroversLoop(register, oracle, numIterations);\n",
|
||||
"\n",
|
||||
" // Measure the result.\n",
|
||||
" let res = MultiM(register);\n",
|
||||
"\n",
|
||||
" // Apply the oracle to the register after measurement to check whether the result is correct. \n",
|
||||
" oracle(register, output);\n",
|
||||
"\n",
|
||||
" if (MResetZ(output) == One) {\n",
|
||||
" let answer = ResultArrayAsBoolArray(res);\n",
|
||||
" Message($\"Found Answer: {answer}\");\n",
|
||||
" } else {\n",
|
||||
" Message(\"Failed to find an answer. Try again!\");\n",
|
||||
" }\n",
|
||||
" ResetAll(register); \n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
|
@ -1034,27 +1029,26 @@
|
|||
"operation UniversalGroversAlgorithm (N : Int, oracle : ((Qubit[], Qubit) => Unit is Adj)) : Bool[] {\n",
|
||||
" // Since we are unaware of the optimal number of iterations, we try different numbers of iterations.\n",
|
||||
" mutable answer = new Bool[N];\n",
|
||||
" using ((register, output) = (Qubit[N], Qubit())) {\n",
|
||||
" mutable correct = false;\n",
|
||||
" mutable iter = 1;\n",
|
||||
" repeat {\n",
|
||||
" Message($\"Trying search with {iter} iterations\");\n",
|
||||
" GroversLoop(register, oracle, iter);\n",
|
||||
" let res = MultiM(register);\n",
|
||||
" \n",
|
||||
" oracle(register, output);\n",
|
||||
" if (MResetZ(output) == One) {\n",
|
||||
" set correct = true;\n",
|
||||
" set answer = ResultArrayAsBoolArray(res);\n",
|
||||
" }\n",
|
||||
" ResetAll(register);\n",
|
||||
" } until (correct or iter > 10) // The fail-safe to avoid going into an infinite loop\n",
|
||||
" fixup {\n",
|
||||
" set iter *= 2;\n",
|
||||
" }\n",
|
||||
" if (not correct) {\n",
|
||||
" fail \"Failed to find an answer\";\n",
|
||||
" use (register, output) = (Qubit[N], Qubit());\n",
|
||||
" mutable correct = false;\n",
|
||||
" mutable iter = 1;\n",
|
||||
" repeat {\n",
|
||||
" Message($\"Trying search with {iter} iterations\");\n",
|
||||
" GroversLoop(register, oracle, iter);\n",
|
||||
" let res = MultiM(register);\n",
|
||||
"\n",
|
||||
" oracle(register, output);\n",
|
||||
" if (MResetZ(output) == One) {\n",
|
||||
" set correct = true;\n",
|
||||
" set answer = ResultArrayAsBoolArray(res);\n",
|
||||
" }\n",
|
||||
" ResetAll(register);\n",
|
||||
" } until (correct or iter > 10) // The fail-safe to avoid going into an infinite loop\n",
|
||||
" fixup {\n",
|
||||
" set iter *= 2;\n",
|
||||
" }\n",
|
||||
" if (not correct) {\n",
|
||||
" fail \"Failed to find an answer\";\n",
|
||||
" }\n",
|
||||
" Message($\"{answer}\");\n",
|
||||
" return answer;\n",
|
||||
|
|
|
@ -83,24 +83,23 @@ namespace Quantum.Kata.SuperdenseCoding {
|
|||
operation SuperdenseCodingProtocol_Reference (message : ProtocolMessage) : ProtocolMessage {
|
||||
|
||||
// Get a temporary qubit register for the protocol run.
|
||||
using ((q1, q2) = (Qubit(), Qubit())) {
|
||||
// STEP 1:
|
||||
// Start by creating an entangled pair of qubits.
|
||||
CreateEntangledPair_Reference(q1, q2);
|
||||
use (q1, q2) = (Qubit(), Qubit());
|
||||
// STEP 1:
|
||||
// Start by creating an entangled pair of qubits.
|
||||
CreateEntangledPair_Reference(q1, q2);
|
||||
|
||||
// Alice and Bob receive one half of the pair each.
|
||||
// Alice and Bob receive one half of the pair each.
|
||||
|
||||
// STEP 2:
|
||||
// Alice encodes the pair of bits in the qubit she received.
|
||||
EncodeMessageInQubit_Reference(q1, message);
|
||||
// STEP 2:
|
||||
// Alice encodes the pair of bits in the qubit she received.
|
||||
EncodeMessageInQubit_Reference(q1, message);
|
||||
|
||||
// Alice sends her qubit to Bob.
|
||||
// Alice sends her qubit to Bob.
|
||||
|
||||
// STEP 3:
|
||||
// Bob receives the qubit from Alice and can now
|
||||
// manipulate and measure both qubits to get the encoded data.
|
||||
return DecodeMessageFromQubits_Reference(q1, q2);
|
||||
}
|
||||
// STEP 3:
|
||||
// Bob receives the qubit from Alice and can now
|
||||
// manipulate and measure both qubits to get the encoded data.
|
||||
return DecodeMessageFromQubits_Reference(q1, q2);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,17 +16,16 @@ namespace Quantum.Kata.SuperdenseCoding {
|
|||
// ------------------------------------------------------
|
||||
@Test("QuantumSimulator")
|
||||
operation T1_CreateEntangledPair () : Unit {
|
||||
using ((q1, q2) = (Qubit(), Qubit())) {
|
||||
use (q1, q2) = (Qubit(), Qubit());
|
||||
|
||||
// apply operation that needs to be tested
|
||||
CreateEntangledPair(q1, q2);
|
||||
// apply operation that needs to be tested
|
||||
CreateEntangledPair(q1, q2);
|
||||
|
||||
// apply adjoint reference operation and check that the result is |0^N⟩
|
||||
Adjoint CreateEntangledPair_Reference(q1, q2);
|
||||
// apply adjoint reference operation and check that the result is |0^N⟩
|
||||
Adjoint CreateEntangledPair_Reference(q1, q2);
|
||||
|
||||
// assert that all qubits end up in |0⟩ state
|
||||
AssertAllZero([q1, q2]);
|
||||
}
|
||||
// assert that all qubits end up in |0⟩ state
|
||||
AssertAllZero([q1, q2]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -39,11 +38,10 @@ namespace Quantum.Kata.SuperdenseCoding {
|
|||
message : ProtocolMessage
|
||||
) : ProtocolMessage {
|
||||
|
||||
using (qs = Qubit[2]) {
|
||||
CreateEntangledPair_Reference(qs[0], qs[1]);
|
||||
encodeOp(qs[0], message);
|
||||
return decodeOp(qs[0], qs[1]);
|
||||
}
|
||||
use qs = Qubit[2];
|
||||
CreateEntangledPair_Reference(qs[0], qs[1]);
|
||||
encodeOp(qs[0], message);
|
||||
return decodeOp(qs[0], qs[1]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -53,10 +51,10 @@ namespace Quantum.Kata.SuperdenseCoding {
|
|||
operation TestProtocol (protocolOp : (ProtocolMessage => ProtocolMessage)) : Unit {
|
||||
|
||||
// Loop over the 4 possible combinations of two bits
|
||||
for (n in 0 .. 3) {
|
||||
for n in 0 .. 3 {
|
||||
let data = ProtocolMessage(1 == n / 2, 1 == n % 2);
|
||||
|
||||
for (iter in 1 .. 100) {
|
||||
for iter in 1 .. 100 {
|
||||
let result = protocolOp(data);
|
||||
|
||||
// Now test if the bits were transfered correctly.
|
||||
|
|
|
@ -56,16 +56,15 @@ 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) {
|
||||
using (message = Qubit()) {
|
||||
if (state) {
|
||||
X(message);
|
||||
}
|
||||
|
||||
PrepareQubit(basis, message);
|
||||
let classicalBits = SendMessage_Reference(qAlice, message);
|
||||
Reset(message);
|
||||
return classicalBits;
|
||||
use message = Qubit();
|
||||
if (state) {
|
||||
X(message);
|
||||
}
|
||||
|
||||
PreparePauliEigenstate(basis, message);
|
||||
let classicalBits = SendMessage_Reference(qAlice, message);
|
||||
Reset(message);
|
||||
return classicalBits;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -17,16 +17,15 @@ namespace Quantum.Kata.Teleportation {
|
|||
// ------------------------------------------------------
|
||||
@Test("QuantumSimulator")
|
||||
operation T11_Entangle () : Unit {
|
||||
using ((q0, q1) = (Qubit(), Qubit())) {
|
||||
// Apply operation that needs to be tested
|
||||
Entangle(q0, q1);
|
||||
use (q0, q1) = (Qubit(), Qubit());
|
||||
// Apply operation that needs to be tested
|
||||
Entangle(q0, q1);
|
||||
|
||||
// Apply adjoint reference operation and check that the result is |00⟩
|
||||
Adjoint Entangle_Reference(q0, q1);
|
||||
// Apply adjoint reference operation and check that the result is |00⟩
|
||||
Adjoint Entangle_Reference(q0, q1);
|
||||
|
||||
// Assert that all qubits end up in |0⟩ state
|
||||
AssertAllZero([q0, q1]);
|
||||
}
|
||||
// Assert that all qubits end up in |0⟩ state
|
||||
AssertAllZero([q0, q1]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -82,19 +81,18 @@ namespace Quantum.Kata.Teleportation {
|
|||
teleportOp : ((Qubit, Qubit, Qubit) => Unit),
|
||||
setupPsiOp : (Qubit => Unit is Adj)) : Unit {
|
||||
|
||||
using ((qMessage, qAlice, qBob) = (Qubit(), Qubit(), Qubit())) {
|
||||
setupPsiOp(qMessage);
|
||||
use (qMessage, qAlice, qBob) = (Qubit(), Qubit(), Qubit());
|
||||
setupPsiOp(qMessage);
|
||||
|
||||
// This should modify qBob to be identical to the state
|
||||
// of qMessage before the function call.
|
||||
teleportOp(qAlice, qBob, qMessage);
|
||||
// This should modify qBob to be identical to the state
|
||||
// of qMessage before the function call.
|
||||
teleportOp(qAlice, qBob, qMessage);
|
||||
|
||||
// Applying the inverse of the setup operation to qBob
|
||||
// should make it Zero.
|
||||
Adjoint setupPsiOp(qBob);
|
||||
AssertQubit(Zero, qBob);
|
||||
ResetAll([qMessage, qAlice, qBob]);
|
||||
}
|
||||
// Applying the inverse of the setup operation to qBob
|
||||
// should make it Zero.
|
||||
Adjoint setupPsiOp(qBob);
|
||||
AssertQubit(Zero, qBob);
|
||||
ResetAll([qMessage, qAlice, qBob]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -114,8 +112,8 @@ namespace Quantum.Kata.Teleportation {
|
|||
// Depending on the outcomes different paths are taken on Bob's side.
|
||||
// We repeat each test run several times to ensure that all paths are checked.
|
||||
let numRepetitions = 100;
|
||||
for (psiOp in setupPsiOps) {
|
||||
for (j in 1 .. numRepetitions) {
|
||||
for psiOp in setupPsiOps {
|
||||
for j in 1 .. numRepetitions {
|
||||
TeleportTestHelper(teleportOp, psiOp);
|
||||
}
|
||||
}
|
||||
|
@ -163,15 +161,14 @@ namespace Quantum.Kata.Teleportation {
|
|||
(PauliZ, true)];
|
||||
let numRepetitions = 100;
|
||||
|
||||
using ((qAlice, qBob) = (Qubit(), Qubit())) {
|
||||
for ( (basis, sentState) in messages) {
|
||||
for (j in 1 .. numRepetitions) {
|
||||
StatePrep_BellState(qAlice, qBob, 0);
|
||||
let classicalBits = prepareAndSendMessageOp(qAlice, basis, sentState);
|
||||
let receivedState = reconstructAndMeasureMessageOp(qBob, classicalBits, basis);
|
||||
EqualityFactB(receivedState, sentState, $"Sent and received states were not equal for {sentState} eigenstate in {basis} basis.");
|
||||
ResetAll([qAlice, qBob]);
|
||||
}
|
||||
use (qAlice, qBob) = (Qubit(), Qubit());
|
||||
for (basis, sentState) in messages {
|
||||
for j in 1 .. numRepetitions {
|
||||
StatePrep_BellState(qAlice, qBob, 0);
|
||||
let classicalBits = prepareAndSendMessageOp(qAlice, basis, sentState);
|
||||
let receivedState = reconstructAndMeasureMessageOp(qBob, classicalBits, basis);
|
||||
EqualityFactB(receivedState, sentState, $"Sent and received states were not equal for {sentState} eigenstate in {basis} basis.");
|
||||
ResetAll([qAlice, qBob]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -220,16 +217,15 @@ namespace Quantum.Kata.Teleportation {
|
|||
let setupPsiOps = [I, X, H, Ry(42.0, _)];
|
||||
let numRepetitions = 100;
|
||||
|
||||
using ((qMessage, qAlice, qBob) = (Qubit(), Qubit(), Qubit())) {
|
||||
for (psiOp in setupPsiOps) {
|
||||
for (j in 1 .. numRepetitions) {
|
||||
psiOp(qMessage);
|
||||
StatePrep_BellState(qAlice, qBob, 0);
|
||||
MeasurementFreeTeleport(qAlice, qBob, qMessage);
|
||||
Adjoint psiOp(qBob);
|
||||
AssertQubit(Zero, qBob);
|
||||
ResetAll([qMessage, qAlice, qBob]);
|
||||
}
|
||||
use (qMessage, qAlice, qBob) = (Qubit(), Qubit(), Qubit());
|
||||
for psiOp in setupPsiOps {
|
||||
for j in 1 .. numRepetitions {
|
||||
psiOp(qMessage);
|
||||
StatePrep_BellState(qAlice, qBob, 0);
|
||||
MeasurementFreeTeleport(qAlice, qBob, qMessage);
|
||||
Adjoint psiOp(qBob);
|
||||
AssertQubit(Zero, qBob);
|
||||
ResetAll([qMessage, qAlice, qBob]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -239,16 +235,15 @@ namespace Quantum.Kata.Teleportation {
|
|||
@Test("QuantumSimulator")
|
||||
operation T41_EntangleThreeQubits () : Unit {
|
||||
|
||||
using ((qAlice, qBob, qCharlie) = (Qubit(), Qubit(), Qubit())) {
|
||||
// Apply operation that needs to be tested
|
||||
EntangleThreeQubits(qAlice, qBob, qCharlie);
|
||||
use (qAlice, qBob, qCharlie) = (Qubit(), Qubit(), Qubit());
|
||||
// Apply operation that needs to be tested
|
||||
EntangleThreeQubits(qAlice, qBob, qCharlie);
|
||||
|
||||
// Apply adjoint reference operation and check that the result is |000⟩
|
||||
Adjoint EntangleThreeQubits_Reference(qAlice, qBob, qCharlie);
|
||||
// Apply adjoint reference operation and check that the result is |000⟩
|
||||
Adjoint EntangleThreeQubits_Reference(qAlice, qBob, qCharlie);
|
||||
|
||||
// Assert that all qubits end up in |0⟩ state
|
||||
AssertAllZero([qAlice, qBob, qCharlie]);
|
||||
}
|
||||
// Assert that all qubits end up in |0⟩ state
|
||||
AssertAllZero([qAlice, qBob, qCharlie]);
|
||||
}
|
||||
|
||||
@Test("QuantumSimulator")
|
||||
|
@ -257,18 +252,17 @@ namespace Quantum.Kata.Teleportation {
|
|||
let setupPsiOps = [I, X, H, Ry(42.0, _)];
|
||||
let numRepetitions = 100;
|
||||
|
||||
using ((qMessage, qAlice, qBob, qCharlie) = (Qubit(), Qubit(), Qubit(), Qubit())) {
|
||||
for (psiOp in setupPsiOps) {
|
||||
for (j in 1 .. numRepetitions) {
|
||||
psiOp(qMessage);
|
||||
EntangleThreeQubits_Reference(qAlice, qBob, qCharlie);
|
||||
let (b1, b2) = SendMessage_Reference(qAlice, qMessage);
|
||||
let b3 = ResultAsBool(M(qBob));
|
||||
ReconstructMessageWhenThreeEntangledQubits(qCharlie, (b1, b2), b3);
|
||||
Adjoint psiOp(qCharlie);
|
||||
AssertQubit(Zero, qCharlie);
|
||||
ResetAll([qMessage, qAlice, qBob, qCharlie]);
|
||||
}
|
||||
use (qMessage, qAlice, qBob, qCharlie) = (Qubit(), Qubit(), Qubit(), Qubit());
|
||||
for psiOp in setupPsiOps {
|
||||
for j in 1 .. numRepetitions {
|
||||
psiOp(qMessage);
|
||||
EntangleThreeQubits_Reference(qAlice, qBob, qCharlie);
|
||||
let (b1, b2) = SendMessage_Reference(qAlice, qMessage);
|
||||
let b3 = ResultAsBool(M(qBob));
|
||||
ReconstructMessageWhenThreeEntangledQubits(qCharlie, (b1, b2), b3);
|
||||
Adjoint psiOp(qCharlie);
|
||||
AssertQubit(Zero, qCharlie);
|
||||
ResetAll([qMessage, qAlice, qBob, qCharlie]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ namespace Quantum.Kata.TruthTables {
|
|||
|
||||
// Task 10. Apply truth table as a quantum operation
|
||||
operation ApplyXControlledOnFunction_Reference (tt : TruthTable, controls : Qubit[], target : Qubit) : Unit is Adj {
|
||||
for (i in AllMinterms_Reference(tt)) {
|
||||
for i in AllMinterms_Reference(tt) {
|
||||
(ControlledOnInt(i, X))(controls, target);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ namespace Quantum.Kata.TruthTables {
|
|||
Message($"Testing on truth table {testTT}");
|
||||
let minterms = AllMinterms(testTT);
|
||||
EqualityFactI(Length(minterms), 4, "Number of minterms is not correct");
|
||||
for (minterm in [3, 4, 6, 7]) {
|
||||
for minterm in [3, 4, 6, 7] {
|
||||
Fact(IndexOf(EqualI(minterm, _), minterms) != -1, $"Minterm {minterm} should be part of the result");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ namespace Quantum.Kata.UnitaryPatterns {
|
|||
// Task 8. 2⨯2 chessboard pattern
|
||||
operation ChessPattern2x2_Reference (qs : Qubit[]) : Unit {
|
||||
H(Head(qs));
|
||||
for (i in 2 .. Length(qs) - 1) {
|
||||
for i in 2 .. Length(qs) - 1 {
|
||||
H(qs[i]);
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ namespace Quantum.Kata.UnitaryPatterns {
|
|||
// Helper operation: decrement a little-endian register
|
||||
operation Decrement (qs : Qubit[]) : Unit {
|
||||
X(qs[0]);
|
||||
for (i in 1..Length(qs)-1) {
|
||||
for i in 1..Length(qs)-1 {
|
||||
Controlled X(qs[...i-1], qs[i]);
|
||||
}
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ namespace Quantum.Kata.UnitaryPatterns {
|
|||
|
||||
// Helper function for Embedding_Perm: finds first location where bit strings differ.
|
||||
function FirstDiff (bits1 : Bool[], bits2 : Bool[]) : Int {
|
||||
for (i in 0 .. Length(bits1)-1) {
|
||||
for i in 0 .. Length(bits1)-1 {
|
||||
if (bits1[i] != bits2[i]) {
|
||||
return i;
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ namespace Quantum.Kata.UnitaryPatterns {
|
|||
}
|
||||
|
||||
// iterate through the bit strings again, setting the final state of qubits
|
||||
for (i in 0..n-1) {
|
||||
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]) {
|
||||
|
@ -216,7 +216,7 @@ namespace Quantum.Kata.UnitaryPatterns {
|
|||
// 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,35 +29,34 @@ namespace Quantum.Kata.UnitaryPatterns {
|
|||
// ε is the threshold for probability, which is absolute value squared; the absolute value is bounded by √ε.
|
||||
let ε = 0.000001;
|
||||
|
||||
using (qs = Qubit[N]) {
|
||||
for (k in 0 .. size - 1) {
|
||||
// Prepare k-th basis vector
|
||||
let binary = IntAsBoolArray(k, N);
|
||||
use qs = Qubit[N];
|
||||
for k in 0 .. size - 1 {
|
||||
// Prepare k-th basis vector
|
||||
let binary = IntAsBoolArray(k, N);
|
||||
|
||||
//Message($"{k}/{N} = {binary}");
|
||||
// binary is little-endian notation, so the second vector tried has qubit 0 in state 1 and the rest in state 0
|
||||
ApplyPauliFromBitString(PauliX, true, binary, qs);
|
||||
//Message($"{k}/{N} = {binary}");
|
||||
// binary is little-endian notation, so the second vector tried has qubit 0 in state 1 and the rest in state 0
|
||||
ApplyPauliFromBitString(PauliX, true, binary, qs);
|
||||
|
||||
// Reset the counter of measurements done outside of the solution call
|
||||
ResetOracleCallsCount();
|
||||
// Reset the counter of measurements done outside of the solution call
|
||||
ResetOracleCallsCount();
|
||||
|
||||
// Apply the operation
|
||||
op(qs);
|
||||
// Apply the operation
|
||||
op(qs);
|
||||
|
||||
// Make sure the solution didn't use any measurements
|
||||
Fact(GetOracleCallsCount(Measure) == 0, "You are not allowed to use measurements in this task");
|
||||
// Make sure the solution didn't use any measurements
|
||||
Fact(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);
|
||||
// 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);
|
||||
|
||||
let (expected, tol) = nonZero ? (0.5 + ε, 0.5) | (0.0, ε);
|
||||
AssertProbInt(j, expected, LittleEndian(qs), tol);
|
||||
}
|
||||
|
||||
ResetAll(qs);
|
||||
let (expected, tol) = nonZero ? (0.5 + ε, 0.5) | (0.0, ε);
|
||||
AssertProbInt(j, expected, LittleEndian(qs), tol);
|
||||
}
|
||||
|
||||
ResetAll(qs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,7 +68,7 @@ namespace Quantum.Kata.UnitaryPatterns {
|
|||
|
||||
@Test("Microsoft.Quantum.Katas.CounterSimulator")
|
||||
operation T01_MainDiagonal () : Unit {
|
||||
for (n in 2 .. 5) {
|
||||
for n in 2 .. 5 {
|
||||
AssertOperationMatrixMatchesPattern(n, MainDiagonal, MainDiagonal_Pattern);
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +81,7 @@ namespace Quantum.Kata.UnitaryPatterns {
|
|||
|
||||
@Test("Microsoft.Quantum.Katas.CounterSimulator")
|
||||
operation T02_AllNonZero () : Unit {
|
||||
for (n in 2 .. 5) {
|
||||
for n in 2 .. 5 {
|
||||
AssertOperationMatrixMatchesPattern(n, AllNonZero, AllNonZero_Pattern);
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +94,7 @@ namespace Quantum.Kata.UnitaryPatterns {
|
|||
|
||||
@Test("Microsoft.Quantum.Katas.CounterSimulator")
|
||||
operation T03_BlockDiagonal () : Unit {
|
||||
for (n in 2 .. 5) {
|
||||
for n in 2 .. 5 {
|
||||
AssertOperationMatrixMatchesPattern(n, BlockDiagonal, BlockDiagonal_Pattern);
|
||||
}
|
||||
}
|
||||
|
@ -111,7 +110,7 @@ namespace Quantum.Kata.UnitaryPatterns {
|
|||
|
||||
@Test("Microsoft.Quantum.Katas.CounterSimulator")
|
||||
operation T04_Quarters () : Unit {
|
||||
for (n in 2 .. 5) {
|
||||
for n in 2 .. 5 {
|
||||
AssertOperationMatrixMatchesPattern(n, Quarters, Quarters_Pattern);
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +126,7 @@ namespace Quantum.Kata.UnitaryPatterns {
|
|||
|
||||
@Test("Microsoft.Quantum.Katas.CounterSimulator")
|
||||
operation T05_EvenChessPattern () : Unit {
|
||||
for (n in 2 .. 5) {
|
||||
for n in 2 .. 5 {
|
||||
AssertOperationMatrixMatchesPattern(n, EvenChessPattern, EvenChessPattern_Pattern);
|
||||
}
|
||||
}
|
||||
|
@ -143,7 +142,7 @@ namespace Quantum.Kata.UnitaryPatterns {
|
|||
|
||||
@Test("Microsoft.Quantum.Katas.CounterSimulator")
|
||||
operation T06_OddChessPattern () : Unit {
|
||||
for (n in 2 .. 5) {
|
||||
for n in 2 .. 5 {
|
||||
AssertOperationMatrixMatchesPattern(n, OddChessPattern, OddChessPattern_Pattern);
|
||||
}
|
||||
}
|
||||
|
@ -156,7 +155,7 @@ namespace Quantum.Kata.UnitaryPatterns {
|
|||
|
||||
@Test("Microsoft.Quantum.Katas.CounterSimulator")
|
||||
operation T07_Antidiagonal () : Unit {
|
||||
for (n in 2 .. 5) {
|
||||
for n in 2 .. 5 {
|
||||
AssertOperationMatrixMatchesPattern(n, Antidiagonal, Antidiagonal_Pattern);
|
||||
}
|
||||
}
|
||||
|
@ -169,7 +168,7 @@ namespace Quantum.Kata.UnitaryPatterns {
|
|||
|
||||
@Test("Microsoft.Quantum.Katas.CounterSimulator")
|
||||
operation T08_ChessPattern2x2 () : Unit {
|
||||
for (n in 2 .. 5) {
|
||||
for n in 2 .. 5 {
|
||||
AssertOperationMatrixMatchesPattern(n, ChessPattern2x2, ChessPattern2x2_Pattern);
|
||||
}
|
||||
}
|
||||
|
@ -192,7 +191,7 @@ namespace Quantum.Kata.UnitaryPatterns {
|
|||
|
||||
@Test("Microsoft.Quantum.Katas.CounterSimulator")
|
||||
operation T09_TwoPatterns () : Unit {
|
||||
for (n in 2 .. 5) {
|
||||
for n in 2 .. 5 {
|
||||
AssertOperationMatrixMatchesPattern(n, TwoPatterns, TwoPatterns_Pattern);
|
||||
}
|
||||
}
|
||||
|
@ -218,7 +217,7 @@ namespace Quantum.Kata.UnitaryPatterns {
|
|||
|
||||
@Test("Microsoft.Quantum.Katas.CounterSimulator")
|
||||
operation T10_IncreasingBlocks () : Unit {
|
||||
for (n in 2 .. 5) {
|
||||
for n in 2 .. 5 {
|
||||
AssertOperationMatrixMatchesPattern(n, IncreasingBlocks, IncreasingBlocks_Pattern);
|
||||
}
|
||||
}
|
||||
|
@ -231,7 +230,7 @@ namespace Quantum.Kata.UnitaryPatterns {
|
|||
|
||||
@Test("Microsoft.Quantum.Katas.CounterSimulator")
|
||||
operation T11_XWing_Fighter () : Unit {
|
||||
for (n in 2 .. 5) {
|
||||
for n in 2 .. 5 {
|
||||
AssertOperationMatrixMatchesPattern(n, XWing_Fighter, XWing_Fighter_Pattern);
|
||||
}
|
||||
}
|
||||
|
@ -246,7 +245,7 @@ namespace Quantum.Kata.UnitaryPatterns {
|
|||
|
||||
@Test("Microsoft.Quantum.Katas.CounterSimulator")
|
||||
operation T12_Rhombus () : Unit {
|
||||
for (n in 2 .. 5) {
|
||||
for n in 2 .. 5 {
|
||||
AssertOperationMatrixMatchesPattern(n, Rhombus, Rhombus_Pattern);
|
||||
}
|
||||
}
|
||||
|
@ -264,7 +263,7 @@ namespace Quantum.Kata.UnitaryPatterns {
|
|||
|
||||
@Test("Microsoft.Quantum.Katas.CounterSimulator")
|
||||
operation T13_TIE_Fighter () : Unit {
|
||||
for (n in 2 .. 5) {
|
||||
for n in 2 .. 5 {
|
||||
AssertOperationMatrixMatchesPattern(n, TIE_Fighter, TIE_Fighter_Pattern);
|
||||
}
|
||||
}
|
||||
|
@ -295,7 +294,7 @@ namespace Quantum.Kata.UnitaryPatterns {
|
|||
|
||||
@Test("Microsoft.Quantum.Katas.CounterSimulator")
|
||||
operation T15_Hessenberg_Matrix () : Unit {
|
||||
for (n in 2 .. 4) {
|
||||
for n in 2 .. 4 {
|
||||
AssertOperationMatrixMatchesPattern(n, Hessenberg_Matrix, Hessenberg_Matrix_Pattern);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -704,7 +704,7 @@
|
|||
"\n",
|
||||
"operation IncreasingBlocks (qs : Qubit[]) : Unit is Adj + Ctl {\n",
|
||||
" let N = Length(qs);\n",
|
||||
" if (N == 1) {\n",
|
||||
" if N == 1 {\n",
|
||||
" // for N = 1, we need an identity, which is equivalent to doing nothing\n",
|
||||
" } else {\n",
|
||||
" // Apply H to get bottom-right quarter right\n",
|
||||
|
@ -1085,7 +1085,7 @@
|
|||
" X(qs[n-1]);\n",
|
||||
" // decrement operation\n",
|
||||
" X(qs[0]);\n",
|
||||
" for (i in 1..Length(qs)-2) {\n",
|
||||
" for i in 1..Length(qs)-2 {\n",
|
||||
" Controlled X (qs[0..i-1], qs[i]);\n",
|
||||
" }\n",
|
||||
" H(qs[n-1]);\n",
|
||||
|
@ -1420,7 +1420,7 @@
|
|||
" X(qs[diff]);\n",
|
||||
" }\n",
|
||||
" // iterate through the bit strings again, setting the final state of qubits\n",
|
||||
" for (i in 0 .. n-1) {\n",
|
||||
" for i in 0 .. n-1 {\n",
|
||||
" if (bits1[i] == bits2[i]) { // if two bits are the same, set both to 1 using X or nothing\n",
|
||||
" if (not bits1[i]) {\n",
|
||||
" X(qs[i]);\n",
|
||||
|
@ -1456,7 +1456,7 @@
|
|||
"\n",
|
||||
"operation Hessenberg_Matrix (qs : Qubit[]) : Unit {\n",
|
||||
" let n = Length(qs);\n",
|
||||
" for (i in 2^n - 2 .. -1 .. 0){\n",
|
||||
" for i in 2^n - 2 .. -1 .. 0{\n",
|
||||
" RotateToEnd(i, qs);\n",
|
||||
" (Controlled H)(Most(qs), Tail(qs));\n",
|
||||
" (Adjoint RotateToEnd)(i, qs);\n",
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Quantum.Kata.ExploringGroversAlgorithm
|
|||
function GetClauseQubits (queryRegister : Qubit[], clause : (Int, Bool)[]) : (Qubit[], Bool[]) {
|
||||
mutable clauseQubits = new Qubit[Length(clause)];
|
||||
mutable flip = new Bool[Length(clause)];
|
||||
for (varIndex in 0 .. Length(clause) - 1) {
|
||||
for varIndex in 0 .. Length(clause) - 1 {
|
||||
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];
|
||||
|
@ -60,7 +60,7 @@ namespace Quantum.Kata.ExploringGroversAlgorithm
|
|||
operation EvaluateOrClauses (queryRegister : Qubit[],
|
||||
ancillaRegister : Qubit[],
|
||||
problem : (Int, Bool)[][]) : Unit is Adj {
|
||||
for (clauseIndex in 0..Length(problem)-1) {
|
||||
for clauseIndex in 0..Length(problem)-1 {
|
||||
Oracle_SATClause(queryRegister, ancillaRegister[clauseIndex], problem[clauseIndex]);
|
||||
}
|
||||
}
|
||||
|
@ -72,14 +72,13 @@ namespace Quantum.Kata.ExploringGroversAlgorithm
|
|||
target : Qubit,
|
||||
problem : (Int, Bool)[][]) : Unit is Adj {
|
||||
// Allocate qubits to store results of clauses evaluation
|
||||
using (ancillaRegister = Qubit[Length(problem)]) {
|
||||
// Compute clauses, evaluate the overall formula as an AND oracle (can use reference depending on the implementation) and uncompute
|
||||
within {
|
||||
EvaluateOrClauses(queryRegister, ancillaRegister, problem);
|
||||
}
|
||||
apply {
|
||||
Controlled X(ancillaRegister, target);
|
||||
}
|
||||
use ancillaRegister = Qubit[Length(problem)];
|
||||
// Compute clauses, evaluate the overall formula as an AND oracle (can use reference depending on the implementation) and uncompute
|
||||
within {
|
||||
EvaluateOrClauses(queryRegister, ancillaRegister, problem);
|
||||
}
|
||||
apply {
|
||||
Controlled X(ancillaRegister, target);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,18 +95,17 @@ namespace Quantum.Kata.ExploringGroversAlgorithm
|
|||
|
||||
// Helper operation which converts marking oracle into phase oracle using an extra qubit
|
||||
operation ApplyMarkingOracleAsPhaseOracle (markingOracle : ((Qubit[], Qubit) => Unit is Adj), register : Qubit[]) : Unit is Adj {
|
||||
using (target = Qubit()) {
|
||||
// Put the target into the |-⟩ state and later back to |0⟩ so we can return it
|
||||
within{
|
||||
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
|
||||
apply{
|
||||
markingOracle(register, target);
|
||||
}
|
||||
use target = Qubit();
|
||||
// Put the target into the |-⟩ state and later back to |0⟩ so we can return it
|
||||
within {
|
||||
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
|
||||
apply {
|
||||
markingOracle(register, target);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -116,15 +114,15 @@ namespace Quantum.Kata.ExploringGroversAlgorithm
|
|||
operation GroversAlgorithm_Loop (register : Qubit[], oracle : ((Qubit[], Qubit) => Unit is Adj), iterations : Int) : Unit {
|
||||
ApplyToEach(H, register);
|
||||
|
||||
for (i in 1 .. iterations) {
|
||||
for _ in 1 .. iterations {
|
||||
// apply oracle
|
||||
ApplyMarkingOracleAsPhaseOracle(oracle, register);
|
||||
// apply inversion about the mean
|
||||
within{
|
||||
within {
|
||||
ApplyToEachA(H, register);
|
||||
ApplyToEachA(X, register);
|
||||
}
|
||||
apply{
|
||||
apply {
|
||||
Controlled Z(Most(register), Tail(register));
|
||||
}
|
||||
}
|
||||
|
@ -143,7 +141,7 @@ namespace Quantum.Kata.ExploringGroversAlgorithm
|
|||
|
||||
function SATClauseAsString (clause : (Int, Bool)[]) : String {
|
||||
mutable ret = SATVariableAsString(clause[0]);
|
||||
for (ind in 1 .. Length(clause) - 1) {
|
||||
for ind in 1 .. Length(clause) - 1 {
|
||||
set ret = ret + " ∨ " + SATVariableAsString(clause[ind]);
|
||||
}
|
||||
return ret;
|
||||
|
@ -151,7 +149,7 @@ namespace Quantum.Kata.ExploringGroversAlgorithm
|
|||
|
||||
function SATInstanceAsString (instance : (Int, Bool)[][]) : String {
|
||||
mutable ret = "(" + SATClauseAsString(instance[0]) + ")";
|
||||
for (ind in 1 .. Length(instance) - 1) {
|
||||
for ind in 1 .. Length(instance) - 1 {
|
||||
set ret = ret + " ∧ (" + SATClauseAsString(instance[ind]) + ")";
|
||||
}
|
||||
return ret;
|
||||
|
@ -159,7 +157,7 @@ namespace Quantum.Kata.ExploringGroversAlgorithm
|
|||
|
||||
function VariableAssignmentAsString (variables : Bool[]) : String {
|
||||
mutable ret = $"x0 = {variables[0]}";
|
||||
for (ind in 1 .. Length(variables) - 1) {
|
||||
for ind in 1 .. Length(variables) - 1 {
|
||||
set ret = ret + $", x{ind} = {variables[ind]}";
|
||||
}
|
||||
return ret;
|
||||
|
@ -175,16 +173,15 @@ namespace Quantum.Kata.ExploringGroversAlgorithm
|
|||
let oracle = Oracle_SAT(_, _, instance);
|
||||
|
||||
mutable correct = 0;
|
||||
using ((register, answer) = (Qubit[N], Qubit())) {
|
||||
for (run in 1..100) {
|
||||
GroversAlgorithm_Loop(register, oracle, iter);
|
||||
let res = MultiM(register);
|
||||
oracle(register, answer);
|
||||
if (MResetZ(answer) == One) {
|
||||
set correct += 1;
|
||||
}
|
||||
ResetAll(register);
|
||||
use (register, answer) = (Qubit[N], Qubit());
|
||||
for run in 1 .. 100 {
|
||||
GroversAlgorithm_Loop(register, oracle, iter);
|
||||
let res = MultiM(register);
|
||||
oracle(register, answer);
|
||||
if (MResetZ(answer) == One) {
|
||||
set correct += 1;
|
||||
}
|
||||
ResetAll(register);
|
||||
}
|
||||
|
||||
return IntAsDouble(correct) / 100.0;
|
||||
|
@ -193,7 +190,7 @@ namespace Quantum.Kata.ExploringGroversAlgorithm
|
|||
// ---------------------------------------------------------------------------------------------
|
||||
operation Oracle_SolutionCount (queryRegister : Qubit[], target : Qubit, nSol : Int) : Unit is Adj {
|
||||
// Designate first nSol integers solutions (since we don't really care which ones are solutions)
|
||||
for (i in 0 .. nSol - 1) {
|
||||
for i in 0 .. nSol - 1 {
|
||||
(ControlledOnInt(i, X))(queryRegister, target);
|
||||
}
|
||||
}
|
||||
|
@ -204,16 +201,15 @@ namespace Quantum.Kata.ExploringGroversAlgorithm
|
|||
let oracle = Oracle_SolutionCount(_, _, nSol);
|
||||
|
||||
mutable correct = 0;
|
||||
using ((register, answer) = (Qubit[nQubit], Qubit())) {
|
||||
for (run in 1..100) {
|
||||
GroversAlgorithm_Loop(register, oracle, iter);
|
||||
let res = MultiM(register);
|
||||
oracle(register, answer);
|
||||
if (MResetZ(answer) == One) {
|
||||
set correct += 1;
|
||||
}
|
||||
ResetAll(register);
|
||||
use (register, answer) = (Qubit[nQubit], Qubit());
|
||||
for run in 1 .. 100 {
|
||||
GroversAlgorithm_Loop(register, oracle, iter);
|
||||
let res = MultiM(register);
|
||||
oracle(register, answer);
|
||||
if (MResetZ(answer) == One) {
|
||||
set correct += 1;
|
||||
}
|
||||
ResetAll(register);
|
||||
}
|
||||
|
||||
return IntAsDouble(correct) / 100.0;
|
||||
|
|
|
@ -198,21 +198,20 @@
|
|||
" let iterationCount = 1;\n",
|
||||
" \n",
|
||||
" // Allocate the qubits for running the algorithm\n",
|
||||
" using (register = Qubit[variableCount]) {\n",
|
||||
" // Run the iterations using a pre-written operation\n",
|
||||
" GroversAlgorithm_Loop(register, oracle, iterationCount);\n",
|
||||
" \n",
|
||||
" // Perform measurements to get the variables assignment.\n",
|
||||
" // \"MultiM\" operation measures all qubits and returns an array of measurement results, and\n",
|
||||
" // \"ResultArrayAsBoolArray\" converts it to an array of boolean variables.\n",
|
||||
" let assignment = ResultArrayAsBoolArray(MultiM(register));\n",
|
||||
" \n",
|
||||
" // Output the results\n",
|
||||
" Message($\"{VariableAssignmentAsString(assignment)}\");\n",
|
||||
" use register = Qubit[variableCount];\n",
|
||||
" // Run the iterations using a pre-written operation\n",
|
||||
" GroversAlgorithm_Loop(register, oracle, iterationCount);\n",
|
||||
"\n",
|
||||
" // Reset the qubits before releasing them, otherwise you'll get a ReleasedQubitsAreNotInZeroState exception\n",
|
||||
" ResetAll(register);\n",
|
||||
" }\n",
|
||||
" // Perform measurements to get the variables assignment.\n",
|
||||
" // \"MultiM\" operation measures all qubits and returns an array of measurement results, and\n",
|
||||
" // \"ResultArrayAsBoolArray\" converts it to an array of boolean variables.\n",
|
||||
" let assignment = ResultArrayAsBoolArray(MultiM(register));\n",
|
||||
"\n",
|
||||
" // Output the results\n",
|
||||
" Message($\"{VariableAssignmentAsString(assignment)}\");\n",
|
||||
"\n",
|
||||
" // Reset the qubits before releasing them, otherwise you'll get a ReleasedQubitsAreNotInZeroState exception\n",
|
||||
" ResetAll(register);\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
|
@ -291,37 +290,35 @@
|
|||
" let oracle = CreateOracleForSATInstance(problem);\n",
|
||||
" let iterationCount = 1;\n",
|
||||
" \n",
|
||||
" using (register = Qubit[variableCount]) {\n",
|
||||
" GroversAlgorithm_Loop(register, oracle, iterationCount);\n",
|
||||
" let assignment = ResultArrayAsBoolArray(MultiM(register));\n",
|
||||
" Message($\"{VariableAssignmentAsString(assignment)}\");\n",
|
||||
" use register = Qubit[variableCount];\n",
|
||||
" GroversAlgorithm_Loop(register, oracle, iterationCount);\n",
|
||||
" let assignment = ResultArrayAsBoolArray(MultiM(register));\n",
|
||||
" Message($\"{VariableAssignmentAsString(assignment)}\");\n",
|
||||
"\n",
|
||||
" // ========================== Check that the answer is correct. ==========================\n",
|
||||
" \n",
|
||||
" // Allocate another qubit to keep the result of evaluating the function. \n",
|
||||
" // You can allocate a single qubit with the following syntax in using statement: <variable name> = Qubit()\n",
|
||||
" using (...) {\n",
|
||||
" // After measuring \"register\" on line 17, the qubits in \"register\" end up \n",
|
||||
" // in the state that encodes the answer produced by the algorithm (decoded in \"assignment\" variable).\n",
|
||||
" // Call oracle with \"register\" as the first parameter (function input x) \n",
|
||||
" // and the newly allocated qubit as the second parameter (function output f(x))\n",
|
||||
" // to evaluate the function on that answer.\n",
|
||||
" ...\n",
|
||||
" \n",
|
||||
" // Measure the newly allocated qubit and check if the measurement result is Zero or One;\n",
|
||||
" // One means the algorithm returned correct answer, Zero - incorrect.\n",
|
||||
" // You can measure the qubit and reset it immediately using MResetZ operation, \n",
|
||||
" // and compare the measurement result to the constants Zero or One using \"==\" operator.\n",
|
||||
" if (...) {\n",
|
||||
" // Report the correct/incorrect result using Message function.\n",
|
||||
" Message(...);\n",
|
||||
" } else {\n",
|
||||
" Message(...);\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" // ========================== Check that the answer is correct. ==========================\n",
|
||||
"\n",
|
||||
" ResetAll(register);\n",
|
||||
" // Allocate another qubit to keep the result of evaluating the function. \n",
|
||||
" // You can allocate a single qubit with the following syntax in using statement: <variable name> = Qubit()\n",
|
||||
" use ... \n",
|
||||
" // After measuring \"register\" on line 17, the qubits in \"register\" end up \n",
|
||||
" // in the state that encodes the answer produced by the algorithm (decoded in \"assignment\" variable).\n",
|
||||
" // Call oracle with \"register\" as the first parameter (function input x) \n",
|
||||
" // and the newly allocated qubit as the second parameter (function output f(x))\n",
|
||||
" // to evaluate the function on that answer.\n",
|
||||
" ...\n",
|
||||
"\n",
|
||||
" // Measure the newly allocated qubit and check if the measurement result is Zero or One;\n",
|
||||
" // One means the algorithm returned correct answer, Zero - incorrect.\n",
|
||||
" // You can measure the qubit and reset it immediately using MResetZ operation, \n",
|
||||
" // and compare the measurement result to the constants Zero or One using \"==\" operator.\n",
|
||||
" if (...) {\n",
|
||||
" // Report the correct/incorrect result using Message function.\n",
|
||||
" Message(...);\n",
|
||||
" } else {\n",
|
||||
" Message(...);\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" ResetAll(register);\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
|
@ -392,27 +389,26 @@
|
|||
" let oracle = CreateOracleForSATInstance(problem);\n",
|
||||
" let iterationCount = 1;\n",
|
||||
" \n",
|
||||
" using (register = Qubit[variableCount]) {\n",
|
||||
" \n",
|
||||
" // ======== Use repeat-until-success loop to re-run algorithm in case of a failure ========\n",
|
||||
" \n",
|
||||
" // Define a mutable variable to serve as the exit condition.\n",
|
||||
" mutable isAnswerCorrect = false;\n",
|
||||
" // Define a mutable variable to store the answer once you've found a correct one.\n",
|
||||
" mutable finalAnswer = [false, false];\n",
|
||||
" \n",
|
||||
" repeat {\n",
|
||||
" // Loop body: run Grover's search using \"GroversAlgorithm_Loop\",\n",
|
||||
" // measure the answer and check whether it is correct.\n",
|
||||
" // Use \"set <variable name> = <value>;\" to update mutable variables.\n",
|
||||
" ...\n",
|
||||
" use register = Qubit[variableCount];\n",
|
||||
"\n",
|
||||
" // Remember to reset the qubits in \"register\" at the end of each iteration!\n",
|
||||
" } until (isAnswerCorrect);\n",
|
||||
" \n",
|
||||
" // Output the final answer.\n",
|
||||
" Message($\"{finalAnswer}\");\n",
|
||||
" }\n",
|
||||
" // ======== Use repeat-until-success loop to re-run algorithm in case of a failure ========\n",
|
||||
"\n",
|
||||
" // Define a mutable variable to serve as the exit condition.\n",
|
||||
" mutable isAnswerCorrect = false;\n",
|
||||
" // Define a mutable variable to store the answer once you've found a correct one.\n",
|
||||
" mutable finalAnswer = [false, false];\n",
|
||||
"\n",
|
||||
" repeat {\n",
|
||||
" // Loop body: run Grover's search using \"GroversAlgorithm_Loop\",\n",
|
||||
" // measure the answer and check whether it is correct.\n",
|
||||
" // Use \"set <variable name> = <value>;\" to update mutable variables.\n",
|
||||
" ...\n",
|
||||
"\n",
|
||||
" // Remember to reset the qubits in \"register\" at the end of each iteration!\n",
|
||||
" } until (isAnswerCorrect);\n",
|
||||
"\n",
|
||||
" // Output the final answer.\n",
|
||||
" Message($\"{finalAnswer}\");\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
|
@ -510,25 +506,24 @@
|
|||
" let oracle = CreateOracleForSATInstance(problem);\n",
|
||||
" let iterationCount = 1;\n",
|
||||
" \n",
|
||||
" using (register = Qubit[variableCount]) {\n",
|
||||
" \n",
|
||||
" // ======== Use for loop to run algorithm a fixed number of times ========\n",
|
||||
" \n",
|
||||
" // Define a mutable variable to store the number of times the algorithm succeeded.\n",
|
||||
" mutable successCount = 0;\n",
|
||||
" \n",
|
||||
" for (i in 1 .. 100) {\n",
|
||||
" // Loop body: run Grover's search using \"GroversAlgorithm_Loop\",\n",
|
||||
" // measure the answer and check whether it is correct.\n",
|
||||
" // Use \"set successCount += 1;\" to increment the success counter.\n",
|
||||
" ...\n",
|
||||
" use register = Qubit[variableCount];\n",
|
||||
"\n",
|
||||
" // Remember to reset the qubits in \"register\" at the end of each iteration!\n",
|
||||
" }\n",
|
||||
" \n",
|
||||
" // Output the success probability of the algorithm.\n",
|
||||
" Message($\"The algorithm succeeds with {successCount}% probability.\");\n",
|
||||
" // ======== Use for loop to run algorithm a fixed number of times ========\n",
|
||||
"\n",
|
||||
" // Define a mutable variable to store the number of times the algorithm succeeded.\n",
|
||||
" mutable successCount = 0;\n",
|
||||
"\n",
|
||||
" for i in 1 .. 100 {\n",
|
||||
" // Loop body: run Grover's search using \"GroversAlgorithm_Loop\",\n",
|
||||
" // measure the answer and check whether it is correct.\n",
|
||||
" // Use \"set successCount += 1;\" to increment the success counter.\n",
|
||||
" ...\n",
|
||||
"\n",
|
||||
" // Remember to reset the qubits in \"register\" at the end of each iteration!\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" // Output the success probability of the algorithm.\n",
|
||||
" Message($\"The algorithm succeeds with {successCount}% probability.\");\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
|
|
|
@ -127,34 +127,32 @@
|
|||
"operation AlternatingBitPattern_PhaseOracle (x: Qubit[]) : Unit is Adj + Ctl {\n",
|
||||
" let PatternOne = ControlledOnBitString([false, true, false], Z);\n",
|
||||
" let PatternTwo = ControlledOnBitString([true, false, true], Z);\n",
|
||||
" using (q = Qubit()) {\n",
|
||||
" X(q);\n",
|
||||
" PatternOne(x, q);\n",
|
||||
" PatternTwo(x, q);\n",
|
||||
" X(q);\n",
|
||||
" }\n",
|
||||
" use q = Qubit();\n",
|
||||
" X(q);\n",
|
||||
" PatternOne(x, q);\n",
|
||||
" PatternTwo(x, q);\n",
|
||||
" X(q);\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"operation PhaseOracle_Demo() : Unit {\n",
|
||||
" // Allocate 3 qubits in the |000⟩ state\n",
|
||||
" using (q = Qubit[3]) {\n",
|
||||
" // Prepare an equal superposition of all basis states\n",
|
||||
" ApplyToEachA(H, q);\n",
|
||||
" \n",
|
||||
" // Print the current state of the system; notice the phases of each basis state\n",
|
||||
" Message(\"Starting state (equal superposition of all basis states):\");\n",
|
||||
" DumpMachine();\n",
|
||||
" \n",
|
||||
" // Apply the oracle\n",
|
||||
" AlternatingBitPattern_PhaseOracle(q);\n",
|
||||
" \n",
|
||||
" // Print the resulting state; notice which phases changed\n",
|
||||
" Message(\"State after applying the phase oracle:\");\n",
|
||||
" DumpMachine();\n",
|
||||
" \n",
|
||||
" // Reset our state back to all zeros for deallocation\n",
|
||||
" ResetAll(q);\n",
|
||||
" }\n",
|
||||
" use q = Qubit[3];\n",
|
||||
" // Prepare an equal superposition of all basis states\n",
|
||||
" ApplyToEachA(H, q);\n",
|
||||
"\n",
|
||||
" // Print the current state of the system; notice the phases of each basis state\n",
|
||||
" Message(\"Starting state (equal superposition of all basis states):\");\n",
|
||||
" DumpMachine();\n",
|
||||
"\n",
|
||||
" // Apply the oracle\n",
|
||||
" AlternatingBitPattern_PhaseOracle(q);\n",
|
||||
"\n",
|
||||
" // Print the resulting state; notice which phases changed\n",
|
||||
" Message(\"State after applying the phase oracle:\");\n",
|
||||
" DumpMachine();\n",
|
||||
"\n",
|
||||
" // Reset our state back to all zeros for deallocation\n",
|
||||
" ResetAll(q);\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
|
@ -293,26 +291,23 @@
|
|||
"\n",
|
||||
"operation MarkingOracle_Demo() : Unit {\n",
|
||||
" // Allocate the qubits in the |000⟩|0⟩ state\n",
|
||||
" using ((x, y) = (Qubit[3], Qubit())) {\n",
|
||||
" // Prepare an unequal superposition of all basis states\n",
|
||||
" //PrepareArbitraryStateD(H, q[0..Length(q)-2]);\n",
|
||||
" // Prepare an equal superposition of all basis states in the input register\n",
|
||||
" ApplyToEachA(H, x);\n",
|
||||
" \n",
|
||||
" // Print the current state of the system; notice the amplitudes of each basis state\n",
|
||||
" Message(\"Starting state (equal superposition of all basis states ⊗ |0⟩):\");\n",
|
||||
" DumpMachine();\n",
|
||||
" \n",
|
||||
" // Apply the oracle\n",
|
||||
" AlternatingBitPattern_MarkingOracle(x, y);\n",
|
||||
" \n",
|
||||
" // Print the resulting state; notice which amplitudes changed\n",
|
||||
" Message(\"State after applying the marking oracle:\");\n",
|
||||
" DumpMachine();\n",
|
||||
" \n",
|
||||
" // Reset our state back to all zeros for deallocation\n",
|
||||
" ResetAll(x + [y]);\n",
|
||||
" }\n",
|
||||
" use (x, y) = (Qubit[3], Qubit());\n",
|
||||
" // Prepare an equal superposition of all basis states in the input register\n",
|
||||
" ApplyToEachA(H, x);\n",
|
||||
"\n",
|
||||
" // Print the current state of the system; notice the amplitudes of each basis state\n",
|
||||
" Message(\"Starting state (equal superposition of all basis states ⊗ |0⟩):\");\n",
|
||||
" DumpMachine();\n",
|
||||
"\n",
|
||||
" // Apply the oracle\n",
|
||||
" AlternatingBitPattern_MarkingOracle(x, y);\n",
|
||||
"\n",
|
||||
" // Print the resulting state; notice which amplitudes changed\n",
|
||||
" Message(\"State after applying the marking oracle:\");\n",
|
||||
" DumpMachine();\n",
|
||||
"\n",
|
||||
" // Reset our state back to all zeros for deallocation\n",
|
||||
" ResetAll(x + [y]);\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
|
@ -572,36 +567,35 @@
|
|||
"\n",
|
||||
"operation OracleConverterDemo () : Unit {\n",
|
||||
" // Allocate the qubits in the state |000⟩\n",
|
||||
" using (register = Qubit[3]) {\n",
|
||||
" // Prepare an equal superposition state\n",
|
||||
" ApplyToEachA(H, register);\n",
|
||||
" \n",
|
||||
" Message(\"The equal superposition state:\");\n",
|
||||
" DumpMachine();\n",
|
||||
" \n",
|
||||
" // Apply the oracle from task 1.2\n",
|
||||
" IsSeven_PhaseOracle(register);\n",
|
||||
" \n",
|
||||
" // Dump the state after application of the oracle\n",
|
||||
" Message(\"The state after applying the phase oracle from task 1.2:\");\n",
|
||||
" DumpMachine();\n",
|
||||
" \n",
|
||||
" // Reset the qubits for deallocation\n",
|
||||
" ResetAll(register);\n",
|
||||
" \n",
|
||||
" // Prepare an equal superposition state again\n",
|
||||
" ApplyToEachA(H, register);\n",
|
||||
" use register = Qubit[3];\n",
|
||||
" // Prepare an equal superposition state\n",
|
||||
" ApplyToEachA(H, register);\n",
|
||||
"\n",
|
||||
" // Apply the marking oracle from task 1.3 as a phase oracle\n",
|
||||
" ApplyMarkingOracleAsPhaseOracle(IsSeven_MarkingOracle, register);\n",
|
||||
" \n",
|
||||
" // Dump the state after application of the oracle\n",
|
||||
" Message(\"The state after applying the converted marking oracle from task 1.3:\");\n",
|
||||
" DumpMachine();\n",
|
||||
" \n",
|
||||
" // reset the qubits for deallocation\n",
|
||||
" ResetAll(register);\n",
|
||||
" }\n",
|
||||
" Message(\"The equal superposition state:\");\n",
|
||||
" DumpMachine();\n",
|
||||
"\n",
|
||||
" // Apply the oracle from task 1.2\n",
|
||||
" IsSeven_PhaseOracle(register);\n",
|
||||
"\n",
|
||||
" // Dump the state after application of the oracle\n",
|
||||
" Message(\"The state after applying the phase oracle from task 1.2:\");\n",
|
||||
" DumpMachine();\n",
|
||||
"\n",
|
||||
" // Reset the qubits for deallocation\n",
|
||||
" ResetAll(register);\n",
|
||||
"\n",
|
||||
" // Prepare an equal superposition state again\n",
|
||||
" ApplyToEachA(H, register);\n",
|
||||
"\n",
|
||||
" // Apply the marking oracle from task 1.3 as a phase oracle\n",
|
||||
" ApplyMarkingOracleAsPhaseOracle(IsSeven_MarkingOracle, register);\n",
|
||||
"\n",
|
||||
" // Dump the state after application of the oracle\n",
|
||||
" Message(\"The state after applying the converted marking oracle from task 1.3:\");\n",
|
||||
" DumpMachine();\n",
|
||||
"\n",
|
||||
" // reset the qubits for deallocation\n",
|
||||
" ResetAll(register);\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
|
@ -981,7 +975,7 @@
|
|||
"\n",
|
||||
"// The classical function to perform the same computation\n",
|
||||
"function Meeting_Classical (x: Bool[], jasmine: Bool[]) : Bool {\n",
|
||||
" for (i in IndexRange(x)) {\n",
|
||||
" for i in IndexRange(x) {\n",
|
||||
" if ((not x[i]) and (not jasmine[i])) {\n",
|
||||
" // They have a day that they can both meet\n",
|
||||
" return true;\n",
|
||||
|
@ -994,8 +988,8 @@
|
|||
"\n",
|
||||
"operation Test_Meeting_Oracle () : Unit {\n",
|
||||
" // There are 2^5 ways to arrange each of the schedules - let's try all of them\n",
|
||||
" for (k in 0..((2^5)-1)) { \n",
|
||||
" for (j in 0..((2^5)-1)) {\n",
|
||||
" for k in 0..((2^5)-1) { \n",
|
||||
" for j in 0..((2^5)-1) {\n",
|
||||
" // Convert your and Jasmine's schedules to bit arrays\n",
|
||||
" let binaryX = IntAsBoolArray(k, 5);\n",
|
||||
" let binaryJasmine = IntAsBoolArray(j, 5);\n",
|
||||
|
@ -1005,28 +999,27 @@
|
|||
" \n",
|
||||
" // create a register of qubits so we can represent\n",
|
||||
" // your schedule, jasmine's schedule, and the output\n",
|
||||
" using ((x, jasmine, target) = (Qubit[5], Qubit[5], Qubit())) {\n",
|
||||
" // Prepare the quantum schedules in basis states matching the binary schedules\n",
|
||||
" ApplyPauliFromBitString(PauliX, true, binaryX, x);\n",
|
||||
" ApplyPauliFromBitString(PauliX, true, binaryJasmine, jasmine);\n",
|
||||
" \n",
|
||||
" // Apply the quantum oracle\n",
|
||||
" Meeting_Oracle(x, jasmine, target);\n",
|
||||
" \n",
|
||||
" // Check that the result of the quantum algorithm matched that\n",
|
||||
" // of the classical algorithm\n",
|
||||
" AssertQubit(classicalResult ? One | Zero, target);\n",
|
||||
" \n",
|
||||
" // Undo the preparation of basis states x and jasmine\n",
|
||||
" ApplyPauliFromBitString(PauliX, true, binaryX, x);\n",
|
||||
" ApplyPauliFromBitString(PauliX, true, binaryJasmine, jasmine);\n",
|
||||
" \n",
|
||||
" // Check that the oracle did not change its input states\n",
|
||||
" AssertAllZero(x);\n",
|
||||
" AssertAllZero(jasmine);\n",
|
||||
" \n",
|
||||
" Reset(target);\n",
|
||||
" }\n",
|
||||
" use (x, jasmine, target) = (Qubit[5], Qubit[5], Qubit());\n",
|
||||
" // Prepare the quantum schedules in basis states matching the binary schedules\n",
|
||||
" ApplyPauliFromBitString(PauliX, true, binaryX, x);\n",
|
||||
" ApplyPauliFromBitString(PauliX, true, binaryJasmine, jasmine);\n",
|
||||
"\n",
|
||||
" // Apply the quantum oracle\n",
|
||||
" Meeting_Oracle(x, jasmine, target);\n",
|
||||
"\n",
|
||||
" // Check that the result of the quantum algorithm matched that\n",
|
||||
" // of the classical algorithm\n",
|
||||
" AssertQubit(classicalResult ? One | Zero, target);\n",
|
||||
"\n",
|
||||
" // Undo the preparation of basis states x and jasmine\n",
|
||||
" ApplyPauliFromBitString(PauliX, true, binaryX, x);\n",
|
||||
" ApplyPauliFromBitString(PauliX, true, binaryJasmine, jasmine);\n",
|
||||
"\n",
|
||||
" // Check that the oracle did not change its input states\n",
|
||||
" AssertAllZero(x);\n",
|
||||
" AssertAllZero(jasmine);\n",
|
||||
"\n",
|
||||
" Reset(target);\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" \n",
|
||||
|
@ -1076,7 +1069,7 @@
|
|||
"file_extension": ".qs",
|
||||
"mimetype": "text/x-qsharp",
|
||||
"name": "qsharp",
|
||||
"version": "0.12"
|
||||
"version": "0.14"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
@ -43,13 +43,12 @@ namespace Quantum.Kata.Oracles {
|
|||
|
||||
// Task 2.1.
|
||||
operation ApplyMarkingOracleAsPhaseOracle_Reference (markingOracle : ((Qubit[], Qubit) => Unit is Adj + Ctl), qubits : Qubit[]) : Unit is Adj + Ctl {
|
||||
using (minus = Qubit()) {
|
||||
within {
|
||||
X(minus);
|
||||
H(minus);
|
||||
} apply {
|
||||
markingOracle(qubits, minus);
|
||||
}
|
||||
use minus = Qubit();
|
||||
within {
|
||||
X(minus);
|
||||
H(minus);
|
||||
} apply {
|
||||
markingOracle(qubits, minus);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,13 +74,12 @@ namespace Quantum.Kata.Oracles {
|
|||
|
||||
// Task 3.3.
|
||||
operation OrOfBitsExceptKth_Oracle_Reference (x : Qubit[], k : Int) : Unit is Adj + Ctl {
|
||||
using (minus = Qubit()) {
|
||||
within {
|
||||
X(minus);
|
||||
H(minus);
|
||||
} apply {
|
||||
Or_Oracle_Reference(x[...k-1] + x[k+1...], minus);
|
||||
}
|
||||
use minus = Qubit();
|
||||
within {
|
||||
X(minus);
|
||||
H(minus);
|
||||
} apply {
|
||||
Or_Oracle_Reference(x[...k-1] + x[k+1...], minus);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,7 +97,7 @@ namespace Quantum.Kata.Oracles {
|
|||
// Task 4.2.
|
||||
operation ArbitraryBitPattern_Oracle_Challenge_Reference (x : Qubit[], pattern : Bool[]) : Unit is Adj + Ctl {
|
||||
within {
|
||||
for (i in IndexRange(x)) {
|
||||
for i in IndexRange(x) {
|
||||
if (not pattern[i]) {
|
||||
X(x[i]);
|
||||
}
|
||||
|
@ -111,17 +109,16 @@ namespace Quantum.Kata.Oracles {
|
|||
|
||||
// Task 4.3.
|
||||
operation Meeting_Oracle_Reference (x : Qubit[], jasmine : Qubit[], z : Qubit) : Unit is Adj + Ctl {
|
||||
using (q = Qubit[Length(x)]) {
|
||||
within {
|
||||
for (i in IndexRange(q)) {
|
||||
// flip q[i] if both x and jasmine are free on the given day
|
||||
X(x[i]);
|
||||
X(jasmine[i]);
|
||||
CCNOT(x[i], jasmine[i], q[i]);
|
||||
}
|
||||
} apply {
|
||||
Or_Oracle_Reference(q, z);
|
||||
use q = Qubit[Length(x)];
|
||||
within {
|
||||
for i in IndexRange(q) {
|
||||
// flip q[i] if both x and jasmine are free on the given day
|
||||
X(x[i]);
|
||||
X(jasmine[i]);
|
||||
CCNOT(x[i], jasmine[i], q[i]);
|
||||
}
|
||||
} apply {
|
||||
Or_Oracle_Reference(q, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace Quantum.Kata.Oracles {
|
|||
let sol = ApplyOracle(_, oracle1);
|
||||
let refSol = ApplyOracle(_, oracle2);
|
||||
|
||||
for (i in nQubits) {
|
||||
for i in nQubits {
|
||||
AssertOperationsEqualReferenced(i + 1, sol, refSol);
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ namespace Quantum.Kata.Oracles {
|
|||
@Test("QuantumSimulator")
|
||||
function T11_IsSeven_ClassicalOracle () : Unit {
|
||||
let N = 3;
|
||||
for (k in 0..((2^N)-1)) {
|
||||
for k in 0..((2^N)-1) {
|
||||
let x = IntAsBoolArray(k, N);
|
||||
|
||||
let actual = IsSeven(x);
|
||||
|
@ -71,8 +71,8 @@ namespace Quantum.Kata.Oracles {
|
|||
// ------------------------------------------------------
|
||||
@Test("QuantumSimulator")
|
||||
operation T21_ApplyMarkingOracleAsPhaseOracle () : Unit {
|
||||
for (N in 1..5) {
|
||||
for (k in 0..(2^N-1)) {
|
||||
for N in 1..5 {
|
||||
for k in 0..(2^N-1) {
|
||||
let pattern = IntAsBoolArray(k, N);
|
||||
|
||||
AssertOperationsEqualReferenced(N,
|
||||
|
@ -93,8 +93,8 @@ namespace Quantum.Kata.Oracles {
|
|||
// ------------------------------------------------------
|
||||
@Test("QuantumSimulator")
|
||||
operation T32_KthBit_Oracle () : Unit {
|
||||
for (N in 1..5) {
|
||||
for (k in 0..(N-1)) {
|
||||
for N in 1..5 {
|
||||
for k in 0..(N-1) {
|
||||
within {
|
||||
AllowAtMostNQubits(2*N, "You are not allowed to allocate extra qubits");
|
||||
} apply {
|
||||
|
@ -110,8 +110,8 @@ namespace Quantum.Kata.Oracles {
|
|||
// ------------------------------------------------------
|
||||
@Test("QuantumSimulator")
|
||||
operation T33_OrOfBitsExceptKth_Oracle () : Unit {
|
||||
for (N in 1..5) {
|
||||
for (k in 0..(N-1)) {
|
||||
for N in 1..5 {
|
||||
for k in 0..(N-1) {
|
||||
AssertOperationsEqualReferenced(N,
|
||||
OrOfBitsExceptKth_Oracle(_, k),
|
||||
OrOfBitsExceptKth_Oracle_Reference(_, k));
|
||||
|
@ -123,8 +123,8 @@ namespace Quantum.Kata.Oracles {
|
|||
// ------------------------------------------------------
|
||||
@Test("QuantumSimulator")
|
||||
operation T41_ArbitraryBitPattern_Oracle () : Unit {
|
||||
for (N in 1..4) {
|
||||
for (k in 0..((2^N)-1)) {
|
||||
for N in 1..4 {
|
||||
for k in 0..((2^N)-1) {
|
||||
let pattern = IntAsBoolArray(k, N);
|
||||
|
||||
AssertTwoOraclesAreEqual(N..N, ArbitraryBitPattern_Oracle(_, _, pattern),
|
||||
|
@ -137,8 +137,8 @@ namespace Quantum.Kata.Oracles {
|
|||
// ------------------------------------------------------
|
||||
@Test("QuantumSimulator")
|
||||
operation T42_ArbitraryBitPattern_Oracle_Challenge () : Unit {
|
||||
for (N in 1..4) {
|
||||
for (k in 0..((2^N)-1)) {
|
||||
for N in 1..4 {
|
||||
for k in 0..((2^N)-1) {
|
||||
let pattern = IntAsBoolArray(k, N);
|
||||
|
||||
within {
|
||||
|
@ -156,17 +156,16 @@ namespace Quantum.Kata.Oracles {
|
|||
// ------------------------------------------------------
|
||||
@Test("QuantumSimulator")
|
||||
operation T43_Meeting_Oracle () : Unit {
|
||||
for (N in 1..4) {
|
||||
using (jasmine = Qubit[N]) {
|
||||
for (k in 0..(2^N-1)) {
|
||||
let binaryJasmine = IntAsBoolArray(k, N);
|
||||
for N in 1..4 {
|
||||
use jasmine = Qubit[N];
|
||||
for k in 0..(2^N-1) {
|
||||
let binaryJasmine = IntAsBoolArray(k, N);
|
||||
|
||||
within {
|
||||
ApplyPauliFromBitString(PauliX, true, binaryJasmine, jasmine);
|
||||
} apply {
|
||||
AssertTwoOraclesAreEqual(1..N, Meeting_Oracle(_, jasmine, _),
|
||||
Meeting_Oracle_Reference(_, jasmine, _));
|
||||
}
|
||||
within {
|
||||
ApplyPauliFromBitString(PauliX, true, binaryJasmine, jasmine);
|
||||
} apply {
|
||||
AssertTwoOraclesAreEqual(1..N, Meeting_Oracle(_, jasmine, _),
|
||||
Meeting_Oracle_Reference(_, jasmine, _));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@
|
|||
"operation SampleData (samplesNumber : Int, separationAngles : Double[]) : (Double[][], Int[]) {\n",
|
||||
" mutable features = new Double[][samplesNumber];\n",
|
||||
" mutable labels = new Int[samplesNumber];\n",
|
||||
" for (i in 0 .. samplesNumber - 1) {\n",
|
||||
" for i in 0 .. samplesNumber - 1 {\n",
|
||||
" let sample = [DrawRandomDouble(0.0, 1.0), DrawRandomDouble(0.0, 1.0)];\n",
|
||||
" let angle = ArcTan2(sample[1], sample[0]);\n",
|
||||
" set features w/= i <- sample;\n",
|
||||
|
@ -122,7 +122,7 @@
|
|||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"([[0.4551074511628167,0.3589961064788495],[0.029864609255392388,0.03013458104344764],[0.4418538373158564,0.5573442585567684],[0.9947988069592039,0.5994662421753008],[0.020553547898565207,0.47611901093093634]], [1,1,1,1,0])\r\n"
|
||||
"([[0,41558553018401634,0,8455760422374942],[0,4469224612447072,0,16762420449760937],[0,4400985573605162,0,05275775680912554],[0,1748506683739138,0,9069414613335121],[0,8807629122774875,0,7115352604126256]], [0,0,0,0,1])\r\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -210,13 +210,12 @@
|
|||
" let norm = Sqrt(sample[0] ^ 2.0 + sample[1] ^ 2.0);\n",
|
||||
" Message($\"Normalized data: [{sample[0] / norm}, {sample[1] / norm}]\");\n",
|
||||
" \n",
|
||||
" using (q = Qubit()) {\n",
|
||||
" let (_, encoder) = (InputEncoder(sample))!;\n",
|
||||
" encoder(LittleEndian([q]));\n",
|
||||
" Message(\"Encoded as a quantum state:\");\n",
|
||||
" DumpMachine();\n",
|
||||
" Reset(q);\n",
|
||||
" }\n",
|
||||
" use q = Qubit();\n",
|
||||
" let (_, encoder) = (InputEncoder(sample))!;\n",
|
||||
" encoder(LittleEndian([q]));\n",
|
||||
" Message(\"Encoded as a quantum state:\");\n",
|
||||
" DumpMachine();\n",
|
||||
" Reset(q);\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
|
@ -231,14 +230,14 @@
|
|||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Raw data: [0.3992584247138623,0.7656880741779172]\n",
|
||||
"Normalized data: [0.46235572011769804, 0.8866945291781408]\n",
|
||||
"Raw data: [0,2991085887416772,0,2821816500659015]\n",
|
||||
"Normalized data: [0,7273891172943013, 0,6862252341919649]\n",
|
||||
"Encoded as a quantum state:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"application/json": "{\"QubitIds\":[0],\"NQubits\":1,\"Amplitudes\":[{\"Real\":0.4623557201176982,\"Imaginary\":0.0,\"Magnitude\":0.4623557201176982,\"Phase\":0.0},{\"Real\":0.8866945291781408,\"Imaginary\":0.0,\"Magnitude\":0.8866945291781408,\"Phase\":0.0}]}",
|
||||
"application/json": "{\"div_id\":\"dump-machine-div-9aceb95a-a721-421d-a5f3-8da9588bf3dd\",\"qubit_ids\":[0],\"n_qubits\":1,\"amplitudes\":[{\"Real\":0.7273891172943014,\"Imaginary\":0.0,\"Magnitude\":0.7273891172943014,\"Phase\":0.0},{\"Real\":0.686225234191965,\"Imaginary\":0.0,\"Magnitude\":0.686225234191965,\"Phase\":0.0}]}",
|
||||
"text/html": [
|
||||
"\r\n",
|
||||
" <table style=\"table-layout: fixed; width: 100%\">\r\n",
|
||||
|
@ -251,24 +250,32 @@
|
|||
" \r\n",
|
||||
" <tr>\r\n",
|
||||
" <th style=\"width: 20ch)\">Basis state (little endian)</th>\r\n",
|
||||
" <th style=\"width: 20ch\">Amplitude</th>\r\n",
|
||||
" <th style=\"width: calc(100% - 26ch - 20ch)\">Meas. Pr.</th>\r\n",
|
||||
" <th style=\"width: 6ch\">Phase</th>\r\n",
|
||||
" <th style=\"width: 20ch\">Amplitude</th><th style=\"width: calc(100% - 26ch - 20ch)\">Meas. Pr.</th><th style=\"width: 6ch\">Phase</th>\r\n",
|
||||
" </tr>\r\n",
|
||||
" </thead>\r\n",
|
||||
"\r\n",
|
||||
" <tbody>\r\n",
|
||||
" \r\n",
|
||||
" \r\n",
|
||||
" <tr>\r\n",
|
||||
" <td>$\\left|0\\right\\rangle$</td>\r\n",
|
||||
" <td>$0.4624 + 0.0000 i$</td>\r\n",
|
||||
" <td>$0.7274 + 0.0000 i$</td>\r\n",
|
||||
" \r\n",
|
||||
" <td>\r\n",
|
||||
" <progress\r\n",
|
||||
" max=\"100\"\r\n",
|
||||
" value=\"21.37728119255553\"\r\n",
|
||||
" value=\"52.9094927958183\"\r\n",
|
||||
" style=\"width: 100%;\"\r\n",
|
||||
" >\r\n",
|
||||
" > \r\n",
|
||||
" <td>\r\n",
|
||||
" <p id=\"round-0f3d530d-b4cc-4920-afe3-638111695e5a\"> \r\n",
|
||||
" <script>\r\n",
|
||||
" var num = 52.9094927958183;\r\n",
|
||||
" num = num.toFixed(4);\r\n",
|
||||
" var num_string = num + \"%\";\r\n",
|
||||
" document.getElementById(\"round-0f3d530d-b4cc-4920-afe3-638111695e5a\").innerHTML = num_string;\r\n",
|
||||
" </script> </p>\r\n",
|
||||
" </td>\r\n",
|
||||
" </td>\r\n",
|
||||
" \r\n",
|
||||
" \r\n",
|
||||
" <td style=\"transform: rotate(0deg);\r\n",
|
||||
" text-align: center;\">\r\n",
|
||||
|
@ -280,14 +287,25 @@
|
|||
"\r\n",
|
||||
" <tr>\r\n",
|
||||
" <td>$\\left|1\\right\\rangle$</td>\r\n",
|
||||
" <td>$0.8867 + 0.0000 i$</td>\r\n",
|
||||
" <td>$0.6862 + 0.0000 i$</td>\r\n",
|
||||
" \r\n",
|
||||
" <td>\r\n",
|
||||
" <progress\r\n",
|
||||
" max=\"100\"\r\n",
|
||||
" value=\"78.62271880744449\"\r\n",
|
||||
" value=\"47.090507204181726\"\r\n",
|
||||
" style=\"width: 100%;\"\r\n",
|
||||
" >\r\n",
|
||||
" > \r\n",
|
||||
" <td>\r\n",
|
||||
" <p id=\"round-8ee190ed-a26f-4390-86fe-07ef2e4c2d5c\"> \r\n",
|
||||
" <script>\r\n",
|
||||
" var num = 47.090507204181726;\r\n",
|
||||
" num = num.toFixed(4);\r\n",
|
||||
" var num_string = num + \"%\";\r\n",
|
||||
" document.getElementById(\"round-8ee190ed-a26f-4390-86fe-07ef2e4c2d5c\").innerHTML = num_string;\r\n",
|
||||
" </script> </p>\r\n",
|
||||
" </td>\r\n",
|
||||
" </td>\r\n",
|
||||
" \r\n",
|
||||
" \r\n",
|
||||
" <td style=\"transform: rotate(0deg);\r\n",
|
||||
" text-align: center;\">\r\n",
|
||||
|
@ -297,12 +315,11 @@
|
|||
" </tr>\r\n",
|
||||
" \r\n",
|
||||
" </tbody>\r\n",
|
||||
" </table>\r\n",
|
||||
" "
|
||||
" </table>"
|
||||
],
|
||||
"text/plain": [
|
||||
"|0⟩\t0.4623557201176982 + 0𝑖\n",
|
||||
"|1⟩\t0.8866945291781408 + 0𝑖"
|
||||
"|0⟩\t0,7273891172943014 + 0𝑖\n",
|
||||
"|1⟩\t0,686225234191965 + 0𝑖"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
|
@ -500,7 +517,7 @@
|
|||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Training complete, found optimal parameters: [1.565600000000005], -0.42915000000000003 with 0 misses\r\n"
|
||||
"Training complete, found optimal parameters: [1,5743999999999962], -0,43235 with 0 misses\r\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -608,7 +625,7 @@
|
|||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Training complete, found optimal parameters: [1.6001000000000027], -0.42524999999999996 with 0 misses\n",
|
||||
"Training complete, found optimal parameters: [1,5632000000000161], -0,43415 with 0 misses\n",
|
||||
"Miss rate: 0%\n"
|
||||
]
|
||||
},
|
||||
|
|
|
@ -71,10 +71,9 @@
|
|||
"%kata T1_RandomBit\n",
|
||||
"\n",
|
||||
"operation RandomBit () : Int {\n",
|
||||
" using (q = Qubit()) {\n",
|
||||
" // ...\n",
|
||||
" return -1;\n",
|
||||
" }\n",
|
||||
" use q = Qubit();\n",
|
||||
" // ...\n",
|
||||
" return -1;\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
|
|
|
@ -20,10 +20,9 @@ namespace Quantum.Kata.RandomNumberGeneration {
|
|||
|
||||
// Exercise 1.
|
||||
operation RandomBit_Reference () : Int {
|
||||
using (q = Qubit()) {
|
||||
H(q);
|
||||
return M(q) == Zero ? 0 | 1;
|
||||
}
|
||||
use q = Qubit();
|
||||
H(q);
|
||||
return M(q) == Zero ? 0 | 1;
|
||||
}
|
||||
|
||||
// Exercise 2.
|
||||
|
@ -34,7 +33,7 @@ namespace Quantum.Kata.RandomNumberGeneration {
|
|||
// Exercise 3.
|
||||
operation RandomNBits_Reference (N: Int) : Int {
|
||||
mutable result = 0;
|
||||
for (i in 0..(N - 1)) {
|
||||
for i in 0..(N - 1) {
|
||||
set result = result * 2 + RandomBit_Reference();
|
||||
}
|
||||
return result;
|
||||
|
@ -43,10 +42,9 @@ namespace Quantum.Kata.RandomNumberGeneration {
|
|||
// Exercise 4.
|
||||
operation WeightedRandomBit_Reference (x : Double) : Int {
|
||||
let theta = ArcCos(Sqrt(x));
|
||||
using (q = Qubit()) {
|
||||
Ry(2.0 * theta, q);
|
||||
return M(q) == Zero ? 0 | 1;
|
||||
}
|
||||
use q = Qubit();
|
||||
Ry(2.0 * theta, q);
|
||||
return M(q) == Zero ? 0 | 1;
|
||||
}
|
||||
|
||||
// Exercise 5.
|
||||
|
|
|
@ -15,10 +15,9 @@ namespace Quantum.Kata.RandomNumberGeneration {
|
|||
|
||||
// Exercise 1.
|
||||
operation RandomBit () : Int {
|
||||
using (q = Qubit()) {
|
||||
// ...
|
||||
return -1;
|
||||
}
|
||||
use q = Qubit();
|
||||
// ...
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Exercise 2.
|
||||
|
|
|
@ -72,7 +72,7 @@ namespace Quantum.Kata.RandomNumberGeneration {
|
|||
mutable average = 0.0;
|
||||
|
||||
ResetOracleCallsCount();
|
||||
for (i in 1..nRuns) {
|
||||
for i in 1..nRuns {
|
||||
let val = f(numBits);
|
||||
if (val < 0 or val >= max) {
|
||||
fail $"Unexpected number generated. Expected values from 0 to {max - 1}, generated {val}";
|
||||
|
@ -93,7 +93,7 @@ namespace Quantum.Kata.RandomNumberGeneration {
|
|||
|
||||
}
|
||||
|
||||
for (i in 0..max - 1) {
|
||||
for i in 0..max - 1 {
|
||||
if (counts[i] < minimumCopiesGenerated) {
|
||||
fail $"Unexpectedly low number of {i}'s generated. Only {counts[i]} out of {nRuns} were {i}";
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ namespace Quantum.Kata.RandomNumberGeneration {
|
|||
|
||||
operation FindMedian (counts : Int [], arrSize : Int, sampleSize : Int) : Int {
|
||||
mutable totalCount = 0;
|
||||
for (i in 0..arrSize - 1) {
|
||||
for i in 0..arrSize - 1 {
|
||||
set totalCount = totalCount + counts[i];
|
||||
if (totalCount >= sampleSize / 2) {
|
||||
return i;
|
||||
|
@ -129,7 +129,7 @@ namespace Quantum.Kata.RandomNumberGeneration {
|
|||
mutable oneCount = 0;
|
||||
let nRuns = 1000;
|
||||
ResetOracleCallsCount();
|
||||
for (N in 1..nRuns) {
|
||||
for N in 1..nRuns {
|
||||
let val = WeightedRandomBit(x);
|
||||
if (val < 0 or val > 1) {
|
||||
fail $"Unexpected number generated. Expected 0 or 1, instead generated {val}";
|
||||
|
@ -170,7 +170,7 @@ namespace Quantum.Kata.RandomNumberGeneration {
|
|||
mutable average = 0.0;
|
||||
|
||||
ResetOracleCallsCount();
|
||||
for (i in 1..nRuns) {
|
||||
for i in 1..nRuns {
|
||||
let val = f(min, max);
|
||||
if (val < min or val > max) {
|
||||
fail $"Unexpected number generated. Expected values from {min} to {max}, generated {val}";
|
||||
|
@ -191,7 +191,7 @@ namespace Quantum.Kata.RandomNumberGeneration {
|
|||
|
||||
}
|
||||
|
||||
for (i in min..max) {
|
||||
for i in min..max {
|
||||
if (counts[i] < minimumCopiesGenerated) {
|
||||
fail $"Unexpectedly low number of {i}'s generated. Only {counts[i]} out of {nRuns} were {i}";
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче