-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcw2_sol.c
247 lines (222 loc) · 6.74 KB
/
cw2_sol.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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
#include<math.h>
struct matrix
{
int numrow;
int numcol;
int *elements;
};
typedef struct matrix Matrix;
/*
Print an image to the console.
image: an array stores the flattened image stored in row major order.
Height: the height of the image.
Width: the width of the image.
*/
void image2char(int image[], int Height, int Width)
{
//See lab 7, how images are stored in computers
// https://github.com/anewgithubname/MATH10017-2022/blob/main/lecs/lec8.pdf
for(int i = 0; i < Height; i++){
for(int j = 0; j < Width; j++){
if( image[i*Width + j] < 85){
printf(" ");
}
else if(image[i*Width + j] <170){
printf("I");
}else{
printf("M");
}
}
printf("\n");
}
}
/*
Read a matrix from file. Don't change it!
filename: the file that contains the matrix.
return: a matrix structure containing the matrix.
*/
Matrix read_matrix(char *filename)
{
FILE *f = fopen(filename, "rb");
// read int variables to the file.
int numrow = getw(f);
int numcol = getw(f);
Matrix M = {numrow, numcol, calloc(numrow * numcol, sizeof(int))};
for (int i = 0; i < M.numrow; i++)
{
for (int j = 0; j < M.numcol; j++)
{
M.elements[i*numcol + j] = getc(f);
}
}
fclose(f);
return M;
}
/*
Retrieve an element from a matrix.
M: the matrix.
i,j: the row and column of the element.
return: the element at row i and column j.
*/
int get_elem(Matrix M, int i, int j)
{
//see lecture 9 for row major order
return M.elements[i*M.numcol + j];
}
/*
Assign value to an element in a matrix.
M: the matrix.
i,j: the row and column of the element.
value: the value to be assigned.
*/
void set_elem(Matrix M, int i, int j, int value)
{
//see lecture 9 for row major order
M.elements[i*M.numcol + j] = value;
}
/*
Compute the pairwise squared distance of the i-th row of M1 and the j-th row of M2.
M1: the first matrix.
M2: the second matrix.
return: a matrix D where D_ij is the squared distance between the i-th row of M1 and the j-th row of M2.
*/
void pairwise_dist2(Matrix M1, Matrix M2, Matrix D)
{
//Have a look at lab 9, matrix multiplication algorithm
//Do they look similar? What are the similarities and differences?
// https://github.com/anewgithubname/MATH10017-2022/blob/main/labs/lab9.pdf
// loop over each row of M1
for (int i = 0; i< M1.numrow; i++)
{
// loop over each row of M2
for (int j = 0; j < M2.numrow; j++)
{
// compute D_ij = sum_k (M1_ik - M2_jk)^2
int sum = 0;
for (int k = 0; k < M1.numcol; k++)
{
int diff = get_elem(M1, i, k) - get_elem(M2, j, k);
sum += diff * diff;
}
set_elem(D, i, j, sum);
}
}
}
/*
Find the index of the minimum element in an array.
a: the array.
len: the length of the array.
return: the index of the minimum element in the array.
example: [1,2,3,4,5] -> 0
[5,4,3,2,1] -> 4
*/
int find_min_index(int a[], int len)
{
// for more information, see the last tutorial in TB1
// https://github.com/anewgithubname/MATH10017-2022/blob/main/labs/tutorial6.pdf
//set the initial minimum value to be the first element in the array.
int min = a[0];
int min_idx = 0;
// compare the minimum value with the rest of the elements in the array.
for (int i = 1; i < len; i ++){
// if the current element is smaller than the current minimum value,
// update the minimum value and the index.
if (a[i] < min){
min = a[i];
min_idx = i;
}
}
return min_idx;
}
/*
Find the indices of 5 minimum elements in an array.
a: the array.
len: the length of the array.
return: an array of 5 integers containing the indices of the 5 minimum elements in a.
example: [1,2,33,4,5,23,6] -> [0,1,3,4,6]
*/
void minimum5(int a[], int len, int indices[])
{
// this is a bit challenging.
// However, pay attention to the second task in the last tutorial.
// https://github.com/anewgithubname/MATH10017-2022/blob/main/labs/tutorial6.pdf
for (int i = 0; i < 5; i++)
{
indices[i] = find_min_index(a, len);
// after finding the minimum index, set the value to be INT_MAX
// so it won't be found again.
a[indices[i]] = INT_MAX;
}
}
void print(Matrix M){
// matrix printing, see lab 8
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
printf("%d ", get_elem(M, i, j));
}
printf("\n");
}
}
void main()
{
// 10% for submitting the correct code.
Matrix X = read_matrix("./X.matrix");
printf("N: %d, M: %d\n", X.numrow, (int) sqrt(X.numcol));
Matrix T = read_matrix("./T.matrix");
printf("L: %d\n", T.numrow);
Matrix Y = read_matrix("./Y.matrix");
int s = 0;
for (int i = 0; i < Y.numrow; i++)
{
if(Y.elements[i*Y.numcol + 0] == 1)
s++;
}
printf("Number of 1 in the training set: %d\n", s);
//TODO: construct the matrix D, where D_ij is the squared distance between the i-th row of T and the j-th row of X.
// 40% of the total score.
// 15% for the helper functions.
// 25% for the pairwise_dist2 function.
// See lecture 9 for heap memory allocation of structs
// https://github.com/anewgithubname/MATH10017-2022/blob/main/lecs/lec9_.pdf
// allocate HEAP memory for D
Matrix D = {T.numrow, X.numrow, calloc(T.numrow * X.numrow, sizeof(int))};
// compute the pairwise distances
pairwise_dist2(T, X, D);
// print out a subatrix of D, for checking.
print(D);
// loop over each testing image
for(int i=0; i<D.numrow; i++){
printf("The %d-th testing image:\n", i);
// visualize the image
image2char(T.elements + i*T.numcol, 28, 28);
// get the indices with the 5 smallest distances to the
// i-th testing image.
int indices[5];
// see How I indexed the i-th row of D.
minimum5(D.elements + i*D.numcol, D.numcol, indices);
// collect the labels of the 5 nearest neighboring images.
// how many 1s are there?
int count = 0;
for(int j=0; j<5; j++){
if(get_elem(Y, indices[j], 0) == 1)
count++;
}
printf("The %d-th testing image is classified as", i);
if(count >= 3)
printf(" 1.\n");
else
printf(" not 1.\n ");
printf("\n");
printf("----------------------------------------\n");
}
// free matrix D
free(D.elements);
free(X.elements);
free(T.elements);
free(Y.elements);
}