kunstig intelligens (mnfit-272) - høst 1999
DESCRIPTION
Kunstig intelligens (MNFIT-272) - høst 1999. Forelesning 7. Emner:. •. AI språk - Egenskaper generelt - Prolog - Lisp Usikkerhetsbehandling - Statistisk-orienterte metoder - Kunnskapsbaserte metoder. AI språk. •. Spesielt utviklet for å kunne behandle. symbolstrukturer. •. - PowerPoint PPT PresentationTRANSCRIPT
Kunstig intelligens (MNFIT-272) - høst 1999. Forelesning 7
Emner:
• AI språk- Egenskaper generelt- Prolog- LispUsikkerhetsbehandling- Statistisk-orienterte metoder- Kunnskapsbaserte metoder
AI språk
• Spesielt utviklet for å kunne behandle symbolstrukturer.
• Et AI språk er utviklet for ett bestemt beskrivelsesnivå.
◊ Kunnskapsnivå-språk støtter analyse og modellering på et konseptuelt - og intensjonelt - nivå. Ofte endel av et system eller en metodologi for kunnskapsakkvisisjon i generell forstand.
Eksempler spenner fra grafiske editorer, der visualisering er sentralt, til formelle språk der sjekking av konsistens etc. er sentralt.
◊ Symbolnivå-språk støtter programmering og implementasjon.
En kan skille mellom to typer språk:
- Generelle programmeringsspråk (Lisp, Prolog, Smalltalk, C++, C, Pascal, Fortran, ...)
- Spesielle høynivå-språk og KBS-skall (KEE, ART, Nexpert Object, CLIPS, KappaPC, ...)
Krav til AI språk:
Behandler her kun symbolnivå-språk.
1. Støtte til symbolbehandling
2. Fleksibilitet
3. Støtte til eksplorativ programmering
4. Sen binding av variable
5. Veldefinert semantikk
1. Støtte til symbolbehandling
• Symbolbehandling innebærer evne til å representere, generere, og operere på symbolske uttrykk og strukturer av slike.
• Mønster-gjenkjenning (pattern matching) er sentralt
- matching av beskrivelser og tilstander i søkerommet, hel eller delvis match.
• Liste-behandling er sentralt
- lister er egnet til lagring av symbolstrukturer, uansett kompleksitet
2. Fleksibilitet
• Lett modifiserbare symbol-representasjoner
• Data-drevet kontroll av eksekveringen
• Bruker-spesifisert programkontroll
3. Støtte til eksplorativ programmering
• Gradvis definering av problemet- AI programmer angriper komplekse problemer.
• Gradvis definering av problemløsningen- heuristiske metoder, i motsetning til algoritmiske, er empiriske.
• Gradvis utforming av AI-metodene- valg og tilpasning av representasjon og reson- neringsmetoder krever ofte prøving og feiling.
• Et språk for eksplorativ programmering bør:
- være modulært- være utvidbart- ha gode abstraksjonsmekanismer- støtte rask prototyping- ha lett lesbare programmer- være interpreterbart- støttes av en effektiv programmeringsomgivelse
4. Sen binding av variable
• Manipulering av variable uten å ha angitt verdi eller verdi-type.
• Gradvis tilordning av typer og verdier til variable.
• Verdier eller typer angis til å begynne med som beskrankninger (constraints), som så influerer på verdiene til relaterte variable, osv. (constraint propagation).
5. Veldefinert språk-semantikk
• Enkel, klart forståelig språk-semantikk er en fordel.
• Eksempler er 'Horn clause' logikk (Prolog), og rekursiv funksjonsteori (Lisp).
• Pascal og Fortran, f.eks. har mer kompleks og uoversiktig semantikk.
• Siden AI programmer ofte utfører en kompleks behandling, er det dessto viktigere at program-meringsspråket er enkelt bydg opp, og benyttes på en mest mulig klar og oversiktlig måte.
PROLOG
• Basis: Matematisk logikk, 1. ordens predikatlogikk
• Et Prolog program er et sett av fakta-uttrykk og implikasjoner:
father(haakon,olav).male(olav).son(X,Y) :- father(Y,X), male(X).
• En eksekvering av et Prolog program er en logisk deduksjon utifra et startbegrep (goal):
son(olav,X).
• Deduksjon i et Prolog-program er basert på 'resolusjons'-algoritmen for teorembevis.
• Det fins også andre deduktive bevis-algoritmer. Mange som arbeider med logikk-programmering utfra andre bevis-algortimer enn 'resolusjon', benytter Lisp som programmeringsspråk.
• Prolog er et deklarativt språk
Satt på spissen: "make declarations, not programs"
LISP
• Basis: Matematisk teori for rekursive funksjoner, lambda-kalkyle.
• Et Lisp program er et sett av funksjonsdefinisjoner og funksjonskall. En funksjonsdefinisjon består av et sett funksjonskall til andre definerte funksjoner, rekursivt:
(push '(haakon olav) fathers) (push 'olav males) (defun is-father-of? (person-1 person-2)
(equal person-2 (second (assoc person-1 fathers))))(defun is-son-of? (person-1 person-2)
(and (member person-1 males) (is-father-of? person-2 person-1)))
(defun son-of (person)(second (assoc person fathers)))
• En eksekvering av et Lisp program er kall av en funksjon, hvis argumenter kan være kall til andre funksjoner, etc., rekursivt:
(is-son-of? (son-of 'haakon) (father-of (son-of 'haakon)))
• Lisp er et funksjonelt språk
Satt på spissen: "make functions, not assignments"
LISP - basiselementer:
s-expression
atom list
symbolnumber
• En liste er en sekvens av atomer og/eller andre lister adskilt av blanke tegn og innesluttet i parentes.
• Lister kan være nøstet i et uspesifisert antall nivåer
• Funksjonsdefinisjoner, dvs. programmer, såvel som datastrukturer er lister.
- Programmer og data er av samme type, dvs.programmer kan tolkes som data og omvendt.
• Datatyper tilordnes verdier, ikke variable
• Den tomme listen, dvs. () eller NIL har en spesiell rolle.
• Benytter dynamisk plass-allokering."Garbarge collection" frigjør tidligere okkupert plass.
LISP - basismekanismer
• Read - Eval - Print løkken er grunnmekanismen for eksekvering av Lisp programmer:
Read - et uttrykk (s-expression) leses inn
Eval - uttrykket evalueres
Print - returnert resultat skrives ut
• Eval er selve Lisp interpretatoren. Evaluering innebærer alltid at en verdi returneres.Dette gjelder for alle Lisp-uttrykk:
◊ et tall evalueres til seg selv - tallverdien returneres◊ et symboler evalueres til verdien det er bundet til◊ en liste evalueres ved at
første element tolkes som et funksjonsnavnresterende elementer tolkes som argumenter
I tillegg har mange funksjoner sideeffekter, som medfører større eller mindre endringer i den globale lisp-omgivelsen ('working memory' om du vil).
LISP - basisfunksjoner
• Listebehandling:cons car cdr
• Evalueringskontroll:eval quote
• Inn/Ut:read print
• Funksjonsdefinisjoner:defun lambda
• Prosedyrekontroll:do return
• Testing :cond equal atom listp
• Verditilordning:let set
+ ofte brukt
list, append, removecadr, caaddr, cdadr, ..first, second, .., last, nth
funcall, apply, ' , #'
format
dolist, dotimes
if, while, unless>, <=, = numberp, symbolp, ...
progn
Side-effekter, Bindinger
(funk-1 (funk-2 (funk-3 (funk-4 ...) ...) ...) ...)
• En funksjon som utføres returnerer en verdi. Verdien gis tilbake til den kallende funksjonen,som igjen returnerer en verdi som gis tilbake tildenne funksjonens kallende funksjon, osv. opp til topp-nivået i funksjonskall-kjeden.
• Mange Lisp funksjoner har i tillegg side-effekter , dvs. at det skjer ting når en funksjon utføres som ikkefanges opp av retur-verdien.
• Eksempler:(setq a 'b) ; returnerer: b
; side-effekt: symbolet a bindes til ; symbolet b
(defun a (n) (+ n 1)) ; returnerer symbolet a
; side-effekt: binder funksjons-
; definisjonen til a
Funksjonene over benyttes kun pga. sine side-effekter.
• (let ((a 'b) (c 2)) (list a c)) ; returnerer listen (b 2)
; side-effekt: ingen
• let benyttes for å definere lokale variable inni en funksjon,
og å gi dem initielle verdier
setq benyttes for å definere globale variable,
og for å endre verdien til variable innen en let blokk
Rekursjon og Lisp
• Et rekursivt program er et program som kaller seg selv.En rekursiv funksjon er en funksjon som er definert ved seg selv.
• Rekursive definisjoner er problemfrie såsant det fins et 'uthopp' fra rekursjonen, dvs. et test-kriterium som fører til at rekursjonsprosessen terminerer.
• Lisp's listebehandlings-egenskaper gjør rekursjon til en relativt enkel og naturlig programmerings-mekanisme for symbolbehandling.
• Prinsippet for rekursiv listebehandling er:
◊ Funksjonen kalles med den aktuelle listen som ett av argumentene.
◊ Det sjekkes om terminerings-kriteriet er oppfylt.
◊ Funksjonen utføres ved å kombinere en operasjon på første element i argument-listen med et kall til funksjonen (seg selv) utført på de resterende elementer i listen.
Rekursjon
Eksempel 1 For å utføre en operasjon på hvert element i en liste:
1. Hvis listen er tom, stopp. 2. Utfør operasjonen på første element i listen,
og kall funksjonen med resten av listen som argument.
;;; Funksjon for å finne antall elementer i en liste(defun count-elements (liste)
(cond ((null liste) 0) (t (+ 1 (count-elements (cdr liste))))))
Eksempel 2 For å utføre en operasjon på hvert element inntil en test slår til:
1. Hvis listen er tom, stopp og returner at test mislyktes. 2. Hvis testen slår til, stopp og returner aktuelt resultat,
hvis ikke, kall funksjonen med resten av listen som argument.
;;; Funksjon for å sjekke om et gitt element er medlem av en liste:(defun my-member (element liste)
(cond ((null liste) nil) ((equal element (car liste)) t) (t (my-member element (cdr liste)))))
Rekursjon
• En funksjon kan kalle seg selv rekursivt flere steder i funksjonskroppen.
Eksempel 3;;; Funksjon for å fjerne negative tall i en liste. Det rekursive ;;; kallet utføres både hvis testen slår til, og hvis den ikke gjør ;;; det:
(defun filter-negatives (liste) (cond ((null liste) nil) ((plusp (car liste))
(cons (car liste) (filter-negatives (cdr liste)))) (t (filter-negatives (cdr liste)))))
Numeriske funksjoner• Det er ikke bare for listebehandling at rekursive
definisjoner er velegnet:
;;; Funksjon for å beregne fakultet av et tall,;;; n! = 1*2*3*4*5*.....*(n-1)*n
(defun fac (n) (cond ((= n 0) 1)
(t (* n (fac (- n 1))))))
Kombinert car / cdr rekursjon
• Hvis elementer i en liste kan være lister, og underliggende liste-nivåer også skal behandles, er kombinert car- og cdr-rekursjon en metode som utnytter rekursivitet maksimalt.
;;; Funksjon for å telle opp antall atomære elementer i en ;;; liste, uansett på hvilket under-nivå de befinner seg(defun count-atoms (liste) (cond((null liste) 0) ((atom liste) 1) (t (+ (count-atoms (car liste)) (count-atoms (cdr liste))))))
;;; Funksjon for å 'flate ut' en liste, dvs. fjerne alle ;;; under-nivåer(defun flatten (liste) (cond((null liste) nil) ((atom liste) (list liste)) (t (append (flatten (car liste)) (flatten (cdr liste))))))
Iterasjon:
• Rekursjon er ikke eneste metoden for å utføre repeterende programtrinn i Lisp. - Men ofte den enkleste - såsant en har trening i å tenke rekursivt!
• Vanligste iterasjons-funksjoner: - do dolist dotimes- mapcar
• (dolist (<var> <list> <result>)(<body>))
(defun count-elements (liste) (let ((len 0)) (dolist (element liste len) (setq len (+ len 1)))))
• (do ((<var 1> <init 1> <update 1>) (<var 2> <init 2> <update 2>) ... (<var n> <init n> <update n>))
(<termination test> <returned result>) (<body>))
(defun count-elements (liste) (do ((len 0 (+ len 1)) (l liste (cdr l))) ((null l) len)))
En enkel do-løkke - uten kropp (<body>) !!
Høyere ordens Lisp-funksjoner• Tar andre Lisp-funksjoner som argument
Eksempel 1
;;; Generell filter-funksjon [ikke standard Lisp funksjon](defun filter (liste test-funksjon)
(cond ((null liste) nil) ((funcall test-funksjon (car liste))
(cons (car liste) (filter (cdr liste) test-funksjon))) (t (filter (cdr liste) test-funksjon))))
Eksempel 2
Mapping-funksjonen mapcar
• Iterativ funksjon for repeterende anvendelse av en funksjon på hvert element i en liste.
> (mapcar #'count-atoms '((a b) (c (((d) e)) f ((g))) h))(2 5 1)
(defun square-root-elements (liste) (mapcar #'sqrt liste))
> (square-root-elements '(2 3 4 5 6))(1.414213 1.732050 2 2.236067 2.449489)