// Checks if any errors occur while building Hamiltonian for both index conventions.
        public void BuildFermionHamiltonian()
        {
            var sourceHamiltonian = new OrbitalIntegralHamiltonian();

            sourceHamiltonian.Add(orbitalIntegrals);

            var targetHamiltonian0 = sourceHamiltonian.ToFermionHamiltonian(IndexConvention.HalfUp);

            var targetHamiltonian1 = sourceHamiltonian.ToFermionHamiltonian(IndexConvention.UpDown);
        }
Beispiel #2
0
        static void SimulateHubbardHamiltonianTest()
        {
            //////////////////////////////////////////////////////////////////////////
            // Introduction //////////////////////////////////////////////////////////
            //////////////////////////////////////////////////////////////////////////

            // In this example, we will estimate the ground state energy of
            // 1D Hubbard Hamiltonian using the quantum chemistry library.

            // The 1D Hubbard model has `n` sites. Let `i` be the site index,
            // `s` = 1,0 be the spin index, where 0 is up and 1 is down, `t` be the
            // hopping coefficient, `u` the repulsion coefficient, and aᵢₛ the fermionic
            // annihilation operator on the fermion indexed by `(i,s)`. The Hamiltonian
            // of this model is
            //
            //     H ≔ - t Σᵢ (a†ᵢₛ aᵢ₊₁ₛ + a†ᵢ₊₁ₛ aᵢₛ) + u Σᵢ a†ᵢ₀ a†ᵢ₁ aᵢ₁ aᵢ₀
            //
            // Note that we use closed boundary conditions.

            #region Building the Hubbard Hamiltonian through orbital integrals

            var t      = 0.2; // hopping coefficient
            var u      = 1.0; // repulsion coefficient
            var nSites = 6;   // number of sites;
            // Construct Hubbard Hamiltonian
            var hubbardOrbitalIntegralHamiltonian = new OrbitalIntegralHamiltonian();

            foreach (var i in Enumerable.Range(0, nSites))
            {
                hubbardOrbitalIntegralHamiltonian.Add(new OrbitalIntegral(new[] { i, (i + 1) % nSites }, -t));
                hubbardOrbitalIntegralHamiltonian.Add(new OrbitalIntegral(new[] { i, i, i, i }, u));
            }

            // Create fermion representation of Hamiltonian
            // In this case, we use the spin-orbital to integer
            // indexing convention `x = orbitalIdx + spin * nSites`; as it
            // minimizes the length of Jordan–Wigner strings
            var hubbardFermionHamiltonian = hubbardOrbitalIntegralHamiltonian.ToFermionHamiltonian(IndexConvention.HalfUp);

            #endregion


            #region Estimating energies by simulating quantum phase estimation
            // Create Jordan–Wigner representation of Hamiltonian
            var jordanWignerEncoding = hubbardFermionHamiltonian.ToPauliHamiltonian();

            // Create data structure to pass to QSharp.
            var qSharpData = jordanWignerEncoding.ToQSharpFormat().Pad();

            Console.WriteLine($"Estimate Hubbard Hamiltonian energy:");

            #endregion
        }
        /// <summary>
        /// Sample implementation of end-to-end electronic structure problem simulation.
        /// </summary>
        /// <param name="filename"></param>
        public static void SampleWorkflow(
            string filename,
            string wavefunctionLabel,
            IndexConvention indexConvention
            )
        {
            // Deserialize Broombridge from file.
            Data broombridge = Deserializers.DeserializeBroombridge(filename);

            // A single file can contain multiple problem descriptions. Let us pick the first one.
            var problemData = broombridge.ProblemDescriptions.First();

            #region Create electronic structure Hamiltonian
            // Electronic structure Hamiltonians are usually represented compactly by orbital integrals. Let us construct
            // such a Hamiltonian from broombridge.
            OrbitalIntegralHamiltonian orbitalIntegralHamiltonian = problemData.OrbitalIntegralHamiltonian;

            // We can obtain the full fermion Hamiltonian from the more compact orbital integral representation.
            // This transformation requires us to pick a convention for converting a spin-orbital index to a single integer.
            // Let us pick one according to the formula `integer = 2 * orbitalIndex + spinIndex`.
            FermionHamiltonian fermionHamiltonian = orbitalIntegralHamiltonian.ToFermionHamiltonian(indexConvention);

            // We target a qubit quantum computer, which requires a Pauli representation of the fermion Hamiltonian.
            // A number of mappings from fermions to qubits are possible. Let us choose the Jordan–Wigner encoding.
            PauliHamiltonian pauliHamiltonian = fermionHamiltonian.ToPauliHamiltonian(QubitEncoding.JordanWigner);
            #endregion

            #region Create wavefunction Ansatzes
            // A list of trial wavefunctions can be provided in the Broombridge file. For instance, the wavefunction
            // may be a single-reference Hartree--Fock state, a multi-reference state, or a unitary coupled-cluster state.
            // In this case, Broombridge indexes the fermion operators with spin-orbitals instead of integers.
            Dictionary <string, FermionWavefunction <SpinOrbital> > inputStates = problemData.Wavefunctions ?? new Dictionary <string, FermionWavefunction <SpinOrbital> >();

            // If no states are provided, use the Hartree--Fock state.
            // As fermion operators the fermion Hamiltonian are already indexed by, we now apply the desired
            // spin-orbital -> integer indexing convention.
            FermionWavefunction <int> inputState = inputStates.ContainsKey(wavefunctionLabel)
                ? inputStates[wavefunctionLabel].ToIndexing(indexConvention)
                : fermionHamiltonian.CreateHartreeFockState(problemData.NElectrons);
            #endregion

            #region Pipe to QSharp and simulate
            // We now convert this Hamiltonian and a selected state to a format that than be passed onto the QSharp component
            // of the library that implements quantum simulation algorithms.
            var qSharpHamiltonian  = pauliHamiltonian.ToQSharpFormat();
            var qSharpWavefunction = inputState.ToQSharpFormat();
            var qSharpData         = QSharpFormat.Convert.ToQSharpFormat(qSharpHamiltonian, qSharpWavefunction);
            #endregion
        }
        void NormTerms()
        {
            var hamiltonian = new OrbitalIntegralHamiltonian();

            hamiltonian.AddRange(orbitalIntegrals.Select(o => (o, o.Coefficient.ToDoubleCoeff())));
            var oneNorm = hamiltonian.Norm();

            hamiltonian.AddRange(orbitalIntegrals.Select(o => (o, o.Coefficient.ToDoubleCoeff())));
            Assert.Equal(oneNorm * 2.0, hamiltonian.Norm());

            hamiltonian.AddRange(orbitalIntegrals.Select(o => (o, o.Coefficient.ToDoubleCoeff())));
            Assert.Equal(oneNorm * 3.0, hamiltonian.Norm());

            hamiltonian.AddRange(orbitalIntegrals.Select(o => (o, o.Coefficient.ToDoubleCoeff())));
            Assert.Equal(oneNorm * 4.0, hamiltonian.Norm());
        }
        static void MakeHamiltonian()
        {
            // These orbital integrals are represented using the OrbitalIntegral
            // data structure.
            var energyOffset     = 0.713776188;
            var nElectrons       = 2;
            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();

            // 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.
            var jordanWignerEncoding = fermionHamiltonian.ToPauliHamiltonian(Paulis.QubitEncoding.JordanWigner);

            // We also need to create an input quantum state to this Hamiltonian.
            // Let us use the Hartree–Fock state.
            var fermionWavefunction = fermionHamiltonian.CreateHartreeFockState(nElectrons);

            // 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);

            Assert.True(fermionWavefunction.MCFData.Excitations.Keys.Single()
                        .ToIndices().SequenceEqual(new[] { 0, 1 })
                        );
        }
Beispiel #6
0
        public void MakeHamiltonian()
        {
            // We create a `FermionHamiltonian` object to store the terms.
            var hamiltonian = new OrbitalIntegralHamiltonian(
                new[] {
                new OrbitalIntegral(new[] { 0, 1, 2, 3 }, 0.123),
                new OrbitalIntegral(new[] { 0, 1 }, 0.456)
            }
                )
                              .ToFermionHamiltonian(IndexConvention.UpDown);

            // We convert this fermion Hamiltonian to a Jordan–Wigner representation.
            var jordanWignerEncoding = hamiltonian.ToPauliHamiltonian(QubitEncoding.JordanWigner);

            // We now convert this representation into a format consumable by Q#.
            var qSharpData = jordanWignerEncoding.ToQSharpFormat();

            Assert.Equal(10, hamiltonian.CountTerms());
            Assert.Equal(6, jordanWignerEncoding.CountTerms());
        }
        public void JsonEncoding()
        {
            var  filename    = "Broombridge/broombridge_v0.2.yaml";
            Data broombridge = Deserializers.DeserializeBroombridge(filename);
            var  problemData = broombridge.ProblemDescriptions.First();

            OrbitalIntegralHamiltonian original = problemData.OrbitalIntegralHamiltonian;

            var json = JsonConvert.SerializeObject(original);

            File.WriteAllText("oribital.original.json", json);

            var serialized = JsonConvert.DeserializeObject <OrbitalIntegralHamiltonian>(json);

            File.WriteAllText("orbital.serialized.json", JsonConvert.SerializeObject(serialized));

            Assert.Equal(original.SystemIndices.Count, serialized.SystemIndices.Count);
            Assert.Equal(original.Terms.Count, serialized.Terms.Count);
            Assert.Equal(original.Norm(), serialized.Norm());
            Assert.Equal(original.ToString(), serialized.ToString());
        }
        void CheckTermPresent()
        {
            var hamiltonian = new OrbitalIntegralHamiltonian();
            var addTerms0   = orbitalIntegrals.Select(o => (o, o.Coefficient.ToDoubleCoeff())).ToList();

            hamiltonian.AddRange(addTerms0);

            // Check that all terms present.
            foreach (var term in addTerms0)
            {
                Assert.Equal(term.Item2, hamiltonian.GetTerm(term.o));
            }

            // Now check that indexing is by value and not by reference.
            var newTerms0Copy = new[] {
                new[] { 0, 0 },
                new[] { 1, 1 },
                new[] { 0, 0, 0, 0 },
                new[] { 0, 1, 0, 1 },
                new[] { 0, 1, 1, 0 },
                new[] { 1, 1, 1, 1 }
            }.Select(o => new OrbitalIntegral(o, 0.123));

            foreach (var term in addTerms0.Zip(newTerms0Copy, (a, b) => (a.Item2.Value, b)))
            {
                Assert.Equal(term.Item1, hamiltonian.GetTerm(term.b).Value);
            }


            var orb = new OrbitalIntegral(new[] { 0, 1, 1, 0 }, 4.0);

            Assert.Equal(new[] { 0, 1, 1, 0 }, orb.OrbitalIndices);
            Assert.Equal(addTerms0[4].o.OrbitalIndices, orb.OrbitalIndices);

            Debug.WriteLine($"Term type is { orb.TermType.ToString()}");
            Debug.WriteLine($"Coefficient is { hamiltonian.Terms[orb.TermType][new OrbitalIntegral(orb.OrbitalIndices, orb.Coefficient)]}");
            Debug.WriteLine($"Coefficient is { hamiltonian.Terms[orb.TermType][addTerms0[4].o]}");

            Assert.True(0.663472101 == hamiltonian.Terms[orb.TermType][new OrbitalIntegral(orb.OrbitalIndices, orb.Coefficient)]);
        }
Beispiel #9
0
        /// <summary>
        /// Loads a FermionHamiltonian from either a .yaml file with a Broombridge definition,
        /// or from a ProblemDescription.
        /// If the fileName is specified, that will be used and the problemDescription will be ignored.
        /// </summary>
        public Task <ExecutionResult> Run(string input, IChannel channel)
        {
            if (string.IsNullOrWhiteSpace(input))
            {
                channel.Stderr("Please provide the name of a Broombridge file or a problem description to load the fermion Hamiltonian from.");
                return(Task.FromResult(ExecuteStatus.Error.ToExecutionResult()));
            }

            // Identify the ProblemDescription with the hamiltonian from the arguments.
            var args        = JsonConvert.DeserializeObject <Arguments>(input);
            var problemData = SelectProblemDescription(args);

            // Electronic structure Hamiltonians are usually represented compactly by orbital integrals. Let us construct
            // such a Hamiltonian from broombridge.
            OrbitalIntegralHamiltonian orbitalIntegralHamiltonian = problemData.OrbitalIntegralHamiltonian;

            // We can obtain the full fermion Hamiltonian from the more compact orbital integral representation.
            // This transformation requires us to pick a convention for converting a spin-orbital index to a single integer.
            // Let us pick one according to the formula `integer = 2 * orbitalIndex + spinIndex`.
            FermionHamiltonian fermionHamiltonian = orbitalIntegralHamiltonian.ToFermionHamiltonian(args.IndexConvention);

            return(Task.FromResult(fermionHamiltonian.ToExecutionResult()));
        }
Beispiel #10
0
        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

            // One of the simplest representations of Hydrogen uses only two
            // molecular orbitals indexed by `0` and `1`.
            var nOrbitals = 2;

            // 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
        }
Beispiel #11
0
        static void MolecularHydrogenTest()
        {
            //////////////////////////////////////////////////////////////////////////
            // Introduction //////////////////////////////////////////////////////////
            //////////////////////////////////////////////////////////////////////////

            // In this example, we will create a spin-orbital representation of the molecular
            // Hydrogen Hamiltonian `H`, given ovelap 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

            // One of the simplest representations of Hydrogen uses only two
            // molecular orbitals indexed by `0` and `1`.
            var nOrbitals = 2;

            // 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 sufficies 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");
            #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.


            // 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);



            Console.WriteLine("Press Enter to continue...");
            if (System.Diagnostics.Debugger.IsAttached)
            {
                Console.ReadLine();
            }
            #endregion
        }
Beispiel #12
0
        static void Main(string[] args)
        {
            //////////////////////////////////////////////////////////////////////////
            // Introduction //////////////////////////////////////////////////////////
            //////////////////////////////////////////////////////////////////////////

            // In this example, we will estimate the ground state energy of
            // 1D Hubbard Hamiltonian using the quantum chemistry library.

            // The 1D Hubbard model has `n` sites. Let `i` be the site index,
            // `s` = 1,0 be the spin index, where 0 is up and 1 is down, `t` be the
            // hopping coefficient, `u` the repulsion coefficient, and aᵢₛ the fermionic
            // annihilation operator on the fermion indexed by `(i,s)`. The Hamiltonian
            // of this model is
            //
            //     H ≔ - t Σᵢ (a†ᵢₛ aᵢ₊₁ₛ + a†ᵢ₊₁ₛ aᵢₛ) + u Σᵢ a†ᵢ₀ a†ᵢ₁ aᵢ₁ aᵢ₀
            //
            // Note that we use closed boundary conditions.

            #region Building the Hubbard Hamiltonian through orbital integrals

            var t      = 0.2; // hopping coefficient
            var u      = 1.0; // repulsion coefficient
            var nSites = 6;   // number of sites;
            // Construct Hubbard Hamiltonian
            var hubbardOrbitalIntegralHamiltonian = new OrbitalIntegralHamiltonian();

            foreach (var i in Enumerable.Range(0, nSites))
            {
                hubbardOrbitalIntegralHamiltonian.Add(new OrbitalIntegral(new[] { i, (i + 1) % nSites }, -t));
                hubbardOrbitalIntegralHamiltonian.Add(new OrbitalIntegral(new[] { i, i, i, i }, u));
            }

            // Create fermion representation of Hamiltonian
            // In this case, we use the spin-orbital to integer
            // indexing convention `x = orbitalIdx + spin * nSites`; as it
            // minimizes the length of Jordan–Wigner strings
            var hubbardFermionHamiltonian = hubbardOrbitalIntegralHamiltonian.ToFermionHamiltonian(IndexConvention.HalfUp);

            #endregion


            #region Estimating energies by simulating quantum phase estimation
            // Create Jordan–Wigner representation of Hamiltonian
            var jordanWignerEncoding = hubbardFermionHamiltonian.ToPauliHamiltonian();

            // Create data structure to pass to QSharp.
            var qSharpData = jordanWignerEncoding.ToQSharpFormat().Pad();

            Console.WriteLine($"Estimate Hubbard Hamiltonian energy:");
            // Bits of precision in phase estimation.
            var bits = 7;

            // Repetitions to find minimum energy.
            var reps = 5;

            // Trotter step size
            var trotterStep = 0.5;

            using (var qsim = new QuantumSimulator())
            {
                for (int i = 0; i < reps; i++)
                {
                    // EstimateEnergyByTrotterization
                    // Name should make clear that it does it by trotterized
                    var(phaseEst, energyEst) = GetEnergy.Run(qsim, qSharpData, bits, trotterStep).Result;

                    Console.WriteLine($"Rep #{i}: Energy estimate: {energyEst}; Phase estimate: {phaseEst}");
                }
            }

            Console.WriteLine("Press Enter to continue...");
            if (System.Diagnostics.Debugger.IsAttached)
            {
                Console.ReadLine();
            }
            #endregion
        }
        void BuildOrbitalIntegralHamiltonian()
        {
            var hamiltonian = new OrbitalIntegralHamiltonian();

            hamiltonian.Add(orbitalIntegrals);
        }
Beispiel #14
0
        /// <summary>
        ///     Deserializes an FCIDUMP-formatted problem description.
        /// </summary>
        /// <param name="reader">A stream for reading FCIDUMP data.</param>
        /// <returns>
        ///      An electronic structure problem deserialized from the file.
        /// </returns>
        public static IEnumerable <ElectronicStructureProblem> Deserialize(TextReader reader)
        {
            // FCIDUMP files begin with a FORTRAN-formatted namelist, delimited
            // by &FCI and &END. We start by extracting that namelist.
            var allText = reader.ReadToEnd();
            var lines   = Regex.Split(allText, "\r\n|\r|\n");

            if (lines == null)
            {
                throw new IOException("Expected a non-empty FCIDUMP file.");
            }
            var header = System.String.Join("\n", lines.TakeWhile(line => line.Trim() != "&END")).Trim();
            var body   = lines !.SkipWhile(line => line.Trim() != "&END").Skip(1).ToList();

            // Make sure that the header starts with &FCI, as expected.
            if (!header.StartsWith("&FCI"))
            {
                throw new IOException("FCIDUMP file did not start with \"&FCI\" as expected.");
            }

            // Split out the &FCI and &END lines, turn the rest into a dictionary of namelist items.
            var namelist = Regex.Matches(
                header
                .Replace("&FCI", "")
                .Replace("&END", ""),
                pattern: "\\s*(?<identifier>\\w+)\\s*=\\s*(?<value>[^=]+),\\s*"
                )
                           .ToDictionary(
                match => match.Groups["identifier"].Value,
                match => match.Groups["value"].Value
                );

            var hamiltonian = new OrbitalIntegralHamiltonian();
            var arrayData   = body
                              .Select(line => line.Trim())
                              .Where(line => line.Length > 0)
                              .Select(
                line => line.Split(" ", StringSplitOptions.RemoveEmptyEntries)
                )
                              .Select(
                row => (
                    Double.Parse(row[0]),
                    row[1..].Select(Int32.Parse).Where(idx => idx != 0).ToZeroBasedIndices()
                    )
                );

            var(coulomb, _) = arrayData.Where(item => item.Item2.Length == 0).Single();
            hamiltonian.Add(arrayData
                            .Where(row => row.Item2.Length > 0)
                            .SelectMaybe(
                                row => row.Item2.Length % 2 == 0
                           ? new OrbitalIntegral(
                                    row.Item2, row.Item1, OrbitalIntegral.Convention.Mulliken
                                    ).ToCanonicalForm()
                           : null
                                )
                            .Distinct()
                            );

            // The identity term in deserialized Hamiltonians is the sum of the
            // Coloumb repulsion and the energy offset. Since only the former
            // exists in FCIDUMP, we set the identity term accordingly.
            hamiltonian.Add(new OrbitalIntegral(), coulomb);

            return(new List <ElectronicStructureProblem>
            {
                new ElectronicStructureProblem
                {
                    EnergyOffset = 0.0.WithUnits("hartree"),
                    CoulombRepulsion = coulomb.WithUnits("hartree"),
                    Metadata = new Dictionary <string, object>
                    {
                        ["Comment"] = "Imported from FCIDUMP"
                    },
                    NElectrons = Int32.Parse(namelist["NELEC"]),
                    NOrbitals = Int32.Parse(namelist["NORB"]),
                    OrbitalIntegralHamiltonian = hamiltonian
                }
            });
        }
Beispiel #15
0
        internal static ElectronicStructureProblem DeserializeSingleProblem(string line)
        {
            var problem = new ElectronicStructureProblem()
            {
                Metadata = new Dictionary <string, object>()
            };

            var regexMiscellaneous = new Regex(@"((info=(?<info>[^\s]*)))");
            var regexnuc           = new Regex(@"nuc=(?<nuc>-?\s*\d*.\d*)");
            var regexPQ            = new Regex(@"(^|\s+)(?<p>\d+),(?<q>\d+)\D*=\s*(?<coeff>-?\s*\d*.\d*)e?(?<exponent>-?\d*)");
            var regexPQRS          = new Regex(@"(^|\s+)(?<p>\d+)\D+(?<q>\d+)\D+(?<r>\d+)\D+(?<s>\d+)\D*=\s*(?<coeff>-?\s*\d*.\d*)e?(?<exponent>-?\d*)");

            double coulombRepulsion = 0.0;
            var    fileHIJTerms     = new Dictionary <int[], double>(new Extensions.ArrayEqualityComparer <int>());
            var    fileHIJKLTerms   = new Dictionary <int[], double>(new Extensions.ArrayEqualityComparer <int>());
            var    hamiltonian      = new OrbitalIntegralHamiltonian();

            var nOrbitals = 0L;

            Match stringMisc = regexMiscellaneous.Match(line);

            if (stringMisc.Success)
            {
                problem.Metadata["misc_info"] = stringMisc.Groups["info"].ToString();
            }


            Match stringnuc = regexnuc.Match(line);

            if (stringnuc.Success)
            {
                coulombRepulsion = double.Parse(stringnuc.Groups["nuc"].ToString()).ToDoubleCoeff();
                hamiltonian.Add(TermType.OrbitalIntegral.Identity, new OrbitalIntegral(), coulombRepulsion);
            }
            foreach (Match stringPQ in regexPQ.Matches(line))
            {
                if (stringPQ.Success)
                {
                    var p              = int.Parse(stringPQ.Groups["p"].ToString());
                    var q              = int.Parse(stringPQ.Groups["q"].ToString());
                    var coeff          = double.Parse(stringPQ.Groups["coeff"].ToString());
                    var exponentString = stringPQ.Groups["exponent"].ToString();
                    var exponent       = 0.0;
                    if (exponentString != "")
                    {
                        exponent = double.Parse(stringPQ.Groups["exponent"].ToString());
                    }
                    nOrbitals = new long[] { nOrbitals, p + 1, q + 1 }.Max();

                    var orbitalIntegral          = new OrbitalIntegral(new int[] { p, q }, coeff * (10.0).Pow(exponent));
                    var orbitalIntegralCanonical = orbitalIntegral.ToCanonicalForm();


                    if (fileHIJTerms.ContainsKey(orbitalIntegralCanonical.OrbitalIndices))
                    {
                        // Check consistency
                        if (fileHIJTerms[orbitalIntegralCanonical.OrbitalIndices] != orbitalIntegral.Coefficient)
                        {
                            // Consistency check failed.
                            throw new System.NotSupportedException(
                                      $"fileHPQTerm Consistency check fail. " +
                                      $"Orbital integral {orbitalIntegral} coefficient {orbitalIntegral.Coefficient}" +
                                      $"does not match recorded {orbitalIntegralCanonical} coefficient {fileHIJTerms[orbitalIntegral.OrbitalIndices]}.");
                        }
                        else
                        {
                            // Consistency check passed.
                        }
                    }
                    else
                    {
                        fileHIJTerms.Add(orbitalIntegralCanonical.OrbitalIndices, orbitalIntegralCanonical.Coefficient);
                    }
                }
            }
            foreach (Match stringPQRS in regexPQRS.Matches(line))
            {
                if (stringPQRS.Success)
                {
                    var p              = int.Parse(stringPQRS.Groups["p"].ToString());
                    var q              = int.Parse(stringPQRS.Groups["q"].ToString());
                    var r              = int.Parse(stringPQRS.Groups["r"].ToString());
                    var s              = int.Parse(stringPQRS.Groups["s"].ToString());
                    var coeff          = double.Parse(stringPQRS.Groups["coeff"].ToString());
                    var exponentString = stringPQRS.Groups["exponent"].ToString();
                    var exponent       = 0.0;
                    if (exponentString != "")
                    {
                        exponent = double.Parse(stringPQRS.Groups["exponent"].ToString());
                    }
                    nOrbitals = new long[] { nOrbitals, p + 1, q + 1, r + 1, s + 1 }.Max();

                    var orbitalIntegral          = new OrbitalIntegral(new int[] { p, q, r, s }, coeff * (10.0).Pow(exponent));
                    var orbitalIntegralCanonical = orbitalIntegral.ToCanonicalForm();


                    if (fileHIJKLTerms.ContainsKey(orbitalIntegralCanonical.OrbitalIndices))
                    {
                        // Check consistency
                        if (fileHIJKLTerms[orbitalIntegralCanonical.OrbitalIndices] != orbitalIntegral.Coefficient)
                        {
                            // Consistency check failed.
                            throw new System.NotSupportedException(
                                      $"fileHPQRSTerm Consistency check fail. " +
                                      $"Orbital integral {orbitalIntegral.OrbitalIndices} coefficient {orbitalIntegral.Coefficient}" +
                                      $"does not match recorded {orbitalIntegralCanonical.OrbitalIndices} coefficient {fileHIJKLTerms[orbitalIntegral.OrbitalIndices]}.");
                        }
                        else
                        {
                            // Consistency check passed.
                        }
                    }
                    else
                    {
                        fileHIJKLTerms.Add(orbitalIntegralCanonical.OrbitalIndices, orbitalIntegralCanonical.Coefficient);
                    }
                }
            }

            hamiltonian.Add(fileHIJTerms.Select(o => new OrbitalIntegral(o.Key, o.Value)).ToList());

            hamiltonian.Add(fileHIJKLTerms.Select(o => new OrbitalIntegral(o.Key, o.Value)).ToList());

            problem.OrbitalIntegralHamiltonian = hamiltonian;
            problem.NOrbitals        = System.Convert.ToInt32(nOrbitals);
            problem.CoulombRepulsion = coulombRepulsion.WithUnits("hartree");

            return(problem);
        }
        void BuildHamiltonian()
        {
            var hamiltonian = new OrbitalIntegralHamiltonian();

            hamiltonian.AddRange(orbitalIntegrals.Select(o => (o, o.Coefficient.ToDoubleCoeff())));
        }