microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
billt/mac-intel-cryptography

Branches

Tags

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

Clone

HTTPS

Download ZIP

library/chemistry/src/JordanWigner/BlockEncoding.qs

215lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4export JWBlockEncodingGeneratorSystem;
5
6import Std.Arrays.IndexRange;
7
8import Generators.GeneratorIndex;
9import Generators.GeneratorSystem;
10import Generators.HTermToGenIdx;
11import Utils.IsNotZero;
12import Utils.RangeAsIntArray;
13import JordanWigner.Data.JWOptimizedHTerms;
14
15// This block encoding for qubitization runs off data optimized for a Jordan–Wigner encoding.
16// This collects terms Z, ZZ, PQandPQQR, hpqrs separately.
17// This only apples the needed hpqrs XXXX XXYY terms.
18
19// Convention for GeneratorIndex = ((Int[],Double[]), Int[])
20// We index single Paulis as 0 for I, 1 for X, 2 for Y, 3 for Z.
21// We index Pauli strings with arrays of integers e.g. a = [3,1,1,2] for ZXXY.
22// We assume the zeroth element of Double[] is the angle of rotation
23// We index the qubits that Pauli strings act on with arrays of integers e.g. q = [2,4,5,8] for Z_2 X_4 X_5, Y_8
24// An example of a Pauli string GeneratorIndex is thus ((a,b), q)
25
26// Consider the Hamiltonian H = 0.1 XI + 0.2 IX + 0.3 ZY
27// Its GeneratorTerms are (([1],b),[0]), 0.1), (([1],b),[1]), 0.2), (([3,2],b),[0,1]), 0.3).
28
29/// # Summary
30/// Converts a Hamiltonian described by `JWOptimizedHTerms`
31/// to a `GeneratorSystem` expressed in terms of the Pauli
32/// `GeneratorIndex`.
33///
34/// # Input
35/// ## data
36/// Description of Hamiltonian in `JWOptimizedHTerms` format.
37///
38/// # Output
39/// Representation of Hamiltonian as `GeneratorSystem`.
40function JWBlockEncodingGeneratorSystem(data : JWOptimizedHTerms) : GeneratorSystem {
41 let ZData = data.HTerm0;
42 let ZZData = data.HTerm1;
43 let PQandPQQRData = data.HTerm2;
44 let h0123Data = data.HTerm3;
45 mutable genIdxes = Repeated(
46 new GeneratorIndex { Term = ([0], [0.0]), Subsystem = [0] },
47 ((Length(ZData) + Length(ZZData)) + 2 * Length(PQandPQQRData)) + 8 * Length(h0123Data)
48 );
49 mutable startIdx = 0;
50
51 for idx in IndexRange(ZData) {
52 // Array of Arrays of Length 1
53 genIdxes w/= idx <- (ZTermToPauliGenIdx(HTermToGenIdx(ZData[idx], [0])))[0];
54 }
55
56 startIdx = Length(ZData);
57
58 for idx in IndexRange(ZZData) {
59 // Array of Arrays of Length 1
60 genIdxes w/= startIdx + idx <- (ZZTermToPauliGenIdx(HTermToGenIdx(ZZData[idx], [1])))[0];
61 }
62
63 startIdx = startIdx + Length(ZZData);
64
65 for idx in IndexRange(PQandPQQRData) {
66
67 // Array of Arrays of Length 2
68 let genArr = PQandPQQRTermToPauliGenIdx(HTermToGenIdx(PQandPQQRData[idx], [2]));
69 genIdxes w/= startIdx + 2 * idx <- genArr[0];
70 genIdxes w/= (startIdx + 2 * idx) + 1 <- genArr[1];
71 }
72
73 startIdx = startIdx + 2 * Length(PQandPQQRData);
74 mutable finalIdx = startIdx;
75
76 for idx in 0..Length(h0123Data) - 1 {
77 // Array of Arrays of Length up to 8
78 let genArr = V0123TermToPauliGenIdx(HTermToGenIdx(h0123Data[idx], [3]));
79
80 for idx0123 in IndexRange(genArr) {
81 genIdxes w/= finalIdx <- genArr[idx0123];
82 finalIdx += 1;
83 }
84 }
85
86 let genIdxes = genIdxes[0..finalIdx - 1];
87 return new GeneratorSystem { NumEntries = finalIdx, EntryAt = idx -> genIdxes[idx] };
88}
89
90/// # Summary
91/// Converts a `GeneratorIndex` describing a Z term to
92/// an expression `GeneratorIndex[]` in terms of Paulis.
93///
94/// # Input
95/// ## term
96/// `GeneratorIndex` representing a Z term.
97///
98/// # Output
99/// `GeneratorIndex[]` expressing Z term as Pauli terms.
100function ZTermToPauliGenIdx(term : GeneratorIndex) : GeneratorIndex[] {
101 let (_, coeff) = term.Term;
102 return [new GeneratorIndex { Term = ([3], coeff), Subsystem = term.Subsystem }];
103}
104
105/// # Summary
106/// Converts a `GeneratorIndex` describing a ZZ term to
107/// an expression `GeneratorIndex[]` in terms of Paulis.
108///
109/// # Input
110/// ## term
111/// `GeneratorIndex` representing a ZZ term.
112///
113/// # Output
114/// `GeneratorIndex[]` expressing ZZ term as Pauli terms.
115function ZZTermToPauliGenIdx(term : GeneratorIndex) : GeneratorIndex[] {
116 let (_, coeff) = term.Term;
117 return [new GeneratorIndex { Term = ([3, 3], coeff), Subsystem = term.Subsystem }];
118}
119
120/// # Summary
121/// Converts a `GeneratorIndex` describing a PQ term to
122/// an expression `GeneratorIndex[]` in terms of Paulis
123///
124/// # Input
125/// ## term
126/// `GeneratorIndex` representing a PQ term.
127///
128/// # Output
129/// `GeneratorIndex[]` expressing PQ term as Pauli terms.
130function PQTermToPauliGenIdx(term : GeneratorIndex) : GeneratorIndex[] {
131 let (_, coeff) = term.Term;
132 let newCoeff = [coeff[0]];
133 let qubitPidx = term.Subsystem[0];
134 let qubitQidx = term.Subsystem[1];
135 let qubitIndices = RangeAsIntArray(qubitPidx..qubitQidx);
136 return [
137 new GeneratorIndex { Term = (([1] + Repeated(3, Length(qubitIndices) - 2)) + [1], newCoeff), Subsystem = qubitIndices },
138 new GeneratorIndex { Term = (([2] + Repeated(3, Length(qubitIndices) - 2)) + [2], newCoeff), Subsystem = qubitIndices }
139 ];
140}
141
142/// # Summary
143/// Converts a `GeneratorIndex` describing a PQ or PQQR term to
144/// an expression `GeneratorIndex[]` in terms of Paulis
145///
146/// # Input
147/// ## term
148/// `GeneratorIndex` representing a PQ or PQQR term.
149///
150/// # Output
151/// `GeneratorIndex[]` expressing PQ or PQQR term as Pauli terms.
152function PQandPQQRTermToPauliGenIdx(term : GeneratorIndex) : GeneratorIndex[] {
153 let (_, coeff) = term.Term;
154 let newCoeff = [coeff[0]];
155
156 if Length(term.Subsystem) == 2 {
157 return PQTermToPauliGenIdx(term);
158 } else {
159 let qubitPidx = term.Subsystem[0];
160 let qubitQidx = term.Subsystem[1];
161 let qubitRidx = term.Subsystem[3];
162
163 if (qubitPidx < qubitQidx and qubitQidx < qubitRidx) {
164
165 // Apply XZ..ZIZ..ZX
166 let qubitIndices = RangeAsIntArray(qubitPidx..qubitQidx - 1) + RangeAsIntArray(qubitQidx + 1..qubitRidx);
167 return [
168 new GeneratorIndex { Term = (([1] + Repeated(3, Length(qubitIndices) - 2)) + [1], newCoeff), Subsystem = qubitIndices },
169 new GeneratorIndex { Term = (([2] + Repeated(3, Length(qubitIndices) - 2)) + [2], newCoeff), Subsystem = qubitIndices }
170 ];
171 } else {
172
173 // Apply ZI..IXZ..ZX or XZ..ZXI..IZ
174 let qubitIndices = RangeAsIntArray(qubitPidx..qubitRidx) + [qubitQidx];
175 return [
176 new GeneratorIndex { Term = (([1] + Repeated(3, Length(qubitIndices) - 3)) + [1, 3], newCoeff), Subsystem = qubitIndices },
177 new GeneratorIndex { Term = (([2] + Repeated(3, Length(qubitIndices) - 3)) + [2, 3], newCoeff), Subsystem = qubitIndices }
178 ];
179 }
180 }
181}
182
183/// # Summary
184/// Converts a `GeneratorIndex` describing a PQRS term to
185/// an expression `GeneratorIndex[]` in terms of Paulis
186///
187/// # Input
188/// ## term
189/// `GeneratorIndex` representing a PQRS term.
190///
191/// # Output
192/// `GeneratorIndex[]` expressing PQRS term as Pauli terms.
193function V0123TermToPauliGenIdx(term : GeneratorIndex) : GeneratorIndex[] {
194 let (_, v0123) = term.Term;
195 let qubitsPQ = term.Subsystem[0..1];
196 let qubitsRS = term.Subsystem[2..3];
197 let qubitsPQJW = RangeAsIntArray(qubitsPQ[0] + 1..qubitsPQ[1] - 1);
198 let qubitsRSJW = RangeAsIntArray(qubitsRS[0] + 1..qubitsRS[1] - 1);
199 let ops = [[1, 1, 1, 1], [1, 1, 2, 2], [1, 2, 1, 2], [2, 1, 1, 2], [2, 2, 2, 2], [2, 2, 1, 1], [2, 1, 2, 1], [1, 2, 2, 1]];
200 mutable genIdxes = Repeated(new GeneratorIndex { Term = ([0], [0.0]), Subsystem = [0] }, 8);
201 mutable nonZero = 0;
202
203 for idxOp in IndexRange(ops) {
204 if (IsNotZero(v0123[idxOp % 4])) {
205 let newCoeff = [v0123[idxOp % 4]];
206 genIdxes w/= nonZero <- new GeneratorIndex {
207 Term = (ops[idxOp] + Repeated(3, Length(qubitsPQJW) + Length(qubitsRSJW)), newCoeff),
208 Subsystem = ((qubitsPQ + qubitsRS) + qubitsPQJW) + qubitsRSJW
209 };
210 nonZero = nonZero + 1;
211 }
212 }
213
214 return genIdxes[0..nonZero - 1];
215}
216