SISTEMAS EXPERTOS

Asignatura: Aplicaciones del Álgebra Computacional a la Inteligencia Artificial Profesor: Eugenio Roanes Lozano Alumno: Alfonso de la Fuente Ruiz Fecha (v1.1): 11 de Agosto de 2009

INTRODUCCIÓN
Se presenta este trabajo para optar a la superación de la asignatura “Aplicaciones del Álgebra Computacional a la Inteligencia Artificial” [15] del Master Oficial en Ingeniería Matemática adaptado al Espacio Europeo de Educación Superior, impartido por la Facultad de Ciencias Matemáticas de la Universidad Complutense de Madrid. El trabajo presentado es invención completa del alumno y se compone de dos partes diferenciadas por su temática, perspectiva y programación, en Maple y LISP respectivamente. La primera parte contiene el desarrollo de un sistema experto fundamentado sobre bases de Gröbner. La segunda constituye un sistema de decisión completamente diferente, diseñado para complementar a la primera parte y en ningún caso sustituirla, aportando una perspectiva informática (que es la principal formación anterior del alumno) desde la ingeniería del conocimiento [1], [4]. Para ambas partes se incluye el código fuente, tanto impreso en este documento, como en fichero digital adjunto.

La presente revisión constituye una actualización del trabajo original. Éste fue calificado con “Sobresaliente”. La nueva versión contiene una corrección cosmética a la galería de casos de flujo en el cruce tipo (eliminación de diagramas redundantes) y otros arreglos menores.

SS.EE. EN MAPLE/GRÖBNER
El sistema experto desarrollado por el alumno en Maple constituye un sistema de control de tráfico rodado para cruces semafóricos de vías con doble sentido de circulación. El motor de inferencia hace uso de las bases de Gröbner para resolver de forma exacta un sistema polinómico general empleando internamente el algoritmo de Buchberger. El sistema puede tener aplicabilidad real a la hora de programar reguladores de cruce para evitar colisiones vehiculares y optimizar la gestión de incidencias diversas, tales como obstrucciones de vías. Es modular y fácilmente extensible a redes viarias con varios cruces de diversa forma, sentidos para la circulación y ubicación de lámparas indicativas en varios colores y para varias direcciones. Se indican algunas de estas posibles extensiones tras el código fuente del programa. El cruce básico considerado tiene la siguiente forma:

En el siguiente diagrama se han etiquetado y señalizado las subáreas para representar los sentidos de circulación, los orígenes y destinos de tráfico, y los tramos de cruce.

Inmediatamente emerge la problemática de evitar colisiones entre los vehículos que sigan diferentes rutas. Para ello se equipa el cruce con cuatro semáforos, uno para cada origen de tráfico (etiquetas 1, 3, 5, 7). Para simplificar, no se situarán semáforos en los destinos de tráfico, ni para peatones o supernumerarios suspendidos en columna o báculo.

Cada semáforo contará con tres luminarias de bajo voltaje para indicar las tres direcciones posibles que pueda tomar un conductor: derecha, frente e izquierda (R – Right; F: Front; L – Left). Véase diagrama de la página siguiente para apreciar su situación.

Se almacenará además la información concerniente a la ruta seguida para alcanzar cada tramo de vía para efectuar la detección de colisiones, del siguiente modo:

Se presenta a continuación una galería de casos que permite observar el flujo de tráfico a través del cruce, en condiciones normales.

Una de las aplicaciones del sistema experto será prevenir colisiones derivadas de la intersección de rutas, como en el siguiente ejemplo:

Para ello se valdrá de una serie de reglas de inferencia que detallarán la ocupación de los tramos de vía según la siguiente formalización. Tramos de cruce alcanzables según origen y destino:

D\O

1

2

3

4

5

6

7

8

1

-

-

-

-

-

-

-

-

2

-

-

B

-

C,B

-

D,C,B

-

3

-

-

-

-

-

-

-

-

4

A,D,C

-

-

-

C

-

D,C

-

5

-

-

-

-

-

-

-

-

6

A,D

-

B,A,D

-

-

-

D

-

7

-

-

-

-

-

-

-

-

8

A

-

B,A

-

C,B,A

-

-

-

-

Pares: nodos de salida u orígenes de tráfico Impares: nodos de llegada o destinos de tráfico 𝐸1 𝐸3 𝐸5 𝐸7 = = = = 𝐷1, 𝐼1, 𝐹1 𝐷3, 𝐼3, 𝐹3 𝐷5, 𝐼5, 𝐹5 𝐷7, 𝐼7, 𝐹7 ; ; ; ;

Estado del sistema semafórico:

ℰ𝑆 = 𝐸1 ∪ 𝐸3 ∪ 𝐸5 ∪ 𝐸7 ; Se pueden entender los estados prohibidos o estados de colisión como aquellos en los que los tramos de cruce {A,B,C,D} son ocupados más de una vez por tráfico procedente de varios haces de rutas con distinto origen.

Volviendo al diagrama de rutas podemos empezar a definir algunas reglas de producción: 𝑅

1 ↔ (𝐴1 ∧ 𝐵1′ ∧ 𝐶1′ ∧ 𝐷1′ ) 𝐹1 ↔ (𝐴1 ∧ 𝐵1′ ∧ 𝐶1′ ∧ 𝐷1) 𝐿1 ↔ (𝐴1 ∧ 𝐵1′ ∧ 𝐶1 ∧ 𝐷1) 𝑅3 ↔ (𝐴3′ ∧ 𝐵3 ∧ 𝐶3′ ∧ 𝐷3′ ) 𝐹3 ↔ (𝐴3 ∧ 𝐵3 ∧ 𝐶3′ ∧ 𝐷3′) 𝐿3 ↔ (𝐴3 ∧ 𝐵3 ∧ 𝐶3′ ∧ 𝐷3) 𝑅5 ↔ (𝐴5′ ∧ 𝐵5′ ∧ 𝐶5 ∧ 𝐷5′ ) 𝐹5 ↔ (𝐴5′ ∧ 𝐵5 ∧ 𝐶5 ∧ 𝐷5′) 𝐿5 ↔ (𝐴5 ∧ 𝐵5 ∧ 𝐶5 ∧ 𝐷5′) 𝑅7 ↔ (𝐴7′ ∧ 𝐵7′ ∧ 𝐶7′ ∧ 𝐷7) 𝐹7 ↔ (𝐴7′ ∧ 𝐵7′ ∧ 𝐶7 ∧ 𝐷7) 𝐿7 ↔ (𝐴7′ ∧ 𝐵7 ∧ 𝐶7 ∧ 𝐷7)

Nótese el uso del apóstrofe (‘) para indicar negación lógica.

Para detectar las colisiones se construye la tabla de verdad para cada tramo de cruce. Por ejemplo, para el tramo A, los estados afirmados son estados de colisión y la tabla de verdad asociada sería la siguiente: A1 A2 A3 A4 TRAMO_A 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 1 1 0 1 0 0 0 0 1 0 1 1 0 1 1 0 1 0 1 1 1 1 1 0 0 0 0 1 0 0 1 1 1 0 1 0 1 1 0 1 1 1 1 1 0 0 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 1 De ahí obtenemos reglas lógicas como la siguiente: 𝐴1′ ∧ 𝐴3′ ∧ 𝐴5′ ∧ 𝐴7′ ∨ 𝐴1 ∧ 𝐴3′ ∧ 𝐴5′ ∧ 𝐴7′ ∨ 𝐴1′ ∧ 𝐴3 ∧ 𝐴5′ ∧ 𝐴7′ ∨ 𝐴1′ ∧ 𝐴3′ ∧ 𝐴5 ∧ 𝐴7′ ∨ 𝐴1′ ∧ 𝐴3′ ∧ 𝐴5′ ∧ 𝐴7 ↔ (𝑇𝑅𝐴𝑀𝑂_𝐴′) Y análogamente para los otros tres tramos.

CÓDIGO FUENTE
Código fuente del sistema experto en Maple Classic v11. Se incluyen comentarios sobre el mismo para explicitar los apartados. Se han desarrollado asimismo dos casos de prueba para conjuntos de hechos consistentes e inconsistentes respectivamente.

#----------------------------------------------------

# UCM/MIM/AAICA - ALFONSO DE LA FUENTE RUIZ (2009) # http://www.linkedin.com/in/alfonsofr

#---------------------------------------------------restart; # Carga de paquetes Maple: with(Groebner): with(Ore_algebra): # Sucesión de variables proposicionales: # Semáforo={R#,F#,L#}. Right, Front, Left, + '#' origen del tráfico. # Tramo_de_ruta='@#', donde '@' es la ruta y '#' es el origen del tráfico. # Tramo_de_vía="TRAMO_#", donde '#' es el código de tramo. SV:= R1,F1,L1 ,R3,F3,L3, R5,F5,L5, R7,F7,L7, A1,A3,A5,A7, B1,B3,B5,B7, C1,C3,C5,C7, D1,D3,D5,D7, TRAMO_A, TRAMO_B, TRAMO_C, TRAMO_D; # También se admiten inputs referidas a tramos del cruce que permitirían modelizar, # por ejemplo, una obstrucción de la calzada que mantenenga el cruce semioperativo. # El comportamiento típico es que no deben existir colisiones en los tramos de cruce.

# Definición del anillo de polinomios (variables las de SV y cuerpo base Z/2Z), # y del orden a usar para los monomios: A:=poly_algebra(SV,characteristic=2):

Orde:=MonomialOrder(A,'plex'(SV)): # Definición del ideal iI (usando una función auxiliar "fu"): fu:=v->v^2-v: iI:=map(fu,[SV]);

# Definición de las conectivas lógicas (las binarias como infijas) # y tautología y contradicción: `NEG` :=(m::algebraic) `&AND`:=(m::algebraic,n::algebraic) `&OR` :=(m::algebraic,n::algebraic) `&IMP`:=(m::algebraic,n::algebraic) `&IFF`:=(m::algebraic,n::algebraic) `&XOR`:=(m::algebraic,n::algebraic) t:=1: c:=0: ->Reduce(1+`m`,iI,Orde): ->Reduce(`m`*`n`,iI,Orde): ->Reduce(`m`+`n`+`m`*`n`,iI,Orde): ->Reduce(1+`m`+`m`*`n`,iI,Orde): ->Reduce(1+`m`+`n`,iI,Orde): ->Reduce(`m`+`n`,iI,Orde):

#----------------------------------------------------

# SISTEMA EXPERTO PARA CRUCE SEMAFÓRICO:

#----------------------------------------------------

# Reglas: # Origen de tráfico 1: RULE01:=R1 &IFF (A1 &AND (NEG(B1) &AND (NEG(C1) &AND NEG(D1)))): RULE02:=F1 &IFF (A1 &AND (D1 &AND (NEG(C1) &AND NEG(B1)))): RULE03:=L1 &IFF (A1 &AND (D1 &AND (C1 &AND NEG(B1)))): # Origen de tráfico 2: RULE04:=R3 &IFF (B3 &AND NEG(A3) &AND NEG(C3) &AND NEG(D3)): RULE05:=F3 &IFF (A3 &AND B3 &AND NEG(C3) &AND NEG(D3)): RULE06:=L3 &IFF (A3 &AND B3 &AND # Origen de tráfico 3: RULE07:=R5 &IFF (C5 &AND NEG(B5) &AND NEG(A5) &AND NEG(D5)): RULE08:=F5 &IFF (B5 &AND C5 &AND NEG(D5) &AND NEG(A5)): D3 &AND NEG(C3)):

RULE09:=L5 &IFF (A5 &AND B5 &AND C5 &AND NEG(D5)): # Origen de tráfico 4: RULE10:=R7 &IFF (D7 &AND NEG(B7) &AND NEG(C7) &AND NEG(A7)): RULE11:=F7 &IFF (C7 &AND D7 &AND NEG(A7) &AND NEG(B7)): RULE12:=L7 &IFF (D7 &AND C7 &AND B7 &AND NEG(A7)):

# Detección de colisiones: RULE13:=(NEG(A1) &AND NEG(A3) &AND NEG(A5) &AND NEG(A7)) &OR ((A1) &AND NEG(A3) &AND NEG(A5) &AND NEG(A7)) &OR (NEG(A1) &AND (A3) &AND NEG(A5) &AND NEG(A7)) &OR (NEG(A1) &AND NEG(A3) &AND (A5) &AND NEG(A7)) &OR (NEG(A1) &AND NEG(A3) &AND NEG(A5) &AND (A7)) &IFF NEG(TRAMO_A): RULE14:=(NEG(B1) &AND NEG(B3) &AND NEG(B5) &AND NEG(B7)) &OR ((B1) &AND NEG(B3) &AND NEG(B5) &AND NEG(B7)) &OR (NEG(B1) &AND (B3) &AND NEG(B5) &AND NEG(B7)) &OR (NEG(B1) &AND NEG(B3) &AND (B5) &AND NEG(B7)) &OR (NEG(B1) &AND NEG(B3) &AND NEG(B5) &AND (B7)) &IFF NEG(TRAMO_B): RULE15:=(NEG(C1) &AND NEG(C3) &AND NEG(C5) &AND NEG(C7)) &OR ((C1) &AND NEG(C3) &AND NEG(C5) &AND NEG(C7)) &OR (NEG(C1) &AND (C3) &AND NEG(C5) &AND NEG(C7)) &OR (NEG(C1) &AND NEG(C3) &AND (C5) &AND NEG(C7)) &OR (NEG(C1) &AND NEG(C3) &AND NEG(C5) &AND (C7)) &IFF NEG(TRAMO_C): RULE16:=(NEG(D1) &AND NEG(D3) &AND NEG(D5) &AND NEG(D7)) &OR ((D1) &AND NEG(D3) &AND NEG(D5) &AND NEG(D7)) &OR (NEG(D1) &AND (D3) &AND NEG(D5) &AND NEG(D7)) &OR (NEG(D1) &AND NEG(D3) &AND (D5) &AND NEG(D7)) &OR (NEG(D1) &AND NEG(D3) &AND NEG(D5) &AND (D7)) &IFF NEG(TRAMO_D):

# Los hechos potenciales son: 1R,1F,1L ,2R,2F,2L, 3R,3F,3L, 4R,4F,4L y sus negaciones

# Ideal de reglas y NICs (restricciones de integridad): iK := [ NEG(RULE01),NEG(RULE02),NEG(RULE03),NEG(RULE04),NEG(RULE05),NEG(RULE06), NEG(RULE07),NEG(RULE08),NEG(RULE09),NEG(RULE10),NEG(RULE11),NEG(RULE12), NEG(RULE13),NEG(RULE14),NEG(RULE15),NEG(RULE16) ]:

#----------------------------------------------------

# EJEMPLO 1:

#----------------------------------------------------

# Un ideal generado por un conjunto consistente de hechos: {L1,R3} # Hay que alimentar el sistema con los 16 estados: 12 luces + 4 tramos de cruce. iJ:=[NEG(L1),NEG(R3), NEG(NEG(F1)),NEG(NEG(R1)), NEG(NEG(L5)),NEG(NEG(F5)),NEG(NEG(R5)), NEG(NEG(L3)),NEG(NEG(F3)), NEG(NEG(L7)),NEG(NEG(F7)),NEG(NEG(R7)), NEG(NEG(TRAMO_A)), NEG(NEG(TRAMO_B)), NEG(NEG(TRAMO_C)), NEG(NEG(TRAMO_D))]:

# Consistencia (la GB que sigue es distinta de [1] ): Base:=Basis([op(iI),op(iJ),op(iK)],Orde);

# Comprobamos: # Todos los Activos (=1): Reduce(A1,Base,Orde); Reduce(D1,Base,Orde); Reduce(C1,Base,Orde); Reduce(B3,Base,Orde); # Algunos Inactivos (<>1): Reduce(A3,Base,Orde); Reduce(D7,Base,Orde); # Efectivamente, un giro a la izquierda (largo) desde el origen 1 # es compatible con un giro a la derecha (corto) desde el origen 3. # Véanse diagramas.

#----------------------------------------------------

# EJEMPLO 2:

#----------------------------------------------------

# Un ideal generado por un conjunto inconsistente de hechos: {L1,L3} # Hay que alimentar el sistema con los 16 estados: 12 luces + 4 tramos de cruce. iJ2:=[NEG(L1),NEG(L3), NEG(NEG(F1)),NEG(NEG(R1)), NEG(NEG(L5)),NEG(NEG(F5)),NEG(NEG(R5)), NEG(NEG(R3)),NEG(NEG(F3)), NEG(NEG(L7)),NEG(NEG(F7)),NEG(NEG(R7)), NEG(NEG(TRAMO_A)), NEG(NEG(TRAMO_B)), NEG(NEG(TRAMO_C)), NEG(NEG(TRAMO_D))]:

# Inconsistencia (la GB que sigue es igual a [1] ): Base:=Basis([op(iI),op(iJ2),op(iK)],Orde);

# Efectivamente, un giro a la izquierda (largo) desde el origen 1 # es incompatible con un giro a la izquierda (largo) desde el origen 3 # so riesgo de colisión. Véanse diagramas.

DESARROLLO FUTURO
Este sistema experto podría mejorarse y extenderse en varias dimensiones durante un eventual desarrollo futuro. Algunas de ellas podrían ser las siguientes:  Optimización de tráfico: garantizar el máximo de casillas (tramos de cruce) ocupadas en todo momento  Generación de estados semafóricos para varios carriles por sentido y dirección  Añadido de estados ámbar entre estados rojo y verde, con lógica trivaluada o categorías.  Añadido de luces para peatones, semáforos en los destinos de tráfico o luces supernumerarias en columnas, báculos, etc.  Asignación, estudio y ajuste de pasos temporales a cada estado.  Posibilidad de tener en cuenta la secuencia de ocupación de cada tramo de cruce.  Lectura y conteo de densidad de tráfico por cada tramo de cruce  Concatenación con otros cruces  Imbricación en un grafo conteniendo ejes de vía para una implementación sobre parcelario real  Adaptar el código fuente a las equivalencias y simetrías que presenta este caso particular de cruce, respecto de rotaciones de 90º en el eje z.  Abreviar y simplificar reglamentación en el código fuente para optimizar el espacio en memoria y/o el tiempo de ejecución  Definir otras conectivas lógicas, como por ejemplo “Colisión”.  Estudio de cruces con diferente morfología. Véanse propuestas a continuación:

Cruce simplificado

Cruce inglés

Modelo de rotonda

SISTEMA EXPERTO EN C-LISP
INTRODUCCIÓN:
Este proyecto se presenta como complemento al anterior tal como se indica en la introducción, y consiste en la creación de un Sistema Experto que atienda un establecimiento de venta de animales domésticos, entre los cuales se cuentan aves, mamíferos y peces como animales de compañía. Este sistema no utilizará bases de Gröebner, centrándose en las facetas más informáticas del desarrollo de sistemas. Los clientes del establecimiento serán los usuarios del sistema, el cual responderá con conocimiento de experto a las preguntas que se le hagan. Este proyecto se encuentra estructurado por fases, siguiendo cada uno de los pasos necesarios para la creación de un Sistema Experto y representadas por los siguientes apartados: 1. 2. 3. 4. 5. Definición de tareas. Adquisición de conocimientos. Conceptualización del problema. Formalización del problema. Implementación de Sistemas Basados en Conocimiento (SBC).

El sistema se debe controlar a alto nivel con un mecanismo de pizarra, constando de tres agentes, uno por cada tipo de animales, y uno más como responsable de almacén.

FASE PRIMERA: DEFINICIÓN DE TAREAS
El Sistema Experto (Sistema Basado en Conocimiento + Conocimiento de Experto) que se aborda constará de tres componentes: - La interfaz de usuario: que se encargará de recibir las preguntas del cliente y de devolver las respuestas al mismo. - Un sistema de explicaciones que se encargará únicamente de formatear las respuestas para el usuario. - Un conjunto de Solucionadores de Problemas o “kernel”, que a su vez está compuesto por: o Una Base de Conocimiento especializada en tiendas de animales. o Un determinado mecanismo de razonamiento que se encargará de construir las respuestas a las preguntas del usuario. o Una memoria de trabajo sobre la que se irá construyendo la solución. ¿En qué consistirá la solución? Existen dos posibles casos: a) Se ofrece al cliente un animal como el que él desea, y él lo compra. b) El cliente no encuentra lo que busca y se le despide sin comprar nada.

Modo de operación del Kernel: 1. Primero se cargará en la memoria de trabajo una representación del problema a resolver, que en este caso es: “hallar el animal que corresponda a las indicaciones dadas por el cliente con el mayor beneficio para la tienda”. 2. Se buscan, en la base de conocimientos, animales que presenten características como las que el cliente requiere. 3. Si se encuentran, son seleccionados y aplicados al problema, alterando la memoria de trabajo. Identificación del problema: El plan de requisitos de la práctica se define como el siguiente: - El objetivo de la aplicación es que el Sistema Experto pueda hallar el animal conveniente para la mayor cantidad posible de consultas (que representan cada una un cliente), contrastando los datos con su propia Base de Conocimiento sobre los animales de compañía de que dispone, obteniendo por ellos la mayor cantidad de dinero posible. - El tiempo de respuesta y el rendimiento de la aplicación no se consideran factores determinantes, por lo que se pasarán a un segundo plano. El problema a tratar (asesoría de venta de animales domésticos) puede ser resuelto mediante un Sistema Basado en Conocimiento, en concreto mediante un Sistema Experto con Base de Conocimiento sobre animales domésticos. Las características del problema se definen del siguiente modo: - Naturaleza: Asociación de caracteres de animales con las peticiones del usuario, lo que requerirá una función de aproximación que determine si una característica es identificable o sinonimiable por otra. - Complejidad: Será necesaria la comparación mediante la mencionada función de aproximación entre el número n de características solicitadas por el cliente, con cada una de las m

características detalladas en la Base de Conocimiento, obteniéndose por tanto una complejidad cuadrática n*m. - Fiabilidad: estará determinada enteramente por la función de aproximación. Por ejemplo, si el usuario quisiera un animal de tamaño grande, esto podría ser tomado por la función con varios grados de precisión, desde sugerirle cualquier animal a partir del tamaño de un loro común, hasta ofrecerle solamente ejemplares de mascota de tamaño superior a un mastín. - Criterios de éxito: conseguir seleccionar un animal que encaje con los requisitos, y venderlo. Descripción lógica de la solución del problema: (Todas_las_características_satisfechas OR Todas_las_características_revisadas AND NOT Todas_las_características_satisfechas))

FASE SEGUNDA: ADQUISICIÓN DE CONOCIMIENTO
Para la construcción de una Base de Conocimiento es necesario obtener una o varias Fuentes fiables de Conocimiento que confieran al SBC la calidad de Sistema Experto. Con este fin en mira se planteó una visita a una tienda real de mascotas donde se realizaría una entrevista al dependiente de la misma para efectuar una posterior educción de conocimiento sobre las notas tomadas.

Ensayo de educción: Se supone una visita hipotética a la tienda real de mascotas y acuarios donde se realizaron una serie de preguntas al encargado con el fin de obtener información acerca del funcionamiento general del establecimiento, así como de otras particularidades. Primeramente se redactó una batería de preguntas que incluían: - ¿Qué tipo de animal es más solicitado por los clientes? - ¿Cómo acostumbran los clientes a pedir un animal (Raza, género, alimentación...) - ¿Qué características son más valoradas y cuales menos? - ¿Qué accesorios son los más solicitados y cómo son escogidos? - ¿Los clientes vienen con una idea clara de lo que quieren o se dejan guiar por el dependiente hasta encontrar lo que buscan? - Si es así, ¿Cómo se las arregla para elegir un ejemplar y no otro? - ¿Cuáles son los criterios de selección de un animal u otro dentro de cada tipo (peces, aves y mamíferos como gatos y perros)? - ¿Es el precio el criterio más observado? Y otras de índole similar.

Una vez preparadas las preguntas se procede a la sesión con el empleado. Tras explicarle los objetivos de las preguntas, se le formulan

éstas y se va tomando notas de los puntos más importantes para el desarrollo de la práctica, así como de algunos comentarios que puedan ser de ayuda en la orientación general que se dar después al conjunto del proyecto. Asimismo se observa la manera de actuar de dependiente durante la atención a clientes.

Con los resultados obtenidos se realiza primero una lectura general de los mismos, y luego una descomposición de las notas tomadas en objetos, atributos, acciones y decisiones, de la que obtener un Glosario de términos y una librería de casos.

Glosario de términos: Animal: Clase base con tres posibles tipos: Pez, Mamífero o Ave. Pez: tipo derivado de animal. Mamífero: tipo derivado de animal. Ave: tipo derivado de animal. Precio: Atributo de un animal. Se comparará con el precio máximo que un cliente esté dispuesto a pagar. Carácter: Atributo de un animal. Tamaño: Atributo de un animal. Color: Atributo de un animal. Especie: Atributo único para cada animal, que constituye una superclave de identificación. Solicitud: Lista de todos los atributos que puede tener un animal. Puede tener alguno o todos sus campos vacíos o sin rellenar Canario: Ave muy pequeña, amarilla o verde de carácter alegre. Loro: Ave mediana, azulada o verde, de carácter agresivo. Cacatúa: Ave pequeña, blanca, de carácter tranquilo.

- Gato andaluz: Mamífero mediano, negro, gris o rojizo, de carácter cariñoso. - Gato persa: Mamífero mediano, gris, de carácter cariñoso (más caro). - Perro salchicha o teckel: Mamífero grande, rojizo, de carácter cariñoso. - Perro Boxer: Mamífero grande, pardo o rojizo, de carácter agresivo. - Perro Chihuahua: Mamífero mediano, pardo o gris, de carácter alegre. - Pez Tropical: Pez pequeño, gris, negro o rojizo, de carácter agresivo. - Pez Tropical decorativo: muy pequeño, negro, gris, amarillo, verde, rojizo o azulado de carácter tranquilo. - Pez Resistente: muy pequeño, negro, gris o azulado de carácter tranquilo. - Pez Limpiador: pequeño, gris, pardo o verdoso de carácter tranquilo. Librería de casos: - El cliente no tiene ninguna idea previa: Se le asigna el animal en stock con mayor precio. - El cliente sabe sólo el precio máximo que quiere pagar: Se le asigna el animal con precio máximo de entre los que tienen un precio igual o inferior al especificado, si existe. Si no: Fallo. - El cliente sabe una o más características que desea, que no incluyen el precio: Se le asigna el animal de mayor precio de los que encajen con todas las características. Si no encaja ninguno: falla. - El cliente sabe dos o más características que desea, incluyendo el precio máximo a pagar: Se le asigna el animal con precio máximo de entre los que tienen un precio igual o inferior al especificado y encajan con todas las características. Si no existe ninguno: falla. - Si hay un fallo se despide al cliente y no se le asigna (vende) ningún animal.

FASE TERCERA: CONCEPTUALIZACIÓN DEL PROBLEMA
Para conceptualizar el problema se deben organizar los conocimientos obtenidos en la adquisición. En este punto tenemos una clase “Animal” con tres subgéneros (“Pez”, “Mamífero” y “Ave”) y una serie de atributos que pueden tomar diferentes valores que serán especificados más tarde. También disponemos de un objeto “Solicitud” que es una lista de atributos de animal, que representa la petición de un cliente, pudiendo tener alguno o todos sus campos vacíos (lo que significa que al cliente no le interesan esas características en particular).

Análisis: - ¿Cómo puedo hallar la mejor venta? o Encontrando el Animal más caro que mejor se ajuste a la Solicitud - ¿Cómo sé qué Animal es el más caro? o Comparando los Atributos “Precio” - ¿Cómo sé qué Animal es el que mejor se ajusta a la Solicitud? o Confrontando los Atributos de los Animales con los de la Solicitud - ¿Cómo puedo confrontar Atributos? o Mediante una función dedicada a ello que se base en criterios de similitud. - ¿Cómo obtengo los Atributos de la Solicitud? o Preguntando al cliente. Síntesis: Preguntar al cliente. Confrontar Atributos. Hallar los Animales más adecuados. Hallar el más caro de los Animales Adecuados. Realizar la venta.

El Sistema Experto debe ir obteniendo los campos de la Solicitud haciendo preguntas al cliente, e ir buscando los Animales que se ajusten a los atributos especificados, para finalmente decidirse por uno, o devolver un Fallo. De este modo, la solución hallada será siempre la mejor.

Tipos de conocimientos:

 Estratégicos o de control: Aquellos que fijan la secuencia de pasos
que el S.E. debe seguir para efectuar una venta.  Tácticos u Operativos: Cómo y cuándo debe el S.E. añadir a sus conocimientos genéricos información actual acerca de la Solicitud.  Factuales o declarativos: Especifican lo que es cierto acerca de la Solicitud, para la cual se busca la mejor venta posible.

Universo de discurso: Es el conjunto de conceptos acerca del cual se expresan los conocimientos. Los conceptos primordiales en este Sistema son los Atributos de los Animales, y todos los valores que pueden tomar, valores que serán definidos más adelante.

Estudio declarativo: Relaciones y sus propiedades: Existe la interacción entre varios conceptos del universo de discurso; entre todas las relaciones, se enfatiza un conjunto relacional más importante que es el siguiente: - Relación taxonómica de instancia “es_un_tipo_de” para los tres grupos básicos de animales. Tiene valencia uno-es-a-uno. - Relación estructurante múltiple dependiente “tiene” entre un animal y su conjunto de atributos, con valencia uno-es-a-muchos. - Relación estructurante múltiple dependiente “exige” entre una Solicitud y un conjunto de atributos, con valencia uno-es-a-muchos.

Funciones: Los elementos del universo de discurso se interrelacionan entre sí por medio de las siguientes funciones: - Función “Confronta_Atributos”: (Atributo x Atributo)  Booleano. - Función “Obtener_Atributo”: (Animal x Tipo_de_Atributo)  (Valor de Atributo). - Función “Obtener_Mas_Caro” (Lista de Animales)  Animal.

Identificación de conceptos: Para la identificación de conceptos se construye un diccionario de conceptos, que incluye la utilidad o función de un concepto, los atributos que lo definen, los valores que pueden tomar esos atributos, y cualquier otro tipo de referencias, cruzadas o no, al mismo:

CONCEPTO

REFERENCIAS

ATRIBUTOS Precio Carácter Tamaño Color

VALORES Cualquier número entero no negativo. Tranquilo, Alegre, Cariñoso, Agresivo Muy pequeño, pequeño, mediano, grande. Negro, Pardo, Gris, Amarillo, Verde, Rojizo, Azulado Aves: Canario, Loro, Cacatúa. Mamíferos: Gato andaluz, Gato persa, Perro Salchicha (teckel), boxer, chihuahua. Peces: Tropical, Tropical decorativo, Resistente, Limpiador

Animal

Puede subdividirse en tres tipos: Ave, Mamífero y Pez.

Especie

Solicitud

Lista, que puede ser vacía de atributos de Animal

---

---

Conocimientos estratégicos: flujo de control del Sistema Experto:

Pasos de Alto Nivel: El experto realiza siempre una serie de pasos durante el transcurso de una venta, que se resumen en los siguientes: 1. Recibir y saludar al cliente. 2. Obtener los requisitos que el cliente busca en un animal determinado e ir comparándolos con las características de los animales que hay en la tienda. 3. Si se encuentra el animal apropiado, se efectúa su venta, si no, se sigue buscando hasta agotar todas las posibilidades. 4. Despedir al cliente. Subpasos de bajo nivel: Cada paso de los anteriores se descompone en una serie de subpasos de nivel más detallado, a saber: 1.1. Saludar al cliente. 1.2. Preguntar cuánto está dispuesto a gastar. 2.2. Repetir hasta que todos los elementos de la Solicitud se han analizado o hasta llegar a la solución vacía: Preguntar siguiente característica. Comparar característica con los animales de la tienda y reducir el grupo de búsqueda. 3.1. Seleccionar el animal más caro posible de los que quedan en el grupo de búsqueda. 3.2. Si existe algún Animal tal, venderlo; si no, indicar que no se encuentra solución. 4.1. Despedir al cliente.

El motor de inferencia efectuará su trabajo más importante en el paso 2.2. para la decisión de los animales que se preseleccionan en un conjunto. De esta manera se observan todas las circunstancias posibles con todos los elementos (Animales) de que se dispone.

El proceso a seguir por el Sistema Experto es el de crear un primer conjunto con todos los animales de precio igual o inferior al requerido por el cliente (si es precio no es relevante, se incluirán todos los Animales disponibles), del que luego se van eliminando aquellos animales cuyos atributos no encajen con los de la Solicitud, para finalmente quedarse con un conjunto (vacío o no) de animales que cumplen todos los requisitos, del cual se escogerá el animal más caro, si es que queda alguno.

Conocimientos factuales: Información que el Sistema Experto conoce a priori

El Sistema Experto conoce al principio los animales de los que dispone y entre los que realizará la selección, así como las características de cada uno, existiendo además una función que devolverá el animal más caro de una serie de animales. Metaconocimientos: El Sistema Experto conoce la forma de crear y reducir un grupo de selección de Animales, basándose en unos criterios de contraste de atributos, regulados por una función específica “Confrontar_Atributos”. Cuando se haya evaluado un Atributo, el sistema sabe también si debe seguir preguntando atributos al cliente, o si ya se han obtenido todos los Atributos que corresponden a una selección, mediante una condición de parada de bucle.

Descripción estándar de los procedimientos:

Nombre en la Base de Conocimientos

Propósito

Información necesaria

Acciones

Confrontar_Atributos

Obtener un Booleano Atributo de un TRUE si son Animal + Atributo equiparables, y FALSE de la Solicitud si no lo son (del mismo tipo) Se obtendrá el valor que toma el Atributo en ese tipo de animal (definido por la especie) Obtendrá el animal con mayor precio Obtendrá el valor que toma el atributo de la Solicitud, si toma alguno Formalidad Animal + Tipo_de_ _Atributo a comprobar

Efectuará un contraste de similitud entre los valores de los Atributos, siempre que sean del mismo tipo

Obtener_Atributos

Accederá al conocimiento disponible sobre el Animal consultado si existe

Obtener_Mas_Caro

Lista de Animales

Llamará a la función ObtenerAtributos(AnimalX, Precio) Se preguntará al cliente y se realizará un análisis de su respuesta. Se emite un mensaje de saludo al cliente. Se emite un mensaje con el Animal escogido y el precio por el que es vendido Se emite un mensaje de despedida al cliente

Preguntar_Atributo

Tipo de Atributo

Saludar

---

Vender

Formalidad

Animal

Despedir

Formalidad

---

FASE CUARTA: FORMALIZACIÓN DEL PROBLEMA
Para la correcta conceptualización del problema se necesita obtener un modelo computable formado por una Base de Conocimiento, un Motor de Inferencia y una determinada Estrategia de Control. Para esta práctica concreta se ha escogido un formalismo basado en conceptos, habiéndose representado las principales clases y entidades del dominio, sus propiedades o atributos y los posibles valores que pueden tomar, empleándose por tanto un formalismo de marcos. Mediante este tipo de formalismo se usan Marcos para representar conceptos, Propiedades para describir cada concepto, Relaciones para representar las dependencias entre conceptos, y Facetas para representar los valores con los que pueden rellenarse las Propiedades.

Representación de conceptos e instancias: Los Marcos Clase (MC) representan conceptos genéricos descritos por un conjunto de propiedades comunes al concepto representado. En el caso particular de este sistema, nos encontramos con el MC principal, que es “Animal”, con sus Atributos. Los Marcos Instancia (MI) son individuos de los conceptos representados por los Marcos Clase, relacionados con alguno de ellos. Por ejemplo, una Instancia de la Clase “Animal” sería un Perro Salchicha o ‘teckel’.

Representación de relaciones entre conceptos: Representación de las relaciones estándar: - “Animal” es una Superclase de “Tipo_de_Animal”, con lo que “Tipo_de_Animal” (Ave, Mamífero, Pez) posee una relación de Subclase que hereda las propiedades de “Animal”. - Un animal concreto se determina por la Superclave “Especie”, y mantiene una relación de Instancia con la Clase “Tipo_de_Animal” - Una solicitud concreta se determina por el valor de los Atributos de la lista, que excluyen “Especie”, y se relaciona instancialmente con la Clase Solicitud.

Representación de Relaciones no estándar: - Los tres tipos de Animal presentan una relación Fraternal entre sí, al ser subclases del mismo Marco Clase. Representación de las propiedades de un concepto: - Propiedades de clase: Son aquellas que toman el mismo valor en todos los elementos de la clase. En este caso, la única propiedad de

clase que existe es la que especifica el tipo de animal (Ave, Pez, Mamífero) dentro de la clase Tipo_de_Animal. - Propiedades de instancia: Aquellas que toman valores concretos dependientes del elemento de la clase al que representan, siendo aquí todos los Atributos, tanto de un animal como de una solicitud. Representación de facetas de propiedades: - Valores que pueden tomar las propiedades: La propiedad de clase Tipo_de_Animal puede tomar los tres valores que especifican las tres clases derivadas (Ave, Pez y Mamífero). Las propiedades de instancia pueden tomar los valores que se muestran anteriormente en la tabla de identificación de conceptos, además del valor “No_especifica” en el caso de que se trate de una propiedad de Solicitud (Que posteriormente se empleará en el proceso de información para representar que al Cliente no le importa esa propiedad en particular). - Valores por omisión: En el caso de una Solicitud, el valor por omisión de cualquier propiedad será “No_especifica”. En el caso de los animales, todos los que se consideran en la tienda tienen rellenados todos sus campos. - En caso de que sea necesario conocer el valor de una cierta propiedad de una solicitud que no se sepa, se preguntará al cliente mediante la función “Preguntar_Atributo”.

Técnicas de inferencia en Marcos: - Herencia de propiedades: En el caso de este sistema, no habrá ningún problema para localizar una determinada propiedad, ya que todas las propiedades necesarias se encuentran en el nivel más bajo de herencia, con lo que no será necesario navegar por los niveles hereditarios para buscarlas. - Valores activos: Existirán dos elementos en el Sistema Basado en Marcos en los que se efectuará un almacenado y borrado de la información: El conjunto de animales candidatos a la solución, y la reproducción en la memoria de trabajo de la solicitud del cliente.

Componente de control: El componente de control del Sistema Basado en el Conocimiento se define como el conjunto de informaciones, datos y conocimientos que proporcionan al sistema los criterios de decisión. - Decisión de bases de conocimientos a emplear: Al haber una única base de conocimientos sobre los animales de que dispone la tienda, siempre se empleará ésta como fuente de conocimiento. - El modo de inferencia escogido se compone de la comparación literal de los valores de las propiedades, existiendo la posibilidad de ampliar el sistema dotándole de un comprobador de sinónimos. Así, por ejemplo, podría decidirse que si el cliente pidiera un animal de color “oscuro” se le pudiera asignar un de color “Negro” o “Pardo”, aunque este Sistema concreto no presenta tal capacidad. - Evaluar si se ha alcanzado la solución o no: Se integra un componente de control que evalúa si se han contrastado todas las propiedades de una Solicitud con todos los animales disponibles en la tienda. Si una vez hecho esto quedan animales en el conjunto de selección, se elegirá el más caro y se habrá alcanzado la solución; si no quedan animales, se devolverá la solución vacía y no se realizará ninguna venta. - Fijar el foco de atención: Se seleccionará en cada momento el conjunto de hechos en la memoria de trabajo que se tendrán en cuenta durante la inferencia, es decir, la propiedad que se está contrastando en un momento determinado. Control de alto nivel: mecanismo de pizarra: El funcionamiento del modelo de pizarra se basa en la iteración de tres elementos: - Pizarra: Estado de resolución del problema. Comprobar si quedan propiedades por contrastar y si el conjunto de candidatos se ha reducido al conjunto vacío. - Fuentes de conocimiento: Obtención de la propiedad a

contrastar. - Componente de control: se seleccionan las Fuentes de conocimiento a ejecutar. Como ninguno de los tipos de animales tiene prioridad sobre otro, se seleccionarán las tres FFCC de manera secuencial, dejando que cada una contribuya su parte de la solución. La contribución a la solución de las Fuentes de Conocimiento (Agentes) se hará de forma secuencial en cualquiera de los seis órdenes posibles (Ave-Pez-Mamífero, Ave-Mamífero-Pez, Pez-Mamífero-Ave,...). En cada vuelta del bucle se comprobará si se ha alcanzado un estado de fallo (Conjunto de candidatos vacío), en cuyo caso se romperá el bucle. Si se sale del bucle por otro medio que no sea el de alcanzar un estado de fallo, se realizará la selección del animal más caro de entre los animales candidato mediante la función Obtener_Mas_Caro y se devolverá el resultado de ésta como Solución. La pizarra se compone, pues, de una lista, vacía o no, de animales indexados por “Especie” (el campo Clave), de una lista ordenada de los valores que la Solicitud establece sobre las propiedades, y del tipo de Atributo a contrastar en cada momento, si queda alguno.

Proceso de control: 1. Una Fuente de Conocimiento modifica el valor de la pizarra. 2. Se evalúa la contribución que realizará cada Fuente de Conocimiento a la solución. 3. Se selecciona un foco de atención (una FC, un objeto, o un objeto y una FC). 4. Se repara la ejecución (Se llama a la función correspondiente con el Foco seleccionado). La estrategia de control, de este modo, asegura que siempre se da un paso hacia la solución.

FASE QUINTA: IMPLEMENTACIÓN DE UN SBC
La herramienta de desarrollo ha de proporcionar los formalismos de representación para codificar la base de conocimientos y los mecanismos de inferencia y control para interpretarla.

Para el presente proyecto se evaluó la implementación en CLIPS, aunque su desarrollo también es posible con otras herramientas que ofrezcan capacidades de desarrollo de modelos conceptuales, formalización y representación de conocimientos y empleo de motor de inferencias, como puede ser Borland Delphi, que requeriría una menor carga en la parte de implementación, ya que integra un entorno más ágil con mayor cantidad de opciones, aunque menos estructurado, o C++ Builder, que además presenta capacidades de integración con CLIPS (‘C Language’ Integrated Production System).

Requisitos de la herramienta para el modelo conceptual: La herramienta elegida para el modelo conceptual debe presentar las siguientes características: - Capacidad para representar los conocimientos Estratégicos, tácticos y factuales usados por el Sistema Experto: CLIPS permite la representación de números, símbolos y cadenas de caracteres, y la estructuración de los mismos mediante hechos (fact – lista atómica de valores con referencia posicional o por nombre), Instancias (defclass para crear clases de usuario; make-instance para generar instancias), campos simples y múltiples, variables, construcciones para añadir conocimiento (defrule para definir reglas, deffacts para hechos, defmessage-handles para manejar el paso de mensajes, defmethod para la definición de métodos de clase, defmodule, defglobal, defgeneric...)... - Capacidad para representar las inferencias necesarias siguiendo la secuencia de pasos correcta: En CLIPS se definen reglas, hechos y métodos, se permite añadir, modificar, duplicar y eliminar hechos (assert, modify, duplicate, retract). - Capacidad para realizar cálculos lógicos y matemáticos: Para los lógicos existen los operadores prefijos <or>, <and> y <not>, mientras que para los matemáticos se permiten los operadores tradicionales como funciones aritméticas básicas, siempre en notación prefija, que se pueden emplear en funciones de cualquier tipo, y se cuenta con un conjunto de funciones aritméticas extendidas (acos – arcoseno, sqrt – raíz cuadrada,...). En caso de que se necesite más potencia, o quizás eficiencia en los cálculos, se puede llamar desde CLIPS a módulos enteros escritos en C que realicen dichos cálculos. - Capacidad para gestionar Bases de Conocimentos Modularizadas accediendo y ligando cuando sea necesario: CLIPS dispone también de funciones con hechos (assert, retract,...), con deftemplates, agenda, reglas, deffunctions, etcétera. CLIPS no presenta, empero, capacidad desarrollada para cooperar con otro tipo de sistemas, como determinadas Bases de Datos y Hojas de Cálculo, ni tampoco posee amplias características de depuración, aunque permite diseño modular y desarrollo independiente. (Notas para la versión 5.01; puede haber cambiado)

Tampoco permite la creación de interfaces de usuario amigables, y al ser un lenguaje interpretativo se incrementan las necesidades de memoria y se reduce la velocidad del sistema desarrollado. Por otro lado es muy versátil, tiene escaso coste y su curva de aprendizaje es razonablemente rápida.

Adjunto a este documento se incluyen los ficheros generados y el programa resultante, ejecutable éste sobre S.O. Microsoft o Linux con el emulador WinE.

CÓDIGO FUENTE
El siguiente programa corresponde a la implementación del sistema experto para la tienda de animales, implementado en Allegro Common Lisp Lite 5.01. Véanse enlaces para ampliar información: - Guía de instalación de Allegro CL 5.01: http://www.franz.com/support/documentation/5.0.1/readme.htm - Allegro en Franz.com: http://www.franz.com/products/allegrocl/ A continuación se especifican los tres ficheros asociados al programa. Todos ellos se adjuntan además al presente documento. Los ficheros son los siguientes: - PracLISP.BAT - Respnoimp.TXT - Tienda.CLP El fichero “PracLISP.BAT” se encarga de efectuar la carga y ejecución del programa, toda vez que Allegro CL se encuentre adecuadamente instalado en el sistema. El fichero “respnoimp.TXT” es llamado (referenciado) por el programa principal que se aloja en “Tienda.CLP” y debe estar en el mismo directorio que éste para que el software funcione correctamente.

PracLISP.BAT

(reset) (load "tienda.clp") (run)

Tienda.CLP
; ######################################################################################## ##### ; # # ; # Allegro CLISP # ; # # ; # Trabajo Práctico: SISTEMA EXPERTO # ; # TIENDA DE ANIMALES DOMÉSTICOS # ; # # ; # Alfonso de la Fuente Ruiz # ; # # ; # # ; ######################################################################################## ##### ; ######################################################################################## ##### (defmodule MAIN (export deftemplate venta) (export deftemplate animal-seleccionado) (export deftemplate ani) (export deftemplate solicitud) ) ; ######################################################################################## ##### ; ######################################################################################## ##### ; CONOCIMIENTO A PRIORI: ; ######################################################################################## ##### ; ######################################################################################## ##### (deftemplate MAIN::venta (slot estado (type SYMBOL) (allowed-symbols saludo pregunta-dinero respuesta-dinero annadir-animales eliminar-caros comprobar-cond-bucle preguntar-atributo obteneratributo comprobar-respuesta comprobar-aves comprobar-peces comprobar-mamiferos obtener-mas-caro comprobacion-venta vender despedir-con-venta despedir-sin-venta)) (slot tipoatr (type SYMBOL) (allowed-symbols precio caracter tamanno color especie) (default precio)) (slot cond-bucle (type SYMBOL) (allowed-symbols TRUE FALSE) (default FALSE)) (slot respuesta-valida (type SYMBOL) (allowed-symbols TRUE FALSE) (default FALSE)) (slot respuesta-atributo (type STRING) (default "no importa"))) ; ######################################################################################## ##### (deftemplate MAIN::animal-seleccionado (slot precio (type NUMBER) (default 0) ) (slot caracter (type SYMBOL) (default noespecifica)

(allowed-symbols noespecifica tranquilo alegre carinnoso agresivo)) (slot tamanno (type SYMBOL) (default noespecifica) (allowed-symbols noespecifica muypequenno pequenno mediano grande)) (slot color (type SYMBOL) (default noespecifica) (allowed-symbols noespecifica blanco negro pardo gris amarillo verde rojizo azul)) (slot tipoani (type SYMBOL) (default noespecifica) (allowed-symbols ave pez mamifero noespecifica)) (slot especie (type SYMBOL) (default noespecifica) (allowed-symbols noespecifica canario loro cacatua gatoandaluz gatopersa teckel boxer chihuahua peztropical pezdecorativo pezresistente pezlimpiador))) ; ######################################################################################## ##### (deftemplate MAIN::ani (slot precio (type NUMBER) (default 0) ) (slot caracter (type SYMBOL) (default noespecifica) (allowed-symbols noespecifica tranquilo alegre carinnoso agresivo)) (slot tamanno (type SYMBOL) (default noespecifica) (allowed-symbols noespecifica muypequenno pequenno mediano grande)) (slot color (type SYMBOL) (default noespecifica) (allowed-symbols noespecifica blanco negro pardo gris amarillo verde rojizo azul)) (slot tipoani (type SYMBOL) (default noespecifica) (allowed-symbols ave pez mamifero noespecifica)) (slot especie (type SYMBOL) (default noespecifica) (allowed-symbols noespecifica canario loro cacatua gatoandaluz gatopersa teckel boxer chihuahua peztropical pezdecorativo pezresistente pezlimpiador))) ; ######################################################################################## ##### ; NOTA: Los precios no son los reales. (deftemplate MAIN::solicitud (slot precio (type NUMBER) (default 20000)) (slot caracter (type SYMBOL) (default noespecifica) (allowed-symbols noespecifica tranquilo alegre carinnoso agresivo)) (slot tamanno (type SYMBOL) (default noespecifica) (allowed-symbols noespecifica muypequenno pequenno mediano grande)) (slot color (type SYMBOL) (default noespecifica) (allowed-symbols noespecifica blanco negro pardo gris amarillo verde rojizo azul))) ; ######################################################################################## ##### ; ######################################################################################## ##### ; REGLAS: ; ######################################################################################## ##### ; ######################################################################################## ##### (defrule MAIN::entrar-tienda => (printout t crlf) (printout t "######################################" crlf crlf) (printout t "Sistema Experto desarrollado por:" crlf) (printout t "Alfonso de la Fuente Ruiz" crlf crlf) (printout t "######################################" crlf crlf)

(assert (venta (estado saludo) (tipoatr precio) (cond-bucle FALSE) (respuesta-valida FALSE) (respuesta-atributo ""))) (assert (animal-seleccionado (tipoani noespecifica) (precio 0) (caracter noespecifica) (tamanno noespecifica) (color noespecifica) (especie noespecifica))) (assert (solicitud (precio 0) (caracter noespecifica) (tamanno noespecifica) (color noespecifica))) ) ; ######################################################################################## ##### (defrule MAIN::saludar ?var1 <- (venta (estado saludo)) => (printout t "Bienvenido a la Tienda de Animales:" crlf) (modify ?var1 (estado pregunta-dinero)) ) ; ######################################################################################## ##### (defrule MAIN::cuanto-dinero ?var1 <- (venta (estado pregunta-dinero)) ?var2 <- (solicitud (precio ?dinero)) ?var3 <- (animal-seleccionado) => (printout t crlf "######################################" crlf crlf) (printout t "Veamos en qué podemos ayudarle..." crlf) (printout t "¿Cuánto tenía pensado gastar (0..20000 euro-cents.)?" crlf) (printout t "(Si no lo sabe o no lo ha pensado aún, responda 0)" crlf "EURO: >> ") (bind ?dinero (read stdin)) (modify ?var1 (estado respuesta-dinero) (tipoatr precio) (cond-bucle FALSE) (respuesta-valida FALSE) (respuesta-atributo "")) (modify ?var2 (precio ?dinero) (caracter noespecifica) (tamanno noespecifica) (color noespecifica)) (modify ?var3 (precio 0) (caracter noespecifica) (tamanno noespecifica) (color noespecifica) (tipoani noespecifica)(especie noespecifica)) ) ; ######################################################################################## ##### (deffunction MAIN::valido (?n) (and (numberp ?n) (<= 0 ?n) (>= 20000 ?n))) ; ######################################################################################## ##### (defrule MAIN::mala-respuesta-dinero ?var1 <- (venta (estado respuesta-dinero)) ?var2 <- (solicitud (precio ?dinero&:(not (valido ?dinero)))) => (printout t crlf "######################################" crlf crlf "No le entiendo; por favor, especifique una cantidad entre 0 y 20000:" crlf) (modify ?var1 (estado pregunta-dinero)) (modify ?var2 (precio 20000)) )

; ######################################################################################## ##### (defrule MAIN::buena-respuesta-dinero ?var1 <- (venta (estado respuesta-dinero) (cond-bucle ?cond)) ?var2 <- (solicitud (precio ?dinero&:(valido ?dinero))) => (modify ?var1 (estado annadir-animales) (cond-bucle FALSE)) ) ; ######################################################################################## ##### (defrule MAIN::annade-animales ?var1 <- (venta (estado annadir-animales)) ?var2 <- (solicitud (precio ?precio-deseado)) => (assert (ani (tipoani ave) (precio 6500) (caracter tranquilo) (tamanno pequenno) (color blanco) (especie cacatua))) (assert (ani (tipoani ave) (precio 5900) (caracter agresivo) (tamanno mediano) (color azul) (especie loro))) (assert (ani (tipoani ave) (precio 4700) (caracter agresivo) (tamanno mediano) (color verde) (especie loro))) (assert (ani (tipoani ave) (precio 1200) (caracter alegre) (tamanno muypequenno) (color amarillo) (especie canario))) (assert (ani (tipoani ave) (precio 900) (caracter alegre) (tamanno muypequenno) (color verde) (especie canario))) (assert (ani (tipoani pez) (precio 1300) (caracter tranquilo) (tamanno pequenno) (color gris) (especie pezlimpiador))) (assert (ani (tipoani pez) (precio 900) (caracter tranquilo) (tamanno pequenno) (color pardo) (especie pezlimpiador))) (assert (ani (tipoani pez) (precio 2100) (caracter tranquilo) (tamanno pequenno) (color verde) (especie pezlimpiador)))

(assert (ani (tipoani pez) (precio 2500) (caracter tranquilo) (tamanno muypequenno) (color negro) (especie pezresistente))) (assert (ani (tipoani pez) (precio 1600) (caracter tranquilo) (tamanno muypequenno) (color gris) (especie pezresistente))) (assert (ani (tipoani pez) (precio 3900) (caracter tranquilo) (tamanno muypequenno) (color azul) (especie pezresistente))) (assert (ani (tipoani pez) (precio 8900) (caracter tranquilo) (tamanno muypequenno) (color azul) (especie pezdecorativo))) (assert (ani (tipoani pez) (precio 8400) (caracter tranquilo) (tamanno muypequenno) (color rojizo) (especie pezdecorativo))) (assert (ani (tipoani pez) (precio 6900) (caracter tranquilo) (tamanno muypequenno) (color verde) (especie pezdecorativo))) (assert (ani (tipoani pez) (precio 5000) (caracter tranquilo) (tamanno muypequenno) (color amarillo) (especie pezdecorativo))) (assert (ani (tipoani pez) (precio 4300) (caracter tranquilo) (tamanno muypequenno) (color gris) (especie pezdecorativo))) (assert (ani (tipoani pez) (precio 6500) (caracter tranquilo) (tamanno muypequenno) (color negro) (especie pezdecorativo))) (assert (ani (tipoani pez) (precio 3600) (caracter agresivo) (tamanno pequenno) (color gris) (especie peztropical))) (assert (ani (tipoani pez) (precio 4000) (caracter agresivo) (tamanno pequenno) (color negro) (especie peztropical)))

(assert (ani (tipoani pez) (precio 4500) (caracter agresivo) (tamanno pequenno) (color rojizo) (especie peztropical))) (assert (ani (tipoani mamifero) (precio 11500) (caracter alegre) (tamanno mediano) (color pardo) (especie chihuahua))) (assert (ani (tipoani mamifero) (precio 13500) (caracter alegre) (tamanno mediano) (color gris) (especie chihuahua))) (assert (ani (tipoani mamifero) (precio 17900) (caracter agresivo) (tamanno grande) (color pardo) (especie boxer))) (assert (ani (tipoani mamifero) (precio 19500) (caracter agresivo) (tamanno grande) (color rojizo) (especie boxer))) (assert (ani (tipoani mamifero) (precio 16900) (caracter carinnoso) (tamanno grande) (color rojizo) (especie teckel))) (assert (ani (tipoani mamifero) (precio 13900) (caracter carinnoso) (tamanno mediano) (color gris) (especie gatopersa))) (assert (ani (tipoani mamifero) (precio 9900) (caracter carinnoso) (tamanno mediano) (color negro) (especie gatoandaluz))) (assert (ani (tipoani mamifero) (precio 9000) (caracter carinnoso) (tamanno mediano) (color gris) (especie gatoandaluz))) (assert (ani (tipoani mamifero) (precio 10500) (caracter carinnoso) (tamanno mediano) (color rojizo) (especie gatoandaluz))) (if (eq ?precio-deseado 0) then (modify ?var2 (precio 20000)) ) (modify ?var1 (estado eliminar-caros)) )

; ######################################################################################## ##### (defrule MAIN::elimina-caros (declare (salience 1000)) (venta (estado eliminar-caros)) (solicitud (precio ?precio-tope)) ?var1 <- (ani (precio ?coste-animal) (color ?color) (especie ?especie)) (test (> ?coste-animal ?precio-tope)) => (retract ?var1) ) ; ######################################################################################## ##### (defrule MAIN::caros-eliminados-quedan (declare (salience 500)) ?var1 <- (venta (estado eliminar-caros) (cond-bucle ?cond)) (ani (color ?color) (especie ?especie)) => (modify ?var1 (cond-bucle TRUE) (estado comprobar-cond-bucle)) ) ; ######################################################################################## ##### (defrule MAIN::caros-eliminados-todos ?var1 <- (venta (estado eliminar-caros) (cond-bucle ?cond)) => (printout t crlf "No tenemos nada tan barato" crlf) (modify ?var1 (cond-bucle FALSE) (estado comprobar-cond-bucle)) ) ; ######################################################################################## ##### (deffunction MAIN::comprueba-no-importa (?respuesta-atr) (if (symbolp respsnoimp) then (close respsnoimp) ) (if (not (open "respnoimp.txt" respsnoimp "r")) then (return FALSE) ) (bind ?linea (readline respsnoimp)) (bind ?encontrado FALSE) (while (and (eq ?encontrado FALSE) (not (or (eq ?linea EOF) (eq ?linea "EOF") (eq ?linea "*** READ ERROR ***")))) do (if (neq (str-index (lowcase ?linea) ?respuesta-atr) FALSE) then (bind ?encontrado TRUE) ) (bind ?linea (readline respsnoimp)) ) (close respsnoimp) (eval ?encontrado) ) ; ######################################################################################## ##### (defrule MAIN::comprueba-cond-bucle ?var1 <- (venta (cond-bucle ?cond) (estado comprobar-cond-bucle)) => (if ?cond then (modify ?var1 (estado preguntar-atributo) (tipoatr tamanno) (respuestaatributo "")) else (modify ?var1 (estado obtener-mas-caro)) )

) ; ######################################################################################## ##### ; BUCLE DE PREGUNTAS: ; ######################################################################################## ##### (defrule MAIN::obtener-atributo ?var1 <- (venta (estado preguntar-atributo) (tipoatr ?atributo)) => (if (eq ?atributo tamanno) then (printout t crlf "¿Cómo de grande es el animal que busca?" crlf crlf "[(Muy pequenno) (Pequenno) (Mediano) (Grande) (No sé / No importa)]:" crlf ">> ") ) (if (eq ?atributo caracter) then (printout t crlf "¿Qué carácter quiere que tenga su animal?" crlf crlf "[(Tranquilo) (Alegre) (Carinnoso) (Agresivo) (No sé / No importa)]:" crlf ">> ") ) (if (eq ?atributo color) then (printout t crlf "¿De qué color quiere que sea su animal?" crlf crlf "[(Negro) (Pardo) (Gris) (Blanco) (Amarillo) (Azul) (Verde) (Rojizo) (No sé / No importa)]:" crlf crlf "(NOTA: Lógicamente no tenemos todos los animales en todos los colores)" crlf ">> ") ) ; FUERA DE LOS IF: (bind ?respuesta (readline stdin)) (modify ?var1 (respuesta-atributo ?respuesta) (estado comprobar-respuesta)) ) ; ######################################################################################## ##### (defrule MAIN::comprueba-respuesta ?var1 <- (venta (estado comprobar-respuesta) (tipoatr ?atributo) (respuesta-atributo ?respuesta)) ?var2 <- (solicitud) => (printout t crlf "Comprobando existencias..." crlf) (bind ?respuestavalida FALSE) (if (eq ?atributo tamanno) then (if (eq (lowcase ?respuesta) "muy pequenno" ) then (bind ?respuestavalida TRUE) (modify ?var2 (tamanno muypequenno)) else (if (eq (lowcase ?respuesta) "pequenno" ) then (bind ?respuestavalida TRUE) (modify ?var2 (tamanno pequenno)) else (if (eq (lowcase ?respuesta) "mediano" ) then (bind ?respuestavalida TRUE) (modify ?var2 (tamanno mediano)) else (if (eq (lowcase ?respuesta) "grande" ) then (bind ?respuestavalida TRUE) (modify ?var2 (tamanno grande)) else (if (comprueba-no-importa ?respuesta ) then (bind ?respuestavalida TRUE) (modify ?var2 (tamanno noespecifica)) ))))) else (if (eq ?atributo caracter) then (if (eq (lowcase ?respuesta) "tranquilo" ) then (bind ?respuestavalida TRUE) (modify ?var2 (caracter tranquilo)) else (if (eq (lowcase ?respuesta) "alegre" ) then (bind ?respuestavalida TRUE)

(modify ?var2 (caracter alegre)) else (if (eq (lowcase ?respuesta) "carinnoso" ) then (bind ?respuestavalida TRUE) (modify ?var2 (caracter carinnoso)) else (if (eq (lowcase ?respuesta) "agresivo" ) then (bind ?respuestavalida TRUE) (modify ?var2 (caracter agresivo)) else (if (comprueba-no-importa ?respuesta ) then (bind ?respuestavalida TRUE) (modify ?var2 (caracter noespecifica)) ))))) else (if (eq ?atributo color) then (if (eq (lowcase ?respuesta) "negro" ) then (bind ?respuestavalida TRUE) (modify ?var2 (color negro)) else (if (eq (lowcase ?respuesta) "pardo" ) then (bind ?respuestavalida TRUE) (modify ?var2 (color pardo)) else (if (eq (lowcase ?respuesta) "blanco" ) then (bind ?respuestavalida TRUE) (modify ?var2 (color blanco)) else (if (eq (lowcase ?respuesta) "gris" ) then (bind ?respuestavalida TRUE) (modify ?var2 (color gris)) else (if (eq (lowcase ?respuesta) "amarillo" ) then (bind ?respuestavalida TRUE) (modify ?var2 (color amarillo)) else (if (eq (lowcase ?respuesta) "verde" ) then (bind ?respuestavalida TRUE) (modify ?var2 (color verde)) else (if (eq (lowcase ?respuesta) "rojizo" ) then (bind ?respuestavalida TRUE) (modify ?var2 (color rojizo)) else (if (eq (lowcase ?respuesta) "azul" ) then (bind ?respuestavalida TRUE) (modify ?var2 (color azul)) else (if (comprueba-no-importa ?respuesta ) then (bind ?respuestavalida TRUE) (modify ?var2 (color noespecifica)) else (bind ?respuestavalida FALSE) )))))))))))) ; FUERA DE LOS IF: (if (eq ?respuestavalida TRUE) then (modify ?var1 (estado comprobar-aves)) else (printout t crlf "Lo siento, no le he entendido bien:" crlf) (modify ?var1 (estado preguntar-atributo)) ) ) ; ######################################################################################## ##### (defrule MAIN::comprueba-aves (declare (salience 1000)) ?var1 <- (venta (tipoatr ?atributo) (estado comprobar-aves) (respuesta-atributo ?respuesta)) (solicitud (caracter ?carsol) (tamanno ?tamsol) (color ?colsol)) ?var2 <- (ani (tipoani ave) (caracter ?carani) (tamanno ?tamani) (color ?colani)) => (if (eq ?atributo caracter) then (if (and (neq ?carani ?carsol) (neq noespecifica ?carsol))

then (retract ?var2) ) ) (if (eq ?atributo tamanno) then (if (and (neq ?tamani ?tamsol) (neq noespecifica ?tamsol)) then (retract ?var2) ) ) (if (eq ?atributo color) then (if (and (neq ?colani ?colsol) (neq noespecifica ?colsol)) then (retract ?var2) ) ) ) ; ######################################################################################## ##### (defrule MAIN::fin-aves ?var1 <- (venta (estado comprobar-aves)) => (modify ?var1 (estado comprobar-peces)) ) ; ######################################################################################## ##### (defrule MAIN::comprueba-peces (declare (salience 1000)) ?var1 <- (venta (tipoatr ?atributo) (estado comprobar-peces) (respuesta-atributo ?respuesta)) (solicitud (caracter ?carsol) (tamanno ?tamsol) (color ?colsol)) ?var2 <- (ani (tipoani pez) (caracter ?carani) (tamanno ?tamani) (color ?colani)) => (if (eq ?atributo caracter) then (if (and (neq ?carani ?carsol) (neq noespecifica ?carsol)) then (retract ?var2) ) ) (if (eq ?atributo tamanno) then (if (and (neq ?tamani ?tamsol) (neq noespecifica ?tamsol)) then (retract ?var2) ) ) (if (eq ?atributo color) then (if (and (neq ?colani ?colsol) (neq noespecifica ?colsol)) then (retract ?var2) ) ) ) ; ######################################################################################## ##### (defrule MAIN::fin-peces ?var1 <- (venta (estado comprobar-peces)) => (modify ?var1 (estado comprobar-mamiferos)) ) ; ######################################################################################## ##### (defrule MAIN::comprueba-mamiferos (declare (salience 1000)) ?var1 <- (venta (tipoatr ?atributo) (estado comprobar-mamiferos) (respuesta-atributo ?respuesta)) (solicitud (caracter ?carsol) (tamanno ?tamsol) (color ?colsol)) ?var2 <- (ani (tipoani mamifero) (caracter ?carani) (tamanno ?tamani) (color ?colani)) => (if (eq ?atributo caracter) then (if (and (neq ?carani ?carsol) (neq noespecifica ?carsol)) then (retract ?var2)

) ) (if (eq ?atributo tamanno) then (if (and (neq ?tamani ?tamsol) (neq noespecifica ?tamsol)) then (retract ?var2) ) ) (if (eq ?atributo color) then (if (and (neq ?colani ?colsol) (neq noespecifica ?colsol)) then (retract ?var2) ) ) ) ; ######################################################################################## ##### (defrule MAIN::fin-mamiferos (declare (salience -1000)) ?var1 <- (venta (estado comprobar-mamiferos) (tipoatr ?atributo)) => (if (eq ?atributo tamanno) then (modify ?var1 (tipoatr caracter) (estado preguntar-atributo))) (if (eq ?atributo caracter) then (modify ?var1 (tipoatr color) (estado preguntar-atributo))) (if (eq ?atributo color) then (modify ?var1 (estado obtener-mas-caro)) ; _Ya se han comprobado todos los atributos... ) ) ; ######################################################################################## ##### ; FIN BUCLE DE PREGUNTAS. ; ######################################################################################## ##### (defrule MAIN::obten-mas-caro (declare (salience 1000)) (venta (estado obtener-mas-caro)) ?var1 <- (ani (tipoani ?tipo) (precio ?prec) (caracter ?car) (tamanno ?tam) (color ?col) (especie ?esp)) ?var2 <- (animal-seleccionado (precio ?coste)) => (if (< ?coste ?prec) then (modify ?var2 (tipoani ?tipo) (precio ?prec) (caracter ?car) (tamanno ?tam) (color ?col) (especie ?esp)) else (retract ?var1) ) ) ; ######################################################################################## ##### (defrule MAIN::obtenido-mas-caro ?var1 <- (venta (estado obtener-mas-caro)) => (modify ?var1 (estado comprobacion-venta)) ) ; ######################################################################################## #####

(defrule MAIN::comprobar-venta ?var1 <- (venta (estado comprobacion-venta)) ?var2 <- (animal-seleccionado (especie ?esp)) => (if (eq ?esp noespecifica) then (modify ?var1 (estado despedir-sin-venta)) else (modify ?var1 (estado vender)) ) ) ; ######################################################################################## ##### (defrule MAIN::vender-animal ?var1 <- (venta (estado vender)) ?var2 <- (animal-seleccionado (tipoani ?tipo) (precio ?prec) (caracter ?car) (tamanno ?tam) (color ?col) (especie ?esp)) => (printout t crlf "Creo que tenemos exactamente lo que busca." crlf) (printout t "El animal que hemos seleccionado para usted es:" crlf crlf) (printout t "###################" crlf) (printout t "ESPECIE: " ?esp crlf) (printout t "###################" crlf) (printout t "TIPO: " ?tipo crlf) (printout t "CARÁCTER: " ?car crlf) (printout t "TAMAÑO: " ?tam crlf) (printout t "COLOR: " ?col crlf) (printout t crlf "PRECIO: " ?prec crlf) (printout t "###################" crlf crlf) (modify ?var1 (estado despedir-con-venta)) ) ; ######################################################################################## ##### (defrule MAIN::despide-con-venta ?var1 <- (venta (estado despedir-con-venta)) => (printout t crlf "###############################" crlf crlf) (printout t "Ha sido un placer ayudarle." crlf) (printout t "Le aseguro que ha hecho usted una buena compra." crlf) (printout t "Se lleva uno de nuestros mejores ejemplares." crlf crlf) (printout t "Vuelva cuando quiera." crlf crlf) (printout t "###############################" crlf crlf) (printout t "FIN DEL PROGRAMA." crlf crlf); ) ; ######################################################################################## ##### (defrule MAIN::despide-sin-venta ?var1 <- (venta (estado despedir-sin-venta)) => (printout t crlf "###############################" crlf crlf) (printout t "Sentimos no poder ayudarle:" crlf) (printout t "No disponemos de ningún animal con esas características." crlf crlf) (printout t "Vuelva cuando quiera." crlf crlf) (printout t "###############################" crlf crlf) (printout t "FIN DEL PROGRAMA." crlf crlf); ) ; ######################################################################################## ##### ; END OF CODE ; ######################################################################################## #####

respnoimp.TXT

no no se no sé nose nosé no lo se no lo sé nolose nolosé aun no lo se aún no lo se aun no lo sé aún no lo sé no lo he pensado no lo había pensado cualquiera cualquiera de esos cualquiera de esas no importa no me importa no lo he decidido ni idea no tengo ni idea no tengo ninguna idea ninguno ninguna ninguno de esos ninguna de esas nada nada de eso ese no

eso no esa no esos no esas no decide tú decida usted el que quieras el que quiera el que usted quiera el que tu quieras el que tú quieras la que quieras la que quiera la que usted quiera la que tu quieras la que tú quieras lo que quieras lo que quiera lo que usted quiera lo que tu quieras lo que tú quieras

BIBLIOGRAFÍA
Se incluye a continuación una selección de referencias bibliográficas consultadas por el alumno para la realización del presente trabajo y el estudio de la asignatura.

    

 

 

      

[1] “Elements of artificial intelligence – an introduction using LISP”, Steven L. Tanimoto, Computer Science Press (1987) [2] “Algorithmic Algebra”, Bhubaneswar Mishra. Springer-Verlag (1993) [3] “Gröbner bases: A computational approach to commutative algebra”, Thomas Becker, Volker Weispfenning et Heinz Kredel. Springer-Verlag (1993) [4] Apuntes de la asignatura: Ingeniería de Conocimiento (Univ. León, 1999-2000) *5+ “Railway interlocking systems and Gröbner bases”, Eugenio Roanes Lozano, Eugenio Roanes Macías & Luis M. Laita. IMACS/Elsevier Science B. V. (2000). www.elsevier.nl/locate/matcom [6] “Essential Maple 7: An introduction for scientific programmers”, Robert M. Corless, Springer (2002) *7+ “Cálculos efectivos en lógica proposicional booleana interpretada como un anillo de clases residuals (polynomial) sobre ℤ𝟐 ”, Eugenio Roanes Lozano, Eugenio Roanes Macías & Luis M. Laita. Boletín Nº 65 de la sociedad <<Puig Adam>> de profesores de matemáticas (Octubre de 2003). [8] “Aprenda Maple 9.5 como si estuviera en primero”, VV.AA. Tecnum (2004) [9] “The geometry of algebraic systems and their exact solving using Gröbner bases”, Eugenio Roanes Lozano, Eugenio Roanes Macías y Luis M. Laita. Computing Prescriptions – IEEE CS & AIP (2004) [10] “Some applications of Gröbner bases”, Eugenio Roanes Lozano, Eugenio Roanes Macías y Luis M. Laita. Computing Prescriptions – IEEE CS & AIP (2004) [11] “Maple 10 user manual: harnessing the power of mathematics”, VV.AA. Maplesoft (2005) [12] “Maple introductory programming guide”, VV.AA. Maplesoft (2005) [13] “Maple advanced programming guide”, VV.AA., Maplesoft (2005) [14] “Introducción a Maple”, Mª Teresa Pérez Rodríguez y Óscar Arratia García. UOC – e-Math (2006) [15] Apuntes de la asignatura: AACIA (UCM, 2006-2007) [16] “Algunas aplicaciones de las bases de Gröbner en Inteligencia Artificial”, Eugenio Roanes Lozano – I jornadas de lógica, computación

 

e I.A. en homenaje al profesor Luis M. Laita, Sevilla (2008) [17] “Gröbner bases, coding and cryptography”, VV.AA. Springer (2009) [18] “Pictures at a DERIVE’s exhibition” (interpreting DERIVE’s SOLVE command)”, Eugenio Roanes Lozano. Departamento de Algebra - UCM. http://www.mat.ucm.es/~imgomezc/almacen/PIMCD_463/Materiales_Secund aria_2/pdf/Roanes.pdf

Crédito fotografías:
 Sistema de control semafórico: http://abigailtaller3uajms.blogspot.com/2009/04/enfoque-practico-de-la-informaticaen.html Avenida de América: http://www.flickr.com/photos/alair2525/2853979984/sizes/l/ Semáforo Montevideo: http://www.flickr.com/photos/juanchoo/2488947101/ Penjat Copenhagen: http://www.flickr.com/photos/natgg/2467746175/ Light men: http://www.flickr.com/photos/hectorgomez/3374149103/ Dos y dos: http://www.flickr.com/photos/rociontheroof/2091987420/ Niño en la jungla: http://www.flickr.com/photos/rociontheroof/2091200715/ Sacked for being a fish: http://www.flickr.com/photos/mworrell/116105712/ Leaping lizards: http://www.flickr.com/photos/corruptkitten/1550218600/ Buying pet fish: http://www.flickr.com/photos/mikesten/67736560/ Pizarra: http://www.flickr.com/photos/mr_peebles/2742578710/

         

http://creativecommons.org/licenses/by-nc-sa/2.5/