C++: problem with while loop for large number of iterations (code is attached)
First of all, thank you all for helping me with my questions before.
Input 1: (CSV file) listdata (input as list of vectors)
0,44,38,42,29,26,29,18,39,29,25,18,15,18,34,31,22,12,14,22,9,27
0,0,43,37,32,30,24,25,29,16,24,30,29,9,26,8,24,8,7,12,13,15
0,0,0,21,31,32,24,21,26,23,25,23,21,18,18,19,21,11,17,11,12,10
0,0,0,0,23,27,28,24,26,20,13,19,23,22,20,16,18,11,6,12,10,7
0,0,0,0,0,17,31,26,25,24,30,25,25,15,19,8,19,13,7,16,7,4
0,0,0,0,0,0,18,22,21,31,13,30,18,15,19,14,15,13,10,9,8,7
0,0,0,0,0,0,0,20,20,17,28,25,13,18,8,18,23,11,9,19,6,7
0,0,0,0,0,0,0,0,13,12,24,11,25,15,16,12,16,17,4,9,7,8
0,0,0,0,0,0,0,0,0,21,25,7,23,23,27,20,15,22,8,9,7,10
0,0,0,0,0,0,0,0,0,0,18,21,14,14,10,19,14,9,5,11,7,3
0,0,0,0,0,0,0,0,0,0,0,25,5,15,16,19,15,8,10,12,3,11
0,0,0,0,0,0,0,0,0,0,0,0,9,16,9,12,16,8,13,10,5,5
0,0,0,0,0,0,0,0,0,0,0,0,0,29,10,10,7,16,5,6,7,9
0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,13,6,10,2,6,13,11
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,13,9,7,11,7,9
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,15,12,20,8,13
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,4,11,5,10
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,11,9,3
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,8
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,10
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
input 2 : listmoves 14630x8 entries (CSV file).
{here is couple of lines from the file:
1,2,3,4,-1,-3,-2,-4
1,2,3,5,-1,-3,-2,-5
1,2,3,6,-1,-3,-2,-6
1,2,3,7,-1,-3,-2,-7
1,2,3,8,-1,-3,-2,-8
1,2,3,9,-1,-3,-2,-9
1,2,3,10,-1,-3,-2,-10
1,2,3,11,-1,-3,-2,-11 }
Here is the code:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <cstdlib>
#include <ctime>
using namespace std;
/*reading data files into vectors (22x22 matrix is in CSV format and 14630x8 vectors of moves in CSV format)*/
void readListData(vector< vector<short> > &vvec, const char *filename) {
ifstream dataFile;
dataFile.open(filename);
if(!dataFile.good()) {
cerr << "Could not open file '" << filename << "' for read\n";
exit(EXIT_FAILURE);
}
string line;
while (getline(dataFile, line)) {
istringstream iss(line);
vector<short> lvec;
while (!iss.eof()) {
short num;
iss >> num;
lvec.push_back(num);
char ch;
iss >> ch;
}
vvec.push_back(lvec);
}
}
/* write modified list of vectors into file at the end */
void writeListData(vector< vector <short> > &vvec, std::string filename) {
ofstream dataOutFile;
dataOutFile.open(filename.c_str());
if(!dataOutFile.good()) {
cerr << "Could not open file 'listdata.out' for write\n";
exit(EXIT_FAILURE);
}
for (vector<vector <short> >::size_type i = 0; i < vvec.size(); i++) {
vector<short>::size_type j;
for (j = 0; j < vvec[i].size() - 1; j++) {
dataOutFile << vvec[i][j] << ",";
}
dataOutFile << vvec[i][j] << endl;
}
dataOutFile.flush();
}
/* creat a toy vector for the input */
void copyVectors(const vector<vector<short> >& source, vector<vector<short> >& dest){
for(unsigned int i=0; i< source.size(); i++){
vector<short> rowSrc = source[i];
vector<short> rowDest;
for(unsigned int j=0; j< rowSrc.size(); j++){
rowDest.push_back(rowSrc[j]);
}
dest.push_back(rowDest);
}
}
int main() {
vector<vector <short> > mvec; //moves vectors
vector<vector <short> > vvecOrig; // original data vectors
readListData(vvecOrig, "listdata");
readListData(mvec, "listmoves");
const int NITERATIONS = 25; //set number of iterations
int numTables=25; //set number of outputs
vector<vector <short> > vvec;
copyVectors(vvecOrig, vvec);
for (int i=0; i<numTables; i++) {
srand((int) time(NULL));
int j = 0;
while (j < NITERATIONS) {
int movesIndex = rand() % mvec.size(); //generate random # from 0 to 14630
short a = mvec[movesIndex][0];
short b = mvec[movesIndex][1];
short c = mvec[movesIndex][2];
short d = mvec[movesIndex][3];
short e = abs(mvec[movesIndex][4]);
short f = abs(mvec[movesIndex][5]);
short g = abs(mvec[movesIndex][6]);
short h = abs(mvec[movesIndex][7]);
int x=vvec[e - 1][f - 1]-1;
int y=vvec[g - 1][h - 1]-1;
int z=vvec[a - 1][b - 1]+1;
int w=vvec[c - 1][d - 1]+1;
int x1=vvec[e - 1][f - 1];
int y1=vvec[g - 1][h - 1];
int z1=vvec[a - 1][b - 1];
int w1=vvec[c - 1][d - 1];
/*check for probability of the move */
/*if move does not create negative number in the list of vectors*/
if ((x>=0 && y>=0)) {
if (x==0 ){
x=1;
}
if(y==0){
y=1;
}
if (z==0){
z=1;
}
if (w==0){
w=1;
}
if (x1==0){
x1=1;
}
if (y1==0){
y1=1;
}
if (z1==0){
z1=1;
}
if (w1==0){
w1=1;
}
int numerator=x*y;
int denominator=z1*w1;
double probMove=numerator/denominator; //conditional probability
double prob = rand() % RAND_MAX; //generate random numer [0,1]
if ( probMove >=1 || probMove>prob) {
/*make a move if conditions are satisfied */
vvec[a - 1][b - 1]++;
vvec[c - 1][d - 1]++;
vvec[e - 1][f - 1]--;
vvec[g - 1][h - 1]--;
j++;
}
}
}
/*write output file after iterations*/
std::stringstream filenamestr;
filenamestr<<"listdata."<<i<<".out";
writeListData(vvec, filenamestr.str());
}
return 0;
}
The programs runs and produces desirable output. However, when I change number of iteration in while
loop to about 1000, and then run the program in the command line, it seems to be stuck in the loop ( doesn't produce any output and then terminal (on mac) becomes unresponsive). I am even scared to set it to 30,000 which is what my simulation required.
I am very new to C++ and I am not sure how to troubleshoot this.
Please help!
UPDATE: I changed the following lines:
srand((unsigned int) time(NULL));
...
double probMove=double(numerator)/denominator;
double prob = double(rand() )/ (RAND_MAX);
well, I cout prob
, and it seems now that when prob
is less than 10^(-5) the script becomes unresponsive. I have no idea how to approach开发者_运维百科 this...
I'll tell you 2 things:
probMove is an integer, even though you are saving it in a double variable. When two integers are divided together, the result is always an integer. When at least one of the operands is a double then the result is a double. Fix this by making either num or den a double.
rand()%RAND_MAX
is probably not doing what you intend (you want it to be a number between 0 and 1 it seems). rand() is a value between 0 and 32767, and RAND_MAX is 32767. So you're basically going to get the value of rand() back (number between 0 and 32766) unless rand() happened to return 32767, in which case you'll get a 0.
You are probably hitting a case where probMove
is either zero, very close to zero, or even negative, in which case j++
will never execute to increment your loop.
Also,
double prob = rand() % RAND_MAX; //generate random numer [0,1]
doesn't do what the comment says. If that's what you want, you need
double prob = double(rand()) / RAND_MAX;
精彩评论