#lang racket

;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    (define-struct regla
    ;(struct regla
      (   
       (fuerza #:mutable)
       (antecedente #:mutable)
       (produccion #:mutable)
       (id #:mutable)
       )
      #:transparent
      )
(define operaciones-ag%
  (class object%
    ;;;;;POBLACION INICIAL;;;;;;
    (define intervalo
      (lambda (a b)
        (if (> a b)
            '()
            (cons a
                  (intervalo (add1 a) b))
            )
        ))
    ;;;;;;;;;;;;;;;;;;;;;;;
    (define mutando-gen;fuerza a que el gen cambie
      (lambda (gen)
        (let ((gen-mutante (haz-gen!)))
          (if (equal? gen gen-mutante)
              (mutando-gen gen)
              gen-mutante) )
        ))
    ;;;;;;;;;;;;;;;;;;;;;;;
    (define haz-gen!
      (lambda ()
        (let ((tabla-pares
               (list
                (cons 0 0)
                (cons 0 #\#)
                (cons 1 1)
                ) )
              (azar (random 3))
              )
          (list-ref tabla-pares azar)
          )
        ))
    (define genera-antecedente
      (lambda ()
        (map
         (lambda (o)
           (haz-gen!)
           )
         '(0 1 2 3 4 5 6 7))
        ))
    (define genera-produccion
      (lambda (antecedente)
        (ormap
         (lambda (par ord)
           (if (char? (cdr par))
               #f
               ord)
           )
         antecedente '(0 1 2 3 4 5 6 7))
        ))
    (define gen-regla
      (lambda ()
        (let* ((antecedente (genera-antecedente))
               (accion (genera-produccion antecedente))
               )
          (list antecedente accion)
          )
        ))
    (define antecedente-con-accion
      (lambda (accion)
        (map
         (lambda (ord)
           (if (= ord accion)
               (if (= 0 (random 2)) (cons 0 0) (cons 1 1))
               (haz-gen!))
           )
         '(0 1 2 3 4 5 6 7))
        ))
    (define gen-subpoblacion
      (lambda (n accion temp)
        (if (= n 0)
            temp
            (let ((r (list (antecedente-con-accion accion) accion)) )
              (if (member r temp)
                  (gen-subpoblacion n accion temp)
                  (gen-subpoblacion (sub1 n) accion (cons r temp))
                  )
              )
            )
        ))
    (define gen-poblacion
      (lambda (n);n divisible por 8
        (append-map
         (lambda (A)
           (gen-subpoblacion (quotient n 8) A '())
           )
         '(0 1 2 3 4 5 6 7)
         )
        ))
    (define poblacion
      (lambda (n temp)
        (if (= n 0)
            temp
            (let ((r (gen-regla)) )
              (if (member r temp)
                  (poblacion n temp)
                  (poblacion (sub1 n) (cons r temp))
                  )
              )
            )
        ))
    (define/public make-BC
      (lambda (n)
        (map
         (lambda (individuo ord)
           (make-regla 1 (first individuo) (second individuo) ord)
           )
         (poblacion n '()) (intervalo 0 (sub1 n)))
        ))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Módulo SELECCION PROGENITORES
;;el método de la ruleta de Goldberg
;;genera una tira de números dado el primero y la cantidad de números
(define tira-numeros
  (lambda (prim cant)
    (let go ((i 0)
             (j cant)
             )
      (if (= i j)
          '()
          (cons
           (+ prim i)
           (go (add1 i) j))
          ))
    ))

;;como distintos individuos pueden tener igual fit, a cada uno le corresponderá
;;una tira de igual longitud pero con números distintos.
;;formamos grupos con los individuos de igual fit
(define da-tiras-cada-individuo
  (lambda (reverse-poblacion fit-primero base cant)
    (if (null? reverse-poblacion)
        '()
        (if (equal? (regla-fuerza (car reverse-poblacion)) fit-primero)
            (cons
             (cons (tira-numeros base cant) (car reverse-poblacion))
             (da-tiras-cada-individuo 
              (cdr reverse-poblacion) fit-primero (+ base cant) cant))
            (da-tiras-cada-individuo 
             reverse-poblacion (regla-fuerza (car reverse-poblacion)) base (add1 cant))
            )) 
    ))



(define metodo-goldberg-ruleta
  (lambda (pob)
    (let* ((pobl (da-tiras-cada-individuo (reverse pob) (regla-fuerza (last pob)) 0 1))
           (nmax (last(car(last pobl))))
           )
      (let go
        ((i 0)
         (j (length pob))
         (num (random nmax))
         )
        (if (= i j)
            '()
            (append
             (remove 
              (void)
              (remove-duplicates
               (map
                (lambda (x)
                  (if (member num (car x))
                      (cdr x)
                      (void)))
                pobl)))
             (go (add1 i) j (random nmax)))
            ))
      ) ))

(define otro-azar;fuerza a que n cambie
  (lambda (n lon)
    (let ((num (random lon)))
      (if (equal? num n)
          (otro-azar n lon)
          num) )))
(define remove-por-ref
  (lambda (lista ref)
    (let ((comienzo (take lista ref))
          (resto (drop lista (add1 ref)))
          )
      (append comienzo resto) )))
(define empareja-dos-azar;
  (lambda (padres);un padre = (fitness (representación))
    (if (null? padres)
        '()
        (let* ((long (length padres))
               (n1-azar (random long))
               (n2-azar (otro-azar n1-azar long))
               (prog1 (list-ref padres n1-azar));(cadr (list-ref padres n1-azar)))
               (prog2 (list-ref padres n2-azar));(cadr (list-ref padres n2-azar)))
              )
          (cons
           (list prog1 prog2)
           (empareja-dos-azar
            (if (> n1-azar n2-azar)
                (remove-por-ref
                 (remove-por-ref padres n1-azar) n2-azar)
                (remove-por-ref
                 (remove-por-ref padres n2-azar) n1-azar)) ))
          )
        ) ))



(define son-padres
  (lambda (r1 r2)
    (values
     (append (regla-antecedente r1) (list (regla-produccion r1)))
     (append (regla-antecedente r2) (list (regla-produccion r2)))
     )
    ))
;;MODULO CRUCE
    (define sublista
      (lambda (lista i j)
        (if (= i j)
            '()
            (cons
             (list-ref lista i)
             (sublista lista (add1 i) j)
             )
            )
        ))
    (define fragmentos_cromosoma
      (lambda (cromosoma lista_puntos_cruce n)
        (if (null? lista_puntos_cruce)
            (cons
             (sublista cromosoma n (length cromosoma))
             '())
            (cons
             (sublista cromosoma n (car lista_puntos_cruce))
             (fragmentos_cromosoma cromosoma (cdr lista_puntos_cruce) (car lista_puntos_cruce))
             )
            )
        ))
    (define cruce_aux
      (lambda (frag_1 frag_2)
        (let go ((i 0)
                 (j (length frag_1))
                 (salida '())
                 )
          (if (= i j)
              salida
              (go (add1 i) j 
                  (if (even? i)
                      (append salida (list-ref frag_1 i))
                      (append salida (list-ref frag_2 i))
                      ))
              )
          )
        ))
    ;;;CREAR NUEVA GENERACIÓN
    (define cruce
      (lambda (c1 c2 lista-puntos_cruce)
        (let* ((frag_c1 (fragmentos_cromosoma c1 lista-puntos_cruce 0))
               (frag_c2 (fragmentos_cromosoma c2 lista-puntos_cruce 0))
               (hijo1 (cruce_aux frag_c1 frag_c2))
               (hijo2 (cruce_aux frag_c2 frag_c1))
               (hacer-mutacion? (< (random 1000) 5))
               (ord-mutante1 (random 8))
               (ord-mutante2 (random 8))
               (par-mutante1 (list-ref hijo1 ord-mutante1))
               (par-mutante2 (list-ref hijo2 ord-mutante2))
               (par-mutado1 (mutando-gen par-mutante1))
               (par-mutado2 (mutando-gen par-mutante2))
               (hijo1-mutado
                (map
                 (lambda (par ord)
                   (if (= ord ord-mutante1)
                       par-mutado1
                       par)
                   )
                 hijo1 '(0 1 2 3 4 5 6 7 8))
                )
               (hijo2-mutado
                (map
                 (lambda (par ord)
                   (if (= ord ord-mutante2)
                       par-mutado2
                       par)
                   )
                 hijo2 '(0 1 2 3 4 5 6 7 8))
                )
               )
          (if hacer-mutacion?
              (list hijo1-mutado hijo2-mutado)
              (list hijo1 hijo2))       
;          (list
;           (cruce_aux frag_c1 frag_c2)
;           (cruce_aux frag_c2 frag_c1)
;           )
          )
        ))
    (define genera-hijos
      (lambda (lista-parejas)
        (if (null? lista-parejas)
            '()
            (let*-values 
                ([(pareja) (car lista-parejas)]
                 [(r1) (first pareja)]
                 [(r2) (second pareja)]
                 [(c1 c2) (son-padres r1 r2)]
                 )
              (append
               (cruce c1 c2 '(3 6))
               (genera-hijos (cdr lista-parejas)))
              )
            )
        ))
 
 (define nuevas-reglas
   (lambda (nueva-generacion base-cromosomas)
     (if (null? nueva-generacion)
         '()
         (if (member (car nueva-generacion) base-cromosomas)
             (nuevas-reglas (cdr nueva-generacion) base-cromosomas)
             (cons
              (make-regla 1 (take (car nueva-generacion) 8) (last (car nueva-generacion)) -1)
              (nuevas-reglas (cdr nueva-generacion) base-cromosomas))
             )
         )
     ))

 
 (define reemplazar
   (lambda (new-reglas bc)
     (let* ((long-new-reglas (length new-reglas))
           (permanecen (take bc (- (length bc) long-new-reglas)))
           (sustituidas (list-tail bc (- (length bc) long-new-reglas)))
           (reemplazo
            (map
             (lambda (sustituida new)
               (set-regla-id! new (regla-id sustituida))
               new)
             sustituidas new-reglas)
            )
           )
       (sort (append permanecen reemplazo) #:key regla-id >)
       )
     ))

 
 (define/public new-classifiers->BC
   (lambda (bc)
     (let* ((Base-cromosomas
             (map
              (lambda (reg)
                (append (regla-antecedente reg) (list (regla-produccion reg)))
                )
              bc))
            (mejores (take bc 288))
            (pob-pot-padres (metodo-goldberg-ruleta mejores))
            (parejas (empareja-dos-azar pob-pot-padres))
            (nueva-gen (genera-hijos parejas))
            (New (nuevas-reglas nueva-gen Base-cromosomas))
            (nueva-bc (reemplazar New bc))
            )
       (printf "~a~n" (length nueva-bc))
       nueva-bc
       )
     )
   )
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    (super-new)
    ))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define ag (make-object operaciones-ag%))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define generar_reglas%
  (class object%
    ;;Técnica para generar una regla
    (define genera-antecedente
      (lambda (out_receptor)
        out_receptor ))
    ;;;;;;;;;;;;;;
    (define genera-accion
      (lambda (list_ordinales)
        (first list_ordinales)
        ))
    ;;;;;;;;;;;;;;
    (define/public generar-regla
      (lambda (out_receptor N)
        (let* ((antecedente (genera-antecedente out_receptor))
               (accion 
                (genera-accion (list 0 1 2 3 4 5 6 7)))
;                 (if orden_vec (remove* orden_vec (list 0 1 2 3 4 5 6 7)) (list 0 1 2 3 4 5 6 7))))
               )
          (make-regla 1 antecedente accion N)
          )
        ))
    ;;;;;;;;;;;;;;
    (define/public modificar-accion
      (lambda (lista_ordinales lista-acciones_realizadas)
        (let ((proc (if (= (random 2) 0) first last)) )
          (first
           (remove* lista-acciones_realizadas
                    lista_ordinales))
          )
        ))
    ;;Técnica para generalizar una regla
    (define/public generalizar-regla
      (lambda (regla)
        (let ((antecedente (regla-antecedente regla))
              (accion (regla-produccion regla))
              )
          (map
           (lambda (par ord)
             (if (= ord accion)
                 par
                 (if (= (car par) 0)
                     (cons 0 #\#)
                     par)
                 )
             )
           antecedente '(0 1 2 3 4 5 6 7))
          )
        ))
    (super-new)
    ))
;;;;;;;
(define generar-reglas (make-object generar_reglas%))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define motor_inferencias%
  (class object%
    (field
     (M-set 'conjunto-reglas-activadas)
     )
    (define seleccion-de-M
      (lambda (output_receptor BC)
        (cond
          ((null? BC) '())
          ((match (regla-antecedente (first BC)) output_receptor)
           (cons
            (first BC)
            (seleccion-de-M output_receptor (rest BC))) )
          (else
           (seleccion-de-M output_receptor (rest BC)))
          )
        ))
    (define match-par?
      (lambda (par1 par2);antecedente-regla output_receptor
        (and
         (equal? (car par1) (car par2))
         (or
          (char? (cdr par1))
          (equal? (cdr par1) (cdr par2))
          ))
        ))
    (define match
      (lambda (lista1 lista2);antecedente-regla output_receptor
        (let go ((i 0)
                 (j (length lista1))
                 )
          (if (= i j)
              #t
              (if (match-par? (list-ref lista1 i) (list-ref lista2 i))
                  (go (add1 i) j)
                  #f)
              )
          )
        ))
    (define/public proceso!
      (lambda (out_receptor bc)
        (set! M-set
              (seleccion-de-M out_receptor bc))
        M-set
        ))
    (super-new)
    ))
;;;;;;
(define motor_inferencial (make-object motor_inferencias%))
;;;;;;;;;;;;;;;;;;;;;
(define probabilidad_reglas%
  (class object%
    (field
     )
    (define sumatorio-fuerzas
      (lambda (set-M)
        (if (null? set-M)
            0
            (+
             (regla-fuerza (first set-M))
             (sumatorio-fuerzas (rest set-M)))
            )
        ))
    (define probabilidad-uno
      (lambda (fuerza-uno sumatorio_fuerzas)
        (/ fuerza-uno sumatorio_fuerzas)
        ))
    (define lista-ordinales
      (lambda (M_set n)
        (if (null? M_set)
            '()
            (cons
             n
             (lista-ordinales (rest M_set) (add1 n)))
            )
        ))
    (define/public proceso!
      (lambda (set_M)
        (let* ((sumatorio (sumatorio-fuerzas set_M))
               (set-M-ordenado
                (sort    
                 (map
                  (lambda (una-r ordinal)
                    (cons
                     (probabilidad-uno (regla-fuerza una-r) sumatorio)
                     ordinal)
                    )
                  set_M (lista-ordinales set_M 0))
                 #:key car >));#:key car <
               (rule_order (cdr (first set-M-ordenado)))
               (regla_mas_probable (list-ref set_M rule_order))
               ;;;
               (regla_mayor_exito
                (ormap
                 (lambda (r)
                   (let* ((accion (regla-produccion r))
                          (par_de_accion (list-ref (regla-antecedente r) accion))
                          )
                     (if (equal? par_de_accion (cons 1 1))
                         r
                         #f)
                     )
                   )
                 set_M) )
               )
          regla_mas_probable
;          (if regla_mayor_exito
;              regla_mayor_exito
;              regla_mas_probable)
          )
        ))
    (super-new)
    ))
;;;;;;;;
(define regla-mas-probable (make-object probabilidad_reglas%))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define procesar-recompensa%
  (class object%
    (define/public procesar-recompensa!
      (lambda (secuencia-actos)
        (difundir-recompensa-secuencia secuencia-actos 1)
        ))
    (define difundir-recompensa-secuencia
      (lambda (secuencia p)
        (cond
          ((null? secuencia) #t)
          (else
           (set! p
                 (refuerzo-un-acto (car secuencia) p))
           (difundir-recompensa-secuencia (cdr secuencia) p)
           )
          )
        ))
    (define refuerzo-un-acto
      (lambda (elemento-secuencia P)
        (let ((A-set (third elemento-secuencia))
              (next-p 0)
              )
          (letrec ((aux
                    (lambda (set-A p)
                      (if (null? set-A)
                          '()
                          (let ((fraccion_restada (reajuste-fuerza-por-recompensa (car set-A) 0.10 p (length A-set))))
                            (set! next-p (+ next-p fraccion_restada))
                            (cons
                             (car set-A)
                             (aux (cdr set-A) p)
                             )
                            )
                          )
                      ))
                   )
            (aux A-set P)
            next-p
            )
          )
        ))
    (define reajuste-fuerza-por-recompensa
      (lambda (regla epsilon p length-A-set)
        (let* ((fuerza_r (regla-fuerza regla))
               (recompensa (/ p length-A-set))
               (fraccion-restada (* epsilon fuerza_r))
               )
          (set-regla-fuerza!
           regla
           (+
            fuerza_r
            recompensa
            (- fraccion-restada)
            )
           )
          fraccion-restada
          )
        ))
    (super-new)
    ))
;;;;;;;
(define calculos-recompensa (make-object procesar-recompensa%))
;;;;;;;;;;;;;;;;;;;;;
(define control_central%
  (class object%
    ;;init-field: los subsistemas
    (init-field
     (Generador-reglas 'generar-reglas)
     (Interprete-reglas 'motor_inferencial)
     (Probabilidad-reglas 'regla-mas-probable)
     (Calcular-recompensa 'calculos-recompensa)
     (Operador-genetico 'ag)
     (BC_length 0)
     )
    ;;field: propiedades estructurales
    (field
     (BC '())
     (M_set 'conjunto-de-reglas-activadas)
     (exito 0)
     (last-rule #f)
     (last-action '())
     ;;;
     (historia '())
     (Secuencia-actos '())
     (A_set '())
     (accion #f)
     ;;;
     (numero-recompensas 0)
     (la_peor #f)
     (h-recompensas '())
     (AG-activado #f)
     )
    ;;;;;;;;;;;;;;;;;;;;
    (define/public set-BC
      (lambda (n)
        (set! BC
              (send Operador-genetico make-BC n))
        ))
    (define/public get-h-recompensas
      (lambda ()
        h-recompensas))
    ;;;;;;;;;;;;;;;;;;;;
    (define sustituir-regla
      (lambda (BC new-last-rule)
        (let ((V (list->vector BC))
              )
          (vector-set! V (regla-id new-last-rule) new-last-rule)
          (set! BC
                (vector->list V))
          )
        BC
        ))
    (define borrar-la-peor
      (lambda (R-peor)
        (set! BC
              (filter-map
               (lambda (r)
                 (if (= (regla-id r) (regla-id R-peor))
                     #f
                     r)
                 )
               BC)
              )
        ))
    (define regla-peor
      (lambda (BC clase)
        (let ((clase-peor 
               (ormap
                (lambda (c)
                  (cond
                    ((null? c) #f)
                    ((= (regla-produccion (first c)) clase) c)
                    (else #f)
                    )
                  )
                BC)
               )
              )
          (if clase-peor
              (last clase-peor)
              (last (get_bc))
              )
          )
        ))
    (define set-fuerza
      (lambda (regla BC)
        (ormap
         (lambda (r)
           (if
            (and
             (equal?  (regla-antecedente regla) (regla-antecedente r))
             (equal? (regla-produccion regla) (regla-produccion r))
             )
            (regla-fuerza r)
            #f)
           )
         BC)
        ))
    ;;;;;;;;;;;;;;;;;;;;
    (define set-secuencia_actos
      (lambda ()
        (set! Secuencia-actos (cons (list accion last-rule A_set) Secuencia-actos))
        ))
    (define inicializa-secuencia_actos
      (lambda ()
        (set! Secuencia-actos '())
        ))
    (define generalizada?
      (lambda (antecedente)
        (ormap
         (lambda (par)
           (char? (cdr par))
           )
         antecedente)
        ))
;;;;;;;;;;;;;;;;;;;;;;;;;
    (define M-set->A-set
      (lambda (M-set rule)
        (cond 
          ((null? M-set) '())
          ((= (length M-set) 1) M-set)
          ((= (regla-produccion rule) (regla-produccion (car M-set)))
           (cons (car M-set)
                 (M-set->A-set (cdr M-set) rule)) )
          (else
           (M-set->A-set (cdr M-set) rule))
          )
        ))
;;;;;;;;;;;;;;;;;;;;;;;;;
    (define/public get_bc
      (lambda ()
        (sort BC #:key regla-fuerza >) ))
    (define/public get-bc
      (lambda ()
        (map
         (lambda (o)
           (sort
           (filter-map
            (lambda (r)
              (if (= (regla-produccion r) o)
                  r
                  #f))
            BC) 
           #:key regla-fuerza >))
         '(0 1 2 3 4 5 6 7))
        ))    
    ;;;;;;;;;;;;;;;;;;;;
    (define/public set-exito
      (lambda (valor num_iter)
        (set! exito valor)
        (printf "***Proceso de refuerzo***~n")
        (printf "La acción realizada ha tenido ~a~n" (if (< exito 0) "fracaso" (if (= exito 0) "éxito" "recompensa")))
        (cond
          ((negative? exito)
           (printf "Secuencia actos: ~a~nRegla: ~a~n" (length Secuencia-actos) last-rule)
           (set-regla-produccion! last-rule
                                  (send Generador-reglas modificar-accion (list 0 1 2 3 4 5 6 7) last-action) )
           (sustituir-regla BC last-rule)
           (printf "Regla modificada: ~a~n" last-rule) 
           )
          
          ((zero? exito)
           (set-secuencia_actos)
           (printf "Secuencia actos: ~a~n regla: ~a~n" (length Secuencia-actos) last-rule)
           (unless (generalizada? (regla-antecedente last-rule))
             (printf "Se generaliza el antecedente de la regla~a~n" last-rule)
             (set-regla-antecedente! last-rule
                                     (send Generador-reglas generalizar-regla last-rule))
             (printf "Regla modificada: ~a~n" last-rule)
;             (printf "Id-last_rule ~a~n" (regla-id last-rule))
;             (printf "Id-peor ~a~n" (regla-id la_peor))
;             (printf "Tamaño BC: ~a ~n" (length BC))
             (if (= BC_length (length BC))
                 (sustituir-regla BC last-rule)
                 (begin
                   (borrar-la-peor la_peor)
                   (set-regla-id! last-rule (regla-id la_peor))
                   (sustituir-regla BC last-rule)
                   )
;             (printf "Id-last_rule ~a~n" (regla-id last-rule))
;             (printf "Tamaño BC: ~a ~n" (length BC))
             )
;             (printf "Tamaño BC: ~a ~n" (length BC))
             )
           )
          
          ((= exito 1)
           (set! numero-recompensas (add1 numero-recompensas))
           (set-secuencia_actos)
           (printf "Secuencia actos: ~a~n regla: ~a~n" (length Secuencia-actos) last-rule)
           (unless (generalizada? (regla-antecedente last-rule))
             (printf "Se generaliza el antecedente de la regla~a~n" last-rule)
             (set-regla-antecedente! last-rule
                                     (send Generador-reglas generalizar-regla last-rule))
             (printf "Regla modificada: ~a~n" last-rule)
             
;             (printf "Id-last_rule ~a~n" (regla-id last-rule))
;             (printf "Id-peor ~a~n" (regla-id la_peor))
;             (printf "Tamaño BC: ~a ~n" (length BC))
             (borrar-la-peor la_peor)
             (set-regla-id! last-rule (regla-id la_peor))
;             (printf "Id-last_rule ~a~n" (regla-id last-rule))
;             (printf "Tamaño BC: ~a ~n" (length BC))
             (sustituir-regla BC last-rule)
;             (printf "Tamaño BC: ~a ~n" (length BC))
             
             ) 
           (send Calcular-recompensa procesar-recompensa! Secuencia-actos)
           (inicializa-secuencia_actos)
           )
          )
        (printf "***Fin del proceso de refuerzo***~n")
        ))
    ;;;;;;;;;;;;;;;;;;;;
    (define/public proceso!
      (lambda (output_receptor iter)
        (printf "***Proceso del cerebro***~n")
        (cond
          ((and 
            (or (>= numero-recompensas 5) (= iter 50))
                (not AG-activado))
           (set! AG-activado #t) )
          (AG-activado
           (set! BC (send Operador-genetico new-classifiers->BC BC))    
           (printf "Proceso del AG acabado~n")
           )
          )
;        (when (>= numero-recompensas 5) 
;          (set! BC (send Operador-genetico new-classifiers->BC BC))    
;          (printf "Proceso del AG acabado~n")
;          )
        (printf "Estímulo: ~a~n" output_receptor)
        (printf "Tamaño BC: ~a ~n" (length BC))
        (set! M_set (send Interprete-reglas proceso! output_receptor BC))
        (printf "M-Set ~a~n" (length M_set))
        (cond
          ;;M-set está vacío. Se necesita una nueva regla
          ((null? M_set)
           (set! last-rule (send Generador-reglas generar-regla output_receptor (length BC)))
           (set! accion (regla-produccion last-rule))
           (set! last-action (cons accion '()))
           (printf "Regla generada: ~a~n" last-rule)

           ;(read-char)
           (set! la_peor (regla-peor (get-bc) accion))
           ;(set! la_peor (if la_peor la_peor (last (get_bc))))
           
           (set! BC (cons last-rule BC)) 
           (set! M_set (cons last-rule M_set))
           )
          ;;M-set no está vacío
          (else
           
           (set! last-rule (send Probabilidad-reglas proceso! M_set))
           (set! accion (regla-produccion last-rule))
           (set! last-action (cons accion last-action))
           (printf "Regla de mayor probabilidad: ~a~n" last-rule)
           )
          )
        (set! A_set (M-set->A-set M_set last-rule))
        (printf "***Fin proceso del cerebro***~n")
        (values accion)
        ))
    (super-new)
    ))
;;;;;;;;;;;
(define cerebro (make-object control_central% generar-reglas motor_inferencial regla-mas-probable calculos-recompensa ag 480))
                  
(send cerebro set-BC 480)

(provide cerebro)

