in Chemistry/src/DataModel/LadderOperator/LadderOperatorExtensions.cs [28:112]
public static LadderSequence<int> ToLadderSequence(this IEnumerable<(RaisingLowering, int)> setSequence, int setSign = 1) =>
new LadderSequence<int>(setSequence.Select(o => new LadderOperator<int>(o)), setSign);
/// <summary>
/// Construct a sequence of ladder operators from an even-length sequence of integers.
/// </summary>
/// <param name="indices">Even-length sequence of integers.</param>
/// <returns>
/// Sequence of ladder operators with an equal number of creation and annihilation terms
/// that are normal-ordered.
/// </returns>
/// <example>
/// <code>
/// // The following two return the same ladder operator sequence.
/// var seq = new[] { 1, 2, 3, 4 }.ToLadderSequence();
/// var expected = new[] { (u, 1), (u, 2), (d, 3), (d, 4) }.ToLadderSequence();
/// </code>
/// </example>
public static LadderSequence<int> ToLadderSequence(this IEnumerable<int> indices) => new LadderSequence<int>(indices);
internal static LadderSequence<SpinOrbital> ToLadderSequence(this IEnumerable<SpinOrbital> indices) => new LadderSequence<SpinOrbital>(indices);
/// <summary>
/// Construct a sequence of ladder operators from an even-length sequence of spin-orbit indices.
/// </summary>
/// <param name="indices">Even-length sequence of spin-orbit indices.</param>
/// <returns>
/// Sequence of ladder operators with an equal number of creation and annihilation terms
/// that are normal-ordered.
/// </returns>
public static LadderSequence<SpinOrbital> ToLadderSequence(this IEnumerable<(int, Spin)> indices) => indices.Select(x => new SpinOrbital(x)).ToLadderSequence();
#endregion
#region Reordering methods
/// <summary>
/// Converts a <see cref="LadderSequence"/> to normal order.
/// In general, this can generate new terms and modifies the coefficient.
/// </summary>
public static HashSet<NormalOrderedSequence<TIndex>> ToNormalOrder<TIndex>(this LadderSequence<TIndex> ladderOperator)
where TIndex : IEquatable<TIndex>
{
// Recursively anti-commute creation to the left.
var TmpTerms = new Stack<LadderSequence<TIndex>>();
var NewTerms = new HashSet<NormalOrderedSequence<TIndex>>();
TmpTerms.Push(new LadderSequence<TIndex>(ladderOperator));
// Anti-commutes creation and annihilation operators to canonical order
// and creates new terms if spin-orbital indices match.
while (TmpTerms.Any())
{
var tmpTerm = TmpTerms.Pop();
if (tmpTerm.IsInNormalOrder())
{
NewTerms.Add(new NormalOrderedSequence<TIndex>(tmpTerm));
}
else
{
// Anticommute creation and annihilation operators.
for (int i = 0; i < tmpTerm.Sequence.Count() - 1; i++)
{
if ((int)tmpTerm.Sequence.ElementAt(i).Type > (int)tmpTerm.Sequence.ElementAt(i + 1).Type)
{
// If the two elements have the same spin orbital index, generate a new term.
if (tmpTerm.Sequence.ElementAt(i).Index.Equals(tmpTerm.Sequence.ElementAt(i + 1).Index))
{
var newTerm = new LadderSequence<TIndex>(tmpTerm);
newTerm.Sequence.RemoveRange(i, 2);
TmpTerms.Push(newTerm);
}
// Swap the two elements and flip sign of the coefficient.
var tmpOp = tmpTerm.Sequence.ElementAt(i + 1);
tmpTerm.Sequence[i + 1] = tmpTerm.Sequence.ElementAt(i);
tmpTerm.Sequence[i] = tmpOp;
tmpTerm.Coefficient *= -1;
}
}
TmpTerms.Push(tmpTerm);
}
}
return NewTerms;
}