我正在编写一个分子动力学程序,该程序需要吸收一个分子中的原子并找到它们可能键合的方式。为此,我有一个Atom对象向量,并使用以下算法生成组合对:
void CombinationKN(std::vector<std::vector<int>> &indices, int K, int N) {
std::string bitmask(K, 1);
bitmask.resize(N, 0);
do {
/* This loop takes forever with larger N values (approx. 3000) */
std::vector<int> indexRow;
for (int i = 0; i < N; i++)
{
if (bitmask[i]) indexRow.push_back(i);
}
indices.push_back(indexRow);
} while (std::prev_permutation(bitmask.begin(), bitmask.end()));
}
这是一种简单的N选择K算法(即返回的索引可以包含(1,2),但不能包含(2,1)),在我的情况下,N是分子中的原子数,而K是2。 / p>
然后我像这样调用算法:
void CalculateBondGraph(const std::vector<Atom *> &atoms, std::map<int,
std::map<int, double>> &bondGraph, ForceField *forceField) {
int natoms = atoms.size();
std::vector<std::vector<int>> indices;
utils::CombinationKN(indices, 2, natoms);
for (auto &v : indices) {
int i = v[0];
int j = v[1];
/*... Check if atoms i and j are bonded based on their coordinates.*/
}
}
此算法的问题在于,对于具有3000+原子的大分子,它需要永久完成。我曾考虑过将其并行化(特别是与OpenMP并行化),但是即使那样,该工作也仍必须拆分到几个线程中,并且仍然需要大量时间才能完成。我需要一种优化此算法的方法,以便计算组合不会花费很长时间。任何帮助表示赞赏。
谢谢你, 维卡斯
答案 0 :(得分:1)
如果CombinationKN
比K
小得多,并且N
大,那么{ {1}}比N
小得多,否则您将很快耗尽内存。
请注意,每个有效的K
都是严格小于N
的{{1}}整数的单调递增序列,反之亦然。直接生成这些代码很容易:
index_row
此外,如果您要对这些组合进行的唯一操作是遍历它们,那么就没有理由浪费存储全部列表所需的(可能非常大量的)内存。上述功能包含在需要时从上一个生成下一个的过程。