This repository has been archived by the owner on Nov 30, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Tasks_0_twos_complement.qs
137 lines (124 loc) · 4.07 KB
/
Tasks_0_twos_complement.qs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
namespace Final_Project
{
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Extensions.Math;
open Microsoft.Quantum.Extensions.Convert;
// from "QUANTUM ADDER OF CLASSICAL NUMBERS"
// by A.V. Cherkas and S.A. Chivilikhin
// https://iopscience.iop.org/article/10.1088/1742-6596/735/1/012083/pdf
/// # Summary
/// create gate described by matrix [1 0; 0 e^(2*i*PI/2^k)]
///
/// # Input
/// ## q
/// qubit being rotated.
/// ## k
/// Amount to rotate, defined by above equation.
///
/// # Example
/// ```Q#
/// // often used as a controlled rotation
/// Controlled Rzk([A], (B, 1.0));
/// ```
operation Rzk (q : Qubit, k : Double) : Unit {
body (...) {
ApplyDiagonalUnitary([0.0, 2.0*PI()/PowD(2.0, k)], BigEndian([q]));
}
adjoint auto;
controlled auto;
controlled adjoint auto;
}
/// # Summary
/// Adder that takes A, B -> A+B, B
/// Uses QFT cascading design described in paper
///
/// # Input
/// ## A
/// operand. Will become A+B.
/// ## B
/// operand. Remains B.
///
/// # Example
/// ```Q#
/// efficient_adder(A, B);
/// ```
operation efficient_adder (A : Qubit[], B : Qubit[]) : Unit {
body (...) {
let N = Length(A);
let P = Length(B);
// length of A, B must be the same
if (N != P) {
fail "Eror: improper quantum adder usage";
}
QFT((BigEndian(A))); // apply fourier transform
for (i in 0..N-1) {
for (j in 0..i) {
// rotate lower bits according controlled on higher bits
Controlled Rzk([A[N-j-1]], (B[i], ToDouble(i-j+1)));
}
}
Adjoint QFT((BigEndian(A))); // undo fourier transform
}
adjoint auto;
controlled auto;
controlled adjoint auto;
}
/// # Summary
/// Compares d and dmax
/// d, dmax, target -> d, dmax, (d > dmax)⊕target
/// uses 1 extra qubit in function
///
/// # Input
/// ## d
/// Unchanged operand.
/// ## dmax
/// Unchanged operand.
/// ## target
/// Flipped if d > dmax
///
/// # Example
/// ```Q#
/// using (target = Qubit()) {
/// efficient_TC_comparator(A, B, target);
/// // do stuff with knowledge of d > dmax
/// efficient_TC_comparator(A, B, target); // reset target
/// }
/// ```
operation efficient_TC_comparator (d : Qubit[], dmax : Qubit[], target : Qubit) : Unit {
body(...) {
let N = Length(d);
let P = Length(dmax);
// d, dmax must be the same length
if (N != P) {
fail "Eror: improper efficient_TC_comparator usage";
}
// if dmax is negative and d is positive, d > dmax
(ControlledOnBitString([false, true], X))([d[0], dmax[0]], target);
using (dmax_tmp = Qubit()) {
CNOT(dmax[0], dmax_tmp); // store sign bit of dmax in dmax_tmp
Adjoint efficient_adder(dmax, d); // subtract d from dmax and store in dmax
// if dmax and d are positive and dmax - d is negative, d > dmax
(ControlledOnBitString([false, false, true], X))([d[0], dmax_tmp, dmax[0]], target);
// if dmax and d are negative and dmax - d is positive, d > dmax
(ControlledOnBitString([true, true, true], X))([d[0], dmax_tmp, dmax[0]], target);
efficient_adder(dmax, d); // undo subtraction
CNOT(dmax[0], dmax_tmp); // undo temporary storage
}
}
adjoint auto;
controlled auto;
controlled adjoint auto;
}
operation negateBE(a : Qubit[]) : Unit {
body (...) {
for (q in a) {
X(q);
}
IntegerIncrementBE(1, a);
}
adjoint auto;
controlled auto;
controlled adjoint auto;
}
}