]> git.llucax.com Git - z.facultad/75.68/celdas.git/blobdiff - trunk/src/sistemaautonomo.cpp
Últimos cambios y documentación.
[z.facultad/75.68/celdas.git] / trunk / src / sistemaautonomo.cpp
index 5f1cf2c7b12b221b89cecaf6b5b185bfd4a1c0f6..695e5381e5518c5967ba3a83f62f53ca96422e0c 100644 (file)
@@ -1,5 +1,10 @@
 
 #include "sistemaautonomo.h"
+#include <sstream>
+
+#ifdef DEBUG
+#include <iostream>
+#endif // DEBUG
 
 
 //--------------------------------------------------------------------------------------------
@@ -20,6 +25,129 @@ bool incluye_a (CIndiceMagico<t_dato>& a, CIndiceMagico<t_dato>& b)
        return result ;
 }
 
+//--------------------------------------------------------------------------------------------
+//--
+void CSistemaAutonomo::plan()
+{
+       double p = 1.0;
+       m_plan.clear();
+       if (teorias.count() > max_teorias) purgar_teorias();
+#ifdef DEBUG
+       std::cout << "SA: Planificando...\n";
+       std::cout << "SA: \tentorno:\n" << p_entorno->datos << "\n";
+       std::cout << "SA: \tteorias:\n" << teorias << "\n";
+#endif // DEBUG
+#ifdef LOG
+       std::cout << "Planificando...\n";
+       std::cout << "Entorno:\n" << p_entorno->datos << "\n";
+       std::cout << "Teorias:\n" << teorias << "\n";
+#endif // LOG
+       planificar(p_entorno->datos, m_datos_finales, m_plan, p);
+#ifdef DEBUG
+       std::cout << "SA: \tplan:\n" << m_plan << "\n";
+#endif // DEBUG
+#ifdef LOG
+       std::cout << "Plan:\n" << m_plan << "\n";
+#endif // LOG
+       curr_theory = m_plan.begin();
+#ifdef DEBUG
+       if (curr_theory == m_plan.end())
+               std::cout << "SA: No hay teorías\n";
+       else
+               std::cout << "SA: curr teoria: " << **curr_theory << "\n";
+#endif // DEBUG
+}
+
+//--------------------------------------------------------------------------------------------
+//--
+bool CSistemaAutonomo::has_next_theory()
+{
+       return curr_theory != m_plan.end();
+}
+
+//--------------------------------------------------------------------------------------------
+//--
+CTeoria* CSistemaAutonomo::get_next_theory()
+{
+       if (curr_theory == m_plan.end())
+       {
+               m_datos_finales.clear();
+               return 0;
+       }
+       else
+       {
+#ifdef DEBUG
+               std::cout << "SA: ejecuta teoria: " << **(curr_theory) << "\n";
+#endif // DEBUG
+#ifdef LOG
+               std::cout << "Ejecutando teoria:\n" << **(curr_theory) << "\n";
+#endif // LOG
+               return *(curr_theory++);
+       }
+}
+
+//--------------------------------------------------------------------------------------------
+//--
+bool CSistemaAutonomo::validate_theory(CTeoria* t)
+{
+       bool result ;
+
+       // Aumento k (cantidad de veces que se probó la teoría
+       ++t->k;
+
+#ifdef DEBUG
+       std::cout << "SA: Entorno de verificacion:\n" << p_entorno->datos;
+#endif // DEBUG
+
+#ifdef LOG
+       std::cout << "Verificacion...\n";
+       std::cout << "Entorno:\n" << p_entorno->datos << "\n";
+#endif // LOG
+
+       // Verifico
+       result = verificar_condicion(t->datos_finales) ;
+
+       // Si se ejecuto bien la teoria incremento el p
+       if (result) t->p++ ;
+
+       // Si fallo la teoria
+       if (!result)
+       {
+               // Aplico heuristicas de observacion
+#ifdef DEBUG
+               std::cout << "SA: No verifica, aplicando heuristicas...\n";
+               std::cout << "SA: Aplicando heuristica de observacion\n";
+#endif // DEBUG
+#ifdef LOG
+               std::cout << "No verifica, aplicando heuristicas...\n";
+               std::cout << "Aplicando heuristica de observacion:\n";
+#endif // LOG
+               this->heuristca_observacion(*t) ;
+#ifdef DEBUG
+               std::cout << "SA: Aplicando heuristica de generalizacion\n";
+#endif // DEBUG
+#ifdef LOG
+               std::cout << "Aplicando heuristica de generalizacion:\n";
+#endif // LOG
+               //this->heuristca_generalizacion(*t);
+#ifdef DEBUG
+               std::cout << "SA: Aplicando heuristica de retraccion\n";
+#endif // DEBUG
+#ifdef LOG
+               std::cout << "Aplicando heuristica de retraccion:\n";
+#endif // LOG
+               // Aplico heuristicas de correccion
+               this->heuristca_retraccion(*t) ;
+       }
+#ifdef DEBUG
+       else std::cout << "SA: Verifica!\n";
+#endif // DEBUG
+#ifdef LOG
+       else std::cout << "Verifica!\n";
+#endif // LOG
+
+       return result;
+}
 
 
 //--------------------------------------------------------------------------------------------
@@ -29,90 +157,184 @@ bool CSistemaAutonomo::verificar_condicion(CIndiceMagico<t_dato>& datos)
        bool result = true ;
        unsigned i ;
 
+       for (i = 0; i < datos.count() && result; i++)
+               result = (datos[i] == ANY || datos[i] == this->p_entorno->datos.find(datos.keys(i)));
 
-       for (i=0; i<datos.count() && result; i++)
-               result = datos[i] == ANY || datos[i] == this->p_entorno->datos.find(datos.keys(i))  ;
-
-
-       //
        return result ;
 }
 
-
+std::string make_nombre(const std::string& n, char mod, unsigned i)
+{
+       std::ostringstream oss;
+       oss << n << "-" << mod << i;
+       return oss.str();
+}
 
 //--------------------------------------------------------------------------------------------
 //--
-void CSistemaAutonomo::heurisitca_observacion(CTeoria& t)
+void CSistemaAutonomo::heuristca_observacion(CTeoria& t)
 {
-       CTeoria nt ; //Nueva Teoria
-       unsigned i ;
-       std::string nombre ;
-       
+       CTeoria* pnt = new CTeoria ; //Nueva Teoria
+       CTeoria& nt = *pnt;
+
        // Le agrego los datos iniciales tal cual estaban antes
-       for (i=0; i<t.datos_iniciales.count(); i++)
-               nt.datos_iniciales.add(t.datos_iniciales.keys(i), t.datos_iniciales[i]) ;
+       nt.datos_iniciales = t.datos_iniciales;
 
        // Le agrego todas las condiciones del entorno como condicion final
-       for (i=0; i<this->p_entorno->datos.count(); i++)
-               nt.datos_finales.add(this->p_entorno->datos.keys(i), this->p_entorno->datos[i]) ;
+       nt.datos_finales = p_entorno->datos;
 
+       // Le cargo nombre y funcion (queda con k=1 y p=1)
+       nt.nombre = make_nombre(t.nombre, 'o', teorias.count());
+       nt.funcion = t.funcion;
 
        // Agrego la teoria
-       nombre = teorias.count() ;
-       teorias.add (nombre.c_str(), nt) ;
-       
+       teorias.add (nt.nombre, pnt) ;
+#ifdef DEBUG
+       std::cout << "SA: Se agrego una nueva teoria: " << nt << " basada en " << t << "\n";
+       std::cout << "SA: \tdatos_iniciales:\n" << nt.datos_iniciales << "\n";
+       std::cout << "SA: \tdatos_finales:\n" << nt.datos_finales << "\n";
+#endif // DEBUG
+#ifdef LOG
+       std::cout << "Agrega teoria: " << nt << "," << nt.datos_iniciales << "," << nt.datos_finales << "\n";
+#endif // LOG
+
 }
 
+//--------------------------------------------------------------------------------------------
+//--
+// Si las condiciones finales del entorno son iguales a las condiciones finales de alguna teoria y
+// solo una condicion inicial es distinta => agrego una nueva teoría igual (a la q cumple los requisitos
+// anteriormente detallados) pero tomando ANY en el valor de entrada en el cual difieren.  
+void CSistemaAutonomo::heuristca_generalizacion(CTeoria& t)
+{
+       unsigned i ;
+       int count = 0;
+       unsigned k = 0;
+       unsigned j = 0;
+       int posicionCambio = -1;
+       unsigned cantidadTeorias = 0;
+       std::string nombreTeoria;
+
+       cantidadTeorias = this->teorias.count();
+
+       for (i = 0; i < cantidadTeorias; i++)
+       {
+               for (k = 0; k < this->teorias[i]->datos_finales.count(); k++)
+               {
+                       //me fijo si las condiciones finales de la teoria se corresponden con la del entorno.
+                       if ((this->teorias[i]->datos_finales[k] != ANY) && (this->p_entorno->datos.find(t.datos_finales.keys(k)) != ANY))
+                       {
+                               if (this->teorias[i]->datos_finales[k] != this->p_entorno->datos.find(t.datos_finales.keys(k))) 
+                               {
+                                       count++;
+                               }
+                       }
+               }
+               if (count == 0)
+               {       // si se corresponden (las condiciones finales son iguales) => me fijo si hay alguna condicion inicial q cambia. 
+                       for (j = 0; j < this->teorias[i]->datos_iniciales.count(); j++)
+                       {
+                               if ((this->teorias[i]->datos_iniciales[j] != ANY) && (this->p_entorno->datos.find(t.datos_iniciales.keys(j)) != ANY))
+                               {
+                                       if (this->teorias[i]->datos_iniciales[j] != this->p_entorno->datos.find(t.datos_iniciales.keys(j))) 
+                                       {
+                                               posicionCambio = j;
+                                               count++;
+                                       }
+                               }
+                       }
+                       if (count == 1)
+                       {
+                               //si cambia solo una => creo una nueva teoria igual pero con ANY en la condicion q cambia.
+                               CTeoria* nt = new CTeoria ; //Nueva Teoria
+                               *nt = *this->teorias[i];
+                               nt->datos_iniciales[posicionCambio] = ANY;
+
+                               // Agrego la teoria
+                               nt->nombre = make_nombre(t.nombre, 'g', teorias.count());
+                               teorias.add (nt->nombre, nt) ;
+#ifdef DEBUG
+                               std::cout << "SA: Se agrego una nueva teoria: " << *nt << " basada en " << *teorias[i] << "\n";
+                               std::cout << "SA: \tdatos_iniciales:\n" << nt->datos_iniciales << "\n";
+                               std::cout << "SA: \tdatos_finales:\n" << nt->datos_finales << "\n";
+#endif // DEBUG
+#ifdef LOG
+                               std::cout << "Agrega teoria: " << *nt << "," << nt->datos_iniciales << "," << nt->datos_finales << "\n";
+#endif // LOG
+                       }
+               }
+               posicionCambio = -1;
+               count = 0;
+       }
+}
 
 //--------------------------------------------------------------------------------------------
 //--
-void CSistemaAutonomo::heurisitca_retraccion(CTeoria& t)
+void CSistemaAutonomo::heuristca_retraccion(CTeoria& t)
 {
-       CTeoria nt ; //Nueva Teoria
        unsigned i ;
+       unsigned modif = (unsigned)-1;
 
        // Recorro la condicion final de la teoria
-       for (i=0; i<t.datos_finales.count(); i++)
+       for (i = 0; i < t.datos_finales.count(); i++)
+       {
                // Si el dato no coincidio con el del entorno, y no era ANY
                if (t.datos_finales[i] != ANY && 
-                       t.datos_finales[i] != this->p_entorno->datos.find(t.datos_finales.keys(i))
-                  )
+                               t.datos_finales[i] != this->p_entorno->datos.find(t.datos_finales.keys(i)))
+               {
                        // Le asigno ANY
                        t.datos_finales[i] = ANY ;
+                       modif = i;
+               }
+       }
+       if (modif != (unsigned)-1)
+       {
+               // Le cambio el nombre para indicar que fue modificada
+               t.nombre += "-r";       
+#ifdef DEBUG
+               std::cout << "SA: Se modifica la teoria: " << t << ", el dato final '"
+                       << t.datos_finales.keys(modif) << "' puede tomar ahora cualquier valor\n";
+#endif // DEBUG
+#ifdef LOG
+               std::cout << "Se modifica teoria:\n" << t << "\nEl dato final '"
+                       << t.datos_finales.keys(modif) << "' puede tomar ahora cualquier valor\n";
+               std::cout << "Agrega teoria: " << t << "," << t.datos_iniciales << "," << t.datos_finales << "\n";
+#endif // LOG
+       }
 }
 
 
 //--------------------------------------------------------------------------------------------
 //--
-void CSistemaAutonomo::planificar (    CIndiceMagico<t_dato>&  datos_iniciales,
-                                                                       CIndiceMagico<t_dato>&  datos_finales,
-                                                                       CIndiceMagico<CTeoria>& plan,
-                                                                       double&                                 p,
-                                                                       unsigned long                   numero_de_llamada)
+void CSistemaAutonomo::planificar (CIndiceMagico<t_dato>&      datos_iniciales,
+                               CIndiceMagico<t_dato>&          datos_finales,
+                               CIndiceMagico<CTeoria*>&        plan,
+                               double&                         p,
+                               unsigned long                   numero_de_llamada)
 {
        unsigned i;
-       CIndiceMagico<CTeoria> test_plan ;
-       CIndiceMagico<CTeoria> new_plan ;
+       CIndiceMagico<CTeoria*> test_plan ;
+       CIndiceMagico<CTeoria*> new_plan ;
        double test_p ;
        double max_p = 0 ;
 
 
        if ( incluye_a(datos_iniciales, datos_finales) ) return ;
 
-       if ( numero_de_llamada > 7 ) return ;
+       if (numero_de_llamada > max_pasos) return ;
 
-       for (i=0; i<teorias.count(); i++)
-               if ( incluye_a(teorias[i].datos_iniciales, datos_iniciales) )
+       for (i = 0; i < teorias.count(); i++)
+               if ( incluye_a(teorias[i]->datos_iniciales, datos_iniciales) )
                {
                        test_plan.clear() ;
-                       test_plan.add (teorias[i].nombre.c_str(), teorias[i]) ;
+                       test_plan.add (teorias[i]->nombre, teorias[i]) ;
 
-                       test_p = p * ((double)teorias[i].p)/((double)teorias[i].k) ;
+                       test_p = p * ((double)teorias[i]->p)/((double)teorias[i]->k) ;
+
+                       planificar(teorias[i]->datos_finales, datos_finales, test_plan, test_p, numero_de_llamada+1) ; 
 
-                       planificar(teorias[i].datos_finales, datos_finales, test_plan, test_p, numero_de_llamada+1) ; 
-                       
                        if ( test_p>max_p )
-                       if ( incluye_a(test_plan[test_plan.count()-1].datos_finales, datos_finales) )
+                       if ( incluye_a(test_plan[test_plan.count()-1]->datos_finales, datos_finales) )
                        {
                                max_p = test_p ;
                                new_plan.clear() ;
@@ -124,50 +346,27 @@ void CSistemaAutonomo::planificar (       CIndiceMagico<t_dato>&  datos_iniciales,
                plan.add (new_plan) ;
 }
 
-
-
-//--------------------------------------------------------------------------------------------
-//--
-bool CSistemaAutonomo::ejecutar (CIndiceMagico<CTeoria>& plan)
+void CSistemaAutonomo::purgar_teorias()
 {
-       bool result = true ;
-       unsigned i ;
-       t_fnc(pFnc) ;
-       CTeoria t ;     
-
-
-       for (i=0; i<plan.count() && result; i++)
+       unsigned size = teorias.count();
+       unsigned pos = size - 1;
+       double whorst_prob = 1.0;
+       for (unsigned i = 0; i < size; ++i)
        {
-               t = plan[i] ;
-               pFnc = t.funcion;
-
-               // Ejecuto la funcion
-               (*pFnc)(*(this->p_entorno)) ;
-
-               // Incremento el K
-               t.k++ ;
-
-               // Actualizo los datos del entorno
-               this->p_entorno->actualizar() ;
-
-               // Veo si se verifica la condicion final
-               result = this->verificar_condicion(t.datos_finales) ;
-
-               // Si fallo la teoria
-               if (!result)
+               double p = (double)teorias[i]->p / (double)teorias[i]->k;
+               if (p < whorst_prob)
                {
-                       // Aplico heuristicas de correccion
-                       this->heurisitca_retraccion(t) ;
+                       whorst_prob = p;
+                       pos = i;
                }
-               else
-               {
-                       t.p++ ;
-               }
-
-               // Aplico heuristicas de observacion
-               this->heurisitca_observacion(t) ;
        }
-
-       //
-       return result ;
+       teorias.remove(pos);
+#ifdef DEBUG
+       std::cout << "SA: Se purgo la teoria " << *teorias[pos] << "\n";
+#endif // DEBUG
+#ifdef LOG
+       std::cout << "Se purgo la teoria:\n" << *teorias[pos] << "\n";
+#endif // LOG
+       if (size - 1 > max_teorias) purgar_teorias();
 }
+