/// <summary>
        /// Updates an instance of <see cref="FermionHamiltonian"/>
        /// with all spin-orbitals from described by a sequence of two-body orbital integrals.
        /// </summary>
        /// <param name="nOrbitals">Total number of distinct orbitals.</param>
        /// <param name="hpqTerms">Sequence of two-body orbital integrals.</param>
        /// <param name="hamiltonian">Fermion Hamiltonian to be updated.</param>
        public void CreateTwoBodySpinOrbitalTerms(OrbitalIntegral orbitalIntegral)
        {
            // One-electron orbital integral symmetries
            // ij = ji
            var pqSpinOrbitals = orbitalIntegral.EnumerateOrbitalSymmetries().EnumerateSpinOrbitals();

            var coefficient = orbitalIntegral.Coefficient;

            foreach (var pq in pqSpinOrbitals)
            {
                var p = pq[0];
                var q = pq[1];

                var pInt = p.ToInt();
                var qInt = q.ToInt();
                if (pInt == qInt)
                {
                    AddFermionTerm(FermionTermType.Common.PPTermType, new FermionTerm {
                        CreationAnnihilationIndices = new Int64[] { 1, 0 }, SpinOrbitalIndices = pq, coeff = coefficient
                    });
                }
                else if (pInt < qInt)
                {
                    AddFermionTerm(FermionTermType.Common.PQTermType, new FermionTerm {
                        CreationAnnihilationIndices = new Int64[] { 1, 0 }, SpinOrbitalIndices = pq, coeff = 2.0 * coefficient
                    });
                }
            }
        }
 /// <summary>
 /// Method for adding to a <see cref="FermionHamiltonian"/>.
 /// all <see cref="FermionTerm"/> generalted by all all symmetries of
 /// <see cref="OrbitalIntegral.EnumerateOrbitalSymmetries"/> and
 /// <see cref="OrbitalIntegral.EnumerateSpinOrbitals"/>.
 /// </summary>
 /// <param name="termType"><see cref="OrbitalIntegral"/> representing terms to be added.</param>
 public void AddFermionTerm(OrbitalIntegral orbitalIntgral)
 {
     if (orbitalIntgral.Length() == 2)
     {
         CreateTwoBodySpinOrbitalTerms(orbitalIntgral);
     }
     else if (orbitalIntgral.Length() == 4)
     {
         CreateFourBodySpinOrbitalTerms(orbitalIntgral);
     }
     else
     {
         throw new System.NotImplementedException();
     }
 }
        /// <summary>
        /// Updates an instance of <see cref="FermionHamiltonian"/>
        /// with all spin-orbitals from described by a sequence of four-body orbital integrals.
        /// </summary>
        /// <param name="nOrbitals">Total number of distinct orbitals.</param>
        /// <param name="rawPQRSTerms">Sequence of four-body orbital integrals.</param>
        /// <param name="hamiltonian">Fermion Hamiltonian to be updated.</param>
        public void CreateFourBodySpinOrbitalTerms(OrbitalIntegral orbitalIntegral)
        {
            // Two-electron orbital integral symmetries
            // ijkl = lkji = jilk = klij = ikjl = ljki = kilj = jlik.
            var pqrsSpinOrbitals = orbitalIntegral.EnumerateOrbitalSymmetries().EnumerateSpinOrbitals();
            var coefficient      = orbitalIntegral.Coefficient;


            // We only need to see one of these.
            // Now iterate over pqrsArray
            foreach (var pqrs in pqrsSpinOrbitals)
            {
                var p = pqrs[0];
                var q = pqrs[1];
                var r = pqrs[2];
                var s = pqrs[3];

                var pInt = p.ToInt();
                var qInt = q.ToInt();
                var rInt = r.ToInt();
                var sInt = s.ToInt();

                // Only consider terms on the lower diagonal due to Hermitian symmetry.

                // For terms with two different orbital indices, possibilities are
                // PPQQ (QQ = 0), PQPQ, QPPQ (p<q), PQQP, QPQP (p<q), QQPP (PP=0)
                // Hence, if we only count PQQP, and PQPQ, we need to double the coefficient.
                // iU jU jU iU | iU jD jD iD | iD jU jU iD | iD jD jD iD
                if (pInt == sInt && qInt == rInt && pInt < qInt)
                {   // PQQP
                    AddFermionTerm(FermionTermType.Common.PQQPTermType, new FermionTerm {
                        CreationAnnihilationIndices = new Int64[] { 1, 1, 0, 0 }, SpinOrbitalIndices = new SpinOrbital[] { p, q, r, s }, coeff = 1.0 * coefficient
                    });
                }
                else if (pInt == rInt && qInt == sInt && pInt < qInt)
                {
                    // iU jU iU jU | iD jD iD jD
                    // PQPQ
                    AddFermionTerm(FermionTermType.Common.PQQPTermType, new FermionTerm {
                        CreationAnnihilationIndices = new Int64[] { 1, 1, 0, 0 }, SpinOrbitalIndices = new SpinOrbital[] { p, q, s, r }, coeff = -1.0 * coefficient
                    });
                }
                else if (qInt == rInt && pInt < sInt && rInt != sInt && pInt != qInt)
                {
                    // PQQR
                    // For any distinct pqr, [i;j;j;k] generates PQQR ~ RQQP ~ QPRQ ~ QRPQ. We only need to record one.
                    if (rInt < sInt)
                    {
                        if (pInt < qInt)
                        {
                            AddFermionTerm(FermionTermType.Common.PQQRTermType, new FermionTerm {
                                CreationAnnihilationIndices = new Int64[] { 1, 1, 0, 0 }, SpinOrbitalIndices = new SpinOrbital[] { p, q, s, r }, coeff = -2.0 * coefficient
                            });
                        }
                        else
                        {
                            AddFermionTerm(FermionTermType.Common.PQQRTermType, new FermionTerm {
                                CreationAnnihilationIndices = new Int64[] { 1, 1, 0, 0 }, SpinOrbitalIndices = new SpinOrbital[] { q, p, s, r }, coeff = 2.0 * coefficient
                            });
                        }
                    }
                    else
                    {
                        if (pInt < qInt)
                        {
                            AddFermionTerm(FermionTermType.Common.PQQRTermType, new FermionTerm {
                                CreationAnnihilationIndices = new Int64[] { 1, 1, 0, 0 }, SpinOrbitalIndices = new SpinOrbital[] { p, q, r, s }, coeff = 2.0 * coefficient
                            });
                        }
                        else
                        {
                            AddFermionTerm(FermionTermType.Common.PQQRTermType, new FermionTerm {
                                CreationAnnihilationIndices = new Int64[] { 1, 1, 0, 0 }, SpinOrbitalIndices = new SpinOrbital[] { q, p, r, s }, coeff = -2.0 * coefficient
                            });
                        }
                    }
                }
                else if (qInt == sInt && pInt < rInt && rInt != sInt && pInt != sInt)
                {
                    // PQRQ
                    // For any distinct pqr, [i;j;k;j] generates {p, q, r, q}, {q, r, q, p}, {q, p, q, r}, {r, q, p, q}. We only need to record one.
                    if (pInt < qInt)
                    {
                        if (rInt > qInt)
                        {
                            AddFermionTerm(FermionTermType.Common.PQQRTermType, new FermionTerm {
                                CreationAnnihilationIndices = new Int64[] { 1, 1, 0, 0 }, SpinOrbitalIndices = new SpinOrbital[] { p, q, r, s }, coeff = 2.0 * coefficient
                            });
                        }
                        else
                        {
                            AddFermionTerm(FermionTermType.Common.PQQRTermType, new FermionTerm {
                                CreationAnnihilationIndices = new Int64[] { 1, 1, 0, 0 }, SpinOrbitalIndices = new SpinOrbital[] { p, q, s, r }, coeff = -2.0 * coefficient
                            });
                        }
                    }
                    else
                    {
                        AddFermionTerm(FermionTermType.Common.PQQRTermType, new FermionTerm {
                            CreationAnnihilationIndices = new Int64[] { 1, 1, 0, 0 }, SpinOrbitalIndices = new SpinOrbital[] { q, p, r, s }, coeff = -2.0 * coefficient
                        });
                    }
                }
                else if (pInt < qInt && pInt < rInt && pInt < sInt && qInt != rInt && qInt != sInt && rInt != sInt)
                {
                    // PQRS
                    // For any distinct pqrs, [i;j;k;l] generates
                    // {{p, q, r, s}<->{s, r, q, p}<->{q, p, s, r}<->{r, s, p, q},
                    // {1,2,3,4}<->{4,3,2,1}<->{2,1,4,3}<->{3,4,1,2}
                    // {p, r, q, s}<->{s, q, r, p}<->{r, p, s, q}<->{q, s, p, r}}
                    // 1324, 4231, 3142, 2413
                    if (rInt < sInt)
                    {
                        AddFermionTerm(FermionTermType.Common.PQRSTermType, new FermionTerm {
                            CreationAnnihilationIndices = new Int64[] { 1, 1, 0, 0 }, SpinOrbitalIndices = new SpinOrbital[] { p, q, s, r }, coeff = -2.0 * coefficient
                        });
                    }
                    else
                    {
                        AddFermionTerm(FermionTermType.Common.PQRSTermType, new FermionTerm {
                            CreationAnnihilationIndices = new Int64[] { 1, 1, 0, 0 }, SpinOrbitalIndices = new SpinOrbital[] { p, q, r, s }, coeff = 2.0 * coefficient
                        });
                    }
                }
            }
        }
예제 #4
0
        /// <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);
        }
예제 #5
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);
        }