/// <summary> /// Concatenates two Fermion terms. /// </summary> /// <param name="left">Left Fermion term `x`</param> /// <param name="right">Right Fermion term `y`</param> /// <returns>Returns new <see cref="FermionTerm"/> `xy` where coefficients and /// Fermion operators are multipled together.</returns> public FermionTerm Concatenate(FermionTerm left, FermionTerm right) { return(new FermionTerm( left.CreationAnnihilationIndices.Concat(right.CreationAnnihilationIndices).ToArray(), left.SpinOrbitalIndices.Concat(right.SpinOrbitalIndices).ToArray(), left.coeff * right.coeff )); }
/// <summary> /// Method for adding a <see cref="FermionTerm"/> of type <see cref="FermionTermType"/> /// to a <see cref="FermionHamiltonian"/>. /// </summary> /// <param name="termType">Type of fermion term to be added.</param> /// <param name="term">Fermion term to be added.</param> public void AddFermionTerm(FermionTermType termType, FermionTerm term) { if (!FermionTerms.ContainsKey(termType)) { FermionTerms.Add(termType, new List <FermionTerm>()); } FermionTerms[termType].Add(term); }
/// <summary> /// Method for adding a <see cref="FermionTerm"/> of type <see cref="FermionTermType"/> /// to a <see cref="FermionHamiltonian"/>. /// </summary> /// <param name="termType">Type of fermion term to be added.</param> /// <param name="fermionIdxArray">indices of Fermion term to be added.</param> public void AddFermionTerm(FermionTermType termType, Int64[] fermionIdxArray, Double coefficient) { if (!FermionTerms.ContainsKey(termType)) { FermionTerms.Add(termType, new List <FermionTerm>()); } var conjugateArray = termType.GetConjugateSequence(); var fermionTerm = new FermionTerm( nOrbitals: NOrbitals, caArray: conjugateArray, fermionIdxArray: fermionIdxArray, coeffIn: coefficient ); AddFermionTerm(termType, fermionTerm); }
/// <summary> /// This approximates the Hamiltonian ground state by a greedy algorithm /// that minimizes only the PP term energies. If there are no PP terms, /// states will be occupied in lexicographic order. /// </summary> /// <returns> /// Greedy trial state for minimizing Hamiltonian diagonal one-electron energy. /// </returns> public InputState GreedyStatePreparation() { var label = "Greedy"; (Double, Double)coeff = (1.0, 0.0); var conjugate = Enumerable.Range(0, (int)NElectrons).Select(o => (Int64)1).ToArray(); if (FermionTerms.ContainsKey(PPTermType)) { var hPPTermSortedByCoeff = FermionTerms[PPTermType]; var spinOrbitals = hPPTermSortedByCoeff.OrderBy(o => o.coeff).Select(o => o.SpinOrbitalIndices.First()).Take((int)NElectrons).ToArray(); var fermionTerm = new FermionTerm(conjugate, spinOrbitals, 1.0); fermionTerm.ToSpinOrbitalCanonicalOrder(); fermionTerm.coeff = 1.0; var superposition = new((Double, Double), FermionTerm)[] {
public bool Equals(FermionTerm x) { if (ReferenceEquals(null, x)) { return(false); } else if (ReferenceEquals(this, x)) { return(true); } else if (GetType() != x.GetType()) { return(false); } else { return(this == x); } }
/// <summary> /// Method for adding a <see cref="FermionTerm"/> /// to a <see cref="FermionHamiltonian"/>. /// </summary> /// <param name="term">Fermion term to be added.</param> public void AddFermionTerm(FermionTerm term) { AddFermionTerm(term.GetFermionTermType(), term); }
/// <summary> /// Converts a <c>FermionTerm</c> to canonical order. This generates /// new terms and modifies the coefficient as needed. /// </summary> public List <FermionTerm> ToCanonicalOrder() { // Step 1: anti-commute creation to the left. // Step 2: sort to canonical order var TmpTerms = new Stack <FermionTerm>(); var NewTerms = new List <FermionTerm>(); TmpTerms.Push(this); // 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(tmpTerm); } else { // Anticommute creation and annihilation operators. for (int i = 0; i < tmpTerm.CreationAnnihilationIndices.Count() - 1; i++) { if (tmpTerm.CreationAnnihilationIndices.ElementAt(i) < tmpTerm.CreationAnnihilationIndices.ElementAt(i + 1)) { var antiCommutedCreationAnnihilationIndices = tmpTerm.CreationAnnihilationIndices.ToList(); var antiCommutedSpinOrbitalIndices = tmpTerm.SpinOrbitalIndices.ToList(); // Swap the two elements and flip sign of the coefficient. antiCommutedCreationAnnihilationIndices[i + 1] = tmpTerm.CreationAnnihilationIndices.ElementAt(i); antiCommutedCreationAnnihilationIndices[i] = tmpTerm.CreationAnnihilationIndices.ElementAt(i + 1); antiCommutedSpinOrbitalIndices[i + 1] = tmpTerm.SpinOrbitalIndices.ElementAt(i); antiCommutedSpinOrbitalIndices[i] = tmpTerm.SpinOrbitalIndices.ElementAt(i + 1); var antiCommutedTerm = new FermionTerm(antiCommutedCreationAnnihilationIndices.ToArray(), antiCommutedSpinOrbitalIndices.ToArray(), -1.0 * tmpTerm.coeff); TmpTerms.Push(antiCommutedTerm); // If the two elements have the same spin orbital index, generate a new term. if (antiCommutedSpinOrbitalIndices.ElementAt(i).Equals(antiCommutedSpinOrbitalIndices.ElementAt(i + 1))) { var newCreationAnnihilationIndices = antiCommutedCreationAnnihilationIndices.ToList(); var newSpinOrbitalIndices = antiCommutedSpinOrbitalIndices.ToList(); newCreationAnnihilationIndices.RemoveRange(i, 2); newSpinOrbitalIndices.RemoveRange(i, 2); var newTerm = new FermionTerm(newCreationAnnihilationIndices.ToArray(), newSpinOrbitalIndices.ToArray(), tmpTerm.coeff); TmpTerms.Push(newTerm); } break; } } } } // Anti-commutes spin-orbital indices to canonical order // and changes the sign of the coefficient as necessay. for (int idx = 0; idx < NewTerms.Count(); idx++) { var tmp = NewTerms[idx]; tmp.ToSpinOrbitalCanonicalOrder(); NewTerms[idx] = tmp; } return(NewTerms); }