
/****************************************************************************/
/* CALCULA la funcion logica de una tabla , con un hilo de alg genetico                   */
/* y con un Hilo de un alg aletatorio                                       */
/***************************************************************************/                            



import java.awt.*;
import java.applet.*;
import java.awt.event.*;
import java.lang.*;



public class Ejemplo extends Applet implements Runnable {

  //*** TAMANYO DEL APPLET
  int WIDTH=300;



  //******************************************************************/ 
   int TAM_ENTRADA=3; // Numero de variables de entrada 
   int TABLA[][]=new int[(int)Math.pow(2,TAM_ENTRADA)][TAM_ENTRADA];
   int RESULTADO[]=new int[(int)Math.pow(2,TAM_ENTRADA)];
   int ww,v;
  

  //****VARIABLES A CERCA DE LA MATRIZ DE CELDAS******************/
  int N_ENTRADAS=2;  // variables de entrada a las puertas logicas  
  int N_COLUMNAS=2;  // columnas de la matirz (puertas por columna)
  int col;
  int N_FILAS=N_COLUMNAS; // filas de la matriz
  
  int N_TIPO_PUERTAS=10; // 0:and 1:or 2:xor 3:not 4:not2  5:dir 6:dir2 
                         // 7:nand 8:nor 9:xnor   
  
  //**********VARIABLES INTRODUCIDAS POR MI *******************
  //INFORMACION ACERCA DE LA POBLACIÓN
  int TAM_POB=50;     // tamaño de la poblacion 
  int NUM_GEN=(N_ENTRADAS+1)*N_COLUMNAS*N_FILAS +(N_ENTRADAS+1); // numero de genes de cada cormosoma
  int[][] cromosomas=new int[TAM_POB][NUM_GEN];  // matriz que contiene la poblacion
  int[] evalua=new int[NUM_GEN]; // auxiliar para evaluar
  int[] vector_entrada=new int[TAM_ENTRADA];

  // INFORMACION ACERCA DEL COMPORTAMIENTO DE LA POBLACION
  int ELITISTA=0;      // comportamiento no elitista  
  int NUMERO_MEJORES=2; // los 4 mejores que se cruzaran
  int PROB_MUTACION=5; // prob de mutacion del 5%
  int PROB_CRUCE=85; // prob de cruce del 95%
  int[] suma=new int[TAM_POB]; // evaluacion de cada cromosoma
  int[] sector=new int[TAM_POB]; // porcentaje del sector que ocupa
                                 // la ruleta
  int[] indice=new int[TAM_POB]; // elementos seleccionados
  int[][] reproducir=new int[TAM_POB][NUM_GEN];// matriz que contiene los
                                               // elementos seleccionado o sea
  //OTROS                                      // los que van a reproducirse.
  int SUMA_TOTAL; // suma de todos los suma
  int[] fitness=new int[TAM_POB]; // fitness de cada cromosoma
  int MAXIMO=63;       // valor maximo que se permite buscar
  int FITNESS_BUSCADO=14;
  int ITERACIONES=500; // numero de veces que repito el bucle
  int[] media=new int[ITERACIONES]; // contiene la media de cada pob
  int[] mejores=new int[ITERACIONES]; // contiene el mejor de cada pob
  int[] peores=new int[ITERACIONES]; // contiene el peor de cada pob
  int[] aux=new int[NUM_GEN];
  int[][] cromosomas2=new int[TAM_POB][NUM_GEN];// matriz que contiene la poblacion

 
  // VARIABLES USADAS EN LOS HILOS
    /**** USADAS AL GENERAR LA POBLACION************/
    int pob,gen;
    int primera_vez; /* generacion de poblacion */
    int t;
    int genaux,auxx;
    /**********************************************/

  
    /****** USADAS AL COMENZAR EL ALGORITMO **********/
    int sel; // numero elementos seleccionados
    int elemento_de_cruce; // en que gen cruzo
    int muta;
    int i,bucle,fin,pareja;
    int gen_mutado; //gen aleatorio que va a mutarse
    int valor_mejor; // indice del mejor en cada vuelta 
    int valor_peor;
    String cad;

    int ruleta;
    int flecha_ruleta;
    int TOTAL;  // usado en el calclulo de % de la ruleta
    int max; // el cromosoma que mas se aleja 
    int min; //el cromosoma que + se acerca
    /****************************************************/

    /***********BOTONES Y DEMAS **************************************/
     Button Comenzar;    
     Button ProbCruceMas;
     Button ProbCruceMenos;
     Button ProbMutacionMas;
     Button ProbMutacionMenos;
     Button ElitistaSi;
     Button ElitistaNo;
     a_l Objeto; // clase que impleneta el manejador de eventos
     Label     EtiquetaCruce;
     Label     EtiquetaMutacion;
     TextField TextoCruce;
     TextField TextoMutacion;
     TextField TextoElitista; 
    /*****************************************************************/   

    /***BOTONES PARA LA TABLA DE VERDAD ***/
    Button[] Botones=new Button[(int)Math.pow(2,TAM_ENTRADA)];

    /*********** TAMAÑOS DE FUENTE Y ESO*******************************/
    Font font1;

Thread AlgoritmoGenetico;
Thread AlgoritmoAleatorio;


String nada;
String circuito;
String salida;
String Salida_de_exito;

public void init(){

 AlgoritmoGenetico=new Thread(this);
 AlgoritmoAleatorio=new Thread(this);
 primera_vez=0;
 
 Objeto=new a_l();
 Objeto.tipo(this); // Le indico a la clase que implementa los eventos
                    // que los eventos se leen de esta clase


 Comenzar=new Button("COMENZAR");
 Comenzar.addActionListener(Objeto); // el escuchador de eventos esta en Objeto
 
 EtiquetaCruce=new Label("Prob de cruce:");
 TextoCruce=new TextField(" "+PROB_CRUCE,35);

 EtiquetaMutacion=new Label("Prob de mutacion:");
 TextoMutacion=new TextField(" "+PROB_MUTACION,35);

 TextoElitista=new TextField("Modo no elistista",35); 
 
 ProbCruceMas=new Button("+"); 
 ProbCruceMas.addActionListener(Objeto);  

 ProbCruceMenos=new Button("-"); 
 ProbCruceMenos.addActionListener(Objeto);  

 ProbMutacionMas=new Button("+"); 
 ProbMutacionMas.addActionListener(Objeto);  

 ProbMutacionMenos=new Button("-"); 
 ProbMutacionMenos.addActionListener(Objeto);  

 ElitistaSi=new Button("ELITISTA");
 ElitistaSi.addActionListener(Objeto);
 
 ElitistaNo=new Button("NO ELITISTA");
 ElitistaNo.addActionListener(Objeto);
 

 this.add(EtiquetaCruce);
 this.add(ProbCruceMas);
 this.add(ProbCruceMenos);
 this.add(TextoCruce);
 
 this.add(EtiquetaMutacion);
 this.add(ProbMutacionMas);
 this.add(ProbMutacionMenos);
 this.add(TextoMutacion); 

 this.add(ElitistaSi);
 this.add(ElitistaNo);
 this.add(TextoElitista);

 this.add(Comenzar);

 for(i=0;i<Math.pow(2,TAM_ENTRADA);i++)
 { 
  Botones[i]=new Button("0");
  this.add(Botones[i]);
  Botones[i].addActionListener(Objeto);
 }

   TABLA[0][0]=0; TABLA[0][1]=0; TABLA[0][2]=0;  RESULTADO[0]=0;
   TABLA[1][0]=0; TABLA[1][1]=0; TABLA[1][2]=1;  RESULTADO[1]=0;
   TABLA[2][0]=0; TABLA[2][1]=1; TABLA[2][2]=0;  RESULTADO[2]=0;
   TABLA[3][0]=0; TABLA[3][1]=1; TABLA[3][2]=1;  RESULTADO[3]=0;
   TABLA[4][0]=1; TABLA[4][1]=0; TABLA[4][2]=0;  RESULTADO[4]=0;
   TABLA[5][0]=1; TABLA[5][1]=0; TABLA[5][2]=1;  RESULTADO[5]=0;
   TABLA[6][0]=1; TABLA[6][1]=1; TABLA[6][2]=0;  RESULTADO[6]=0;
   TABLA[7][0]=1; TABLA[7][1]=1; TABLA[7][2]=1;  RESULTADO[7]=0;
 

 font1=new Font("TimesRoman",Font.BOLD,8);

}


public void run() {

Thread.currentThread().setPriority(Thread.MIN_PRIORITY);

// bucle de animacion

primera_vez=0;
while (Thread.currentThread()==AlgoritmoGenetico)
{

  /********** BLOQUE DONDE GENERO LA POBLACION *******************/
   if (primera_vez==0)
   { 
    Salida_de_exito="--->"+"De momento sin extio...."; 
    for (pob=0;pob<TAM_POB;pob++)
     for (gen=0;gen<NUM_GEN;gen++)
     {
       col=(int)(gen/((N_ENTRADAS+1)*N_FILAS));
       if (gen==NUM_GEN-1) cromosomas[pob][gen]=1; // ultima puerta un or
       else 
       if (gen%(N_ENTRADAS+1)==N_ENTRADAS) 
        cromosomas[pob][gen]=(int)(Math.random()*(N_TIPO_PUERTAS));
       else 
       if(col==0) 
         cromosomas[pob][gen]=(int)(Math.random()*TAM_ENTRADA);
       else 
        cromosomas[pob][gen]=N_ENTRADAS+((N_ENTRADAS+1)*N_FILAS*(col-1))+((int)(Math.random()*N_FILAS))*(N_ENTRADAS+1);
     } // fin for gen;     
      primera_vez=1;
   } //fin if primera vez
   
    //***********FIN DE GENERACION DE POBLACION*************/
  


  
   /***********BLOQUE DE COMIENZO DEL ALGORITMO ***************************/

   for (bucle=0;bucle<ITERACIONES;bucle++)
   {

    // vuelvo a calcular el suma y todo esto
    SUMA_TOTAL=0;
    TOTAL=0;
    min=MAXIMO;
    max=0;
            

        //************** COMIENZA LA EVALUACION *************//
     for (pob=0;pob<TAM_POB;pob++)
     {
         circuito=" ";
         salida=" ";
  	 fitness[pob]=0;
         for (gen=0;gen<NUM_GEN;gen++)
           if ((gen%(N_ENTRADAS+1))==N_ENTRADAS) circuito+="--"+cromosomas[pob][gen]+"--";
           else  circuito+=":"+cromosomas[pob][gen];
                                                                                      
                                                                                                                                                           
	   for(ww=0;ww<(int)Math.pow(2,TAM_ENTRADA);ww++)
           {
              for (gen=0;gen<NUM_GEN;gen++) evalua[gen]=cromosomas[pob][gen];
     		 for(v=0;v<TAM_ENTRADA;v++)
        	 {
                  vector_entrada[v]=TABLA[ww][v];
                 } 

     	         i=N_ENTRADAS;
           	 while (i<NUM_GEN)
     	         {
                   if (i<(N_ENTRADAS+1)*N_COLUMNAS) /* valores de la entrada */
                   { 
                     evalua[i-2]=vector_entrada[evalua[i-2]];
                     evalua[i-1]=vector_entrada[evalua[i-1]];
                   }
                   
                    switch(evalua[i]) 
                    {
          
         		 /*** and ****/ 
         		 case 0:
                         evalua[i]=evalua[evalua[i-1]]&evalua[evalua[i-2]];         
                         break;
 
 		         /*** or ****/
         		 case 1:
                         
         		 evalua[i]=evalua[evalua[i-1]]|evalua[evalua[i-2]];
                         break;
 
 		         /*** xor ***/
         		 case 2:
         		 //evalua[i]=evalua[evalua[i-1]]^evalua[evalua[i-2]];
         		 if (evalua[evalua[i-1]]==evalua[evalua[i-2]])
                              evalua[i]=0;
                         else
                             evalua[i]=1;
                          break;

                         /**** not ***/
                           case 3:
         		   evalua[i]=Math.abs(1-evalua[evalua[i-2]]); // niego una entrada , la otra
                           break;

                         /**** not (de la otra) ***/
                           case 4:
         		   evalua[i]=Math.abs(1-evalua[evalua[i-1]]); // niego una entrada , la otra
                           break;
                        
                         
                         /**** directo ***/
                           case 5:
         		   evalua[i]=evalua[evalua[i-2]]; // niego una entrada , la otra
                           break;
                        
                         /**** directo de la otra ***/
                           case 6:
         		   evalua[i]=evalua[evalua[i-1]]; // niego una entrada , la otra
                           break;
                             
                          // nand  
         		 case 7:
                           evalua[i]=evalua[evalua[i-1]]&evalua[evalua[i-2]];         
                           evalua[i] =Math.abs(1-evalua[i]);
                          break;
 
 		         // nor 
         		 case 8:
                         
         		   evalua[i]=evalua[evalua[i-1]]|evalua[evalua[i-2]];
                           evalua[i] =Math.abs(1-evalua[i]);
                         
                         break;
 
 		         // xnor 
         		 case 9:
         		 //evalua[i]=evalua[evalua[i-1]]^evalua[evalua[i-2]];
         		 if (evalua[evalua[i-1]]==evalua[evalua[i-2]])
                              evalua[i]=0;
                         else
                             evalua[i]=1;
                        
                         evalua[i]=Math.abs(1-evalua[i]);
                          
                         break;

                        
                          
                  
	             } // fin switch
        		 i=i+(N_ENTRADAS+1);
                 } // fin while i<NUM_GEN
                  if (evalua[NUM_GEN-1]==RESULTADO[ww]) fitness[pob]++;
                 salida+=" "+evalua[NUM_GEN-1];
           } // fin for ww

     	 TOTAL+=fitness[pob];
     	 SUMA_TOTAL+=TOTAL;
         if (fitness[pob]<min) {min=fitness[pob];valor_peor=pob;peores[bucle]=fitness[pob];}
         if (fitness[pob]>max)
         {
          max=fitness[pob];
          if (max==Math.pow(2,TAM_ENTRADA))
             Salida_de_exito="EXITO, el circuito es :"+circuito;
        
          valor_mejor=pob;
          mejores[bucle]=fitness[pob];
          nada="-->"+salida;
          circuito="-->"+circuito;
        }

    
      }// fin del for pob

        media[bucle]=(int)((int)((TOTAL*100)/TAM_POB)/Math.pow(2,TAM_ENTRADA)); //media de la poblacion
        
                 
      
         repaint();

      
         try { 
         Thread.sleep(250);
          }catch (InterruptedException e) { break;}
        
    
          
        sector[0]=0; 
        for (pob=1;pob<TAM_POB;pob++) sector[pob]=sector[pob-1]+(int)((fitness[pob]*100)/TOTAL);
    
            

    //  FASE DE SELECCION
      sel=0;
      pob=0;
   
    // giramos la ruleta
    
    //-***************** caso elitista ********************************-/

	     if (ELITISTA==1)
    		 {    
       		  for (gen=0;gen<NUM_GEN;gen++)
      		   cromosomas2[0][gen]=cromosomas[valor_mejor][gen];
                    sel=1;   
    		 }
    		 else
     		 sel=0; 
    //-*******************************************************************-/    
 
       while (sel<TAM_POB)
       {    
           
      		 flecha_ruleta=(int)(Math.random()*100);
    
    		 for (ruleta=0;ruleta<TAM_POB;ruleta++)
      		 {
       		 if (flecha_ruleta<=sector[ruleta])
          		{
          		  pob=ruleta;
           		  ruleta=TAM_POB;
           		  break;
         		 }      
                 } 
       
         if ((int)(Math.random()*100)<PROB_CRUCE)
         {
           elemento_de_cruce=(int)(Math.random()*NUM_GEN)+1; //1..NUM_GEN
           do{ //-*-evito que se cruce con si mismo *-/
             pareja=(int)(Math.random()*TAM_POB); //0..TAM_POB-1
            } while (pareja==pob); 


           // seleccion y cruce de la primera parte de los hijos
          for (gen=0;gen<elemento_de_cruce;gen++)
          {
           cromosomas2[sel][gen]=cromosomas[pob][gen];
           if ((TAM_POB-sel)>1)
           cromosomas2[sel+1][gen]=cromosomas[pareja][gen];
          }
          // seleccion de la segunda parte
          for (gen=elemento_de_cruce;gen<NUM_GEN;gen++)
          {
           cromosomas2[sel][gen]=cromosomas[pareja][gen];
           if ((TAM_POB-sel)>1)
           cromosomas2[sel+1][gen]=cromosomas[pob][gen];
          }
          sel=sel+2;    
         } // fin if se reproducen 
         else {
               for (gen=0;gen<NUM_GEN;gen++)
                 cromosomas2[sel][gen]=cromosomas[pob][gen];
               sel++; 
             } // fin if no se reproducen 

 
      }// fin sel



     //-* fase de mutacion *-/
 
     //-*
      muta=0;
      for (pob=0;pob<TAM_POB;pob++)
      {
         if ( PROB_MUTACION>(int)(Math.random()*100))  muta=1;
         else muta=0;         
         for (gen=0;gen<NUM_GEN;gen++)
         {
           cromosomas[pob][gen]=cromosomas2[pob][gen];
           
            if ((muta==1 )&&((int)(Math.random()*100)<20))
            {
             gen_mutado=(int)(Math.random()*NUM_GEN); //0..NUM_GEN-1
             col=(int)(gen_mutado/((N_ENTRADAS+1)*N_FILAS));
            if (gen==NUM_GEN-1) cromosomas[pob][gen]=1; // ultima puerta un or
            else
            if (gen_mutado%(N_ENTRADAS+1)==N_ENTRADAS) 
               cromosomas[pob][gen_mutado]=(int)(Math.random()*(N_TIPO_PUERTAS));
            else if(col==0) 
            cromosomas[pob][gen_mutado]=(int)(Math.random()*TAM_ENTRADA);
            else 
            cromosomas[pob][gen_mutado]=N_ENTRADAS+((N_ENTRADAS+1)*N_FILAS*(col-1))+((int)(Math.random()*N_FILAS))*(N_ENTRADAS+1);
           }
           
         }
      }

      

   
    
 } // fin for bucle

         
} // fin del while 

 
 
} // fin run



public void paint (Graphics g)
   {
     
       
       g.setFont(font1);
       g.setColor(Color.red);
       g.drawString("Iteracion: "+bucle+" Pob :"+pob,10,WIDTH-70);
       g.drawLine(0,WIDTH-200,ITERACIONES,WIDTH-200);
       
         
       g.setColor(Color.green);
       g.drawString("MAX:"+max+"MIN:"+min+"Media"+media[bucle],10,WIDTH-50);
      
      
       g.setColor(Color.blue);
       g.drawString("Circuito:"+circuito,10,WIDTH-30);
      
       g.setColor(Color.blue);
       g.drawString("Salida:"+nada,10,WIDTH-10);
      
       g.setColor(Color.black);
       g.drawString(Salida_de_exito,10,WIDTH-100);
     
       g.setColor(Color.yellow);
       for (i=0;i<bucle;i++)
       g.drawLine(i,WIDTH-100-(media[i]),i,WIDTH-100-(media[i]));
             
   } // fin paint
      



} // fin clase





/***************************************************************************/
/* Esto es una clase que implementa el manejador de eventos ***************/

class a_l implements ActionListener{

Ejemplo c;
int i;

void tipo(Ejemplo obj){ 
 c=obj;
}

public void actionPerformed(ActionEvent e){

        for(i=0;i<Math.pow(2,c.TAM_ENTRADA);i++)
        {
          if (e.getSource()==c.Botones[i])
          {
           c.Salida_de_exito="De momento sin exito"; 
           if (c.Botones[i].getLabel()=="0")
           {  
             c.Botones[i].setLabel("1");
             c.RESULTADO[i]=1;
           } 
           else
           {
            c.Botones[i].setLabel("0");
            c.RESULTADO[i]=0;
           } 
          }
        }

 	if (e.getSource()==c.Comenzar){
          c.AlgoritmoGenetico.start();
          c.Comenzar.disable();
	 }


       if (e.getSource()==c.ProbCruceMas){
          c.PROB_CRUCE++;
          if (c.PROB_CRUCE==100) c.ProbCruceMas.disable();
          c.ProbCruceMenos.enable();
          c.TextoCruce.setText(" "+c.PROB_CRUCE); 
       }

       if (e.getSource()==c.ProbCruceMenos){
          c.PROB_CRUCE--;
          if (c.PROB_CRUCE==70) c.ProbCruceMenos.disable();
          c.ProbCruceMas.enable();
          c.TextoCruce.setText(" "+c.PROB_CRUCE); 
       }

       if (e.getSource()==c.ProbMutacionMas){
           c.PROB_MUTACION++;
           if (c.PROB_MUTACION==25) c.ProbMutacionMas.disable();
           c.ProbMutacionMenos.enable();
           c.TextoMutacion.setText(" "+c.PROB_MUTACION); 
       }

       if (e.getSource()==c.ProbMutacionMenos){
           c.PROB_MUTACION--;
           if (c.PROB_MUTACION==0) c.ProbMutacionMenos.disable();
           c.ProbMutacionMas.enable();
           c.TextoMutacion.setText(" "+c.PROB_MUTACION); 
       }

      if (e.getSource()==c.ElitistaSi) {
           c.TextoElitista.setText("Modo  Elitista");
           c.ELITISTA=1;
           
       }   

      if (e.getSource()==c.ElitistaNo) {
          c.TextoElitista.setText("Modo no Elitista"); 
          c.ELITISTA=0;
       }

 } // fin action peroformed


} // fin clase


