/************************************

* Name: Musawir Ali *

************************************

Type: Console Application

Instructions: Compile and run with any C++ compiler (coded on MS VisualC++) 

Sample input:

Enter a 7x7 matrix of 1's and 0's (49 digits in all):

1 1 1 1 1 1 1

0 0 0 0 0 0 0

1 1 1 1 1 1 1

1 1 1 1 1 1 1

1 1 1 1 1 1 1

0 0 0 0 0 0 0

0 0 0 0 0 0 0

Add more? y

1 0 1 0 1 0 1

0 1 1 1 1 1 0

1 1 1 1 1 1 1

1 1 1 1 1 1 1

1 1 1 1 1 1 1

0 0 0 0 0 0 0

0 0 0 0 0 0 0

Add more? y

1 0 1 0 1 0 1

0 1 0 1 0 1 0

0 0 0 0 0 0 0

1 1 1 1 1 1 1

1 1 1 1 1 1 1

0 0 0 0 0 0 0

0 0 0 0 0 0 0

Add more? n

Done Learning! Now enter a pattern to recognize.

1 0 1 1 1 0 1

0 1 0 1 0 1 0

0 0 0 0 0 0 0

1 1 1 1 1 1 1

1 1 1 1 1 1 1

0 0 0 0 0 0 0

0 0 0 0 0 0 0

Pattern recognized as:

1 0 1 0 1 0 1

0 1 0 1 0 1 0

0 0 0 0 0 0 0

1 1 1 1 1 1 1

1 1 1 1 1 1 1

0 0 0 0 0 0 0

0 0 0 0 0 0 0 

******************************

End of Demonstration

*/

#include 

#include 

#include 

using namespace std;

class agent

    {

    private:

     int input[49]; //Input Layer

     int output[49]; //Output Layer

     double w1[49][25]; //Weights layer 1

     double w2[25][49]; //Weights layer 2

     double hidden[25]; //Hidden Layer

     //Get the input from the main function and update the Input Layer

     void fill_input(int array[49])

         {

         for(int i=0;i<49;i++)

         input[i]=array[i];

         }

         //Make the Output layer equal to the Input layer

         void io()

             {

             for(int i=0;i<49;i++)

             output[i]=input[i];

             }

             //Fill the Weights layer 1 with random decimal numbers between 0 and 1

             void fill_w1()

                 {

                 for(int i=0;i<49;i++)

                     {

                     for(int j=0;j<25;j++)

                         {

                         w1[i][j] = double(rand())/double(RAND_MAX);

                         }

                         }

                         }

                         //Fill the hidden layer from the input and weights 1 layers

                         void fill_hidden()

                             {

                             for(int i=0;i<49;i++)

                                 {

                                 for(int j=0;j<25;j++)

                                 hidden[j] += input[i]*w1[i][j];

                                 }

                                 }

                                 //Get the address of the maximum number from the hidden layer

                                 //and update the weights layers 1 and 2 from the input layer.

                                 void get_maxi()

                                     {

                                     double max=0.0;

                                     int address=0;

                                     for(int i=0;i<25;i++)

                                         {

                                         if(max < hidden[i])

                                             {

                                             max=hidden[i];

                                             address=i;

                                             }

                                             }

                                             hidden[address]=-8888.88;

                                             for(i=0;i<25;i++)

                                                 {

                                                 if(i!=address && hidden[i]>=0)

                                                 hidden[i]=0.0;

                                                 }

                                                 for(i=0;i<49;i++)

                                                     {

                                                     if(input[i]==1)

                                                         {

                                                         w2[address][i] = 1;

                                                         w1[i][address]=1;

                                                         }

                                                         else

                                                             {

                                                             w2[address][i] = 0;

                                                             w1[i][address]=0;

                                                             }

                                                             }

                                                             }

                                                             //Initialize input and output layers.

                                                             void init()

                                                                 {

                                                                 for(int i=0;i<49;i++)

                                                                     {

                                                                     input[i]=0;

                                                                     output[i]=0;

                                                                     }

                                                                     }

                                                                     //Initialize all the layers

                                                                     void initall()

                                                                         {

                                                                         for(int i=0;i<49;i++)

                                                                             {

                                                                             input[i]=0;

                                                                             output[i]=0;

                                                                             }

                                                                             for(i=0;i<25;i++)

                                                                             hidden[i]=0.0;

                                                                             }

                                                                             //Get the address of the maximum number from the hidden layer

                                                                             //and update the weights layers 1 and 2 from the output layer.

                                                                             void get_maxo()

                                                                                 {

                                                                                 double max=0.0;

                                                                                 int address=0;

                                                                                 for(int i=0;i<25;i++)

                                                                                     {

                                                                                     if(max < hidden[i])

                                                                                         {

                                                                                         max=hidden[i];

                                                                                         address=i;

                                                                                         }

                                                                                         }

                                                                                         hidden[address]=-8888.88;

                                                                                         for(i=0;i<25;i++)

                                                                                             {

                                                                                             if(i!=address && hidden[i]>=0)

                                                                                             hidden[i]=0.0;

                                                                                             }

                                                                                             for(i=0;i<49;i++)

                                                                                                 {

                                                                                                 output[i]=w2[address][i];

                                                                                                 }

                                                                                                 }

                                                                                                public: //Bringing everything together...

                                                                                                 agent() //Default Constructor

                                                                                                     {

                                                                                                     for(int i=0;i<49;i++)

                                                                                                         {

                                                                                                         input[i]=0;

                                                                                                         output[i]=0;

                                                                                                         for(int j=0;j<25;j++)

                                                                                                             {

                                                                                                             w1[i][j]=0.0;

                                                                                                             w2[j][i]=0.0;

                                                                                                             }

                                                                                                             }

                                                                                                             for(i=0;i<25;i++)

                                                                                                             hidden[i]=0;

                                                                                                             }

                                                                                                             //The basic learning mechanism. Consists of functions defined earlier

                                                                                                             void learn(int array[49],int i)

                                                                                                                 {

                                                                                                                 init();

                                                                                                                 fill_input(array);

                                                                                                                 io();

                                                                                                                 if(i==0)

                                                                                                                 fill_w1();

                                                                                                                 fill_hidden();

                                                                                                                 get_maxi();

                                                                                                                 }

                                                                                                                 //The basic recall mechanism. Consists of functions defined earlier

                                                                                                                 void recall(int array[49])

                                                                                                                     {

                                                                                                                     initall();

                                                                                                                     fill_input(array);

                                                                                                                     io();

                                                                                                                     fill_hidden();

                                                                                                                     get_maxo();

                                                                                                                     }

                                                                                                                     //Prints out the matrix in the output layer

                                                                                                                     void print()

                                                                                                                         {

                                                                                                                         for(int i=0;i<49;i++)

                                                                                                                             {

                                                                                                                             if(i%7==0)

                                                                                                                             cout << "\n" << output[i] << " ";

                                                                                                                             else

                                                                                                                             cout << output[i] << " ";

                                                                                                                             }

                                                                                                                             }

                                                                                                                        };

                                                                                                                        //Main Function. All this is take the in

                                                                                                                        //     put matrix for learning and outputs

                                                                                                                        //recognized matrix.

                                                                                                                        void main()

                                                                                                                            {

                                                                                                                             agent myagent;

                                                                                                                             int count=0;

                                                                                                                             int array[49];

                                                                                                                             char add='y';

                                                                                                                             cout << "Enter a 7x7 matrix of 1's and 0's (49 digits in all):" << endl;

                                                                                                                             while(add=='y')

                                                                                                                                 {

                                                                                                                                 for(int i=0;i<49;i++)

                                                                                                                                 cin >> array[i];

                                                                                                                                 myagent.learn(array,count);

                                                                                                                                 count++;

                                                                                                                                 cout << "\nAdd more? ";

                                                                                                                                 cin >> add;

                                                                                                                                 }

                                                                                                                                 cout << "\n\nDone Learning! Now enter a pattern to recognize.\n" << endl;

                                                                                                                                 for(int i=0;i<49;i++)

                                                                                                                                 cin >> array[i];

                                                                                                                                 myagent.recall(array);

                                                                                                                                 cout << "\nPattern recognized as:\n" << endl;

                                                                                                                                 myagent.print();

                                                                                                                            }