Sunteți pe pagina 1din 7

Inteligen artificial

Laboratorul 6

1. Obiective
Obiectivele acestui laborator se refer la prezentarea tipurilor de modele active din F#:

modele active singulare;


modele active pariale;
modele active parametrizate;
modele active multiple.

2. Motivaie
Potrivirea modelelor este mai elegant dect folosirea expresiilor condiionale if. Totui, nu
se poate aplica dect valorilor literale (ntregi, iruri de caractere etc.) sau, n mod limitat, unor
structuri de date predefinite, precum listele sau vectorii. Anumite probleme mai complexe se pot
rezolva folosind condiii when, care ns nu sunt foarte elegante. Pentru aceste cazuri, exist
construciile numite modele active (engl. active patterns), care combin potrivirea modelelor cu
funciile.

3. Modele active singulare


Modelele active singulare (engl. single-case active patterns) sunt cele mai simple modele
active i au rolul de a converti datele dintr-un tip n altul. Ele extind sintaxa de potrivire a modelelor
asupra unor tipuri de date care altfel nu ar putea beneficia de aceasta. Modelele active se definesc
folosind simbolurile (| i |) . n exemplul urmtor, modelul activ FileExtension identific
extensia unui fiier a crui cale o primete ca parametru.
let (|FileExtension|) filePath =
System.IO.Path.GetExtension(filePath)
let determineFileType filePath =
match filePath with
| FileExtension ".png"
| FileExtension ".jpg"
| FileExtension ".bmp"
-> sprintf "Este o imagine."
| FileExtension ".txt"
-> sprintf "Este un text."

Florin Leon, Inteligenta artificiala - Laborator, http://florinleon.byethost24.com/lab_ia.htm

Florin Leon, Inteligenta artificiala - Laborator, http://florinleon.byethost24.com/lab_ia.htm

Modele active

| FileExtension ext
-> sprintf "Este un fisier cu extensia %s." ext
...

Modelele active singulare pot fi tratate ca nite funcii normale. n exemplul de mai jos,
modelul activ ToUpper doar i transform intrarea i deci poate fi folosit n alte funcii:
let (|ToUpper|) (input : string) = input.ToUpper()
let f(ToUpper x) = sprintf "x = %s" x
...
printfn "%s" (f "abc") // x = ABC

4. Modele active pariale


n cazul n care nu exist o coresponden de 1 la 1 ntre intrri i ieiri, modelele active
singulare nu pot fi folosite. Un astfel de caz este conversia unui ir de caractere ntr-un tip numeric,
de exemplu ntreg. Modelele active pariale permit definirea unor funcii care nu realizeaz
ntotdeauna conversia datelor de intrare. Acest lucru este posibil datorit faptului c returneaz date
de tip Option care pot lua valorile Some i None. Pentru definirea modelelor active pariale, se
introduce simbolul _ ntre paranteze, pentru a arta c exist un rest de valori de intrare pentru
care nu se pot aplica potrivirile definite explicit.
open System
let (|ToInt|_|) x =
let success, result = Int32.TryParse(x)
if success then Some(result)
else None
let (|ToFloat|_|) x =
let success, result = Double.TryParse(x)
if success then Some(result)
else None
let (|ToBool|_|) x =
let success, result = Boolean.TryParse(x)
if success then Some(result)
else None
let test str =
match str with
|ToInt i -> sprintf "'%s' reprezinta un numar intreg: %d" str i
|ToFloat f -> sprintf "'%s' reprezinta un numar real: %f" str f
|ToBool b -> sprintf "'%s' reprezinta o valoare booleana: %b" str b
| _ -> sprintf "'%s' nu reprezinta un numar intreg, real sau o valoare booleana" str
...

Florin Leon, Inteligenta artificiala - Laborator, http://florinleon.byethost24.com/lab_ia.htm

Florin Leon, Inteligenta artificiala - Laborator, http://florinleon.byethost24.com/lab_ia.htm

printfn "%s" (determineFileType "C:\\image.png") // Este o imagine.


printfn "%s" (determineFileType "C:\\text.txt") // Este un text.
printfn "%s" (determineFileType "C:\\program.exe") // Este un fisier cu extensia .exe.

printfn "%s" (test "1") // '1' reprezinta un numar intreg: 1


printfn "%s" (test "1.1") // '1.1' reprezinta un numar real: 1.100000
printfn "%s" (test "TRUE") // 'TRUE' reprezinta o valoare booleana: true
printfn "%s" (test "abc") // 'abc' nu reprezinta un numar intreg, real sau o valoare booleana

Modele active pot primi i parametri, care sunt specificai imediat dup numele modelului.
Exemplul urmtor prezint o rezolvare a problemei FizzBuzz. Se afieaz numerele de la 1 la m.
Pentru numerele divizibile cu 3, se afieaz Fizz, pentru cele divizibile cu 5, se afieaz Buzz, iar
pentru cele divizibile i cu 3 i cu 5, se afieaz FizzBuzz. Modelul activ parametrizat este aici
DivisibleBy, care testeaz dac parametrul n este divizibil cu parametrul x.
let (|DivisibleBy|_|) x n =
if n % x = 0 then Some(DivisibleBy)
else None
let fizzbuzz n =
match n with
| DivisibleBy 3 & DivisibleBy 5-> sprintf "FizzBuzz"
| DivisibleBy 3 -> sprintf "Fizz"
| DivisibleBy 5-> sprintf "Buzz"
| _ -> ""
[<EntryPoint>]
let main() =
[ 1 .. 20 ]
|> List.map (fun x -> fizzbuzz x)
|> List.iteri (fun i x -> printfn "%d %s" (i + 1) x)

Rezultatul execuiei programului este urmtorul:


1
2
3 Fizz
4
5 Buzz
6 Fizz
7
8
9 Fizz
10 Buzz
11
12 Fizz
13
14
15 FizzBuzz
16
17

Florin Leon, Inteligenta artificiala - Laborator, http://florinleon.byethost24.com/lab_ia.htm

Florin Leon, Inteligenta artificiala - Laborator, http://florinleon.byethost24.com/lab_ia.htm

5. Modele active parametrizate

18 Fizz
19
20 Buzz

Modele active multiple (engl. multi-case active patterns) se utilizeaz n cazul n care este
necesar mprirea datelor de intrare n mai multe categorii. Acestea convertesc datele de intrare
ntr-o uniune discriminat.
Modele active multiple nu pot fi pariale.
S considerm mai nti un exemplu simplu, care testeaz dac un numr ntreg este par sau
impar:
let (|Even|Odd|) n =
if n % 2 = 0 then Even
else Odd
let test n =
match n with
| Even -> sprintf "%d este par" n
| Odd -> sprintf "%d este impar" n
...
printfn "%s" (test 1) // 1 este impar
printfn "%s" (test 2) // 2 este par

Exemplul urmtor primete un ir de caractere pe care l interpreteaz ca aparinnd uneia


din urmtoarele categorii: paragraf, propoziie sau cuvnt.
open System
let (|Paragraph|Sentence|Word|) (input : string) =
let input = input.Trim()
if input.IndexOf(".") <> -1 then
// paragraful contine o tupla cu numarul propozitiilor sale si propozitiile propriu-zise
let sentences = input.Split([|"."|], StringSplitOptions.None)
Paragraph (sentences.Length, sentences)
elif input.IndexOf(" ") <> -1 then
// propozitia contine un vector de cuvinte
Sentence (input.Split([|" "|], StringSplitOptions.None))
else
// cuvantul este un sir de caractere
Word (input)
let rec countLetters str =
// numara literele unui sir de caractere impartindu-l recursiv
match str with
| Word x ->
if x <> "" then printfn "Cuvant %A " x
x.Length

Florin Leon, Inteligenta artificiala - Laborator, http://florinleon.byethost24.com/lab_ia.htm

Florin Leon, Inteligenta artificiala - Laborator, http://florinleon.byethost24.com/lab_ia.htm

6. Modele active multiple

let main() =
printfn "%A" (countLetters "Laborator")
printfn "%A" (countLetters "Propozitia 1. Propozitia 2.")

Exemplu 1 de utilizare:
printfn "%A" (countLetters "Laborator")

Rezultat:
Cuvant "Laborator"
9

Exemplul 2 de utilizare:
printfn "%A" (countLetters "Propozitia 1. Propozitia 2.")

Rezultat:
Paragraf [|"Propozitia 1"; " Propozitia 2"; ""|]
Propozitie [|"Propozitia"; "1"|]
Cuvant "Propozitia"
Cuvant "1"
Propozitie [|"Propozitia"; "2"|]
Cuvant "Propozitia"
Cuvant "2"
22

Modelele active pot fi combinate. n exemplul urmtor, funcia imageTooBigForEmail


determin dac un fiier imagine are dimensiunea mai mare dect 1 MB, folosind trei modele
active:
open System.IO
let (|FileExtension|) filePath =
Path.GetExtension(filePath)
let (|KBInSize|MBInSize|GBInSize|) filePath =
// dimensiune in kilobytes, megabytes, gigabytes
let file = File.Open(filePath, FileMode.Open)
if file.Length < 1024L * 1024L then KBInSize
elif file.Length < 1024L * 1024L * 1024L then MBInSize
else GBInSize

Florin Leon, Inteligenta artificiala - Laborator, http://florinleon.byethost24.com/lab_ia.htm

Florin Leon, Inteligenta artificiala - Laborator, http://florinleon.byethost24.com/lab_ia.htm

| Sentence words ->


printfn "Propozitie %A " words
words |> Array.map countLetters |> Array.sum
| Paragraph (_, sentences) ->
printfn "Paragraf %A " sentences
sentences |> Array.map countLetters |> Array.sum

let imageTooBigForEmail filePath =


match filePath with
| IsImageFile & (MBInSize|GBInSize) -> true
| _ -> false

7. Aplicaii
7.1. Rulai programele din laborator, pentru cele patru tipuri de modele active.
7.2. Realizai un sistem expert bazat pe un arbore de decizie generic, reprezentnd
raionamentul pentru rezolvarea unei anumite probleme. Problema va fi rezolvat interactiv, prin
ntrebri adresate utilizatorului. Se pleac din rdcina arborelui i apoi, n funcie de rspunsurile
date, se coboar n arbore pn se atinge o frunz, corespunztoare unei concluzii sau soluii.
Pentru fiecare nod neterminal, se definesc urmtoarele caracteristici:

o ntrebare de al crei rspuns depinde alegerea urmtorului nod;


o list de rspunsuri acceptabile;
o mulime de reguli care determin nodul urmtor, n funcie de un anumit rspuns.
n acest scop se utilizeaz fapte de tipul:

regul <nod_curent> <rspuns> <nod_urmtor> // rspuns if, nod_urmtor then


ntrebare <nod_curent> <text_ntrebare>
rspunsuri <nod_curent> <list_rspunsuri_acceptabile>
concluzie <nod_terminal> <text_concluzie>

Se d urmtoarea baz de cunotine, inclus n fiierul viteza.kbf, care definete un arbore


de decizie pentru a determina tipul de micare al unui punct material:
root n11
question n11 Viteza isi pastreaza directia?
answers n11 da nu nu_stiu
rule when n11 if nu then n21
rule when n11 if da then n22
rule when n11 if nu_stiu then n23
conclusion n23 Informatii insuficiente.
question n21 Modulul vectorului viteza este constant?
answers n21 da nu
rule when n21 if nu then n31
rule when n21 if da then n32
conclusion n31 Miscare curbilinie neuniforma.
conclusion n32 Miscare curbilinie uniforma.
question n22 Vectorul acceleratie este nul?
answers n22 da nu
rule when n22 if nu then n33
rule when n22 if da then n34

Florin Leon, Inteligenta artificiala - Laborator, http://florinleon.byethost24.com/lab_ia.htm

Florin Leon, Inteligenta artificiala - Laborator, http://florinleon.byethost24.com/lab_ia.htm

let (|IsImageFile|_|) filePath =


match filePath with
| FileExtension ".png" | FileExtension ".jpg" | FileExtension ".bmp" -> Some()
| _ -> None

De exemplu, pentru nodul rdcin (notat n11) vom avea urmtoarele fapte:
question n11 Viteza isi pastreaza directia?
answers n11 da nu nu_stiu
rule when n11 if nu then n21
rule when n11 if da then n22
rule when n11 if nu_stiu then n23

Citirea coninutului fiierului se poate face astfel, valoarea facts fiind o list de string-uri,
cte un string pentru fiecare linie din fiier.
let facts =
File.ReadAllLines "viteza.kbf"
|> List.ofSeq

Utilizai un model activ de tipul:


let (|Root|Question|Answers|Rule|Conclusion|Other|) (line : string, node) =
let toks = line.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
match toks.[0], node with
// ...

Realizai cte o funcie pentru a identifica rdcina, ntrebarea din nodul curent, lista de
rspunsuri valide n nodul curent, o regul de tranziie ntr-un nod nou i concluzia din nodul curent,
dac exist: getRoot, getQuestion, getValidAnswers, applyRule, getConclusion. n acestea, se poate
folosi funcia List.choose.
Trebuie subliniat faptul c programul este independent de arborele de decizie pe care
lucreaz. Acelai program poate fi aplicat pentru alte probleme fr modificri suplimentare.
Exemplu:
Viteza isi pastreaza directia?
Raspunsul dumneavoastra (da/nu/nu_stiu): da
Vectorul acceleratie este nul?
Raspunsul dumneavoastra (da/nu): nu
Acceleratie constanta?
Raspunsul dumneavoastra (da/nu): da
Acceleratie pozitiva?
Raspunsul dumneavoastra (da/nu): nu
Miscare rectilinie uniform incetinita.

Florin Leon, Inteligenta artificiala - Laborator, http://florinleon.byethost24.com/lab_ia.htm

Florin Leon, Inteligenta artificiala - Laborator, http://florinleon.byethost24.com/lab_ia.htm

conclusion n34 Miscare rectilinie uniforma.


question n33 Acceleratie constanta?
answers n33 da nu
rule when n33 if nu then n41
rule when n33 if da then n42
conclusion n41 Miscare rectilinie neuniforma.
question n42 Acceleratie pozitiva?
answers n42 da nu
rule when n42 if nu then n51
rule when n42 if da then n52
conclusion n51 Miscare rectilinie uniform incetinita.
conclusion n52 Miscare rectilinie uniform accelerata.