Aiheet ICS-C2000 Tietojenkäsittelyteori Luento 4: Säännölliset lusekkeet Alto-yliopisto Perustieteiden korkekoulu Tietotekniikn litos Kevät 2016 Säännöllisten lusekkeiden syntksi Säännöllisten lusekkeiden semntiikk Säännöllisten lusekkeiden j äärellisten utomttien yhteys Mterili: suomeksi Orposen prujun luvut 2.6 2.7 englnniksi Sipserin kirjn luku 1.3 2/32 Äärelliset utomtit Äärelliset utomtit vs. säännölliset lusekkeet q7 q7.. M :=. q0 q1 q2 q3 exp exp exp M :=. q0 q1 q2 q3 exp exp exp q4 q6 q4 q6 +,- q5 +,- q5 tunnist L(M) = {.256,1.,3.14,2.3E 10,... tunnist L(M) = {.256,1.,3.14,2.3E 10,...= L(r) kuv r := (dd.d.dd )(e(+ )dd ) (dd e(+ )dd ) 3/32 4/32
Säännölliset lusekkeet Säännöllisten lusekkeiden sovelluskohteit Säännöllisiä lusekkeit (j niiden ljennuksi) käytetään mm. Kääntäjien seljien spesifiointi (lkionimien tunnistus) Tekstin hku j muokkus Ominisuuksien kuvuskielet (esim. PSL)... : Opiskelijnumeroiden piilotus Pythonill from sys import stdin, stdout import re i d P t t e r n = re. compile ( r ( \ d { 5 [ A Z ] ) ( \ d { 6 ) ( K \ d { 5 ) ) f o r l i n e i n s t d i n : stdout. w r i t e ( i d P t t e r n. su ( xxxxxx, l i n e ) ) Syöte: Tulos: Oiv :Opiskelij:12345X:5:2:4:9 F.I. :Nnce :K12345:5:9:4:2 Rimo:Rketti :123456:7:7:7:9 Oiv :Opiskelij:xxxxxx:5:2:4:9 F.I. :Nnce :xxxxxx:5:9:4:2 Rimo:Rketti :xxxxxx:7:7:7:9 5/32 6/32 Säännölliset lusekkeet Automttimlleist poikkev tp kuvt yksinkertisi kieliä. Olkoot A j B kkoston Σ kieliä. Perusopertioit: Yhdiste: A B = {x Σ x A ti x B Ktentio: AB = {xy Σ x A j y B; Potenssit: { A 0 = {, A k = AA k 1 = {x 1...x k x i A i = 1,...,k (k 1); Sulkeum t. Kleenen tähti : A = A k k 0 = {x 1...x k k 0, x i A i = 1,...,k. Määritelmä Akkoston Σ säännölliset lusekkeet määritellään induktiivisesti säännöillä: 1. /0 j ovt Σ:n säännöllisiä lusekkeit; 2. on Σ:n säännöllinen luseke kikill Σ; 3. jos r j s ovt Σ:n säännöllisiä lusekkeit, niin (r s), (rs) j r ovt Σ:n säännöllisiä lusekkeit; 4. muit Σ:n säännöllisiä lusekkeit ei ole. Huom! Kksi ensimmäistä sääntöä ovt perustpukset kun ts kolms sääntö on induktiivinen (rekursiivinen) sääntö. Viimeisin sääntö oletetn yleensä implisiittisesti j jätetään sen tki usein pois. 7/32 8/32
Määritelmä Kukin Σ:n säännöllinen luseke r kuv kielen L(r), jok määritellään induktiivisesti: L(/0) = /0 L() = { L() = { kikill Σ L((r s)) = L(r) L(s) L((rs)) = L(r)L(s) L(r ) = (L(r)) Akkoston {, säännöllisiä lusekkeit: r 1 = (()), r 2 = (), r 3 = ( ), r 4 = (( ())) Lusekkeiden kuvmt kielet: L(r 1 ) = ({{){ = {{ = { L(r 2 ) = { = {,,,,... = {() i i 0 L(r 3 ) = {({) = {,,,,... = { i i 0 L(r 4 ) = ({{,) = {, = {,,,,,... = {x {, kutkin -kirjint x:ssä seur 1 ti 2 -kirjint j ennen jokist -kirjint on iemmin inkin 1 -kirjin. 9/32 10/32 Sulkumerkkien vähentämissääntöjä: Operttoreiden prioriteetti: Eli (( )) trkoitt (( ())) mutt ( ) olisi jo eri luseke (() ()) Yhdiste- j tulo-opertioiden ssositiivisuus: L(((r s) t)) = L((r (s t))) L(((rs)t)) = L((r(st))) peräkkäisiä yhdisteitä j tuloj ei trvitse sulutt. Edellisen esimerkin lusekkeet yksinkertisemmin esitettynä: r 1 =, r 2 = (), r 3 =, r 4 = (( )). C-kielen etumerkittömät reliluvut numer = (dd.d.dd )(e(+ )dd ) (dd e(+ )dd ), missä d on lyhennemerkintä lusekkeelle d = (0 1 2 3 4 5 6 7 8 9) j e on lyhennemerkintä lusekkeelle e = (E e). Usein merkitään myös lyhyesti rr r +. (d +.d.d + )(e(+ )d + ) (d + e(+ )d + ). 11/32 12/32
Säännöllisten lusekkeiden sieventäminen Säännöllisillä kielillä on yleensä useit vihtoehtoisi kuvuksi, esim.: Määritelmä 2.4 Kieli on säännöllinen, jos se voidn kuvt säännöllisellä lusekkeell. Σ = L(( ) ) = L(( ) ) Säännölliset lusekkeet r j s ovt ekvivlentit, merk. r = s, jos L(r) = L(s). Lusekkeen sieventäminen = yksinkertisimmn ekvivlentin lusekkeen määrittäminen. Säännöllisten lusekkeiden ekvivlenssitestus on epätrivili, mutt peritteess meknisesti rtkev ongelm. 13/32 14/32 Sievennyssääntöjä: r (s t) = (r s) t r(st) = (rs)t r s = s r r(s t) = rs rt (r s)t = rt st r r = r r /0 = r r = r /0r = /0 r = r r r = ( r) Mikä thns säännöllisten lusekkeiden tosi ekvivlenssi voidn joht näistä lskuleist, kun lisätään päättelysääntö: jos r = rs t, niin r = ts, edellyttäen että / L(s). Khden lusekkeen ekvivlenssin totemiseksi knntt usein päätellä erikseen kummnkin kuvmn kielen sisältyminen toiseen. Merkitään lyhyesti: r s, jos L(r) L(s). Tällöin siis r = s joss r s j s r. Todetn, että ( ) = ( ). 1. Selvästi ( ) ( ), kosk ( ) kuv kikki kkoston {, merkkijonoj. 2. Kosk selvästi ( ), niin myös ( ) ( ). 15/32 16/32
Äärelliset utomtit j säännölliset kielet r = : Luse 2.4 r = s t : Jokisen säännöllisen lusekkeen r kuvm kieli voidn tunnist äärellisellä utomtill. Todistus r = : M s Seurvn klvon induktiivisen konstruktion vull voidn mielivltisen säännöllisen lusekkeen r rkennett seurten muodost - utomtti M r, joll L(M r ) = L(r). Tästä utomtist voidn poist -siirtymät Luseen 2.3 mukisesti, j trvittess voidn syntyvä epädeterministinen utomtti determinisoid Luseen 2.2 konstruktioll. Esitettävästä konstruktiost on syytä huomt, että muodostettviin - utomtteihin tulee in yksikäsitteiset lku- j lopputil, eikä minkään os-utomtin lopputilst lähde eikä lkutiln tule yhtään ko. osutomtin sisäistä siirtymää. r = : ( Σ) r = st : M s M t r = s : M t Ms 17/32 18/32 Lusekkeest r = (( )) sdn näiden sääntöjen mukn seurv -utomtti: Edellä esitetty utomtti on selvästi hyvin redundntti. Käsin utomttej suunniteltess ne knnttkin usein muodost suorn (mikäli tietää, mitä on tekemässä). Esim. lusekkeest r = (( )) on suhteellisen helppo muodost seurv yksinkertinen epädeterministinen tunnistj-utomtti: 19/32 20/32
Luse 2.5 Jokinen äärellisellä utomtill tunnistettv kieli voidn kuvt säännöllisellä lusekkeell. Todistus Trvitn vielä yksi äärellisten utomttien ljennus: lusekeutomtiss voidn siirtymien ehtoin käyttää mielivltisi säännöllisiä lusekkeit. Formlisointi: Merk. RE Σ = kkoston Σ säännöllisten lusekkeiden joukko. Lusekeutomtti on viisikko M = (Q,Σ,δ,q 0,F), missä siirtymäfunktio δ on äärellinen kuvus δ : Q RE Σ P (Q) Yhden skelen tilnnejohto määritellään: (q,w) M (q,w ) jos on q δ(q,r) jollkin sellisell r RE Σ, että w = zw, z L(r). Muut määritelmät smt kuin iemmin. Todistetn: jokinen lusekeutomtill tunnistettv kieli on säännöllinen. Olkoon M jokin lusekeutomtti. Säännöllinen luseke, jok kuv M:n tunnistmn kielen, muodostetn khdess viheess: (so. δ(q,r) /0 vin äärellisen monell prill (q,r) Q RE Σ ). 21/32 22/32 1. Tiivistetään M ekvivlentiksi enintään 2-tiliseksi lusekeutomtiksi seurvill muunnoksill: (i) Jos M:llä on useit lopputiloj, yhdistetään ne seurvsti. (ii) Poistetn M:n muut kuin lku- j lopputil yksi kerrlln seurvsti. Olk. q jokin M:n til, jok ei ole lku- eikä lopputil; trkstelln kikki reittejä, jotk M:ssä kulkevt q:n kutt. Olk. q i j q j q:n välittömät edeltäjä- j seurjtil jollkin tällisell reitillä. Poistetn q reitiltä q i q j oheisen kuvn (i) muunnoksell, jos tilst q ei ole siirtymää itseensä, j kuvn (ii) muunnoksell, jos tilst q on siirtymä itseensä: (i): r s q i q q j q i rs q j (ii): t r s q i q q j q i rt s q j 23/32 24/32
2. Tiivistyksen päättyessä jäljellä olev 2-tilist utomtti vstv säännöllinen luseke muodostetn seurvll tvll: (i): r Smll yhdistetään rinnkkiset siirtymät seurvsti: r r r s q i q j q i q j s (ii): r 1 r 3 r2 r 1r 2 (r 3 r 4 r 1r 2 ) r 4 25/32 26/32 ( )() ( ) ( )() ( ) ( ( )() ( )) Sivupolku: säännölliset lusekkeet ohjelmointikielissä Merkkijonojen käsittely on tärkeää moness sovelluskohteess (syötteen vlidointi we-lomkkeiss, hhmojen tunnistus j korvus toisill editoreiss jne) Niinpä monet (kikki uusimmt?) ohjelmointikielet sisältävät tuen säännöllisille lusekkeille (ti niiden ljennuksille): re-kirjsto Python-kielessä (lkuun: HOWTO) regex-kirjsto uusimmss C++:ss scl.util.mtching.regex-luokk Scl-kielessä jv.util.regex-pketti Jv-kielessä JvScript (stndrdin EMCAScript), ktso esim. W3Schools j moni muit! Myös sequentil expressions (SEREs) litteiston ominisuuksien kuvuskielessä Property Specifiction Lnguge PSL (IEEE stndrd 1850) Eräs kirj: Jeffrey Friedl, Mstering Regulr Expressions 27/32 28/32
: Nodes: -rivin numeron lukeminen perl-kielessä perl-ohjelmn os: su getnodes { my( $f ) = $_ [ 0 ] ; open ( FILE, $f ) ; while ( $ l i n e = <FILE >) { i f ( $ l i n e =~ / ^ Nodes : \W *([0 9]+) / ) { $nodes = $1 ; close ( FILE ) ; $nodes ; Eräs dttiedosto: Cnrep updtes : 1 Genertors : 2 Mx l e v e l : 3 Aut : 8 Nodes : 109294 Lef nodes : 3 Bd nodes : 107682 Totl time : 2.60 seconds missä s =~/r/ trkoitt merkkijonon s vertilu säännölliseen lusekkeeseen r, ^ täsmää rivin lkuun, \W on white spce, [0-9] jokin merkki joukost {0, 1,..., 9, j sulkujen sisällä olevn lilusekkeeseen täsmäävä limerkkijono sijoitetn muuttujn $1 Ljennukset: cse Python Monet kielet tukevt puhtiden säännöllisten lusekkeiden ljennuksi, trkstelln esimerkkinä Pythonin re-kirjsto Kiinteään potenssiin korotus, esim. () 5, on mhdollist toisto-operttorin {m,n vull, missä m on vähimmäs- j n mksimitoistojen määrä. Esimerkiksi ( ){20,200 täsmää merkkijonon knss, joss 20 200 /-merkkiä peräkkäin. Voidn ilmist (mhdollisesti hyvinkin ison) puhtn lusekkeen. Tunnistus on oletusrvoisesti hne eli löydetään vin pisimpiä täsmääviä limerkkijonoj: >>> import re >>> f o r m i n re. f i n d i t e r ( r ( )+, c ) : m. spn ( )... ( 0, 4) ( 5, 11) 29/32 30/32 : Scl-ohjelm, jok etsii henkilötunnuksi syötteestä: vl hetu = " " " (? : ^ \ D) ( \ d \ d ) ( \ d \ d ) ( \ d \ d ) ( \ + A) ( \ d { 3 ) ([0 9A Y ] ) (? : $ [ ^0 9A Y ] ) " " ". r vl centurymp = Mp( " + " >1800, " " >1900, "A" >2000) vl checksumtoletter = " 0123456789ABCDEFHKLMNPQRSTUVWXY". zipwithindex. mp( _. swp ). tomp for ( l i n e < i o. Source. s t d i n. getlines ) { hetu. f i n d A l l M t c h I n ( l i n e ). forech { cse hetu ( dy, month, yer, century, id, check ) => { vl enbirthdte = s " $month / $dy / $ { centurymp ( century ) +yer. t o I n t " vl checksum = ( dy+month+yer+ i d ). tolong % 31 vl i s V l i d = checksumtoletter ( checksum. t o I n t ) == check ( 0 ) p r i n t l n ( s " " " A${ i f (! i s V l i d ) " n i n " else " " v l i d hetu f o r someone orn on $enbirthdte " " " ) Scl Regex j Jv Pttern Joillkin ljennuksill on mhdollist ilmist ei-säännöllisiä ominisuuksi. Esimerkiksi tksepäin viittuksill ( ck-references ) voidn tunnist kieli {wcw w {, seurvsti: >>> import re >>> p t t e r n = re. compile ( r ( [ ] * ) c \1 $ ) >>> f o r s i n [ c, c, c ] :... i f p t t e r n. mtch ( s ) : p r i n t ( s+ " kuuluu k i e l e e n " )... c kuuluu k i e l e e n c kuuluu k i e l e e n Rivin 2 muuttuj \1 täsmää edellä olevn sulutettuun lusekkeen täsmänneen merkkijonon knss. Kyseinen kieli ei ole säännöllinen (miksi? sin pltn myöhemmin kurssill). Pähkinöitä tlvi-iltoihin Säännöllisten lusekkeiden ristisntehtävä (syntksi melko stndrdi ohjelmointikielissä käytetty, ktso esim. tästä) 31/32 32/32