Skip to content
This repository has been archived by the owner on Jan 12, 2024. It is now read-only.

Commit

Permalink
Broombridge 0.3 work (#682)
Browse files Browse the repository at this point in the history
* Started work on updating to BB 0.3.

* Added v0.3 support to qdk-chem convert.

* --from → --format

* Add --flatten option.

* Update magic.

* Temporarily disable test not compatible with 0.3.

* Update test to bb 0.3, remove test made irrelevant by serialization refactor.

* Disable test for loading old version.

* Use trivial symmetry for orbital → fermion transform.

* Fix fourfold symmetry bugs

* Add unit test

* Update datamodel tests for v0.3

* Addressed feedback

---------

Co-authored-by: Christopher Granade <cgranade@cgranade.com>
Co-authored-by: Cassandra Granade <chgranad@microsoft.com>
Co-authored-by: Guang Hao Low <guanghaolow@gmail.com>
Co-authored-by: Dmitry Vasilevsky <dmitryv@microsoft.com>
  • Loading branch information
5 people authored Sep 11, 2023
1 parent de631b7 commit 6b29682
Show file tree
Hide file tree
Showing 20 changed files with 966 additions and 113 deletions.
27 changes: 17 additions & 10 deletions Chemistry.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28803.156
# Visual Studio Version 17
VisualStudioVersion = 17.3.32929.385
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentation", "{561759D2-4D2D-4EE3-9565-9AAEC4A7D64B}"
ProjectSection(SolutionItems) = preProject
Expand All @@ -24,23 +24,25 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Standard", "Standard\src\St
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BroombridgeExamples", "BroombridgeExamples", "{F25F3396-EDE5-4A9F-A428-643EB138F00F}"
ProjectSection(SolutionItems) = preProject
Chemistry\tests\BroombridgeExamples\broombridge_v0.1.yaml = Chemistry\tests\BroombridgeExamples\broombridge_v0.1.yaml
Chemistry\tests\BroombridgeExamples\broombridge_v0.2.yaml = Chemistry\tests\BroombridgeExamples\broombridge_v0.2.yaml
Chemistry\tests\BroombridgeExamples\hydrogen_0.1.yaml = Chemistry\tests\BroombridgeExamples\hydrogen_0.1.yaml
Chemistry\tests\BroombridgeExamples\hydrogen_0.2.yaml = Chemistry\tests\BroombridgeExamples\hydrogen_0.2.yaml
Chemistry\tests\BroombridgeExamples\LiH_0.1.yaml = Chemistry\tests\BroombridgeExamples\LiH_0.1.yaml
Chemistry\tests\BroombridgeExamples\LiH_0.2.yaml = Chemistry\tests\BroombridgeExamples\LiH_0.2.yaml
Chemistry\tests\TestData\Broombridge\broombridge_v0.1.yaml = Chemistry\tests\TestData\Broombridge\broombridge_v0.1.yaml
Chemistry\tests\TestData\Broombridge\broombridge_v0.2.yaml = Chemistry\tests\TestData\Broombridge\broombridge_v0.2.yaml
Chemistry\tests\TestData\Broombridge\hydrogen_0.1.yaml = Chemistry\tests\TestData\Broombridge\hydrogen_0.1.yaml
Chemistry\tests\TestData\Broombridge\hydrogen_0.2.yaml = Chemistry\tests\TestData\Broombridge\hydrogen_0.2.yaml
Chemistry\tests\TestData\Broombridge\LiH_0.1.yaml = Chemistry\tests\TestData\Broombridge\LiH_0.1.yaml
Chemistry\tests\TestData\Broombridge\LiH_0.2.yaml = Chemistry\tests\TestData\Broombridge\LiH_0.2.yaml
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SamplesTests", "Chemistry\tests\SamplesTests\SamplesTests.csproj", "{2A0E61DB-7187-4359-B5C7-C30FCB1D6800}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Metapackage", "Chemistry\src\Metapackage\Metapackage.csproj", "{E8268248-FC5B-4F4E-82FF-5C8CC40950BB}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Metapackage", "Chemistry\src\Metapackage\Metapackage.csproj", "{E8268248-FC5B-4F4E-82FF-5C8CC40950BB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Chemistry", "Chemistry", "{43A9F607-5884-4CB9-A455-01E98F5532E2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{812F2D11-792D-4305-8427-01B632A92299}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tools", "Chemistry\src\Tools\Tools.csproj", "{3EF5845F-B348-4DC9-A905-23A6FB9AB421}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tools", "Chemistry\src\Tools\Tools.csproj", "{3EF5845F-B348-4DC9-A905-23A6FB9AB421}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataModelTests", "Chemistry\tests\DataModelTests\DataModelTests.csproj", "{B86DDA60-44F0-4C05-837E-CEA84DBCADF7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -80,6 +82,10 @@ Global
{3EF5845F-B348-4DC9-A905-23A6FB9AB421}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3EF5845F-B348-4DC9-A905-23A6FB9AB421}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3EF5845F-B348-4DC9-A905-23A6FB9AB421}.Release|Any CPU.Build.0 = Release|Any CPU
{B86DDA60-44F0-4C05-837E-CEA84DBCADF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B86DDA60-44F0-4C05-837E-CEA84DBCADF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B86DDA60-44F0-4C05-837E-CEA84DBCADF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B86DDA60-44F0-4C05-837E-CEA84DBCADF7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -93,6 +99,7 @@ Global
{E8268248-FC5B-4F4E-82FF-5C8CC40950BB} = {F561BE56-63D8-4C33-A3B3-CF2685BC7A5C}
{812F2D11-792D-4305-8427-01B632A92299} = {43A9F607-5884-4CB9-A455-01E98F5532E2}
{3EF5845F-B348-4DC9-A905-23A6FB9AB421} = {812F2D11-792D-4305-8427-01B632A92299}
{B86DDA60-44F0-4C05-837E-CEA84DBCADF7} = {595D5855-8820-48D7-B5E1-9C88215A866A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6869E5BF-551A-40F1-9B6B-D1B27A5676CB}
Expand Down
90 changes: 66 additions & 24 deletions Chemistry/src/DataModel/OrbitalIntegral/OrbitalIntegral.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ public enum Convention
Dirac, Mulliken
}

// NB [Design note]: this intentionally duplicates the corresponding
// enum in the V0_3 class, allowing forward versions
// to add or modify permutation symmetries without
// retroactively changing the definition of V0_3.
public enum PermutationSymmetry
{
Eightfold,
Fourfold,
Trivial
}

/// <summary>
/// Indices of orbitals in the overlap integral.
/// </summary>
Expand All @@ -34,28 +45,35 @@ public enum Convention
/// </summary>
public double Coefficient;

/// <summary>
/// Symmetry of the orbital overlap integral.
/// </summary>
public PermutationSymmetry Symmetry = PermutationSymmetry.Eightfold;

/// <summary>
/// Parameterless constructors. Sets this as an empty OrbitalIntegral with coefficient 0.0
/// </summary>
public OrbitalIntegral() : this(0.0)
{
}

public OrbitalIntegral(double coefficient)
/// <param name="coefficient">coefficient of orbital integral.</param>
/// <param name="symmetry">Convention of symmetry of orbital indices.</param>
public OrbitalIntegral(double coefficient, PermutationSymmetry symmetry = PermutationSymmetry.Eightfold) : this(new int[] { }, coefficient, symmetry)
{
OrbitalIndices = new int[] { };
Coefficient = coefficient;
}

/// <summary>
/// Constructor for orbital integral object.
/// </summary>
/// <param name="orbitalIndices">Array of orbital indices in Dirac notation.</param>
/// <param name="coefficient">coefficient of orbital integral.</param>
public OrbitalIntegral(IEnumerable<int> orbitalIndices, double coefficient = 0.0)
/// <param name="symmetry">Convention of symmetry of orbital indices.</param>
public OrbitalIntegral(IEnumerable<int> orbitalIndices, double coefficient = 0.0, PermutationSymmetry symmetry = PermutationSymmetry.Eightfold)
{
OrbitalIndices = orbitalIndices.ToArray();
Coefficient = coefficient;
Symmetry = symmetry;
}

/// <summary>
Expand All @@ -64,10 +82,12 @@ public OrbitalIntegral(IEnumerable<int> orbitalIndices, double coefficient = 0.0
/// <param name="orbitalIndices">Array of orbital indices.</param>
/// <param name="coefficient">coefficient of orbital integral.</param>
/// <param name="convention">Convention for ordering of orbital indices.</param>
public OrbitalIntegral(IEnumerable<int> orbitalIndices, double coefficient, Convention convention = Convention.Mulliken)
/// <param name="symmetry">Convention of symmetry of orbital indices.</param>
public OrbitalIntegral(IEnumerable<int> orbitalIndices, double coefficient, PermutationSymmetry symmetry, Convention convention = Convention.Mulliken)
{
OrbitalIndices = ConvertIndices(orbitalIndices, convention, Convention.Dirac);
Coefficient = coefficient;
Symmetry = symmetry;
}

public TermType.OrbitalIntegral TermType
Expand Down Expand Up @@ -107,6 +127,40 @@ public void ResetSign()
/// <returns>Length of orbital indices.</returns>
public int Length => OrbitalIndices.Length;

private static int[][] EnumerateTwoBodyPermutations(PermutationSymmetry symmetry, int i, int j, int k, int l) =>
symmetry switch
{
// In Mulliken notation,
// (ij|kl) = (ij|lk) = (ji|kl) = (ji|lk) =
// (kl|ij) = (lk|ij) = (kl|ji) = (lk|ji)
// Orbital indices are in Dirac notation.
PermutationSymmetry.Eightfold => new int[][]
{
new int[] { i, j, k, l }, // 0123
new int[] { j, i, l, k }, // 1032
new int[] { k, l, i, j }, // 2301
new int[] { l, k, j, i }, // 3210
new int[] { i, k, j, l }, // 0213
new int[] { k, i, l, j }, // 2031
new int[] { j, l, i, k }, // 1302
new int[] { l, j, k, i } // 3120
},
// In Mulliken notation,
// (ij|kl) = (ji|lk)* = (kl|ij) = (lk|ji)*, where * denotes complex conjugation
// Orbital indices are in Dirac notation.
PermutationSymmetry.Fourfold => new int[][]
{
new int[] { i, j, k, l }, // Identity
new int[] { l, k, j, i }, // Complex conjugation
new int[] { j, i, l, k }, // Complex conjugation & Change of variables
new int[] { k, l, i, j }, // Change of variables
},
PermutationSymmetry.Trivial => new int[][]
{
new int[] { i, j, k, l }
},
_ => throw new Exception($"Permutation symmetry {symmetry} is not valid for two-body permutations.")
};

/// <summary>
/// Enumerates over all orbital integrals with the same coefficient
Expand All @@ -128,25 +182,13 @@ public OrbitalIntegral[] EnumerateOrbitalSymmetries()
new int[] {i, j},
new int[] {j, i}
};
return symmetries.Distinct(new ArrayEqualityComparer<int>()).Select(o => new OrbitalIntegral(o, coefficient)).ToArray();
return symmetries.Distinct(new ArrayEqualityComparer<int>()).Select(o => new OrbitalIntegral(o, coefficient, Symmetry)).ToArray();
}
else if (OrbitalIndices.Length == 4)
{
var i = OrbitalIndices[0];
var j = OrbitalIndices[1];
var k = OrbitalIndices[2];
var l = OrbitalIndices[3];
var symmetries = new int[][] {
new int[] { i, j, k, l }, // 0123
new int[] { j, i, l, k }, // 1032
new int[] { k, l, i, j }, // 2301
new int[] { l, k, j, i }, // 3210
new int[] { i, k, j, l }, // 0213
new int[] { k, i, l, j }, // 2031
new int[] { j, l, i, k }, // 1302
new int[] { l, j, k, i } // 3120
};
return symmetries.Distinct(new ArrayEqualityComparer<int>()).Select(o => new OrbitalIntegral(o, coefficient)).ToArray();
return EnumerateTwoBodyPermutations(Symmetry, OrbitalIndices[0], OrbitalIndices[1], OrbitalIndices[2], OrbitalIndices[3])
.Distinct(new ArrayEqualityComparer<int>())
.Select(o => new OrbitalIntegral(o, coefficient, Symmetry)).ToArray();
}
else
{
Expand All @@ -160,7 +202,7 @@ public OrbitalIntegral[] EnumerateOrbitalSymmetries()
public OrbitalIntegral Clone()
{
var newArray = OrbitalIndices.Clone<int>();
return new OrbitalIntegral(newArray, Coefficient);
return new OrbitalIntegral(newArray, Coefficient, Symmetry);
}

/// <summary>
Expand All @@ -172,14 +214,14 @@ public OrbitalIntegral ToCanonicalForm()
{
var symmetries = EnumerateOrbitalSymmetries().Select(o => o.OrbitalIndices).ToList();
symmetries.Sort(new ArrayLexicographicComparer<int>());
return new OrbitalIntegral(symmetries.First(), Coefficient);
return new OrbitalIntegral(symmetries.First(), Coefficient, Symmetry);
}

/// <summary>
/// Checks of this orbital integral has indices sorted in canonical order.
/// </summary>
/// <returns>Returns <see cref="bool"/> if the orbital integral indices are canonically sorted
/// and <see cref="false"/> otherwise.
/// and <c>false</c> otherwise.
/// </returns>
public bool IsInCanonicalOrder()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ namespace Microsoft.Quantum.Chemistry.OrbitalIntegrals
/// </summary>
public static partial class Extensions
{

/// <summary>
/// Method for constructing a fermion Hamiltonian from an orbital integral Hamiltonian.
/// </summary>
Expand All @@ -34,7 +33,7 @@ public static FermionHamiltonian ToFermionHamiltonian(
var nOrbitals = sourceHamiltonian.SystemIndices.Max() + 1;
var hamiltonian = new FermionHamiltonian();
Func<OrbitalIntegral, double, IEnumerable<(HermitianFermionTerm, DoubleCoeff)>> conversion =
(orb, coeff) => new OrbitalIntegral(orb.OrbitalIndices, coeff).ToHermitianFermionTerms(nOrbitals, indexConvention)
(orb, coeff) => new OrbitalIntegral(orb.OrbitalIndices, coeff, orb.Symmetry).ToHermitianFermionTerms(nOrbitals, indexConvention)
.Select(o => (o.Item1, o.Item2.ToDoubleCoeff()));

foreach (var termType in sourceHamiltonian.Terms)
Expand Down Expand Up @@ -95,7 +94,9 @@ public static FermionHamiltonian ToFermionHamiltonian(
{
// One-electron orbital integral symmetries
// ij = ji
var pqSpinOrbitals = orbitalIntegral.EnumerateOrbitalSymmetries().EnumerateSpinOrbitals();
var pqSpinOrbitals = orbitalIntegral
.EnumerateOrbitalSymmetries()
.EnumerateSpinOrbitals();

var coefficient = orbitalIntegral.Coefficient;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ namespace Microsoft.Quantum.Chemistry.Broombridge
/// <summary>
/// Latest Broombridge format.
/// </summary>
// NB: When obsoleted, this should likely be made internal rather than
// removed.
[Obsolete(
"Please use collections of ElectronicStructureProblem instead.",
error: false
Expand All @@ -39,7 +41,7 @@ public Data()
/// <summary>
/// Raw deserialized Broombridge data.
/// </summary>
public V0_2.Data Raw { get; set; }
public V0_3.Data Raw { get; set; }

// Root of Broombridge data structure

Expand All @@ -62,12 +64,12 @@ public Data()
/// <summary>
/// Deserialized Broombridge data
/// </summary>
/// <param name="broombridgeV0_2">Broombridge data structure.</param>
internal Data(Broombridge.V0_2.Data broombridgeV0_2)
/// <param name="broombridgeV0_3">Broombridge data structure.</param>
internal Data(Broombridge.V0_3.Data broombridgeV0_3)
{
Raw = broombridgeV0_2;
Schema = broombridgeV0_2.Schema;
VersionNumber = VersionNumber.v0_2;
Raw = broombridgeV0_3;
Schema = broombridgeV0_3.Schema;
VersionNumber = VersionNumber.v0_3;

ProblemDescriptions = Raw.ProblemDescriptions.Select(problem => ProblemDescription.ProcessRawProblemDescription(problem));
}
Expand Down Expand Up @@ -114,14 +116,14 @@ public struct ProblemDescription
/// </summary>
/// <param name="problem">Problem description to be converted</param>
/// <returns>The internal problem description data structure.</returns>
public static ProblemDescription ProcessRawProblemDescription(Broombridge.V0_2.ProblemDescription problem)
public static ProblemDescription ProcessRawProblemDescription(Broombridge.V0_3.ProblemDescription problem)
{
var problemDescription = new ProblemDescription
{
EnergyOffset = problem.EnergyOffset.Value + problem.CoulombRepulsion.Value,
NElectrons = problem.NElectrons,
NOrbitals = problem.NOrbitals,
OrbitalIntegralHamiltonian = V0_2.ToOrbitalIntegralHamiltonian(problem),
OrbitalIntegralHamiltonian = V0_3.ToOrbitalIntegralHamiltonian(problem),
Wavefunctions = problem.InitialStates?.FromBroombridgeV0_2() ?? new Dictionary<string, FermionWavefunction<SpinOrbital>>()
};
return problemDescription;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ internal static OrbitalIntegralHamiltonian ToOrbitalIntegralHamiltonian(
hamiltonian.Add
(hamiltonianData.OneElectronIntegrals.Values
.Select(o => new OrbitalIntegral(o.Item1
.Select(k => (int)(k - 1)), o.Item2, OrbitalIntegral.Convention.Mulliken)
.Select(k => (int)(k - 1)), o.Item2, OrbitalIntegral.PermutationSymmetry.Eightfold, OrbitalIntegral.Convention.Mulliken)
.ToCanonicalForm())
.Distinct());

Expand All @@ -395,7 +395,7 @@ internal static OrbitalIntegralHamiltonian ToOrbitalIntegralHamiltonian(
hamiltonian.Add
(hamiltonianData.TwoElectronIntegrals.Values
.Select(o => new OrbitalIntegral(o.Item1
.Select(k => (int)(k - 1)), o.Item2, OrbitalIntegral.Convention.Mulliken)
.Select(k => (int)(k - 1)), o.Item2, OrbitalIntegral.PermutationSymmetry.Eightfold, OrbitalIntegral.Convention.Mulliken)
.ToCanonicalForm())
.Distinct());

Expand Down
Loading

0 comments on commit 6b29682

Please sign in to comment.