microsoft/qdk

Public

mirrored fromhttps://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
9c33427155ee7a0d2f2beebc2f03d7c4609b6e4f

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

samples/algorithms/DotProductViaPhaseEstimation.qs

161lines · modecode

1// MIT License
2
3// Copyright (c) 2023 KPMG Australia
4
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22import Std.Math.*;
23import Std.Convert.*;
24
25operation Main() : (Int, Int) {
26 // The angles for inner product. Inner product is meeasured for vectors
27 // (cos(Θ₁/2), sin(Θ₁/2)) and (cos(Θ₂/2), sin(Θ₂/2)).
28 let theta1 = PI() / 7.0;
29 let theta2 = PI() / 5.0;
30 // Number of iterations
31 let n = 4;
32 // Perform measurements
33 Message("Computing inner product of vectors (cos(Θ₁/2), sin(Θ₁/2))⋅(cos(Θ₂/2), sin(Θ₂/2)) ≈ -cos(x𝝅/2ⁿ)");
34 let result = PerformMeasurements(theta1, theta2, n);
35 // Return result
36 return (result, n);
37}
38
39@Config(Adaptive)
40@Config(not HigherLevelConstructs)
41@Config(not FloatingPointComputations)
42operation PerformMeasurements(theta1 : Double, theta2 : Double, n : Int) : Int {
43 let measurementCount = n + 1;
44 return QuantumInnerProduct(theta1, theta2, measurementCount);
45}
46
47@Config(HigherLevelConstructs)
48@Config(FloatingPointComputations)
49operation PerformMeasurements(theta1 : Double, theta2 : Double, n : Int) : Int {
50 Message($"Θ₁={theta1}, Θ₂={theta2}.");
51
52 // First compute quantum approximation
53 let measurementCount = n + 1;
54 let x = QuantumInnerProduct(theta1, theta2, measurementCount);
55 let angle = PI() * IntAsDouble(x) / IntAsDouble(2^n);
56 let computedInnerProduct = -Cos(angle);
57 Message($"x = {x}, n = {n}.");
58
59 // Now compute true inner product
60 let trueInnterProduct = ClassicalInnerProduct(theta1, theta2);
61
62 Message($"Computed value = {computedInnerProduct}, true value = {trueInnterProduct}");
63
64 return x;
65}
66
67function ClassicalInnerProduct(theta1 : Double, theta2 : Double) : Double {
68 return Cos(theta1 / 2.0) * Cos(theta2 / 2.0) + Sin(theta1 / 2.0) * Sin(theta2 / 2.0);
69}
70
71operation QuantumInnerProduct(theta1 : Double, theta2 : Double, iterationCount : Int) : Int {
72 //Create target register
73 use TargetReg = Qubit();
74 //Create ancilla register
75 use AncilReg = Qubit();
76 //Run iterative phase estimation
77 let Results = IterativePhaseEstimation(TargetReg, AncilReg, theta1, theta2, iterationCount);
78 Reset(TargetReg);
79 Reset(AncilReg);
80 return Results;
81}
82
83operation IterativePhaseEstimation(
84 TargetReg : Qubit,
85 AncilReg : Qubit,
86 theta1 : Double,
87 theta2 : Double,
88 Measurements : Int
89) : Int {
90
91 use ControlReg = Qubit();
92 mutable MeasureControlReg = [Zero, size = Measurements];
93 mutable bitValue = 0;
94 //Apply to initialise state, this is defined by the angles theta1 and theta2
95 StateInitialisation(TargetReg, AncilReg, theta1, theta2);
96 for index in 0..Measurements - 1 {
97 H(ControlReg);
98 //Don't apply rotation on first set of oracles
99 if index > 0 {
100 //Loop through previous results
101 for index2 in 0..index - 1 {
102 if MeasureControlReg[Measurements - 1 - index2] == One {
103 //Rotate control qubit dependent on previous measurements and number of measurements
104 let angle = -IntAsDouble(2^(index2)) * PI() / (2.0^IntAsDouble(index));
105 R(PauliZ, angle, ControlReg);
106 }
107 }
108
109 }
110 let powerIndex = (1 <<< (Measurements - 1 - index));
111 //Apply a number of oracles equal to 2^index, where index is the number or measurements left
112 for _ in 1..powerIndex {
113 Controlled GOracle([ControlReg], (TargetReg, AncilReg, theta1, theta2));
114 }
115 H(ControlReg);
116 //Make a measurement mid circuit
117 set MeasureControlReg w/= (Measurements - 1 - index) <- MResetZ(ControlReg);
118 if MeasureControlReg[Measurements - 1 - index] == One {
119 //Assign bitValue based on previous measurement
120 bitValue += 2^(index);
121 }
122 }
123 return bitValue;
124}
125
126/// # Summary
127/// This is state preparation operator A for encoding the 2D vector (page 7)
128operation StateInitialisation(
129 TargetReg : Qubit,
130 AncilReg : Qubit,
131 theta1 : Double,
132 theta2 : Double
133) : Unit is Adj + Ctl {
134
135 H(AncilReg);
136 // Arbitrary controlled rotation based on theta. This is vector v.
137 Controlled R([AncilReg], (PauliY, theta1, TargetReg));
138 // X gate on ancilla to change from |+〉 to |-〉.
139 X(AncilReg);
140 // Arbitrary controlled rotation based on theta. This is vector c.
141 Controlled R([AncilReg], (PauliY, theta2, TargetReg));
142 X(AncilReg);
143 H(AncilReg);
144}
145
146operation GOracle(
147 TargetReg : Qubit,
148 AncilReg : Qubit,
149 theta1 : Double,
150 theta2 : Double
151) : Unit is Adj + Ctl {
152
153 Z(AncilReg);
154 within {
155 Adjoint StateInitialisation(TargetReg, AncilReg, theta1, theta2);
156 X(AncilReg);
157 X(TargetReg);
158 } apply {
159 Controlled Z([AncilReg], TargetReg);
160 }
161}
162