/** Generates the */ std::vector<std::pair<Indices, Indices>> GenerateTwoPartition(const Indices& indices) const { assert(indices.Size() > 1); std::vector<std::pair<Indices, Indices>> result; // Take the first letter auto first = indices[0]; for (int i=1; i<indices.Size(); i++) { auto current = indices[i]; Indices remaining = indices; Indices gamma; gamma.Insert(first); gamma.Insert(current); remaining.Remove(i); remaining.Remove(0); result.push_back({ gamma, remaining }); } return result; }
Tensor::Tensor Generate(const Indices& indices) const { // Expect all the ranges to be in space unsigned order = indices.Size(); for (auto& index : indices) { if (index.GetRange() != Common::Range(1,3)) { // throw error } } // We cannot build anything with one index! if (indices.Size() == 1) return Tensor::Tensor::Zero(); Tensor::Tensor result = Tensor::Tensor::Zero(); unsigned variableCounter = 0; // Calculate unsigned numEpsilon = (indices.Size() % 2 == 0) ? 0 : 1; unsigned numGammas = (indices.Size() % 2 == 0) ? indices.Size()/2 : (indices.Size()-3)/2; std::vector<Indices> possibleIndices; if (numEpsilon == 1) { possibleIndices = GenerateOddRank(indices); } else { possibleIndices = GenerateEvenRank(indices); } std::vector<Tensor::Tensor> tensors; for (auto& newIndices : possibleIndices) { // Create variable Tensor::Scalar variable ("e", ++variableCounter); tensors.push_back(variable * Tensor::Tensor::EpsilonGamma(numEpsilon, numGammas, newIndices)); } return Tensor::Tensor::Add(tensors); }
std::vector<Indices> GenerateEvenRank(const Indices& indices) const { auto res = GenerateTwoPartition(indices); std::vector<Indices> result; if (indices.Size() == 2) { for (auto& pair : res) { result.push_back(pair.first); } } else { for (auto& pair : res) { auto newComb = GenerateEvenRank(pair.second); for (auto &v : newComb) { auto current = pair.first; current.Append(v); result.push_back(current); } } } return result; }