Guia Sistema Experto Win_prolog

77
FUNDACIÓN UNIVERSITARIA KONRAD LORENZ FACULTAD DE MATEMÁTICAS E INGENIERÍAS INGENIERÍA DE SISTEMAS SISTEMAS BASADOS EN EL CONOCIMIENTO I GUIA PARA LA CONSTRUCCIÓN DE SISTEMAS BASADOS EN EL CONOCIMIENTO A PARTIR DE UNA TABLA Y A PARTIR DE UN ÁRBOL DE DECISIÓN. Pervys Rengifo Rengifo Esta guía se preparó como parte del apoyo didáctico que se ofrece a los estudiantes de ingeniería de sistemas de la Fundación Universitaria Konrad Lorenz, dentro del curso de Sistemas Basados en el Conocimiento I. Los procedimientos básicos para la construcción de sistemas basados en el conocimiento se hará alrededor de unos ejemplos que ilustran claramente cómo hacer esta construcción para los casos en que el conocimiento esté representado o estructurado como una tabla o como un árbol de decisión: CASO 1: EL CONOCIMIENTO ESTÁ REPRESENTADO COMO UNA TABLA DE DECISIÓN. EJEMPLO: DE QUÉ ANIMAL SE TRATA? A partir de la siguiente tabla de datos construya un sistema basado en el conocimiento que permita determinar de qué animal se trata, a partir de la clase y la alimentación del mismo. El conocimiento disponible está embebido en la siguiente tabla: ANIMAL CLASE ALIMENTACION 'LEON' Mamífero carnivoro 'MUSARAÑA' Mamífero insectivoro 'CABALLO' Mamífero herbivoro 'COCODRILO' Reptil carnivoro 'CAMALEON' Reptil insectivoro 'TORTUGA DE TIERRA’ Reptil herbivoro 'AGUILA' Ave carnivoro 'GOLONDRINA' Ave insectivoro 'PERDIZ' Ave herbivoro FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

description

Esta guía se preparó para el curso de sistemas basados en el conocimiento del programa de Ingeniería de Sistemas de la FUNDACIÓN UNIVERSITARIA KONRAD LORENZ http://www.fukl.edu.co

Transcript of Guia Sistema Experto Win_prolog

Page 1: Guia Sistema Experto Win_prolog

FUNDACIÓN UNIVERSITARIA KONRAD LORENZFACULTAD DE MATEMÁTICAS E INGENIERÍAS

INGENIERÍA DE SISTEMAS SISTEMAS BASADOS EN EL CONOCIMIENTO I

GUIA PARA LA CONSTRUCCIÓN DE SISTEMAS BASADOS EN EL CONOCIMIENTO A PARTIR DE UNA TABLA Y A PARTIR DE UN ÁRBOL

DE DECISIÓN.Pervys Rengifo Rengifo

Esta guía se preparó como parte del apoyo didáctico que se ofrece a los estudiantes de ingeniería de sistemas de la Fundación Universitaria Konrad Lorenz, dentro del curso de Sistemas Basados en el Conocimiento I.Los procedimientos básicos para la construcción de sistemas basados en el conocimiento se hará alrededor de unos ejemplos que ilustran claramente cómo hacer esta construcción para los casos en que el conocimiento esté representado o estructurado como una tabla o como un árbol de decisión:

CASO 1: EL CONOCIMIENTO ESTÁ REPRESENTADO COMO UNA TABLA DE DECISIÓN.EJEMPLO: DE QUÉ ANIMAL SE TRATA?A partir de la siguiente tabla de datos construya un sistema basado en el conocimiento que permita determinar de qué animal se trata, a partir de la clase y la alimentación del mismo. El conocimiento disponible está embebido en la siguiente tabla:

ANIMAL CLASE ALIMENTACION'LEON' Mamífero carnivoro'MUSARAÑA' Mamífero insectivoro'CABALLO' Mamífero herbivoro'COCODRILO' Reptil carnivoro'CAMALEON' Reptil insectivoro'TORTUGA DE TIERRA’ Reptil herbivoro'AGUILA' Ave carnivoro'GOLONDRINA' Ave insectivoro'PERDIZ' Ave herbivoro

Paso 1: Construya la base de conocimiento en Prolog, utilizando lógica de predicados

animal('LEON'):-clase(mamifero),alimentacion(carnivoro).Quiere decir: Un animal es un tigre si es mamífero y carnívoro.

animal('MUSARAÑA'):-clase(mamifero),alimentacion(insectivoro).animal('CABALLO'):-clase(mamifero),alimentacion(herbivoro).animal('COCODRILO'):-clase(reptil),alimentacion(carnivoro).animal('CAMALEON'):-clase(reptil),alimentacion(insectivoro).animal('TORTUGA DE TIERRA'):-clase(reptil),alimentacion(herbivoro).animal('AGUILA'):-clase(ave),alimentacion(carnivoro).animal('GOLONDRINA'):-clase(ave),alimentacion(insectivoro).animal('PERDIZ'):-clase(ave),alimentacion(herbivoro).

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 2: Guia Sistema Experto Win_prolog

Predicados Prolog Análisisanimal('LEON'):-clase(mamifero),alimentacion(carnivoro).

El león es un mamífero que se alimenta de carne o de otros animales

animal('MUSARAÑA'):-clase(mamifero),alimentacion(insectivoro).

La musaraña es un mamífero que se alimenta de insectos

animal('CABALLO'):-clase(mamifero),alimentacion(herbivoro).

El caballo es un mamífero que se alimenta de vegetales

animal('COCODRILO'):-clase(reptil),alimentacion(carnivoro).

El cocodrilo es un reptil que se alimenta de carne o de otros animales

animal('CAMALEON'):-clase(reptil),alimentacion(insectivoro).

El camaleón es un reptil que se alimenta de insectos

animal('TORTUGA DE TIERRA'):-clase(reptil),alimentacion(herbivoro).

Este predicado indica que no hay un reptil que se alimente con sólo vegetales

animal('AGUILA'):-clase(ave),alimentacion(carnivoro).

El águila es un ave que se alimenta de carne.

animal('GOLONDRINA'):-clase(ave),alimentacion(insectivoro).

La golondrina es un ave que se alimenta de insectos.

animal('PERDIZ'):-clase(ave),alimentacion(herbivoro).

La perdiz es un ave que se alimenta de vegetales.

Paso 2: Construya las preguntas en donde solicitará al usuario las características del animal que desea clasificar:pregunta1:- write(' El grupo al que pertenece el animal es:'),nl,nl, write('1. Mamifero.'),nl, write('2. Reptil.'),nl, write('3. Ave.'),nl, read(N), clasificar1(N).Construya predicados para proceder de acuerdo con la respuesta a la pregunta 1:clasificar1(1):-assert(clase(mamifero)),!.clasificar1(2):-assert(clase(reptil)),!.clasificar1(3):-assert(clase(ave)),!.clasificar1(_):-pregunta1,!.

pregunta2:- write(' Segun tipo de alimentacion puede ser:'),nl,nl, write('1. Carnivoro.'),nl, write('2. Insectivoro.'),nl, write('3. Herbivoro.'),nl, read(N2),

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 3: Guia Sistema Experto Win_prolog

clasificar2(N2).Construya predicados para proceder de acuerdo con la respuesta a la pregunta 2:clasificar2(1):-assert(alimentacion(carnivoro)),!.clasificar2(2):-assert(alimentacion(insectivoro)),!.clasificar2(3):-assert(alimentacion(herbivoro)),!.clasificar2(_):-pregunta2,!.

Paso 3: Defina un predicado que determine la clasificación de acuerdo con las respuestas del usuario:

clasificar:- animal(M), write('El animal puede ser : '),nl, write(' '),write(M),nl,nl.

Paso 4: Defina el predicado que permita ejecutar todo el programa:empezar:- pregunta1, pregunta2, consultar,!.

Ahora, que hacer si usted quiere proveer al usuario la posibilidad de hacer otra consulta:Paso 1: Limpie todas las acciones del predicado assert, para esto puede definir un predicado de nombre purgar

limpiar:-retract(clase(_)), retract(alimentacion(_)),!.

Paso 2: Defina un predicado que permita continuar si el usuario responde adecuadamente:continue('s'):-empezar,!.continue('S'):-empezar,!.continue('n'):-continue('N').continue('N'):-write(' NOS AGRADÓ AYUDARTE '),nl, write('............HASTA PRONTO............').

Paso 3: Defina el predicado que pregunte al usuario si desea continuar.

pregunta:-nl,nl, write('Desea continuar s/n : '), read(X), continue(X).

Paso 4: redefina el predicado consultar para que responda la clasificación y pregunte al usuario si desea continuar:clasificar:- animal(M), write('El animal puede ser : '),nl, write(' '),write(M),nl,nl,

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 4: Guia Sistema Experto Win_prolog

limpiar, pregunta.

FINALMENTE EL PROGRAMA QUEDARÍA ASI:

animal('LEON'):-clase(mamifero),alimentacion(carnivoro).animal('MUSARAÑA'):-clase(mamifero),alimentacion(insectivoro).animal('CABALLO'):-clase(mamifero),alimentacion(herbivoro).animal('COCODRILO'):-clase(reptil),alimentacion(carnivoro).animal('CAMALEON'):-clase(reptil),alimentacion(insectivoro).animal('TORTUGA DE TIERRA'):-clase(reptil),alimentacion(herbivoro).animal('AGUILA'):-clase(ave),alimentacion(carnivoro).animal('GOLONDRINA'):-clase(ave),alimentacion(insectivoro).animal('PERDIZ'):-clase(ave),alimentacion(herbivoro).

empezar:- pregunta1, pregunta2, clasificar,!.

pregunta1:- write(' La clase a la que pertenece el animal es:'),nl,nl, write('1. Mamifero.'),nl, write('2. Reptil.'),nl, write('3. Ave.'),nl, read(N), clasificar1(N).

clasificar1(1):-assert(clase(mamifero)),!.clasificar1(2):-assert(clase(reptil)),!.clasificar1(3):-assert(clase(ave)),!.clasificar1(_):-pregunta1,!.

pregunta2:- write(' Segun tipo de alimentacion puede ser:'),nl,nl, write('1. Carnivoro.'),nl, write('2. Insectivoro.'),nl, write('3. Herbivoro.'),nl, read(N2), clasificar2(N2).

clasificar2(1):-assert(alimentacion(carnivoro)),!.clasificar2(2):-assert(alimentacion(insectivoro)),!.clasificar2(3):-assert(alimentacion(herbivoro)),!.clasificar2(_):-pregunta2,!.

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 5: Guia Sistema Experto Win_prolog

limpiar:-retract(clase(_)), retract(alimentacion(_)),!.

continue('s'):-empezar,!.continue('S'):-empezar,!.continue('n'):-continue('N').continue('N'):-write(' NOS AGRADÓ AYUDARTE '),nl, write('............HASTA PRONTO............').

clasificar:- animal(M), write('El animal puede ser : '),nl, write(' '),write(M),nl,nl, limpiar, pregunta.

pregunta:-nl,nl, write('Desea continuar s/n : '), read(X), continue(X).

1. El programa empieza cuando en la consola le digitamos

empezar. El símbolo :- se lee “si “ y corresponde a una implicación de derecha a izquierda. Empieza a cargar las preguntas 1 y 2:

empezar:- pregunta1, pregunta2, clasificar,!.

2. El programa muestra al usuario la pregunta y las diferentes

opciones a escoger. En este caso, escribe en pantalla si el animal pertenece al grupo de los mamíferos, reptiles o aves. En cualquier caso, el número que se digite será leído y guardado en una variable N.

pregunta1:- write(' El grupo al que pertenece el animal es:'),nl,nl, write('1. Mamifero.'),nl, write('2. Reptil.'),nl, write('3. Ave.'),nl, read(N), clasificar1(N).

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 6: Guia Sistema Experto Win_prolog

3. El programa al leer el número digitado por el usuario lee si es un 1 guarda la clase mamífero, si es 2 guarda la clase reptil, si es 3 guarda la clase ave y si digita cualquier otro número presenta de nuevo la pregunta 1:

clasificar1(1):-assert(clase(mamifero)),!.clasificar1(2):-assert(clase(reptil)),!.clasificar1(3):-assert(clase(ave)),!.clasificar1(_):-pregunta1,!.

Se pueden incluir más cláusulas a la base de datos mediante el predicado assert. Es decir, que para cada número que ingrese el usuario se le asigna una clase.

4. El programa a continuación muestra al usuario las diferentes opciones a escoger con la pregunta 2. En este caso, escribe en pantalla si el animal según el tipo de alimentación puede ser carnívoro, insectívoro o herbívoro. Igual al caso anterior, leerá el número digitado y lo guardará en la variable N2.

pregunta2:-

write(' Segun tipo de alimentacion puede ser:'),nl,nl, write('1. Carnivoro.'),nl, write('2. Insectivoro.'),nl, write('3. Herbivoro.'),nl, read(N2), clasificar2(N2).

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 7: Guia Sistema Experto Win_prolog

6. El programa al leer el número digitado por el usuario lee si es un 1 guarda el tipo carnívoro, si es 2 guarda el tipo insectívoro, si es 3 guarda el tipo herbívoro y si digita cualquier otro numero presenta de nuevo la pregunta 2

clasificar2(1):-assert(alimentacion(carnivoro)),!.clasificar2(2):-assert(alimentacion(insectivoro)),!.clasificar2(3):-assert(alimentacion(herbivoro)),!.clasificar2(_):-pregunta2,!.

7. El programa empieza a hacer búsquedas de que animal cumple con las características dadas por el usuario según la clase y la alimentación y hace una eliminación de cláusulas de predicados.

limpiar:-retract(clase(_)), retract(alimentacion(_)),!.

8. Encuentra el animal y lo guarda en la variable M y luego lo muestra al usuario el animal encontrado.

clasificar:- animal(M), write('El animal puede ser : '),nl, write(' '),write(M),nl,nl, limpiar, pregunta.

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 8: Guia Sistema Experto Win_prolog

9. El programa pregunta si desea continuar. Si el usuario le dice que si se devuelve a hacer la pregunta No. 1 y así sucesivamente hasta que a la pregunta Desea Continuar se le dé que no.

pregunta:-nl,nl, write('Desea continuar s/n : '), read(X), continue(X).

continue('s'):- continue('S').continue('S'):-empezar,!.continue('n'):-continue('N').continue('N'):-write(' NOS AGRADÓ AYUDARTE'),nl, write('............HASTA PRONTO............').

Funciones desconocida:

Añadiendo cláusulas

Para insertar cláusulas de un predicado dinámico existe una familia de predicados ISO-standard, la familia assert, consistente en los siguientes predicados:

asserta/1

Inserta una nueva cláusula como si se hubiera escrito al principio del programa.

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 9: Guia Sistema Experto Win_prolog

assertz/1 Inserta una nueva cláusula como si se hubiera escrito al final del programa.

assert/1 Idéntico a asserta/1.

Eliminando cláusulas

Análogamente, es posible eliminar cláusulas de predicados dinámicos mediante la familia de predicados retract consistente en:

retract/1 Elimina únicamente la primera cláusula que unifique con el argumento. Siempre se elimina por el principio del programa.

rectractall/1

Elimina todas las cláusulas que unifiquen con el argumento.

AÑADIENDO INTERFACE GRÁFICA CON WINPROLOG 4.2

Win-Prolog, permite la creación de interfaces gráfica de usuario, tanto desde el código como a través de una utilidad ayuda a construir de forma más sencilla estas interfaces. A esta utilidad se puede acceder a través de la siguiente ruta:

Con lo cual aparecerá una ventana como la siguiente:

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 10: Guia Sistema Experto Win_prolog

En la ventana de controles, se pueden seleccionar el tipo de control que se desea crear y luego se ubica control en la ventana de la derecha, dimensionándolo con el ratón

Después de esto se obtendría una ventana con la siguiente apariencia

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 11: Guia Sistema Experto Win_prolog

Al hacer doble clic en el control (en este caso un botón), se abre una pantalla de configuración básica (en este caso se le va a cambiar la leyenda que aparece en el control, por Prueba 1.

Cuando ya se tenga listo el paquete de controles, se hace clic en export, obteniendo un texto con un conjunto de instrucciones que se pegaría al código de Prolog que se esté implementando y se adaptaría según las necesidades que se tengan.

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 12: Guia Sistema Experto Win_prolog

Si desea un listado de los predicados usados en este tutorial puede consultar el apéndice 1, al final de este documento.

A continuación se muestra un ejemplo del programa anterior utilizando una interface gráfica de usuario:animal('LEON'):-clase(mamifero), alimentacion(carnivoro),!.

animal('MUSARAÑA'):-clase(mamifero), alimentacion(insectivoro),!.

animal('CABALLO'):-clase(mamifero), alimentacion(herbivoro),!.

animal('COCODRILO'):-clase(reptil), alimentacion(carnivoro),!.

animal('CAMALEÓN'):-clase(reptil), alimentacion(insectivoro),!.

animal('NO EXISTE EN LA BASE DE CONOCIMIENTO'):-clase(reptil), alimentacion(herbivoro),!.

animal('AGUILA'):-clase(ave), alimentacion(carnivoro),!.

animal('GOLONDRINA'):-clase(ave), alimentacion(insectivoro),!.

animal('PERDIZ'):-clase(ave), alimentacion(herbivoro),!.

inicio:-retractall(clase(_)), retractall(alimentacion(_)),

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 13: Guia Sistema Experto Win_prolog

bienvenida, empezar.

empezar:-pregunta1, % empezar ejecuta las funciones de pregunta1, pregunta2 pregunta2, % y hacer la consulta. consultar,!.

pregunta1:-combo_select(`El grupo al que pertenece el animal es:`, [`Mamífero`,`Reptil`,`Ave`], S ),grupo(S),!. % y se llama una funcion pregunta con parametro N, y segun el numero ingresado, se ejecuta alguna de las siguientesgrupo(`Mamífero`):-assert(clase(mamifero)),!. % si N es 1, se ingresa a la base del conocimiento, el predicado clase(mamifero)grupo(`Reptil`):-assert(clase(reptil)),!. % igual para el 2, que ingresa clase(reptil),grupo(`Ave`):-assert(clase(ave)),!. % y para 3.grupo(_):-pregunta1,!.

pregunta2:-combo_select(`Segun tipo de alimentacion puede ser:`, [`Carnívoro`,`Insectívoro`,`Herbivoro`], T ),tipo(T),!. tipo(`Carnívoro`):-assert(alimentacion(carnivoro)),!. % si la opcion fue la 1, se ingresa a la base de conocimiento alimentacion(carnivoro)tipo(`Insectívoro`):-assert(alimentacion(insectivoro)),!. % con el 2, alimentacion(carnivoro)tipo(`Herbivoro`):-assert(alimentacion(herbivoro)),!. % y con el 3 se ingresa alimentacion(herbivoro)tipo(_):-pregunta2,!.

limpiar_base:-retract(clase(_)), % limpiar_base limpia la base de lo ingresado por las opciones del usuario, retract(alimentacion(_)),!. % para ejecutar una nueva consulta

continue('yes'):-empezar,!. % dependiendo del parametro, se sigue con otra consulta o se sale.continue('no'):-despedida.

consultar:- animal(M), atom_string( M,Animal), despliega_repuesta(Animal), continuar.

despliega_repuesta(Animal) :- _S1 = [dlg_ownedbydesktop,ws_sysmenu,ws_caption], _S2 = [ws_child,ws_visible,ss_center], _S3 = [ws_child,ws_visible,ws_tabstop,bs_pushbutton], wdcreate( respuesta, `user_dialog`, 235, 43, 402, 160, _S1 ),

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 14: Guia Sistema Experto Win_prolog

wccreate( (respuesta,10000), static, `EL ANIMAL PODRÍA SER`, 20, 10, 370, 20, _S2 ), wccreate( (respuesta,10001), static, Animal, 120, 40, 170, 30, _S2 ), wccreate( (respuesta,1000), button, `ACEPTAR`, 130, 80, 150, 30, _S3 ), wfcreate( foo1, arial, 18, 2 ), wfont( (respuesta,10000), foo1 ), wfont( (respuesta,10001), foo1 ), window_handler( respuesta, bienvenida_handler ), call_dialog( respuesta, R ), wfclose(foo1),wclose(respuesta).

continuar:-message_box( yesno, 'Desea Continuar', A ), continue(A).

despedida:- _S1 = [ws_sysmenu,ws_popup,ws_caption,dlg_ownedbyprolog], _S2 = [ws_child,ws_visible,ss_center], _S3 = [ws_child,ws_visible,ws_tabstop,bs_pushbutton], wdcreate( despedida, `user_dialog`, 235, 43, 533, 358, _S1 ), wccreate( (despedida,10000), static, `Hasta pronto`, 146, 40, 240, 20, _S2 ), wccreate( (despedida,10001), static, `Fue un placer Ayudarte`, 146, 60, 240, 20, _S2 ), wccreate( (despedida,10002), static, `Sistemas Basados en el Conocimiento I`, 117, 90, 300, 20, _S2 ), wccreate( (despedida,10003), static, `Facultad de Matemáticas e Ingenierías`, 117, 110, 300, 20, _S2 ), wccreate( (despedida,10004), static, `FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-FUKL (http://www.fukl.edu)`, 16, 130, 500, 60, _S2 ), wccreate( (despedida,1000), button, `OK`, 226, 190, 80, 20, _S3 ), wcreate((despedida,2),grafix,``,0, 210, 533, 96,16'50000000), wfcreate( foo, arial, 18, 0 ), wfont( (despedida,10000), foo ), wfont( (despedida,10001), foo ), wfont( (despedida,10002), foo ), wfont( (despedida,10003), foo ), wfont( (despedida,10004), foo ), wfont( (despedida,1000), foo ), window_handler( despedida, bienvenida_handler ), call_dialog( despedida, R ), wfclose(foo),gfx_bitmap_close(fukl),gfx_bitmap_close(fukl1),wclose(despedida).

bienvenida :- _S1 = [ws_sysmenu,ws_popup,ws_caption,dlg_ownedbyprolog], _S2 = [ws_child,ws_visible,ss_center], _S3 = [ws_child,ws_visible,ss_left], _S4 = [ws_child,ws_visible,ws_tabstop,bs_pushbutton],

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 15: Guia Sistema Experto Win_prolog

wdcreate( bienvenida, `user_dialog`, 235, 43, 532, 325, _S1 ), wccreate( (bienvenida,10000), static, `FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-FUKL (http://www.fukl.edu)`, 70, 10, 390, 20, _S2 ), wccreate( (bienvenida,10001), static, `FACULTAD DE MATEMÁTICAS E INGENIERÍAS`, 110, 30, 320, 20, _S2 ), wccreate( (bienvenida,10002), static, `SISTEMAS BASADOS EN EL CONOCIMIENTO I`, 110, 50, 320, 20, _S2 ), wccreate( (bienvenida,10003), static, `BIENVENIDOS AL PROGRAMA "ANIMALES"`, 110, 70, 320, 20, _S2 ), wccreate( (bienvenida,10004), static, `EL CUAL, CON UN EJEMPLO SENCILLO, ILUSTRA EL PROCESO`, 60, 90, 420, 20, _S2 ), wccreate( (bienvenida,10005), static, `DE CONSTRUCCIÓN DE UN SISTEMA BASADO EN EL CONOCIMIENTO`, 60, 110, 420, 20, _S2 ), wccreate( (bienvenida,10006), static, `SE TRATA DE DETERMINAR DE QUE ANIMAL SE TRATA, A PARTIR DE`, 60, 130, 420, 20, _S3 ), wccreate( (bienvenida,10007), static, `CIERTAS CARACTERÍSTICAS DEL MISMO`, 60, 150, 420, 20, _S2 ), wccreate( (bienvenida,1000), button, `CONTINUAR`, 210, 180, 130, 30, _S4 ), wcreate((bienvenida,2),grafix,``,0, 210, 533, 96,16'50000000), window_handler( bienvenida, bienvenida_handler ), gfx_bitmap_load(fukl,'fukl.bmp'), gfx_bitmap_load(fukl1,'fukl1.bmp'), call_dialog( bienvenida, R ), wclose(bienvenida).

bienvenida_handler( (Window,2), msg_paint, _, _ ) :- gfx_paint( (Window,2) ), gfx(bitmap(0,0, 533, 96,0,0,fukl1)), gfx_end( (Window,2)). bienvenida_handler( (Window,1000), msg_button, _, cancel ).

combo_select( Pregunta,Items, Selected ) :-_S1 = [ws_sysmenu,ws_popup,ws_caption,dlg_ownedbyprolog], _S2 = [ws_child,ws_visible,ws_tabstop,cbs_dropdown], _S3 = [ws_child,ws_visible,ss_left], _S4 = [ws_child,ws_visible,ws_tabstop,bs_pushbutton], _S5 = [ws_child,ws_visible,ws_border], wdcreate( combo, `user_dialog`, 272, 150, 390, 350, _S1 ), wccreate( (combo,500), combobox, `Combo1`, 100, 60, 170, 150, _S2 ), wccreate( (combo,3), static, Pregunta, 50, 20, 280, 20, _S3 ), wccreate( (combo,1), button, `OK`, 140, 140, 100, 30, _S4 ), wcreate((combo,4),static,`iconbds`,10,10,70,54,16'50000003),

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 16: Guia Sistema Experto Win_prolog

wcreate((combo,2),grafix,``,25, 200, 343, 90,16'50000000), fcreate( combo, [], -2, 0, 0 ), wfcreate( foo, arial, 18, 0 ), wfont( (combo,3), foo ), wfont( (combo,500), foo ), fill_combo( (combo,500), Items ), window_handler( combo, combo_handler ), call_dialog( combo, R ), (R=cancel->Selected=R; (P is R+1,enesimo(Selected,P,Items))), fclose( combo ),wclose(combo),!. combo_handler( (Window,2), msg_paint, _, _ ) :- gfx_paint( (Window,2) ), gfx(bitmap(0,0, 343, 90,0,0,fukl)), %tamaño de la imagen 343x90, iniciada en 0,0 gfx_end( (Window,2)).

% cuando ocurra un mensaje de cierre retorna "cancel"

combo_handler( _, msg_close, _, cancel ).

% cuando se presiona el boton "OK" retorna la seleccion

combo_handler( (Window,1), msg_button, _, Result ) :- get_selected_item( (Window,500), Result ).

% llena el combobox con la lista de items, preseleccionando el primer item

fill_combo( Window, Items ) :-sndmsg( Window, cb_resetcontent, 0, 0, _ ), forall( member( Item, Items ),sndmsg( Window, cb_addstring, 0, Item, _ )), sndmsg( Window, cb_setcursel, 0, 0, _ ).

% Se obtiene la posición-1 del ítem seleccionado

get_selected_item( Window, R ) :- sndmsg( Window, cb_getcursel, 0, 0, R ).

%obtiene el elemento enésimo de una listaenesimo(X,1,[X|_]).enesimo(X,N,[_|L]):-R is N-1, enesimo(X,R,L).

*****************************************************************

Para correr este programa debe descargar el archivo comprimido en la siguiente dirección: http://in.solit.us/archives/download/152660

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 17: Guia Sistema Experto Win_prolog

Lo descomprime en una carpeta y luego lo abre con winprolog(se utilizó la versión 4.2). Estos cuidados se requieren debido a los archivos de imágenes que se cargan al programa: “fukl.bmp” y “fukl1.bmp”, los cuales deben estar en la carpeta local( aunque si se quiere se puede cambiar esta ruta y colocar la ruta en donde se encuentren estos archivos o eliminar el código que hace el llamado a estas imágenes), es decir en la carpeta en donde se cargue el archivo SistemaExpertoFUKL.pl.

Después de abrir este abrir este archivo, proceda a compílarlo:

Corra el programa escribiendo en consola:|?:- inicio.Con lo que aparecerá la pantalla de bienvenida.

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 18: Guia Sistema Experto Win_prolog

Al darle continuar, aparecerá la siguiente ventana:

Se escoge la elección que se desee, para este caso se escogerá reptil:

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 19: Guia Sistema Experto Win_prolog

Luego al hacer clic en OK, aparecerá la ventana de la siguiente pregunta, en la cual se escogió la opción herbívoro:

Con estas respuestas, el programa produce el siguiente resultado:

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 20: Guia Sistema Experto Win_prolog

Al hacer clic en aceptar, el programa preguntará si se desea continuar:

Si se hace clic en “sí”, el programa volverá a presentar las dos preguntas, si le da clic en “no”, el programa se despedirá y saldrá al darle ok.

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 21: Guia Sistema Experto Win_prolog

2. EJEMPLO: RECOMENDACIÓN DE LENTES DE CONTACTOSuponga que se conocen datos sobre el tipo de lentes de contacto recomendadas en función de ciertos variables: edad (3 valores), prescripción (2 valores), existencia de astigmatismo (2 valores) y tasa de producción de lágrimas (2 valores). La tabla que recoge la información disponible es la siguiente:

EDAD_DEL_PACIENTE PRESCRIPCION ASTIGMATISMO TASA_DE_PRODUCCION_LAGRIMAS LENTE_RECOMENDADOJOVEN MIOPIA SI REDUCIDA NO_LENTE_CONTACTOJOVEN MIOPIA SI NORMAL LENTE_CONTACTO_SUAVEJOVEN MIOPIA NO REDUCIDA NO_LENTE_CONTACTOJOVEN MIOPIA NO NORMAL LENTE_CONTACTO_DUROJOVEN HIPERMETROPIA SI REDUCIDA NO_LENTE_CONTACTOJOVEN HIPERMETROPIA SI NORMAL LENTE_CONTACTO_SUAVEJOVEN HIPERMETROPIA NO REDUCIDA NO_LENTE_CONTACTOJOVEN HIPERMETROPIA NO NORMAL LENTE_CONTACTO_DUROPRE_PRESBIOPICO1 MIOPIA SI REDUCIDA NO_LENTE_CONTACTOPRE_PRESBIOPICO MIOPIA SI NORMAL LENTE_CONTACTO_SUAVEPRE_PRESBIOPICO MIOPIA NO REDUCIDA NO_LENTE_CONTACTOPRE_PRESBIOPICO MIOPIA NO NORMAL LENTE_CONTACTO_DUROPRE_PRESBIOPICO HIPERMETROPIA SI REDUCIDA NO_LENTE_CONTACTOPRE_PRESBIOPICO HIPERMETROPIA SI NORMAL LENTE_CONTACTO_SUAVEPRE_PRESBIOPICO HIPERMETROPIA NO REDUCIDA NO_LENTE_CONTACTOPRE_PRESBIOPICO HIPERMETROPIA NO NORMAL NO_LENTE_CONTACTOPRESBIOPICO MIOPIA SI REDUCIDA NO_LENTE_CONTACTOPRESBIOPICO MIOPIA SI NORMAL NO_LENTE_CONTACTOPRESBIOPICO MIOPIA NO REDUCIDA NO_LENTE_CONTACTOPRESBIOPICO MIOPIA NO NORMAL LENTE_CONTACTO_DUROPRESBIOPICO HIPERMETROPIA SI REDUCIDA NO_LENTE_CONTACTOPRESBIOPICO HIPERMETROPIA SI NORMAL LENTE_CONTACTO_SUAVEPRESBIOPICO HIPERMETROPIA NO REDUCIDA NO_LENTE_CONTACTOPRESBIOPICO HIPERMETROPIA NO NORMAL NO_LENTE_CONTACTO

1 PRESBIOPIA

que significa dificultad para enfocar objetos que están cerca y es común en los ancianos.Alteración de la visión asociada a la vejez. En este trastorno existe una mayor rigidez del cristalino que produce dificultad para ver los objetos cercanos.

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 22: Guia Sistema Experto Win_prolog

El objetivo es generar un modelo que se ajuste a los ejemplos de entrenamiento y posteriormente usar el modelo para clasificar un ejemplo nuevo.Si se programa directamente la tabla anterior en Win-Prolog, se obtiene el siguiente código:

lente_recomendado('No formular Lente de Contacto'):- tasa_de_produccion_de_lagrimas(reducida).lente_recomendado('Lente de Contacto Suave'):-edad_del_paciemte(joven), astigmatismo(si), tasa_de_produccion_de_lagrimas(normal).lente_recomendado('Lente de Contacto Suave'):-edad_del_paciemte(pre_presbyopic), astigmatismo(si), tasa_de_produccion_de_lagrimas(normal).lente_recomendado('No formular Lente de Contacto'):-edad_del_paciemte(presbyopic), prescripcion(miopia), astigmatismo(si), tasa_de_produccion_de_lagrimas(normal).lente_recomendado('Lente de Contacto Suave'):-edad_del_paciemte(presbyopic), prescripcion(hipermetropia), astigmatismo(si), tasa_de_produccion_de_lagrimas(normal).lente_recomendado('Lente de Contacto Suave'):-prescripcion(miopia), astigmatismo(no), tasa_de_produccion_de_lagrimas(normal).lente_recomendado('Lente de Contacto Duro'):-edad_del_paciemte(joven), prescripcion(hipermetropia), astigmatismo(no), tasa_de_produccion_de_lagrimas(normal).lente_recomendado('No formular Lente de Contacto'):-edad_del_paciemte(pre_presbyopic), prescripcion(hipermetropia), astigmatismo(no), tasa_de_produccion_de_lagrimas(normal).lente_recomendado('No formular Lente de Contacto'):-edad_del_paciemte(presbyopic), prescripcion(hipermetropia), astigmatismo(no), tasa_de_produccion_de_lagrimas(normal).inicio:-write('Formulacion de lentes de contacto'),nl,nl, pregunta0, pregunta1, pregunta2, pregunta3, conclusion, !.pregunta0:-write('Seleccione las caracteristicas del paciente'),nl,write('Tasa de produccion de Lagrimas'),nl,write(' 1. Normal.'),nl,write(' 2. Reducida.'),nl, read(N), respuesta0(N).respuesta0(1):- assert(tasa_de_produccion_de_lagrimas(normal)),!.respuesta0(2):- assert(tasa_de_produccion_de_lagrimas(reducida)),!.respuesta0(_):- write('Intente de nuevo'), nl, pregunta0.pregunta1:-write('Tiene astigmatismo?'),nl,write(' 1. Si.'),nl,write(' 2. No.'),nl, read(N), respuesta1(N).respuesta1(1):-assert(astigmatismo(si)), !.respuesta1(2):-assert(astigmatismo(no)), !.respuesta1(_):-write('Intente de nuevo'), nl, pregunta1,!.pregunta2:-write('Seleccione la prescripcion del paciente'), nl, write(' 1. Miopia.'), nl, write(' 2. Hipermetropia.'), nl,

read(N), respuesta2(N).respuesta2(1):-assert(prescripcion(miopia)),!.

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 23: Guia Sistema Experto Win_prolog

respuesta2(2):-assert(prescripcion(hipermetropia)),!.respuesta2(_):-write('Intente de nuevo'), nl, pregunta2,!.

pregunta3:-write('Edad del paciente'), nl, write(' 1. Joven.'), nl,write(' 2. Presbiópico.'), nl, write(' 3. Pre - Presbiópico.'), nl,

read(N), respuesta3(N).respuesta3(1):-assert(edad_del_paciente(joven)),!.respuesta3(2):-assert(edad_del_paciente(presbiopico)),!.respuesta3(3):-assert(edad_del_paciente(pre_presbiopico)),!.respuesta3(_):-write('Intente de nuevo'), nl, pregunta3,!.conclusion:-lente_recomendado(Lente), write('Lo recomendado es: '), write(Lente),nl,

retract(edad_del_paciente(_)), retract(prescripcion(_)), retract(tasa_de_produccion_de_lagrimas(_)), retract(astigmatismo(_)), pregunta4.

pregunta4:-nl,nl, write('Desea continuar s/n : '), read(X), continuar(X).continuar('s'):-inicio,!.continuar('S'):-inicio,!.continuar('n'):-write('Hasta Pronto'),nl,nl,!.continuar('N'):-write('Hasta Pronto'),nl,nl,!.

Sin embargo, este programa no explota las regularidades presentes en los datos. Con este propósito se utilizan técnicas de minería de datos que buscan extraer patrones o asociaciones relevantes que permitan hacer representaciones simplificadas o muy sintéticas del conocimiento embebido en la información.Para este caso se utilizará el aprendizaje de árboles de decision para inducir una representación más simplificada del problema. Como apoyo computacional para esta tarea se utilizó el applet “Desición Tree Learning” 2

Este applet, tiene la siguiente apariencia:

2 http://www.c2i.ntu.edu.sg/Courses/AI/CIspace/Version4/dTree/index-2.html

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 24: Guia Sistema Experto Win_prolog

Al hacer clic en “start applet”, aparece la siguiente pantalla:

Luego se va a “edit”-“View Edit Text Representation” como se muestra en la siguiente figura

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 25: Guia Sistema Experto Win_prolog

Resultando la siguiente ventana

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 26: Guia Sistema Experto Win_prolog

Los datos de la tabla se preparan siguiendo el siguiente formato:

T:;EDAD_DEL_PACIENTE;PRESCRIPCION;ASTIGMATISMO;TASA_DE_PRODUCCION_LAGRIMAS;LENTE_RECOMENDADOA:;JOVEN;MIOPIA;SI;REDUCIDA;NO_LENTE_COTACTOA:;JOVEN;MIOPIA;SI;NORMAL;LENTE_CONTACTO_SUAVEA:;JOVEN;MIOPIA;NO;REDUCIDA;NO_LENTE_COTACTOA:;JOVEN;MIOPIA;NO;NORMAL;LENTE_CONTACTO_DUROA:;JOVEN;HIPERMETROPIA;SI;REDUCIDA;NO_LENTE_COTACTOA:;JOVEN;HIPERMETROPIA;SI;NORMAL;LENTE_CONTACTO_SUAVEA:;JOVEN;HIPERMETROPIA;NO;REDUCIDA;NO_LENTE_COTACTOA:;JOVEN;HIPERMETROPIA;NO;NORMAL;LENTE_CONTACTO_DUROA:;PRE_PRESBYOPIC;MIOPIA;SI;REDUCIDA;NO_LENTE_COTACTOA:;PRE_PRESBYOPIC;MIOPIA;SI;NORMAL;LENTE_CONTACTO_SUAVEA:;PRE_PRESBYOPIC;MIOPIA;NO;REDUCIDA;NO_LENTE_COTACTOA:;PRE_PRESBYOPIC;MIOPIA;NO;NORMAL;LENTE_CONTACTO_DUROA:;PRE_PRESBYOPIC;HIPERMETROPIA;SI;REDUCIDA;NO_LENTE_COTACTOA:;PRE_PRESBYOPIC;HIPERMETROPIA;SI;NORMAL;LENTE_CONTACTO_SUAVEA:;PRE_PRESBYOPIC;HIPERMETROPIA;NO;REDUCIDA;NO_LENTE_COTACTOA:;PRE_PRESBYOPIC;HIPERMETROPIA;NO;NORMAL;NO_LENTE_COTACTOA:;PRESBYOPIC;MIOPIA;SI;REDUCIDA;NO_LENTE_COTACTOA:;PRESBYOPIC;MIOPIA;SI;NORMAL;NO_LENTE_COTACTOA:;PRESBYOPIC;MIOPIA;NO;REDUCIDA;NO_LENTE_COTACTOA:;PRESBYOPIC;MIOPIA;NO;NORMAL;LENTE_CONTACTO_DUROA:;PRESBYOPIC;HIPERMETROPIA;SI;REDUCIDA;NO_LENTE_COTACTOA:;PRESBYOPIC;HIPERMETROPIA;SI;NORMAL;LENTE_CONTACTO_SUAVEA:;PRESBYOPIC;HIPERMETROPIA;NO;REDUCIDA;NO_LENTE_COTACTOA:;PRESBYOPIC;HIPERMETROPIA;NO;NORMAL;NO_LENTE_COTACTO

Donde T indica los nombres de las variables, A indica los patrones de entrenamiento y B(aunque no aparece en este ejemplo) indica los patrones de validación.

Los datos en el formato anterior se pegan en la ventana anterior, con lo cual se obtiene la siguiente apariencia:

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 27: Guia Sistema Experto Win_prolog

Al presionar Update, se obtiene una pantalla como la siguiente:

A continuación se hace clic en la pestaña “solve”, como se muestra en la siguiente figura

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 28: Guia Sistema Experto Win_prolog

Luego se elige el criterio para determinar el mejor atributo. En este caso se eligió Ganancia de Información(Information Gain)

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 29: Guia Sistema Experto Win_prolog

A continuación se hace clic en el icono “Auto Create”, para que genere el árbol automáticamente con el criterio de Ganancia de Información

'

Con lo anterior se genera un árbol que tendra la siguiente apariencia:

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 30: Guia Sistema Experto Win_prolog

Si se accede a la ruta “View” + “Autoscale”, la gráfica del árbol se autoescala para que quepa en la ventana de visualización.

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 31: Guia Sistema Experto Win_prolog

En View-Font Size se selecciona un tamaño de letra menor para un mayor ajuste de la gráfica del árbol, la cual se reorganiza mediante el tradicional arrastre y suelte con el ratón. Finalmente se obtiene el siguiente árbol de decisión.

Cada hoja del árbol(las que se presentan con recuadro verde) representa una regla de decisión sintetizada a partir de los datos. Como se puede observar que los 24 patrones originales, se pueden expresar mediante 9 reglas, lo cual revela una compresión de 24:9= 2.7.

Las reglas aprendidas fueron:

1. Si la “TASA DE PRODUCCIÓN DE LÁGRIMAS” es “REDUCIDA”, entonces la recomendación es “NO USAR LENTES DE CONTACTO”.

2. Si la “TASA DE PRODUCCIÓN DE LÁGRIMAS” es “NORMAL” y SI presenta astigmatismo y la edad del paciente es JOVEN, entonces la recomendación es “USAR LENTES DE CONTACTO SUAVES”.

3. Si la “TASA DE PRODUCCIÓN DE LÁGRIMAS” es “NORMAL” y SI presenta astigmatismo y la edad del paciente es “PRE_PRESBYOPIC”, entonces la recomendación es “USAR LENTES DE CONTACTO SUAVES”.

4. Si la “TASA DE PRODUCCIÓN DE LÁGRIMAS” es “NORMAL” y SI presenta astigmatismo y la edad del paciente es “PRESBYOPIC”, y la

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 32: Guia Sistema Experto Win_prolog

prescripción es MIOPIA, entonces la recomendación es “NO USAR LENTES DE CONTACTO”.

5. Si la “TASA DE PRODUCCIÓN DE LÁGRIMAS” es “NORMAL” y SI presenta astigmatismo y la edad del paciente es “PRESBYOPIC”, y la prescripción es HIPERMETROPÍA, entonces la recomendación es “USAR LENTES DE CONTACTO SUAVES”.

6. Si la “TASA DE PRODUCCIÓN DE LÁGRIMAS” es “NORMAL” ” y NO presenta astigmatismo y la prescripción es MIOPIA, entonces la recomendación es “USAR LENTES DE CONTACTO DUROS”.

7. Si la “TASA DE PRODUCCIÓN DE LÁGRIMAS” es “NORMAL” ” y NO presenta astigmatismo y la prescripción es HIPERMETROPÍA, y la edad del paciente es “JOVEN”, entonces la recomendación es “USAR LENTES DE CONTACTO DUROS”.

8. Si la “TASA DE PRODUCCIÓN DE LÁGRIMAS” es “NORMAL” ” y NO presenta astigmatismo y la prescripción es HIPERMETROPÍA, y la edad del paciente es “PRE_PRESBYOPIC”, entonces la recomendación es “NO USAR LENTES DE CONTACTO”.

9. Si la “TASA DE PRODUCCIÓN DE LÁGRIMAS” es “NORMAL” ” y NO presenta astigmatismo y la prescripción es HIPERMETROPÍA, y la edad del paciente es “PRESBYOPIC”, entonces la recomendación es “NO USAR LENTES DE CONTACTO”.

Una vez obtenido el árbol, se definen funciones para cada nodo del árbol. Para este ejemplo se decidió la convención ilustrada en la siguiente gráfica, en la cual se observa que el proceso 0, indaga por la tasa de producción de lágrimas; el proceso 1b, por el astigmatismo; el proceso 2ba, por la edad del paciente; el proceso 2bb, por la prescripción; el proceso 3bac, por prescripción, el cual es diferente al proceso 2bb, a pesar de que ambos hacen la misma pregunta, las decisiones que se toman con la respuesta son diferentes; el proceso 3bbb, por la edad del paciente, el cual es diferente que el proceso 2ba, por las mismas razones esgrimidas antes.

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 33: Guia Sistema Experto Win_prolog

pregunta(1, Respuesta):-combo_select(`TASA DE PRODUCCIÓN DE LÁGRIMAS?`, [`REDUCIDA`,`NORMAL`], Respuesta ).

pregunta(2, Respuesta):-combo_select(`TIENE ASTIGMATISMO?`, [`SI`,`NO`], Respuesta ).

pregunta(3, Respuesta):-combo_select(`QUE PRESCRIPCIÓN TIENE?`, [`MIOPIA`,`HIPERMETROPIA`], Respuesta ).

pregunta(4, Respuesta):-combo_select(`CUAL ES LA EDAD DEL PACIENTE?`, [`JOVEN`,`PRE-PRESBIOPICO`,`PRESBIOPICO`], Respuesta ).

recomendacion_lentes(Clase, Recomendacion):-(Clase=1->Recomendacion='Usar lente de Contacto Suave'; Clase=2-> Recomendacion='Usar lente de Contacto Duro'; Clase=3->Recomendacion='No usar Lente de Contacto'),nl.

empezar:-bienvenida,proceso0.proceso0:- pregunta(1, Respuesta ), (Respuesta=`REDUCIDA`-> proceso_final(3); Respuesta=`NORMAL` -> proceso('1b');inicio).proceso('1b'):-pregunta(2, Respuesta ), (Respuesta= `SI` ->proceso('2ba'); Respuesta= `NO` -> proceso('2bb'); proceso('1b')).proceso('2ba'):-pregunta(4, Respuesta), (Respuesta=`JOVEN`-> proceso_final(1); Respuesta=`PRE-PRESBIOPICO`-> proceso_final(1); Respuesta=`PRESBIOPICO`->proceso('3bac');proceso('2ba')).proceso('2bb'):-pregunta(3, Respuesta ), (Respuesta=`MIOPIA`->proceso_final(2); Respuesta=`HIPERMETROPIA`->proceso('3bbb');proceso('2bb')).proceso('3bac'):-pregunta(3, Respuesta ), (Respuesta=`MIOPIA`->proceso_final(3); Respuesta=`HIPERMETROPIA`->proceso_final(1);proceso('3bac')).proceso('3bbb'):- pregunta(4, Respuesta), (Respuesta=`JOVEN`-> proceso_final(2); Respuesta=`PRE-PRESBIOPICO`-> proceso_final(3); Respuesta=`PRESBIOPICO`-> proceso_final(3);proceso('3bbb')).

proceso_final(Clase):- recomendacion_lentes(Clase, M),atom_string( M,Recomendacion), despliega_repuesta(Recomendacion) , continuar.

despliega_repuesta(Lente) :- _S1 = [dlg_ownedbydesktop,ws_sysmenu,ws_caption], _S2 = [ws_child,ws_visible,ss_center], _S3 = [ws_child,ws_visible,ws_tabstop,bs_pushbutton], wdcreate( respuesta, `user_dialog`, 235, 43, 402, 180, _S1 ), wccreate( (respuesta,10000), static, `LA RECOMENDACIÓN ES`, 20, 10, 370, 20, _S2 ), wccreate( (respuesta,10001), static, Lente, 120, 40, 170, 50, _S2 ), wccreate( (respuesta,1000), button, `ACEPTAR`, 130, 100, 150, 30, _S3 ), wfcreate( foo1, arial, 18, 2 ), wfont( (respuesta,10000), foo1 ), wfont( (respuesta,10001), foo1 ),

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 34: Guia Sistema Experto Win_prolog

window_handler( respuesta, bienvenida_handler ), call_dialog( respuesta, R ), wfclose(foo1),wclose(respuesta). continue('yes'):-proceso0,!. % dependiendo del parametro, se sigue con otra consulta o se sale.continue('no'):-despedida.continuar:-message_box( yesno, 'Desea Continuar', A ), continue(A).

despedida:- _S1 = [ws_sysmenu,ws_popup,ws_caption,dlg_ownedbyprolog], _S2 = [ws_child,ws_visible,ss_center], _S3 = [ws_child,ws_visible,ws_tabstop,bs_pushbutton], wdcreate( despedida, `user_dialog`, 235, 43, 533, 358, _S1 ), wccreate( (despedida,10000), static, `Hasta pronto`, 146, 40, 240, 20, _S2 ), wccreate( (despedida,10001), static, `Fue un placer Ayudarte`, 146, 60, 240, 20, _S2 ), wccreate( (despedida,10002), static, `Sistemas Basados en el Conocimiento I`, 117, 90, 300, 20, _S2 ), wccreate( (despedida,10003), static, `Facultad de Matemáticas e Ingenierías`, 117, 110, 300, 20, _S2 ), wccreate( (despedida,10004), static, `FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-FUKL (http://www.fukl.edu)`, 16, 130, 500, 60, _S2 ), wccreate( (despedida,1000), button, `OK`, 226, 190, 80, 20, _S3 ), wcreate((despedida,2),grafix,``,0, 210, 533, 96,16'50000000), wfcreate( foo, arial, 18, 0 ), wfont( (despedida,10000), foo ), wfont( (despedida,10001), foo ), wfont( (despedida,10002), foo ), wfont( (despedida,10003), foo ), wfont( (despedida,10004), foo ), wfont( (despedida,1000), foo ), window_handler( despedida, bienvenida_handler ), call_dialog( despedida, R ), wfclose(foo),gfx_bitmap_close(fukl),gfx_bitmap_close(fukl1),wclose(despedida).

bienvenida :- _S1 = [ws_sysmenu,ws_popup,ws_caption,dlg_ownedbyprolog], _S2 = [ws_child,ws_visible,ss_center], _S3 = [ws_child,ws_visible,ss_left], _S4 = [ws_child,ws_visible,ws_tabstop,bs_pushbutton], wdcreate( bienvenida, `user_dialog`, 235, 43, 532, 325, _S1 ), wccreate( (bienvenida,10000), static, `FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-FUKL (http://www.fukl.edu)`, 70, 10, 390, 20, _S2 ), wccreate( (bienvenida,10001), static, `FACULTAD DE MATEMÁTICAS E INGENIERÍAS`, 110, 30, 320, 20, _S2 ), wccreate( (bienvenida,10002), static, `SISTEMAS BASADOS EN EL CONOCIMIENTO I`, 110, 50, 320, 20, _S2 ), wccreate( (bienvenida,10003), static, `BIENVENIDOS AL PROGRAMA " LENTES"`, 110, 70, 320, 20, _S2 ), wccreate( (bienvenida,10004), static, `EL CUAL, CON UN EJEMPLO SENCILLO, ILUSTRA EL PROCESO`, 60, 90, 420, 20, _S2 ), wccreate( (bienvenida,10005), static, `DE CONSTRUCCIÓN DE UN SISTEMA BASADO EN EL CONOCIMIENTO`, 60, 110, 420, 20, _S2 ), wccreate( (bienvenida,10006), static, `SE TRATA DE RECOMENDAR UN TIPO DE LENTE, A PARTIR DE`, 60, 130, 420, 20, _S3 ),

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 35: Guia Sistema Experto Win_prolog

wccreate( (bienvenida,10007), static, `CIERTAS CARACTERÍSTICAS DEL PACIENTE`, 60, 150, 420, 20, _S2 ), wccreate( (bienvenida,1000), button, `CONTINUAR`, 210, 180, 130, 30, _S4 ), wcreate((bienvenida,2),grafix,``,0, 210, 533, 96,16'50000000), window_handler( bienvenida, bienvenida_handler ), gfx_bitmap_load(fukl,'fukl.bmp'), %carga el archivo fukl.bmp del directorio local gfx_bitmap_load(fukl1,'fukl1.bmp'), %carga el archivo fukl1.bmp del directorio local call_dialog( bienvenida, R ), wclose(bienvenida).

bienvenida_handler( (Window,2), msg_paint, _, _ ) :- gfx_paint( (Window,2) ), gfx(bitmap(0,0, 533, 96,0,0,fukl1)), gfx_end( (Window,2)). bienvenida_handler( (Window,1000), msg_button, _, cancel ).

combo_select( Pregunta,Items, Selected ) :-_S1 = [ws_sysmenu,ws_popup,ws_caption,dlg_ownedbyprolog], _S2 = [ws_child,ws_visible,ws_tabstop,cbs_dropdown], _S3 = [ws_child,ws_visible,ss_left], _S4 = [ws_child,ws_visible,ws_tabstop,bs_pushbutton], _S5 = [ws_child,ws_visible,ws_border], wdcreate( combo, `user_dialog`, 272, 150, 400, 350, _S1 ), wccreate( (combo,500), combobox, `Combo1`, 100, 60, 170, 150, _S2 ), wccreate( (combo,3), static, Pregunta, 50, 20, 350, 20, _S3 ), wccreate( (combo,1), button, `OK`, 140, 140, 100, 30, _S4 ), wcreate((combo,4),static,`iconbds`,10,10,70,54,16'50000003), wcreate((combo,2),grafix,``,25, 200, 343, 90,16'50000000), fcreate( combo, [], -2, 0, 0 ), wfcreate( foo, arial, 18, 0 ), wfont( (combo,3), foo ), wfont( (combo,500), foo ), fill_combo( (combo,500), Items ), window_handler( combo, combo_handler ), call_dialog( combo, R ), (R=cancel->Selected=R; (P is R+1,enesimo(Selected,P,Items))), fclose( combo ),wclose(combo),!. combo_handler( (Window,2), msg_paint, _, _ ) :- gfx_paint( (Window,2) ), gfx(bitmap(0,0, 343, 90,0,0,fukl)), %tamaño de la imagen 343x90, iniciada en 0,0 gfx_end( (Window,2)).

% cuando ocurra un mensaje de cierre retorna "cancel"

combo_handler( _, msg_close, _, cancel ).

% cuando se presiona el boton "OK" retorna la seleccion

combo_handler( (Window,1), msg_button, _, Result ) :- get_selected_item( (Window,500), Result ).

% llena el combobox con la lista de items, preseleccionando el primer item

fill_combo( Window, Items ) :-sndmsg( Window, cb_resetcontent, 0, 0, _ ), forall( member( Item, Items ),sndmsg( Window, cb_addstring, 0, Item, _ )), sndmsg( Window, cb_setcursel, 0, 0, _ ).

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 36: Guia Sistema Experto Win_prolog

% Se obtiene la posición-1 del ítem seleccionado

get_selected_item( Window, R ) :- sndmsg( Window, cb_getcursel, 0, 0, R ).

%obtiene el elemento enésimo de una listaenesimo(X,1,[X|_]).enesimo(X,N,[_|L]):-R is N-1, enesimo(X,R,L).

Para correr este programa se debe descargar el archivo comprimido de la siguiente dirección: http://in.solit.us/archives/download/153909, descomprimirlo en una carpeta y luego abrirlo con winprolog(se utilizó la versión 4.2), igual que se hizo para el ejemplo 1.Aquí se muestra una secuencia de corrida del programa:Al entrar el comando “empezar” se obtiene:

Al hacer clic en continuar…

Luego de seleccionar la opción “NORMAL”

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 37: Guia Sistema Experto Win_prolog

Luego de seleccionar la opción SI

Luego de elegir la opción JOVEN

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 38: Guia Sistema Experto Win_prolog

Al elegir la opción Aceptar

A elegir la opción NO

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 39: Guia Sistema Experto Win_prolog

APÉNDICE 1Este apéndice fue elaborado a partir del documento “WIN-PROLOG 4.2

Technical Reference” de Brian D. Steel3 PREDICADOS UTILIZADOS EN ESTE TUTORIAL PARA EL DESARROLLO

DE LA INTERFACE DE USUARIOA continuación se hace una breve descripción de los predicados usados para la construcción de las interfaces gráficas de usuario gfx_paint/1

obtiene el dispositivo de contexto recortado para comenzar gráficosgfx_paint( Ventana )+Ventana <window_handle>Ejemplos El siguiente programa crea una ventana "grafix", y le asocia un manejador (handler), antes de mostrar la ventanamostrar_ventana:-wcreate( ventana, grafix, ``, 10, 10, 100, 100, 16'80800000 ),window_handler( ventana, manejador ),wshow(ventana, 1 ).

El manejador de ventana sólo tiene una cláusula, la cual reacciona a mensajes "msg_paint", mediante la obtención del dispositivo de recortado, dibujando un círculo gris, y luego liberando el dispositivo de contexto:manejador( ventana, msg_paint, _, _ ) :-gfx_paint( ventana ), % obtención del contexto recortado del dispositivogfx( (brush = stock(gray_brush) -> ellipse(10,10,90,90)) ), % dibujando un círculo grisgfx_end( ventana ). % liberando el dispositivo de contexto

3 Copyright (c) 1989-2001 Logic Programming Associates Ltda

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 40: Guia Sistema Experto Win_prolog

gfx_end/1Libera el dispositivo de contexto para finalizar la graficacióngfx_end( Ventana )+Window <window_handle> o <empty_list>CommentariosEsto libera el dispositivo de contexto de graficación actual, para la Ventana con el fin de finalizar una secuencia de graficación, antes de restaurar cualquier dispositivo de contexto guardado previamente previamente. Si Ventana se especifica como una lista vacía, se libera el dispositivo de contexto correspondiente a la impresora actual. Ver ejemplo de gfx_paint/1Notas:Los dispositivos de contexto, tienen escasos recursos y siempre deberían retornarse una vez se terminen de usar. Cada una de las llamadas a gfx_begin/1 o a gfx_paint/1 debería estar acompañada de una llamada a gfx_end/1, idealmente con una o más llamadas a gfx/1entre ellos:ideal_grafix( W ):-gfx_begin( W ),... realice una o más llamadas a gfx/1 aquí ...gfx_end( W )ideal_repaint( W) :-gfx_paint( W ),... realice una o más llamadas a gfx/1 aquí ...gfx_end( W ).

El “subsistema GraFiX “ de WIN-PROLOG comprende un completo conjunto de predicados, referidos genéricamente como "gfx*/n" debido a que virtualmente todos sus nombres comienzan con las letras "gfx". Muchos de ellos, incluyendo el predicado gfx_end/1, están relacionados con el manejo de “dispositivos de contexto”: Ellos constituyen el ambiente virtual en el cual se dibujan todas las gráficas en las ventanas.

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 41: Guia Sistema Experto Win_prolog

sndmsg/5Envía un mensaje a una ventanasndmsg( Ventana, Mensaje, Wparam, Lparam, Resultado )+Ventana <window_handle>+Mensaje <atom>+Wparam <term>+Lparam <term>-Resultado <variable>Comentarios Esto envía el mensaje denominado Mensaje a la Ventana dada, pasándole los parámetros Wparam y Lparam: El Resultado de la llamada se retorna como un entero. Cada uno de los dos parámetros puede ser de los siguientes tipos:Tipo Significado<integer> El entero se pasa directamente como un dato<string> El texto de cadena se almacena en un buffer

temporal, y su dirección se pasa como un apuntador

<atom> Este es un archivo de memoria creado con fcreate/5: su dirección es pasada como un apuntador

Ejemplo: La siguiente llamada establece un archivo de memoria denominado “buffer”, con un tamaño de 1024 bytes, con el fin de usarlo para con sndmsg/5:?- fcreate( buffer, [], -1, 1024, 0 ). <enter>yesUna vez se crea este buffer, se puede usar como un parámetro en la llamada a sndmsg/5. La siguiente llamada envía un mensaje a la ventana principal de WIN-PROLOG(“0”), la cual copia el título de la ventana en el buffer, retornando el número de caracteres en el nombre:?- sndmsg( 0, wm_gettext, 1024, buffer, R ). <enter>R = 10Se puede hacer una llamada a wintxt/4 para recuperar el texto contenido en buffer, antes de cerrarlo con fclose/1:?- wintxt( buffer, 0, 0, T ), fclose( buffer ). <enter>T = `W `Notas:Muchas operaciones en el ambiente Windows (Win32 API) son manejados mediante el paso de mensajes a windows. Los cuales pueden ser enviados por el mismo sistema operativo o por aplicaciones. En tiempo de corrida, los mensajes y sus parámetros son simplemente números, aunque la mayoría de compiladores de Windows los proveen con nombres significativos y tipos de datos de parámetros en tiempo de compilación. Debido a que Prolog es un lenguaje dinámico, podría ser restrictivo limitar la denominación de los mensajes al tiempo de compilación.

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 42: Guia Sistema Experto Win_prolog

sndmsg/5 se ha proveído para facilitar específicamente la programación del acceso a mensajes de windows.El predicado sndmsg/5 , en efecto, no es nada más que un front end para el predicado winapi/4, el cual permite que se pueda llamar virtualmente a cualquier función el API win32( como también la mayoría de aquellas en cualquier Librería de enlace dinámico(DLL) de 32 bits)Este predicado soporta la mayoría de los mensajes de Windows, incluyendo todos los documentados en la versión 2.0 del SDK de Win32 de Microsoft.

call_dialog/2Llama a un diálogo modal y obtiene o verifica el resultadocall_dialog( Ventana, Resultado )+Ventana <window_handle>?Resultado <term>Comentarios Esto muestra la Ventana de diálogo dada, deshabilitando toas las demás ventanas de nivel superior de WIN-PROLOG y espera a que el usuario complete el diálogo: Resultado es unificado con cualquier valor que haya sido retornado por el manejador de la ventana del diálogo.Ejemplo El siguiente predicado crea un diálogo muy simple con dos botones,etiquetados con “Hola” y “Mundo”, respectivamente:

crear_dialogo :-Dstyle = [ws_popup,ws_caption],Bstyle = [ws_child,ws_visible,bs_pushbutton],wdcreate( dialogo, `diálogo`, 100, 100, 170, 75, Dstyle ),wccreate( (dialogo,1), button, `Hola`, 10, 10, 70, 30, Bstyle ),wccreate( (dialogo,2), button, `Mundo`, 90, 10, 70, 30, Bstyle ).

Cuando se compila, y se entra el siguiente comando, se crea el diálogo “dialogo”, pero no se depliega todavía?- crear_dialogo. <enter>Yes

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 43: Guia Sistema Experto Win_prolog

Para mostrar el diálogo, y retornar el texto del botón que fue presionado, entre el siguiente comando:?- call_dialog( dialogo, X ). <enter>El diálogo aparecerá, deshabilitando todas las demás ventanas de WIN-PROLOG, y si se presiona el botón "Hola", su texto en minúsculas será retornado como sigue:X = hola

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 44: Guia Sistema Experto Win_prolog

Notes El ejemplo anterior usa el manejador de ventana por defecto,window_handler/4, which simply unifica el texto en minúsculas de cualquier botón cliqueado con Resultado. Esta acción de unificar esta variable es lo que realmente completa el diálogo. Los manejadores de ventanas (window handler) son simplemente programas de aridad 4 que interceptan mensajes destinados a una ventana(incluyendo diálogos y sus controles), permitiendo que se puedan procesar acciones arbitrarias. Considere el siguiente ejemplo: manejador_boton( (dialogo,1), msg_button, _, Resultado ) :-time( _, _, _, H, M, S, _ ),Resultado= finished_at(H,M,S).manejador_boton( Ventana, Mensaje, Datos, Resultado ) :-window_handler(Ventana, Mensaje, Datos, Resultado ).La primera cláusula detecta que un botón denominado “(boton,1)" haya sido cliqueado y completa el diálogo retornando la estructura “finished_at(H,M,S)" en lugar el átomo "hello". Los demás mensajes son pasados al manejador de ventana por defecto. El código completo sería:crear_dialogo :-Dstyle = [ws_popup,ws_caption],Bstyle = [ws_child,ws_visible,bs_pushbutton],wdcreate( dialogo, `diálogo`, 100, 100, 170, 75, Dstyle ),wccreate( (dialogo,1), button, `Hola`, 10, 10, 70, 30, Bstyle ),wccreate( (dialogo,2), button, `Mundo`, 90, 10, 70, 30, Bstyle ).

manejador_boton( (dialogo,1), msg_button, _, Resultado ) :-time( _, _, _, H, M, S, _ ),Resultado= finished_at(H,M,S).manejador_boton( Ventana, Mensaje, Datos, Resultado ) :-window_handler(Ventana, Mensaje, Datos, Resultado ).

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 45: Guia Sistema Experto Win_prolog

Una vez compilado el nuevo manejador de ventana es asociado a la ventana de diálogo con una llamada a window_handler/2, como se muestra a continuación:

?- window_handler( dialogo, manejador_boton). <enter>yesSi el diálogo es invocado una vez más, y se presiona el botón "(boton,1)" (etiquetado con "Hola"), se retorna el tiempo en lugar del átomo "hola":?- call_dialog( dialogo, X ). <enter>

X = finished_at(16,25,6)Que indica la hora en que fue presionado el botón “Hola”. Si presiona el botón “Mundo”, solo retornará R=mundo, ya que el nuevo manejador(manejador_boton), no se definió para la ventana de ese botón((dialogo,2)).

Si se deseara que los dos botones reaccionaran igual, se debía incluir un predicado similar para el botón “Mundo” ((dialogo, 2)).crear_dialogo :- Dstyle = [ws_popup,ws_caption], Bstyle = [ws_child,ws_visible,bs_pushbutton],

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 46: Guia Sistema Experto Win_prolog

wdcreate( dialogo, `diálogo`, 100, 100, 170, 75, Dstyle ), wccreate( (dialogo,1), button, `Hola`, 10, 10, 70, 30, Bstyle ), wccreate( (dialogo,2), button, `Mundo`, 90, 10, 70, 30, Bstyle ). manejador_boton( (dialogo,1), msg_button, _, Resultado ) :- time( _, _, _, H, M, S, _ ), Resultado= finished_at(H,M,S).manejador_boton( (dialogo,2), msg_button, _, Resultado ) :- time( _, _, _, H, M, S, _ ),Resultado= finished_at(H,M,S).manejador_boton( Ventana, Mensaje, Datos, Resultado ) :-window_handler(Ventana, Mensaje, Datos, Resultado ).

Note que los diálogos “modales” y “no modales” tiene exactamente los mismos manejadores de ventana: en efecto en WIN-PROLOG, estos dos tipos de diálogos son lo mismo. Todo lo que determina si un diálogo se comporta de forma modal o no modal en tiempo de corrida, es si el diálogo es invocado por call_dialog/2 (modal) o show_dialog/1 ( no modal).

window_handler/2Obtiene o establece el manejador para una ventana dadawindow_handler( Ventana, Manejador )+Ventana<atom> o <integer> en el dominio {0,1}?Manejador <atom> o <variable>ComentariosObtiene o establece el nombre de un predicado de aridad 4 que sera usado como el Manejador para la Ventana de nivel superior(de diálogo, de texto o de usuario). Si Manejador es una variable no acotada, retorna el nombre del manejador existente, de otra forma, establece que el manajador Manejador asociándolo a la Ventana.EjemploEl siguiente programa usa wdcreate/7 y wccreate/8 para crear un pequeño diálogo que contiene un pequeño botón de presionar por defecto:dialogo_ejemplo:-Dstyle = [ws_visible,ws_popup,ws_caption],Bstyle = [ws_visible,ws_child,bs_defpushbutton],wdcreate( dialogo, `diálogo`, 10, 10, 100, 60, Dstyle ),wccreate( (dialogo,1), button, `clic`, 10, 10, 80, 20, Bstyle ).

Una vez compilado, la siguiente llamada despliega el diálogo cerca a la esquina superior izquierda de la pantalla(haciendo posteriormente clic en el botón ocultará(aunque no cerrará) el diálogo)?- dialogo_ejemplo. <enter>

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 47: Guia Sistema Experto Win_prolog

Yes

Este comportamiento es debido al manejador de ventana por defecto para el diálogo, window_handler/4, como se puede apreciar mediante la siguiente llamada, cuando se pregunta por el nombre del manejador actual de la ventana “dialogo”:?- window_handler( dialogo, H ). <enter>H = window_handlerAhora considere el siguiente manejador de ventana:dialogo_manejador( (dialogo,1), msg_button, _, _ ) :-time( _, _, _, H, M, S, _ ),write( H-M-S ) ~> String,wtext( (dialogo,1), String ).dialogo_manejador( Ventana, Mensaje, Datos, Resultado ) :-window_handler( Ventana, Mensaje, Datos, Resultado ).La primera cláusula simplemente intercepta el mensaje "msg_button" destinado al control del botón, "(dialogo,1)", y en vez de permitir al botón, ocultar el diálogo, escribe el tiempo actual en una cadena, usando esto para renombrar al botón. Todos los demás mensajes son recogidos por la segunda cláusula, la cual simplemente se los pasa a window_handler/4 para el procesamiento por defecto.El código del programa completo sería:dialogo_ejemplo:-Dstyle = [ws_visible,ws_popup,ws_caption],Bstyle = [ws_visible,ws_child,bs_defpushbutton],wdcreate( dialogo, `diálogo`, 10, 10, 100, 60, Dstyle ),wccreate( (dialogo,1), button, `clic`, 10, 10, 80, 20, Bstyle ).dialogo_manejador( (dialogo,1), msg_button, _, _ ) :-time( _, _, _, H, M, S, _ ),write( H-M-S ) ~> String,wtext( (dialogo,1), String ).dialogo_manejador( Ventana, Mensaje, Datos, Resultado ) :-window_handler( Ventana, Mensaje, Datos, Resultado ).

Una vez compilado este programa puede ser asociado al diálogo “dialogo” con la siguiente llamada:?- window_handler( dialogo, dialogo_manejador ). <enter>yes

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 48: Guia Sistema Experto Win_prolog

Ahora, cuando se despliega el diálogo con una llamada a dialogo_ejemplo /0, al hacer clic sobre el botón simplemente cambiará su etiqueta desplegando el tiempo actual sin cerrar el diálogo.?- dialogo_ejemplo. <enter>Yes

Notas El window_handler/2 simplemente mantiene una base de datos local de los nombre de las ventana de nivel superior y los nombres de sus respectivos predicados “manejadores de ventana”: cuando un mensaje llega a una ventana dada, se verifica esta base de datos para buscar una coincidencia. Si se halla la ventana de nivel superior, entonces se llama el correspondiente manejador con cuatro argumentos:<handler>( Ventana, Mensaje, Datos, Resultado )Los primeros tres argumentos son acotados como sigue: Ventana contiene el manejador de la ventana que recibe el mensaje (<window_handle>), Mensaje contiene el nombre del mensaje(<atom> if known, otherwise <integer>), y Data contiene información suplementaria (dependiendo del mensaje).El último argumento, Resultado, es una variable no acotada. Si el manejador de ventana une esto a algún valor, causará la terminación de la ventana de nivel superior(generalmente un diálogo): si la ventana fue invocada por call_dialog/2, este valor es pasado hacia atrás como el segundo argumento del último predicado. Considere la siguiente variante del manejador de ventana mostrado anteriormente:

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 49: Guia Sistema Experto Win_prolog

dialogo_manejador ( (dialogo,1), msg_button, _, (H,M,S) ) :-time( _, _, _, H, M, S, _ ).dialogo_manejador ( Ventana, Mensaje, Datos, Resultado ) :-window_handler(Ventana, Mensaje, Datos, Resultado).El dialogo completo sería:dialogo_ejemplo:-Dstyle = [ws_visible,ws_popup,ws_caption],Bstyle = [ws_visible,ws_child,bs_defpushbutton],wdcreate( dialogo, `diálogo`, 10, 10, 100, 60, Dstyle ),wccreate( (dialogo,1), button, `clic`, 10, 10, 80, 20, Bstyle ).

dialogo_manejador( (dialogo,1), msg_button, _, (H,M,S) ) :-time( _, _, _, H, M, S, _ ).dialogo_manejador( Ventana, Mensaje, Datos, Resultado ) :-window_handler(Ventana, Mensaje, Datos, Resultado).

Esta vez la primera cláusula retorna simplemente el tiempo. Una vez compilado, el diálogo puede ser llamado “modalmente “ como se muestra a continuación:?-dialogo_ejemplo.<enter>

?- call_dialog( dialogo, R ).<enter>

Al hacer clic sobre el botón, se obtieneR=(0,7,8)

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 50: Guia Sistema Experto Win_prolog

Que indica el tiempo: 0 horas, 7 minutos y 8 segundos (12:07:08 am, hora a la que se corrió el programa.

Para remover la asociación entre una ventana y su manejador definido por el usuario, window_handler/2 se llama para "re-asociar" la ventana con el manejador por defecto, window_handler/4:?- window_handler( dialogo, window_handler ). <enter>Ahora cuando se llame el diálogo modalmente, simplemente retorna el nombre del botón, cuando éste sea cliqueado.?- dialogo_ejemplo.

?- call_dialog( dialogo, R ). <enter>

Al hacer clic sobre el botón, se obtieneR=clic

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 51: Guia Sistema Experto Win_prolog

Que indica el nombre del botón.

Note que window_handler/2 asocia solamente ventanas de “nivel superior"(ventanas de “Diálogo”, de “Texto” y de usuario, junto con la “ventana principal” (“0”) y la “ventana de consola” (“1”): no es posible asociar manejadores de ventanas a controles individuales dentro de estas ventanas. Cuando se llama a un manejador de ventana, su primer argumento especifica la ventana precisa (de nivel superior o de control, según sea el caso) que ha recibido el mensaje, y corresponde al programador decidir cómo usar esta información. En el ejemplo anterior la primer cláusula especifica la ventana exacta (“(diálogo, 1)”) y el mensaje ("msg_button") que está siendo procesado, pero uno de estos parámetros o los dos se pueden especificar total o parcialmente no instanciados. Por ejemplo, la siguiente cláusula recogería los mensajes “msg_button” para cualquier botón de cualquier diálogo para el cual se estableció dialogo_handler/4 como su manejador, retornando el entero ID en vez de su nombredialogo_handler ( (Dialogo,ID), msg_button, _, ID ).Cualquier predicado puede servir a un número arbitrario de ventanas de nivel superior (en particular, window_handler/4 sirve a todas las ventanas hasta que es reemplazado por un manejador definido por el usuario). Adicionalmente, es posible asociar ventanas y nombre de manejadores, llamando a window_handler/2 incluso antes de que la ventana y/o el manejador existan. Todo lo que se requiere es que el predicado del manejador de aridad 4 está compilado y listo para usarse en el momento en que se cree una ventana para la cual ese predicado sea elegido como manejador gfx_bitmap_load/2Carga un objeto bitmap de un archivo de disco dado. wdcreate/7Crea una ventana de diálogo

wdcreate( Ventana, Texto, Izquierda, Superior, Ancho, Profundidad, Estilo )+Ventana <window_handle>+Texto <string>

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 52: Guia Sistema Experto Win_prolog

+Izquierda <integer>+Superior <integer>+Ancho <integer>+Profundidad <integer>+Estilo <list>

Comentarios Esto crea una “ventana de diálogo” con el manejador Ventana, el título Texto, en la posición (Izquierda, Superior), con el tamaño (Ancho, Profundidad) y el estilo tipo lista Estilo. Ejemplo El siguiente programa usa wdcreate/7 wccreate/8 para crear un pequeño diálogo que contiene un solo botón "pulsación por defecto”:ejemplo_wdcreate :-Dstyle = [ws_visible,ws_popup,ws_caption],Bstyle = [ws_visible,ws_child,bs_defpushbutton],wdcreate( prueba, `foo`, 10, 10, 100, 60, Dstyle ),wccreate( (prueba,1), button, `fukl`, 10, 10, 80, 20, Bstyle ).Una vez compilado, la siguiente llamada desplegará el diálogo cerca de la esquina superior izquierda de la pantalla(al hacer clic sobre el botón, la ventana se ocultará, pero no se cerrará):?- ejemplo_wdcreate. <enter>yes

wclose/1cierra una ventanawclose( Ventana )+Ventana <window_handle>Commentarios: Esto cierra la ventana denominada Ventana, liberando sus recursos.Ejemplo: La siguiente llamada crea una pequeña ventana de usuario(MDI child):?- wcreate( ventana, user, ``, 100, 100, 300, 200, 0 ). <enter>Yes

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 53: Guia Sistema Experto Win_prolog

Después de hacer clic al mouse se retorna a la “ventana de consola”, la ventana recientemente creada se puede cerrar con el siguiente comando:?- wclose( foo ). <enter>yesNotas Cuando se cierra una ventana de “nivel superior”(tal como un diálogo o una ventana de usuario), se cierran también todos los controles constituyentes de esa ventana: de esta manera pueden hacerse varias llamadas a wcreate/8 por cada subsecuente llamada a close/1. El número de ventanas que se pueden abrir a la vez es una función de los recursos spare en el ambiente Windows. Sin embargo, existe un techo límite en WIN-PROLOG que limita el número de diálogos abiertos a 64, pero, debido a que los diáologos pueden ser creados y cerrados a voluntad cualquier número de veces, este límite, en general, nunca es un problema.

wcreate/8crea una ventanawcreate( Ventana, Clase, Texto, Izquierda, Superior, Ancho, Profundidad, Estilo )+Ventana <window_handle>+Clase <atom>+Texto <string>+Izquierda <integer>+Superior <integer>+Ancho <integer>+Profundidad <integer>+Estilo <integer>Comentarios:Esto crea una ventana con un Manejador, Clase y Texto dados, en la posición (Izquierda, Superior), con el tamaño (Ancho, Profundidad) y el Estilo entero. Las siguientes clases de ventanas estándar que se pueden crear por medio de este predicado:Clase Significado de la claseButton control de botón

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 54: Guia Sistema Experto Win_prolog

ComboBox Control comboboxEdit control editListBox control listboxScrollBar control scrollbarStatic Control static

Además de las clases anteriores , Win Prolog define las siguientes clases:

Clase Significado de la claseText: Ventana de Texto de WIN-PROLOGUser: Ventana de usuario de WIN-PROLOGGrafix: Control grafix de WIN-PROLOG

Una pseudo clase denominado, “Dialog”, se usa para crear ventana de diálogo.La siguiente instrucción crea una pequeña ventana de usuario(MDI Child):?- wcreate( ventana, user, ``, 100, 100, 300, 200, 0 ). <enter>yes

Después de hacer clic al mouse se retorna a la “ventana de consola”, la ventana recientemente creada se puede cerrar con el siguiente comando;?- wclose( ventana ). <enter>yesNotas: El predicado wcreate/8 proporciona soporte de bajo nivel para los otros cuatro creadores de ventana: Los predicados wccreate/8 y wdcreate/7 tratan a Estilo como una lista de nombres de estilo, convirtiéndolos en un entero, mientras que wtcreate/6 y wucreate/6 no tienen parámetro de estilo, y usan un entero por defecto.Este es uno de la pequeña familia de predicados de WIN-PROLOG para manipular ventanas implementadas directamente en kernel codificado en ensamblador, permitiendo funciones especiales de bajo nivel que pueden ser manipuladas eficientemente. La mayor parte de los demás predicados para manipular ventanas se implementan como una “capa delgada” sobre la todo-poderosa winapi/4 para simplificar

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 55: Guia Sistema Experto Win_prolog

las tareas comunes de programación en Windows. A pesar de que la mayoría de aplicaciones pueden ser satisfechas con estos predicados simples, siempre es probable que se presenten combinaciones de funciones que no pueden ser realizadas fácilmente con ellas. En estas ocasiones, se puede usar winapi/4 y su predicado ayudante wintxt/4, para acceder virtualmente a cualquier función del API de Windows al igual que las implementadas en DLL.

wccreate/8Crea una ventana de controlwccreate( Ventana, Clase, Texto, Izquierda, Superior, Ancho, Profundidad, Estilo )+Window <window_handle>+Clase <atom>+Texto <string>+Izquierda <integer>+Superior <integer>+Ancho<integer>+Profundidad <integer>+Estilo <list>Comentarios Esto crea una ventana con un Manejador, Clase y Texto dados, en la posición(Izquierda, Superior), con el tamaño (Ancho, Profundidad) y la lista de Estilo. La lista de tipos de clases de estilo se describen en wcreate/8.Ejemplo El siguiente programa usa wdcreate/7 y wccreate/8 para crear un pequeño diálogo que contiene un pequeño diálogo con un botón.ejemplo_dialogo :-Dstyle = [ws_visible,ws_popup,ws_caption],Bstyle = [ws_visible,ws_child,bs_defpushbutton],wdcreate( ejemplo, `hola esta es una prueba`, 10, 10, 200,160, Dstyle ),wccreate( (ejemplo,1), button, `es es un ejemplo`, 30, 10, 120, 20, Bstyle ).

Una vez compilado, la siguiente llamada desplegará el diálogo cerca de la esquina superior izquierda de la pantalla(Si se ha clic en el botón, el diálogo se ocultará, pero no se cerrará)?- ejemplo_dialogo. <enter>yes

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 56: Guia Sistema Experto Win_prolog

Notas:Este es uno de una familia de predicados para la creación de ventanas de WIN-PROLOG, implementada en términos de un predicado de más bajo nivel, wcreate/8, el cual espera un valor de estilo entero como su argumento final. Los predicados wccreate/8 and wdcreate/7 esperan que el estilo sea especificado como una lista de átomos, cada uno de los cuales denota el nombre de un estilo, los cuales son convertidos en un estilo entero; wtcreate/6 y wucreate/6 no tienen parámetro Estilo, sino que simplemente usan un estilo entero por defecto: Entonces, todos los cuatro predicados anteriores llaman a wcreate/8 con su estilo por defecto o calculado.

wfcreate/4crea una fuentewfcreate( Fuente, Apariencia, Tamaño, Estilo )+Font <atom>+Face <atom>+Size <integer>+Style <integer> in the range [0..3]Comentarios Esto crea la fuente llamada “Fuente”, usando la Apariencia dada, los puntos Tamaño y estilo Estilo; cualquier fuente que existe con el mismo nombre se cierra antes de que la nueva fuente sea creada. Los Estilos son listados en la siguiente tabla:Estilo Significado0 normal1 italic2 bold3 bolditalic

Ejemplo La siguiente llamada creará una fuente llamada “fuente”, especificando su apariencia como “Arial”, tamaño como 16 puntos y estilo como normal ("0"), y asigna esta fuente a la ventana de consola("(1,1)"):

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 57: Guia Sistema Experto Win_prolog

?- wfcreate( fuente, arial, 16, 0 ), wfont( (1,1), fuente ). <enter>yesLa siguiente llamada restaura la fuente de consola por defecto("OEM fixed font")("0"), antes de cerrar la fuente creada anteriormente:?- wfont( (1,1), 0 ), wfclose( foo ). <enter>yesNotas Cuando se crean y usan Fuentes, es importante recordar que ellas son recursos de bajo nivel de windows, que su uso inadecuado puede resultar en comportamientos impredecibles. En particular una fuente nunca puede ser cerrada o redefinida mientras esté seleccionada en una ventana(ver ejemplo de arriba) o contexto de dispositivo gráfico. Note que las fuentes creadas con wfcreate/4 son idénticas a las creadas por gfx_font_create/4: los predicados orientados a ventanas wf*/n son completamente intercambiables con los predicados "Grafix" más recientes, gfx_font*/n

wfont/2obtiene o establece la fuente usada por un control de ventanawfont( Ventana, Fuente )+Ventana <window_handle>?Fuente <variable>, <atom>, <integer> o <tuple>ComentariosEsto obtiene o establece la Fuente usada actualmente para desplegar el texto de una Ventana de control determinada: Si Fuente es una variable no acotada, retorna la fuente de ventana existente; de otra forma, se usa para establecer la nueva fuente de ventana.Ejemplo Ver wfcreate/4NotasEste predicado puede ser usado únicamente para establecer la fuente a ser usada por la ventana de control: no tiene efecto sobre la barra de títulos de la ventana de nivel superior. Igualmente para manipular fuentes preestablecidas, se puede usar wfont/2 para obtener o fijar un stock de seis fuentes numéricas especiales, predefinidas, así como también cualquier handle de fuente entera, donde handle está contenida en una tupla de la forma “font(integer)”. El stock de fuentes se lista a continuación:

Número Significado 0 OEM fixed font1 system font2 system fixed font3 ANSI var font4 ANSI fixed font5 device default font

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 58: Guia Sistema Experto Win_prolog

wfclose/1cierra una fuentewfclose( Fuente )+Fuente <atom>Commentarios Esto cierra la denominada Fuente, liberando sus recursos.Ejemplos Ver wfcreate/4

Nombre de estilos de ventanasCuando se crea una ventana, es a menudo necesario especificar su “estilo”: esto determina la apariencia de la ventana y sus características de comportamiento. Algunos estilos corresponden a la mayoría de las ventanas: visibilidad , por ejemplo, o si la ventana es una ventana “hija” o “emergente”. Otros estilos están relacionados con clases específicas de ventanas: un control button puede aparecer y comportarse como un checkbox, radio button o simple pushbutton. Cada uno de los estilos está asociado con uno o más bits en un entero de 32 bits: el conjunto requeridos de estilos debe ser combinado usando la función “o inclusiva”, pasándolo antes a wcreate/8 para crear una ventana. Por ejemplo, el siguiente programa crea una ventan de diálogo con estilos combinados, "ws_visible", "ws_popup" y "ws_caption", conteniendo un control "button" con los estilos combinados, "ws_visible", "ws_child" and "bs_defpushbutton".ejemplo :-wcreate( prueba, dialog, `prueba`, 10, 10, 100, 60, 16'90C00000 ),wcreate( (prueba,1), button, `bar`, 10, 10, 80, 20, 16'50000001 ).Para hacer más fácil la especificación de la ventana, WIN-PROLOG incluye dos predicados adicionales para la creación de ventanas, wdcreate/7 y wccreate/8, en los cuales el argumento final “Estilo” puede ser presentada como una lista de nombres de estilo, en vez de un entero; el siguiente programa produce exactamente el mismo diálogo que antes, pero usa lista de estilos en lugar de estilos enteros precomputados:

ejemplo :-Dstyle = [ws_visible,ws_popup,ws_caption],Bstyle = [ws_visible,ws_child,bs_defpushbutton],wdcreate( prueba, `prueba`, 10, 10, 100, 60, Dstyle ),wccreate( (prueba,1), button, `bar`, 10, 10, 80, 20, Bstyle ).

Los dos predicados adicionales, wtcreate/6 y wucreate/6, crean ventana de “texto” y de “usuario”(MDI Child) respectivamente: estas dos tipos de ventanas tienen estilos predefinidos, por lo tanto estos predicados omiten el parámetro estilo

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 59: Guia Sistema Experto Win_prolog

Notese que no todos los tipos de estilo pueden ser combinados: un botón, por ejemplom no puede se simultáneamente un checkbox ("bs_checkbox"), radio button ("bs_radiobutton") y el pushbutton por defecto("bs_defpushbutton").El conjunto completo de nombres de estilo que pueden ser usadas en wdcreate/7 y wccreate/8, junto con los tipos de ventana a las cuales ellos pueden corresponder, son listados a continuación. Estilos GenéricosEstos son los estilos que pueden ser aplicados a más de una clase de ventana.Estilo Valorws_overlapped 16'00000000ws_popup 16'80000000ws_child 16'40000000ws_minimize 16'20000000ws_visible 16'10000000ws_disabled 16'08000000ws_clipsiblings 16'04000000ws_clipchildren 16'02000000ws_maximize 16'01000000ws_caption 16'00C00000ws_border 16'00800000ws_dlgframe 16'00400000ws_vscroll 16'00200000ws_hscroll 16'00100000ws_sysmenu 16'00080000ws_thickframe 16'00040000ws_minimizebox 16'00020000ws_maximizebox 16'00010000ws_group 16'00020000ws_tabstop 16'00010000

Estilos de EditEstos son los estilos que pueden ser aplicados a los controles editEstilo Valores_left 16'00000000es_center 16'00000001es_right 16'00000002es_multiline 16'00000004es_uppercase 16'00000008es_lowercase 16'00000010es_password 16'00000020es_autovscroll 16'00000040es_autohscroll 16'00000080es_nohidesel 16'00000100es_oemconvert 16'00000400es_readonly 16'00000800es_wantreturn 16'00001000

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 60: Guia Sistema Experto Win_prolog

Estilos de ListboxEstos son los estilos que pueden aplicarse a los controles listboxEstilo Valorlbs_notify 16'00000001lbs_sort 16'00000002lbs_noredraw 16'00000004lbs_multiplesel 16'00000008lbs_ownerdrawfixed 16'00000010lbs_ownerdrawvariable 16'00000020lbs_hasstrings 16'00000040lbs_usetabstops 16'00000080lbs_nointegralheight 16'00000100lbs_multicolumn 16'00000200lbs_wantkeyboardinput 16'00000400lbs_extendedsel 16'00000800lbs_disablenoscroll 16'00001000

Estilos de ComboboxEstos son los estilos que pueden aplicarse a los controles combobox:Estilo Valorcbs_simple 16'00000001cbs_dropdown 16'00000002cbs_dropdownlist 16'00000003cbs_ownerdrawfixed 16'00000010cbs_ownerdrawvariable 16'00000020cbs_autohscroll 16'00000040cbs_oemconvert 16'00000080cbs_sort 16'00000100cbs_hasstrings 16'00000200cbs_nointegralheight 16'00000400cbs_disablenoscroll 16'00000800

Estilos EstaticosEstos son los estilos que pueden aplicarse a los controles estáticosEstilo Valorss_left 16'00000000ss_center 16'00000001ss_right 16'00000002ss_icon 16'00000003ss_blackrect 16'00000004ss_grayrect 16'00000005ss_whiterect 16'00000006ss_blackframe 16'00000007ss_grayframe 16'00000008ss_whiteframe 16'00000009ss_simple 16'0000000B

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS

Page 61: Guia Sistema Experto Win_prolog

ss_leftnowordwrap 16'0000000Css_noprefix 16'00000080

Estilos de Scrollbar Estos son los estilos que pueden aplicarse a los controles scrollbar:

Estilo Valorsbs_horz 16'00000000sbs_vert 16'00000001sbs_topalign 16'00000002sbs_leftalign 16'00000002sbs_bottomalign 16'00000004sbs_rightalign 16'00000004sbs_sizebox 16'00000008

FUNDACIÓN UNIVERSITARIA KONRAD LORENZ-INGENIERÍA DE SISTEMAS