Sisteme Expert

Nu esti logat.

Laboratorul 6


(Deadline: 07.05.2017 23:59:59)

Daca nu sunteti logati exercitiile nu se mai afiseaza.

Module si bilioteci

Biblioteci din Sicstus Prolog

Se vor prezenta doar bibliotecile de care aveti nevoie in teme, dar daca sunteti interesati puteti vizualiza si lista completa de biblioteci oferite de Sicstus Prolog.

Biblotecile pe care le vom folosi:

Atentie, in cadrul laboratorului nu sunt explicate toate predicatele din bibliotecile mentionate mai sus, pe acestea este necesar sa le citit voi direct din documentatie. In cadrul laboratorului sunt mentionate doar predicatele cele mai importante si mai frecvent folosite prin teme (dar asta nu inseamna ca nu pot sa apara in teme si teste si din celelalte care nu apar in exemple)

Predicatele unei biblioteci se incarca prin predicatul use_module(library(nume_biblioteca)), de exemplu, in consola putem scrie:

| ?- use_module(library(random)).
% loading c:/documents and settings/userpc/desktop/sicstus prolog 4.0.2/sicstus prolog 4.0.2/library/random.po...
% module random imported into user
%  loading c:/documents and settings/userpc/desktop/sicstus prolog 4.0.2/sicstus prolog 4.0.2/library/types.po...
%  module types imported into random
%  loaded c:/documents and settings/userpc/desktop/sicstus prolog 4.0.2/sicstus prolog 4.0.2/library/types.po in module types, 0 msec 536 bytes
%  loading foreign resource c:/documents and settings/userpc/desktop/sicstus prolog 4.0.2/sicstus prolog 4.0.2/library/x86-win32-nt-4/random.dll in module random
% loaded c:/documents and settings/userpc/desktop/sicstus prolog 4.0.2/sicstus prolog 4.0.2/library/random.po in module random, 0 msec 12112 bytes
yes
| ?-
In acest moment putem folosi oricare din predicatele definite in cadrul acestei biblioteci. Bineinteles dupa inchiderea si redeschiderea consolei, predicatele nu vor mai fi incarcate si va trebui sa efectuam din nou un use_module.

Atunci cand avem nevoie de predicatele unei biblioteci in cadrul unui program vom apela use_module cu bibliotecile necesare, printr-o directiva, pentru ca incarcarea modulelor sa se faca in timpul consultarii programului, iar la inteogarea diverselor predicate din program sa avem deja biblioteca incarcata.
Sa luam ca exemplu programul urmator in care se calculeaza suma a N numere random (iar numerele random se si afiseaza pe masura ce se genereaza).

:-use_module(library(random)).

%suma(+Nr,-Suma)
suma(0,0).
suma(N,S):-N>0, N1 is N-1, suma(N1,S1),
            random(X),write(X),nl, S is S1+X.
Observam mai jos mesajele care insotesc incarcarea bibliotecii (marcate cu galben) afisate in timpul consultarii:
| ?- :-
consult('E:/schimbate_pe site/inteligenta artificiala 2013/exemplu_random_suma.pl').
% consulting e:/schimbate_pe site/inteligenta artificiala 2013/exemplu_random_suma.pl...
%  loading c:/documents and settings/userpc/desktop/sicstus prolog 4.0.2/sicstus prolog 4.0.2/library/random.po...
%  module random imported into user
%   loading c:/documents and settings/userpc/desktop/sicstus prolog 4.0.2/sicstus prolog 4.0.2/library/types.po...
%   module types imported into random
%   loaded c:/documents and settings/userpc/desktop/sicstus prolog 4.0.2/sicstus prolog 4.0.2/library/types.po in module types, 0 msec 536 bytes
%   loading foreign resource c:/documents and settings/userpc/desktop/sicstus prolog 4.0.2/sicstus prolog 4.0.2/library/x86-win32-nt-4/random.dll in module random
%%  loaded c:/documents and settings/userpc/desktop/sicstus prolog 4.0.2/sicstus prolog 4.0.2/library/random.po in module random, 0 msec 12128 bytes

% consulted e:/schimbate_pe site/inteligenta artificiala 2013/exemplu_random_suma.pl in module user, 0 msec 12792 bytes
| ?- suma(3,S).
0.2163110752346893
0.6344657121210742
0.7621277925774055
S = 1.612904579933169 ?
yes
| ?-

Timp

Cateva predicate utile referitoare la data curenta ori la timestamp gasiti in biblioteca library(system).

Sa luam ca exemplu un program care calculeaza in cat timp se afiseaza numerele de la 0 la 5000.

:-use_module(library(system)).

scrie_nr(N,N).
scrie_nr(N,C):-C<N, C1 is C+1, write(C), write(' '), scrie_nr(N,C1).


durata_scriere(D):-now(D1), scrie_nr(5000,0), now(D2), D is D2-D1.
Dupa ce termina de afisat, in D va fi numarul de secunde in care s-a executat programul.


Generare numere random.

Se foloseste biblioteca library(random). Predicatul random(X), calculeaza in X un numar random in intervalul [0,1). Atentie, la intoarcerea in backtracking la reinterogarea lui random nu se intoarce un nou numar aleator
| ?- random(X).
X = 0.2393746982829037 ? ;
no
| ?-
O sa observati ca la prima interogare a predicatului random(X) dupa ce a fost deschisa consola, primim mereu aceeasi valoare. Aceasta se intampla deoarece are acelasi seed setat default. Seed-ul este, conform documentatiei, o structura de 4 elemente random(X,Y,Z,B). Pentru a va asigura ca obtineti un numar random diferit de fiecare data cand deschideti consola, ar trebui sa setati seed-ul in functie de ceva ce se schimba in mod constant de la ultima deschidere a consolei. Deci, ne vom folosi de timp, si anume de predicatul now, care ne ofera de fiecare data un alt numar (timestamp). Pentru a seta seed-ul oricare si oricati din cei patru parametri pot sa depinda de timestamp restul ramanand eventual fixati pe o anume valoare (mai putin cazul cand X, Y, Z raman fixati si doar B variaza - am vazut ca da in unele cazuri acelasi numar - nu cunosc motivul fiindca nu am reusit inca sa aflu modul de calcul al numerelor pseudoaleatoare din cadrul Sicstus-ului). Deci un exemplu de astfel de predicat ar fi:
:-use_module(library(random)).
:-use_module(library(system)).
seteaza_seed:-now(X1), X is X1 mod 30000,
              now(B),setrand(random(X,100,100,B)).

Fisiere si directoare

In biblioteca library(file_systems) veti intalni predicate cu care puteti manipula fisierele si directoarele(sa testati daca exista, sa le stergeti, sa le redenumiti).

De exemplu, puteti vedea care este working directory-ul:
| ?- current_directory(D).
D = 'e:/schimbate_pe site/inteligenta artificiala 2013/' ?
yes
| ?-
Puteti folosi predicatul close_all_streams care va inchide, cum ii spune si numele toate fisierele deschise, evitand astfel eventualele erori care apar cand doriti sa deschideti un fisier cae a ramas deschis din alta interogare.
| ?- close_all_streams.
yes
Se pot crea si sterge directoare, se poate testa existenta unui director:
| ?- directory_exists('piticei').
no
| ?- make_directory('piticei').
yes
| ?- directory_exists('piticei').
yes
| ?-
Si exista inca multe alte predicate utile despre care va recomand sa cititi in pagina de documentatie a bibliotecii library(file_systems) pentru a va putea realiza temele.

Executie in timp limitat

In unele cazuri avem nevoie sa oprim executia daca aceasta dureaza prea mult. Pentru aceasta vom folosi predicatul time_out(:Scop,+Timp_ms,-Rezultat) din biblioteca library(timeout). Asa cum e precizat in documentatie, predicatul time_out porneste inteorgarea Scop, dar daca executia acesteia depaseste Timp_ms (masurat in milisecunde) atunci se opreste executia si Rezultat va avea valoarea time_out, altfel, daca executia nu dureaza mai mult de Timp_ms milisecunde aceasta se realizeaza cu succes iar in Rezultat e returnata chiar valoarea success.

Pentru a vedea un exemplu, consideram definit urmatorul predicat, care nu face altceva decat sa numere de la N pana la 0, afisand la final gata.

numara(0):-write(gata).
numara(N):-N>0,N1 is N-1,numara(N1).
Facem interogarea folosind timeout pentru N=10000 si apoi pentru N=100000
| ?- time_out(numara(10000),100,R).
gata
R = success ?
yes
| ?- time_out(numara(100000),100,R).
R = time_out ?
yes
| ?-
Se observa ca pentru prima interogare executia a durat mai putin de 1000 milisecunde (= 1 secunda), al treilea parametru al lui time_out fiind instantiat cu succes. Pentru N=100000 insa dureaza mai mult de o secunda si time_out-ul opreste executia inainte ca predicatul sa ajunga la sfarsit, instantiand R cu valoarea time_out (adica a fost depasit timpul alocat).

Atentie, time_out pentru apeluri blocante precum read sau sleep nu va lua in considerare timpul de executie al acestora. In exemplul de mai jos, 3-ul s-a introdus dupa 2 secunde de la apel, si cu toate acestea time_out-ul a rezultat cu succes. In cel de-al doilea exemplu, sleep opreste executia pentru 2 secude insa time_out setat pe 1000 ms = 1 secunda in continuare rezulta in succes

| ?- time_out(read(X),100,R).
|: 3.
R = success,
X = 3 ? yes
| ?- time_out((write(a),sleep(2),write(b)),1000,R).
ab
R = success ?
yes
| ?-

Definirea propriilor module se face foarte usor, puteti citi in documentatia Prolog despre acest lucru.