-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathIOModelSSI.c
203 lines (167 loc) · 5.72 KB
/
IOModelSSI.c
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
194
195
196
197
198
199
200
201
202
203
// Set libraries to include
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <omp.h>
// Read a file of doubles of size MAT_SIZE to an array of size MAT_SIZE
void read_double_file(FILE *infile, int MAT_SIZE, double *MAT) {
for(int i = 0; i < MAT_SIZE; i++) {
fscanf(infile, "%lf", &MAT[i]);
};
};
// Read a file of integers of size MAT_SIZE to an array of size MAT_SIZE
void read_int_file(FILE *infile, int MAT_SIZE, int *MAT) {
for(int i = 0; i < MAT_SIZE; i++) {
fscanf(infile, "%d", &MAT[i]);
};
};
// Read a specified file into a double matrix of size MAT_SIZE
void read_custmat_double(int MAT_SIZE, double *doubmat, char *arr) {
FILE *infile;
if(!(infile = fopen(arr, "r"))) {
printf("Error opening input file\n");
exit(EXIT_FAILURE);
}
read_double_file(infile, MAT_SIZE, doubmat);
fclose(infile);
}
// Read a specified file into a integer matrix of size MAT_SIZE
void read_custmat_int(int MAT_SIZE, int *intmat, char *arr) {
FILE *infile;
if(!(infile = fopen(arr, "r"))) {
printf("Error opening input file\n");
exit(EXIT_FAILURE);
}
read_int_file(infile, MAT_SIZE, intmat);
fclose(infile);
}
int main(int argc, char** argv) {
// Check enough arguments have been provided
if(argc != 6) {
printf("Too many or too few arguments, 6 required %d provided \n", argc);
exit(1);
}
// Initialise variables to store input args
double starta, enda, stepa;
int n;
// Read in input args
// First value for alpha
sscanf(argv[1], "%lf", &starta);
// Last value for alpha
sscanf(argv[2], "%lf", &enda);
// Step size between alphas
sscanf(argv[3], "%lf", &stepa);
// Total number of locations
sscanf(argv[4], "%d", &n);
// Open the output file
FILE *f;
f = fopen(argv[5], "w");
if (f == NULL) {
printf("Error opening output file \n");
exit(1);
}
// Initialise arrays for input data and misc variables
double *distmat, *popmatpow, *travmat, *O, *Sij;
double *popmat;
double error;
double alpha;
// Allocate memory for each array
distmat = (double *) malloc(n * n * sizeof(double));
popmat = (double *) malloc(n * sizeof(double));
popmatpow = (double *) malloc(n * sizeof(double));
O = (double *) malloc(n * sizeof(double));
travmat = (double *) malloc(n * n * sizeof(double));
Sij = (double *) malloc(n * n * sizeof(double));
// Read in the input arrays for the distances, the flow sizes and the population sizes
read_custmat_double(n * n, distmat, "distmat.dat");
read_custmat_double(n * n, travmat, "travmat.dat");
read_custmat_double(n, popmat, "popsize.dat");
// Evaluate the O_i values
#pragma omp parallel for
for(int i = 0; i < n; i ++) {
O[i] = 0;
for(int j = 0; j < n; j++) {
if(i!=j) {
O[i] += travmat[i * n + j];
}
}
}
// Set alpha to the start value
alpha = starta;
// Initialise value to check if we are on the final iteration
int finala = 0;
//double itime0 = omp_get_wtime();
// Evaluate Sij
#pragma omp parallel for
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
int iter = i * n + j;
double distij = distmat[iter];
double Sijval = 0;
if( i != j ) {
// add populations that are closer the location j
for(int k = 0; k < n; k++) {
if(distij >= distmat[i * n + k]) {
Sijval += popmat[k];
}
}
}
Sij[iter] = Sijval;
}
}
// Initialise variable to store population size
double totalpop = 0;
// Calculate the total population size
#pragma omp parallel for reduction(+: totalpop)
for(int i = 0; i < n; i++) {
totalpop += popmat[i];
}
// printf("Time taken for initial section = %g \n", omp_get_wtime() - itime0);
// Loop over values of alpha
while(alpha <= enda) {
//double time0 = omp_get_wtime();
// Reset the error variable
error = 0;
// Precalculate the denominator term and invert to reduce division operations
double denom = 1.0 / (1 - exp(-1.0 * alpha * totalpop));
// Evaluate the SSI
#pragma omp parallel for reduction(+: error)
for(int i = 0; i < n; i++) {
double errorval = 0;
for(int j = 0; j < n; j++) {
if (i != j) {
int iter = i * n + j;
// Evaluate the predicted flow for this path
double val = O[i] * ((exp(-1 * alpha * (Sij[iter] - popmat[j])) - exp(-1 * alpha * Sij[iter])) * denom);
// Add values to the total SSI
errorval += 2 * fmin(val, travmat[iter]) / (val + travmat[iter]);
}
}
// add the SSI from the i flows
error += errorval;
}
// printf("alpha = %g, error = %g, time taken = %g\n", alpha, error, omp_get_wtime() - time0);
// Save the values from the current iteration
fprintf(f, "%g %g\n", alpha, error / (n * (n-1)));
// Check if the final loop has been reached
if(alpha + stepa < enda) {
alpha += stepa;
} else if(!finala) {
alpha = enda;
finala = 1;
} else{
break;
}
}
//printf("Total time taken was %g\n", omp_get_wtime() - itime0);
// Free the memory from the arrays
free(distmat);
free(popmat);
free(travmat);
free(popmatpow);
free(O);
free(Sij);
// Close the output file
fclose(f);
return 0;
}