/*                  Zadanie z predmetu: NEURONOVE SIETE
                    Projekt c. 3: Zhlukovanie textovych dokumentov - KOHONEN
                    Riesitel: Tomas Smajda, 4. roc., 2001/2002
                                                                             */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

#define	N1	          399	               // pocet neuronov vo vstupnej vrstve
#define	N2            7 	               // pocet riadkov vo vystupnej vrstve
#define  N3            7                  // pocet stlpcov vo vystupnej vrstve
#define POCET_EPOCH   100                 // pocet epoch

double x_j[N1];                           // hodnoty neuronov vo vstupnej vrstve
double ou[N2][N3];                        // hodnoty vystupnych neuronov
double sv[N1][N2][N3];                    // vahy w(ij)
double dsv[N1][N2][N3];                   // zmena vah dw(ij)
int x1, x2;                               // suradnice vitazneho neuronu
double Gama, r;
FILE *pattern_file, *final_file, *vahy;
char nazov[50][20];                       // pole pre nazvy klasifikovanych suborov
double x[50][N1];                         // polia na ulozenie vstupov

void main(void)
{
   double min, d, temp;
   int i, j, k, l, epocha=0;
   Gama=0.8;
   r=50;

   //randomize();

   if ((final_file = fopen("final_file.txt", "a+")) == NULL){
       fprintf(stderr, "Vystupny - chybovy subor sa neda otvorit.\n");
       printf("Stlacte ENTER a aplikacia sa skonci...");
       getchar();
       exit(1);
   }
   if ((pattern_file = fopen("norm.dat", "r")) == NULL){
       fprintf(stderr, "Datovy subor sa neda otvorit.\n");
       printf("Stlacte ENTER a aplikacia sa skonci...");
       getchar();
       exit(1);
   }
   if ((vahy = fopen("vahy.txt", "w+")) == NULL){
       fprintf(stderr, "Nedaju sa zapisat vahy do vystupneho suboru.\n");
       printf("Stlacte ENTER a aplikacia sa skonci...");
       getchar();
       exit(1);
   }

   fscanf(pattern_file,"%lf %lf", &temp, &temp); // odrezanie cisel 399, 50

   for(i=0;i<50;i++){       // index textoveho suboru  (50 suborov)
     for(j=0;j<399;j++){    // nacitanie 399-rozmerneho vstupneho vektora
            fscanf(pattern_file,"%lf", &x[i][j]);
     }
     fscanf(pattern_file,"%s\n", &nazov[i]); // nacitanie nazvu subora
   }

   // prvotna inicializacia vah
   printf("Stlacte ENTER a inicializuju sa vahy...\n");
   getchar();
   for(i=0;i<N1;i++){
       for(j=0;j<N2;j++){
          for(k=0;k<N3;k++){
             sv[i][j][k]=0.05*rand()/RAND_MAX;
             //printf("sv[%d][%d][%d]=%.10lf\n ", i+1 , j+1, k+1, sv[i][j][k]);
             //getchar();
         }
       }
   }
   do{
      printf("Epocha=%d\t r=%lf\t Gama=%lf\n", epocha, r, Gama);
      for(l=0;l<50;l++){
         for(i=0;i<N1;i++){
            x_j[i]=x[l][i];
         }

         for(i=0;i<N2;i++){         // vypocet hodnoty neuronov na vystupe            for(j=0;j<N3;j++){
               ou[i][j]=0;
               for(k=0;k<N1;k++){
                  ou[i][j]+=(sv[k][i][j]-x_j[k]) * (sv[k][i][j]-x_j[k]);
               }
            }
         }

         min=ou[0][0];              // najdenie minima
         x1=0;
         x2=0;
         for(i=0;i<N2;i++){
            for(j=0;j<N3;j++){
               if(min>ou[i][j]){
                 min=ou[i][j];
                 x1=i;
                 x2=j;
               }
            }
         }

         for(i=0;i<N1;i++){         // zmena vah
            for(j=0;j<N2;j++){
               for(k=0;k<N3;k++){
                  d=((j-x1)*(j-x1))+((k-x2)*(k-x2));
                  d=sqrtl(d);
                  dsv[i][j][k]=-Gama*(sv[i][j][k]-x_j[i])*exp(-d*d/r);
                  sv[i][j][k]+=dsv[i][j][k];
               }
            }
         }
         if(!(epocha%10) || epocha==(POCET_EPOCH-1)){  // vypis na obrazovku
            printf("%s [%d] [%d]\n", nazov[l], x1, x2);
         }
         if(epocha==(POCET_EPOCH-1)){                  // zapis do suboru
            fprintf(final_file,"%s [%d] [%d]\n", nazov[l], x1, x2);
            //fprintf(final_file,"\n");
         }
      }
      r=r/1.09;             // uprava parametrov r, Gama
      Gama=Gama/1.04;

      epocha++;
   }while(epocha<POCET_EPOCH);

   fprintf(final_file,"\n");

   // ulozenie konecnych vah do suboru "vahy.txt"
   for(j=0;j<N2;j++){
       for(k=0;k<N3;k++){
          for(i=0;i<N1;i++){
             fprintf(vahy,"%.10lf\t", sv[i][j][k]);
          }
          fprintf(vahy,"\n");
       }
   }

   fclose(final_file);
   fclose(vahy);
   fclose(pattern_file);

   printf("\nKlasifikovane subory sa ulozili do suboru 'final_file.txt'\n");
   printf("Stlacte ENTER a aplikacia sa skonci...");
   getchar();
}

