hamming.cpp

Go to the documentation of this file.
00001 #ifndef HAMMING_IMPLEMENTATION_FILE
00002 #define HAMMING_IMPLEMENTATION_FILE
00003 
00004 /*****************************************************************************\
00005 *                                                                             *
00006 *  Name   : hamming network                                                   *
00007 *  Author : Chris Koeritz                                                     *
00008 *                                                                             *
00009 *******************************************************************************
00010 * Copyright (c) 1992-$now By Author.  This program is free software; you can  *
00011 * redistribute it and/or modify it under the terms of the GNU General Public  *
00012 * License as published by the Free Software Foundation; either version 2 of   *
00013 * the License or (at your option) any later version.  This is online at:      *
00014 *     http://www.fsf.org/copyleft/gpl.html                                    *
00015 * Please send any updates to: fred@gruntose.com                               *
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 // the bit on/off represent binary information.
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;   // keeps track of bits already flipped.
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   // corruption is the list of weights that are incorrect
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;  // clear all corruptions
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         // a value from 0 to 30000, divided by 30000, is from 0 to 1.
00087         // then subtracting 1/2 gives us a value in the right weight range.
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   // the list of weights incorrect in maxnet
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;  // clear all corruptions
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         // a value from 0 to 30000, divided by 15000, is from 0 to 2.
00122         // then subtracting 1 gives us a value in the right range.
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     // range is from N over 2 to -N over 2.
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;  // set clock to starting time
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++;  // time marches on....
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       // no output was standing previously, so this is current hope.
00195       standing = i;
00196     else if (mu [t] [i] > 0.0)
00197       // a value was already standing, so return a failure.
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;   // the winner.
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     // looping over the set of exemplars
00249     for (int k = 0; k < rows; k++) {
00250       // looping over each row of the current set
00251       for (int j = i; j < i + exemplars_that_fit; j++) {
00252         // looping over each exemplar's current row
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);     // first is number of patterns
00339   fscanf(defaults_file, "%d\n", &rows);  // second is number of rows
00340   fscanf(defaults_file, "%d\n", &cols);  // third is number of columns
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;                       // bits per exemplar
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");  // add suffix for first
00361 
00362   for (int i = 0; i < M; i++) {
00363     // fix filename up to get current exemplar
00364     filename[posn] = (char)( (int)'0' + i / 10);
00365     filename[posn+1] = (char)( (int)'0' + i % 10);
00366     // read file name into the exemplar storage
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 

Generated on Tue Aug 19 04:29:44 2008 for HOOPLE Libraries by  doxygen 1.5.1