microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
copilot/add-link-to-qsharp-application

Branches

Tags

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

Clone

HTTPS

Download ZIP

library/chemistry/src/Trotterization.qs

325lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4export DecomposedIntoTimeStepsCA;
5export TrotterStep;
6export TrotterSimulationAlgorithm;
7
8import Std.Arrays.*;
9import Std.Convert.IntAsDouble;
10import Std.Math.*;
11
12import Generators.EvolutionGenerator;
13
14/// # Summary
15/// Implementation of the first-order Trotter–Suzuki integrator.
16///
17/// # Type Parameters
18/// ## 'T
19/// The type which each time step should act upon; typically, either
20/// `Qubit[]` or `Qubit`.
21///
22/// # Input
23/// ## nSteps
24/// The number of operations to be decomposed into time steps.
25/// ## op
26/// An operation which accepts an index input (type `Int`) and a time
27/// input (type `Double`) and a quantum register (type `'T`) for decomposition.
28/// ## stepSize
29/// Multiplier on size of each step of the simulation.
30/// ## target
31/// A quantum register on which the operations act.
32///
33/// # Example
34/// The following are equivalent:
35/// ```qsharp
36/// op(0, deltaT, target);
37/// op(1, deltaT, target);
38/// ```
39/// and
40/// ```qsharp
41/// Trotter1ImplCA((2, op), deltaT, target);
42/// ```
43operation Trotter1ImplCA<'T>(
44 (nSteps : Int, op : ((Int, Double, 'T) => Unit is Adj + Ctl)),
45 stepSize : Double,
46 target : 'T
47) : Unit is Adj + Ctl {
48
49 for idx in 0..nSteps - 1 {
50 op(idx, stepSize, target);
51 }
52}
53
54/// # Summary
55/// Implementation of the second-order Trotter–Suzuki integrator.
56///
57/// # Type Parameters
58/// ## 'T
59/// The type which each time step should act upon; typically, either
60/// `Qubit[]` or `Qubit`.
61///
62/// # Input
63/// ## nSteps
64/// The number of operations to be decomposed into time steps.
65/// ## op
66/// An operation which accepts an index input (type `Int`) and a time
67/// input (type `Double`) and a quantum register (type `'T`) for decomposition.
68/// ## stepSize
69/// Multiplier on size of each step of the simulation.
70/// ## target
71/// A quantum register on which the operations act.
72///
73/// # Example
74/// The following are equivalent:
75/// ```qsharp
76/// op(0, deltaT / 2.0, target);
77/// op(1, deltaT / 2.0, target);
78/// op(1, deltaT / 2.0, target);
79/// op(0, deltaT / 2.0, target);
80/// ```
81/// and
82/// ```qsharp
83/// Trotter2ImplCA((2, op), deltaT, target);
84/// ```
85operation Trotter2ImplCA<'T>(
86 (nSteps : Int, op : ((Int, Double, 'T) => Unit is Adj + Ctl)),
87 stepSize : Double,
88 target : 'T
89) : Unit is Adj + Ctl {
90 for idx in 0..nSteps - 1 {
91 op(idx, stepSize * 0.5, target);
92 }
93
94 for idx in nSteps - 1.. -1..0 {
95 op(idx, stepSize * 0.5, target);
96 }
97}
98
99/// # Summary
100/// Computes Trotter step size in recursive implementation of
101/// Trotter simulation algorithm.
102///
103/// # Remarks
104/// This operation uses a different indexing convention than that of
105/// [quant-ph/0508139](https://arxiv.org/abs/quant-ph/0508139). In
106/// particular, `DecomposedIntoTimeStepsCA(_, 4)` corresponds to the
107/// scalar $p_2(\lambda)$ in quant-ph/0508139.
108function TrotterStepSize(order : Int) : Double {
109 return 1.0 / (4.0 - 4.0^(1.0 / (IntAsDouble(order) - 1.0)));
110}
111
112
113/// # Summary
114/// Recursive implementation of even-order Trotter–Suzuki integrator.
115///
116/// # Type Parameters
117/// ## 'T
118/// The type which each time step should act upon; typically, either
119/// `Qubit[]` or `Qubit`.
120///
121/// # Input
122/// ## order
123/// Order of Trotter-Suzuki integrator.
124/// ## nSteps
125/// The number of operations to be decomposed into time steps.
126/// ## op
127/// An operation which accepts an index input (type `Int`) and a time
128/// input (type `Double`) and a quantum register (type `'T`) for decomposition.
129/// ## stepSize
130/// Multiplier on size of each step of the simulation.
131/// ## target
132/// A quantum register on which the operations act.
133operation TrotterArbitraryImplCA<'T>(
134 order : Int,
135 (nSteps : Int, op : ((Int, Double, 'T) => Unit is Adj + Ctl)),
136 stepSize : Double,
137 target : 'T
138) : Unit is Adj + Ctl {
139 if (order > 2) {
140 let stepSizeOuter = TrotterStepSize(order);
141 let stepSizeInner = 1.0 - 4.0 * stepSizeOuter;
142 TrotterArbitraryImplCA(order - 2, (nSteps, op), stepSizeOuter * stepSize, target);
143 TrotterArbitraryImplCA(order - 2, (nSteps, op), stepSizeOuter * stepSize, target);
144 TrotterArbitraryImplCA(order - 2, (nSteps, op), stepSizeInner * stepSize, target);
145 TrotterArbitraryImplCA(order - 2, (nSteps, op), stepSizeOuter * stepSize, target);
146 TrotterArbitraryImplCA(order - 2, (nSteps, op), stepSizeOuter * stepSize, target);
147 } elif (order == 2) {
148 Trotter2ImplCA((nSteps, op), stepSize, target);
149 } else {
150 Trotter1ImplCA((nSteps, op), stepSize, target);
151 }
152}
153
154/// # Summary
155/// Returns an operation implementing the Trotter–Suzuki integrator for
156/// a given operation.
157///
158/// # Type Parameters
159/// ## 'T
160/// The type which each time step should act upon; typically, either
161/// `Qubit[]` or `Qubit`.
162///
163/// # Input
164/// ## nSteps
165/// The number of operations to be decomposed into time steps.
166/// ## op
167/// An operation which accepts an index input (type `Int`) and a time
168/// input (type `Double`) for decomposition.
169/// ## trotterOrder
170/// Selects the order of the Trotter–Suzuki integrator to be used.
171/// Order 1 and even orders 2, 4, 6,... are currently supported.
172///
173/// # Output
174/// Returns a unitary implementing the Trotter–Suzuki integrator, where
175/// the first parameter `Double` is the integration step size, and the
176/// second parameter is the target acted upon.
177///
178/// # Remarks
179/// When called with `order` equal to `1`, this function returns an operation
180/// that can be simulated by the lowest-order Trotter–Suzuki integrator
181/// $$
182/// \begin{align}
183/// S_1(\lambda) = \prod_{j = 1}^{m} e^{H_j \lambda},
184/// \end{align}
185/// $$
186/// where we have followed the notation of
187/// [quant-ph/0508139](https://arxiv.org/abs/quant-ph/0508139)
188/// and let $\lambda$ be the evolution time (represented by the first input
189/// of the returned operation), and have let $\{H_j\}_{j = 1}^{m}$ be the
190/// set of (skew-Hermitian) dynamical generators being integrated such that
191/// `op(j, lambda, _)` is simulated by the unitary operator
192/// $e^{H_j \lambda}$.
193///
194/// Similarly, an `order` of `2` returns the second-order symmetric
195/// Trotter–Suzuki integrator
196/// $$
197/// \begin{align}
198/// S_2(\lambda) = \prod_{j = 1}^{m} e^{H_k \lambda / 2}
199/// \prod_{j' = m}^{1} e^{H_{j'} \lambda / 2}.
200/// \end{align}
201/// $$
202///
203/// Higher even values of `order` are implemented using the recursive
204/// construction of [quant-ph/0508139](https://arxiv.org/abs/quant-ph/0508139).
205///
206/// # References
207/// - [ *D. W. Berry, G. Ahokas, R. Cleve, B. C. Sanders* ](https://arxiv.org/abs/quant-ph/0508139)
208function DecomposedIntoTimeStepsCA<'T>(
209 (nSteps : Int, op : ((Int, Double, 'T) => Unit is Adj + Ctl)),
210 trotterOrder : Int
211) : ((Double, 'T) => Unit is Adj + Ctl) {
212 if (trotterOrder == 1) {
213 return Trotter1ImplCA((nSteps, op), _, _);
214 } elif (trotterOrder == 2) {
215 return Trotter2ImplCA((nSteps, op), _, _);
216 } elif (trotterOrder % 2 == 0) {
217 return TrotterArbitraryImplCA(trotterOrder, (nSteps, op), _, _);
218 } else {
219 fail $"Odd order {trotterOrder} not yet supported.";
220 }
221}
222
223/// # Summary
224/// Implements time-evolution by a term contained in a `GeneratorSystem`.
225///
226/// # Input
227/// ## evolutionGenerator
228/// A complete description of the system to be simulated.
229/// ## idx
230/// Integer index to a term in the described system.
231/// ## stepsize
232/// Multiplier on duration of time-evolution by term indexed by `idx`.
233/// ## qubits
234/// Qubits acted on by simulation.
235operation TrotterStepImpl(
236 evolutionGenerator : EvolutionGenerator,
237 idx : Int,
238 stepsize : Double,
239 qubits : Qubit[]
240) : Unit is Adj + Ctl {
241
242 let generatorIndex = evolutionGenerator.System.EntryAt(idx);
243 (evolutionGenerator.EvolutionSet(generatorIndex))(stepsize, qubits);
244}
245
246/// # Summary
247/// Implements a single time-step of time-evolution by the system
248/// described in an `EvolutionGenerator` using a Trotter–Suzuki
249/// decomposition.
250///
251/// # Input
252/// ## evolutionGenerator
253/// A complete description of the system to be simulated.
254/// ## trotterOrder
255/// Order of Trotter integrator. This must be either 1 or an even number.
256/// ## trotterStepSize
257/// Duration of simulated time-evolution in single Trotter step.
258///
259/// # Output
260/// Unitary operation that approximates a single step of time-evolution
261/// for duration `trotterStepSize`.
262function TrotterStep(
263 evolutionGenerator : EvolutionGenerator,
264 trotterOrder : Int,
265 trotterStepSize : Double
266) : (Qubit[] => Unit is Adj + Ctl) {
267
268 // The input to DecomposeIntoTimeStepsCA has signature
269 // (Int, ((Int, Double, Qubit[]) => () is Adj + Ctl))
270 let trotterForm = (
271 evolutionGenerator.System.NumEntries,
272 TrotterStepImpl(evolutionGenerator, _, _, _)
273 );
274 return (DecomposedIntoTimeStepsCA(trotterForm, trotterOrder))(trotterStepSize, _);
275}
276
277/// # Summary
278/// Makes repeated calls to `TrotterStep` to approximate the
279/// time-evolution operator exp(_-iHt_).
280///
281/// # Input
282/// ## trotterStepSize
283/// Duration of simulated time-evolution in single Trotter step.
284/// ## trotterOrder
285/// Order of Trotter integrator. This must be either 1 or an even number.
286/// ## maxTime
287/// Total duration of simulation $t$.
288/// ## evolutionGenerator
289/// A complete description of the system to be simulated.
290/// ## qubits
291/// Qubits acted on by simulation.
292operation TrotterSimulationAlgorithmImpl(
293 trotterStepSize : Double,
294 trotterOrder : Int,
295 maxTime : Double,
296 evolutionGenerator : EvolutionGenerator,
297 qubits : Qubit[]
298) : Unit is Adj + Ctl {
299
300 let nTimeSlices = Ceiling(maxTime / trotterStepSize);
301 let resizedTrotterStepSize = maxTime / IntAsDouble(nTimeSlices);
302
303 for idxTimeSlice in 0..nTimeSlices - 1 {
304 (TrotterStep(evolutionGenerator, trotterOrder, resizedTrotterStepSize))(qubits);
305 }
306}
307
308/// # Summary
309/// `SimulationAlgorithm` function that uses a Trotter–Suzuki
310/// decomposition to approximate the time-evolution operator _exp(-iHt)_.
311///
312/// # Input
313/// ## trotterStepSize
314/// Duration of simulated time-evolution in single Trotter step.
315/// ## trotterOrder
316/// Order of Trotter integrator. This must be either 1 or an even number.
317///
318/// # Output
319/// A `SimulationAlgorithm` type.
320function TrotterSimulationAlgorithm(
321 trotterStepSize : Double,
322 trotterOrder : Int
323) : (Double, EvolutionGenerator, Qubit[]) => Unit is Adj + Ctl {
324 return TrotterSimulationAlgorithmImpl(trotterStepSize, trotterOrder, _, _, _);
325}
326