SET 39 Call For Papers

¿Eres un hacker? Si deseas pasar a formar parte de la historia del hacking hispano, colabora con la próxima edición de SET 39 enviándonos un artículo. No esperes más, esta es tu oportunidad de demostrar lo que sabes. Ayúdanos a construir una revista de hackers para hackers. SET Staff

SET 17

93159 visitas

Sistemas Expertos

      7447

Autor: Falken
-[ 0x09 ]--------------------------------------------------------------------
-[ SISTEMAS EXPERTOS ]-------------------------------------------------------
-[ by Falken ]--------------------------------------------------------SET-17-

                        _     _
                       (_)   | |
                    ___ _ ___| |_ ___ _ __ ___   __ _ ___ 
                   / __| / __| __/ _ \ '_ ` _ \ / _` / __|
                   \__ \ \__ \ ||  __/ | | | | | (_| \__ \
                   |___/_|___/\__\___|_| |_| |_|\__,_|___/

                                             _
                                            | |
                    _____  ___ __   ___ _ __| |_ ___  ___
                   / _ \ \/ / '_ \ / _ \ '__| __/ _ \/ __|
                  |  __/>  <| |_) |  __/ |  | || (_) \__ \
                   \___/_/\_\ .__/ \___|_|   \__\___/|___/
                            | |
                            |_|


      				  by Falken


Introduccion
=-=-=-=-=-=-

  Hacia tiempo que no escribia algo, y ya iba siendo hora, verdad?

  Al grano. He comprobado como ultimamente ha crecido el interes por la
inteligencia artificial, publicandose articulos en algunos fanzines de
tematica under.

  Asi que en este numero vamos a tratar un oco por encima lo que es la
inteligencia artificial, en que nos puede servir, y vamos a poner un ejemplo
en C de un sistema experto. Y que conste que C no es el lenguaje mas
apropiado para la inteligencia artificial. Para algo tenemos los
tradicionales Lisp y Prolog. (A quien he oido decir que Java iba a sustituir
al Lisp?)


Breve historia... de la inteligencia
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  Hace unos a~os la inteligencia artificial paso por un momento que quizas
podriamos considerar de esplendor en lo que a imagen se refiere, pero no en
cuanto a resultados.

  Todos nos quedabamos fascinados viendo ejemplos de maquinas que aprendian,
mantenian conversaciones, resolvian problemas.

  De hecho, en 'Juegos de guerra', mientras que para mucha gente el
protagonismo lo tiene David LightMan como hacker, para otros lo tiene la
WOPR como maquina inteligente, que consigue aprender algo que mucha
gente ni siquiera entiende. Pero eso es una pelicula, y la realidad esta
aun muy lejos de esos extremos. Aunque hay leyendas... ;)

  El primer problema al que nos enfrentamos cuando hablamos de inteligencia
artificial es el propio hecho de la inteligencia. Que es la inteligencia?
Esta claro que se puede reproducir la inteligencia, aunque algunos se
empe~an en demostrar lo contrario, comportandose como idiotas toda su
vida.

  Pero de lo que se traa es de controlar ese proceso de inteligencia. De
ser capaces de definir que es lo que distingue un comportamiento
inteligente de otro no inteligente. En otras palabras. Se trata de
averiguar que es realmente la inteligencia.

  Durante a~os se estuvo de acuerdo con ciertas definiciones, como la que
propuso Alan Turing. Decia que una maquina se podia considerar inteligente
si superaba cierta prueba.

  La prueba consiste en tener a una persona en una habitacion y a la
maquina en otra. Una persona fuera de ambas, y sin poder entrar a
ninguna, raliza las preguntas que desee, a ambas entidades. Tanto la
maquina como la persona responden lo que crean oportuno.

  Si no es posible determinar con total certeza cual es la persona y cual
la maquina, entonces la maquina habra de considerarse inteligente.

  Este test, en mi opinion y en la de otros que saben mas que yo del tema,
ha sido ampliamente superado. De hecho, por eso hoy dia no se le considera
valido.

  El nacimiento de la Inteligencia Artificial (IA pa los amigos ;) ), se
ha establecido en 1960, con la creacion del LISP por John McCarthy, del MIT.
Justo un a~o despues, Marvin Minsky, tambien del MIT escribiria un tratado
titulado 'hacia la inteligencia artificial'.

  Quizas el programa mas conocido que realmente nunca supero el test de
Turing, aunque algunos asi lo consideren, es Eliza, de Joseph Weizenbaum,
creado en 1964. Un programa capaz de mantener una conversacion, parodiando
a un psicoanalista. Esa era la intencion de Weizenbaum cuando lo creo:
burlarse de los psicoanalistas de su epoca.

  La sorpresa se la llevo el, cuando su secretaria le pidio permiso para
poder usar a Eliza con otra persona que se lo habia solicitado, pues a ella
le habia resuelto los problemas que tenia. Weizenbaum se esforzo en
demostrar primero que Eliza no era inteligente, y segundo, que era
peligroso.

  La verdad, en mi opinion no es inteligente,pero si util. Un buen
psicoanalista no te resuelve el problema que tengas, te hace pensar para que
tu seas capaz de rsolverlo por ti mismo. Y eso es lo que hacia Eliza. A
menos que se refiera al peligro para el psicoanalisis, que entonces
muchos se quedarian sin trabajo.

  El programa que causo un mayor revuelo fue el Doctor, de Borrow (espero
haberlo escrito bien ;) ). Se trata de una version ampliada de Eliza, que
realmente supero el test de Turing.

  Borrow lo estaba desarrollando como hobby, y lo dejo funcionando en el
ordenador de su despacho mientras atendia otros asuntos. Su jefe se puso
en contacto con el, o al menos eso creia. Conectado a la terminal, confundio
al Doctor con Borrow, dandose cuenta del error cuando se le olvido finalizar
una frase con el punto. Esto era una condicion necesaria para que Doctor
recogiera la frase, la analizara y respondiese en consecuencia. Pero no
respondio... Y al final todo se descubrio.

  Sigo sin creer que Dector fuera inteligente. Solo seguia un automata
que en funcion de una entrada generaba una salida. Como una calculadora
vulgar y corriente, pero mas entretenido.

  Despues llego Shrdlu. Mas loco que ninguno de los anteriores. Te cambia
de tema de conversacion cuando de sale de las narices, y lo mejor es que
realmente parece inteligente.

  Pero volvemos al mismo punto de partida. Que es la inteligencia?

  Generalmente, aunque tengamos la inteligencia delante de nuestras narices,
no nos daremos cuenta. Ni siquiera lo hacemos con los animales. Veamos.
Su estructura biologica les impide vocalizar como un humano. Pero eso no
dice que no sean inteligentes. De hecho, un animal, aparte de entenderse
con los propios de su especie, aprenden a entender a los humanos, aunque
sean cosas reducidas, e incluso a otras especies. Y sin embargo, el ser
humano solo entiende al ser humano, y a veces ni eso.

  Un ejemplo lo tenemos con la gorila Koko. Habla usando el lenguaje de
signos de los sordomudos y mantiene perfectamente una conversacion. Hace
poco incluso sele adapto una terminal (menudo tecladito para soportar sus
'delicados dedos'), y estuvo una hora y pico charlando con la gente que lo
queria a traves de Internet.

  Asi que si ni siquiera somos capaces de discernir con certeza la
inteligencia en un ser vivo, como lo vamos a hacer en una maquina?


Ramas de la IA
=-=-=-=-=-=-=-

  Con el paso del tiempo, la inteligencia artificial ha ido evolucionando.
En esta evolucion han surgido diversas ramas, algunas de las cuales no tienen
nada que ver con las demas.

  Una de las mas conocidas es la busqueda de soluciones, que ademas es la que
de momento esta mas cerca de las redes.

  La busqueda de soluciones tiene su ejemplo mas conocido en los programas
de ajedrez. Estos programas exploran un arbol evaluando la posicion de cada
pieza dentro del tablero, analizando a su vez las jugadas posteriores para
determinar cual es el movimiento mejor o en su caso, el menos malo.

  Pero nosotros tenemos un ejemplo mucho mas cercano. En la red Internet.
Cuando un paquete IP no puede llegar a su destino por un camino, se busca
uno alternativo. Y ahi entran en juego los algoritmos de busqueda usados
en inteligencia artificial.

  De hecho, los algoritmos de prediccion de saltos de los modernos
procesadores y los algoritmos de gestion de procesos de los sistemas
multitarea siguen reglas muy proximas a los algoritmos de busqueda de la
inteligencia artificial.

  Otro campo de interes es el del procesamiento del lenguaje natural. Aqui
entran programas como Eliza, Doctor o Schrdlu. Pero mucho mejores. Desde
luego, ninguna empresa hoy piensa en desarrollar un programa que mantenga
una conversacion con el usuario, a no ser que se trate de un programa que
intente convencernos para que compremos Windows 2000.

  Esta rama de la IA se aplica especialmente a correctores ortograficos que
no solo miran que una palabra este en un diccionario. Pero sobre todo a los
archipopulares traductores automaticos. Hay que tener presente que entre los
diferentes idiomas existen diferencias de expresion que no se solucionan
simplemente con cambiar una palabra de un idioma a otro.

  Ademas, junto con otro campo de la IA que ahora veremos, es el ideal para
los sistemas de reconocimiento de voz dedicados a procesadores de texto.
Os imaginais un programa que segun le dictais os corrige gramatical y
sintacticamente... que rollo, no?

  Lo siguiente es el reconocimento de modelos... Interesante y a la vez
util, sobre todo en fabricas, usado en conunto con un control de robotica.

  Por seguir, podemos segui tratando de la logica, la logica difusa, y las
ultimas tendencias como la vida artificial.

  Pero de lo que va a tratar este articulo principalmente es de los
sistemas expertos. De que son, como funcionan y para que se usan.


Sistemas expertos
=-=-=-=-=-=-=-=-=

  Realmente no hay mucho que decir sobre los sistemas expertos... Se trata
de sistemas que son expertos. A que lo he dejado claro? ;)

  Bromas aparte. Un sistema experto trata de reproducir a un experto en una
materia concreta. Imaginemos a una persona que no tiene mucha idea de
ordenadores y se ha encontrado una tarjeta para su equipo. No sabe para que
sirve, pero tiene un amigo que es un genio de las computadoras. Vamos, que
nacio con un modem/fax bajo el brazo.

  Da la casualidad que el dia que se encuentran no lleva la tarjea encima y
sale el tema. Entonces el amigo le pregunta:

<amigo> Es ISA o PCI
<afortunado> Y eso que es?
<amigo> la conexion al ordenador... tiene pistas grandes o peque~as?
<afortunado> peque~as
<amigo> tiene conectores externos?
<afortunado> si
<amigo> Cuantos?
<afortunado> 1
<amigo> Reconoces el tipo?
<afortunado> Parece de telefono, pero es mas ancho
<amigo> Y solo tiene 1?
<afortunado> Si, con dos lucecitas a un lado
<amigo> Tio, lo tuyo es una tarjeta de red UTP.

  El sistema experto, cn unas reglas para las preguntas mas estrictas, tiene
que reproducir al amigo.

  El uso de sistemas expertos nos ayuda a evitar que se nos pasen detalles
por alto cuando tenemos que tomar una decision importante, por ejemplo.
Ademas, la ventaja de disponer de un sistema experto se fundamenta
especialmente en que al ser un programa de ordenador, o una maquina, se hacen
copias y cada uno puede tener en su casa a su propio experto, sin tener que
estar dependiendo de la experiencia y formacion que requiere un experto
humano.

  Ademas, lo que aprenda el sistema experto podra ser usado en los demas
sistemas expertos, y sobre todo, no se cansa nunca. Asi nos aseguramos que
no falla en un momento crucial.

  Claro, que nada de esto se desarrolla si no tiene unas posibilidades
comerciales. Lamentable, pero es asi... Al menos lo era con la era
Microsoft.

  La IA estaba un poco muerta, cerrada a los laboratorios de investigacion.
Pero a finales de los a~os 70 se creo MYCIN, el primer sistema experto
comercial.

  MYCIN fue un exito total. Se desarrollo en la Universidad de Standford
(que curioso, como el cache kernel), con la intencion de ayudar a los
medicos a diagnosticar ciertas enfermedades bacterianas. En base a la
comparacion de muestras, el sistema experto elabora un criterio con el
que se contrasta el criterio del medico.

  Hoy dia ya es impensable que un moderno hospital no cuente con un sistema
experto para confirmar las decisiones de los medicos. La palabra final la
sigue teniendo el medico, pero ahora cuenta con una ayuda importantisima,
y que nunca falla. (Fallara el al introducir los datos, pero el programa
no falla. Hace lo que esta programado).

  En 1978 se desarrollo otro sistema experto de exito: PROSPECTOR. Este
quizas impulso mas la carrera por desarrollar mejores sistemas expertos,
dado que su mision era predecir la posibilidad de encontrar depositos de
minerales en una region en concreto. Minerales como petroleo, gas natural,
helio...


El sistema experto... por dentro
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  Fundamentalmente un sistema experto se constituye de dos partes esenciales.
Son la Base de conocimiento y el Motor de inferencia.

  La Base de conocimiento es una base de datos constituida por los objetos
de la muestra y los atributos que poseen mediante una relacion especial.
Por ejemplo, la tarjeta de red anterior es el objeto, y los atributos son
rj45, indicadores luminosos, etc. La relacion es 'tiene'

  El Motor de inferencia es el que se encarga, a partir de la Base de
Conocimiento y de los datos proporcionados por el usuario, de discernir
a que objeto nos referimos. Para llegar a una conclusion, podemos usar uno
de tres metodos:

	- Encadenamiento hacia adelante: Aqui el usuario suministra los datos
					 al sistema en un principio, y el
					 sistema elabora una hipotesis con
					 ellos.
	- Encadenamiento hacia atras: En este caso, el sistema comienza
				      preguntando al usuario por propiedades
				      que puede tener el objeto, creando una
				      hipotesis inicial y trabajando en
				      demostrarla.
	- Reglas de produccion: Se trata de un encadenamiento hacia atras
				mejorado, en el que por defecto el sistema
				siempre hipotetiza sobre la posibilidad que
				de ser eliminada elimine la mayor
				incertidumbre posible.


Codigo fuente para entrenarse un poco
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

  Aqui os dejo una version muy cutre (y con errores) de un sistema experto
de proposito general muy basico.

<++> set_017/SE/experto.c
/* experto.c by Falken para SET
 *
 * BETA 1
 *
 * SET - Saqueadores Edicion Tecnica, 1998
 *
 * Sistema experto basico de proposito general que ofrece multiples
 * soluciones y ademas muestra el razonamiento seguido.
 * Basado en el fuente incluido en el libro 'Utilizacion de C en inteligencia
 * artificial' de Herbert Schildt, y publicado por Osborne/McGrawHill
 *
 * UNIX/Linux: gcc -o experto experto.c
 * DOS: DJGPP
 * Windows: Cygnus
 *
 * EXPERTO
 *
 */

#include "stdio.h"
#include "alloc.h"

#define MAX 100

struct atributo {
	char atrib [80];
	struct atributo *siguiente;
	} at;

struct objeto {
	char nombre [80];
	struct atributo *alista;	/* Apuntar a la lista de atributos */
	} ob;

struct objeto_rechazado {
	char nombre [80];
	char atrib [80];		/* Atributo que causo el rechazo */
	char condicion;			/* Era necesario o se descarto por
					   una deduccion previa */
	} rj;

struct objeto_rechazado r_base [MAX];
struct objeto base_c [MAX];		/* Base de conocimiento */

int n_pos = -1;				/* Posicion en la base de
					   conocimiento */
int r_pos = -1; 			/* Posicion en la lista de
					   rechazos */

struct atributo *si, *no;		/* listas de tiene y no tiene */
struct atributo	*siguientesi, *siguienteno;

main ()
{
	char ch;

	no=si=0x00;
	do {
		libera_lista();
		ch=menu();
		switch(ch) {
			case 'i': introduce();
				  break;
			case 'p': pregunta();
				  break;
			case 's': salva();
				  break;
			case 'c': carga();
				  break;
		}
	} while (ch != 'x');
}

libera_lista()
{
	struct atributo *p;

	while (si) {
		p = si -> siguiente;
		free (si);
		si = p;
	}

	while (no) {
		p = no -> siguiente;
		free (no);
		no = p;
	}
}

/*
 * Ahora codificamos la funcion encargada de crear la base de conocimiento
 */

introduce()
{
	int t;
	struct atributo *p, *anterior_p;

	for (;;) {
		t = obtiene_siguiente();
		if (t == -1) {
			printf ("Fuera de la lista.\n");
			return;
		}
		printf ("Nombre del objeto: ");
		gets (base_c[t].nombre);

		if (!*base_c[t].nombre) {
			n_pos--;
			break;
		}

		p = (struct atributo *) malloc(sizeof(at));
		if (p == 0x00) {
			printf ("No hay memoria suficiente.\n");
			return;
		}
		base_c[t].alista = p;
		printf ("Introduce los atributos del objeto. ENTER para salir\n");
		for (;;) {
			printf (">> ");
			gets (p->atrib);
			if (!p->atrib[0]) break;
			anterior_p = p;
			p->siguiente = (struct atributo *) malloc(sizeof(at));
			p = p->siguiente;
			p->siguiente = 0x00;
			if (p == 0x00) {
				printf ("No hay memoria suficiente.\n");
				return;
			}
		}
		anterior_p->siguiente = 0x00;
	}
}

/*
 * Ahora codificamos la funcion encargada de realizar las preguntas al
 * Sistema Experto.
 */

pregunta ()
{
	int t;
	char ch;
	struct atributo *p;

	for (t=0;t<=n_pos;t++) {
		p = base_c[t].alista;
		if (intenta(p, base_c[t].nombre)) {
			printf ("%s concuerda con la actual descripcion\n", base_c[t].nombre);
			printf ("sigo (S/N): ");
			ch = tolower(getche());
			printf ("\n");
			if (ch == 'n') return;
		}
	}
	printf ("No se ha(n) encontrado (mas) objeto(s)\n");
}

/*
 * Esta funcion se encarga de comprobar un objeto.
 */

intenta (struct atributo *p, char *ob)
{
	char respuesta;
	struct atributo *a, *t;

	if (!sigueno(p)) return 0;
	if (!siguesi(p)) return 0;

	while (p) {
		if (preg (p->atrib)) {
			printf ("es/ha/tiene %s? ", p->atrib);
			respuesta = tolower(getche());
			printf ("\n");

			a = (struct atributo *) malloc(sizeof(at));
			if (!a) {
				printf ("No hay memoria suficiente.\n");
				return;
			}
			a->siguiente = 0x00;
			switch(respuesta) {
				case 'n': strcpy (a->atrib, p->atrib);
					  if (!no) {
						no = a;
						siguienteno = no;
					  }
					  else {
						siguienteno->siguiente = a;
						siguienteno = a;
					  }
					  return 0;
				case 's': strcpy (a->atrib,p->atrib);
					  if (!si) {
						si = a;
						siguientesi = si;
					  }
					  else {
						siguientesi->siguiente = a;
						siguientesi = a;
					  }
					  p = p->siguiente;
					  break;
				case 'p': razonando (ob);
					  break;
			}
		}
		else p = p->siguiente;
	}
	return 1;
}

/*
 * Busca un atributo que no tenga el objeto y que este en la lista
 */


sigueno (struct atributo *p)
{
	struct atributo *a, *t;
	a = no;
	while (a) {
		t = p;
		while (t) {
			if (!strcmp(t->atrib,a->atrib))
				return 0;
			t = t->siguiente;
		}
		a = a->siguiente;
	}
	return 1;
}

/*
 * Comprueba que tenga los atributos seleccionados
 */

siguesi (struct atributo *p)
{
	struct atributo *a, *t;
	char ok;

	a = si;
	while (a) {
		ok = 0x00;
		t = p;
		while (t) {
			if (!strcmp(t->atrib,a->atrib))
				ok = 0x01;
			t = t->siguiente;
		}
		if (!ok) return 0;
		a = a->siguiente;
	}
	return 1;
}

/*
 * Comprueba si el atributo se pregunto con anterioridad
 */

preg (char *atrib)
{
	struct atributo *p;

	p = si;
	while (p && strcmp(atrib, p->atrib))
		p = p->siguiente;

	if (!p) return 1;
	else return 0;
}

/*
 * Esta funcion muestra el motivo por el que se sigue una determinada linea
 * de conocimiento.
 */

 razonando (char *ob)
 {
	struct atributo *t;
	int i;

	printf ("Intentando %s\n", ob);
	if (si)
		printf ("es/tiene/ha :\n");
	t = si;
	while (t) {
		printf ("%s\n", t->atrib);
		t = t->siguiente;
	}
	if (no)
		printf ("No es/tiene/ha :\n");
	t = no;
	while (t) {
		printf ("%s\n", t->atrib);
		t = t->siguiente;
	}

	for (i=0;i<=r_pos;i++) {
		printf ("%s rechazado porque ", r_base[i].nombre);
		if (r_base[i].condicion == 'n')
			printf ("%s no es un atributo.\n", r_base[i].atrib);
		else
			printf ("%s es un atributo requerido.\n", r_base[i].atrib);
	}
 }

 /*
  * Situar el objeto rechazado en la base de datos
  */

rechaza (char *ob, char *at, char cond)
{
	r_pos++;

	strcpy(r_base[r_pos].nombre, ob);
	strcpy(r_base[r_pos].atrib, at);
	r_base[r_pos].condicion = cond;
}

/*
 * Conseguir el siguiente indice libre del array de la base de conocimiento
 */

obtiene_siguiente()
{
	n_pos++;
	if (n_pos < MAX) return n_pos;
	else return -1;
}

/*
 * Aqui va la codificacion del menu de opciones
 */

menu()
{
	char ch;

	printf ("(I)ntroduce (P)regunta (S)alva (C)arga e(X)it\n");
	do {
		printf ("Selecciona una opcion: ");
		ch = tolower(getche());
	} while (!esta_en (ch, "ipscx"));
	printf ("\n");
	return ch;
}

/*
 * Salvar la base de conocimiento
 */

salva ()
{
	int t, x;
	struct atributo *p;
	FILE *fp;

	if ((fp = fopen("experto.dat", "w")) == 0) {
		printf ("No puedo crear el archivo\n");
		return;
	}
	printf ("Salvando la base de conocimientos\n");

	for (t=0;t<=n_pos;++t) {
		for (x=0;x<sizeof(base_c[t].nombre);x++)
			putc (base_c[t].nombre[x], fp);
		p = base_c[t].alista;
		while (p) {
			for (x=0;x<sizeof(p->atrib);x++)
				putc(p->atrib[x], fp);
			p = p->siguiente;
		}
		for (x=0;x<sizeof(p->atrib);x++)
			putc ('\0', fp);
	}
	putc (0, fp);
	fclose (fp);
}

/*
 * Cargar una base de conociminto previamente almacenada
 */

carga()
{
	int t, x;
	struct atributo *p, *anterior_p;
	FILE *fp;

	if ((fp = fopen("experto.dat", "r")) == 0) {
		printf ("No puedo abrir el archivo.\n");
		return;
	}
	printf ("Cargando la base de conocimientos\n");

	ini_basec();

	for (t=0;t<MAX;++t) {
		if ((base_c[t].nombre[0] = getc(fp)) == 0)
			break;
		for (x=1;x<sizeof(base_c[t].nombre);x++)
			base_c[t].nombre[x]=getc(fp);
		base_c[t].alista = (struct atributo *) malloc(sizeof(at));
		if (!base_c[t].alista) {
			printf ("No hay memoria suficiente.\n");
			break;
		}

		base_c[t].alista = (struct atributo *) malloc(sizeof(at));
		p = base_c[t].alista;
		if (!p) {
			printf ("No hay memoria suficiente.\n");
			return;
		}
		for (;;) {
			for (x=0;x<sizeof(p->atrib);x++)
				p->atrib[x]=getc(fp);

			if (!p->atrib[0]) {
				anterior_p->siguiente=0x00;
				break;
			}

			p->siguiente = (struct atributo *) malloc(sizeof(at));
			if (!p->siguiente) {
				printf ("No hay memoria suficiente.\n");
				break;
			}
			anterior_p = p;
			p = p->siguiente;
		}
	}
	fclose (fp);
	n_pos = t - 1;
}

/*
 * Funcion para inicializar la base de conocimiento
 */

ini_basec()
{
	int t;
	struct atributo *p, *p2;

	for (t=0;t<=n_pos;t++) {
		p = base_c[t].alista;
		while (p) {
			p2 = p;
			free (p);
			p = p2->siguiente;
		}
	}
}

esta_en (char ch, char *s)
{
	while (*s)
		if (ch == *s++)
			return 1;
	return 0;
}
<-->

  Por el momento lo vamos a dejar aqui. Aun queda mucho por ver, tanto de
sistemas expertos como de IA.

  Como os decia mas arriba, este codigo fuente tiene muchos errores, y el
sistema experto no funciona precisamente bien. Asi lo teneis como
ejercicio para SET 18. Venga, intentad hacer que funcione lo mejor posible,
a~adirle mejoras. Y a ver si es mejor que el que os de en SET 18.


Have P/Hun
Falken