]> git.llucax.com Git - z.facultad/75.68/celdas.git/blob - trunk/src/sistemaautonomo.cpp
Agrega un modo de salida intentando que sea más fácil generar tablas con la evolución...
[z.facultad/75.68/celdas.git] / trunk / src / sistemaautonomo.cpp
1
2 #include "sistemaautonomo.h"
3 #include <sstream>
4
5 #ifdef DEBUG
6 #include <iostream>
7 #endif // DEBUG
8
9
10 //--------------------------------------------------------------------------------------------
11 //-- Funciones Auxiliares
12 bool incluye_a (CIndiceMagico<t_dato>& a, CIndiceMagico<t_dato>& b) 
13 {
14         bool result = true ;
15         unsigned i ;
16
17         // Todas las variables de la condicion b deben estar en la condicion a
18         for (i=0; i<b.count() && result; i++)
19                 result=a.exist(b.keys(i)) ;
20
21         // Todas las variables de la condicion a deben tener el mismo valor que en la condicion b
22         for (i=0; i<b.count() && result; i++)
23                 result = b[i] == a.find(b.keys(i)) || b[i] == ANY || a.find(b.keys(i)) == ANY  ;
24         //
25         return result ;
26 }
27
28 //--------------------------------------------------------------------------------------------
29 //--
30 void CSistemaAutonomo::plan()
31 {
32         double p = 1.0;
33         m_plan.clear();
34         if (teorias.count() > max_teorias) purgar_teorias();
35 #ifdef DEBUG
36         std::cout << "SA: Planificando...\n";
37         std::cout << "SA: \tentorno:\n" << p_entorno->datos << "\n";
38         std::cout << "SA: \tteorias:\n" << teorias << "\n";
39 #endif // DEBUG
40 #ifdef LOG
41         std::cout << "Planificando...\n";
42         std::cout << "Entorno:\n" << p_entorno->datos << "\n";
43         std::cout << "Teorias:\n" << teorias << "\n";
44 #endif // LOG
45         planificar(p_entorno->datos, m_datos_finales, m_plan, p);
46 #ifdef DEBUG
47         std::cout << "SA: \tplan:\n" << m_plan << "\n";
48 #endif // DEBUG
49 #ifdef LOG
50         std::cout << "Plan:\n" << m_plan << "\n";
51 #endif // LOG
52         curr_theory = m_plan.begin();
53 #ifdef DEBUG
54         if (curr_theory == m_plan.end())
55                 std::cout << "SA: No hay teorías\n";
56         else
57                 std::cout << "SA: curr teoria: " << **curr_theory << "\n";
58 #endif // DEBUG
59 }
60
61 //--------------------------------------------------------------------------------------------
62 //--
63 bool CSistemaAutonomo::has_next_theory()
64 {
65         return curr_theory != m_plan.end();
66 }
67
68 //--------------------------------------------------------------------------------------------
69 //--
70 CTeoria* CSistemaAutonomo::get_next_theory()
71 {
72         if (curr_theory == m_plan.end())
73         {
74                 m_datos_finales.clear();
75                 return 0;
76         }
77         else
78         {
79 #ifdef DEBUG
80                 std::cout << "SA: ejecuta teoria: " << **(curr_theory) << "\n";
81 #endif // DEBUG
82 #ifdef LOG
83                 std::cout << "Ejecutando teoria:\n" << **(curr_theory) << "\n";
84 #endif // LOG
85                 return *(curr_theory++);
86         }
87 }
88
89 //--------------------------------------------------------------------------------------------
90 //--
91 bool CSistemaAutonomo::validate_theory(CTeoria* t)
92 {
93         bool result ;
94
95         // Aumento k (cantidad de veces que se probó la teoría
96         ++t->k;
97
98 #ifdef DEBUG
99         std::cout << "SA: Entorno de verificacion:\n" << p_entorno->datos;
100 #endif // DEBUG
101
102 #ifdef LOG
103         std::cout << "Verificacion...\n";
104         std::cout << "Entorno:\n" << p_entorno->datos << "\n";
105 #endif // LOG
106
107         // Verifico
108         result = verificar_condicion(t->datos_finales) ;
109
110         // Si se ejecuto bien la teoria incremento el p
111         if (result) t->p++ ;
112
113         // Si fallo la teoria
114         if (!result)
115         {
116                 // Aplico heuristicas de observacion
117 #ifdef DEBUG
118                 std::cout << "SA: No verifica, aplicando heuristicas...\n";
119                 std::cout << "SA: Aplicando heuristica de observacion\n";
120 #endif // DEBUG
121 #ifdef LOG
122                 std::cout << "No verifica, aplicando heuristicas...\n";
123                 std::cout << "Aplicando heuristica de observacion:\n";
124 #endif // LOG
125                 this->heuristca_observacion(*t) ;
126 #ifdef DEBUG
127                 std::cout << "SA: Aplicando heuristica de generalizacion\n";
128 #endif // DEBUG
129 #ifdef LOG
130                 std::cout << "Aplicando heuristica de generalizacion:\n";
131 #endif // LOG
132                 this->heuristca_generalizacion(*t);
133 #ifdef DEBUG
134                 std::cout << "SA: Aplicando heuristica de retraccion\n";
135 #endif // DEBUG
136 #ifdef LOG
137                 std::cout << "Aplicando heuristica de retraccion:\n";
138 #endif // LOG
139                 // Aplico heuristicas de correccion
140                 this->heuristca_retraccion(*t) ;
141         }
142 #ifdef DEBUG
143         else std::cout << "SA: Verifica!\n";
144 #endif // DEBUG
145 #ifdef LOG
146         else std::cout << "Verifica!\n";
147 #endif // LOG
148
149         return result;
150 }
151
152
153 //--------------------------------------------------------------------------------------------
154 //--
155 bool CSistemaAutonomo::verificar_condicion(CIndiceMagico<t_dato>&       datos)
156 {
157         bool result = true ;
158         unsigned i ;
159
160         for (i = 0; i < datos.count() && result; i++)
161                 result = (datos[i] == ANY || datos[i] == this->p_entorno->datos.find(datos.keys(i)));
162
163         return result ;
164 }
165
166 std::string make_nombre(const std::string& n, char mod, unsigned i)
167 {
168         std::ostringstream oss;
169         oss << n << "-" << mod << i;
170         return oss.str();
171 }
172
173 //--------------------------------------------------------------------------------------------
174 //--
175 void CSistemaAutonomo::heuristca_observacion(CTeoria& t)
176 {
177         CTeoria* pnt = new CTeoria ; //Nueva Teoria
178         CTeoria& nt = *pnt;
179
180         // Le agrego los datos iniciales tal cual estaban antes
181         nt.datos_iniciales = t.datos_iniciales;
182
183         // Le agrego todas las condiciones del entorno como condicion final
184         nt.datos_finales = p_entorno->datos;
185
186         // Le cargo nombre y funcion (queda con k=1 y p=1)
187         nt.nombre = make_nombre(t.nombre, 'o', teorias.count());
188         nt.funcion = t.funcion;
189
190         // Agrego la teoria
191         teorias.add (nt.nombre, pnt) ;
192 #ifdef DEBUG
193         std::cout << "SA: Se agrego una nueva teoria: " << nt << " basada en " << t << "\n";
194         std::cout << "SA: \tdatos_iniciales:\n" << nt.datos_iniciales << "\n";
195         std::cout << "SA: \tdatos_finales:\n" << nt.datos_finales << "\n";
196 #endif // DEBUG
197 #ifdef LOG
198         std::cout << "Agrega teoria: " << nt << "," << nt.datos_iniciales << "," << nt.datos_finales << "\n";
199 #endif // LOG
200
201 }
202
203 //--------------------------------------------------------------------------------------------
204 //--
205 // Si las condiciones finales del entorno son iguales a las condiciones finales de alguna teoria y
206 // solo una condicion inicial es distinta => agrego una nueva teoría igual (a la q cumple los requisitos
207 // anteriormente detallados) pero tomando ANY en el valor de entrada en el cual difieren.  
208 void CSistemaAutonomo::heuristca_generalizacion(CTeoria& t)
209 {
210         unsigned i ;
211         int count = 0;
212         unsigned k = 0;
213         unsigned j = 0;
214         int posicionCambio = -1;
215         unsigned cantidadTeorias = 0;
216         std::string nombreTeoria;
217
218         cantidadTeorias = this->teorias.count();
219
220         for (i = 0; i < cantidadTeorias; i++)
221         {
222                 for (k = 0; k < this->teorias[i]->datos_finales.count(); k++)
223                 {
224                         //me fijo si las condiciones finales de la teoria se corresponden con la del entorno.
225                         if ((this->teorias[i]->datos_finales[k] != ANY) && (this->p_entorno->datos.find(t.datos_finales.keys(k)) != ANY))
226                         {
227                                 if (this->teorias[i]->datos_finales[k] != this->p_entorno->datos.find(t.datos_finales.keys(k))) 
228                                 {
229                                         count++;
230                                 }
231                         }
232                 }
233                 if (count == 0)
234                 {       // si se corresponden (las condiciones finales son iguales) => me fijo si hay alguna condicion inicial q cambia. 
235                         for (j = 0; j < this->teorias[i]->datos_iniciales.count(); j++)
236                         {
237                                 if ((this->teorias[i]->datos_iniciales[j] != ANY) && (this->p_entorno->datos.find(t.datos_iniciales.keys(j)) != ANY))
238                                 {
239                                         if (this->teorias[i]->datos_iniciales[j] != this->p_entorno->datos.find(t.datos_iniciales.keys(j))) 
240                                         {
241                                                 posicionCambio = j;
242                                                 count++;
243                                         }
244                                 }
245                         }
246                         if (count == 1)
247                         {
248                                 //si cambia solo una => creo una nueva teoria igual pero con ANY en la condicion q cambia.
249                                 CTeoria* nt = new CTeoria ; //Nueva Teoria
250                                 *nt = *this->teorias[i];
251                                 nt->datos_iniciales[posicionCambio] = ANY;
252
253                                 // Agrego la teoria
254                                 nt->nombre = make_nombre(t.nombre, 'g', teorias.count());
255                                 teorias.add (nt->nombre, nt) ;
256 #ifdef DEBUG
257                                 std::cout << "SA: Se agrego una nueva teoria: " << *nt << " basada en " << *teorias[i] << "\n";
258                                 std::cout << "SA: \tdatos_iniciales:\n" << nt->datos_iniciales << "\n";
259                                 std::cout << "SA: \tdatos_finales:\n" << nt->datos_finales << "\n";
260 #endif // DEBUG
261 #ifdef LOG
262                                 std::cout << "Agrega teoria: " << *nt << "," << nt->datos_iniciales << "," << nt->datos_finales << "\n";
263 #endif // LOG
264                         }
265                 }
266                 posicionCambio = -1;
267                 count = 0;
268         }
269 }
270
271 //--------------------------------------------------------------------------------------------
272 //--
273 void CSistemaAutonomo::heuristca_retraccion(CTeoria& t)
274 {
275         unsigned i ;
276         unsigned modif = (unsigned)-1;
277
278         // Recorro la condicion final de la teoria
279         for (i = 0; i < t.datos_finales.count(); i++)
280         {
281                 // Si el dato no coincidio con el del entorno, y no era ANY
282                 if (t.datos_finales[i] != ANY && 
283                                 t.datos_finales[i] != this->p_entorno->datos.find(t.datos_finales.keys(i)))
284                 {
285                         // Le asigno ANY
286                         t.datos_finales[i] = ANY ;
287                         modif = i;
288                 }
289         }
290         if (modif != (unsigned)-1)
291         {
292                 // Le cambio el nombre para indicar que fue modificada
293                 t.nombre += "-r";       
294 #ifdef DEBUG
295                 std::cout << "SA: Se modifica la teoria: " << t << ", el dato final '"
296                         << t.datos_finales.keys(modif) << "' puede tomar ahora cualquier valor\n";
297 #endif // DEBUG
298 #ifdef LOG
299                 std::cout << "Se modifica teoria:\n" << t << "\nEl dato final '"
300                         << t.datos_finales.keys(modif) << "' puede tomar ahora cualquier valor\n";
301                 std::cout << "Agrega teoria: " << t << "," << t.datos_iniciales << "," << t.datos_finales << "\n";
302 #endif // LOG
303         }
304 }
305
306
307 //--------------------------------------------------------------------------------------------
308 //--
309 void CSistemaAutonomo::planificar (CIndiceMagico<t_dato>&       datos_iniciales,
310                                 CIndiceMagico<t_dato>&          datos_finales,
311                                 CIndiceMagico<CTeoria*>&        plan,
312                                 double&                         p,
313                                 unsigned long                   numero_de_llamada)
314 {
315         unsigned i;
316         CIndiceMagico<CTeoria*> test_plan ;
317         CIndiceMagico<CTeoria*> new_plan ;
318         double test_p ;
319         double max_p = 0 ;
320
321
322         if ( incluye_a(datos_iniciales, datos_finales) ) return ;
323
324         if (numero_de_llamada > max_pasos) return ;
325
326         for (i = 0; i < teorias.count(); i++)
327                 if ( incluye_a(teorias[i]->datos_iniciales, datos_iniciales) )
328                 {
329                         test_plan.clear() ;
330                         test_plan.add (teorias[i]->nombre, teorias[i]) ;
331
332                         test_p = p * ((double)teorias[i]->p)/((double)teorias[i]->k) ;
333
334                         planificar(teorias[i]->datos_finales, datos_finales, test_plan, test_p, numero_de_llamada+1) ; 
335
336                         if ( test_p>max_p )
337                         if ( incluye_a(test_plan[test_plan.count()-1]->datos_finales, datos_finales) )
338                         {
339                                 max_p = test_p ;
340                                 new_plan.clear() ;
341                                 new_plan.add (test_plan) ;
342                         }
343                 }
344
345         if (max_p>0)
346                 plan.add (new_plan) ;
347 }
348
349 void CSistemaAutonomo::purgar_teorias()
350 {
351         unsigned size = teorias.count();
352         unsigned pos = size - 1;
353         double whorst_prob = 1.0;
354         for (unsigned i = 0; i < size; ++i)
355         {
356                 double p = (double)teorias[i]->p / (double)teorias[i]->k;
357                 if (p < whorst_prob)
358                 {
359                         whorst_prob = p;
360                         pos = i;
361                 }
362         }
363         teorias.remove(pos);
364 #ifdef DEBUG
365         std::cout << "SA: Se purgo la teoria " << *teorias[pos] << "\n";
366 #endif // DEBUG
367 #ifdef LOG
368         std::cout << "Se purgo la teoria:\n" << *teorias[pos] << "\n";
369 #endif // LOG
370         if (size - 1 > max_teorias) purgar_teorias();
371 }
372