在单循环计算期间,程序陷入无限循环

问题描述 投票:0回答:1

我是c ++编程的新手,正在进行计算物理课,我们正在使用单簇算法分析正方形点阵上的渗透问题。我的教授给了我们一些基本代码,并要求我们修改它,以及在这个特定程序内外编写一些额外的代码和脚本。我已经编写了解决和绘制这个问题所需的大部分代码和脚本,但是我的主数据输出程序存在问题,特别是当我将输入参数设置为0以外的任何值时的无限循环问题。

这个程序有三个主要功能,即LATTICE :: LATTICE,CLUSTER :: grow和CUSTER :: print,还使用标准的Mersenne Twister头文件。经过大量修改,评论和玩弄c ++程序如下:

#include <fstream> 
#include <iostream> 
#include <math.h>
#include <string>
#include <sstream>
#include <iomanip>
#include <vector>
#include <cstdlib>
#include "MersenneTwister.h"

using namespace std;

class PARAMS
{
public:
  int Nlin; // linear size of lattice
  double pr; // probability for a site
  double Nclust; // number of clusters in a bin
  double Nbin; // number of bins of data to output
  int SEED; // seed for mersenne twister
  string latt_; // which lattice 
  PARAMS();//constructor
};

class LATTICE
{
public:
  LATTICE(const PARAMS&);//constructor
  int Nsite;// number of lattice sites
  int Lx,Ly;
  vector<vector<int> > nrnbrs;
  void print ();

};

class CLUSTER
{
public:
  CLUSTER(const PARAMS&, const LATTICE&);//constructor
  void grow(const PARAMS&, const LATTICE&, MTRand&);
  void meas_clear(const LATTICE&);
  void meas(const LATTICE&);
  void binwrite(const PARAMS&, const LATTICE&);
  //void print(const LATTICE& latt, int index);
  void print(const PARAMS& p, const LATTICE& latt);
  ~CLUSTER();// destructor
//private:
  int size;
  vector <int> conf;
  vector <int> stack;
  double pr;
  //int stck_pnt,stck_end;
  double avg_size;
  ofstream dfout;
  vector <int> stck_pnt;
  vector <int> stck_end;
  int z, pnt, prob, val, row, column;
  vector< vector< vector <int> > > imax; 
};






int main(void)
{
  PARAMS p;
  LATTICE latt(p);
  CLUSTER cluster(p,latt);
  MTRand ran(p.SEED);

  latt.print();
  /*for (int bin=0;bin<p.Nbin;bin++)
    {
      cluster.meas_clear(latt);
      for(int clust=0;clust<p.Nclust;clust++)
    {
      cluster.grow(p,latt,ran);
      cluster.meas(latt);

    }
      cluster.binwrite(p,latt);
    }
*/
  cluster.grow(p, latt, ran);
  cluster.print(p,latt);


}





PARAMS::PARAMS(){
  //initializes commonly used parameters from a file
  ifstream pfin;
  pfin.open("param.dat");  
  if (pfin.is_open()) { 
    pfin >> Nlin;
    pfin >> pr;
    pfin >> Nclust;
    pfin >> Nbin;
    pfin >> SEED;
    pfin >> latt_;
  }
  else
    {cout << "No input file to read ... exiting!"<<endl;exit(1);}
  pfin.close();
  // print out all parameters for record
  cout << "--- Parameters at input for percolation problem ---"<<endl; 
  cout <<"Nlin = "<<Nlin<<"; prob. of site = "<<pr<<endl;
  cout <<"Number of clusters in a bin = "<<Nclust<<"; Number of bins = "<<Nbin<<endl;
  cout <<"RNG will be given SEED of = "<<SEED<<endl;
  cout <<"Percolation problem on lattice --> "<<latt_<<endl;
};//constructor


LATTICE::LATTICE (const PARAMS& p)
{


  string latt_=p.latt_;

  if(p.latt_=="sqlatt_PBC")
    {
      Lx=p.Nlin;Ly=p.Nlin;
      Nsite=Lx*Ly;
      int i;

      nrnbrs = vector<vector<int> >(Nsite, vector<int>(4));

      for (i=0; i<Nsite; i++){

        if((i+1) % p.Nlin != 0) nrnbrs[i][0] = i+1;
          else nrnbrs[i][0] = i - p.Nlin + 1 ;
        if(i + p.Nlin < Nsite ) nrnbrs[i][1] = i+p.Nlin;
          else nrnbrs[i][1] = i - (Nsite-p.Nlin);
        if(i % p.Nlin > 0) nrnbrs[i][2] = i-1;
          else nrnbrs[i][2] = i-1+p.Nlin;
        if(i - p.Nlin >= 0) nrnbrs[i][3] = i-p.Nlin;
          else nrnbrs[i][3] = i + (Nsite-p.Nlin);


      }
    }
  else if(p.latt_=="sqlatt_OBC")
    {
      Lx=p.Nlin;Ly=p.Nlin;
      Nsite=Lx*Ly;

      nrnbrs = vector<vector<int> >(Nsite, vector<int>(0));

      for (int i=0; i<Nsite; i++){

        if((i+1) % p.Nlin != 0){ 
          nrnbrs[i].push_back(i+1);
          }
        if(i + p.Nlin < Nsite ){
          nrnbrs[i].push_back(i+p.Nlin);
          }

        if(i % p.Nlin > 0){
          nrnbrs[i].push_back(i-1);
          }
        if(i - p.Nlin >= 0){
          nrnbrs[i].push_back(i-p.Nlin);
          }
      }

    }
  else
    {cout <<"Dont know your option for lattice in param.dat .. exiting"<<endl;exit(1);}
}




void LATTICE::print()
{
  //THIS FUNCTIONS MAY BE CALLED DURING DEBUGGING TO MAKE SURE LATTICE HAS BEEN DEFINED CORRECTLY
  cout <<"---printing out properties of lattice ---"<<endl;
  cout<<"size is  "<<Lx<<"x"<<Ly<<endl;
  cout <<"neighbors are"<<endl;
  for (int site=0;site<Nsite;site++)
    {
      cout <<site<<" : ";
      for (size_t nn=0;nn<nrnbrs.at(site).size();nn++)
    cout<<nrnbrs.at(site).at(nn)<<" ";
      cout <<endl;
    }
  cout << endl;
}





CLUSTER::CLUSTER(const PARAMS& p, const LATTICE& latt)
{
  conf.resize(latt.Nsite);
  stack.resize(latt.Nsite);
  pr=p.pr;// store prob in a private member of cluster
  dfout.open("data.out");
}




CLUSTER::~CLUSTER()
{
  dfout.close();
}






void CLUSTER::grow(const PARAMS& p, const LATTICE& latt, MTRand& ran)
{
    conf.resize(latt.Nsite);                         // Initalize Nsite elements of lattice to 0 in conf
                                                     // 0 = Not Asked; 1 = Asked, Joined; 2 = Asked, Refused
    for (int i = 0; i < p.Nclust; ++i) {                  // Iterate for Nclust values
        z = ran.randInt(latt.Nsite - 1);               // Random integer between 0 and Nsite; Selects first lattice element in the cluster algorithm per Nclus
        stck_pnt.resize(0);                          // Set stck_pnt and stck_end vectors to size 0; Will be filled when iterating through each Nclust 
        stck_end.resize(0);                          //-----------------------------------------------------------------------------------------------

        //while (conf[z] != 0) { z = ran.randInt(latt.Nsite - 1); }         // Iterate through lattice elements until we select one that has not been asked to join 

        conf[z] = 1;                            // Set element z in conf to have been asked to join and accepted

        stck_pnt.push_back(z);                      // Add z to both stck_pnt and stck_end
        stck_end.push_back(z);
        for (int j = 0; j = 3; ++j) {                // Add z's nearest neighbors to stck_end; Ignore if already been asked
            if (conf[latt.nrnbrs[z][j] == 0]) {
                stck_end.push_back(latt.nrnbrs[z][j]);
            }
        }


        pnt = 1;                                        // Initialize pnt for trasnferral of stack_end values to stck_pnt


        while (stck_pnt.size() < stck_end.size()) {

            stck_pnt.push_back(stck_end[pnt]);     // Add pnt element of stck_end to stck_pnt

            double prob = ran.rand();                      // Get probability value for testing if cluster grows

            if (prob <= pr) {

                conf[stck_pnt[pnt]] = 1;            // Set the current stck_pnt element to joined in conf

                for (int j = 0; j = 3; ++j) {                // Add z's nearest neighbors to stck_end; Ignore if already been asked

                    if (find(stck_end.begin(), stck_end.end(), latt.nrnbrs[stck_pnt[pnt]][j]) != stck_end.end()) {

                        // The given value already exists in stck_end, don't add it again 
                    }

                    else {                          // The given value is not contained in stck_end, add it to stck_end

                        stck_end.push_back(latt.nrnbrs[z][j]);
                    }
                }
            }

            else {

                conf[stck_pnt[pnt]] = 2;       // Set the given value to haven been asked and refused in conf
            }
            ++pnt;                              // Increment pnt; ++p is more efficient then p++ due to lack of copying value
        }

    }
}


/*
    void CLUSTER::print(const LATTICE& latt, int index)
    {

        stringstream ss;
        string file_name;
        ss << index << ".clust";
        file_name = ss.str();

        ofstream clout;
        clout.open(file_name.c_str());
        clout << "#" << latt.Lx << " x " << latt.Ly << endl;

        for (int y = 0; y < latt.Ly; y++)
        {
            for (int x = 0; x < latt.Lx; x++)
                clout << conf[x + y*latt.Lx] << " ";
            clout << endl;
        }

        clout.close();
    }
    */


void CLUSTER::print(const PARAMS& p, const LATTICE& latt)
{
    //vector< vector< vector<int> > > imax(latt.Lx, vector< vector<int>>(latt.Ly, vector<int>(1)));
    //  Resize and allocate memeory for imax

    //-------------- Row = y-position = i/Lx --------------- Column = x-position = i%Lx ---------------- val = conf[i]
    ofstream myFile;
    myFile.open("imax.out");

    cout << "THe following output was calculated for the input parameters; Recorded to 'imax.out'" << endl;
    cout <<"[index]" << "\t" << "[x-position]" << "\t" << "[y-position]" << "\t" << "[conf val]" << endl << endl;
    for (int i = 0; i < latt.Nsite; ++i) {

        val = conf[i];                            // Find color value
        row = i / latt.Lx;                               // Find row number
        column = i%latt.Lx;                            // Find column number

        cout << i << "\t" << column << "\t" << row << "\t" << val << endl;
        myFile << i << "\t" << column << "\t" << row << "\t" << val << endl;
    }
    myFile.close();
    double size = 0.0;                                       // Initialize size 

    for (int i = 0; i < latt.Nsite; ++i) {

        if (conf[i] == 1) {
            size += 1;
        }
    }

    double avg_size = size / p.Nclust;                 // Find avg_size 


}

void CLUSTER::meas(const LATTICE& latt)
{
  avg_size+=(double)size;
}


void CLUSTER::meas_clear(const LATTICE& latt)
{
  avg_size=0.;
}


void CLUSTER::binwrite(const PARAMS& p, const LATTICE& latt)
{
  dfout << avg_size/((double)p.Nclust)<<endl;
}

当我在输入文件中设置Nclust = 0时,代码按预期运行并在文件和控制台中提供正确的输出。但是,当我将Nclust设置为等于任何其他值时,我得到了正确的网格控制台输出,但程序挂起了群集算法。我起初认为我的计算机和算法速度慢且效率低,并且该程序在某些非线性时间内工作。但是,在程序运行大约30分钟后运行4x4点阵(conf []向量中只有16个元素)后,没有进展,我认为程序陷入循环。

在花了几个小时逐行浏览CLUSTER :: grow()方法并尝试更改各种代码之后,我一直无法解决此循环错误的起源。我会假设它在while循环中的某个地方比较了stck_pnt和stck_end的大小,但我无法弄清楚为什么或这是什么。任何有关这方面的帮助将非常感激。

c++ infinite-loop
1个回答
0
投票

Tl; dr:对于Nclust!= 0,CLUSTER:grow陷入无限循环

你在这里有无限循环:

 stck_end.push_back(z);
    for (int j = 0; j = 3; ++j) {  // <======== HERE

和这里:

conf[stck_pnt[pnt]] = 1;            // Set the current stck_pnt element to joined in conf

                for (int j = 0; j = 3; ++j) { // <======== HERE
© www.soinside.com 2019 - 2024. All rights reserved.