00001 #ifndef HAMMING_IMPLEMENTATION_FILE
00002 #define HAMMING_IMPLEMENTATION_FILE
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 static const char *NAME = "hamming";
00019
00020 #include "hamming.h"
00021
00022 #include <basis/guards.h>
00023
00024 #include <ctype.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027
00028
00029 #define BIT_ON 1
00030 #define BIT_OFF -1
00031
00032 hamming::hamming()
00033 {
00034 }
00035
00036 hamming::~hamming()
00037 {
00038 }
00039
00040 void hamming::corrupter(int ex[], int faults)
00041 {
00042 int fault_location;
00043 bit_pattern flip_record;
00044
00045 if (faults > N)
00046 non_continuable_error(NAME, "corrupter", "more faults than bits");
00047
00048 for (int j = 0; j < N; j++) flip_record[j] = false;
00049 for (int i = 0; i < faults; i++) {
00050 do
00051 fault_location = randomizer.inclusive(0, N-1);
00052 while (flip_record[fault_location]);
00053 flip_record[fault_location] = true;
00054 ex[fault_location] = -ex[fault_location];
00055 }
00056 }
00057
00058 void hamming::init_lower_subnet(int faults)
00059 {
00060 if (faults > N * M)
00061 non_continuable_error(NAME, "init_lower_subnet", "more faults than weights");
00062
00063
00064 int corruption [MAXIMUM_BITS_IN_PATTERN] [MAXIMUM_EXEMPLARS];
00065
00066 int m;
00067 int n;
00068 for (n = 0; n < N; n++)
00069 for (m = 0; m < M; m++)
00070 corruption [n] [m] = false;
00071
00072 for (int pos = 0; pos < faults; pos++) {
00073 do {
00074 n = randomizer.inclusive(0, N-1);
00075 m = randomizer.inclusive(0, M-1);
00076 } while (corruption [n] [m]);
00077 corruption [n] [m] = true;
00078 }
00079
00080 for (int i = 0; i < N; i++)
00081 for (int j = 0; j < M; j++) {
00082 w [i] [j] = exemplars [j] [i] / 2.0;
00083 if (corruption [i] [j]) {
00084 w [i] [j] = ((double)randomizer.inclusive
00085 (0, 30000) / 30000.0) - 0.5;
00086
00087
00088 }
00089 }
00090 }
00091
00092 void hamming::init_upper_subnet(int faults)
00093 {
00094 if (faults > M * M)
00095 non_continuable_error(NAME, "init_upper_subnet", "more faults than Maxnet connections");
00096
00097
00098 int corruption [MAXIMUM_BITS_IN_PATTERN] [MAXIMUM_EXEMPLARS];
00099
00100 int m1, m2;
00101 for (m1 = 0; m1 < M; m1++)
00102 for (m2 = 0; m2 < M; m2++)
00103 corruption [m1] [m2] = false;
00104
00105 for (int pos = 0; pos < faults; pos++) {
00106 do {
00107 m1 = randomizer.inclusive(0, M-1);
00108 m2 = randomizer.inclusive(0, M-1);
00109 } while (corruption [m1] [m2]);
00110 corruption [m1] [m2] = true;
00111 }
00112
00113 for (int k = 0; k < M; k++)
00114 for (int l = 0; l < M; l++) {
00115 if (!corruption [k] [l]) {
00116 if (k == l) maxnet [k] [l] = 1.0;
00117 else maxnet [k] [l] = -EPSILON;
00118 } else {
00119 w [k] [l] = ((double)randomizer.inclusive
00120 (0, 30000) / 15000.0) - 1.0;
00121
00122
00123 }
00124 }
00125 }
00126
00127 double hamming::weighted_sum(int j)
00128 {
00129 double sum = 0;
00130 for (int i = 0; i < N; i++)
00131 sum = sum + (w [i] [j] * (double)x[i]);
00132 return sum;
00133 }
00134
00135 double hamming::corrupted_sum()
00136 {
00137 return -(double)N * ((double)randomizer.inclusive(0, 30000) / 60000.0);
00138
00139 }
00140
00141 double hamming::f_thresh(double alpha)
00142 {
00143 if (alpha <= 0.0) return 0.0;
00144 else return alpha;
00145 }
00146
00147 void hamming::init_with_unknown_pattern(int faults)
00148 {
00149 int corruption[MAXIMUM_EXEMPLARS];
00150 int fault_location;
00151
00152 if (faults > M)
00153 non_continuable_error(NAME, "init_with_unknown_pattern", "more faults than exemplars");
00154
00155 t = 0;
00156
00157 for (int l = 0; l < M; l++) corruption[l] = false;
00158 for (int i = 0; i < faults; i++) {
00159 do
00160 fault_location = randomizer.inclusive(0, M-1);
00161 while (corruption[fault_location]);
00162 corruption[fault_location] = true;
00163 }
00164
00165 for (int j = 0; j < M; j++) {
00166 if (!corruption[j])
00167 mu [t] [j] = f_thresh(weighted_sum(j) - THETA);
00168 else
00169 mu [t] [j] = f_thresh(corrupted_sum() - THETA);
00170 }
00171 }
00172
00173 double hamming::maxnet_output_sum(int j)
00174 {
00175 double sum = 0.0;
00176 int k;
00177 for (k = 0; k < j; k++) sum += mu [t] [k];
00178 for (k = j+1; k < M; k++) sum += mu [t] [k];
00179 return sum;
00180 }
00181
00182 void hamming::converge()
00183 {
00184 for (int j = 0; j < M; j++)
00185 mu [t+1] [j] = f_thresh( mu [t] [j] - EPSILON * maxnet_output_sum(j) );
00186 t++;
00187 }
00188
00189 int hamming::only_one_positive_output_left()
00190 {
00191 int standing = -1;
00192 for (int i = 0; i < M; i++) {
00193 if ( (mu [t] [i] > 0.0) && (standing < 0) )
00194
00195 standing = i;
00196 else if (mu [t] [i] > 0.0)
00197
00198 return -1;
00199 }
00200 if (standing == -1)
00201 non_continuable_error(NAME, "only_one_positive_output_left", "no positive outputs are left at all");
00202 return standing;
00203 }
00204
00205 int hamming::iterate_until_convergence()
00206 {
00207 int converged = false;
00208 int answer;
00209
00210 while (!converged) {
00211 converge();
00212 answer = only_one_positive_output_left();
00213 if (answer >= 0) converged = true;
00214 else if (t >= MAXIMUM_ITERATION)
00215 return -1;
00216 }
00217 return answer;
00218 }
00219
00220 void hamming::show_pattern_line(int ex[], int line)
00221 {
00222 for (int i = line * cols; i < line * cols + cols; i++) {
00223 if (ex[i] == BIT_OFF) { printf("."); fflush(stdout); }
00224 else { printf("*"); fflush(stdout); }
00225 }
00226 }
00227
00228 void hamming::show_pattern_line(int ex[], int line, FILE *print_to)
00229 {
00230 for (int i = line * cols; i < line * cols + cols; i++) {
00231 if (ex[i] == BIT_OFF) fprintf(print_to, ".");
00232 else fprintf(print_to, "*");
00233 }
00234 }
00235
00236 void hamming::dump_pattern(int ex[])
00237 {
00238 for (int i = 0; i < rows; i++) {
00239 show_pattern_line(ex, i);
00240 printf("\n");
00241 }
00242 }
00243
00244 void hamming::show_exemplars()
00245 {
00246 int exemplars_that_fit = SCREEN_WIDTH / (cols + 2);
00247 for (int i = 0; i < M; i += exemplars_that_fit) {
00248
00249 for (int k = 0; k < rows; k++) {
00250
00251 for (int j = i; j < i + exemplars_that_fit; j++) {
00252
00253 if (j < M) {
00254 show_pattern_line(exemplars[j], k);
00255 printf(" "); fflush(stdout);
00256 }
00257 }
00258 printf("\n");
00259 }
00260 printf("\n");
00261 }
00262 }
00263
00264 void hamming::get_sample()
00265 {
00266 char temp[MAXIMUM_BITS_IN_PATTERN];
00267 printf("Please enter a %d x %d sample for the hamming net.\n",
00268 rows, cols);
00269 printf("Use \"*\" to turn a bit on and \".\" to turn a bit off.\n");
00270 for (int i = 0; i < rows; i++) {
00271 printf("Enter pattern for row %d:", i + 1); fflush(stdout);
00272 fgets(temp, MAXIMUM_BITS_IN_PATTERN - 2, stdin);
00273 for (int j = 0; j < cols; j++)
00274 if (temp[j] == '*') x[ cols*i + j] = BIT_ON;
00275 else x[ cols*i + j] = BIT_OFF;
00276 }
00277 }
00278
00279 void hamming::save_sample()
00280 {
00281 int status;
00282 FILE *fp;
00283 char save[20];
00284
00285 printf("\nWould you like to save your example? (Y/N): ");
00286 fflush(stdout);
00287 fgets(save, 18, stdin);
00288 if (save[0] == 'Y' || save[0] == 'y') {
00289 printf("\nEnter filename for saving: "); fflush(stdout);
00290 scanf("%s", save);
00291 fp = fopen(save, "w");
00292 if (fp) {
00293 for (int i = 0; i < rows * cols; i++) {
00294 status = fprintf(fp, "%d%c", x[i], ' ');
00295 if (status < 1)
00296 non_continuable_error(NAME, "save_sample", "bad write");
00297 }
00298 fclose(fp);
00299 } else
00300 printf("\nCould not open file %s\n", save);
00301 }
00302 }
00303
00304 void hamming::read_file(char *filename, int pattern[])
00305 {
00306 int status;
00307 FILE *fp;
00308
00309 fp = fopen(filename, "r");
00310 if (!fp) {
00311 char error_msg[50];
00312 strcpy(error_msg, "could not open file '");
00313 strcat(error_msg, filename);
00314 strcat(error_msg, "'");
00315 non_continuable_error(NAME, "read_file", error_msg);
00316 } else {
00317 for (int i = 0; i < rows * cols; i++) {
00318 status = fscanf(fp, "%d", &pattern[i]);
00319 if (status != 1)
00320 non_continuable_error(NAME, "read_file", "read failed");
00321 }
00322 fclose (fp);
00323 }
00324 }
00325
00326 void hamming::copy_pattern(bit_pattern destination, bit_pattern source)
00327 {
00328 for (int i = 0; i < N; i++) destination[i] = source[i];
00329 }
00330
00331 void hamming::get_defaults()
00332 {
00333 FILE *defaults_file = fopen(DEFAULTS_FILE_NAME, "r");
00334
00335 if (defaults_file == NIL)
00336 non_continuable_error(NAME, "get_defaults", "missing defaults file");
00337
00338 fscanf(defaults_file, "%d\n", &M);
00339 fscanf(defaults_file, "%d\n", &rows);
00340 fscanf(defaults_file, "%d\n", &cols);
00341 fclose(defaults_file);
00342
00343 if (M > MAXIMUM_EXEMPLARS)
00344 non_continuable_error(NAME, "get_defaults", "too many exemplars");
00345
00346 N = rows * cols;
00347 if (N > MAXIMUM_BITS_IN_PATTERN)
00348 non_continuable_error(NAME, "get_defaults", "too many bits in pattern size");
00349
00350 EPSILON = 1.0 / (double)(M+2);
00351 THETA = - (double)N / 2.0;
00352 }
00353
00354 void hamming::get_exemplars()
00355 {
00356 char filename[90];
00357
00358 strcpy(filename, EXEMPLAR_PREFIX);
00359 int posn = int(strlen(filename));
00360 strcat(filename, "00.dat");
00361
00362 for (int i = 0; i < M; i++) {
00363
00364 filename[posn] = (char)( (int)'0' + i / 10);
00365 filename[posn+1] = (char)( (int)'0' + i % 10);
00366
00367 read_file(filename, exemplars[i]);
00368 }
00369 }
00370
00371 int hamming::current_time()
00372 {
00373 return t;
00374 }
00375
00376 int hamming::pattern_rows()
00377 {
00378 return rows;
00379 }
00380
00381 int hamming::pattern_cols()
00382 {
00383 return cols;
00384 }
00385
00386 void hamming::show_pattern_line(int exemplar_number, int line, FILE *print_to)
00387 {
00388 show_pattern_line(exemplars[exemplar_number], line, print_to);
00389 }
00390
00391 #endif //HAMMING_IMPLEMENTATION_FILE
00392