forked from microsoft/Quantum
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProgram.cs
129 lines (105 loc) · 6.06 KB
/
Program.cs
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
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.Simulators;
namespace Microsoft.Quantum.Samples.Ising
{
class Program
{
static void Main(string[] args)
{
// We start by loading the simulator that we will use to run our Q# operations.
using (var qsim = new QuantumSimulator()) {
#region Basic Definitions
// Each site of the Ising model is simulated using a single qubit.
var nSites = 9;
// This coefficient is the initial coupling to the transverse field.
var hXInitial = 1.0;
// This coefficient is the final coupling to the transverse field.
var hXFinal = 0.0;
// This coefficient is the final coupling between sites.
var jFinal = 1.0;
// This is how long we take to sweep over the schedule parameter.
var adiabaticTime = 10.0;
// As we are using a Trotter–Suzuki decomposition as our simulation algorithm,
// we will need to pick a timestep for the simulation, and the order of the
// integrator. The optimal timestep needs to be determined empirically, and
// we find that the following choice works well enough.
var trotterStepSize = 0.1;
var trotterOrder = 2;
// The phase estimation algorithm requires us to choose the duration of time-
// evolution in the oracle it calls, and the bits of precision to which we
// estimate the phase. Note that the error of the energy estimate is typically
// rescaled by 1 / `qpeStepSize`
var qpeStepSize = 0.1;
var nBitsPrecision = 5;
#endregion
#region Ising Model Simulations
// For diagnostic purposes, before we proceed to the next step, we'll print
// out a description of the parameters we just defined.
Console.WriteLine("\nIsing model parameters:");
Console.WriteLine(
$"\t{nSites} sites\n" +
$"\t{hXInitial} initial transverse field coefficient\n" +
$"\t{hXFinal} final transverse field coefficient\n" +
$"\t{jFinal} final two-site coupling coefficient\n" +
$"\t{adiabaticTime} time-interval of interpolation\n" +
$"\t{trotterStepSize} simulation time step \n" +
$"\t{trotterOrder} order of integrator \n" +
$"\t{qpeStepSize} phase estimation oracle simulation time step \n" +
$"\t{nBitsPrecision} phase estimation bits of precision\n");
// Let us now prepare an approximate ground state of the Ising model and estimate its
// ground state energy. This procedure is probabilistic as the quantum state
// obtained at the end of adiabatic evolution has overlap with the ground state that
// is less that one. Thus we repeat several times. In this case, we also know that the
// ground state has all spins pointing in the same direction, so we print the results of
// measuring each site after perform phase estimation to check if we were close.
Console.WriteLine(
"Adiabatic state preparation of the Ising model " +
"with uniform couplings followed by phase estimation and then measurement of sites."
);
// Theoretical prediction of ground state energy when hXFinal is 0.
var energyTheory = - jFinal * ((Double)(nSites - 1));
foreach (var idx in Enumerable.Range(0, 10))
{
// As usual, the Q# operation EstimateIsingEnergy is
// represented by a C# class with a static Run method
// which calls the Q# operation asynchronously and returns
// a Task object. To wait for the operation to complete,
// we can get the Result property of the returned Task.
var data = EstimateIsingEnergy.Run(
qsim,
nSites, hXInitial, hXFinal, jFinal,
adiabaticTime, trotterStepSize, trotterOrder,
qpeStepSize, nBitsPrecision
).Result;
// Next, we need to unpack the tuple returned by
// EstimateIsingEnergy. We do so by using the Item1, Item2
// fields exposed by the C# ValueTuple class. Since Item2
// here represents a Q# array of Result values, we also use
// ToArray to turn it back into a standard C# array.
var energyEst = data.Item1;
var measuredState = data.Item2.ToArray();
Console.WriteLine(
$"State: {string.Join(", ", measuredState.Select(x => x.ToString()).ToArray())} Energy estimate: {energyEst} vs Theory: {energyTheory}."
);
}
Console.WriteLine("\nSame procedure, but using the built-in function.");
foreach (var idx in Enumerable.Range(0, 10))
{
var data = EstimateIsingEnergyUsingBuiltin.Run(qsim, nSites, hXInitial, hXFinal, jFinal, adiabaticTime, trotterStepSize, trotterOrder, qpeStepSize, nBitsPrecision).Result;
var phaseEst = data;
Console.WriteLine("Energy estimate: {0} vs Theory: {1}.", phaseEst, energyTheory);
}
Console.WriteLine("Press Enter to continue...");
Console.ReadLine();
#endregion
}
}
}
}