我正在编写一个小程序来计算物理问题,但是我在从二维数组中擦除元素时遇到了问题。我正在使用XCode编译(所以GDB)。
问题总是出现在walker.erase(walker.begin()+ loacationInArray)部分(在void diffuseWalkers函数中),并且总是经过不同数量的函数调用。所以有时,“热化”循环可能会运行50次,有时则会一直运行。我经常收到一个EXC_BAD_ACCESS错误,偶尔会出现malloc错误。
任何帮助都会非常感激,因为我已经尝试了所有的东西而且真的看不出我做错了什么。我已经发布了以下代码。名为'heliumHeader.h'的头文件包含一些对我的问题不重要的数学函数。
#include "heliumHeader.h"
void copyVectorInformation(vector<double>& walker, vector<double>& walkerTemp);
void diffuseWalker(double beta, double a, double alpha, int locationInArray, vector<double>& walker, double dt,
double& trialEnergy, int& numberOfWalkers, int targetNumberOfWalkers);
using namespace std;
int main(){
srand(time(NULL));
double s=0.; //inter-molecular distance
double beta = 0.15;
double alpha = 2.;
double dt=0.1;
int numberOfWalkers = 1; //number of particles
int targetNumberOfWalkers = numberOfWalkers;
//2D-vectors to hold information
vector<vector<double> > walker(numberOfWalkers,6);
//solve for a
double a = 1.;
for(int i=0; i<20;i++)
a = 1./(1.+exp(-s/a));
//set up sums
double localEnergy, trialEnergy, localEnergy2, trialEnergy2;
localEnergy = trialEnergy = localEnergy2 = trialEnergy2 = 0.;
//put the walkers randomly in space & get the energy of that configuration
for(int i=0; i<walker.size(); i++){
for(int j=0; j<6; j++)
walker[i][j]=randomPositiveNegative();
localEnergy += calculateEnergy(beta, alpha, a, walker[i]);
}
localEnergy /= numberOfWalkers;
double beforeEnergy = localEnergy;
cout << "local energy of random " << localEnergy << endl;
trialEnergy = -2.903;
//move the walkers
for(int thermalisationCounter = 1; thermalisationCounter<1000; thermalisationCounter++){
for(int i=0; i<walker.size(); i++)
diffuseWalker(beta, a, alpha, i, walker[i], dt, trialEnergy, numberOfWalkers, targetNumberOfWalkers);
cout << thermalisationCounter << endl;
}
//recalculate the local energy
for(int i=0; i<walker.size(); i++){
for(int j=0; j<6; j++)
localEnergy += calculateEnergy(beta, alpha, a, walker[i]);
}
localEnergy /= numberOfWalkers;
for(int numberOfSteps = 1; numberOfSteps<1000; numberOfSteps++){
for(int i=0; i<walker.size(); i++)
diffuseWalker(beta, a, alpha, i, walker[i], dt, trialEnergy, numberOfWalkers, targetNumberOfWalkers);
cout << numberOfSteps << endl;
}
//get initial energy of random positiions
for(int i=0; i<walker.size(); i++)
localEnergy += calculateEnergy(beta, alpha, a, walker[i]);
localEnergy /= numberOfWalkers;
cout << "before energy " << beforeEnergy << " local energy " << localEnergy <<
" trial energy " << trialEnergy << " number " << numberOfWalkers << endl;
return 0;
}
void copyVectorInformation(vector<double>& walker, vector<double>& walkerTemp){
for(int i=0; i<6; i++)
walkerTemp[i] = walker[i];
}//end of copyVectorInformation
void diffuseWalker(double beta, double a, double alpha, int locationInArray, vector<double>& walker, double dt,
double& trialEnergy, int& numberOfWalkers, int targetNumberOfWalkers){
vector<double> driftFunction(6);
vector<double> walkerTemp(6); //temporary store of information
//copy the walker information over
copyVectorInformation(walker, walkerTemp);
//get the drift functions
calculateDriftFunctions(beta, alpha, a, walker, driftFunction);
//get the old local energy
double preMoveLocalEnergy = calculateEnergy(beta, alpha, a, walker);
//move the walker
for(int j=0; j<6;j++)
walker[j] += 0.5*dt*driftFunction[j] + randomGauss()*sqrt(dt);
//caclulate the local energy of the new position
double postMoveLocalEnergy = calculateEnergy(beta, alpha, a, walker);
//calculate the weight, q and branching ration s
double q = exp(-dt*(0.5*(postMoveLocalEnergy + preMoveLocalEnergy) - trialEnergy));
double s = q+randomPositive();
if(int(s)<1){
//kill the walker
walker.erase(walker.begin()+locationInArray);
numberOfWalkers--;
}
else{
//reproduce walker int(s) number of times
for(int k=0; k<int(s); k++){
walker.push_back(walker[locationInArray]);
numberOfWalkers++;
}
}
//update the trial energy
trialEnergy += 0.2*log((double)targetNumberOfWalkers/(double)numberOfWalkers);
}//end of diffuse walkers
答案 0 :(得分:1)
你有:
if(int(s)<1){
//kill the walker
walker.erase(walker.begin()+locationInArray);
numberOfWalkers--;
}
假设
(int(s) < 1)
总是如此(总是擦除)然后
//move the walkers
for(int thermalisationCounter = 1; thermalisationCounter<1000; thermalisationCounter++){
for(int i=0; i<walker.size(); i++)
diffuseWalker(beta, a, alpha, i, walker[i], dt, trialEnergy, numberOfWalkers, targetNumberOfWalkers);
cout << thermalisationCounter << endl;
}
将删除所有对角线元素。这是你的意图吗?也许您将行索引与列索引(或1D与2D)混合在一起?
无论如何,问题是locationInArray太大了,你正在删除不再在向量中的项目。
答案 1 :(得分:0)
我认为你的问题在于矢量的大小是动态的。当你打电话给.erase时,你看起来像是在循环中。如果你在中间擦掉一些东西,并继续在元素中循环,那么随之而来的奇怪就会让我感到惊讶。
答案 2 :(得分:0)
我认为你正在从错误的向量中删除。在main
函数walker
中是2D向量。在diffuseWalker
中,您正在从已传递到函数的walker
中删除,该函数是双向的一维向量。您在这里使用locationInArray
并递减numberOfWalkers
这对于1D walker没有意义 - 看起来您想要实际从2D矢量中删除。我建议为2D和1D矢量使用不同的名称,以避免这样的混淆。
答案 3 :(得分:0)
我通过将函数传递给完整的2D向量来解决它,因此当我擦除walker(walker.begin()+locationInArray)
时,迭代器引用i
向量的第一个索引“walker[i][j]
”。之前,当我刚刚将它作为1D向量(基本上是'j
'索引片段)传递时,如果'locationInArray
&gt; = 6'为0&lt;&lt; 0&lt; = j
&lt; = 5。
非常感谢你的回答。