2010-07-04 72 views
0

我正在寫一個小程序來計算物理問題,但是我有從二維數組中刪除元素的問題。我正在編譯XCode(所以GDB)。不可重複的2D矢量問題

問題總是出現在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

我想你是從錯誤的向量擦除。在main功能walker是一個2D矢量。在diffuseWalker中,您正在從walker中刪除已被傳遞給函數的函數,該函數是雙精度的一維向量。您在這裏使用locationInArray並減少numberOfWalkers,這對一維助行器來說沒有意義 - 它看起來像要從二維向量中真正擦除。我建議使用2D和1D矢量的不同名稱來避免這樣的混淆。

0

我認爲你的問題在於矢量的大小是動態的。看起來你在調用.erase時處於循環狀態。如果你在中間抹掉了一些東西,並繼續循環這些元素,我不會感到奇怪的是隨機怪異隨之而來。

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太大,你正在擦除不再在向量中的項目。

0

是的 - 非常感謝。的確,我正在刪除數組的診斷元素,我通過在另一個程序中做了一個更小的玩具示例發現了這個元素。

我解決了它通過傳遞函數全2D矢量,以便當我擦除walker(walker.begin()+locationInArray)迭代器引用walker[i][j]向量的第一個索引'i'。之前,當我剛通過它作爲1D向量(基本上是「j」索引片),我被擦除的是並不存在的位置,如果「locationInArray> = 6」爲0 < j = = < 5.

非常感謝您的回答。