/// <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 }
/// <summary> /// Loads a Hamiltonian from integral data represented /// in LIQ𝑈𝑖|⟩ format. /// Please see the <a href="https://stationq.github.io/Liquid/docs/LIQUiD.pdf"> /// LIQ𝑈𝑖|⟩ documentation</a> for further details about the /// format parsed by this method. /// </summary> /// <param name="lines">Sequence of text describing terms of Hamiltonian.</param> /// <returns> /// An instance of <see cref="FermionHamiltonian"/> representing the /// data contained in <paramref name="lines"/>. /// </returns> public static FermionHamiltonian LoadFromLiquid(string line) { 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 <Int64[], Double>(new Extensions.IntArrayIEqualityComparer()); var fileHIJKLTerms = new Dictionary <Int64[], Double>(new Extensions.IntArrayIEqualityComparer()); var hamiltonian = new FermionHamiltonian(); var nOrbitals = 0L; Match stringMisc = regexMiscellaneous.Match(line); if (stringMisc.Success) { hamiltonian.MiscellaneousInformation = stringMisc.Groups["info"].ToString(); } Match stringnuc = regexnuc.Match(line); if (stringnuc.Success) { hamiltonian.EnergyOffset = Double.Parse(stringnuc.Groups["nuc"].ToString()); } foreach (Match stringPQ in regexPQ.Matches(line)) { if (stringPQ.Success) { var p = Int64.Parse(stringPQ.Groups["p"].ToString()); var q = Int64.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 Int64[] { p, q }, coeff * (10.0).Pow(exponent)); var orbitalIntegralCanonical = orbitalIntegral.ToCanonicalForm(); //Logger.Message.WriteLine($"1e orbital { orbitalIntegral.Print()}, { orbitalIntegralCanonical.Print()}"); 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. } //Logger.Message.WriteLine($"1e orbital collision { orbitalIntegral.Print()}, { orbitalIntegralCanonical.Print()}"); } else { fileHIJTerms.Add(orbitalIntegralCanonical.OrbitalIndices, orbitalIntegralCanonical.Coefficient); } } } foreach (Match stringPQRS in regexPQRS.Matches(line)) { if (stringPQRS.Success) { var p = Int64.Parse(stringPQRS.Groups["p"].ToString()); var q = Int64.Parse(stringPQRS.Groups["q"].ToString()); var r = Int64.Parse(stringPQRS.Groups["r"].ToString()); var s = Int64.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 Int64[] { p, q, r, s }, coeff * (10.0).Pow(exponent)); var orbitalIntegralCanonical = orbitalIntegral.ToCanonicalForm(); //Logger.Message.WriteLine($"2e orbital: { orbitalIntegral.Print()}, { orbitalIntegralCanonical.Print()}"); 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. } //Logger.Message.WriteLine($"2e orbital collision { orbitalIntegral.Print()}, { orbitalIntegralCanonical.Print()}"); } else { fileHIJKLTerms.Add(orbitalIntegralCanonical.OrbitalIndices, orbitalIntegralCanonical.Coefficient); } } } hamiltonian.NOrbitals = nOrbitals; foreach (var ijTerm in fileHIJTerms) { hamiltonian.AddFermionTerm(new OrbitalIntegral(ijTerm.Key, ijTerm.Value)); } foreach (var ijklTerm in fileHIJKLTerms) { hamiltonian.AddFermionTerm(new OrbitalIntegral(ijklTerm.Key, ijklTerm.Value)); } hamiltonian.SortAndAccumulate(); return(hamiltonian); }