SIMULATION problem

I don't know what's wrong with my code. It runs, but it does not print properly.

example simulation.txt
------
2000
0.1
5
15
5
20
------

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
  #include <iostream>
#include <cstdlib>
#include <queue>
#include <fstream>
#include <time.h>

using namespace std;

// Input parameters
#define SIMULATION_TIME 0
#define ARRIVAL_RATE 1
#define MIN_SERVICE_TIME 2
#define MAX_SERVICE_TIME 3
#define MAX_LINE_SIZE 4
#define TARGET_TIME 5
#define PARAMS_MAX 6

// Or like this:
// const int SIMULATION_TIME = 0;

// Or make 6 variables:
// double SIMULATION_TIME = 0;

// Name of the input file
#define FILENAME "sim.txt"

// Counters -- these are indexes into variable 'counters' below
#define CUSTOMERS_SERVICED 0
#define CUSTOMERS_LEAVING 1
#define AVERAGE_WAIT 2
#define AVERAGE_LINE 3
#define WITHIN_TARGET 4
#define COUNTERS_MAX 5

// Holds the current simulation parameters
double parameters[PARAMS_MAX];
double counters[COUNTERS_MAX];

// This is an example debug macro you can use to print
// things each time through the loop
#define DEBUGGING_ENABLED 1
#ifdef DEBUGGING_ENABLED
#define DEBUG(x) do { \
cerr << __FILE__ << ": " << __LINE__ << ": " << x << endl; \
} while (0)
#else
#define DEBUG(x)
#endif // DEBUGGING_ENABLED

// Return the service interval, between 'min'
// and 'max'.
int randomInt(int min, int max) {
return (rand() % (max - min) + min);
}
// Returns TRUE if a customer arrived during this minute.
// We need to divide by RAND_MAX because rand() returns a
// number between 0 and RAND_MAX (which is defined by
// a system header).
bool randomChance(double prob) {
double rv = rand() / (double(RAND_MAX) + 1);
return (rv < prob);
}

// Read the next simulation from the file. Return
// TRUE if one could be read, FALSE otherwise (eof).
bool readNextSim(fstream &f, double parameters[]) {
for (int i = 0; i < PARAMS_MAX; i++) {
string tmp;
getline(f, tmp);
if (f.eof())
return false;
// Read in the next parameter
parameters[i] = atof(tmp.c_str());
}
cout << "Test Case: " << endl;
for (int i = 0; i < PARAMS_MAX; i++) {
cout << "\t Param #" << i << ": " << parameters[i] << endl;
}
return true;
}

int main()
{

// Seed the random number generator here
srand(time(0));
fstream f("simulation.txt");

if (!f.good()) {
cout << "Invalid file." << endl;
return -1;
}

// This loop reads each simulation (a set of parameters) from the input
// file.
while (readNextSim(f, parameters)) {
// Run the next simulation
queue<int> line;

for (int i = 0; i < COUNTERS_MAX; i++)
counters[i] = 0;

// The current time in this individual simulation.
int simTime = 0;

// Each time through this loop represents 1 minute passing.
// There needs to be code to handle everything that can happen
// in 1 minute:
// - Customer arriving (yes/no?)
// - Is the current customer finished
// - Possibly process the next person in line
// - Calculate simulation statistics along the way

//Variable to check if there is any customer being processed, if not, we can send in the next customer
int customerProcessingStarted=0;

//stores the amount of time it would take for the present customer to get free
int timeWhenPresentCustomerFree;

//Takes sum of queue at each instance of time (to later calculate av length)
int totalLengthOfQueue=0;
while (simTime++ < parameters[SIMULATION_TIME]) {

// One iteration of the loop represents one
// minute of simulation time.

// Check to see if a customer arrived
// (if so, process, also see if the line is full)
if(randomChance(parameters[ARRIVAL_RATE])){
if(line.size()!=parameters[MAX_LINE_SIZE]){
line.push(simTime);
}
else {
counters[CUSTOMERS_LEAVING]++;
}
}

//If the queue is empty, we cannot process anything
if(!line.empty()){

// Check to see if the current customer is done
// at the cashier. Also check if there is no customer
// at the cashier (in which the next customer goes to the
// cashier).

if(customerProcessingStarted==1 && simTime==timeWhenPresentCustomerFree){

//Present customer has been serviced, removing from queue and calculating relevant statistics

customerProcessingStarted=0;
int serviceStartTime = line.front();
line.pop();
int timeTaken = simTime - serviceStartTime;
counters[CUSTOMERS_SERVICED]++;
// Update average waiting times (if servicing a customer).
counters[AVERAGE_WAIT] = (counters[AVERAGE_WAIT]*(counters[CUSTOMERS_SERVICED]-1) + (double) timeTaken)/(counters[CUSTOMERS_SERVICED]);
if(timeTaken<=parameters[TARGET_TIME]){
counters[WITHIN_TARGET]++;
}
}
else if(customerProcessingStarted==0){
// If a customer is next in line, get the expected waiting time.
// (random between min and max service time). This will give us
// a timestamp of when the next customer will be done.
int waitingTimeForLatest = randomInt(parameters[MIN_SERVICE_TIME],parameters[MAX_SERVICE_TIME]);
customerProcessingStarted=1;
timeWhenPresentCustomerFree = simTime + waitingTimeForLatest;
}
totalLengthOfQueue+=line.size();
}


}
// Print a summary of the simulation:
cout<<"Simulation Results"<<endl;
cout<<"------------------"<<endl;
cout<<"Overall simulation time: "<<parameters[SIMULATION_TIME]<<endl;
cout<<"Arrival rate: "<<parameters[ARRIVAL_RATE]<<endl;
cout<<"Minimum service time: "<<parameters[MIN_SERVICE_TIME]<<endl;
cout<<"Maximum service time: "<<parameters[MAX_SERVICE_TIME]<<endl;
cout<<"Maximum line size: "<<parameters[MAX_LINE_SIZE]<<endl;
cout<<"Target waiting time: "<<parameters[TARGET_TIME]<<endl<<endl;

cout<<"Customer serviced: "<<counters[CUSTOMERS_SERVICED]<<endl;
cout<<"Customer leaving: "<<counters[CUSTOMERS_LEAVING]<<endl;
cout<<"Average time spent in line: "<<counters[AVERAGE_WAIT]<<endl;
cout<<"Average line length: "<<(double)counters[AVERAGE_LINE]/SIMULATION_TIME<<endl;
cout<<"Pct. serviced within target "<<(double)(counters[WITHIN_TARGET] *100)/counters[CUSTOMERS_SERVICED]<<endl;


}
return 0;
}
what output are you expecting?
how is the data being saved to the file to begin with ?
that is where your problem will be..


you also need to specify file locations
i'd recommend using functions
Last edited on
I can't see it liking these two lines:
1
2
3
#define SIMULATION_TIME 0
...
cout<<"Average line length: "<<(double)counters[AVERAGE_LINE] / SIMULATION_TIME<<endl;


Maybe you meant
parameters[SIMULATION_TIME]
in the second case?



Anyway, do you know what indentation is? Please use it.



BTW. This is what it gave me (the nan is related to the problem above)
Test Case:
	 Param #0: 2000
	 Param #1: 0.1
	 Param #2: 5
	 Param #3: 15
	 Param #4: 5
	 Param #5: 20
Simulation Results
------------------
Overall simulation time: 2000
Arrival rate: 0.1
Minimum service time: 5
Maximum service time: 15
Maximum line size: 5
Target waiting time: 20

Customer serviced: 168
Customer leaving: 37
Average time spent in line: 33.5595
Average line length: nan
Pct. serviced within target 23.8095
Last edited on
Hello rin103,

There are many things wrong. Some small and some big.

Overall the code is in bad need of proper indenting. And a few blank lines would help.

To start with:
1
2
3
4
5
6
7
8
#include <iostream>
#include <cstdlib>
#include <queue>
#include <fstream>
#include <ctime>  // <--- Changed.
#include <string>  // <--- Added.

using namespace std;

There are several old C header files that have been chanced to work with C++. For a list take the "Reference" the link near the top left of the page. I just noticed that this section is being updated.

You are using "std::getline" and ".c_str()". Both of these require the "string" header file. If this code compiled for you I am thinking that you may need to adjust your compiler settings to catch more errors. It would also help if you mention what IDE/compiler you are using.

using namespace std; This is a whole topic in its-self, but you should be learning to not use this.

Your "#defines" will work, but defining constant variables is a better choice. As an example:
1
2
3
4
5
6
7
// Input parameters
//#define SIMULATION_TIME 0
constexpr unsigned int SIMULATION_TIME;  // <--- As a global variable there is a good chance this will be initialized to zero. Otherwise use "SIMULATION_TIME{}".
//#define ARRIVAL_RATE 1
constexpr unsigned int ARRIVAL_RATE{ 1u };  // <--- Or just make it an "int".

const std::string FILENAME{ "sim.txt" };

Whether you use an "int" or "unsigned int" is up to you. I have not gone through enough of the code yet to see how all the constants are used.

1
2
3
// Holds the current simulation parameters
double parameters[PARAMS_MAX];
double counters[COUNTERS_MAX];

As global variables these should be avoided as any line of code that follows can change them. That makes it more difficult to find where it went wrong. It is better to define them in "main" and pass them to any function that needs them. Better control over the variables.

The "randomInt" function may work, but it just does not look right. I will have to check on that.

In the "readNextSim" function the "getline" works when you include the header file "string".

In the line of code: parameters[i] = atof(tmp.c_str()); you are over thinking it and doing to much work. This can be written as: parameters[i] = stod(tmp);.

The "string" class has several member functions to convert a string to a number.

The more I look at the function I wonder why you do not use something like inFile >> parameters[i]. Since you did not provide the input for everyone to see it is only a guess at this point. PLEASE provide the input file when a program requires one. If it is large a fair sample will work.

That gets down to "main". The input file would help with testing.

Andy
Simulation Results
------------------
Overall simulation time: 2000
Arrival rate: 0.1
Minimum service time: 5
Maximum service time: 15
Maximum line size: 5
Target waiting time: 10

Customers serviced: 183
Customers leaving: 25
Average time spent in line: 33.86
Average line length: 3.15
Pct. served within target: 15.38


this is what I expect. and I am using Codeblock:)
Can you tell me what lines I need to change? I am a little confused.
That won't be what you got from your original code, where you were dividing by zero (read my post). You also can't compute anything with counters[AVERAGE_LINE] in, because you haven't set that particular array element anywhere. And you've failed to explain what you are trying to do, anyway: we have to magically interpret your code.

There is an element of randomness built in, isn't there? You are using rand(). So you won't get the same numbers every time.


rin103 wrote:
Can you tell me what lines I need to change?
All of them. You aren't using indentation anywhere. And the fact that you are using Codeblock[s] is irrelevant.
Topic archived. No new replies allowed.