This repository has been archived by the owner on Jan 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 923
/
Program.cs
185 lines (151 loc) · 8.65 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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#region Using Statements
// We will need several different libraries in this sample.
// Here, we expose these libraries to our program using the
// C# "using" statement, similar to the Q# "open" statement.
// We will use the data model implemented by the Quantum Development Kit chemistry
// libraries. This model defines what a fermionic Hamiltonian is, and how to
// represent Hamiltonians on disk.
using Microsoft.Quantum.Chemistry.OrbitalIntegrals;
using Microsoft.Quantum.Chemistry.Fermion;
using Microsoft.Quantum.Chemistry.QSharpFormat;
// To count gates, we'll use the trace simulator provided with
// the Quantum Development Kit.
using Microsoft.Quantum.Simulation.Simulators;
// The System namespace provides a number of useful built-in
// types and methods that we'll use throughout this sample.
using System;
// The System.Diagnostics namespace provides us with the
// Stopwatch class, which is quite useful for measuring
// how long each gate counting run takes.
using System.Diagnostics;
// The System.Collections.Generic library provides many different
// utilities for working with collections such as lists and dictionaries.
using System.Collections.Generic;
// We use the logging library provided with .NET Core to handle output
// in a robust way that makes it easy to turn on and off different messages.
using Microsoft.Extensions.Logging;
// We use this for convenience methods for manipulating arrays.
using System.Linq;
#endregion
namespace Microsoft.Quantum.Chemistry.Samples.Hydrogen
{
class Program
{
static void Main(string[] args)
{
//////////////////////////////////////////////////////////////////////////
// Introduction //////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// In this example, we will create a spin-orbital representation of the molecular
// Hydrogen Hamiltonian `H`, given overlap coefficients for its one- and
// two - electron integrals.
// We when perform quantum phase estimation to obtain an estimate of
// the molecular Hydrogen ground state energy.
#region Building the Hydrogen Hamiltonian through orbital integrals
// This representation also has two occupied spin-orbitals.
var nElectrons = 2;
// The Coulomb repulsion energy between nuclei is
var energyOffset = 0.713776188;
// One-electron integrals are listed below
// <0|H|0> = -1.252477495
// <1|H|1> = -0.475934275
// Two-electron integrals are listed below
// <00|H|00> = 0.674493166
// <01|H|01> = 0.181287518
// <01|H|10> = 0.663472101
// <11|H|11> = 0.697398010
// Note that orbitals are assumed to be real. Moreover, indistinguishability
// of electrons means that the following integrals are equal.
// <PQ|H|RS> = <PR|H|QS> = <SQ|H|RP> = <SR|H|QP>
// = <QP|H|SR> = <RP|H|SQ> = <QS|H|PR> = <RS|H|PQ>
// Thus it suffices to specify just any one of these terms from each symmetry
// group.
// These orbital integrals are represented using the OrbitalIntegral
// data structure.
var orbitalIntegrals = new OrbitalIntegral[]
{
new OrbitalIntegral(new[] { 0,0 }, -1.252477495),
new OrbitalIntegral(new[] { 1,1 }, -0.475934275),
new OrbitalIntegral(new[] { 0,0,0,0 }, 0.674493166),
new OrbitalIntegral(new[] { 0,1,0,1 }, 0.181287518),
new OrbitalIntegral(new[] { 0,1,1,0 }, 0.663472101),
new OrbitalIntegral(new[] { 1,1,1,1 }, 0.697398010),
// Add the identity term
new OrbitalIntegral(new int[] { }, energyOffset)
};
// We initialize a fermion Hamiltonian data structure and add terms to it
var fermionHamiltonian = new OrbitalIntegralHamiltonian(orbitalIntegrals).ToFermionHamiltonian();
// These orbital integral terms are automatically expanded into
// spin-orbitals. We may print the Hamiltonian to see verify what it contains.
Console.WriteLine("----- Print Hamiltonian");
Console.Write(fermionHamiltonian);
Console.WriteLine("----- End Print Hamiltonian \n");
// We also need to create an input quantum state to this Hamiltonian.
// Let us use the Hartree–Fock state.
var fermionWavefunction = fermionHamiltonian.CreateHartreeFockState(nElectrons);
#endregion
#region Jordan–Wigner representation
// The Jordan–Wigner encoding converts the fermion Hamiltonian,
// expressed in terms of Fermionic operators, to a qubit Hamiltonian,
// expressed in terms of Pauli matrices. This is an essential step
// for simulating our constructed Hamiltonians on a qubit quantum
// computer.
Console.WriteLine("----- Creating Jordan–Wigner encoding");
var jordanWignerEncoding = fermionHamiltonian.ToPauliHamiltonian(Paulis.QubitEncoding.JordanWigner);
Console.WriteLine("----- End Creating Jordan–Wigner encoding \n");
// Print the Jordan–Wigner encoded Hamiltonian to see verify what it contains.
Console.WriteLine("----- Print Hamiltonian");
Console.Write(jordanWignerEncoding);
Console.WriteLine("----- End Print Hamiltonian \n");
#endregion
#region Performing the simulation
// We are now ready to run a quantum simulation of molecular Hydrogen.
// We will use this to obtain an estimate of its ground state energy.
// Here, we make an instance of the simulator used to run our Q# code.
using (var qsim = new QuantumSimulator())
{
// This Jordan–Wigner data structure also contains a representation
// of the Hamiltonian and wavefunction made for consumption by the Q# algorithms.
var qSharpHamiltonianData = jordanWignerEncoding.ToQSharpFormat();
var qSharpWavefunctionData = fermionWavefunction.ToQSharpFormat();
var qSharpData = QSharpFormat.Convert.ToQSharpFormat(qSharpHamiltonianData, qSharpWavefunctionData);
// We specify the bits of precision desired in the phase estimation
// algorithm
var bits = 7;
// We specify the step-size of the simulated time-evolution
var trotterStep = 0.4;
// Choose the Trotter integrator order
Int64 trotterOrder = 1;
// As the quantum algorithm is probabilistic, let us run a few trials.
// This may be compared to true value of
Console.WriteLine("Exact molecular Hydrogen ground state energy: -1.137260278.\n");
Console.WriteLine("----- Performing quantum energy estimation by Trotter simulation algorithm");
for (int i = 0; i < 5; i++)
{
// EstimateEnergyByTrotterization
// Name should make clear that it does it by trotterized
var (phaseEst, energyEst) = GetEnergyByTrotterization.Run(qsim, qSharpData, bits, trotterStep, trotterOrder).Result;
Console.WriteLine($"Rep #{i+1}/5: Energy estimate: {energyEst}; Phase estimate: {phaseEst}");
}
Console.WriteLine("----- End Performing quantum energy estimation by Trotter simulation algorithm\n");
Console.WriteLine("----- Performing quantum energy estimation by Qubitization simulation algorithm");
for (int i = 0; i < 1; i++)
{
// EstimateEnergyByTrotterization
// Name should make clear that it does it by trotterized
var (phaseEst, energyEst) = GetEnergyByQubitization.Run(qsim, qSharpData, bits).Result;
Console.WriteLine($"Rep #{i+1}/1: Energy estimate: {energyEst}; Phase estimate: {phaseEst}");
}
Console.WriteLine("----- End Performing quantum energy estimation by Qubitization simulation algorithm\n");
}
Console.WriteLine("Press Enter to continue...");
if (System.Diagnostics.Debugger.IsAttached)
{
Console.ReadLine();
}
#endregion
}
}
}