Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf ·...

51
Medii de programare in Inteligenta Artificiala Mihaela Colhon

Transcript of Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf ·...

Page 1: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

Medii de programare in

Inteligenta Artificiala

Mihaela Colhon

Page 2: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

2

Rationamente bazate pe reguli Un motor de inferenta este un cod software care poate procesa reguli, obiecte sau alte mecanisme de reprezentare a cunostintelor in functie de datele problemei analizate. Marea majoritate a produselor AI contin o capabilitate de rationament deductiva (forward-chaining) sau inductiva (backward-chaining). Sistemele bazate pe reguli sunt folosite pentru a modela expertiza umana prin implementarea de rationamente bazate pe reguli aplicate pe o multime de date. Structura unui sistem bazat pe reguli contine o multime de fapte numita memoria de lucru a sistemului in care sunt stocate faptele ce se cunosc a fi adevarate, o baza de reguli ce contine regulile folosite in inferenta si un motor de inferenta care are rolul de a decide ordinea in care se aplica regulile activate de datele de intrare. Structura unei reguli are urmatoarea sintaxa: IF LHS (premiza) THEN RHS (concluzie) Procesul de pattern matching este declansat in timpul inferentei ... Exista doua tipuri de algoritmi de inferenta: - forward chaining (data-driven reasoning) - backward chaining (goal-driven reasoning) Observatie Exista cazuri in care, structura de control a anumitor sisteme bazate pe reguli nu foloseste nici inlantuirea inainte nici inlantuirea inapoi a regulilor, ci o strategie de control de

tip agenda. Agenda este o lista de sarcini pe care sistemul trebuie sa le execute. Aceasta strategie este in special utila in cazul in care se foloseste un criteriu de selectie a regulilor bazat pe preferinta starilor, deci o functie euristica de evaluare. Strategie de control de tip Agenda 1. Initializeaza agenda cu sarcina de executat 2. repeta

2.1. Selecteaza sarcina cu prioritate maxima, T 2.2. Executa sarcina T in limitele unor resurse de timp si spatiu 2.3. pentru fiecare noua sarcina Ti generata de T executa 2.3.1. daca Ti este deja in agenda atunci i. Fie T'i copia lui Ti din agenda ii. daca justificarile lui T'i nu includ justificarea lui Ti atunci adauga justificarea lui Ti justificarilor lui T'i iii. Inlocuieste T'i cu Ti

2.3.2. altfel adauga Ti si justificarea asociata in agenda 2.3.3. Calculeaza prioritatea sarcinii Ti pe baza justificarilor pana agenda

satisface conditia de stare finala sau agenda este vida sfarsit. Definitie Un sistem expert modeleaza expertiza umana intr-un anumit domeniu. Sistemele expert pot include mai multe tipuri de rationament: rationament bazat pe reguli (rule-based), bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele bayesian, etc. Cele mai multe sisteme expert sunt bazate pe reguli. Ele contin o baza de cunostinte (reguli) si un motor de inferenta care analizeaza faptele si decide care reguli pot fi aplicate si de

Page 3: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

3

asemenea ordinea de aplicare a lor. Faptele sunt analizate pana cand scopul este demonstrat sau pana cand toate regulile sistemului au fost aplicate si atunci spunem ca demonstrarea scopului a esuat. Jess este un shell pentru sisteme expert si un limbaj de scripting scris in totalitate in Java. A fost dezvoltat de Ernest Friedman-Hill la Sandia National Laboratories in Livermore, California. Jess poate procesa un numar mare de reguli fiind unul dintre cele mai rapide motoare de prelucrare a regulilor. Acest mecanism este utilizat ca o varianta perfectionată a shell-ului CLIPS (C Language Integrated Production System). Folosind Jess se pot realiza aplicatii Java în domeniul inteligentei artificiale pe baza unui set de cunostinte acumulate sub forma unor reguli declarative folosite pentru a obtine concluzii si a face inferente. Sunt mai multe moduri de a reprezenta cunostinte in Jess:

• reguli – care in principal sunt pentru cunostinte euristice bazate pe experienta • fapte • functii – pentru cunostinte procedurale • programare orientata obiect, pentru cunostinte procedurale

La fel ca marea majoritate a motoarelor de inferenta bazate pe reguli, regulile sunt definite declarativ si nu in cod procedural. Spre deosebire de o paradigma procedurala , in care un singur program are o bucla care este activata o singura data, paradigma declarativa folosita in Jess, aplica in mod continuu o colectie de reguli unei colectii de fapte printr-un proces numit Potrivire de Șabloane (Pattern Matcher). Regulile pot modifica colectia de fapte sau pot executa orice cod Java. Motorul de inferenta Jess foloseste o varianta imbunatatita a algoritmului Rete (Rete in latina inseamna retea) care decide aplicarea regulilor in functie de faptele existente in memoria de lucru. Un sistem expert bazat pe reguli scris in Jess este un program dirijat de datele încărcate în memorie (data-driven) care hotăresc execuția prin intermediul motorului de inferente. Acesta este un exemplu despre modul in care Jess difera de limbaje procedurale cum ar fi Java si C. În limbajele procedurale, execuția se poate realiza și fără date. Instructiunile sunt suficiente pentru a cauza executia. De exemplu, instructiunea System.out.print(“Hello world!”) poate fi executata imediat în Java. Este o instrucțiune completă care nu are nevoie de date suplimentare pentru a declanșa execuția. În schimb, în Jess, datele sunt necesare pentru a cauza execuția regulilor. Algoritmul Rete ofera o descriere logică generalizată a unei implementări de funcționalitate responsabilă cu potrivirea faptelor în conformitate cu producțiile (regulile) declarate într-un sistem ce folosește Pattern Matcher (o categorie de motoare de inferență bazate pe reguli). O producție e constituită din una sau mai multe condiții corelate la un set de acțiuni care trebuie sa fie executate pentru fiecare set complet de fapte ale căror atribute se potrivesc cu cele exprimate în condiții. Algoritmul Rete prezinta urmatoarele caracteristici majore:

• Elimina anumite tipuri de reduntanță prin folosirea partajată a nodurilor • Salveaza potriviri parțiale ceea ce permite sistemelor de producție să evite reevaluarea

completă a tuturor faptelor de fiecare dată când se fac schimbări în memoria de lucru a sistemului.

Page 4: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

Modalitatea de a accesa motorul de inferente Jess o reprezint[inclusă într-o aplicație Java] import java.net.*

public class TestJess {

public static void main(String[] args) {

Rete r = new Rete(); //se

r.executeCommand(

r.reset(); //se reseteaza motorul

r.run(); //se executa comanda

}

}

Programarea logica Este o paradigma care pleaca de la ideea specificarii unei probleme in limbajul logicii cu predicate de ordin I

teoreme pentru rezolvarea acelei probleme. “cum se rezolva” la programarea declarativa

Deoarece demonstrarea automata de teoreme are niste dezavantaje legate de caracterul sau prea general, au fost necesare niste restrictii. De eHorn care reduc complexitatea calculului si nedeterminarea, introducand aspecte de control.

Programarea functionalabaza are unui program, asa cum intructiunile sunt parte constructiva in programele procedurale, clauzele in programarea logica si obiectele in programarea orientata obiect. Un program functional este o compunere de functii. Cel mai cunoscut reprezentant al paradigmei de programare functionala este limbajul Lisp. Deoarece Lisp este un limbaj interpretat dupa lansarea in executie a sistemului Lisp se intrintr-o bucla in care interpretorul asteapta Semnalul ca interpretorul Lisp asteapta instructiuni pentru a fi executate este facut prin aparitia prompterului. Dupa ce utilizatorul a introdus o expresie Lisp interpretorul o evalueaza si daca aceasta expresie este corecei. Se spune ca interpretorul Lisp functioneaza intrTIPARESTE (read-eval-print). La fel ca si CLIPS, Jess-ul are la baza limbajul Lispreguli (e unul dintre cele mai rapide motoare de inferenta bazate pe reguli) fiind un produs sotware extrem de stabil. Desi sintaxa Jess este similara lui CLIPS, totusi Jess si CLIPS sunt doua sisteme diferite. Spre deosebire de Lisp, Jess nu slucru afectează modul în care codul Java este reprezentat în Jess considerăm codul Java: class JavaTest { private int nr;

public String label;

Modalitatea de a accesa motorul de inferente Jess o reprezintă clasa Rete din pachetul jess

public static void main(String[] args) {

Rete r = new Rete(); //se instantiaza un nou motor de inferenta

r.executeCommand(″jess-command″); //executa comanda Jess

r.reset(); //se reseteaza motorul

r.run(); //se executa comanda

Este o paradigma care pleaca de la ideea specificarii unei logicii cu predicate de ordin I si utilizarea demonstrarii automate de

pentru rezolvarea acelei probleme. Se trece astfel de la programarea imperativa

programarea declarativa “ceea ce trebuie rezolvat”.

Deoarece demonstrarea automata de teoreme are niste dezavantaje legate de caracterul sau prea general, au fost necesare niste restrictii. De exemplu, in Prolog se lucreaza cu clauze Horn care reduc complexitatea calculului si nedeterminarea, introducand aspecte de control.

Programarea functionala In limbajele functionale, functiile sunt componentele de baza are unui program, asa cum intructiunile sunt parte constructiva in programele procedurale, clauzele in programarea logica si obiectele in programarea orientata obiect. Un

e o compunere de functii.

Cel mai cunoscut reprezentant al paradigmei de programare functionala este limbajul Lisp. Deoarece Lisp este un limbaj interpretat dupa lansarea in executie a sistemului Lisp se intr

o bucla in care interpretorul asteapta introducerea unei expresii Lisp. Semnalul ca interpretorul Lisp asteapta instructiuni pentru a fi executate este facut prin aparitia prompterului. Dupa ce utilizatorul a introdus o expresie Lisp interpretorul o evalueaza si daca aceasta expresie este corecta lexical, sintactic si semantic tipareste rezultatul evaluarii ei. Se spune ca interpretorul Lisp functioneaza intr-o bucla CITESTE-EVALUEAZA

ul are la baza limbajul Lisp. Jess poate procesa un numareguli (e unul dintre cele mai rapide motoare de inferenta bazate pe reguli) fiind un produs sotware extrem de stabil. Desi sintaxa Jess este similara lui CLIPS, totusi Jess si CLIPS sunt

Spre deosebire de Lisp, Jess nu suportă listele imbricate (liste care conțin alte liste). Acest modul în care codul Java este reprezentat în Jess și vice-versa. De exemplu, s

clasa Rete din pachetul jess

instantiaza un nou motor de inferenta

//executa comanda Jess

Este o paradigma care pleaca de la ideea specificarii unei demonstrarii automate de

programarea imperativa

Deoarece demonstrarea automata de teoreme are niste dezavantaje legate de caracterul sau xemplu, in Prolog se lucreaza cu clauze

Horn care reduc complexitatea calculului si nedeterminarea, introducand aspecte de control.

In limbajele functionale, functiile sunt componentele de baza are unui program, asa cum intructiunile sunt parte constructiva in programele procedurale, clauzele in programarea logica si obiectele in programarea orientata obiect. Un

Cel mai cunoscut reprezentant al paradigmei de programare functionala este limbajul Lisp. Deoarece Lisp este un limbaj interpretat dupa lansarea in executie a sistemului Lisp se intr-o

Semnalul ca interpretorul Lisp asteapta instructiuni pentru a fi executate este facut prin aparitia prompterului. Dupa ce utilizatorul a introdus o expresie Lisp interpretorul o evalueaza

ta lexical, sintactic si semantic tipareste rezultatul evaluarii EVALUEAZA-

Jess poate procesa un numar mare de reguli (e unul dintre cele mai rapide motoare de inferenta bazate pe reguli) fiind un produs sotware extrem de stabil. Desi sintaxa Jess este similara lui CLIPS, totusi Jess si CLIPS sunt

in alte liste). Acest versa. De exemplu, să

Page 5: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

5

public String getLabel() {return label;}

}

Clasa JavaTest poate fi scrisa folosind următoarele fapte Jess: (class (name JavaTest) (fields nr label) (methods getLabel))

(field (name nr) (class JavaTest) (access private) (type int))

(field (name label) (class JavaTest) (access public) (type String))

(method (name getLabel) (class JavaTest) (access public) (type String)

(body ″return label;″))

În prealabil, pentru a putea fi folosite, aceste fapte trebuiesc mai întâi declarate: (deftemplate field (slot name) (slot class) (slot access) (slot type))

Jess vs. Prolog

Desi sunt amandoua limbaje declarative, Prolog-ul si Jess-ul care este un sistem bazat pe algoritmul Rete sunt foarte diferite. Conceptul central al Prolog-ului este inlantuirea inapoi. Astfel, pe baza regulilor: mama(ana, maria).

copil(X, Y):- mama(Y, X).

cineva ar putea sa testeze daca copil(maria, ana) este adevarat. Pentru aceasta, Prologul aplica regula si ca rezultat va cauta sa verifice daca mama(ana, maria) este adevarat. Pentru o consultare ulterioara, din nou se va aplica regula, adica se va verifica relatia mama(ana,maria). Nu acelasi lucru se intampla pentru consultarile Jess datorita faptului ca in deductii se foloseste inlantuirea inainte. Mai exact, codul (assert (mama ana maria))

(defrule copil (mama ?X ?Y) => (assert (copil ?Y ?X)))

(watch facts)

(run)

nu este definit pentru a raspunde la interogari relative la relatia copil, ci este intentionat de a calcula ce instanta a relatiei copil se obtine pe baza relatiei mama(ana, maria) asertata. ==> f-1 (MAIN:: copil maria ana)

1 Odata ce relatia copil(maria,ana) este obtinuta, la executia urmatoare a codului nu se va mai aplica regula din nou. Jess este insa diferit de alte sisteme bazate pe algoritmul Rete prin faptul ca include un rationament inapoi folosit pentru interogarea directa a bazei de cunostinte prin intermediul constructiei defquery. Jess mosteneste de la Java pe langa caracteristicile de portabilitate si securitate si posibilitatea dezvoltarii aplicatiilor in programe stand-alone sau in browsere (applet-uri). Jess poate fi de asemenea folosit in medii multithread, fiecare obiect Jess.Rete reprezentand un motor de inferenta independent care poate fi rulat in paralel cu alte obiecte de acest tip. Cei mai importanti pasi in dezvoltarea unei aplicatii folosind shell-ul Jess vizeaza stabilirea arhitecturii optime pentru aplicatie si anume stabilirea ponderii codul scris in Jess si a celui in Java. Jess permite dezvoltarea de aplicatii (cu sau fara interfata GUI) fara a fi necesara compilarea nici unui rand de cod Java, sau invers se pot scrie aplicatii Jess folosind un minim cod Jess. Structura unei aplicatii tipice se situeaza undeva la mijloc intre aceste doua extreme astfel incat sistemul expert e scris in Jess iar modulul de interfata utilizator e construit folosind Java API (Application Programming Interfaces). Exista mai multe posibilitati, iar mai jos le enumeram in ordine crescatoare a ponderii codului Java implicat in dezvoltarea aplicatiei:

Page 6: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

1. 100%Jess Exclusiv cod Jess.2. Jess+Java API Cod Jess dar cu 3. most Jess + Java Majoritar cod Jess dar si cod specializat Java in care sunt definite

comenzi Jess. 4. main Jess + Java Pondere egala intre codul Jess si Java. Codul Java este folosit

pentru construirea interfetei si executie (punctul de intrare in program) este data de Jess.

5. Jess + Java Pondere egala intre codul Jess si Java. Codul Java este folosit pentru construirea interfetei si executie de comenzi Jess iar functia programator.

6. most Java In marea majoritate cod Java, care incarca cod Jess in timpul executiei (laseaza in executie programe Jess).

7. 100%Java In totalitate cod Java, iar entitatile Jess sunt manipulinterfetei (nu este suportata in totalitate pentru versiunea Jess61b1)

Desi Jess a fost initial dezvoltat ca o librarie care poate fi ipermite in plus si un mod de lucru interactiv la prompter Jess>classpath jess.jar jess.Main”) La prompterul Jess se pot executa pe rand instructiuni sau se pot rula programa .clp dupa cum urmeaza:

Jess> (printout t "Hello, World!" crlf)

Hello, World!

Jess> (batch hello.clp)

Hello, World!

Aceleasi instructiuni se pot rula si intrdupa modelul ``java -classpath jess.jar jess.Console

Limbajul Jess

Tipurile de date recunoscute de Jess suntsi string-uri (siruri de caractere delimitare de ghilimele “)

Exclusiv cod Jess. Cod Jess dar cu interfata construita folosind Java API

Majoritar cod Jess dar si cod specializat Java in care sunt definite

Pondere egala intre codul Jess si Java. Codul Java este folosit pentru construirea interfetei si executie de comenzi Jess dar functia main() a aplicatiei (punctul de intrare in program) este data de Jess.

Pondere egala intre codul Jess si Java. Codul Java este folosit pentru construirea interfetei si executie de comenzi Jess iar functia main() este definita de

In marea majoritate cod Java, care incarca cod Jess in timpul executiei seaza in executie programe Jess).

In totalitate cod Java, iar entitatile Jess sunt manipulate prin intermediul interfetei (nu este suportata in totalitate pentru versiunea Jess61b1)

Desi Jess a fost initial dezvoltat ca o librarie care poate fi integrata in aplicatii Java, Jess permite in plus si un mod de lucru interactiv la prompter Jess> (folosind comanda “

La prompterul Jess se pot executa pe rand instructiuni sau se pot rula programa .clp dupa cum

(printout t "Hello, World!" crlf)

Jess> (batch hello.clp)

Aceleasi instructiuni se pot rula si intr-o fereastra de dialog (prin apelarea clasei Jess. Console classpath jess.jar jess.Console”)

noscute de Jess sunt: simboluri (in Java se numesc identifica(siruri de caractere delimitare de ghilimele “). Limbajul Jess este case sensitive

Majoritar cod Jess dar si cod specializat Java in care sunt definite

Pondere egala intre codul Jess si Java. Codul Java este folosit () a aplicatiei

Pondere egala intre codul Jess si Java. Codul Java este folosit pentru () este definita de

In marea majoritate cod Java, care incarca cod Jess in timpul executiei

ate prin intermediul

ntegrata in aplicatii Java, Jess (folosind comanda “java -

La prompterul Jess se pot executa pe rand instructiuni sau se pot rula programa .clp dupa cum

o fereastra de dialog (prin apelarea clasei Jess. Console

(in Java se numesc identificatori), numere case sensitive,

Page 7: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

7

ceea ce inseamna ca face distinctie intre majuscule si minuscule. Astfel intnr, intNr, IntNr sunt simboluri diferite in Jess. Fiecare rand de comentariu este precedat de punct si virgula (;). Toate valorile Jess: simboluri, numere, stringuri, etc. sunt reprezentate intern prin instante ale clasei Java jess.Value.

Simboluri speciale in Jess Nume Semnificatie Java

nil null TRUE

java.lang.Boolean FALSE

crlf \n (newline) RU.STRING String

RU.INTEGER byte, short, int RU.LONG long RU.FLOAT double, float RU.ATOM char sau java.lang.Character RU.LIST un tablou Java

RU. EXTERNAL_ADDRESS instanta a unui obiect Java Tabel 1. Tipuri Jess si echvalentele lor in Java

O unitate fundamentala a fiecarui program Jess este lista. Elementele unei liste sunt incluse intre parantezele rotunde ( si ) iar primul element al listei se numeste capul listei. Dupa cum se va vedea, capul listei in marea majoritate a cazurilor are un rol special. In afara de utilizarea lor ca date pentru prelucrari, listele sunt folosite in Lisp si pentru scrierea programelor. Mai exact, in Jess datele si programele au aceeasi reprezentare, si anume liste. Orice apel de functie se scrie ca o lista folosind notatia prefixata astfel incat capul listei este numele functiei iar celelalte elemente reprezinta valorile de apel ale functiei. Observatie Regulile se scriu tot sub forma de liste, capul listei fiind in acest caz un cuvant rezervat, defrule. Functii in Jess Orice lista in Jess se presupune ca este un apel de functie, capul listei avand rolul de a identifica numele functiei. Jess vine cu un numar mare de functii built-in care implementeaza functii matematice, manipuleaza stringuri de caractere, controleaza executia programului, permit accesul la functiile Java API, etc. De exemplu, daca dorim sa ni se returneze rezultatul operatiei aritmetice 2+3 vom scrie: Jess> (+ 2 3)

5

Observatie Orice functie in Jess trebuie sa returneze o valoare, deci nu exista functii void in Jess. Observatie Putem avea apeluri de functii imbricate ca in exemplul de mai jos: Jess> (* (+ 2 3) (- 7 4))

15

Una dintre cele mai utilizate functii este cea de tiparire la iesirea standard, printout. Primul argument al functiei indica unde se sa face tiparirea (la ecran, intr-un fisier, la imprimanta) iar urmatoarele valori sunt cele care vor fi tiparite, fara a se intercala spatii intre ele: Jess> (printout t "Rezultatul este" (+ 2 3) "!" crlf)

Rezultatul este5!

O alta functie utila si des utilizata este batch. Aceasta evalueaza si executa cod Jess mai precis programe Jess. De exemplu, pentru a rula fisierul hello.clp care apartine directorului examples din pachetul de distributie Jess se da comanda: Jess> (batch examples/hello.clp)

Page 8: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

8

Hello, World!

Functii I/O Functia de scriere la consola standard de iesire:

(printout t “hello you!” crlf)

Functii de citire: (read) – citeste un singur element

(readline) – citeste un string de elemente

1. Exemplu de scriere si citire (fisier io1.clp): (printout t "Enter an integer" crlf)

(bind ?x (read t))

(if (> ?x 100) then

(printout t "A big number" crlf)

(* ?x ?x))

Jess> (batch "io1.clp")

Enter an integer

101

A big number

10201

2. Exemplu de scriere si citire (fisier io2.clp)

(printout t "Enter an integer" crlf)

(bind ?x (read t))

(if (> ?x 100) then

(printout t "A big number" crlf)

(* ?x ?x)

else

(printout t "A little number" crlf)

(sqrt ?x)

)

Jess> (batch "io2.clp")

Enter an integer

49

A little number

7.0

3. Exemplu de scriere/citire (io3.clp)

(printout t "Enter an integer" crlf)

(bind ?x (read t))

(if (> ?x 100) then

(printout t "A big number" crlf)

(* ?x ?x)

else (if (> ?x 50) then

(printout t "A medium number" crlf)

(/ ?x 2)

else

(printout t "A little number" crlf)

(sqrt ?x)))

Variabile in Jess

La fel ca variabilele Java, variabilele Jess pot retine o singura valoare, insa spre deosebire de primele nu sunt dependente de un tip anume. Asta inseamna ca pe parcursul existentei sale, o variabila poate fi unificata cu date de tipuri diferite, cum ar fi numere, stringuri, liste, etc.

Page 9: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

9

In general variabilele in Jess sunt identificate cu simboluri prefixate de caracterul ? (astfel, ? devine parte a numelui variabilei). O variabila nu trebuie declarata pentru a fi ulterior folosita. Ea se creaza in momentul in care i se atrbuie o valoare. Atribuirea de valori pentru variabilele Jess se face cu ajutorul functiei bind, ca in exemplul de mai jos: Jess> (bind ?var “string”)

“string”

Jess> (bind ?var 5)

5

Jess> (+ ?var 2)

7

Pentru a crea o lista de elemente (care sa nu fie reprezentarea unui apel de functie) se poate folosi functia create$ cu urmatoarea sintaxa: (bind nume_variabila (create$ lista_elemente))

De exemplu: Jess> (bind ?work_days (create$ mon tue wed thu fri))

(mon tue wed thu fri)

Acest tip de lista care are rolul de a stoca un numar de elemente fara a fi un apel de functie se numeste lista simpla (in engleza plain list). Pentru a accesa elementele unei astfel de liste se pot folosi functiile nth$ n (al n-lea element), first$ (lista formata din primul element) sau rest$ (lista formata din elementele listei prin excluderea capului listei). Jess> (first$ ?work_days)

(mon)

Jess> (rest$ ?work_days)

(tue wed thu fri)

Jess> (nth$ 3 ?work_days)

wed

Functia create$ poate primi ca argument si o lista de elemente, in acest caz rezultatul fiind reuniunea listei date cu restul argumentelor functiei. Jess> (bind ?week_days (create$ ?work_days sat sun))

(mon tue wed thu fri sat sun)

Orice variabila creata folosind cod Jess este distrusa in momentul folosirii comenzii reset. Deoarece aceasta comanda este utila pentru reinitializarea memoriei de lucru a motorului de inferenta Jess, apare firesc nevoia de a avea variabile care sa persiste dupa aceasta reinitializare. Astfel de variabile se numesc variabile globale, numele acestora este de forma ?*nume_variabila_globala* si se construiesc folosind comanda defglobal. Daca apelam functia (set-reset-globals nil) atuci comanda (reset) nu va modifica ultima valoare a variabilelor globale, altfel le va reinitializa cu prima valoare atribuita. Variabilele multicamp (in engleza, multifield) sunt un tip special de variabile, care, asa cum spune numele pot retine mai multe valori. Numele acestora trebuie prefixat de caracterele ?$ si sunt folosite in lista de argumente ale comenzii deffunction sau in membrul stang al regulilor.

Page 10: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

10

Figură 1 Exemplu utilizare set-reset-globals

Functii de control Una din facilitatile importante ale oricarui limbaj de programare este posibilitatea de a stabili in anumite puncte ale programului modul de continuare al prelucrarilor in functie de o anumita valoare (de control). Jess are un numar de functii predefinite care au rolul de a controla executia, de a grupa instructiuni, de a lua decizii si de a executa ciclari. Aceste functii sunt:

• apply – apeleaza o functie cu setul de date specificate • build – parseaza si executa apelul de functie specificat intr-un string de caractere • eval – parseaza si executa apelul de functie specificat intr-un string de caractere • foreach – executa un bloc de instructiuni pentru fiecare item al listei specificate • if/then/else – alege din mai multe alternative de executie • progn – executa un grup de apeluri de functii • while – executa un bloc de instructiuni cat timp o expresie este adevarata

Functia foreach evalueaza un bloc de instructiuni pentru fiecare item dintr-o lista simpla. Sintaxa acestei functii este: (foreach <nume_variabila> <nume_lista_simpla>

<bloc_instructiuni>)

Iata un exemplu de cod Jess ce foloseste functia foreach pentru a lista elementele listei ?week_days din sectiunea anterioara: Jess> (foreach ?day ?work_days (printout t ?day crlf))

mon

tue

wed

thu

fri

Functia foreach este utila atunci cand avem deja o lista de ciclare. Pentru definirea de cicluri mai generale se poate folosi functia while.

Page 11: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

11

Astfel, functia while permite repetarea unui grup de instructiuni atata timp cat o conditie este adevarata. Sintaxa acestei functii este: (while <expresie_booleana> do <bloc_instructiuni>)

Functia while evalueaza expresia booleana si daca rezultatul evaluarii este TRUE atunci toate apelurile din blocul de instructiuni sunt executate. Apoi expresia booleana este reevaluata si ciclul continua pana cand obtinem FALSE la evaluare. Din acest motiv functia while returneaza invariabil valoarea FALSE. Observatie Daca expresia booleana este falsa la prima evaluare atunci blocul de instructiuni nu se executa niciodata.

Figură 2 Functia while

Ciclul while decide in mod implicit ce cod se executa atunci cand evalueaza expresia booleana. Prin intermediul functiei if/then/else se pot defini decizii explicite asupra codului ce se executa. Sintaxa functiei if este similara instructiunii if din limbajul Java:

(if <expresie_booleana> then <bloc_instructiuni_then> [else

<bloc_instructiuni_else>])

Primul argument al functiei este o expresie booleana iar in functie de valoarea de adevar a acesteia se alege pentru executie unul din cele doua blocuri de instructiuni. De exemplu, sa reconsideram listele simple definite anterior ?week_days si ?work_days. Vom scrie un ciclu foreach care sa tipareasca care din zilele saptamanii sunt lucratoare si care nu. Jess> (foreach ?day ?week_days

(if (member$ ?day ?workday) then

(printout t ?day " is a working day " crlf)

else

(printout t ?day " is not a working day " crlf)))

mon is a working day

tue is a working day

wed is a working day

thu is a working day

fri is a working day

sat is not a working day

sun is not a working day

Putem forta iesirea din oricare doua blocuri de instructiuni prin folosirea functiei return. Valoarea returnata de functia if este valoarea de adevar a ultimei expresii evaluate. Intr-un mod asemanator limbajului Java se pot defini apeluri imbricate ale functiei if. Singura conditie este ca sa imbricam apelul unei alte functii if in cadrul blocului de instructiuni pentru ramura else. Jess> (bind ?x 3)

3

Jess> (bind ?y 5)

Page 12: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

12

5

Jess> (bind ?z 7)

7

Jess> (if (and (>= ?x ?y) (>= ?x ?z)) then

(printout t ?x " is the greatest ") else

(if (and (>= ?y ?x) (>= ?y ?z)) then

(printout t ?y " is the greatest " ) else

(if (and (>= ?z ?x) (>= ?z ?y)) then

(printout t ?z " is the greatest "))))

7 is the greatest

Functia if la fel ca functia while are ca prim argument o expresie booleana. In cazul in care avem nevoie de mai multe expresii astfel incat prin evaluarea lor sa obtinem valoarea booleana necesara in definirea conditiilor putem folosi functia progn. Functia progn evalueaza o lista de expresii si returneaza valoarea ultimei. Sintaxa functiei: (progn <lista_expresii>)

Aceasta functie este utila atunci cand dorim sa grupam mai multe expresii intr-una singura. De exemplu, daca dorim sa tiparim toti divizorii unui numar natural, codul ar putea sa fie scris ca mai jos: Jess> (bind ?nr 12)

12

Jess> (bind ?i 1)

1

Jess> (while (progn (bind ?i (+ ?i 1)) (<= ?i ?nr))

(if (= (/ ?nr ?i) (div ?nr ?i)) then

(printout t ?i " is divisor of " ?nr crlf)))

2 is divisor of 12

3 is divisor of 12

4 is divisor of 12

6 is divisor of 12

12 is divisor of 12

FALSE

Urmatoarele functii nu au echivalente in Java si sunt mai putin utilizate, insa pot deveni indispensabile in anumite cazuri. Ele sunt utilizate pentru a converti datele in cod, o particularitate care nu exista in programele compilate ca de exemplu, Java. In Java, pentru aceeasi operanzi daca vrem, de exemplu, sa-i adunam, sa-i inmultim, sau sa ii printam intr-un fisier va trebui sa definim linii de cod distincte pentru fiecare dintre aceste operatii. In Jess se poate scrie o singura linie de cod care, in functie de valorile unui singur argument poate sa execute toate aceste operatii si chiar mai multe. Toate aceastea folosind functia apply care poate primi ca prim argument un nume de functie. Sintaxa functiei este: (apply nume_function expresii)

Numele functiei se poate citi de la intrarea standard (in exemplul din Figura 3 numele functiei se citeste prin apelarea functiei read) sau poate fi stocat intr-o variabila care apoi este folosita in apelul functiei apply: Jess> (bind ?x 1)

1

Jess> (bind ?y 2)

2

Jess> (bind ?z 3)

3

Jess> (bind ?nume_funct max)

max

Jess> (apply ?nume_funct ?x ?y ?z)

3

Page 13: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

Limbaje compilate si limbaje Limbajele compilate sunt traduse în finumit compilator. Odată ce binarul a fost generat, fi nevoie de programul in care s-a generat. Pe de altaun program interpretor care citeşte codul surssistem. Sursa trebuie să fie re-interpretateste executat. Deoarece Jess este un limbaj interpretaturmeaza a fi executat. Acesta poate fi stocat intrla intrarea standard. Functiile evalrezulta ca putem scrie programe Jess care scriu alte programe Jess.

Rezulta o importanta caracteristica a timpul rularii acestea pot sa-si adauge noi reguli de rationament, adprograme care invata din deductiile obtinute! Functia eval accepta un singur argument, un string care cprocesat, evaluat si executat prin intermediul acestei functii. returnata de functie. Jess> (bind ?var "(str

"(str-cat \"happy\" \

Jess> (eval ?var)

"happymeal"

Observatie: Daca stringul ce se atribuie variabilei contine caracterul ghilimele (”) acesta trebuie prefixat de caracterul escape Functia build este sinonima functiei Jess> (build ?var)

"happymeal"

Figură 3 Functia apply

imbaje compilate si limbaje interpretate sunt traduse în fişiere executabile de cod maşină de un program

ce binarul a fost generat, fisierul executabil poate fi rulat fara a mai a generat. Pe de alta parte, un limbaj interpretat

care citeşte codul sursă şi îl traduce pe loc în calcule şi cheminterpretată (şi interpretorul prezent) de fiecare dată

ece Jess este un limbaj interpretat nu conteaza foarte mult de unde provine codul care urmeaza a fi executat. Acesta poate fi stocat intr-un fisier, intr-o variabila sau poate fi citit de

eval si build permit convertirea datelor Jess in cod Jess si astfel rezulta ca putem scrie programe Jess care scriu alte programe Jess.

Rezulta o importanta caracteristica a sistemelor bazate pe reguli scrise in Jess:si adauge noi reguli de rationament, adica putem obtine

din deductiile obtinute!

accepta un singur argument, un string care contine cod Jess ce urmeaza sa fie executat prin intermediul acestei functii. Rezultatul evaluarii este valoarea

Jess> (bind ?var "(str-cat \"happy\" \"meal\")")

\"meal\")"

: Daca stringul ce se atribuie variabilei contine caracterul ghilimele (”) acesta caracterul escape backslash.

este sinonima functiei eval.

de un program special fisierul executabil poate fi rulat fara a mai

depinde de şi chemări de

i interpretorul prezent) de fiecare dată când codul

nu conteaza foarte mult de unde provine codul care o variabila sau poate fi citit de

elor Jess in cod Jess si astfel

n Jess: in ica putem obtine

e urmeaza sa fie Rezultatul evaluarii este valoarea

: Daca stringul ce se atribuie variabilei contine caracterul ghilimele (”) acesta

Page 14: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

14

Functii aritmetice built-in

(+ ) (- ) (* ) (\ ) (** ) (mod )

(= ) (> ) (< ) (<= ) (>= ) (<> )

(and ) (or ) (not )

(random ) (min ) (max )

(sin ) (cos ) (tan ) (sqrt )

Desi Jess are peste 200 de functii built-in este nevoie totusi ca utilizatorii sa-si poata defini propriile functii. Pentru a pastra uniformitatea limbajului, definitia unei noi functii se face tot prin intermediul unei liste. O astfel de lista are pe prima pozitie cuvantul deffunction pentru a indica faptul ca urmeaza o definire de functie. Numele functiei ce se defineste este indicat in cel de-al doilea parametru urmat de lista argumentelor formale ale functiei: (deffunction nume_functie (<lista_parametrii>) [<comentarii>]

<bloc_instructiuni>)

Exemplu de functie construita cu deffunction: Jess> (deffunction varsta (?an)

”Calculeaza varsta unei persoane”

(bind ?varsta (- 2010 ?an))

(return ?varsta)) Din momentul evaluarii unei definitii de functie de catre interpretorul Jess, functie definita devine cunoscuta si poate fi astfel apelata prin intermediul numelui atribuit la fel ca si functiile predefinite: Jess> (varsta 1978)

32 Acesta este un exemplu de functie care nu utilizeaza functii de control. Un astfel de exemplu este dat mai jos: Jess> (deffunction maxim (?a ?b)

”Calculeaza maximul dintre cei doi parametrii”

(if (> ?a ?b) then

(return ?a)

else

(return ?b)))

Jess> (maxim 20 17)

20

Functia de mai sus se poate scrie si mai simplu astfel: Jess> (deffunction maxim (?a ?b)

”Calculeaza maximul dintre cei doi parametrii”

(if (> ?a ?b) then

?a

else

?b)) deoarece in mod implicit, orice functie in Jess returneaza valoarea ultimei expresii evaluate. In cazul in care am dori sa calculam maximul dintr-o lista de numere intregi pozitive, functia maxim devine: Jess> (deffunction maxim ($?args)

(bind ?max (nth$ 1 ?args))

(foreach ?n ?args

(if (> ?n ?max) then

(bind ?max ?n)))

?max)

TRUE

Jess> (maxim 10 100 77 6 43)

6

Page 15: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

15

Incheiem cu un alt exemplu de functie definita folosind deffunction care implementeaza functia fibonacci.

−+−

===

altfelnfibnfib

nsaunnfib

),2()1(

10,1)(

Jess> (deffunction fib (?f)

(if (or (= ?f 1) (=? f 0)) then

1

else

(+ (fib (- ?f 1)) (fib (- ?f 2))))

TRUE

Jess> (fib 5)

8 Exemple de functii pentru manipularea listelor 1. Diferenta de liste. Vom defini o functie care returneaza lista obtinuta din diferenta dintre lista din primul argument si lista din cel de-al doilea:

(deffunction list_diff (?list1 ?list2)

; se initializeaza ?rez cu lista vida

(bind ?rez (create$))

(foreach ?elem ?list1

(if (not (member$ ?elem ?list2)) then

(bind ?rez (create$ ?rez ?elem))))

(return ?rez))

Pentru a apela functia cream mai intai doua liste: Jess> (bind ?list1 (create$ 1 2 3))

(1 2 3)

Jess> (bind ?list2 (create$ 2 3 7))

( 2 3 7) si apoi apelam functia list_diff cu acestea. Automat lista diferenta va fi afisata. Jess> (list_diff ?list1 ?list2) (1) 2. Concatenarea a doua liste. Vom defini o functie care concateneaza doua liste simple (elementele celei de-a doua liste sunt adaugate la prima lista). (deffunction concat (?list1 ?list2)

(return (create$ ?list1 ?list2)) Apelul acestei functii cu listele create anterior va avea urmatorul rezultat: Jess> (concat ?list1 ?list2)

(1 2 3 2 3 7) 3. Produsul scalar a doua liste. Conditia pentru realizarea produsului este ca cele doua liste sa aiba aceeasi lungime. De exemplu produsul scalar pentru listele (1 2) si (3 4) trebuie sa returneze valoarea 1×3 + 2×4 = 11. (deffunction scalar_prod (?list1 ?list2)

; initializam rezultatul cu 0

(bind ?sum 0)

; testam daca listele au lungimi diferite

(bind ?lung1 (length$ ?list1))

(bind ?lung2 (length$ ?list2))

(if (neq ?lung1 ?lung2) then

(printout t "Listele au lungimi diferite" crlf)

else

(bind ?i 1)

(while (<= ?i ?lung1) do

(bind ?prod (* (nth$ ?i ?list1) (nth$ ?i ?list2)))

(bind ?sum (+ ?sum ?prod))

(bind ?i (+ ?i 1))))

Page 16: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

16

(return ?sum))

Jess> (scalar_prod ?list1 ?list2)

29

Jess: limbaj de scripting pentru Java Fara indoiala, cel mai mare avantaj al lui Jess este usurinta de a fi integrat in cod Java sau de a integra cod Java. Programele Java pot accesa orice componenta a librariei Jess astfel incat este usor sa includem cod Jess in aplicatii Java. Acelasi lucru este valabil si invers pentru ca si din Jess putem avea acces neingradit la clasele Java. Astfel, putem folosi limbajul Jess nu numai pentru a implementa sisteme de rationament bazate pe reguli dar si pentru a construi interfete grafice folosind Java API fara a scrie nici un rand de cod Java. Algoritmul Rete Ciclul de executie tipic pentru un sistem expert (și implicit cel folosit de Jess) constă în următorii pași:

� Potrivește faptele din baza de fapte cu cele din premiza regulilor din baza de reguli; mută regulile care s-au potrivit în agenda (activarea regulilor)

� Ordonează regulile din agenda potrivit unei strategii de rezolvare a conflictelor � Executa partea dreapta a regulilor din agenda în ordinea stabilită la punctul 2

De fiecare data când este introdusă comanda run la consolă, Jess realizeaza acești pași, potrivind fiecare regula cu fiecare fapt din memorie, până când nu mai sunt combinații de reguli și fapte care pot fi testate pentru potrivire. Implicit, Jess foloseste o politică “primul potrivit, primul executat” (first matched, first executed) pentru a ordona agenda. Exista totusi modalitati prin care programatorul poate influenta rezolvarea conflictelor. Fiecare regula in Jess are o prioritate, care specifica importanța regulii în raport cu altele asemănătoare ei. Regulile cu o prioritate mai mare sunt declansate înaintea celor cu prioritate mai mica. Programatorul poate stabili manual prioritatea unei reguli ca optiune a functiei defrule. Totusi, aceasta nu e paradigma programării declarative – programatorul mentioneaza in ce ordine sa se execute instructiunile, deoarece se elimină astfel unul dintre avantajele programarii declarative: intervenția programatorul în aplicarea regulilor de raționament. Daca un program necesita un astfel de control asupra ordinei executiei, poate un limbaj imperativ ar fi mai potrivit. Motorul de inferenta Jess creaza arbori de decizie care reprezinta regulile sistemului la un nivel inalt. Pentru fiecare arbore de decizie un nod corespunde unui sub-scop din membrul stang al unei reguli. Fiecare astfel de nod are un set de fapte care valideaza sub-scopul reprezentat in nod. Un drum complet in acest arbore trebuie sa lege fiecare sub-scop al unei reguli de concluzia corespunzatoare acesteia. De exemplu, pentru regulile: IF x AND y AND z THEN p IF x AND y THEN q se genereaza urmatorii arbori:

Page 17: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

17

Pentru fiecare executie, interpretorul cauta acele reguli pentru care concluziile trebuiesc vaditate. Daca concluzia nu are variabile, atunci se va cauta in memoria de lucru o expresie identica cu cea a concluziei. Daca concluzia are variabile atunci se va cauta o instantiere astfel incat aceasta sa fie consistenta cu celelalte instantieri utilizate pana in acel moment in satisfacerea concluziei. Algoritmul Rete prezinta urmatoarele caracteristici majore:

• Elimina anumite tipuri de reduntanta prin folosirea partajata a nodurilor. • Salveaza potrivirile partiale cand face join intre diferite tipuri de fapte. Aceasta la

randul ei permite sistemelor de productie sa evite reevaluarea completa a tuturor faptelor de fiecare data cand se fac schimbari in memoria de lucru a sistemului.

Manipularea obiectelor Java in Jess Pe langa functiile prezentate in capitolul anterior, Jess are definite functii prin intermediul carora se pot crea si manipula obiecte Java. Astfel, putem sa implementam in Jess aproape orice putem face in Java cu exceptia faptului ca din Jess nu putem construi clase Java.

Page 18: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

De exemplu, in loc sa contruim liste folosind formalismul Jess (prezentat in cursul anterior), putem sa le definim prin intermediul claselelor Java: instante ale claselor Java se face Jess> (bind ?hm (new java.util.HashMap))

<External-Address:java.util.HashMap>

Jess> (call ?hm put "white

Jess> (call ?hm put "black

Jess> (call ?hm get "

"0-0-0"

Jess atribute tipul RU.EXTERNAL_ADDRESS pentru a identifica obiectele in care sunt retinute instante ale claselor Java. La fel ca in Java si in Jess se poate evita identificarea claselor folosind numele pachetului din care fac parte prin folosirea cum urmeaza: Jess> (import java.util.*)

TRUE

Jess> (bind ?hm (new HashMap))

<External-Address:java.util.HashMap>

Cod Java import java.util.*; HashMap hm = new HashMap();hm.put("white", "255-255-255");hm.put("black", "0-0-0"); Set s = hm.keySet(); Object[] arr = s.toArray(); O referinta Jess la un obiect Java poate invoca metodele definite pentru obiectul in cauza prin intermediul functiei call asa cum se poate observa in exemplul considerat.acestei functii este referinta la obiect urmat de numele metodei sfolositi in apelare. Acesti parametrii sunt convertiti automat in tipurile Java corespunzatoare (a se vedea Tabelul 1). Mai mult, functia call poate fi omisa, apelul ei fiind considerat implicit atunci cand avem deface cu variabile Jess legate la obiecte Java. Deci, exemplulsimplificat din punctul de vedere al scrierii: Jess> (import java.util.*)

TRUE

Jess> (bind ?hm (new HashMap))

<External-Address:java.util.HashMap>

Jess> (?hm put "white" "

Jess> (?hm put "black" "0

sau mai mult: Jess> (import java.util.*)

TRUE

Jess> ((bind ?hm (new HashMap)) put "white" "255

Jess> (?hm put "black" "0

Metode statice in Java Metodele statice ale unei clase sunt un fel de funcnecesară crearea unei instanţe a clasei. Un exemplu de metodclasei principale a aplicaţiilor. Metodele statice nu pot utiliza atributstatice.

De exemplu, in loc sa contruim liste folosind formalismul Jess (prezentat in cursul anterior), putem sa le definim prin intermediul claselelor Java: Map, Set sau HashMap. C

se face prin intermediul functiei Jess new: Jess> (bind ?hm (new java.util.HashMap))

Address:java.util.HashMap>

(call ?hm put "white" "255-255-255")

(call ?hm put "black" "0-0-0")

get "black")

Jess atribute tipul RU.EXTERNAL_ADDRESS pentru a identifica obiectele in care sunt retinute instante ale claselor Java. La fel ca in Java si in Jess se poate evita identificarea claselor folosind numele pachetului din care fac parte prin folosirea functiei

Jess> (import java.util.*)

Jess> (bind ?hm (new HashMap))

Address:java.util.HashMap>

Cod Jess

= new HashMap(); );

(import java.util.*) (bind ?hm (new HashMap)) (call ?hm put "white" "255-255-(call ?hm put "black" "0-0-0") (bind ?s (?h keySet)) (bind ?list (?s toArray))

O referinta Jess la un obiect Java poate invoca metodele definite pentru obiectul in cauza prin asa cum se poate observa in exemplul considerat. Primul argument al

acestei functii este referinta la obiect urmat de numele metodei si de parametrii care sunt Acesti parametrii sunt convertiti automat in tipurile Java corespunzatoare

poate fi omisa, apelul ei fiind considerat implicit atunci cand avem dea obiecte Java. Deci, exemplul de mai sus poate fi in continuare

simplificat din punctul de vedere al scrierii: Jess> (import java.util.*)

Jess> (bind ?hm (new HashMap))

Address:java.util.HashMap>

(?hm put "white" "255-255-255")

(?hm put "black" "0-0-0")

Jess> (import java.util.*)

Jess> ((bind ?hm (new HashMap)) put "white" "255-255-255")

Jess> (?hm put "black" "0-0-0")

Metodele statice ale unei clase sunt un fel de funcţii globale şi se pot accesa fără să

ţe a clasei. Un exemplu de metodă statică este metoda iilor. Metodele statice nu pot utiliza atribute şi metode care nu sunt

De exemplu, in loc sa contruim liste folosind formalismul Jess (prezentat in cursul anterior), Construirea de

Jess atribute tipul RU.EXTERNAL_ADDRESS pentru a identifica obiectele in care sunt retinute instante ale claselor Java. La fel ca in Java si in Jess se poate evita identificarea

import, dupa

-255")

O referinta Jess la un obiect Java poate invoca metodele definite pentru obiectul in cauza prin Primul argument al

i de parametrii care sunt Acesti parametrii sunt convertiti automat in tipurile Java corespunzatoare

poate fi omisa, apelul ei fiind considerat implicit atunci cand avem de-a de mai sus poate fi in continuare

ără să fie este metoda main() a

i metode care nu sunt

Page 19: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

Atat in Java cat si in Jess metodele statice sunt apelate prin prefixarea lor cu numele clasei din care fac parte. Un bine cunoscut exemplu este functia invocata astfel: Jess> (call Thread sleep 1000)

va genera o pauza de o secunda a

1. In acest caz, nu mai trebuie explicit importat pachetul clasa Thread deoarece acesta este importat automat de catre Jess.2. Apelul metodelor statice se face i Iata un alt exemplu de functie in Jess care utilizeaza functia Short.MAX_VALUE din Java:

Jess>(import java.io.*)

Jess>(deffunction is_short (?i)

(if (> ?i (Short.MAX_VALUE)) the

((System.out) println “Prea mare pentru tipul

short”)

else

((System.out) println “Numarul poate fi stocat ca data

short”)))

TRUE

Jess> (is_short 3)

Numarul poate fi stocat ca data short

Jess nu are un editor prin intermediul caruia sa putem grupa cod Jess in fisiere cu extensia .clp care mai apoi sa fie executate folosind comanda prompterul Jess prin intermediul functiei Notepad pentru editarea fisierului Jess> (system notepad progr.clp &)

<External-Address:java.lang.ProcessImpl>

Specificarea caracterul & determina procese Jess sa fie rulate la linia de comanda Jess

Figură

Atat in Java cat si in Jess metodele statice sunt apelate prin prefixarea lor cu numele clasei din Un bine cunoscut exemplu este functia sleep a clasei Thread

read sleep 1000)

a executiei.

In acest caz, nu mai trebuie explicit importat pachetul java.lang din care face parte deoarece acesta este importat automat de catre Jess.

Apelul metodelor statice se face in mod necesar prin intermediul functiei call.

n Jess care utilizeaza functia System.out.println

Jess>(import java.io.*)

Jess>(deffunction is_short (?i)

(if (> ?i (Short.MAX_VALUE)) then

((System.out) println “Prea mare pentru tipul

((System.out) println “Numarul poate fi stocat ca data

Numarul poate fi stocat ca data short

Jess nu are un editor prin intermediul caruia sa putem grupa cod Jess in fisiere cu extensia .clp care mai apoi sa fie executate folosind comanda batch. Insa putem invoca un editor la prompterul Jess prin intermediul functiei system. Exemplul de mai jos, deschide aplicatia

pentru editarea fisierului progr.clp Jess> (system notepad progr.clp &)

Address:java.lang.ProcessImpl>

determina ca editorul sa ruleze in background, neblocand viitoare rulate la linia de comanda Jess.

Figură 4 Editarea fisierelor .clp cu Notepad

Atat in Java cat si in Jess metodele statice sunt apelate prin prefixarea lor cu numele clasei din care poate fi

din care face parte

System.out.println si constanta

((System.out) println “Prea mare pentru tipul

((System.out) println “Numarul poate fi stocat ca data

Jess nu are un editor prin intermediul caruia sa putem grupa cod Jess in fisiere cu extensia .clp Insa putem invoca un editor la

eschide aplicatia

ze in background, neblocand viitoare

Page 20: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

20

Interfata Grafica cu obiecte Java construita in Jess

O interfata de tip Graphical User Interface (GUI) se poate construi cu usurinta din Jess folosind instante de clase Java API. In aceasta sectiune prezentam un program Jess in care este definita o fereastra de dialog de tip java.awt. Frame populata cu un obiect de tip java.awt.Label si un buton java.awt.Button. Evenimentele generate la inchiderea ferestrei sau la apasarea butonului sunt gestionate din Jess de catre obiecte tip Listener. Enumeram mai jos clasele de tip EventListener in pachetul jess.awt:

jess.awt.ActionListener jess.awt.AdjustmentListener jess.awt.ComponentListener jess.awt.ContainerListener jess.awt.FocusListener jess.awt.ItemListener jess.awt.KeyListener jess.awt.MouseListener jess.awt.MouseMotionListener jess.awt.TextListener jess.awt.WindowListener

Valorile datelor membru ale obiectelor Java se pot obtine prin intermediul functiei Jess get-member. In mod echivalent, instantierea unei date membru a unui obiect Java se poate face folosind functia set-member. De exemplu, un obiect de tipul java.awt.Point are doua date membru:

x coordonata relativa la axa Ox y coordonata pe axa Oy

Astfel accesarea acestor membri se face conform codului: Jess> (bind ?p (new java.awt.Point))

<External-Address:java.awt.Point>

Jess> (set-member ?p x 10)

10

Jess> (set-member ?p y 20)

20

Jess> (printout t “(“ (get-member ?p x) “ , “ (get-member ?p y) “)”

crlf)

(10, 20)

Fisier frame1.clp ;; ****************************** (import java.awt.*) ;; ****************************** ;; Declaratii variabile globale (defglobal ?*f* = 0) (defglobal ?*b* = 0) ;; ****************************** ;; Definire functii (deffunction create-frame () (bind ?*f* (new Frame "Interfata Jess cu obiecte Java"))

Page 21: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

21

(?*f* setBackground (new Color 255 0 255)) (?*f* setLayout (new GridLayout 2 1))) (deffunction add-widgets () (?*f* add (new Label "Gestionarea evenimentelor cu obiecte Jess de tip Listener")) (bind ?*b* (new Button)) (?*b* setLabel "Hello!") (?*f* add ?*b*)) (deffunction add-behaviours () (?*f* addWindowListener (new jess.awt.WindowListener frame-handler (engine))) (?*b* addActionListener (new jess.awt.ActionListener button-handler (engine)))) (deffunction show-frame () (?*f* validate) (?*f* pack) (?*f* setSize 350 100) (?*f* show)) (deffunction frame-handler (?event) ;; verificam daca ID-ul lui ?event este cel de WINDOW_CLOSING (if (= (?event getID) (get-member ?event WINDOW_CLOSING)) then (call (?event getSource) dispose) (call System exit 0))) (deffunction button-handler (?event) (printout t "Hello, World!" crlf)) ;; ****************************** ;; executia programului (create-frame) (add-widgets) (add-behaviours) (show-frame) Executia fisierului duce la urmatoarea afisare:

Page 22: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

22

Captarea exceptiilor in Jess

Metodele Java semnaleaza erorile rezultate in timpul apelului prin intermediului unui mecanism de aruncare al execeptiilor (in engleza, throwing exceptions). O astfel de exceptie este tot un obiect Java si mesajul acestuia de eroare poate fi captat de Jess in momentul in care este generat. Acelasi mecanism a fost folosit si pentru functiile Jess, iar pentru procesarea unor astfel de exceptii se poate folosi functia (try ... catch ... [finally ...]) avand urmatoarea sintaxa: (try <bloc_instructiuni> catch <instructiuni_catch> [finally <instructiuni_finally>]) Functia try evalueaza expresiile din <bloc_instructiuni>. Daca una din acestea genereaza o eroare atunci abandoneaza executia pentru <bloc_instructiuni> si trece la executarea <instructiuni_catch>. Putem avea in continuarea blocului catch si un bloc suplimentar finally, la fel ca in Java. Obiectul rezultat in urma aparitiei exceptiei poate fi accesat in cadrul blocului catch prin intermediul variabilei ?ERROR. Deosebirea fata de blocul try-catch din Java consta in faptul ca in Jess nu se poate folosi decat un singur bloc catch iar diferentierea dintre tipurile de exceptii ce pot rezulta se face folosind metoda instanceOf apelata pentru variabila ?ERROR. Mai jos prezentam un program Jess care citeste de la intrarea standard un nume de fisier si afiseaza la iesirea standard continutul acestuia. (import java.util.*) (import java.io.*) (bind ?file nil) (try (printout t ”Dati numele fisierului” crlf) (bind ?name (read t)) (bind ?file (new BufferedReader (new FileReader ?name))) (while (neq nil (bind ?line (?file readLine))) (printout t ?line crlf)) catch

Page 23: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

23

(printout t "Eroare la procesarea fisierului" crlf) finally (if (neq nil ?file) then (?file close)))

Reprezentarea faptelor in Jess

Odata ce am prezentat sintaxa limbajul Jess putem trece la un studiul dezvoltarii regulilor in acest limbaj de programare. Vom incepe prin prezentarea modului in care putem sa specificam in Jess datele necesare pentru aplicarea regulilor, mai precis vom discuta despre modul de organizare al memoriei de lucru (in engleza, working memory). Memoria de lucru mai este denumita si baza de fapte (fact base) sau baza de cunostinte (knowledge base) si contine toate acele informatii necesare in obtinerea deductiilor. Structura acesteia aminteste de cea a bazelor de date relationale, deoarece toate faptele incarcate in memoria de lucru au o reprezentare comuna. În CLIPS există trei forme principale de reprezentare a informaţiei: fapte (facts), obiecte şi variabile globale. Faptele sunt forma principală de reprezentare a informaţiei în sistemul CLIPS. Si in Jess faptul este forma fundamentală de date folosită de reguli şi constă într-un nume de relaţie urmat de zero sau mai multe sloturi (câmpuri simbolice cărora li se pot asocia valori). Un slot trebuie să aibă obligatoriu asociată o valoare. Valoarea pe care putem sa o asociem unui slot poate lua forma unui tip de dată primitivă (integer, float, symbol, string). Un fapt este cea mai mica structura de informatie care poate fi incarcata sau extrasa din memoria de lucru a unui sistem bazat pe reguli. In Jess exista trei tipuri de fapte: fapte

ordonate (ordered facts), fapte neordonate (unordered facts) si fapte de tip definstance (definstance facts). La fel ca toate celelalte constructii in Jess, faptele sunt reprezentate sub forma de liste. Fapte ordonate Un fapt ordonat (ordered fact) constă într-un nume de relaţie urmat de zero sau mai multe câmpuri separate de spaţii. Acesta ar putea fi comparat cu un slot de tip multifeld (multi-câmp) în care se pun toate valorile ce urmează după numele de relaţie. Faptele ordonate sunt create automat de un deftemplate implicit. Astfel se poate implementa relativ uşor o stivă sau o coadă (şiruri de elemente). De exemplu, urmatoarele scrieri sunt asimilate drept fapte ordonate:

(numere_prime 2 3 5 7 11) (numere_pare 2 4 6 8 10)

Observam, ca in esenta, faptele ordonate sunt liste simple in Jess in care capul listei are un rol special, el specificand categoria de informatie a datelor stocate in respectivul fapt. De exemplu: (lista-fructe mere pere mango)

(angajat ”Ion Popescu” 35 sef-departament)

Câmpurile dintr-un fapt ordonat pot fi orice tip de dată primitivă (cu excepţia primului câmp care reprezintă numele de relaţie şi care trebuie să fie de tip simbol) şi nu există restricţii privitoare la ordinea acestora. Totuşi, următoarele simboluri sunt rezervate şi nu pot fi primul câmp dintr-un fapt: test, and, or, not, declare, logical, object, exists, şi forall (asupra acestor simboluri vom reveni mai departe in acest capitol).

Page 24: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

24

Jess are predefinite functii prin intermediul carora se poate manipula continutul memoriei de lucru. Aceste functii pot fi utilizate in programe Jess cu scopul de a modifica in timpul executiei memoria de lucru.

assert: incarca fapte in memoria de lucru (clear): sterge in totalitate continutul memorie de lucru deffacts: defineste continutul initial al memoriei de lucru (facts): afiseaza lista faptelor incarcate in momentul respectiv in memoria de lucru (reset): reinitializeaza memoria de lucru prin revenirea la continutul initial al memoriei de

lucru retract: scoate faptele precizate din memorie de lucru watch: are rolul de a supraveghea continutului memoriei de lucru si de a anunta

modificarile survenite; atunci cand se doreste suprimarea monitorizarii memoriei de lucru se apeleaza functia unwatch. In functie de parametrii folositi in apelul functie watch, Jess ofera informatii despre anumite componente ale memoriei de lcuru, ca de exemplu: Jess> (watch facts)

TRUE

Jess> (reset)

==> f-0 (MAIN::initial-fact)

TRUE

Jess> (unwatch facts)

TRUE

Semnul ==> indica incarcarea in memorie a unui nou fapt, in vreme ce <== indica extragerea din memorie a unuia sau mai multor fapte.

Desi se poate utiliza apelul (watch facts) pentru a se urmari faptele din memoria de lucru, o mai buna informare asupra acestor elemente se obtine folosind functia (facts).

Figură 5 Functia (facts)

Dupa cum se vede in Figura 5, fiecarui fapt i se atribuie un numar de index, numit fact-id. Un fact-id este un numar mai mare sau egal cu 0, de regula (MAIN::initial-fact) are fact-id = 0. Un fapt care are id-ul maxim inseamna ca a fost ultimul adaugat in memoria de lucru. Pe baza acestor indecsi se pot referi un mod unic faptele incarcate in memorie. Vom relua exemplul din Figura 5 pentru a exemplifica modul in care se pot identifica prin fact-id faptele asertate in memoria de lucru cu scopul extragerii lor din memorie sau pentru a fi atribuite variabilelor de lucru. Jess> (facts)

f-0 (MAIN::initial-fact)

Page 25: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

25

f-1 (MAIN::lista-fructe mere pere mango)

For a total of 2 facts.

Se extrage din memorie faptul cu id-ul 1. Jess> (retract 1)

TRUE

sau, echivalent Jess> (retract (fact-id 1)) TRUE Continutul memoriei prin eliminarea faptului cu id-ul 1 este:

Jess> (facts)

f-0 (MAIN::initial-fact)

For a total of 1 facts.

Faptul cu id-ul 0 se atribuie variabilei ?f si prin intermediul acesteia este referit pentru a fi mai apoi scos din memorie.

Jess> (bind ?f (fact-id 0))

<Fact-0>

Jess> (retract ?f)

TRUE

Jess> (facts)

For a total of 0 facts.

Totusi nu este indicat sa se retraga MAIN::initial-fact din memorie deoarece Jess foloseste acest fapt pentru a tine evidenta operatiilor efectuate. De exemplu, Jess foloseşte acest fapt pentru activarea regulilor care nu au nici un element condiţional în membrul stang. De aceea, atunci cand avem de rulat un program nou, e bine ca operatiile acestuia sa fie precedate de comanda (reset) care are ca scop revenirea la continutul initial al memoriei, implicit prin reincarcarea in memorie a lui MAIN::initial-fact in cazul in care acest fapt fusese in prealabil extras. Asa cum am precizat, identificatorul de fapt al lui initial-fact este întotdeauna f-0 , deoarece acesta este primul fapt ce va fi introdus de Jess în lista de fapte după ce a fost dată comanda (reset). Gruparea faptelor. Constructorul deffacts Într-un program este foarte avantajos ca să se poată adauga toate faptele ce reprezintă baza iniţială de cunoaştere într-o singură aserţiune. Aceste fapte sunt cunoscute a fi adevărate încă înainte de rularea programului. Se poate defini un grup de fapte care reprezintă baza iniţială de cunoaştere cu ajutorul construcţiei deffacts. Cu alte cuvinte, daca dorim ca in continutul initial al memoriei sa avem mai mult decat faptul MAIN::initial-fact putem folosi constructia deffacts. In cadrul construcţiei deffacts poate fi folosit ca nume orice simbol valid. După numele construcţiei urmează opţional un comentariu şi apoi faptele ce vor fi asertate în lista de fapte. Pentru a realiza asertarea faptelor dintr-o declaraţie deffacts trebuie obligatoriu utilizată comanda reset. Efectul acestei comenzi este acela că şterge toate faptele din baza de fapte (ca şi comanda clear ) şi introduce faptele din declaraţiile deffacts. Sintaxa comenzii este:

Jess> (reset) Se va putea observa de asemenea din exemplele care urmeaza, că o dată cu comanda reset

este introdus în lista de fapte si iniţial fact. Observatie. Acest fapt este folosit in Jess pentru a aprinde o regulă care nu are nici un element condiţional în partea stanga a regulii, adica in premiza (membrul LHS). Avantajele oferite de deffacts sunt considerabile, ceea ce il fac un bun candidat pentru construirea bazei de cunostinte a oricarui program Jess bazat pe cunostinte:

Page 26: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

26

inglobeaza mai multe definiri de fapte; in loc sa apelam assert pentru fiecare fapt pe care vrem sa-l incarcam in memorie, deffacts poate fi folosit pentru un set de fapte; mai precis, cu ajutorul lui deffacts putem defini o lista de fapte

faptele definite cu ajutorul lui deffacts compun continutul initial al memoriei de lucru sau baza initiala de cunostinte astfel incat la orice folosire ulterioara a comenzii (reset) se poate reveni la starea problemei descrisa de faptele astfel definite.

Observatie Efectul comenzi reset este acela că şterge toate faptele din baza de fapte (ca şi comanda clear) dar in plus, introduce in memorie faptul initial si faptele din declaraţiile deffacts. Exemplu de utilizare a functiei deffacts: Jess> (clear)

TRUE

Jess> (deffacts tip_mere ”Sortimente de mere”

(mar ”Cortland” dimensiune-mare culoare-rosie)

(mar ”Golden Delicious” dimensiune-mare culoare-galbena)

(mar ”Red Delicious” dimensiune-medie culoare-rosie)

(mar ”Granny Smith” dimensiune-mare))

Jess> (facts)

For a total of 0 facts.

Jess> (reset)

TRUE

Jess> (facts)

f-0 (MAIN::initial-fact)

f-1 (MAIN::mar "Cortland" dimensiune-mare culoare-rosie)

f-2 (MAIN::mar "Golden Delicious" dimensiune-mare culoare-galbena)

f-3 (MAIN::mar "Red Delicious" dimensiune-medie culoare-rosie)

f-4 (MAIN::mar "Granny Smith" dimensiune-mare)

For a total of 5 facts.

Fapte neordonate. Constructorul deftemplate In exemplul din sectiunea anterioara am folosit deffacts pentru a reprezenta informatii despre diferite tipuri de mere in fapte ordonate. Desi sunt usor de prelucrat, faptele ordonate nu pot structura datele in campuri sau slot-uri ca in programarea orientata-obiect. Pentru aceasta este indicat sa se foloseasca reprezentarea oferita de faptele neordonate. Faptele neordonate sunt asemanatoare inregistrarilor dintr-un tabel de date relational, sloturile specificand numele campurilor in care se stocheaza datele inregistrarii. Exemplu. Sa consideram tabelul din Figura de mai jos.

Figură 6 Baza de date relationala

Datele din tabelul tip_mere poate fi cu usurinta reprezentat in Jess folosind faptele neordonate, grupate intr-o constructie deffacts. (deffacts tip_mere ”Sortimente de mere”

(mar (soi ”Cortland”) (dimensiune mare) (culoare rosie))

(mar (soi ”Golden Delicious”) (dimensiune mare) (culoare galbena))

(mar (soi ”Red Delicious”) (dimensiune medie) (culoare rosie))

Page 27: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

27

(mar (soi ”Granny Smith”) (dimensiune mare) (culoare verde)))

Pentru crearea unor astfel de fapte, care sunt formate din mai multe sloturi, trebuie mai întâi ca acestea să fie declarate, astfel încât Jess-ul să poată să interpreteze acele sloturi ca fiind valide şi nu ca fiind nişte funcţii. Special pentru acest lucru avem construcţia deftemplate care va face ca o grupare de fapte cu acelaşi nume de relaţie să conţină un anumit tip de informaţie. Pentru acest lucru, constructorul deftemplate are rolul de a crea un şablon ce va fi folosit pentru a accesa câmpurile faptului după nume. Acesta este identic cu o structură

definită într-un limbaj de programare procedural cum ar fi C. In Jess functia deftemplate are urmatoarea sintaxa: (deftemplate <nume_template> [extends <nume_clasa>] [<comentariu>]

[(slot <nume_slot>

[(default | default-dynamic

<valoare>)]

[(type <typespec>))]*)

Fiecare astfel de template poate contine unul sau mai multe slot-uri. Prin intermediul cuvantului cheie default se specifica <value>, valoarea default pentru respectivul slot, folosita in cazul in care nu este precizata o valoare anume in faptul care se creaza folosind tenplate-ul. Pentru o valoare dinamica (precizata cu default-dynamic), aceasta este evaluata de fiecare data cand faptul construit folosind acest template este incarcat in memorie. De obicei valoarea corespunzatoare lui default-dynamic este obtinuta prin intermediul unei functii. De exemplu, daca dorim caautomat sa se salveze data la care un fapt a fost incarcat in memorie putem sa definim un slot cu valoare default dinamica de maniera urmatoare: (deftemplate nume_template

...

(slot data_creare (default-dynamic (time)))

... )

Campul type este acceptat in Jess dar nu este obligatoriu; acesta precizeaza tipul datei care se va memora in slot. Acesta poate fi: ANY, INTEGER, FLOAT, NUMBER, ATOM, STRING, LEXEME, si OBJECT. Iata cum ar arata template-ul pentru faptele tip_mere construite mai sus: (deftemplate mar

(slot soi (type STRING))

(slot dimensiune (type STRING))

(slot culoare (type STRING) (default rosie)))

Daca dorim ca un slot sa poata retine mai mult decat o valoare atunci il definim ca fiind multislot. Valoarea default pentru un multislot este lista vida (). Un exemplu in acest sens este cel care urmeaza: (deftemplate colectie (slot nume)

(multislot itemuri))

(assert (colectie (nume gradina) (itemuri manusi sapaliga

foarfeca)))

(assert (colectie (nume fluturi) (itemuri emperor painted_lady

blue_butterfly))) sau folosind constructia deffacts:

(deffacts colectii

(colectie (nume gradina) (itemuri manusi sapaliga foarfeca))

(colectie (nume fluturi) (itemuri emperor painted_lady

blue_butterfly)))

Page 28: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

Iata un alt exemplu de fapt neordonat pentru memorarea studentilorastfel:

(deftemplate student “Comentariu optional”

(multislot nume)

(slot nr_grupa)

(slot an))

Atunci cand construim un fapt neordonat pe baza unui template, sloturile pot fi precizate in alta ordine decat cea in care apar definite in template. Insa atunci cand sistemul afiseaza lista faptelor create prin apelarea lui campurile acestora vor fi afisate folosind ordinea standard (specificata in Odata ce un set de fapte neordonate duplicate permit modificarea sau copierea lor. Sintaxa functiei modify este: (modify fact-id (nume_slot valoare_noua))

iar valoarea returnata de functie este idapel. Corespunzator, sintaxa functiei (duplicate fact-id [(nume_slot

valoare_propriek)])

in care fact-id este id-ul faptului care se copiaza, in timp ce idreturneaza ca valoare rezultat a acestei functii. Lista de perechi valoare_proprie1) ... (nume_slotvaloare se redefineste in faptul rezultat in urma copierii. Fapte ordonate vs. fapte neordonateJess-ul face deosebirea între un ordered

fapt (numele de relaţie) şi comparândudeftemplate, schimbând ordinea sloturilor se obschimbând ordinea câmpurilor se ob

(lista 2 3 4) diferit de (lista 4 3 2)Uneori este mai avantajoasă folosirea unui fapt de tip deftempate în locul unui fapt ordonat, deoarece se specifică prin numele sloturilor dintre cele două fapte este de preferat un fapt deftemplate:

(locuinta “Bistitei” 32 X1 A 12)

(locuinta (strada “Bistritei 32”) (bloc X1) (scara A) (apartament

12))

Fapte de tip definstance – sau obiecte JavaUn fapt de tip definstance (definstance fact

campuri corespund proprietatilor unui obiect corespondent in constructiile JavaBean

poate modifica in timpul ciclului de viata al unui obiect.

Remember O clasa Java oarecare poate fi considerata clasa notatie, de definire a constructorilor si a proprietatilor:

Iata un alt exemplu de fapt neordonat pentru memorarea studentilor, care ar putea fi descris

mplate student “Comentariu optional”

(multislot nume)

(slot nr_grupa)

Atunci cand construim un fapt neordonat pe baza unui template, sloturile pot fi precizate in alta ordine decat cea in care apar definite in template. De aici numele de fapte

Insa atunci cand sistemul afiseaza lista faptelor create prin apelarea lui (facts)urile acestora vor fi afisate folosind ordinea standard (specificata in deftemplate

un set de fapte neordonate a fost incarcat in memoria de lucru, functii ca permit modificarea sau copierea lor.

id (nume_slot valoare_noua))

iar valoarea returnata de functie este id-ul faptului ce a fost modificat, deci fact-apel. Corespunzator, sintaxa functiei duplicate este:

id [(nume_slot1 valoare_proprie1) ... (nume_slotk

ul faptului care se copiaza, in timp ce id-ul faptului nou creat se loare rezultat a acestei functii. Lista de perechi

) ... (nume_slotk valoare_propriek) reprezinta acele campuri avaloare se redefineste in faptul rezultat in urma copierii.

onate vs. fapte neordonate ordered-fact şi un deftemplate-fact extrăgând primul câmp din

i comparându-l apoi cu numele fiecărui deftemplate. Dacdeftemplate, schimbând ordinea sloturilor se obţinea acelaşi fapt, în schimb la un fact ordonat schimbând ordinea câmpurilor se obţine un alt fapt.

(lista 4 3 2) folosirea unui fapt de tip deftempate în locul unui fapt ordonat,

prin numele sloturilor semnificaţia fiecărui câmp. In cazul urm fapte este de preferat un fapt deftemplate:

“Bistitei” 32 X1 A 12)

(strada “Bistritei 32”) (bloc X1) (scara A) (apartament

sau obiecte Java incarcate in memoria de lucru definstance fact sau shadow fact) este un fapt neordonat ale carui

campuri corespund proprietatilor unui obiect JavaBean. Slot-urile faptelor neordonate au JavaBean datele membru sau proprietatile a caror valoare se

poate modifica in timpul ciclului de viata al unui obiect.

O clasa Java oarecare poate fi considerata clasa JavaBean daca respecta anumite conventii de torilor si a proprietatilor:

ar putea fi descris

Atunci cand construim un fapt neordonat pe baza unui template, sloturile pot fi precizate in fapte neordonate.

(facts), atunci deftemplate).

in memoria de lucru, functii ca modify sau

-id precizat in

ul faptului nou creat se loare rezultat a acestei functii. Lista de perechi (nume_slot1

reprezinta acele campuri a caror

gând primul câmp din deftemplate. Dacă la un fapt

chimb la un fact ordonat

folosirea unui fapt de tip deftempate în locul unui fapt ordonat, rui câmp. In cazul următor,

(strada “Bistritei 32”) (bloc X1) (scara A) (apartament

) este un fapt neordonat ale carui urile faptelor neordonate au ca si

datele membru sau proprietatile a caror valoare se

daca respecta anumite conventii de

Page 29: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

29

1. clasa trebuie sa aiba un constructor public default (fara parametrii) 2. Proprietatile clasei trebuie sa fie accesibile folosind metode de tip getter (de exemplu getValue()) sau setter (setValue(newValue)). 3. Clasa trebuie sa fie serializabila (adica sa implementeze interfata java.io.Serializable) O proprietate pentru un obiect JavaBean se poate accesa sau modifica si prin intermediul unor functii membru specializate de tip getter sau setter ca in exemplul de mai jos. In acest caz, data membru este protejata de accesari sau modificari directe prin intermediul modificatorul de acces (vizibilitate) private sau protected: public class SimpleBean implements java.io.Serializable{

/* proprietati */

private String label = ””;

/* constructor default */

public SimpleBean() {}

/* metode getter si setter */

public String getLabel() {

return label;

}

public void setLabel(String label) {

this.label = label;

}

}

In Jess astfel de functii se pot apela folosind notatia prefixata: (?bean setLabel “Hint”)

(?bean getLabel)

Functia Jess care construieste template-uri pe baza definitiei unei clase Java este defclass in timp ce functia definstance poate fi folosita pentru a incarca in memorie fapte neordonate ce au structura obtinuta prin intermediul unui apel defclass. Astfel, faptele construite cu definstance pot fi asimilate unor instante de clase Java. Pentru a putea apela functia defclass cu numele unei clase Java, fisierul .class trebuie sa fie accesibil lui Jess, adica sa se gaseasca in una din caile specificate in CLASSPATH. Jess> (defclass template_pct java.awt.Point)

java.awt.Point Primul argument al functiei defclass devine nume de template. Structura unui astfel de template obtinut prin intermediul functiei defclass se poate vizualiza folosind functia ppdeftemplate.

Jess> (ppdeftemplate template_pct) "(deftemplate MAIN::template_pct extends MAIN::__fact \"$JAVA-OBJECT$ java.awt.Point\"

(slot class (default <External-Address:jess.aq>)) (slot location (default <External-Address:jess.aq>)) (slot x (default <External-Address:jess.aq>)) (slot y (default <External-Address:jess.aq>)) (slot OBJECT (type 2048)))" Slotul class corespunde valorii returnata de metoda getClass(), metoda pe care orice obiect Java o mosteneste de la java.lang.Object, iar slotul OBJECT este adaugat de Jess ca o referinta la JavaBeans. Celelalte sloturi corespund proprietatilor obiectelor de tip java.awt.Point.

Page 30: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

30

Rezumand, pentru a crea o instanta a unei clase Java ce respecta formalismul JavaBean, avem nevoie de un template pe baza caruia sa putem construi faptul Jess corespunzator instantei dorite. Un astfel de template se defineste folosind functia defclass iar pe baza lui se incarca fapte in memorie cu ajutorul comenzii definstance, ca in exemplul urmator: Jess> (defclass template_pct java.awt.Point)

java.awt.Point

In variabila ?pct se memoreaza o instanta a clasei Java: Jess> (bind ?pct (new java.awt.Point))

<External-Address:java.awt.Point>

iar aceasta instanta este corelata unui fapt Jess de tip template_pct folosind functia definstance cu modificatorul de acces static.

Jess> (definstance template_pct ?pct static)

<Fact-0>

Jess> (facts)

f-0 (MAIN::template_pct

(class <External-Address:java.lang.Class>)

(location <External-Address:java.awt.Point>)

(x 0.0)

(y 0.0)

(OBJECT <External-Address:java.awt.Point>))

For a total of 1 facts.

Observam ca un fapt cu numele MAIN::template_pct este incarcat in memoria de lucru, acesta corespunzand clasei java.awt.Point. El poate fi invocat in rationamente bazate pe reguli asa cum vom vedea in sectiunile urmatoare. Daca dorim sa modificam proprietatile unui fapt de tip definstance, ... Jess> (?pct setLocation 10 20)

Reprezentarea regulilor in Jess

In acest moment stim cum sa populam memoria de lucru cu faptele necesare procesului de rationament. Pe langa acestea, este nevoie de o baza de cunostinte care in cazul sistemelor bazate pe reguli este compusa din regulile de rationament. O regulă este o colecţie de condiţii şi de acţiuni ce urmează a fi executate dacă condiţiile sunt îndeplinite. Una din metodele primare de reprezentare a cunoaşterii în Jess este regula. O regulă este o colecţie de condiţii şi de acţiuni ce urmează a fi executate dacă condiţiile sunt îndeplinite. Un sistem expert trebuie să aibă atât reguli, cât şi fapte. Regulile executate sau ‘aprinse’ se bazează pe existenţa sau non-existenţa unor fapte sau instanţe ale unei clase definite de utilizator. Mecanismul (motorul de inferenţă) al Jess-ului aşteaptă potrivirea regulilor cu starea curentă a sistemului (reprezentată de lista de fapte şi lista de instanţe) şi apoi aplică acţiunile. Modul de aplicare a regulilor depinde de continutul memoriei de lucru si de strategia de control utilizata: inlantuirea inainte (forward chaining) si inlantuirea inapoi (backward

chaining). Spunem ca o regula este aplicata (in engleza, fired) atunci cand actiunile corespunzatoare concluziei sunt lansate in executie. Regulile pot fi definite la prompterul Jess sau pot fi încărcate dintr-un fişier cu reguli, creat cu un editor. Se poate folosi în acest scop editorul încorporat al Jess-ului sau oricare alt editor. Faţă de introducerea direct în top level a regulilor sau comenzilor, folosirea unui editor aduce posibilitatea corectării eventualelor erori, fără a mai fi necesară rescrierea din nou a regulii. Ne putem imagina cazul în care un calculator ce are introduse deja faptele şi regulile, avertizează operatorul ca în acea zi se dau salariile. Pseudocodul ar fi:

IF ziua curenta este 14 THEN răspunsul este “caseria trebuie să distribuie salariile”

Page 31: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

31

Presupunem din exemplul anterior ca fiind deja asertat faptul data(cu sloturile zi luna an). In acest caz regula noastră ar putea arăta astfel:

(defrule actiunea_zilei “Zi de salariu”

(data (zi 14))

=>

(assert (actiune “caseria da banii…”) ) )

Revenind la exemplul din sectiunea anterioara unde au fost definite faptele locuinta putem presupune ca exista un dispozitiv GPS care furnizeaza in permanenta numele strazii pe care

ne aflam: IF strada furnizata de GPS este Independentei

THEN ofera informatii cu privire la Locuinta1 IF strada furnizata de GPS este Bistritei

THEN ofera informatii cu privire la Locuinta2 (defrule locuinta1 (defrule locuinta2

(locuinta (strada Independentei)) (locuinta (strada Bistritei))

=> =>

(informatii “Bloc X1, Sc. A, Ap 12”) (informatii “Bloc X2, Sc. B, Ap.

12”)

Redefinirea unei reguli deja existente, face ca regula anterioară cu acelaşi nume să fie ştearsă, chiar dacă regula actuală nou introdusă are erori. După cum se observă după numele regulii care poate fi orice simbol valid, după comentariu opţional care trebuie cuprins între ghilimele (comentariile pot fi introduse şi după punct şi virgula ’ ; ‘) urmează zero sau mai multe condiţii (pattern-uri) şi apoi zero sau mai multe acţiuni. Practic o regulă este formată din două părţi LHS şi RHS separate de secvenţa de caractere => pe care o putem numi şi săgeată, formată dintr-un semn ‘egal’ şi un semn ‘mai mare decât’ . In comparaţia regulii cu un IF-THEN săgeata marchează începutul părţii THEN. Partea stângă LHS este formată din zero sau mai multe elemente condiţionale, care sunt legate între ele de un and implicit. RHS-ul este format dintr-o listă de acţiuni care sunt executate dacă şi numai dacă toate elementele condiţionale (pattern-urile) sunt satisfăcute. Nu există nici o limită pentru numărul de condiţii sau de reguli dintr-o regulă, singura limitare o constituie memoria actuală valabilă. Jess-ul aşteaptă îndeplinirea pattern-urilor unei reguli pentru validarea acesteia, in acest sens verificând permanent faptele din memoria de lucru. Atunci când toate pattern-urile se potrivesc cu faptele, regula este activată şi este pusă în agenda. Agenda reprezintă în Jess o colecţie de reguli activate. Arhitectura Jess pentru Sisteme Expert Un sistem expert bazat pe reguli foloseste un set de reguli pentru a deriva concluzii pe baza premizelor. Arhitectura Jess pentru un astfel de sistem este formata din urmatoarele componente: • Baza de reguli (baza de cunostinte) • Memoria de lucru (baza de fapte) • Motorul de inferenta (obligatoriu bazat pe reguli)

Deoarece inferenta este orientata pe reguli, motorul de inferenta este compus din: • Pattern Matcher – activeaza regulile in functie de continutului memoriei de lucru. • Agenda – stabileste ordinea in care regulile activate vor fi aplicate. • Motorul de executie – responsabil de executia regulilor si a codului.

Procesul de inferenta consta din urmatoarele etape: • Validarea faptelor ce compun conditiile regulilor.

Page 32: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

32

• Alegerea regulilor care vor fi aplicate. • Executia actiunilor asociate concluzilor din regulile activate.

Cum lucreaza ? • Jess matches facts in the fact base to rules in the rule base. • The rules contain function calls that manipulate the fact base and/or other Java code. • Jess foloseste algoritmul Rete (ree-tee) to match patterns. • Reteaua Rete = o colectie interconectata de noduri = memoria de lucru.

Structura de control a anumitor sisteme bazate pe reguli nu foloseste nici inlantuirea inainte nici inlantuirea inapoi a regulilor, ci o strategie de control de tip agenda. Jess foloseste aceasta strategie care este in special utila in cazul in care se foloseste un criteriu de selectie a regulilor bazat pe preferinta starilor, deci o functie euristica de evaluare (mai exact dat de algoritmul Rete). In Jess, o regula este asemanatoare instructiunii de control if-then dintr-un limbaj de programare procedural insa modul de aplicare este diferit. Astfel, ordinea de aplicare a regulilor nu este cea data de utilizator ci este obtinuta prin aplicarea algoritmului Rete. De asemenea, nu mai este in totalitate valabila nici conditia prin care premiza unei reguli trebuie sa fie adevarata pentru a executa comenzile din concluzie. Conditiile corespunzatoare membrului stang (LHS: left hand side) al unei reguli sunt exprimate sub forma de fapte iar componentele membrului drept (RHS: right hand side) sunt apeluri de functii. Jess aşteaptă îndeplinirea membrului stang al unei reguli verificând faptele cu cele incarcate in memoria de lucru. Atunci când toate faptele sunt validate, regula este pusă în agenda. Spunem in acest caz ca regula este activată. Agenda reprezintă în Jess ca si in LISP colecţia reguli activate la un moment dat de continutul memoriei. Dacă o regulă nu are nici o condiţie în LHS, atunci Jess-ul va adăuga automat la membrul drept faptul special initial-fact. Orice regulă care nu are condiţii va fi activata automat prin plasarea ei în agendă, după ce va fi dată comanda reset şi faptul initial-fact va fi introdus în memorie. Se poate întâmpla de asemenea ca o regulă să nu aibă nici o acţiune în RHS chiar daca acest lucru nu este prea util. Regulile in Jess sunt definite folosind constructia defrule. Pentru a organiza si gestiona regulile dintr-o baza de cunostinte urmatoarele functii sunt utilizate, ele facand din acest motiv obiectul acestei sectiuni.

defrule – defineste o noua regula ppdefrule – functie de afisare a unei reguli agenda – afiseaza regulile activate din agenda run – lanseaza in executie regulile activate in agenda run n – lanseaza in executie urmatoarele n reguli din agenda undefrule – sterge o regula watch rules – afiseaza un diagnostic atunci cand o regula este executata watch activations – afiseaza un diagnostic atunci cand o regula este activata watch all – include watch rules si watch activations rules – afiseaza toate regulile activate

Sintaxa unei reguli in Jess este: (defrule <nume-regula> [<comentarii>]

<lista_fapte> ;; membrul stang (LHS) => <lista_comenzi> ;; membrul drept (RHS)

) astfel incat:

<nume-regula> este un nume simbolic care identifica in mod unic regula. Simbolul => are rolul de a separa membrul stang al regulii (partea if) de cel drept (partea then).

Page 33: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

33

faptele specificate in <lista_fapte> sunt cautate in memoria de lucru pentru a fi validate, si daca e cazul, instantiate conform cu datele incarcate in memorie. Instantierile astfel rezultate, se pot folosi si in membrul drept al regulii.

membrul stang al unei reguli, identificat aici prin <lista_fapte> se mai numeste pattern in terminologia Jess. Componentele unui pattern se numesc elementele conditionale ale regulii.

Observatie Pattern-ul unei reguli in Jess nu poate contine apeluri de functii ci doar fapte

care sunt validate de continutul memoriei de lucru. Apelurile de functii pot fi folosite in

membrul drept al regulii pentru a compune actiunile necesare. Lansarea în execuţie a unui program se face cu ajutorul comenzii run a cărei sintaxa este următoarea :

( run [ <limit> ] ) Argumentul opţional <limit> este un număr întreg, care specifică numărul maxim de reguli ce vor fi aprinse. Dacă acest argument nu apare, atunci el are implicit valoarea –1 şi toate regulile vor fi aprinse până ce nu va mai rămâne nici una în agendă. In caz contrar execuţia regulilor va înceta după ce un număr de <limit> reguli au fost aprinse. Următoarea comanda run va continua execuţia din locul de unde s-a oprit, astfel încât comanda (run 1) ar fi echivalentul unei rulări pas cu pas a programului. Trebuie reţinut faptul că o regulă o dată aprinsă, nu mai poate fi activată de obicei din nou. Este necesară ori ‘reîmprospătarea’ ei cu ajutorul comenzii reset, care şterge toate faptele şi reintroduce in memorie baza iniţială de fapte din construcţiile deffacts de la care s-a plecat. Odată refăcută baza iniţială de cunoaştere se poate da din nou comanda run. Daca dorim sa definim conditia de activare a unei reguli prin una sau mai multe evaluari de functii putem folosi functia predicativa test (asupra acestor functii vom reveni in continuarea acestui material). De exemplu, o regula de forma: (deftemplate numar

(slot valoare (type NUMBER)))

(defrule regula-gresita

(numar (valoare ?nr))

(< ?nr 0)

=>

(printout t ”Numar pozitiv” crlf))

nu este corecta, datorita apelului de functie din membrul stang. Ea poate fi usor rescrisa intr-o regula corecta din punctul de vedere al formalismului Jess dupa cum urmeaza: (deftemplate numar

(slot valoare (type NUMBER)))

(defrule regula-corecta

(numar (valoare ?nr))

(test (> ?nr 0))

=>

(printout t ”Numar pozitiv” crlf))

(watch all)

(assert (numar (valoare 3)))

(run)

Salvam codul de mai sus intr-un fisier regula.clp, a carui rulare o precedam de comenzile (clear) si (reset) pentru a reveni la continutul initial al memoriei de lucru. Jess> (clear)

TRUE

Jess> (reset)

TRUE

Jess> (batch regula.clp)

Page 34: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

34

==> f-1 (MAIN::numar (valoare 3))

==> Activation: MAIN::regula-corecta : f-1,

FIRE 1 MAIN::regula-corecta f-1,

”Numar pozitiv”

<== Focus MAIN

1

In codul fisierului regula.clp folosim o variabila ?nr care la activarea regulii se instantiaza cu valoarea corespunzatoare din memoria de lucru. Putem folosi insa variabilele nu numai in atribuirea de valori dar si pentru atribuirea de fapte din memoria de lucru. In acest din urma caz, o astfel de atribuire se numeste pattern binding si se noteaza cu <-. Folosind pattern

binding putem atribui unei varibile o referinta la un obiect jess.Fact si astfel, prin intermediul numelui de variabila putem in membrul drept al regulei sa extragem, modificam sau sa copiem faptul referit (cu retract, modify sau respectiv, duplicate). Pentru exemplificare, vom modifica fisierul regula.clp, astfel incat regula-corecta sa extraga din memorie toate faptele numar care au valoarea mai mica decat 0.

(deftemplate numar

(slot valoare (type NUMBER)))

(defrule regula-corecta

?id <- (numar (valoare ?nr))

(test (< ?nr 0))

=>

(retract ?id))

(watch all)

(deffacts numere "Numere pozitive si negative"

(numar (valoare 3))

(numar (valoare -2))

(numar (valoare 5))

(numar (valoare 0)))

(reset)

(run)

(facts)

1. Jess> (reset)

2. TRUE

3. Jess> (batch regula.clp)

4. ==> Focus MAIN

5. ==> f-0 (MAIN::initial-fact)

6. ==> f-1 (MAIN::numar (valoare 3))

7. ==> f-2 (MAIN::numar (valoare -2))

8. ==> Activation: MAIN::regula-corecta : f-2,

9. ==> f-3 (MAIN::numar (valoare 5))

10. ==> f-4 (MAIN::numar (valoare 0))

11. FIRE 1 MAIN::regula-corecta f-2,

12. <== f-2 (MAIN::numar (valoare -2))

13. <== Focus MAIN

14. f-0 (MAIN::initial-fact)

15. f-1 (MAIN::numar (valoare 3))

16. f-3 (MAIN::numar (valoare 5))

17. f-4 (MAIN::numar (valoare 0))

18. For a total of 4 facts.

Ca de obicei, inainte de rularea programului, trebuie sa reinitializam continutul memoriei de lucru prin comanda (reset) – pasul 1. Pe masura ce se incarca faptele in memorie prin intermediul functiei deffacts, se testeaza conditia regulii MAIN::regula-corecta care devine activa in momentul in care se incarca faptul f-2 (MAIN::numar (valoare -2)) (pasul 8). La

Page 35: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

35

pasul 11 regula MAIN::regula-corecta se aplica si drept consecinta la pasul 12 este extras din memorie faptul f-2. Functii predicative

Elementele conditionale ale unui pattern pot fi combinate folosind functiile and, or, not, test, exists, logical pentru a defini constructii logice complexe. In cele ce urmeaza vom detalia functiile or, not si test datorita importantei acestora . Apelul functiei and este implicit atunci cand avem mai multe elemente conditionale intr-un singur pattern insa devine necesar in combinatie cu alte apelurile de functii or sau not. Semnificatia acestora este similara operatorilor logici cu acelasi nume. Pentru exemplificare iata cum se scriu legile lui DeMorgan folosind functiile predicative and, or si not. 1. (not (and (x) (y))) => (or (not (x)) (not (y))) adica “¬ (x ∧y) => (¬x) ∨ (¬y)” 2. (not (or (x) (y))) => (and (not (x)) (not (y))) adica “¬ (x ∨ y) => (¬x) ∧(¬y)” Mai jos prezentam un program Jess frati.clp care foloseste functiile predicative or si not pentru a gasi perechi de frati pe baza faptelor copil incarcate in memorie. (deftemplate copil (slot nume (type STRING)) (slot mama (type STRING)) (slot tata (type STRING)) (slot sex)) (defrule gaseste-frati (copil (nume ?n1) (mama ?m1) (tata ?t1) (sex ?s1)) (copil (nume ?n2) (mama ?m2) (tata ?t2) (sex ?s2)) ; un copil nu e frate cu el insusi (not (test ((new java.lang.String ?n1) equals ?n2))) ; fratii au aceeasi mama (or (test ((new java.lang.String ?m1) equals ?m2)) ; fratii au acelasi tata (test ((new java.lang.String ?t1) equals ?t2))) => (if ((new java.lang.String ?s1) equals masc) then (printout t ?n1 " este fratele lui " ?n2 crlf) else (printout t ?n1 " este sora lui " ?n2 crlf))) (watch all) (deffacts copiii (copil (nume ana) (mama maria) (tata ion) (sex fem)) (copil (nume george) (mama elena) (tata ion) (sex masc))) (reset) (run) La rularea acestui program obtinem urmatoarele rezultate: Jess> (clear)

Page 36: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

36

TRUE

Jess> (reset)

TRUE

Jess> (batch frati.clp)

==> Focus MAIN

==> f-0 (MAIN::initial-fact)

==> f-1 (MAIN::copil (nume ana) (mama maria) (tata ion) (sex fem))

==> f-2 (MAIN::copil (nume george) (mama elena) (tata ion) (sex

masc))

==> Activation: MAIN::gaseste-frati : f-2, f-1,,

==> Activation: MAIN::gaseste-frati : f-1, f-2,,

FIRE 1 MAIN::gaseste-frati f-2, f-1,,

george este fratele lui ana

FIRE 2 MAIN::gaseste-frati f-1, f-2,,

ana este sora lui george

<== Focus MAIN

Jess> (rules)

MAIN::gaseste-frati

MAIN::gaseste-frati&1

For a total of 2 rules.

O regula nume-regula care contine in membrul stang functia or cu n ramuri este dizivata de Jess in n subreguli, prima numindu-se nume-regula, iar celelalte nume-regula&1, nume-regula&2, etc. Numele regulilor rezultate in urma executarii programului de mai sus pot fi vazute daca se da comanda (rules). Definirea paternurilor sintactice in Jess

Programul listat mai jos recunoaste relatia de tip determinant dintr-un pattern sintactic corespunzator unui grup nominal. Se considera ca o astfel de relatia apare intre un substantiv (a carui eticheta in formalismul MSD – morpho-syntactic description – incepe cu litera N) si un adjunct al sau a carui eticheta MSD trebuie sa inceapa cu D sau T. Paternurile sintactice sunt furnizate programului spre analiza sub forma unor fapte (neordonate) a caror template este urmatorul: (deftemplate pattern (multislot words) – in acest camp se retin cuvintele grupului nominal (multislot poss)) – in acest camp se retin tagurile MSD ale cuvintelor GN Exemplu. Considerăm următorul grup nominal „un singur cuvânt”. Reprezentarea acestuia in baza informatiei morfo-sintactice a cuvintelor componente este:

[NP [Timsr un] [Afpms-n singur] [Ncms-n cuvânt]]

Avem deci că structura morfologică a acestui grup nominal este: Timsr Afpms-n Ncms-n

O secvență de N etichete MSD descriu N-1 structuri de dependență, fiecare punând în evidență unul dintre cei N-1 regenți interni. Astfel, în secvența de trei cuvinte de mai sus, corespund două relații de dependență: „un” va fi atașat de regentul "cuvânt" prin intermediul relației determinare (notată det.), iar adjectivul „singur” este atașat tot de regentul „cuvânt” prin intermediul relației de dependență atribut adjectival (notată a.adj.). Exemple de astfel de patternuri: Grup nominal adnotat cu taguri MSD Timsr/un Ncms-n/fond Spsa/de Ncfsrn/rezerva Dd3msr---e/acest Ncms-n/copil Pd3mpr/cei Mcmp-l/doi Ncfp-n/copii

Page 37: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

37

Tsms/al Ps1ms-p/nostru Ncms-n/frate Ncmsry/baiatul Dd3msr---o/acesta Afpms-n/frumos Ncfsry/fata Pd3fsr/cea Afpfsry/buna Timsr/un Ncms-n/copil Ti-po/unor Ncmp-n/baieti Di3-sr---e/fiecare Ncms-n/om Di3msr---e/vreun Ncms-n/copil Tsms/al Moms-l/doilea Ncms-n/copil Dz3msr---e/niciun Ncms-n/copil Dw3--r---e/ce Ncfsrn/solutie ; Pattern string (bind ?*DetPattern* "D+|T+") (bind ?*AdjPattern* "A+|C[cr]+|M+|Ps+") (bind ?*SubstPattern* "N+") (defglobal ?*idx_noun* = -1) (defglobal ?*idx_det* = -1) (import java.util.regex.Pattern) (import java.util.regex.Matcher) (deffunction contains_noun($?list) (bind ?*idx_noun* -1) (bind ?*objPattern* (call Pattern compile ?*SubstPattern*)) (foreach ?pattern $?list (bind ?objMatcher (call ?*objPattern* matcher ?pattern)) (bind ?found (?objMatcher find)) (bind ?*idx_noun* (+ ?*idx_noun* 1)) (if ?found then (return TRUE)) ) (return FALSE) ) (deffunction contains_det($?list) (bind ?*idx_det* -1) (bind ?*objDetPattern* (call Pattern compile ?*DetPattern*)) (bind ?*objAdjPattern* (call Pattern compile ?*AdjPattern*)) (bind ?i ?*idx_noun*) (while (progn (bind ?i (- ?i 1)) (>= ?i 0)) (bind ?pattern (nth$ (+ ?i 1) $?list)) (bind ?objDetMatcher (call ?*objDetPattern* matcher ?pattern)) (bind ?found (?objDetMatcher find)) (bind ?*idx_det* ?i) (if ?found then (return TRUE)) (bind ?objAdjMatcher (call ?*objAdjPattern* matcher ?pattern))

Page 38: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

38

(bind ?found (?objAdjMatcher find)) (if (not ?found) then (return FALSE)) ) (bind ?i ?*idx_noun*) (while (progn (bind ?i (+ ?i 1)) (<= ?i (length$ $?list))) (if (> (+ ?i 1) (length$ $?list)) then (return FALSE)) (bind ?pattern (nth$ (+ ?i 1) $?list)) (bind ?objDetMatcher (call ?*objDetPattern* matcher ?pattern)) (bind ?found (?objDetMatcher find)) (bind ?*idx_det* ?i) (if ?found then (return TRUE)) (bind ?objAdjMatcher (call ?*objAdjPattern* matcher ?pattern)) (bind ?found (?objAdjMatcher find)) (if (not ?found) then (return FALSE)) ) (return FALSE) ) (defrule det-relation (pattern (words $?words) (poss $?pos)) (test (contains_noun $?pos)) (test (contains_det $?pos)) => (bind ?idx_noun (+ ?*idx_noun* 1)) (bind ?idx_det (+ ?*idx_det* 1)) (printout t "det(" (nth$ ?idx_noun $?words) "-" ?idx_noun "," (nth$ ?idx_det $?words) "-" ?idx_det ")" crlf) ) (run) Interogarea fisierelor .clp din Java.Definirea memoriei de lucru in Java

Vom reconsidera programul .clp din laboratorul anterior. Acesta are definita o regula cu ajutorul careia putem recunoaste pentru un fapt pattern, daca cuvintele continute in atributul words sunt intr-o relatie de tip determinant. Ne propunem sa cream o interfata grafica (Java) prin intermediul careia sa se incarce grupuri nominale adnotate cu taguri MSD, care apoi sa fie transformate in fapte pattern, incarcate in memoria de lucru a fisierului .clp si lansat apoi motorul de inferenta Jess care sa determine daca avem sau nu o relatie de tip determinant in secventa introdusa.

Page 39: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

Rutarea iesirii unui fisier .clp ce urmeaza a fi incarcat intr-un proiect java prin intermediul unui obiect Rete se face de maniera urmatoare: import jess.*; engine = new Rete(); TextAreaWriter taw = new TextAreaWriter(textArea1); engine.addOutputRouter("t", taw); engine.addOutputRouter("WSTDOUT", taw); engine.addOutputRouter("WSTDERR", taw); private void button2MouseClicked(java.awt.event.MouseEvent evt) { String str = textField1.getText(); ValueVector words = new ValueVector(); String poss = ""; StringTokenizer token = new StringTokenizer(str, " "); while (token.hasMoreTokens()) { String st = token.nextToken(); StringTokenizer tk = new StringTokenizer(st, "/"); try{ if (!poss.equals("")) poss = poss.concat(" "); poss = poss.concat(tk.nextToken()); words.add(new Value(tk.nextToken(), RU.ATOM)); }catch(JessException ex) {System.out.println("1:" + ex.getMessage());} } System.out.println(words.toString()); System.out.println(poss); try{ engine.executeCommand("(clear)"); engine.executeCommand("(deftemplate input-pattern (multislot words) (slot sequence))"); Fact f = new Fact("input-pattern", engine);

Aici se introduc secvente de genul: Timsr/un Ncms-n/fond Spsa/de Ncfsrn/rezerva

Aici se ruteaza iesirea fisierului .clp

Page 40: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

40

f.setSlotValue("words", new Value(words,RU.LIST)); f.setSlotValue("sequence", new Value(poss,RU.STRING)); engine.reset(); engine.assertFact(f); //engine.executeCommand("(facts)"); engine.executeCommand("(batch patterns.clp)"); }catch(JessException ex){System.out.println("2:" + ex.getMessage());} } Comunicatie bidirectionala Java-Jess

Mecanismul de transfer de valori intre un program Jess si un program Java se face prin intermediul a doua functii de baza: store si fetch care au urmatoarele forme:

• metodele existente in pachetul Rete au urmatorul antet: public Value store(String name, Value val); public Value store(String name, Object val); public Value fetch(String name); public void clearStorage();

• iar echivalentele acestora in Jess sunt: (store <name> <value>) (fetch <name>) (clear-storage) Stocarea valorilor in Jess si accesarea lor din Java De exemplu, sa presupunem ca avem un fisier rule.clp caruia ii definim memoria de lucru in cadrul unei aplicatii Java. In urma lansarii comenzii run, una sau mai multe reguli ale fisierului .clp se pot aplica si fiecare dintre acestea trebuie sa “verse” in ordinea in care se aplica o anumita valoare. Putem astfel sa strangem valorile obtinute prin aplicarea regulilor activate ale fisierului .clp intr-o variabila name, a carei valoare poate fi accesata in aplicatia Java. Codul Java este: Rete engine = new Rete(); Fact f = new Fact("...", engine); f.setSlotValue(..., ...); ... engine.executeCommand("(reset)"); engine.executeCommand("(batch rule.clp)"); engine.assertFact(f); Value executeCommand = engine.executeCommand("(run)"); String return_value = engine.fetch("name").toString(); In programul rule.clp avem o functie store_name care primeste un String, ii adauga caracterul „;” la sfarsit si apoi il concateneaza la vechea valoare a variabilei name. Codul functiei Jess: (deffunction store_name (?name) (bind ?old_name (fetch name)) (bind ?name (call ?name concat ";")) (return (call ?old_name concat ?name))

Page 41: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

41

) Iar fiecare regula din program va stoca in variabila name valorea creata cu ajutorul functiei store_name. (defrule write-names (human (name ?name) (...)) ... => ... (store name (store_name ?name)) ) Initializarile programului rule.clp trebuie sa cuprinda: .... (reset) (store name "") .... Stocarea valorilor in Java si accesarea lor in Jess Sa presupunem ca dorim sa stocam in Java trei valori in trei variabile A, B si C pe care mai apoi dorim sa le accesam intr-un fisier jess. Codul Java este urmatorul: Rete rete = new Rete(); try { rete.reset(); rete.watchAll(); rete.store("A",new Value(11, RU.INTEGER)); rete.store("B",new Value(15, RU.INTEGER)); rete.store("C",new Value(13, RU.INTEGER)); rete.executeCommand("(batch hello.clp)"); rete.run(); } catch (JessException e) { e.printStackTrace(); } Regasirea informatiilo stocate in variabile si folosirea lor (de exemplu) in reguli se face astfel: (defrule startup => (assert (number (fetch A))) (assert (number (fetch B))) (assert (number (fetch C))) ) (defrule write_number (number ?n) => (printout t ?n crlf) ) Implementarea unui sistem expert in Jess Aplicatia software pe care o prezentam in acesta sectiune este un sistem expert scris in limbajul Jess pentru alegerea de telefoane mobile pe baza unor caracteristici specificate de utilizator. Datele despre mobilele procesate de sistem sunt incarcate cu ajutorul predicatelor

Page 42: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

42

assert si deffacts. Pentru fiecare grup de fapte se defineste un template cu ajutorul lui deftemplate. Cunostintele sistemului sunt reprezentate in reguli Jess construite cu defrule. Sistemul expert este construit din punct de vedere logic din entitati care interactioneaza conform unor reguli prestabilite. Entitatile sunt reprezentate de device-urile procesate de aplicatie. Acestea sunt:

1. Cell Phones 2. Smart Phones 3. PDA

Pentru fiecare astfel de entitate s-a definit cate un template. Astfel pentru Cell Phones exista template-ul phone cu urmatoarea structura: (deftemplate phone (slot name (type STRING)) (slot os (default no)) (slot talk (type FLOAT)) (multislot screen (default (create$ 240 320))) (slot rom (type INTEGER) (default 64)) (slot ram (type INTEGER) (default 0)) (slot camera (default 0)) (slot music (default no)) (slot video (default no)) (slot email (default no)) (slot modem (default no)) (slot java (default no)) (slot sync_pc (default no)) (slot blue (default no)) (slot usb (default no))) Pentru memorarea caracteristicilor unui Smart Phone am construit template-ul smart ce are urmatoarele campuri: (deftemplate smart (slot name (type STRING)) (slot os (default no)) (slot talk (type FLOAT)) (multislot screen (default (create$ 240 320))) (slot rom (type INTEGER) (default 64)) (slot ram (type INTEGER) (default 0)) (slot camera (default 0)) (slot music (default yes)) (slot video (default yes)) (slot email (default no)) (slot modem (default no)) (slot java (default no)) (slot sync_pc (default yes)) (slot blue (default yes)) (slot usb (default yes))) Iar pentru PDA-uri exista template-ul pda dupa cum urmeaza: (deftemplate pda (slot name (type STRING)) (slot os (default no)) (slot talk (type FLOAT)) (multislot screen (default (create$ 240 320)))

Page 43: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

43

(slot rom (type INTEGER) (default 64)) (slot ram (type INTEGER) (default 0)) (slot camera (default 0)) (slot music (default no)) (slot video (default no)) (slot email (default no)) (slot modem (default no)) (slot java (default no)) (slot sync_pc (default yes)) (slot blue (default yes)) (slot usb (default yes))) Toate aceste template-uri apartin modulului MAIN al aplicatiei. Expertul uman defineste regulile pe baza carora se aleg din baza de cunostinte faptele care corespund cerintelor utilizatorului. Sistemul este capabil de a retine si stoca raspunsurile utilizatorului la intrebarile afisate in timpul procesului de inferenta. Aceasta instorie se numeste memoria sistemului si este folosita in interpretarea regulilor sistemului. (deftemplate question ; textul intrebarii (slot text) ;id-ul intrebarii (slot ident)) (deftemplate answer ;id-ul raspunsului (slot ident) ;slotul in care se stocheaza raspunsul (slot text)) (defmodule ask) (defrule ask::ask-question-by-id "Given the identifier of a question, ask it" (declare (auto-focus TRUE)) (MAIN::question (ident ?id) (text ?text)) (not (MAIN::answer (ident ?id))) (MAIN::ask ?id) => (ask-user ?text) ((engine) waitForActivations)) (defrule ask::collect-user-input

"Check and optionally return an answer from the GUI" (declare (auto-focus TRUE)) (MAIN::question (ident ?id) (text ?text) ) (not (MAIN::answer (ident ?id))) ?user <- (user-input ?input) ?ask <- (MAIN::ask ?id) => (if (eq ?text "What is your wish for the screen resolution?") then

Page 44: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

44

(assert (MAIN::answer (ident ?id) (text (explode$ ?input)))) else (assert (MAIN::answer (ident ?id) (text ?input))) ) (retract ?ask ?user) (return)) Baza de reguli este formata din 8 reguli dupa cum urmeaza:

4 reguli pentru alegerea unui PDA conform urmatoarelor criterii: regula pentru alegerea unui PDA cu memorie ram de o anumita capacitate si camera foto care are cel putin rezolutia indicata de utilizator, fara memorie ram dar avand camera foto, cu memorie ram, dar fara camera si ultima pentru PDA-uri care nu au in mod necesar memorie ram si camera foto.

2 reguli pentru alegerea unui SmartPhone: cu memorie ram de o anumita capacitate si camera foto de o anumita rezolutie si a doua care nu are in mod necesar memorie ram dar are camera foto

2 reguli pentru alegerea unui telefon celular obisnuit: cu o anumita memorie ram si camera foto si pentru celulare care nu au in mod necesar memorie ram sau camera foto.

Pentru exemplificare in cele ce urmeaza vom da doar regulile definite pentru alegerea unui telefon celular obisnuit: (defrule find_phone1 ; fara ram, cu camera (answer (ident os_id) (text ?os)) (answer (ident talk_id) (text ?talk)) (answer (ident screen_id) (text ?screen)) (answer (ident rom_id) (text ?rom)) (answer (ident ram1_id) (text no)) (answer (ident camera1_id) (text yes)) (answer (ident camera2_id) (text ?camera)) (answer (ident music_id) (text ?music)) (answer (ident video_id) (text ?video)) (answer (ident email_id) (text ?email)) (answer (ident modem_id) (text ?modem)) (answer (ident java_id) (text ?java)) (answer (ident sync_pc_id) (text yes)) (answer (ident blue_id) (text yes)) (answer (ident usb_id) (text yes)) (phone (name ?name) (os ?os)

(talk ?t&:(>= ?t ?talk)) (screen ?s1&:(>= ?s1 (nth$ 1 ?screen)) ?s2&:(>= ?s2 (nth$ 2 ?screen))) (camera ?c&:(>= ?c ?camera)) (music ?music) (video ?video) (email ?email) (modem ?modem) (java ?java))

=>

Page 45: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

45

(bind ?str (str-cat ?*crlf* "(7) The Phone I recommend is " ?name ".")) (?*cText* append ?str) ) (defrule find_phone2 ; fara ram, fara camera (answer (ident os_id) (text ?os)) (answer (ident talk_id) (text ?talk)) (answer (ident screen_id) (text ?screen)) (answer (ident rom_id) (text ?rom)) (answer (ident ram1_id) (text no)) (answer (ident camera1_id) (text no)) (answer (ident music_id) (text ?music)) (answer (ident video_id) (text ?video)) (answer (ident email_id) (text ?email)) (answer (ident modem_id) (text ?modem)) (answer (ident java_id) (text ?java)) (answer (ident sync_pc_id) (text yes)) (answer (ident blue_id) (text yes)) (answer (ident usb_id) (text yes)) (phone (name ?name) (os ?os)

(talk ?t&:(>= ?t ?talk)) (screen ?s1&:(>= ?s1 (nth$ 1 ?screen)) ?s2&:(>= ?s2 (nth$ 2 ?screen))) (music ?music) (video ?video) (email ?email) (modem ?modem) (java ?java))

=> (bind ?str (str-cat ?*crlf* "(8) The Phone I recommend is " ?name "." )) (?*cText* append ?str) ) Interfata sistemului expert cu utilizatorul se face prin intermediul unor casete de dialog construite cu ajutorul pachetelor: (import java.awt.*) (import jess.awt.*) (import javax.swing.*) Pricipala fereastra de dialog a aplicatiei este prezentata in Figura 9. Ea include o componenta de tip TextArea in care se afiseaza intrebarile generate in timpul rationamentului si de asemenea si raspunsurile primite de la utilizator impreuna cu un control de tip TextField in care utilizator raspunde dupa caz cu yes sau no la intrebarile primite.

Page 46: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

46

Figură 7 Fereastra de dialog a aplicatiei

In momentul in care rationamentul s-a incheiat, in fereastra mai apare un Panel care are atatea butoane cate solutii s-au gasit pentru a multumi utilizatorul. Butoanele au ca etichete codurile device-urilor gasite corespunzatoare pentru necesitatile utilizatorului (Figura 10). De asemenea solutiile gasite impreuna cu tipurile lor sunt afisate si in controlul TextArea. Mai jos este prezentat codul de constructie a fereastrei principale a aplicatiei: (set ?*f* background (new Color 0 85 85)) (set ?*f* layout (new BorderLayout)) (?*f* setSize 700 650) (?*f* setVisible TRUE) (bind ?pmsg (new Panel)) (set ?pmsg layout (new BorderLayout)) (bind ?msg1 (new Jlabel "_________")) (?msg1 setForeground (new Color 0 185 0))

Page 47: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

47

(bind ?text (str-cat "Welcome to the Mobile Phone Advisor!" ?*crlf*)) (bind ?text (str-cat ?text "If you answer my questions I will tell you what telephone you need.")) (bind ?msg2 (new JTextArea ?text)) (?msg2 setEditable FALSE) (?msg2 setForeground (new Color 70 0 150)) (bind ?msg3 (new JLabel "____________")) (?msg3 setForeground (new Color 0 185 0)) (bind ?ph (new ImageIcon ".\\images\\logo_en.jpg")) (bind ?lab (new JLabel ?ph)) (?lab setBounds 57 46 10 10) (?pmsg add "North" ?msg1) (?pmsg add "Center" ?msg2) (?pmsg add "South" ?msg3) (?pmsg add "East" ?lab) (bind ?scroll (new JScrollPane ?*cText*)) (?*cText* setText "Here come the questions ...") (?*cField* setText "") (bind ?titlu (new JLabel "Your answer goes here: ")) (?titlu setForeground (new Color 70 0 150)) (bind ?p (new Panel)) (set ?p layout (new BorderLayout)) (?p add "West" ?titlu) (?p add "Center" ?*cField*) (?p add "East" ?*b*) (bind ?photo (new ImageIcon ".\\images\\rim_blackberry_8310.jpg")) (bind ?label (new JLabel ?photo)) (?label setBounds 260 212 100 20) (?*c* add ?label) (?*pButtons* setLayout (new GridLayout 7 1)) ((?*f* getContentPane) add "North" ?pmsg) ((?*f* getContentPane) add "Center" ?scroll) ((?*f* getContentPane) add "South" ?p) ((?*f* getContentPane) add "East" ?*c*) ((?*f* getContentPane) add "West" ?*pButtons*) (?*f* validate) (?*f* repaint)

Page 48: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

48

Figură 8 Raspunsurile sistemului

Daca se da click pe unul din butoanele nou aparute atunci va aparea o fereastra care contine poza telefonului a carui codificare este afisata pe butonul in cauza. Fereastra este etichetata cu numele complet al device-ului (Figura 11). Restrictiile sistemului Restrictiile provin din cunostintele procesate in sistem. Astfel, daca in timpul rationamentului utilizatorul precizeaza o valoare numerica diferita de 0 (zero) pentru memoria ram atunci in lista de device-uri care vor fi gasite ca satisfacatoare pentru cerintele introduse nu se va gasi un cell phone, ci numai smart phone si PDA. De asemenea nu se va gasi in lista de raspuns a sistemului un PDA care sa aiba unul din urmatoarele campuri cu valoarea no:

synchronized with pc, bluetooth, usb incorporated deoarece toate PDA-urile procesate au aceste optiuni.

Page 49: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

49

Figură 11 Afisarea unei solutii

Page 50: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

50

Figure 12 Un alt exemplu de interogare care genereaza ca rezultat un SmartPhone si un PDA

Page 51: Medii de programare in Inteligenta Artificialaid.inf.ucv.ro/~ghindeanu/courses/mpia/Curs.pdf · bazat pe cazuri (case-based), logica fuzzy (fuzzy logic), retele neuronale, retele

51

Cuprins

Rationamente bazate pe reguli ................................................................................................2 Jess vs. Prolog ....................................................................................................................5 Limbajul Jess ......................................................................................................................6 Variabile in Jess ..................................................................................................................8

Jess: limbaj de scripting pentru Java ..................................................................................... 16 Interfata Grafica cu obiecte Java construita in Jess ............................................................ 20 Captarea exceptiilor in Jess ............................................................................................... 22 Reprezentarea faptelor in Jess ........................................................................................... 23 Reprezentarea regulilor in Jess .......................................................................................... 30 Functii predicative ............................................................................................................ 35 Definirea paternurilor sintactice in Jess ............................................................................. 36 Interogarea fisierelor .clp din Java.Definirea memoriei de lucru in Java ............................ 38 Comunicatie bidirectionala Java-Jess ................................................................................ 40