• Nenhum resultado encontrado

Despre controlul execu Ń iei

9.2. Urmărirea execuŃiei

Să presupunem că avem o mini-bază de date cu preŃul pe kilogram al unor fructe:

(deffacts preturi-fructe (pret mere 10000) (pret pere 18000) (pret struguri 24000) …

)

Să mai presupunem că plecăm de acasă cu o listă a fructelor şi a cantităŃilor pe care dorim să le cumpărăm:

(deffacts de-cumparat (cumpar mere 5) (cumpar pere 3) (cumpar struguri 2) )

şi că o altă secŃiune a datelor conŃine o variabilă ce ne va da, la întoarcerea acasă, cât am cheltuit:

(deffacts buzunar (suma 0) )

Dorim ca valoarea sumei să fie actualizată corespunzător cumpărăturilor efectuate. Pentru a face lucrurile cât mai simple, vom admite că fondul de bani de care dispunem este nelimitat. Atunci, tot ce avem de făcut este să lăsăm să ruleze o regulă de felul:

(defrule cumpar_un_fruct ?c <- (cumpar ?fruct ?kg) (pret ?fruct ?lei)

?s <- (suma ?suma) =>

(retract ?f ?s)

(assert (suma =(+ ?suma (* ?kg ?lei)))) )

La fiecare aplicare, un fapt cumpar dispare din bază iar valoarea cheltuită pentru fructele corespunzătoare este adunată la suma deja cheltuită.

Programarea bazată pe reguli 126

Mediul CLIPS are mai multe metode de a urmări o execuŃie. Una din ele este invocarea comenzii (watch <parametri>). Ea poate primi ca parametri: activations, facts, rules, statistics etc. Vom urmări efectul dării acestei comenzi înainte de rularea programului nostru pentru a înŃelege mai bine maniera în care regulile se activează şi faptele sunt retrase ori incluse în bază în cursul execuŃiei. La încărcarea programului printr-o comandă (load ...) sau la definirea la prompter a faptelor, acestea nu sunt încă incluse în bază.

După cum arată şi Figura 31, acest lucru se realizează o dată cu execuŃia comenzii (reset).

CLIPS> (reset)

==> f-0 (initial-fact)

==> f-1 (pret mere 10000)

==> f-2 (pret pere 18000)

==> f-3 (pret struguri 24000)

==> f-4 (cumpar mere 8)

==> f-5 (cumpar pere 3)

==> f-6 (cumpar struguri 2)

==> f-7 (suma 0)

SăgeŃile spre dreapta indică faptele introduse în bază. Faptul (initial- fact) are întotdeauna indexul f-0. Faptele incluse de program sunt cele cu indecşii de la f-1 la f-7.

În continuare, trasarea indică trei activări de reguli, în fapt trei instanŃe ale singurei reguli definite, cumpar-un-fruct:

==> Activation 0 cumpar-un-fruct: f-6,f-3,f-7

==> Activation 0 cumpar-un-fruct: f-5,f-2,f-7

==> Activation 0 cumpar-un-fruct: f-4,f-1,f-7

Indecşii care urmează numelui regulii sunt faptele care sunt satisfăcute de cele trei şabloane ale regulii, primul de tip (cumpar...), al doilea de tip (pret...) şi al treilea – singurul fapt (suma...):

(defrule cumpar_un_fruct ?c <- (cumpar ?fruct ?kg) (pret ?fruct ?lei)

?s <- (suma ?suma) =>

...

)

Rezultă că prima activare corespunde configuraŃiei de fapte:

Despre controlul execuŃiei 127

f-6 (cumpar struguri 2) f-3 (pret struguri 24000) f-7 (suma 0)

a doua – configuraŃiei:

f-5 (cumpar pere 3) f-2 (pret pere 18000) f-7 (suma 0)

iar a treia – configuraŃiei:

f-4 (cumpar mere 8) f-1 (pret mere 10000) f-7 (suma 0)

Dacă am considera o altă ordine de apariŃie a faptelor în bază decât cea dată, de exemplu plasând declaraŃia de sumă înaintea declaraŃiilor fructelor:

(deffacts buzunar (suma 0) )

(deffacts de-cumparat (cumpar mere 5) (cumpar pere 3) (cumpar struguri 2) )

constatăm o uşoară modificare a trasării, în conformitate cu schema de propagare a modificărilor dată de algoritmul RETE, care este reluată schematizat în Figura 31:

CLIPS> (reset)

==> f-0 (initial-fact)

==> f-1 (suma 0)

==> f-2 (pret mere 10000)

==> f-3 (pret pere 18000)

==> f-4 (pret struguri 24000)

==> f-5 (cumpar mere 8)

==> Activation 0 cumpar-un-fruct: f-5,f-2,f-1

==> f-6 (cumpar pere 3)

==> Activation 0 cumpar-un-fruct: f-6,f-3,f-1

==> f-7 (cumpar struguri 2)

==> Activation 0 cumpar-un-fruct: f-7,f-4,f-1

Programarea bazată pe reguli 128

CLIPS>

Întrucât faptele suma şi pret sunt deja introduse, la fiecare apariŃie a unui fapt cumpar, o nouă activare apare în agendă.

Să presupunem, în continuare, că revenim la ordinea iniŃială de declarare a faptelor. Rularea, amorsată de comanda (run), decurge astfel:

CLIPS> (run)

FIRE 1 cumpar-un-fruct: f-4,f-1,f-7

<== f-4 (cumpar mere 8)

<== f-7 (suma 0)

<== Activation 0 cumpar-un-fruct: f-5,f-2,f-7

<== Activation 0 cumpar-un-fruct: f-6,f-3,f-7

==> f-8 (suma 80000)

==> Activation 0 cumpar-un-fruct: f-6,f-3,f-8

==> Activation 0 cumpar-un-fruct: f-5,f-2,f-8

Trasarea indică prima “aprindere” a regulii cumpar-un-fruct datorită potrivirii configuraŃiei de fapte: f-4,f-1,f-7 cu partea de condiŃii a regulii.

Aprinderea în ordine inversă faŃă de ordinea includerilor în agendă se datorează utilizării strategiei depth, care este implicită în lipsa unei declaraŃii explicite de strategie. Dar asupra strategiilor utilizate în CLIPS vom reveni imediat.

În continuare, trasarea indică evenimente induse de executarea părŃii de acŃiuni a regulii cumpar_un_fruct:

...

=>

(retract ?f ?s)

(assert (suma =(+ ?suma (* ?kg ?lei)))) )

SăgeŃile spre stânga indică retrageri de fapte din bază şi dispariŃiile unor activări din agendă. Aşadar aprinderea instanŃei f-4,f-1,f-7 a regulii cumpar-un-fruct duce la eliminarea faptelor cu indecşii f-4 şi f-7.

Totodată, cum faptul f-7 intra în condiŃiile ambelor instanŃe rămase, dispariŃia lui din bază este resimŃită imediat în agendă prin dezactivarea acestor instanŃe.

Rezultatul executării comenzii (assert ...) este apariŃia unui nou fapt de tip sumă, de index f-8: (suma 80000). ApariŃia acestui fapt, corelată cu existenŃa în bază a celorlalte fapte, duce la activarea a două noi instanŃe ale regulii cumpar-un-fruct, respectiv datorate secvenŃelor de fapte f-6,f-3,f-8 şi f-5,f-2,f-8.

Rularea continuă astfel:

Despre controlul execuŃiei 129

FIRE 2 cumpar-un-fruct: f-5,f-2,f-8

<== f-5 (cumpar pere 3)

<== f-8 (suma 80000)

<== Activation 0 cumpar-un-fruct: f-6,f-3,f-8

==> f-9 (suma 134000)

==> Activation 0 cumpar-un-fruct: f-6,f-3,f-9 FIRE 3 cumpar-un-fruct: f-6,f-3,f-9

<== f-6 (cumpar struguri 2)

<== f-9 (suma 134000)

==> f-10 (suma 182000)

Dacă efectuarea unor statistici asupra rulării, printr-o comandă (watch statistics), a fost, de asemenea, invocată, un raport final încheie trasarea.

El indică numărul total de reguli aprinse, timpul total de execuŃie în secunde, o estimare a numărului mediu de reguli aprinse pe secundă etc.

3 rules fired Run time is 0.1850000000013096 seconds.

16.21621621610141 rules per second.

7 mean number of facts (8 maximum).

1 mean number of instances (1 maximum).

2 mean number of activations (3 maximum).

CLIPS>