Created
April 22, 2019 10:13
-
-
Save friguzzi/84fbba72f7b6ba7bd58b0c4f8a8be60f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Quantum.Sample | |
{ | |
open Microsoft.Quantum.Primitive; | |
open Microsoft.Quantum.Canon; | |
open Microsoft.Quantum.Extensions.Convert; | |
open Microsoft.Quantum.Extensions.Math; | |
operation SprinklerAnc (queryRegister: Qubit[], target : Qubit,ancilla: Qubit[]) : Unit { | |
body (...) { | |
X(queryRegister[2]); | |
X(queryRegister[3]); | |
X(queryRegister[4]); | |
X(queryRegister[5]); | |
X(queryRegister[6]); | |
X(ancilla[0]); | |
X(ancilla[1]); | |
X(ancilla[2]); | |
CCNOT(queryRegister[0],queryRegister[1],ancilla[0]); | |
CCNOT(queryRegister[1],queryRegister[2],ancilla[1]); | |
CCNOT(queryRegister[0],queryRegister[2],ancilla[2]); | |
(Controlled X)([ancilla[0],ancilla[1],ancilla[2],queryRegister[3],queryRegister[4],queryRegister[5],queryRegister[6]],target); | |
CCNOT(queryRegister[0],queryRegister[2],ancilla[2]); | |
CCNOT(queryRegister[1],queryRegister[2],ancilla[1]); | |
CCNOT(queryRegister[0],queryRegister[1],ancilla[0]); | |
X(ancilla[2]); | |
X(ancilla[1]); | |
X(ancilla[0]); | |
X(queryRegister[2]); | |
X(queryRegister[6]); | |
X(queryRegister[5]); | |
X(queryRegister[4]); | |
X(queryRegister[3]); | |
} | |
adjoint invert; | |
controlled auto; | |
controlled adjoint auto; | |
} | |
operation OracleConverterImpl (markingOracle : ((Qubit[], Qubit) => Unit : Adjoint, Controlled), register : Qubit[]) : Unit { | |
body (...) { | |
using (target = Qubit()) { | |
// Put the target into the |-⟩ state | |
X(target); | |
H(target); | |
// Apply the marking oracle; since the target is in the |-⟩ state, | |
// flipping the target if the register satisfies the oracle condition will apply a -1 factor to the state | |
markingOracle(register, target); | |
// Put the target back into |0⟩ so we can return it | |
H(target); | |
X(target); | |
} | |
} | |
adjoint invert; | |
controlled auto; | |
adjoint controlled auto; | |
} | |
operation HadamardTransform (register : Qubit[]) : Unit { | |
body (...) { | |
//ApplyToEachA(H, register); | |
// ApplyToEach is a library routine that is equivalent to the following code: | |
let nQubits = Length(register); | |
for (idxQubit in 0..nQubits - 1) { | |
H(register[idxQubit]); | |
} | |
} | |
adjoint invert; | |
controlled auto; | |
controlled adjoint auto; | |
} | |
operation Oracle_ArbitraryPattern (queryRegister : Qubit[], target : Qubit, pattern : Bool[]) : Unit { | |
body (...) { | |
(ControlledOnBitString(pattern, X))(queryRegister, target); | |
} | |
adjoint invert; | |
controlled auto; | |
controlled adjoint auto; | |
} | |
// Task 2.2. Conditional phase flip | |
operation ConditionalPhaseFlip (register : Qubit[]) : Unit { | |
body (...) { | |
// Define a marking oracle which detects an all zero state | |
let allZerosOracle = Oracle_ArbitraryPattern(_, _, new Bool[Length(register)]); | |
// Convert it into a phase-flip oracle and apply it | |
let flipOracle = OracleConverter(allZerosOracle); | |
flipOracle(register); | |
} | |
adjoint self; | |
controlled auto; | |
controlled adjoint auto; | |
} | |
// Task 2.3. The Grover iteration | |
operation GroverIteration (register : Qubit[], oracle : (Qubit[] => Unit : Adjoint, Controlled)) : Unit { | |
body (...) { | |
oracle(register); | |
HadamardTransform(register); | |
ConditionalPhaseFlip(register); | |
HadamardTransform(register); | |
} | |
adjoint invert; | |
controlled auto; | |
controlled adjoint auto; | |
} | |
function OracleConverter (markingOracle : ((Qubit[], Qubit) => Unit : Adjoint, Controlled)) : (Qubit[] => Unit : Adjoint, Controlled) { | |
return OracleConverterImpl(markingOracle, _); | |
} | |
operation UnitaryPowerImpl (U : (Qubit[] => Unit : Adjoint, Controlled), power : Int, q : Qubit[]) : Unit { | |
body (...) { | |
for (i in 1..power) { | |
U(q); | |
} | |
} | |
adjoint auto; | |
controlled auto; | |
controlled adjoint auto; | |
} | |
operation QPE() : Double { | |
mutable phase = -1.0; | |
let n=8; | |
using ((reg,phaseRegister,ancilla)=(Qubit[7 ], Qubit[n],Qubit[3])) | |
{ | |
// Construct a phase estimation oracle from the unitary | |
let phaseOracle = OracleConverter(SprinklerAnc(_,_,ancilla)); | |
let oracle = DiscreteOracle(UnitaryPowerImpl(GroverIteration(_, phaseOracle), _, _)); | |
// let markingOracle = Sprinkler(_, _); | |
// Allocate qubits to hold the eigenstate of U and the phase in a big endian register | |
let phaseRegisterBE = BigEndian(phaseRegister); | |
// Prepare the eigenstate of U | |
HadamardTransform(reg); | |
// Call library | |
QuantumPhaseEstimation(oracle, reg, phaseRegisterBE); | |
// Read out the phase | |
set phase = ToDouble(MeasureIntegerBE(phaseRegisterBE)) / ToDouble(1 <<< (n)); | |
ResetAll(reg); | |
ResetAll(phaseRegister); | |
} | |
let angle = PI()*phase; | |
let res = 128.0 *(1.0- PowD(Sin(angle),2.0)); | |
return res; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment