Skjulte Markov Modeller og Genidentifikation 2003

Størrelse: px
Starte visningen fra side:

Download "Skjulte Markov Modeller og Genidentifikation 2003"

Transkript

1 Aarhus Universitet 18. december 2003 Datalogisk Institut Ny Munkegade, Bldg Århus C Skjulte Markov Modeller og Genidentifikation 2003 Niels Christian Bach Torben Lauritzen

2

3 Dette speciale er dedikeret til vores familier Trine, Sophia, Stine og Nanna.

4

5 Indhold 1. Indledning Specialets opbygning Biologisk model Biologiske Begreber DNA Genom Gen Proteinsyntese Evolution Anvendelse af geninformation Formalisering Skjulte Markov Modeller Grundlæggende begreber Parvis Alignment Viterbi og Forward algoritmen Parameterestimering Push-algoritmen Motivation Push-algoritmen for to sekvenser Push Udførelse Backtracking Pladsbesparelse og fronter Hirschbergs Pladsbesparelse Hirschberg og Skjulte Markov Modeller Push-algoritmen for tre sekvenser Pladsbesparelse og fronter Hirschbergs Pladsbesparelse for tre sekvenser Delproblem: To sekvens alignment Udvidelse til genidentifikation i

6 ii Indhold 5. Implementation Implementation af algoritmen Opbygning Input Implementation af Push-algoritmen Output Profiling Implementationsbetragtninger for Viterbi algoritmen Spildplads i forbindelse med tresekvens projektion Begrænsninger Eksperimenter udført på algoritmen Teoretiske mål Eksperimenterne Sammenligning af forskellige implementationer Asymptotisk udførelsestid Asymptotisk pladsforbrug Modelafhængig udførelsestid Modelafhængigt pladsforbrug Afrunding af eksperimenterne Genidentifikation Genfinder I Genfinder II Simulerede sekvenser Gærsekvenser Konklusion Perspektiv Parameterestimering Blast-søgning Grafisk interface/smm-designer A. XML 69 B. Emissionssandsynligheder 76 C. Kode 81 C.1. Getmaxprob C.2. Notify C.3. Bestprob C.4. getnotifylist D. Summary in English 87

7 Tabeller 2.1. Genomstørrelser Livets kode Viterbi algoritmen Jukes-Cantor Substitutionsmodel Asymptotiske udførelsestider Asymptotisk pladsforbrug iii

8

9 1. Indledning...turning the pages that describe the miracle of human life, written in the mysterious language of all the ages, the language of God. Dr. Francis S. Collins Livets Sprog, eller Guds Sprog, som Dr. Collins 1 kalder det, har et alfabet, der består af kun fire bogstaver (A, G, C, T), og ordene i sproget er generne, de arveenheder, der definerer en organisme. Den samlede arvemasse for en organisme, genomet, kan betragtes som én lang sekvens af de fire bogstaver. Måden man finder generne på er ved at lede efter bestemte mønstre i denne sekvens, som antyder, at der måske er et gen. Desværre er det meget svært at finde gener, hvis man kun leder i én sekvens. Man kan være uheldig både at undgå at finde nogle gener, som rent faktisk er der, og man kan forudsige nogle gener, som ikke findes i virkeligheden. For at nedbringe usikkerheden prøver man ofte at finde de samme gener i to forskellige organismer på én gang. Det er muligt fordi to organismer fra beslægtede arter har arvemasser, der ligner hinanden meget. Fx er arvemassen mellem to mennesker 99.9% identiske. To forskellige organismer har derfor ofte gener tilfælles, som de har arvet fra en fælles stamfader, men hvor det ene måske staves en smule anderledes end det andet. Vores mål har været at lave et framework, som kan bruges til at sammenligne tre sekvenser og finde gener i dem alle tre samtidig. Derved håber vi at kunne bidrage til opklaring af gen/ikke-gen spørgsmålet for sekvenser, hvor dette stadig er uklart, når man fx kun sammenligner to sekvenser. Vores framework er baseret på en sandsynlighedsteoretisk model kaldet en Skjult Markov Model (SMM). Givet en genstruktur af de sekvenser vi sammenligner, tillægges denne struktur en sandsynlighed af vores SMM, og når vi maksimerer denne sandsynlighed (for alle genstrukturer), får vi det bedste bud på en genstruktur. Vores væsentligste bidrag er en pladseffektiv implementation af dette framework, som er uafhængig af den anvendte SMM. For at teste kvaliteten af vores implementation har vi både analyseret simulerede og ægte sekvenser og fundet genstrukturer i dem. En af fordelene ved at vi har brugt en SMM er 1 Direktør, National Human Genome Research Institute. Dr. Francis S. Collins stod i spidsen for det offentlige Human Genome Project, der skulle sekventiere det menneskelige genom. 1

10 2 KAPITEL 1. INDLEDNING ATG TTT GGT CTA CCT CAA CAG GAA GTC TCC GAA GAG GAG AAA AGA GCT CAT CAA GAA CAA ACT GAG AAA ACC TTG AAA CAG GCC GCT TAT GTG GCT GCG TTT CTT TGG GTT TCC CCA ATG ATC TGG CAT TTG GTG AAA AAG CAA TGG AAA TAA Figur 1.1.: Et ord fra Livets Sprog. Genet hedder TOM5 (Translocase Outer Membrane) og dets funktion er translokase, dvs. at katalysere proteintransport i den ydre membran i mitokondrierne. Genet stammer fra en organisme, der hedder Saccharomyces cerevisiae (gær), som er en af de bedst studerede organismer, der findes. nemlig, at vi har haft mulighed for at simulere et output, som i vores tilfælde er nogle sekvenser med en genstruktur. Dette output (hvor strukturen er fjernet) har vi brugt som input til vores framework. Resultatet har vi sammenlignet med det simulerede output inkl. struktur. Desuden har vi anvendt vores program med nogle ægte sekvenser fra fire forskellige slags gær (taget fra [K + 03]). At vælge den bedst mulige SMM, herunder at vælge SMMens parametre til at finde gener, er et omfattende arbejde, som ikke er en del af denne rapport. Til gengæld har vi, som tidligere nævnt, adskilt SMMen fra implementationen af algoritmen, så det efterfølgende er nemt at ændre SMMen og derved opnå bedre genidentifikationsresultater, end vi er i stand til, med den SMM og de parametre vi har brugt Specialets opbygning Resten af denne rapport er opbygget således: Kapitel 2 - Biologisk Model: Her opsummerer vi kort den biologiske verdens sammenhæng og funktion på genniveau. I slutningen af kapitlet formaliserer vi de biologiske begreber, vi anvender i resten af rapporten. Kapitel 3 - Skjulte Markov Modeller: I dette kapitel gennemgår vi den statistiske teori, vi vil anvende til at lave genidentifikationen, dvs. den måde vi vil forsøge at finde mønstre i sekvenserne. Kapitel 4 - Push-algoritmen: Principperne bag den algoritme, vi har implementeret, bliver gennemgået i dette kapitel. Vi starter med to sekvenser og udvider senere til tre sekvenser. Kapitel 5 - Implementation: Detaljer omkring hvordan vi har implementeret algoritmen. I slutningen af kapitlet er der en gennemgang af de eksperimenter, vi har gennemført for at undersøge, om implementationen lever op til de tids- og pladsmæssige krav, vi forudsiger.

11 1.1. SPECIALETS OPBYGNING 3 Kapitel 6 - Genidentifikation: I dette kapitel anvender vi vores implementation til at identificere gener i tre sekvenser. Både simulerede og ægte sekvenser er undersøgt. Bilag A - XML: Et eksempel på en SMM i vores XML-format. Bilag B - Emissionssandsynligheder: Initialisering af emissionssandsynligheder for Genfinder I. Bilag C - Kode: C-kode for de vigtigste metoder. Bilag D - Summary: Resumé på engelsk. På adressen er der en hjemmeside, hvor denne rapport findes i både postscript- og pdf-format. Desuden ligger kildekoden til frameworket på denne side.

12 2. Biologisk model Da specialet handler om at identificere gener, er det nødvendigt at have lidt baggrundsviden, for at vide hvad vi taler om i den resterende del. Derfor gennemgår vi i korte træk de relevante biologiske begreber, der knytter sig til arvelighedslæren eller genetikken. Efter introduktionen af de begreber, der er væsentlige for os, formaliserer vi de begreber vi anvender senere Biologiske Begreber Set med en genetikers øjne kan man overordnet inddele alle levende organismer i 3 hovedgrupper eller -domæner. For det første deler man op i Prokaryoter og Eukaryoter, hvor Prokaryoter igen deles op i Bakterier(Eubakterier) og Arker(Archaeabakterier) [A + 02, figur 1-21 s. 18]. Alle tre hoveddomæner antages at have den samme oprindelse, men de har udviklet sig forskelligt, efter de er blevet adskilt. Opdelingen er baseret på, at arvematerialet i Prokaryoter bevæger sig frit i cytoplasmaet i cellernes indre, medens Eukaryoter har en kerne i deres celler, som indeholder det komplette arvemateriale for organismen (pånær visse organeller 1, som fx mitokondrier), og at Arkers metabolisme fungerer som i Bakterier, medens deres reproduktionsmekanisme fungerer som i Eukaryoter DNA DNA (Deoxyribonucleicacid) er en lang kæde af mindre molekyler kaldet nukleotider eller baser, og kaldes derfor et polynukleotid. Baser er de mindste kemiske byggesten, som vi vil beskæftige os med. En base kan være enten A (Adenin), G (Guanin), C (Cytosin), T (Thymin) eller U (Urasil), hvor de første 2 betegnes puriner og de sidste 3 pyrimidiner. Figur 2.1 viser opbygningen af de forskellige baser. De fire første indgår i DNA, medens Thymin skiftes ud med Urasil i RNA, som vi omtaler senere. Baser er en del af et nukleotid, som, udover basen, består af et sukker med 5 kulatomer (dexoyribose) og en eller flere fosfat-grupper. To nukleotider kan bindes sammen med en binding imellem kulstof nr. 3 i sukkeret på det ene nukleotid og kulstof nr. 5 i sukkeret på det andet nukleotid, via en fosfor-gruppe. Ved at lave mange af sådanne bindinger, opnår man en lang kæde af nukleotider, hvor 1 Organeller menes at være bakterier, som er trængt ind i cellerne på et tidligt tidspunkt i evolutionen, og som derefter har kopieret sig sammen med cellerne. 4

13 2.1. BIOLOGISKE BEGREBER 5 Figur 2.1.: Opbygningen af de forskellige baser, som illustreret i [Mus99]. Baserne til venstre er puriner, og til højre er det pyrimidiner.

14 6 KAPITEL 2. BIOLOGISK MODEL Figur 2.2.: DNA dobbelt-helix [Mus99]. kulstof nr. 5 i den første nukleotid (5 -enden) ikke er bundet til et andet nukleotid, og det samme gælder for kulstof nr. 3 i den sidste nukleotid (3 -enden) i kæden. DNA udgøres netop af en sådan kæde. Når man opskriver en DNA-sekvens, er konventionen, at den starter i 5 -enden og slutter i 3 -enden. I resten af specialet bruger vi betegnelserne A, G, C, T og U, når vi taler om nukleotider eller baser. DNA optræder oftest som en dobbelt-helix, som vist på figur 2.2, hvor der indgår to DNAsekvenser. Sekvenserne bindes sammen af hydrogen-bindinger mellem nukleotiderne, således at A bindes til T, og C bindes til G. De to DNA-sekvenser er derfor hinandens komplementære, så de på den måde begge kan tjene som skabelon for kopiering af DNA et, hvilket ses på figur 2.3. Længden af en DNA-sekvens angives ofte i base par (bp). RNA (Ribonucleicacid), er også et polynukleotid. Det minder meget om DNA, fx indgår A, C og G nukleotiderne både i RNA og DNA, men T er udskiftet med U. I modsætning til DNA, optræder RNA som regel kun som en enkelt streng, der til gengæld folder tilbage til sig selv, så store dele af RNA et sidder i en dobbelt-strenget struktur. RNA bruges som midlertidigt lager under proteinsyntesen, kaldet mrna (messenger RNA), men visse typer RNA har også en direkte funktion og bliver således ikke translateret til et protein. Det gælder fx rrna, som er en del af et ribosom 2. 2 Et ribosom er et stort kompleks bestående af mere end 50 proteiner og adskillige rrnaer, som laver proteinsyntese fra mrna [A + 02, s. 342].

15 2.1. BIOLOGISKE BEGREBER 7 Figur 2.3.: Kopiering af en DNA-sekvens kan ske på begge strenge [Mus99] Genom Når man taler om en organismes genom, mener man hele organismens arvemateriale, dvs. de DNA-sekvenser, der bærer arvematerialet. I tabel 2.1 ses nogle forskellige organismers genomstørrelse. Eukaryote genomer er en samling af kromosomer. Mennesker har således 23 kromosompar, 22 par af såkaldte autosomer og et xx-par (kvinder) eller xy-par (mænd), hvor x og y kaldes kønskromosomer. Det giver et samlet genom på 24 kromosomer. Et kromosom består af en meget lang DNA-sekvens, som er pakket sammen omkring forskellige proteiner, hvilket kaldes kromatin. På figur 2.4 ses et kromosom og den sammenhæng, det optræder i. Når kromosomet afbildes som et X, er der i virkeligheden 2 kopier af det samme kromosom, som er bundet sammen ved deres centromerer, som man kalder midten af et kromosom. Denne konformation viser kromosomerne umiddelbart før de deler sig, som led i en celledeling. Det er på dette tidspunkt, hvor det er lettest at se dem i et lysmikroskop, da det er på dette tidspunkt de er mest kondenserede. I 2001 blev Human Genome Project og Celera Genomics i konkurrence med hinanden færdige med at sekventere det menneskelige genom. Før, undervejs og efter, er der kommet mange andre organismer til, som har fået sekventeret deres genomer. Sekventeringen alene er et imponerende stykke arbejde, men det bliver først virkeligt anvendeligt, når man får kortlagt genomerne og finder ud af hvilken funktionalitet, der knytter sig til forskellige områder i dem.

16 8 KAPITEL 2. BIOLOGISK MODEL Art Træk Leveområde Genomstørrelse / [10 6 bp] Antal gener Eubakterier Escherichia coli Mycobacterium tuberculosis Arker Methanococcus jannaschii Eukaryoter Saccharomyces cerevisiae Drosophila melanogaster (frugt flue) Homo sapiens (menneske) Laboratorie favorit tuber- Forårsager kulose Litotrop, anaerob, methanproducerende Menneskelige tarme Menneskeligt væv 4, , Gejsere 1, Minimal model Drueskræl, øl 12, Eukaryot Nøgle til genetikken Rådden frugt omkring dyrs udvikling Mest studerede dyr Huse Tabel 2.1.: Oversigt over nogle genomstørrelser for udvalgte organismer fra de tre hoveddomæner [A + 02, tabel 1-1 s.20]. Figur 2.4.: Et kromosom set i dets kontekst [Mus99].

17 2.1. BIOLOGISKE BEGREBER Gen Et gen er en DNA-sekvens, som indeholder koden for et bestemt protein eller funktionelt RNA (RNA molekyler, som anvendes direkte i stedet for at blive oversat til et protein). Genstruktur er betegnelsen for genernes indre opbygning/opdeling. I Eukaryoter er der både kodende dele, kaldet exons (expressed sequences), og ikke-kodende dele, kaldte introns (intervening sequences). Derimod er hele genet kodende i Prokaryoter, således at deres gener kan anskues som et-exon-gener. Også genstart (sekvensen ATG) og genslut (sekvenserne TAA, TAA og TGA) signalerne er med i vores definition af genet. Introns er adskilt fra exons (Intervening Sequences) ved deres donor-site-sekvenser og acceptor-site-sekvenser, som er henholdsvis GT og AG. Under proteinsysntesen skilles introns fra exons i en proces, der kaldes splicing, som beskrevet i afsnit Proteinsyntese Proteinsyntese er betegnelsen for den proces, der ud fra et givet gen producerer det protein, der kodes for. En skematisk afbildning af processerne for Prokaryoter og Eukaryoter er vist på henholdsvis figur 2.6 og 2.7. Før vi forklarer proteinsyntesen, skal vi have defineret, hvad et protein og et codon er. Et protein er en lang kæde af aminosyrer. En aminosyre er den grundlæggende byggesten i proteiner, på samme måde som nukleotider er det i DNA og RNA, blot er der 20 forskellige aminosyrer. Proteiner har mange funktioner, hvor en af de vigtigste er deres rolle som katalysator for forskellige reaktioner. For proteinernes virkemåde er deres foldning ekstremt vigtig, idet deres sekundære, tertiære og kvadrære (se figur 2.5) struktur er med til at skabe de nødvendige active-sites, som et andet molekyle binder til for at lave en katalyseret reaktion. Foldningen er entydigt bestemt ud fra den primære struktur, som vi arbejder med. En sekvens af tre på hinanden følgende baser, der optræder i et exon, betegnes som et codon. Under produktionen af et protein, oversættes et codon til en aminosyre, som vist i tabel 2.1.4, der kaldes den genetiske kode. Tabellen gælder i langt de fleste organismer, men i fx mitokondrier er der nogle små afvigelser i koden, som er muliggjort ved, at de har deres egne transskriptions- og proteinsyntese systemer, som virker uafhængigt af resten af cellen og som derfor har kunnet opbygge variationer i koden i forhold til resten af cellen [A + 02, s. 336]. Af de 64 mulige codons er der tre, der ikke omsættes til aminosyrer. Det drejer sig om TAA, TAG og TGA som, når de mødes under oversættelsen fra codon til aminosyre under proteinsyntesen, afslutter denne (og dermed afslutter proteinet). Disse tre codons kaldes derfor for stopcodons. Desuden er codonet ATG specielt, idet det koder for aminosyren Methionin, men samtidig angiver starten på et gen. Det betyder, at der er 61 codons, der koder for en aminosyre, men kun 20 aminosyrer, der

18 10 KAPITEL 2. BIOLOGISK MODEL Figur 2.5.: De forskellige niveauer strukturen af et protein indeles i [Mus99]. Et Pleated sheet kaldes også for Beta-sheet.

19 2.1. BIOLOGISKE BEGREBER 11 Codon Amino Codon Amino Codon Amino Codon Amino TTT Phe TCT Ser TAT Tyr TGT Cys TTC Phe TCC Ser TAC Tyr TGC Cys TTA Leu TCA Ser TAA Stop TGA Stop TTG Leu TCG Ser TAG Stop TGG Trp CTT Leu CCT Pro CAT His CGT Arg CTC Leu CCC Pro CAC His CGC Arg CTA Leu CCA Pro CAA Gln CGA Arg CTG Leu CCG Pro CAG Gln CGG Arg ATT Ile ACT Thr AAT Asn AGT Ser ATC Ile ACC Thr AAC Asn AGC Ser ATA Ile ACA Thr AAA Lys AGA Arg ATG Met ACG Thr AAG Lys AGG Arg GTT Val GCT Ala GAT Asp GGT Gly GTC Val GCC Ala GAC Asp GGC Gly GTA Val GCA Ala GAA Glu GGA Gly GTG Val GCG Ala GAG Glu GGG Gly Tabel 2.2.: Livets kode. Oversættelse af codons til aminosyrer. optræder i organismerne. En aminosyre kan således have mere end et codon der koder for den. Codonsekvensen er altid aflæst i 5 til 3 retningen. I Eukaryot-proteinsyntesen er der følgende delprocesser: Transskription bruger den ene DNA-streng i en dobbelt-helix som skabelon, for at lave en komplementær RNA-streng. Denne form for RNA kaldes pre-mrna. Figur 2.6.: Proteinsyntesen i en Prokaryot. Der er ingen ikke-kodende dele i Prokaryote gener og der er ingen kerne, så derfor kan mrna direkte translateres til protein [A + 02, s. 315].

20 12 KAPITEL 2. BIOLOGISK MODEL Figur 2.7.: Proteinsyntesen i en Eukaryot [A + 02, s. 315]. 5 Capping og 3 Polyadenylation modificerer enderne på pre-mrna, således at det efter splicing kan genkendes som mrna. RNA Splicing fjerner introns fra pre-mrna, som efter 5 capping, splicing og 3 polyadenylation kaldes mrna, hvor m betyder messenger. Eksport Når et stykke mrna er helt færdigt, transporteres det gennem kernemembranen til cytoplasmaet. Translation I cytoplasmaet oversættes mrna til et protein, vha. ribosomer. Til dette formål bruges en speciel form for RNA, en gruppe kaldet trna (transfer RNA), som i den ene ende binder til en aminosyre og i den anden ende har et anticodon 3, som binder til det codon der koder for den givne aminosyre jvf. figur Ribosomet kører hen over mrnasekvensen og sørger for at anvende det rigtige trna på det rette sted, således at det korrekte protein genereres. 3 Da C binder til G og A til T, er et anticodon entydigt defineret ud fra det codon, der bindes til.

21 2.1. BIOLOGISKE BEGREBER Evolution Det antages at alle organismer har den samme stamfader, og organismer der er tilstrækkeligt nært beslægtede har ofte gener med cirka samme placering på genomet og samme funktion. Når man taler om evolution på genom-niveau, menes mutation, dvs. ændring, af den DNA-sekvens, der udgør genomet. De dele af genomet, som udgør generne, muterer som regel meget langsomt i forhold til de dele, der ikke koder for nogen gener. Det skyldes, at det har meget store konsekvenser at ændre et gens funktionalitet eller helt at ødelægge et gen, i modsætning til hvis man ændrer nukleotidesammensætningen i intergen områder. På denne måde bevares generne, og det giver mening at sammenligne beslægtede arters genomer. For at en mutation skal få betydning for de kommende generationer, er det nødvendigt, at den opstår i kønscellerne. Kopiering af genomet i forbindelse med en kønscelledeling, også kaldet meiose, er den væsentligste årsag til mutationer. Undervejs i kopieringsprocessen kan der ske en fejl, selvom der er mange forskellige fejlretningsmekanismer. Hvis en sådan mutation faktisk viser sig at være brugbar, kan det være at organismen overlever, og måske bliver stamfader til en ny art. Mutationerne deles ind i følgende grupper (hvor der kopieres fra stamsekvensen til dattersekvensen): Substitution: Nukleotid α i stamsekvensen er erstattet af nukleotid β i dattersekvensen. Deletion: Nukleotid α i stamsekvensen er slettet i dattersekvensen. Insertion Nukleotid β er indsat i dattersekvensen. Invertion: Et stykke DNA er vendt om i dattersekvensen i forhold til stamsekvensen. Translocation: Et stykke DNA fra stamsekvensen har en anden placering i dattersekvensen. Duplication: Et stykke DNA i stamsekvensen er kopieret og indsat 2 steder i dattersekvensen. Af de nævnte mutationer er de tre første langt de hyppigst forekommende. Vi vil i resten af specialet derfor se bort fra Invertion, Translocation og Duplication og kun fokusere på Substitution, Insertion og Deletion.

22 14 KAPITEL 2. BIOLOGISK MODEL Anvendelse af geninformation Når man kender genernes placering og funktion, kan man begynde at anvende denne information. Som eksempel kan oplysingerne bruges til at diagnosticere sygdomme ved at aflæse et bestemt gen i en patients genom og teste, om der er opstået mutationer i forhold til det normale (fungerende) gen. Er der så tale om en gendefekt, arbejder man i øjeblikket på en behandling kaldet genterapi. Genterapi er årsagsbehandling i stedet for symptombehandling, som traditionel medicinering er. Det er naturligvis en stor fordel, men desværre er man ikke nået så langt, at genterapi kan tilbydes mennesker, og så har man oven i købet haft nogle tilbageslag, som har forsinket udviklingen yderligere. Genterapi virker på en af følgende måder [Lab03]: Et normalt fungerende gen indsættes på et tilfældigt sted i genomet, så det erstatter et defekt gen. Et defekt gen erstattes af et fungerende gen. Det defekte gen kan repareres. Reguleringen af et bestemt gen kan ændres, således at man ændrer i kvantiteten af det tilhørende protein. I de fleste tilfælde forsøger man at anvende den første metode. Til at udføre indsættelsen af det fungerende gen anvender man en bære-enhed, også kaldet en vector. I øjeblikket bruger man forskellige slags vira til at agere vector. De vira, man anvender, er i stand til at indsætte deres eget arvemateriale i DNA i de celler, de inficerer. Man inficerer derfor de celler, man ønsker at reparere (fx leverceller), med en virus, som helst ikke skal forårsage anden sygdom. Til gengæld indeholder virussen en kopi af det fungerende gen, som på denne måde kommer ind i genomet i de inficerede celler Formalisering Formålet med dette afsnit, er at koble de biologiske begreber, der blev gennemgået i afsnittet før sammen med de mere formelle begreber, vi vil anvende i det efterfølgende. Derved får vi fjernet de overflødige biologiske detaljer og opnår en model, der er nemmere at overskue. Grundstenene vi vil benytte er nukleotiderne. Definition (Nukleotid) Et nukleotid er et element i mængden N = {A, C, G, T }. Et nukleotid kaldes til tider også en base, idet et nukleotid er entydigt bestemt ved dets base. Som tidligere nævnt kaldes en sekvens sammensat af nukleotider for en DNAsekvens.

23 2.2. FORMALISERING 15 Definition (DNA-sekvens) En DNA-sekvens er en streng s N. Hvis vi i det efterfølgende taler om en sekvens, mener vi en DNA-sekvens. Definition (Sekvensnavne) Med S k sekvens. Længden af S k kalder vi L k. betegner vi i det følgende den k te input Definition (Exon) Et exon er en kodende del af et gen. Definition (Intron) Et intron er den ikke-kodende del af et gen. Definition (Codon) Et codon er en sekvens af tre på hinanden følgende baser i et exon. Definition (Startcodon) Et startcodon er sekvensen ATG. Definition (Stopcodon) Et stopcodon er en af sekvenserne TAA, TGA eller TAG. De sidste to definitioner dækker de to opfattelser af genstruktur, som vi anvender fremover. Definition (Genstrukturmodel I) En genstruktur består af et startcodon, et exon og et stopcodon. Definition (Genstrukturmodel II) En genstruktur består af et startcodon, nul eller flere exon-intron dele, et exon og et stopcodon.

24 3. Skjulte Markov Modeller Dette kapitel er en introduktion til Skjulte Markov Modeller (SMM, fra engelsk: Hidden Markov Model). Teorien om SMMer [D + 98] vil danne grundlag for vores valgte metode til at lave genidentifikation. Vi definerer, hvad en SMM er, og introducerer nogle af de begreber, vi vil bygge videre på. Herefter gennemgår vi et eksempel på en par-smm, og endelig udvider vi notationen, så vi kan bruge den generelle formulering i en par-smm. Ved genidentifikation er man interesseret i at identificere de kodende regioner i et gen. For at gøre dette, skal man kunne skelne imellem en masse støj, fx strukturer, der ligner gener, men ikke er det, og så de rigtige gener. Derfor sammenligner man ofte det samme område på genomer fra forskellige organismer, idet det tillægges større vægt at finde strukturen af et gen i to organismer end kun i en. En væsentlig grund til at det kan lade sig gøre at finde de samme gener i forskellige organismer er, at de kodende regioner af et genom muterer meget langsommere end de ikke-kodende dele (se afsnit 2.1.5). En Skjult Markov Model er en statistisk model, som er velegnet til mange anvendelser inden for bioinformatik. Den mest anvendte brug af SMMer inden for bioinformatik er som en sandsynlighedsteoretisk profil af en famillie af sekvenser: Givet en sekvens kan man finde sandsynligheden for at sekvensen tilhører famillien af sekvenser. En SMM er velegnet til at genkende en regulær struktur, som fx genstruktur (se definition og ), hvor man leder efter signaler, som kan betyde en bestemt del af genstrukturen, og som overholder strukturen. Man kan vise, at en SMM netop kan genkende regulære sprog. En af fordelene ved en SMM er derfor, at den netop kan opfange, at der kan være forskellige lovlige strukturer og at den kan vægte dem med forskellige sandsynligheder. Teorien omkring SMMer blev udviklet til brug inden for talegenkendelse i starten af 70erne. Formél sprogteori er blevet brugt til at løse biologiske problemer før, se fx [SEA92]. En tidlig brug af en SMM inden for bioinformatik blev præsenteret på en konference i 1992 og i en teknisk rapport, som blev publiceret i [H + 93] og [K + 94] Grundlæggende begreber Definition (Skjult Markov Model) En SMM er en 4-tupel (S,T,A,E). Hvor S er en mængde af tilstande, T er en matrix af transitionssandsynligheder {t kl k, l S}, A er et alfabet af symboler og E er en mængde af emissionssandsynligheder {e k k S}. En SMM har altid en starttilstand (tilstand 0) og en stoptilstand. En vej igennem en 16

25 3.1. GRUNDLÆGGENDE BEGREBER 17 SMM er en sekvens af tilstande π = π 1 π 2...π L, hvor π i er tilstand i. Transitionssandsynligheden er kun afhængig af den foregående tilstand på vejen. Den er givet ved: t kl = P (π i = l π i 1 = k) (3.1) hvor l, k S. Dette er Markov egenskaben for modellen. I en tilstand kan der genereres et symbol fra en fordeling over alfabetet A. Symbolet kalder vi for x i for tilstand i. Emissionssandsynligheden er givet ved: e k (b) = P (x i = b π i = k) (3.2) det er sandsynligheden for at symbol b udsendes i tilstand k. Sekvensen af symboler, der genereres af en vej π, kalder vi x = x 1 x 2...x L. En SMM kan simulere en sekvens x over alfabetet (A). Definition (Simulering af en SMM) En simulering af en SMM genererer en sekvens x, hvor hvert x i er udsendt fra en tilstand π i jvf. dennes emissionsfordeling, og π i er en tilstand i vejen π, som er fundet ud fra transitionssandsynlighederne for de enkelte tilstande. Simuleringen starter i tilstand 0. At det hedder en Skjult Markov Model hænger sammen med definition 3.1.2, idet det der genereres, ikke er vejen af tilstande, π, men derimod symbolerne langs vejen. Vejen π, af tilstande, er således skjult. Givet en sekvens af symboler x og en vej π igennem SMMen kan vi beregne sandsynligheden for, at x udskrives langs π. Vejen π fastlægger transitionssandsynligheden t πi π i+1 for hver transition, og x fastlægger, hvad emissionssandsynlighederne e k (b) er. Starttilstanden er tilstand 0 og stoptilstanden er tilstand L + 1. Den samlede sandsynlighed er P (x, π) = t 0π1 Vi vil gerne finde den mest sandsynlige vej π givet input x: L i=1 e πi (x i )t πi π i+1 (3.3) π = argmax π P (x, π). (3.4) Vi maksimerer over alle mulige tilstandsveje π, der udskriver x. Den mest sandsynlige vej π kan findes rekursivt. Antag at v k (i) er sandsynligheden for den mest sandsynlige vej, der stopper i tilstand k og har udskrevet x 1, x 2,.., x i, er kendt for alle tilstande k. Vi kan beregne sandsynlighederne for symbol x i+1 : v l (i + 1) = e l (x i+1 )max k (v k(i)t kl ). (3.5)

26 18 KAPITEL 3. SKJULTE MARKOV MODELLER Initialisering: (i = 0) v 0 (0) = 1, v k (0) = 0, k > 0 Rekursion: For (i = 0...L) v l (i) = e l (x i )max (v k(i 1)t kl ) k Terminering: P (x, π ) = max (v k(l)t k(l+1) ) k Tabel 3.1.: Viterbi algoritmen Dette giver en rekursiv måde at finde sandsynligheden for den mest sandsynlige vej. Denne metode kaldes Viterbi algoritmen [D + 98, p , 82-85, 109]. For at finde den mest sandsynlige vej π holder vi styr på de tilstande, der indgår i maksimeringen i hver iteration. Hver gang vi maksimerer over alle tilstande l huskes, hvilken tilstand den største sandsynlighed kom fra, sådan at når vi er færdige, kan vi lave backtrack og finde den mest sandsynlige vej. Mange forskellige veje af tilstande kan give anledning til det samme output x. Det kan være interessant at vide, hvad den totale sandsynlighed P (x) er for at sekvensen x udskrives. P (x) = π P (x, π). Sandsynligheden P (x) kan findes ved hjælp af Forward algoritmen, som er en variation af Viterbi algoritmen, hvor maksimeringen blot er skiftet ud med en summering Parvis Alignment Nu vil vi beskrive, hvordan man kan bruge en såkaldt par-smm til at aligne to sekvenser. Betragt to sekvenser S1: AGGAGGCC S2: TTAGGCGG som vi gerne vil aligne. Ved aligne forstår vi at sætte de dele over hinanden, som på en eller anden måde matcher. Resultatet af at aligne nogle sekvenser er et alignment. Definition (Alignment af N sekvenser) N sekvenser sat over hinanden i en N l-matrix, hvor der kan være indsat mellemrumstegn, således at række i uden mellemrumstegn netop er sekvens i. Der må dog ikke være søjler i alignmentet kun med mellemrumstegn. I det følgende anvender vi alignment for to sekvenser. Her ses et muligt alignment: Eksempel (Eksempel alignment) S1: AGG-A-GG-CC S2: -T-TAGGCG-G

27 3.2. PARVIS ALIGNMENT 19 Man kan bruge Smith-Waterman [SW81] algoritmen til at finde alignments med dynamisk programmering. Denne algoritme har både et tids- og pladsforbrug på O(L 1 L 2 ) for to sekvenser. Det gør man ved at definere en cost funktion, der tildeler et alignment en score. At finde et alignment er så blevet til et optimeringsproblem, hvor man skal maksimere eller minimere scoren over mængden af mulige alignments af inputsekvenserne. Vi vil bruge en SMM til at lave alignments med, hvor scoren blot erstattes med en sandsynlighed. Senere ser vi på hvordan man finder det alignment der har størst sandsynlighed. Definition (Søjle) For to sekvenser er en søjle fra et alignment en 2-tupel k 2 ({A, C, G, T, }) 2 \ ( ) 2. Et alignment er bygget op af Substitution, Insertion og Deletion, som er flg. ( # ) # Substitution 1 : En nukleotid i S1 er blevet erstattet med en nukleotid i S2 (muligvis ( - # den samme) ) Insertion: En nukleotid er indsat i S2 ( # ) - Deletion: En nukleotid er slettet i S2 hvor # = {A, C, G, T }. En par-smm har tilstande S = {Start, Stop, Substitution, Insertion, Deletion}, som kan ses på figur 3.1 med tilhørende transitionssandsynligheder, T. Hvordan man bestemmer sandsynlighederne i en SMM nævner vi i afsnit 3.4. Alfabetet (A) er en liste af søjler som er flg. ( )( )( )( )( )( )( )( )( )( )( )( )( )( )( )( )( )( )( )( )( )( )( )( ) A C G T A C G T A C G T A C G T A C G T A C G T A A A A C C C C G G G G T T T T For hver tilstand skal vi angive en emissionsfordeling (E). For tilstanden Insertion og Deletion er de ofte følgende: e Insertion ( ( ) # - ) = 1/4 edeletion ( ( - #) ) = 1/4, hvor # = {A,C,G,T}. For tilstanden Substitution kan man se emissionstabellen i tabel 3.2, fx er e Substitution ( ( A C) ) = α. Denne tabel 3.2 kaldes for Jukes-Cantor substitutionsmodellen med parameter α. I dette eksempel vil vi sætte α = 0.01, hvilket betyder fx at e Substitution ( ( A A) ) = 0.22 og e Substitution ( ( A C) ) = Hermed har vi specificeret en par-smm til alignment. Dvs. vi har beskrevet de forskellige dele af 4-tuplet (S,T,A,E). Lad os nu se på betydningen af at et alignment har en sandsynlighed. Med udgangspunkt i eksempel skriver vi alignmentet op som input til en par-smm: x = ( A ( G ) ( G ( - ( A ) ( G ( G ) ( G ( C ) -) T -) T) A) (Ḡ G) C) (Ḡ -) G 1 Substitution kaldes også (mis)match

28 20 KAPITEL 3. SKJULTE MARKOV MODELLER 3/4 1/3 Substitution 1/20 3/4 1/10 1/10 1/10 Start 1/3 Insertion 1/20 End 3/4 1/10 1/10 1/10 1/3 1/20 Deletion Figur 3.1.: Tilstande og mulige transitionssandsynligheder for en SMM. A C G T A (1 12α)/4 α α α C α (1 12α)/4 α α G α α (1 12α)/4 α T α α α (1 12α)/4 Tabel 3.2.: Jukes-Cantor Substitutionsmodel

29 3.2. PARVIS ALIGNMENT 21 Udfra ovenstående inputsekvens x vil vi finde π = argmax π P (x, π) hvilket betyder, at vi skal maksimere over alle mulige veje af tilstande for denne inputsekvens, men der er faktisk kun en mulig vej af tilstande. Det er tydeligt at se på inputsekvensen x hvilke tilstande den har gennemløbet: x = ( ( A G ) ( G ( - ( A ) ( G ( G ) ( G ( C ) -) T -) T) A) (Ḡ G) C) (Ḡ -) G π = ( # ( # ( # ( - ( # ( - ( # ( # ( - ( # ( # ) -) #) -) #) #) #) #) #) #) -) # Det spørgsmål vi i virkeligheden gerne vil svare på er: Hvad er det mest sandsynlige alignment af S 1 og S 2. Måden vi vil løse dette problem på er ved at omdefinere emissionssandsynlighederne (se ligning (3.2)) og den samlede sandsynlighed (se ligning (3.3)). Vi skal først have defineret nogle funktioner, som gør beskrivelsen lidt lettere, så vi senere kan opskrive rekursionsligningerne for en par-smm til Viterbi algoritmen. Givet inputsekvenser S 1 og S 2 lad os antage, at den første tilstand i et alignment skal være ( - #). Det betyder at man vil aligne ( - S 2 [1]), så første nukleotid på S2 er brugt. Til at beskrive at tilstanden aligner forskellige dele af inputsekvenserne, definerer vi funktionen f adv, som giver advancevektoren: ( ) ( ) ( ) # - # f adv ( ) = (1, 1) f adv ( ) = (0, 1) f adv ( ) = (1, 0) # # - Vi skal vide hvor meget et præfiks af vejen, π p = π 1 π 2..π i, vil generere af inputsekvenserne. Det kan vi finde ved at summere alle advancevektorerne for de tilstande der indgår i præfikset. Summen f adv (π 1 ) + f adv (π 2 ) f adv (π i ) = (v 1, v 2 ) giver de præfikser S 1 [1..v 1 ] og S 2 [1..v 2 ] som er blevet genereret. Det symbol x i, der udskrives i tilstand π i, er x i = ( S1 [v 1 ] S 2 [v 2 ] ( S1 [v 1 ] ( - - S 2 [v 2 ] ) ) ), π i = ( #) #, π i = ( #) -, π i = ( ) - # (3.6) Den sandsynlighed vi skal maksimere, når vi vil finde π, bliver så: P (S 1, S 2, π) = t 0π1 L i=1 e πi (x i )t πi π i+1 (3.7)

30 22 KAPITEL 3. SKJULTE MARKOV MODELLER 3.3. Viterbi og Forward algoritmen I dette afsnit gennemgår vi hvordan Viterbi og Forward algoritmerne virker. Beskrivelsen tager udgangspunkt i Viterbi algoritmen. Viterbi algoritmen er en rekursiv algoritme, der, for et givet input, kan finde den mest sandsynlige vej π igennem en SMM, som genererer dette input. For alignment af to sekvenser giver det anledning til følgende rekursionsligninger: Hvis q er en substitution ( # #) : Hvis q er en deletion ( # -) : Hvis q er en insertion ( - #) : D(q, i, j) = max p D(q, i, j) = max p D(q, i, j) = max p For alle tre tilstande kan man sætte: [ ( ) ] S1 [i] D(p, i 1, j 1)t pq e q ( ) S 2 [j] [ ( S1 [i] D(p, i 1, j)t pq e q ( - ) ) [ ( ) ] - D(p, i, j 1)t pq e q ( ) S 2 [v 2 ] ] (3.8) (3.9) (3.10) D(q, 0, 0) = 1/3 (3.11) Derved bliver sandsynligheden for det mest sandsynlige alignment: hvor L 1 og L 2 er længderne af sekvenserne. P (S 1, S 2, π ) = max(d(q, L 1, L 2 ) t q(l+1) ) (3.12) q Rekursionsligninger kan implementeres vha. dynamisk programmering. Vi genbruger de løsninger, vi har beregnet i stedet for at beregne dem igen. En indgang D(q, i, j) kan fortolkes, som sandsynligheden for den mest sandsynlige vej π 1 π 2...q hvor delsekvenserne S 1 [1..i] og S 2 [1..j] er genereret. Forward algoritmen er, som tidligere nævnt, at man summerer i stedet for at maksimere i rekursionligningerne. I figur 3.2 kan man se en matrix for hver tilstand som udfyldes vha. ligningerne (3.8) (3.9) (3.10) henholdsvis. Det er illustreret med pile, hvilke indgange i matricerne man skal bruge for at beregne en indgang i Substitutionsmatricen.

31 3.3. VITERBI OG FORWARD ALGORITMEN 23 Insertion Deletion 0 Sekvens 2 0 L Sekvens 2 L 1 L 2 L Sekvens 2 L 1 2 Sekvens 1 Sekvens 1 Sekvens 1 Substitution L 2 Figur 3.2.: Matricer til dynamisk programmering.

32 24 KAPITEL 3. SKJULTE MARKOV MODELLER Tidskompleksiteten for Viterbi algoritmen er O(L 1 L 2 ), og pladsforbruget er O(L 1 L 2 ), hvor L 1 = S 1 og L 2 = S Parameterestimering Når man skal designe en SMM, skal man specificere de fire elementer i (S,T,A,E): Tilstande, transitionssandsynligheder, alfabet og emissionssandsynligheder. Strukturen af modellen er vigtig, men uden de rette parametre (sandsynligheder) kan det være svært at opnå gode resultater. I dette afsnit gennemgår vi kort, hvordan man fx kan estimere parametrene. Hvis man har et alignment, og man kender vejen π igennem den tilhørende SMM, kan man estimere transitionssandsynlighederne [D + 98] ved at tælle hvor mange gange, man laver en transition fra tilstand t 1 til tilstand t 2 (se ligning 3.13). Det samme gælder emissionssandsynlighederne, hvis man ved hvor mange gange de forskellige emissioner forekommer. Man skal bruge et træningssæt, som skal være så stort, at det kan indfange de variationer der forekommer i forskellige alignments. Til gengæld skal det ikke være så stort at man overtræner modellen, så det kun er træningssættet den aligner godt. Parametrene kan sættes således: t kl = A kl l A e k (b) = E k(b) kl b E k(b) (3.13) hvor A kl = antal transitioner fra k til l i træningssættet og E k (b) = antal emissioner af b i k i træningssættet. Hvis man ikke kender vejen π, er man nødt til at bruge en iterativ process. Der findes iterative metoder, hvor man kan justere parametrene for hver iteration, som garanterer at processen konvergerer mod et lokalt maksimum. Mange sådanne træningsmetoder bruger Forward algoritmen [D + 98], der gør det samme som Viterbi algoritmen med den undtagelse, at den summerer i stedet for at maksimere.

33 4. Push-algoritmen I dette kapitel beskriver vi en måde at implementere Forward- og Viterbi-algoritmerne på, således at man får en lineær pladsbesparelse foræret, uden at det bliver implementationsmæssigt sværere at lave for tre sekvenser, sammenlignet med to. Desuden adskiller vi algoritmen og implementationen fra strukturen af den SMM, vi vil anvende, således at en udskiftning af SMMen ikke medfører et behov for en reimplementation. Kapitlet er bygget op således, at vi først gennemgår vores algoritme, det vi har kaldt Push-algoritmen, for alignment af to sekvenser (4.2). Herefter viser vi, hvad Hirschbergs Pladsbesparelse er, og hvordan vi kan bruge den i algoritmen (4.2.5). Endelig er der en gennemgang af udvidelsen af Push-algoritmen, til at kunne aligne tre sekvenser (4.3) Motivation Hvis man gerne vil aligne et antal sekvenser, fx vha. en SMM, kan det lade sig gøre i tid og ikke mindst plads proportional med produktet af længderne af de sekvenser, der skal alignes. For alignments af mere end to sekvenser vil de sekvenser, der er interessante, ofte være længere, end hvad der er praktisk muligt at aligne. Især er pladskravet en begrænsende faktor da fx et kubisk pladsforbrug for tre sekvenser hurtigt overstiger de hukommelseskapaciteter, man arbejder med i dag. For at give et eksempel på dette, har vi i afsnit lavet et overslag på hvor meget plads, der skal til at aligne tre sekvenser, der er ca bp lange. Resultatet er, at der skal over 300 Gb RAM til, før det bliver muligt. Hirschberg [Hir75] har beskrevet en pladsbesparende metode, som gennemgåes i afsnit Ved at benytte denne metode, opnår man en lineær pladsreduktion på bekostning af en fordobling af udførelsestiden. Derved bliver det realistisk at forsøge at aligne tre sekvenser, der har en længde, der er mindre end de 1000 bp fra før (se afsnit 5.2.8). Den traditionelle implementation af Hirschbergs Pladsbesparelse for to sekvenser, dvs. implementation af et antal rekursionsligninger som dynamisk programmering, er mere eller mindre kompliceret, afhængig af hvor mange detaljer rekursionerne indfanger. Et af problemerne i dette tilfælde er, at ændrer man i sine rekursionsligninger, skal man også ændre tilsvarende i algoritmen. Vil man udvide sit alignment til at gælde for tre sekvenser, er man nødt til at ændre sine rekursionsligninger til noget passende, samtidig med at man skal have sin algoritme til at håndtere en ekstra dimension. 25

34 26 KAPITEL 4. PUSH-ALGORITMEN A C G A T C A C G A T C A G C A Figur 4.1.: Dynamisk programmerings matrix for to sekvenser, med (0,0) i øverste venstre hjørne. De sorte punkter svarer til celler, som defineret i def Vi har lavet en implementation, som nemt kan udvides til tre sekvenser, og som har indbygget pladsbesparelsen. Det har vi gjort ved at adskille den SMM, vi bruger, fra implementationen af algoritmen, og ved at anvende datastrukturer, som både virker for to og tre sekvenser Push-algoritmen for to sekvenser Dette afsnit beskriver, hvordan vi har valgt at implementere alignment algoritmen, inkl. Hirschbergs Pladsbesparelse. Beskrivelsen tager udgangspunkt i alignment af to sekvenser Push I alignment algoritmer, som implementeres ved hjælp af dynamisk programmering, er det centrale at beskrive, hvorledes en række matricer udfyldes, som givet ved rekursionsligningerne. Man udfylder en indgang, når de indgange, den afhænger af, jvf. rekursionsligningerne, er beregnet. Man kan sige, at en indgang i matricerne spørger sine naboer, om de værdier den har behov for. Vi har valgt en anden strategi, idet vi skubber de beregnede værdier frem. Forstået på den måde, at en celle skubber sine værdier frem til sine naboer, i stedet for at spørge naboerne om deres værdier. Forward dynamisk programmering er beskrevet i [SM97, s ] og [Gus97, s ], bruger samme princip, men med et andet formål end det vi fokuserer på. I vores tilfælde er fordelen ved at skubbe værdierne frem, at vi opnår en lineær pladsreduktion, som er uafhængig af SMMen, og at den implementationsmæssigt er gratis (se afsnit 4.2.4).

35 4.2. PUSH-ALGORITMEN FOR TO SEKVENSER 27 Definition (Celle) En celle indeholder et indeks fra hver sekvens. Desuden er der en liste med sandsynligheder. En for hver mulig umiddelbare forgænger på vejen til cellen. Havde vi haft en dynamisk programmeringsmatrix, ville det svare til, at vi starter i (0, 0) og slutter i (L 1, L 2 ), men det har vi ikke længere behov for, idet vi blot holder styr på hvilke celler, der er ready, og hvilke der er pending. Definition (Pending) En celle er pending, hvis den har modtaget værdier fra mindst én nabo, men ikke fra alle. Definition (Ready) En celle er ready, hvis den har modtaget værdier fra alle sine naboer. Dette kan gøres ved at opretholde en mængde af celler, der er ready (deres rækkefølge er ligegyldig) og en datastruktur, som understøtter indicerede opslag til de celler, der er pending. Grunden til, at vi har brug for at slå pending celler op, er at man sender til de naboer, der svarer til det indeks, der er i ready cellerne plus det antal karakterer, der udsendes (hvad der svarer til advancevektoren, se afsnit 3.2). Dvs. at hvis det er en celle, der svarer til index (i, j) i henholdsvis sekvens et og to, i gang med at sende, og det er til en tilstand, som udsender en karakter fra hver sekvens (advancevektor (1,1)), så skal der skubbes værdier til en pending celle, med indeks (i + 1, j + 1) Udførelse Skabelonen for Push-algoritmen er meget simpel. Når algoritmen udføres, opretholder man to datastrukturer, en stak til celler, der er ready, og en liste til celler, der er pending. ready-stakken er fra starten initieret med den første celle, svarende til indeks 0 i både S 1 og S 2, medens pending-listen er tom. Herefter følger algoritmen nedenstående skabelon: while ready.hasmore(): next = ready.pop() readied = notify(next, pending, S1, S2) ready.update(readied) Så længe der er flere celler på ready-stakken, fjernes den øverste og gemmes i next. notify skubber værdierne fra next videre til de naboer, der kan nåes, og hvis indices ligger inden for de sekvenser, der sendes med som parameter. Hvis naboerne ikke er oprettet i pending, tilføjes de. Returværdien fra notify er en liste af celler, der er blevet ready. ready-stakken opdateres med de nye ready-celler. Når en værdi sendes fra en celle r, der er ready, til en celle p, der er pending, opdateres p, således at den husker på sandsynligheden for den vej, der går gennem r. r sender den værdi videre, som er maksimal i forhold til alle de veje, der kom til r ganget med

36 28 KAPITEL 4. PUSH-ALGORITMEN transitionssandsynligheden til p. Hver gang vi sender fra en ready celle r med index (i r, j r ), sender vi til en pending celle p med index (i p, j p ), således at i r + j r < i p + j p. Dette kan kun gøres indtil i r = L 1 og j r = L 2, hvor algoritmen stopper og vi kan finde sandsynligheden for den mest sandsynlige vej givet de to input sekvenser og modellen, ved at tage maksimum over sandsynlighederne for de forskellige veje, der er gemt i den sidste ready celle. Pladsforbruget af algoritmen er proportionalt med det antal celler, der findes i pendinglisten, som oplagt er en matrix med størrelsen L1 L2. Pladsforbruget skal desuden ganges med antallet af tilstande, idet cellernes størrelse er proportionale med dette. I vores tilfælde er der tre tilstande, og pladsforbruget er derfor O(L 1 L 2 ). På samme måde er tidsforbruget propoertionalt med det antal celler, der skal sendes til, ganget med antal gange, der skal sendes til den samme celle, som igen er O(L 1 L 2 ) Backtracking For at finde alignmentet af de to sekvenser, er vi nødt til at backtracke vejen, som det mest sandsynlige alignment har fulgt. Dette gøres nemt ved at starte med den sidste ready celle og så finde den nabo, der ligger umiddelbart før på alignmentets vej. Dette opslag skal foregå i pending-listen, idet stakken med ready celler ikke undersøtter indicerede opslag. Dette er dog ikke noget problem, hvis ready cellerne er de samme objekter som pending cellerne. Herefter findes den næste celle på stien på samme måde, og dette gøres iterativt, indtil vi når til den celle, der svarer til index (0, 0). Resultatet af backtrackingen er en vej igennem matricen, hvorfra man nu kan lave alignmentet, ved at indsætte ( # #) når man går fra (i, j) til (i + 1, j + 1), ( # ) når man går fra (i, j) til (i + 1, j) eller ( #) når man går fra (i, j) til (i, j + 1) Pladsbesparelse og fronter 1 Beskrivelsen af algoritmen har hidtil taget udgangspunkt i, at alle cellerne i pending listen gemmes undervejs. Det betyder et tidsforbrug på O(n 2 ) og et tilsvarende pladsforbrug, for n L 1 L 2. Tidsforbruget kan vi ikke umiddelbart gøre noget ved, men pladsforbruget kan reduceres med én dimension til O(n). Ideen er, at vi kun gemmer de pending celler, som er blevet sendt til, og så snart de bliver ready, fjernes de fra pending-listen. Grunden til at det er muligt er, at en celle kun afhænger af sine nærmeste foregående naboer, som vist på figur 4.2, hvor cellen med nummer 4 kun afhænger af værdier fra cellerne med nummer 1,2 og 3, som defineret i afsnit 3.3. Det giver følgende skabelon for algoritmen:

37 4.2. PUSH-ALGORITMEN FOR TO SEKVENSER 29 A C G A T C A C G A T C A G C A Figur 4.2.: Kun én række benyttes. Celle 4 har kun brug for oplysninger fra celle 1,2 og 3.

38 30 KAPITEL 4. PUSH-ALGORITMEN A C G A T C A C G A T C A G C A Figur 4.3.: Diagonaler while ready.hasmore(): next = ready.pop() readied = notify(next, pending, S1[a..b], S2[c..d]) ready.update(readied) pending.update(readied) Hvor den sidste linie er tilføjet. Den sørger for, at elementerne i pending-listen fjernes når de bliver ready. Den datastruktur, der skal holde styr på pending celler, dvs. det vi hidtil har kaldt pending-listen, tager udgangspunkt i diagonalerne i en matrix. Definition (2D-diagonal) En diagonal i to dimensioner går fra (i 1, j 1 ) til (i 2, j 2 ), således at i 1 = 0 j 1 = 0 og i 2 = L 1 j 2 = L 2 og i 2 j 2 = i 1 j 1. Med denne definition af en diagonal (se også 4.3), kan vi nu formulere den vigtigste brik i opnåelsen af vores pladsbesparelse. Sætning (Frontsætningen) For et alignment af to sekvenser gælder, at der for hver mulig diagonal kun er én ready celle og én pending celle på et givet tidspunkt. Mængden af alle pending og ready celler kaldes fronten. Bevis 1 (Sætning 4.2.1) Beviset er et modstridsbevis. Antag først, at en diagonal d har to ready celler r 1, r 2 med indices, således at i r1 < i r2 og j r1 < j r2. Da r 2 er ready, må dens naboer til venstre for og over også være ready. Dermed er de tre celler, som r 1 kan sende til, allesammen ready, og r 1 kan ikke være på ready-stakken.

39 4.2. PUSH-ALGORITMEN FOR TO SEKVENSER 31 Figur 4.4.: Projektion af diagonaler i det todimensionale tilfælde, til en 1-dimensionel liste. Antag dernæst, at d har to pending celler p 1, p 2 med indices således at i p1 < i p2 og j p1 < j p2. Da p 1 er pending, er dens naboer under og til højre for også pending, hvilket betyder, at ingen ready indgang har kunnet sende til p 2. Senere under genidentifikationen kommer der lidt yderligere komplikationer, idet det bliver muligt at sende mere end én celle frem. Dette bliver uddybet i afsnit Frontsætningen giver os nu et pladsforbrug på O(n d ), hvor n d er antallet af diagonaler. Det højeste antal diagonaler, der kan være i en matrix med størrelsen L 1 L 2 er L 1 + L 2 1, idet der kan laves en diagonal, der starter i hver række, og en diagonal, der starter i hver søjle, minus én, da søjle-0-diagonalen og række-0-diagonalen er ens. Således at pladsforbruget nu er nede på O(L 1 + L 2 ), hvilket vil sige lineært. Sætning giver en effektiv måde at repræsentere pending-listen med opslag i konstant tid. Sætning (2D-diagonalprojicering) For en matrix kan diagonalerne bijektivt projiceres til et array. Bevis 2 (Sætning 4.2.2) Figur 4.4 viser afbildningen. For cellerne er en mulig afbildning til diagonalnummeret givet ved: f(i, j) = L 1 (i + 1) + j Nu er problemet blot, at vi ikke længere gemmer alle værdierne fra gennemløbet af pending celler, hvilket betyder at vi ikke længere umiddelbart kan backtracke og finde alignmentet. Derfor er vi nødt til at bruge en god idé, kaldet Hirschbergs Pladsbesparelse, som gennemgåes i næste afsnit Hirschbergs Pladsbesparelse I dette afsnit beskrives idéen bag Hirschbergs Pladsbesparelse for traditionel dynamisk programmering. Senere beskriver vi, hvorledes den anvendes i vores push-implementation. Resultatet bliver, at vi kan finde et alignment af to sekvenser ved at bruge lineær plads

40 32 KAPITEL 4. PUSH-ALGORITMEN A C G A T C A C G A T C A G C A Figur 4.5.: En mulig vej gennem en dynamisk programmeringsmatrix. En pil lodret ned betyder, at der er slettet en nukleotid i sekvens to i forhold til sekvens et. En pil skråt ned betyder, at en nukleotid fra sekvens et er blevet substitueret med en nukleotid fra sekvens to. Endelig betyder en vandret pil, at der er blevet indsat en nuklotid i sekvens to i forhold til sekvens et. For dette alignment ( ACGAT CA CGAT CAGCA), som ikke nødevendigvis er det optimale, krydses midten i (4,3) svarende til 4 pile, der går nedad, og 3, der går henad. på bekostning af en fordobling af tidsforbruget. Når man laver alignment vha. dynamisk programmering, er det også muligt at lave en lineær pladsreduktion. Det kræver blot observationen fra figur 4.2, så man kan nøjes med at gemme én række. Det giver igen et problem, når man ønsker at backtracke. En mulig løsning herpå er, som tidligere nævnt, at anvende Hirschbergs Pladsbesparelse. Ideen i pladsbesparelsen er, at man først finder midten af alignmentet, defineret ved midten af den første sekvens, og hvad der skal stå på denne position i alignmentet (se figur 4.5). Lad dette midtpunkt være (M i, M j ). Herefter finder man rekursivt midten af de to delproblemer, alignment af henholdsvis S 1 [0..M i ], S 2 [0..M j ] og S 1 [M i..l 1 ], S 2 [M j..l 2 ]. Rekursionen gentages, indtil problemerne er trivielle at løse. Det betyder så, at man til sidst har defineret hele alignmentet i form af et antal midterpunkter, som man så sætter sammen i den rigtige rækkefølge. Pladsbesparelsen er således en del og kombiner algoritme. På figur 4.6 er skitseret en sådan opsplitning i mindre og mindre delproblemer. Pladsforbruget er herved reduceret fra at været kvadratiskt, til nu at være lineært (for to sekvenser), og generelt kan man opnå en lineær pladsreduktion. Besparelsen er proportional med længden af den sekvens, man halverer hver gang, således at det bedst kan betale sig at bruge den længste sekvens til at dele på midten. Desværre sker det, som tidligere nævnt, på bekostning af en fordobling af tidsforbruget. Forklaringen på dette er følgende: Hvert rekursivt kald giver anledning til to nye rekursive kald, hver med et delproblem, der i gennemsnit er 1/4 af det hidtidige problem, se figur 4.6.

41 4.2. PUSH-ALGORITMEN FOR TO SEKVENSER 33 G C T A C A G C A A C G A T C A G C T A C A G C A A C G A T C A G C T A C A G C A A C G A T C A G C T A C A G C A A C G A T C A Figur 4.6.: Den del af sekvenserne, som endnu ikke er alignede, halveres (mindst) for hvert rekursivt kald.

42 34 KAPITEL 4. PUSH-ALGORITMEN Beviset for denne fordobling, kan gennemføres som et induktionsbevis jvf. [SM97, s. 60], med induktion på n 1 (hvor T (, ) er udførelsestiden for en udførelse af problemet med en størrelse svarende til produktet af parametrene): n 1 = 1: n 1 > 1: T (1, n 2 ) n 2, idet vi efter første gennemløb kender resultatet. T (n 1, n 2 ) n 1 n 2 + T (n 1 /2, j) + T (n 1 /2, n 2 j) Hirschberg og Skjulte Markov Modeller n 1 n 2 + n 1 j + n 1 (n 2 j) = 2n 1 n 2 (4.1) Når man anvender Hirschbergs Pladsbesparelse, skal man køre den alignment algoritme man anvender rekursivt adskillige gange, afhængigt af sekvenslængderne L 1 og L 2. Til slut skal man så have stykket alle resultaterne sammen, så man opnår det ønskede output, alignmentet. For en Skjult Markov Model betyder det, at man skal finde den mest sandsynlige vej i modellen for delsekvenser af en længere sekvens, og disse delveje skal være indeholdt i vejen for hele sekvensen. Måden vi har håndteret dette, er at vi har mulighed for at specificere en påkrævet start- og sluttilstand, når vi kalder Push-aligment algoritmen, dvs. den funktion vi kalder bestprob. Det betyder, at når vi halverer problemet, finder vi ikke blot positionen af midten, men også den hændelse, der skete på det givne sted, på den mest sandsynlige vej. Det kan vi dermed bruge til at bestemme slut- og starthændelser for de to nye delproblemer. Fx giver et kald til bestprob(startstate=start, endstate=end), som returnerer en midtertilstand, middle, anledning til to nye kald: bestprob(startstate=start, endstate=middle) og bestprob(startstate=middle, endstate=end), således at middle både optræder som start- og sluttilstand. Rekursionen slutter, når hele alignmentet er givet ved en række fastlagte middle-tilstande Push-algoritmen for tre sekvenser Vi vil nu gerne overføre principperne fra alignment af to sekvenser til alignment af tre sekvenser. For tre sekvenser bliver matricen, som vi brugte for to sekvenser, til en kube der skal udfyldes for at finde alignmentet. Skabelonen for algoritmen er stadig den samme som i afsnit 4.2.4, dvs. det er den samme som for to sekvenser. Derfor er det kun datastrukturerne, der indeholder ready-cellerne og pending-cellerne, der skal genovervejes.

43 4.3. PUSH-ALGORITMEN FOR TRE SEKVENSER 35 Figur 4.7.: Hvis man forestiller sig, at man lyser på kuben parallelt med diagonalerne, projiceres disse ned i et plan, der er på størrelse med kubens skygge. Som tidligere nævnt, er datastrukturen til at indeholde de celler, som er ready, ikke pålagt særlige krav. Fx er det tilstrækkeligt at gemme dem i en simpel stak, hvorfra man så blot popper den næste celle, der skal sende. I modsætning til dette, er det nødvendigt effektivt at kunne slå op i datastrukturen, som indeholder pending cellerne. Dette er det eneste, der skal ændres i forhold til to sekvens alignmentet og pending-listens repræsentation for tre sekvenser, og er derfor temaet i resten af dette afsnit. Som en første indskydelse, kunne man bruge en hash-tabel, hvori man ville kunne opnå forventede O(1) opslags- og opdateringstider. Denne fremgangsmåde har vi dog valgt ikke at bruge, idet vi indså, at når der kun er én pending celle på hver diagonal, må det være muligt at lave en afbildning til et plan uden huller, ved at bruge et array der er stort nok til at kunne indeholde en celle for hver diagonal, som vist på figur 4.4. Definition (3D-diagonal) En diagonal i tre dimensioner går fra (i 1, j 1, k 1 ) til (i 2, j 2, k 2 ), således at i 1 = 0 j 1 = 0 k 1 = 0 og i 2 = L 1 j 2 = L 2 k 2 = L 3 og i 2 j 2 = i 1 j 1 i 2 k 2 = i 1 k 1 j 2 k 2 = j 1 k 1. I tilfældet med tre sekvenser er det samme idé, men denne gang bliver projektionen ikke helt optimal, idet vi, af hastighedsgrunde, laver et projektionsplan, som er større end det nødvendige, som vist på figur 4.8 og foklaret i næste afsnit. Sætning (3D-diagonalprojicering) For en kube kan diagonalerne bijektivt projiceres ned i et plan. Bevis 3 (Sætning 4.3.1) Figur 4.7 viser ideen og figur 4.8 viser afbildningen Pladsbesparelse og fronter 2 Udvidelsen af projektionsplanet, som blev omtalt i det foregående, drejer sig om at afsætte ekstra plads til de skraverede hjørner på figur 4.8, således at planet får størrelsen (L 1 + L 2 ) (L 1 + L 3 ) i stedet for (L 1 + L 2 ) (L 1 + L 3 ) L 2 1, hvilket stadig

44 36 KAPITEL 4. PUSH-ALGORITMEN Figur 4.8.: Projektion af diagonaler i det tredimensionale tilfælde, til et plan. (0,0,0) Figur 4.9.: Krydsning af midten i en kube. er kvadratisk. Projektionen er således ikke længere surjektiv, men det gør ikke noget, da vi blot skal bruge, at den er injektiv. Den projektionsfunktion vi anvender er p(i, j, k) = (j + (L1 i 1), k + (L1 i 1)) = (l, m). Nu kan vi igen anvende Frontsætningen, sætning At den også gælder for tre sekvenser, kan bevises på samme måde som i det simplere tilfælde. Dermed opnår vi et pladsforbrug for Push-algoritmen anvendt på tre sekvenser, på O(n 2 ), hvor n L 1 L 2 L 3, og pladsreduktionen er opnået Hirschbergs Pladsbesparelse for tre sekvenser Da det nu er en kube, som skal udfyldes, sker halveringen, når en vej krydser midterplanet i kuben (figur 4.9). Midten er dermed et punkt i kuben, og problemet opdeles igen i to delproblemer, det første fra (0, 0, 0) til (M i, M j, M k ) og det andet fra (M i, M j, M k ) til (L 1, L 2, L 3 ), hvor (M i, M j, M k ) er midpunktet. Efter opdelingen er problemet nu reduceret til to mindre kuber, som i gennemsnit har

45 4.3. PUSH-ALGORITMEN FOR TRE SEKVENSER 37 (0,0,0) Figur 4.10.: Opdeling af problemet i to delproblemer, som i gennemsnit har en størrelse der er 1/4 af det oprindelige problem. en størrelse der er 1/4 af det oprindelige problem (figur 4.10), og pladsbesparelsen koster igen en faktor to på tiden i forhold til den oprindelige algoritme Delproblem: To sekvens alignment Under overfladen er der dog kommet en enkelt komplicerende faktor, nemlig det tilfælde, at S 1 er tom, og man mangler stadig at aligne et stykke af S 2 og S 3 til hinanden. Opdelingen af problemet i to mindre delproblemer, som beskrevet tidligere, er kun muligt, når sekvens et ikke er tom. I dette tilfælde giver det ingen mening at bede om midtertilstanden, idet denne kun findes, når sekvens et kan halveres. Måden vi har løst det på er, at man til bestprob kan angive, om man vil gemme alle mellemresultater, man har beregnet undervejs, således at man får returneret en komplet matrix, men kun for to sekvenser, hvilket medfører at matricen udgør et plan i kuben, hvor man kan backtracke hele alignmentet uden yderligere kald til bestprob. Metoden til at håndtere dette har vi kaldt localalignment. Denne udvidelse holder stadig pladsforbruget indenfor O(L 2 L 3 ), dvs. pladsforbruget er stadig kvadratisk, og vi sparer en faktor to på alignment af to sekvenser, idet vi ikke anvender Hirschbergs Pladsbesparelse. Vores algoritme virker i øvrigt også, hvis den ene sekvens er tom fra starten, så man også kan aligne to sekvenser. Det kræver dog en modificering af modellen, hvis man ønsker at aligne to sekvenser fornuftigt. Samtidig er det bedst at lade sekvens to eller sekvens tre være tom, idet man så stadig opnår en lineær pladsreduktion. I afsnit 5.2.5, har vi lavet eksperimenter, der tester og viser netop dette.

46 38 KAPITEL 4. PUSH-ALGORITMEN 4.4. Udvidelse til genidentifikation Det vi har arbejdet med hidtil er det simpleste alignmentproblem. Når vi skal lave en SMM til at identificere gener, er vi fx nødt til at have mulighed for at udsende mere end en nukleotide fra hver sekvens, i nogle tilstande. Det er fx tilfældet, hvis vi vil aligne dele af sekvenserne på codon-niveau i stedet for på nukleotide-niveau, således at vi udsender tre nukleotider af gangen. Det har den konsekvens, at det, vi kalder fronten (pending og ready cellerne), nu får en tykkelse på tre, da det bliver muligt at aktivere en celle tre celler frem. For at håndtere denne situation har vi udvidet vores projektionsfunktion, således at hver diagonal kan indeholde tre celler. Ideen er så, at lave et plan til hvert af de tre celler en diagonal kan indeholde. Måden vi har gjort det på, er at afbilde diagonalen til i mod 3, hvor i, er cellens koordinat på den dimension der skal kollapses. Implementationsmæssigt kan man udvide listen, der skal indeholde projektionsplanerne til at være tre gange længere end tidligere, således at de elementer, der hører til i mod 3 = 0 planet, er i den første trediedel, i mod 3 = 1 planet er i den anden trediedel og i mod 3 = 2 planet er i den sidste trediedel. Projektionsfunktionen fra tre dimensioner til to er stadig den samme, nemlig p(i, j, k) = (j + (L1 i 1), k + (L1 i 1)) = (l, m), men afbildningen til listen bliver nu til: ((L1 + L2) m + l) + (i mod 3) (((L1 + L2) (L3 + L1))). Endelig skal bemærkes, at man kan modificere Frontsætningen, sætning 4.2.1, så den også gælder for tykkere fronter: Sætning (Den generelle frontsætning) For et alignment af tre sekvenser gælder, at der for hver mulig diagonal kun er et antal ready celler og et antal pending celler svarende til to gange fronttykkelsen på et givet tidspunkt. Mængden af alle pending og ready celler kaldes fronten. Bevis 4 (Sætning 4.4.1) Dette kan bevises på samme måde, som i det simplere tilfælde.

47 5. Implementation I dette kapitel gennemgår vi implementationen af Push-algoritmen. Afsnittet er delt op i to hovedafsnit. Det første handler om selve implementationen af algoritmen, medens det sidste viser de eksperimenter, vi har udført for at teste tids- og pladsforbruget af vores implementation. I del I viser vi først opbygningen af det, vi har kaldt et framework, hvor Push-algoritmen indgår, og fortsætter med en beskrivelse af de forskellige dele, der udgør dette framework, i større detalje. Herefter belyses nogle overvejelser omkring effektivitet og udførelse af algoritmen. Endelig forklarer vi de begrænsninger, vores implementation har. I den anden del præsenterer vi resultaterne af de målinger, vi har lavet omkring tids- og pladsforbrug af vores implementation af algoritmen. Dette gøres både for anvendelsen af forskellige programmeringssprog, som funktion af sekvenslængderne og som funktion af model-størrelsen Implementation af algoritmen Opbygning At identificere gener er et problem, som kan løses på mange forskellige måder. De parametre og den model, der ligger til grund for problemet, er for det første vanskelige at bestemme, og for det andet kan det være, at forskellige problemer kræver forskellige modeller. Det er derfor interessant let at kunne ændre i en SMM, for at se om en ændring har en effekt. Vi har derfor lavet et framework, hvor man kan specificere sin egen SMM i et format, vi har valgt, og køre vores Push-algoritme med denne model som grundlag. Det giver en stor fleksibilitet i forhold til algoritmen, idet denne ikke skal ændres, når man ændrer i modellen. Figur 5.1 illustrerer opbygningen af frameworket i skematisk form. Som vist er frameworket delt op i tre dele: input (sekvenser og SMM), algoritmen og outputtet. Implementationen af hvert af disse tre elementer er beskrevet i de følgende underafsnit Input Inputtet til vores algoritme består af to dele. En SMM, der specificerer opførslen af algoritmen, og de sekvenser, der skal alignes. Sekvenserne er blot tekststrenge bestående af 39

48 40 KAPITEL 5. IMPLEMENTATION Input SMM xml Push Alignment Input sekvenser S1, S2, S3 Output alignment Tilstande Figur 5.1.: Frameworket. A, C, G og T. Derimod er beskrivelsen af en SMM mere kompleks, og vi har udviklet et format i XML til dette formål, således at modellen kan gemmes i en fil (appendix A og B viser en komplet specifikation af en SMM). I det følgende gennemgåes de elementer, der optræder i specifikationen af en SMM, i vores XML-format. Gennemgangen tager udgangspunkt i den rækkefølge, elementerne skal stå i. Det er muligt at angive frie variable i starten af filen. Disse kan bruges til at modificere parametrene, således at man på en nem måde kan eksperimentere med modellen. <freevariable startcodonprob = "0.2" exon_length_prob = " " endprob = "0.2" cccprob = "0.9"/> Variablen startcodonprob påvirker fx sandsynligheden for at lave en transition til et startcodon fra alle tilstande. På denne måde kan man nemt påvirke, hvilken genstruktur en SMM genkender. Man skal definere søjler i en SMM vha. <letter>. Til en søjle skal også angives en advancevektor. <letter name="ccc"> <atom seq="0" advance="1"/> <atom seq="1" advance="1"/> <atom seq="2" advance="1"/> </letter> Man skal desuden angive hvilke tilstande, der skal være, herunder hvilke transitionssandsynligheder en tilstand har. Endelig skal man angive, hvilken søjletype (angives som name) en tilstand har, som på denne måde bestemmer en tilstands advancevektor. Nedenfor ses hvordan man definerer en tilstand i XML formatet:

49 5.1. IMPLEMENTATION AF ALGORITMEN 41 <state name="ccc"> <transitions> <transition to="startcodon" p="startcodonprob*(1-endprob)"/> <transition to="gcc" p="0.15*(1-startcodonprob)*(1-endprob)"/> <transition to="end" p="endprob*(1-startcodonprob)"/> <transition to="gcg" p="0.08*(1-startcodonprob)*(1-endprob)"/> <transition to="cgc" p="0.15*(1-startcodonprob)*(1-endprob)"/> <transition to="cgg" p="0.08*(1-startcodonprob)*(1-endprob)"/> <transition to="ggc" p="0.08*(1-startcodonprob)*(1-endprob)"/> <transition to="ccg" p="0.15*(1-startcodonprob)*(1-endprob)"/> <transition to="ccc" p="0.31*(1-startcodonprob)*(1-endprob)"/> </transitions> <emissions name="ccc"> <pythonfunction path="emissionprob"/> </emissions> </state> Ovenfor kan man desuden se brugen af de frie variable, som påvirker sandsynligheden for at gå fra tilstanden ccc til fx startcodon. Man kan også se, at emissionssandsynlighederne bliver sat vha. af en python metode, der hedder emissionprob, som kan ses i bilag B. En anden mulighed er at skrive emissionssandsynlighederne for en tilstand op i XML-filen: <emissions name="codon"> <emission p="1.0">atg,atg,atg</emission> </emissions> Dette XML format giver muligheden for let at kunne ændre i SMMen Implementation af Push-algoritmen I dette afsnit gennemgår vi de vigtigste funktioner i algoritmen. Vi vil starte med at forklare bestprob, metoden som returnerer midten og sandsynligheden for den mest sandsynlige vej. Herefter beskrives notify-metoden, som opdaterer en celles naboer, og som anvendes af bestprob. I notify optræder getmaxprob, som derfor også beskrives. Endelig gennemgåes backtrack-metoden, som genererer det samlede alignment. I det følgende betegner C(i, j, k) en celle, hvor i, j, k er indices i henholdsvis S 1 [a..b], S 2 [c..d] og S 3 [e..f], således at a, b, c, d, e og f afgrænser de tre delsekvenser, og i, j, k alle starter fra 0. Cellen C(i, j, k) skal desuden indeholde en sandsynlighed for hver tilstand, som svarer til sandsynligheden for den vej med størst sandsynlighed af alle veje til cellen, som gik igennem den tilhørende tilstand i sidste skridt. Desuden er de datastrukturer der, indeholder ready og pending elementer, henholdsvis en stak og et array. Metode: bestprob Input: Intervaller i input sekvenserne (a, b), (c, d), (e, f), starttilstand og stoptilstand. Output: Koordinater (i,j,k) og tilstand for det sted hvor den mest sandsynlige vej krydser midten og sandsynligheden for denne.

50 42 KAPITEL 5. IMPLEMENTATION Beskrivelse: Ready-stakken bliver initialiseret med en celle C(0, 0, 0), som svarer til starttilstanden. While-løkken bliver ved at køre, indtil der ikke er flere celler i ready-stakken. I hver iteration tager man den øverste celle fra ready-stakken, og kalder denne celles notify metode. notify bliver beskrevet senere, men i grove træk sender man de maksimale sandsynligheder for hver tilstand videre og opretter evt. de nye celler, som informationen sendes til. notify returnerer en liste (notifylist) af celler, der er blevet sendt til. Hvis cellerne fra notifylist er blevet ready, bliver de indsat i ready-stakken og slettet fre pending-listen. De celler, der er pending, er i pending-listen, indtil de bliver ready, mere herom senere. Den tilhørende C kode kan ses i bilag C.3. Kode: while ready.hasmore(): next = ready.pop() readied = notify(next, pending, (a,b) i S1, (c,d) i S2, (e,f) i S3) ready.update(readied) pending.update(readied) Metoden notify er central, idet den sørger for at sende information videre fra en celle til dens naboer. En detalje er, at notifycount bliver talt op på alle de celler, der er i notifylist. På den måde kan vi lave alignment med en generel SMM. Metode: notify Input: En celle (cell), intervaller i input sekvenserne (a, b), (c, d), (e, f). Output: En liste af celler der har modtaget information Beskrivelse: notifylist indeholder de celler, der skal sendes information til. De er hentet fra pending-listen hvis de eksisterede, ellers er de blevet oprettet og tilføjet til pending-listen. Med udgangspunkt i celle C(i, j, k) har man hentet C(i + state.advance.i, j + state.advance.j, k + state.advance.k) for alle tilstande i SM- Men, dette gøres med metoden getnotifylist (koden kan ses i bilag C.4). For alle tilstande skal vi videregive den maksimale sandsynlighed og den tilhørende midte. Hvis vi krydser midten, skal vi give denne midte videre, så vi ved afslutningen af bestprob har muligheden for at returnere den, ellers returnerer vi den midte, der kommer fra getmaxprob. En celles notifycount bliver talt op med én, idet det er notifycount, der bestemmer, hvornår en celle er ready: Når en celle oprettes sættes dens notifycount til 0. Når dens notifycount er lig antallet af tilstande i SMMen, er den ready. Den tilhørende C kode kan ses i bilag C.2.

51 5.1. IMPLEMENTATION AF ALGORITMEN 43 Kode: notifylist = getnotifylist(cell) for state in states: (maxprob, middle) = getmaxprob(state, cell, notifylist, a, c, e) notifycell = notifylist[state.key] if maxprob!= 0: midpoint = (b-a)/2 if (cell.i < midpoint =< cell.i + state.advance): middle.i = a + cell.i + state.advance.i middle.j = c + cell.j + state.advance.j middle.k = e + cell.k + state.advance.k notifycell.prob[state.key] = maxprob notifycell.middle[state.key] = middle notifycell.notifycount = notifycell.notifycount + 1 return notifylist Betingelsen if maxprob!= 0 er ikke nødvendig, men det er en simpel optimering, som kommer af at sandsynligheden er nul, i de tilfælde hvor der ikke findes en vej. Metode: getmaxprob Input: En celle (cell), en tilstand (state) hvortil vejen skal maksimeres. Intervaller i input sekvenserne (a, b), (c, d), (e, f). Output: En sandsynlighed, der er maksimum over alle mulige transitioner til tilstanden t og den tilhørende midtes koordinater (i,j,k). Beskrivelse: Når man maksimerer over de mulige veje til en tilstand, kan man se ud fra advancevektoren (se afsnit 3), hvor meget tilstanden genererer af inputsekvenserne. Disse sekvensstumper bruger man til at slå op i emissionsfordelingen for en tilstand. Metoden indeholder en for-løkke, der løber alle tilstande igennem som har en transition til den tilstand, vi skal finde maksimum for. For hver iteration holder vi styr på hvilken sandsynlighed/tilstand, der er den største, og returnerer dem til sidst. Den tilhørende C kode kan ses i bilag C.1.

52 44 KAPITEL 5. IMPLEMENTATION Kode: maxprob = 0 emissionprob = state.emission((a,b), (c,d), (e,f)) for fromstate in incominglist(state): transprob = fromstate.transitions[state.key].prob value = cell.middle[fromstate.key] * transprob * emissionprob if value >= maxprob: maxprob = value maxstate = fromstate return (maxprob, maxstate) Nedenfor ses pseudo koden for metoden backtrack, som laver del og kombiner på søgerummet. Metode: backtrack Input: Sekvenser S 1, S 2, S 3 Output: En liste af middle, som kan laves til et alignment. Beskrivelse: Metoden bestprob returnerer midten, hvor den mest sandsynlige vej går igennem. For at gøre koden så overskuelig som mulig har vi undladt at tage stop betingelserne med i rekursionen. Kode: m = bestprob((a,b),(c,d),(e,f), backtrack(a, m.i-adv[0], c, m.j-adv[1], e, m.k-adv[2], startstate, m.state) result.append(m) backtrack(m.i, b, m.j, d, m.k, f, m.state, endstate) Output Outputtet fra vores algoritme, er i sin mest basale form en liste af tilstande, nemlig de tilstande der er returneret fra bestprob under den rekursive udførelse af backtrack (midtertilstandene). Vi har dog også lavet en funktion, som omdanner denne liste til et alignment, så det bliver lettere at overskue resultatet.

53 5.1. IMPLEMENTATION AF ALGORITMEN Profiling Den første version af Push-algoritmen udviklede vi i Python. Grunden til dette er, at det er hurtigt at skrive programmer i et scripting-sprog, og det er lettere at finde fejl. Efter den første version var færdig, har vi brugt Pythons indbyggede profile-modul til at finde ud af, hvilke dele af algoritmen, der tog mest tid, og så har vi oversat disse dele til C. Dermed mener vi, at vi har opnået den bedste kombination mellem Pythons nemme og Cs hurtige implementation. Derfor har det været nødvendigt, at integrere Python og C. Til dette formål har vi valgt wrapper-værktøjet SWIG 1. Profiling af Python-versionen af vores implementation viste at for sekvenser af længde 30bp bruges 99.97% af tiden i bestprob og dennes underkald. Disse dele har vi derfor skrevet om i C. Efter omskrivningen viser profiling, at 98.57% af tiden stadig bruges i bestprob (igen for sekvenser af længde 30bp), og gevinsten ved at skrive yderligere dele om i C vil være minimal. Sammenligning af Python og C-versionernes udførelsestid kan ses i figur Implementationsbetragtninger for Viterbi algoritmen Når man ganger mange sandsynligheder sammen, som i Viterbi algoritmen, kan det give problemer med repræsentationen af produktet, der hurtigt bliver meget småt. Som eksempel kan vi antage at emissions- og transitionssandsynligheder ganget sammen typisk er 0.1, og vi vil aligne tre sekvenser med en længde på 1000pb. Dermed får vi en sandsynlighed for det korteste alignment (hvor der ikke er mellemrum i alignmentet) på = Sandsynligheden kan ikke repræsenteres på en computer med double præcision, idet de numerisk mindste tal, der kan repræsenteres på en sådan er Derfor blev sandsynlighederne i vores tilfælde nul, når sekvenserne blev lange nok. Tager man derimod log( ) = 1000 er der ikke længere noget repræsentationsproblem. I stedet for at gange sandsynlighederne sammen kan man oversætte dem til log-odds[d + 98, s. 77], og summere dem jvf. flg. formel: log(xy) = log(x) + log(y). For ikke at tilføje et overhead som resultat af at tage logaritmer mange gange, tager vi logaritmen til sandsynlighederne allerede når XML-filen med SMMen indlæses. Dette trick kan dog ikke anvendes i Forward-algoritmen, da man summerer sandsynlighederne i stedet for at gange dem sammen, men her opstår problemet ikke, da det var relateret til at gange mange tal sammen Spildplads i forbindelse med tresekvens projektion Som omtalt i beskrivelsen af Push-algoritmen, afsnit 4.3.1, spilder vi en smule plads, når i projicerer diagonalerne til et plan. Pladsforbruget blev (L 1 + L 2 ) (L 1 + L 3 ) i stedet for (L 1 + L 2 ) (L 1 + L 3 ) L 2 1, som er det optimale. I dette afsnit giver vi et eksempel 1

54 46 KAPITEL 5. IMPLEMENTATION på, at denne udvidelse ikke har nogen betydning i praksis. Lad os antage, at sekvenserne er lige lange og at n = L 1 = L 2 = L 3 = 100. Til de celler, der er i brug, afsættes der plads til følgende structs: Størrelse / [byte]: typedef struct Middle { short i; 2 short j; 2 short k; 2 State *state; 4 } Middle; typedef struct ElementData { short i; 2 short j; 2 short k; 2 int key; 4 short notifycount; 2 float *SDlist_prob; 4 x Antal tilstande Middle **SDlist_middle; Middle x Antal tilstande } ElementData; Så størrelsen af en celle der er i brug er (i bytes): 12 + (4 + 10) (antal tilstande) I den mindste model vi har lavet, har vi syv tilstande, hvilket medfører et pladsforbrug på 110 bytes pr. celle. Desuden bruges der en pointer på 4 byte til hver indgang i projektionsplanet. Det samlede optimale pladsforbrug bliver så (( ) ( ) ) 114bytes = bytes. Den ekstra plads der afsættes er bytes = 40000bytes. Det giver et spild på (40.000/ ) = 1.17%, som man må afveje om man vil betale. Alternativet er, at lave en bedre projektion, men med en projektionsfunktion, der tager længere tid at beregne, hvilket har en stor betydning, idet projektionsfunktionen kaldes ofte. Desuden forestiller vi os, at en mere pladseffektiv repræsentation af en celle hurtigt giver en større besparelse end 1.17%, så det er nok på det punkt, der skal sættes ind Begrænsninger På trods af vores ønske om at lave et framework, der er så generelt som muligt, er der visse begrænsninger i vores algoritme. De følgende punkter opsummerer disse begrænsninger.

55 5.2. EKSPERIMENTER UDFØRT PÅ ALGORITMEN 47 Højest tre sekvenser Skulle vi have lavet vores framework helt generelt, skulle det naturligvis have været lavet, så man kunne bruge et vilkårligt antal sekvenser som input og få dem alignet. Vi ser ikke nogen hindring for, at det skulle være muligt at lave et framework, der er så generelt, at det tillader arbitrært mange sekvenser som input. Der er dog visse problemer omkring projicering, som skulle håndteres, idet forskelle i antallet af input-sekvenser kræver forskellige projektionsfunktioner. Allerede for tre sekvenser, med udførelsestider O(n 3 ), pladsforbrug O(n 2 ) og en specifik projektionsfunktion, er vi nødt til at begrænse os til sekvenslængder på under 1000bp, på en computer med 1 Gb ram og 2,4GHz Intel P4 processor (se afsnit 5.2.8). Dermed indsnævres antallet af interessante sekvenser der kan alignes til meget få, hvis man ønsker at aligne mere end tre sekvenser. Advancecount I vores projektionsfunktion bruger vi direkte, at vi højest udsender tre tegn af gangen eller sagt på en anden måde: Det maksimale advancecount 2 i vores genidentifikationsmodel er tre, således at vores front højest bliver tre celler tyk. Vil man udvide modellen til fx at kunne håndtere frameshifts 3, kan det blive nødvendigt at ændre projektionsfunktionen, men hvis dette ikke er nødvendigt, er det vigtigt at bruge en så smal front, som muligt, idet pladsforbruget er lineært i fronttykkelsen. Det er dog meget nemt at udvide indlæsningen af SMMen til at gemme det maksimale advancecount, så vi automatisk kan ændre projektionsfunktionen Eksperimenter udført på algoritmen I dette afsnit gennemgår vi de eksperimenter, vi har foretaget, for at sikre os, at vi har opnået det ønskede tids- og pladsforbrug Teoretiske mål Det primære resourcekrav til vores implementation har været at opnå et tids- og pladsforbrug for tre sekvenser på henholdsvis O(n 3 ) og O(n 2 ), hvor n er længden af sekvenserne, givet at de er lige lange. Desuden er det et krav, at både pladsforbruget og tidsforbruget, som funktion af modelstørrelsen er O(s), hvor s er antallet af tilstande i modellen. Som et sekundært mål har vi haft at opnå muligheden for en mere generel lineær pladsbesparelse. Da vores framework kun er så generelt at det kan håndtere to eller tre sekvenser 2 Den maksimale vektor v i fra advancevektor for alle tilstande i SMMen. 3 Hvis man skifter læseramme i genstrukturen kalder man det et frameshift.

56 48 KAPITEL 5. IMPLEMENTATION (foruden én sekvens, som blot giver det trivielle alignment), er det kun et spørgsmål, om vi kan aligne to sekvenser i kvadratisk tid og med lineært pladsforbrug Eksperimenterne Til de fleste eksperimenter har vi lavet scripts, der kører dem og gemmer resultaterne i filer, der kan tegnes i programmet gnuplot. Vi har også anvendt gnuplot til at fitte funktioner til vore målepunkter, og til at udregne disse funktioners koefficienter med tilhørende standardafvigelser. Til at måle pladsforbruget har vi anvendt programmet ps og har aflæst RSS 4 -variablen, umiddelbart før processen var færdig med at køre. Til at køre eksperimenterne har vi brugt følgende udstyr: 1. Glycine: Dell Pentium IV, 2 GHz, 512Mb RAM 2. Proline: Dell Pentium IV, 2.4 GHz, 1Gb RAM Følgende modeller har været anvendt under forsøgene: 1. tc1.xml: Simpelt alignment, syv tilstande 2. genfinder1.xml: Genidentifikation, 18 tilstande 3. genfinder2.xml: Genidentifikation, introns, 27 tilstande Disse modeller giver ikke noget fornuftigt result, når den ene sekvens er tom, og kan således ikke bruges til at finde gener i to sekvenser. Til gengæld er selve det opnåede alignment uden betydning i disse eksperimenter, og modellerne er derfor udmærket brugbare. Sekvenserne, der er brugt i eksperimenterne, er tilfældigt genererede og af samme længde, for at kunne vise tids- og pladskompleksiteter. Undtaget er dog de forsøg, hvor det er krævet at én af sekvenserne er tom. 4 Resident Set Size - den del af processens hukommelse, der findes i RAM. Så længe operativsystemet ikke swapper dele af processen ud af RAM, er RSS lig med størrelsen på hukommelsen der er tildelt processen. Vi var ikke umiddelbart i stand til at bruge SIZE-variablen, idet den fungerer forskelligt på forskellige Linux-distributioner.

57 5.2. EKSPERIMENTER UDFØRT PÅ ALGORITMEN Sammenligning af forskellige implementationer Formål: Vise det opnåede speedup, ved at implementere dele af algoritmen i C. Testmaskine: Glycine Start sekvenslængde: 10 Trinstørrelse: 2 Antal målepunkter: 20 Model: genfinder1.xml Kommentar: Python-versionerne er så langsomme, at det ikke var praktisk at måle på længere sekvenser Figur: 5.2 og 5.3 Med dette eksperiment ønsker vi at vise, at det virkelig har gjort en forskel at vi har skrevet de mest essentielle dele af koden om i C. På figur 5.2 er de forskellige implementationers absolutte udførelsestid plottet. Det opnåede speedup er tydeligst på figur 5.3, hvor hastigheden af de forskellige implmentationer er afbildet relativt til hastigheden af C-versionen. Som det ses af figuren, har det virkelig stor betydning, at vi har implementeret algoritmen i C. Selv den hurtigste Python implementation er 30 gange langsommere end C-versionen for sekvenser af længde 50, og i forhold til den første version af Pythonkoden er C-versionen omkring 65 gange hurtigere på sekvenser af længde 50. Som en lille detalje kan man se, at de to Python-versioner, som anvender Psyco 5 tager lidt tid at starte op. Det er skyldes, at dele af Python koden bliver JIT-oversat til native kode i det første gennemløb, hvorefter man opnår et speedup. 5

58 50 KAPITEL 5. IMPLEMENTATION 140 Hastighed af forskellige implementationer Tid / [sek] Sekvenslaengde / [Antal nukleotider] C Pure Python Python and Psyco Python, Psyco and no Point Figur 5.2.: Hastigheden af fire forskellige implementationer. Psyco er en JIT-oversætter til Python, som er meget nem at anvende. Folkene bag lover et speedup på mellem 2 og 100 gange, alt efter hvilken algoritme Psyco bruges på. No Point betyder, at en eksisterende klasse, Point, i de andre python implementationer er fjernet, således at de værdier, klassen indeholdt, nu bruges direkte.

59 5.2. EKSPERIMENTER UDFØRT PÅ ALGORITMEN Relativ hastighed af forskellige implementationer Hastighed / [Antal gange langsommere end C-versionen] Sekvenslaengde / [Antal nukleotider] Base case - C Pure Python Python and Psyco Python, Psyco and no Point Figur 5.3.: De samme data, som på figur 5.2, men denne gang afbildet i relativt til hastigheden på C-implementationen.

60 52 KAPITEL 5. IMPLEMENTATION Eksperiment Hældning Std. afvigelse Std. afvigelse / [%] Alle tre sekv ± Mangler sekv. et ± Mangler sekv ± to Mangler sekv ± tre Tabel 5.1.: Asymptotiske udførelsestider. Hældningen for hver af de fire kørsler fra figur 5.4, med standard afvigelser Asymptotisk udførelsestid Formål: Vise at de målte udførelsestider svarer til de teoretiske Testmaskine: Glycine Start sekvenslængde: 50 Trinstørrelse: 2 Antal målepunkter: 60 Model: genfinder1.xml Kommentar: Kerneeksperiment Figur: 5.4 Hvor det første eksperiment fungerer lidt som en appetitvækker, så er dette og det næste eksperiment centrale for dette speciale. Kan vi ikke opnå de teoretiske krav, betyder det, at der er fejl i vores implementation. På tabel 5.1 ses hældningen for hver af de fire kørsler fra figur 5.4. Med hældningen menes den hældning en ret linie har på et dobbeltlogaritmisk plot, hvilket netop svarer til eksponenten i tidskompleksiteten. Som det ses er tidskompleksiteten for tre sekvenser O(n 3 ), som vi havde forudsagt. For alignment af to sekvenser er tidskompleksiteten O(n 2 ), som vi også havde som mål. Algoritmen fungerer ikke på samme måde, hvis det er sekvens et der mangler, som hvis sekvens to eller tre er udeladt. Det skyldes at hvis sekvens et er tom, kaldes localalignment på de to øvrige sekvenser og her gemmes mellemresultaterne, så man kan konstruere alignmentet ud fra disse. Teoretisk set burde det så gå dobbelt så hurtigt at lade sekvens et være tom, som hvis de to andre er tomme. Til gengæld er localalignment skrevet i Python, således at udførslen af den går meget langsomt i forhold til de andre tilfælde. Det er vores vurdering, at det ikke er nødvendigt at omskrive localalignment i C, idet den, for tre sekvenser, kun kaldes, når der ikke er tegn i den første sekvens, der skal alignes med de to andre. Det er meget nemt at jonglere rundt på input sekvenserne, så man altid har den længste sekvens som den første, men vi har med vilje undladt dette,

61 5.2. EKSPERIMENTER UDFØRT PÅ ALGORITMEN f0(x)=3.082*x f1(x)=1.923*x f2(x)=2.059*x f3(x)=2.088*x Asymptotisk tidsforbrug for C-versionen Tid / [sek] Sekvenslaengde / [Antal nukleotider] c-2 c-2 missing seq 1 c-2 missing seq 2 c-2 missing seq 3 f0(x) f1(x) f2(x) f3(x) Figur 5.4.: De asymptotiske hastigheder for fire forskellige kørsler af C-implementationen: Alle tre sekvenser alignes, den første sekvens er ikke med, den anden sekvens er ikke med og den tredie sekvens er ikke med. for netop at kunne undersøge nogle flere ting. Desuden bør det noteres, at da standardafvigelsen er så lav (maksimalt 1.439%), er de forskellige fits af en så god kvalitet, at ovenstående konklusioner kan antages at være korrekte.

62 54 KAPITEL 5. IMPLEMENTATION Eksperiment Hældning Std. afvigelse Std. afvigelse / [%] Alle tre sekv ± Mangler sekv. et ± Mangler sekv ± to Mangler sekv ± tre Tabel 5.2.: Asymptotisk pladsforbrug. Hældningen for hver af de fire kørsler fra figur 5.5, med standard afvigelser Asymptotisk pladsforbrug Formål: Vise at det målte pladsforbrug svarer til det teoretiske Testmaskine: Glycine Start sekvenslængde: 50 Trinstørrelse: 10 Antal målepunkter: 40 Model: genfinder1.xml Kommentar: Kerneeksperiment Figur: 5.5 At måle pladsforbruget for en proces er forbundet med en del usikkerhed, så de absolutte værdier af målingerne i dette eksperiment er måske en smule unøjagtige, men set relativt til andre målepunkter, der er fundet på samme vis, er der ikke noget i vejen for at bruge resultaterne. Og det er præcis det vi har brug for, idet vi gerne vil vise, at det asymptotiske pladsforbrug er O(n 2 ) for tre sekvenser, O(n 2 ) for to sekvenser, hvor det er den første sekvens, der er udeladt, og O(n) for de tilfælde hvor det er den anden eller tredie sekvens, der er udeladt. Der er et initielt pladsforbrug for vores algoritme på Kb til indlæsning af SMMen mm., som er målt ved at køre algoritmen på tre tomme sekvenser. Dette pladsforbrug er fratrukket de målte forbrug på figur 5.5, således at vi får afbildet tilvæksten i pladsforbrug som funktion af længden af sekvenserne, hvilket er nødvendigt for at kunne finde det asymptotiske pladsforbrug for de fire forskellige kørsler. Desuden er det kun målepunkterne for sekvenser over længde 200, der er brugt til at fitte med, idet der er en del støj for sekvenser, der er kortere. Havde vi anvendt alle målepunkter, havde vi fået et bedre asymptotisk pladsforbrug, idet hældningen ville blive mindre, og da vi netop vil vise, at pladsforbruget asymptotisk er mindre end nogle teoretiske værdier, gør det ikke noget, at vi viser, at det højeste asymptotiske pladsforbrug er mindre end det teoretiske. Resultatmæssigt ses for det første at pladsforbruget for tre sekvenser tilhører O(n 2 ), så

63 5.2. EKSPERIMENTER UDFØRT PÅ ALGORITMEN 55 1e f0 x>200 (x)=2.046*x f1 x>200 (x)=1.967*x f2 x>200 (x)=1.047*x f3 x>200 (x)=1.063*x Asymptotisk pladsforbrug for C-versionen Plads / [kb] Sekvenslaengde / [Antal nukleotider] c-2 c-2 missing seq 1 c-2 missing seq 2 c-2 missing seq 3 f0(x) f1(x) f2(x) f3(x) Figur 5.5.: Det asymptotiske pladsforbrug for de samme fire kørsler af C- implementationen, som i figur 5.4. På plottet er et initielt pladsforbrug på Kb fratrukket de målte værdier, for at kunne vise det asymptotiske pladsforbrug. Funktionerne øverst til venstre er resultatet af at fitte til data for sekvenser over længde 200, på den måde undgåes det initielle støj. Knækket i 3-sekvens dataene har vi ikke umiddelbart nogen forklaring på, men det lader til at gentage sig, hvis vi kører eksperimentet igen. vi har opnået en lineær pladsreduktion i dette tilfælde, som ønsket og spået. 2-sekvens kørslerne viser, at lader man den første sekvens være tom, giver det et pladsforbrug O(n 2 ), som netop er hvad vi forventede, idet man gemmer mellemresultaterne og derfor ikke opnår pladsreduktionen. Den lineære pladsreduktion opnåes til gengæld både, når man udelader den anden og den tredie sekvens, således at pladsforbruget i disse tilfælde er i O(n)

64 56 KAPITEL 5. IMPLEMENTATION Modelafhængig udførelsestid Formål: Vise sammenhængen mellem modelstørrelse og udførelsestid. Testmaskine: Proline Start sekvenslængde: 200 Trinstørrelse: 0 Antal målepunkter: 3 10 Model: tc1.xml,genfinder1.xml,genfinder2.xml Kommentar: Udførelsestiden er ikke helt uafhængig af de sekvenser, der bruges som input, så dataene ligger sikkert noget spredte. Figur: 5.6 Teoretisk set skal algoritmens tidskompleksitet afhænge lineært (dvs. tilhøre O(s), hvor s er antallet af tilstande) af antallet af tilstande i den model, der anvendes. Derfor kan vi nøjes med at måle udførelsestiderne for 3 modeller, som vi så fitter til en ret linie. Da udførelsestiden kan variere, alt efter hvilke input sekvenser, der anvendes, har vi valgt at lave 10 målinger til hver model, med fastholdt sekvenslængde, men med tilfældigt genererede sekvenser, som dog alle indeholder et (muligt) gen. Grafen på figur 5.6 tyder på at udførelsestiden tilhører O(s), men det er svært at se, da målepunkterne ligger meget spredte. Fitter man dataene til en ret linie på et dobbeltlogaritmisk plot, får man følgende hældning: ± 0.38(34.81%). Dvs. en lineær afhængighed, men med en ret stor std. afvigelse, som dog ikke er stor nok til, at vi skulle betvivle resultatet Modelafhængigt pladsforbrug Formål: Vise sammenhængen mellem modelstørrelse og pladsforbrug Testmaskine: Proline Start sekvenslængde: 200 Trinstørrelse: 0 Antal målepunkter: 3 10 Model: tc1.xml,genfinder1.xml,genfinder2.xml Kommentar: Svært at måle præcist, idet det så ville kræve mange forskellige modeller. Figur: 5.7 Igen er det teoretiske mål en afhængighed tilhørende O(s), men denne gang på pladsforbruget som funktion af antallet af tilstande. Og ligesom i det foregående eksperiment anvender vi kun tre modeller, men gentager målingerne 10 gange for hver model for at mindske usikkerheden. Som figur 5.7 viser, ligger målepunkterne på eller under den rette linie, hvilket betyder at pladsforbruget er sublineært (funktionen er konkav), så vi kan konkludere at pladsforbruget tilhører O(s). Grunden til denne sublinearitet er sandsynligvis, at en optimering,

65 5.2. EKSPERIMENTER UDFØRT PÅ ALGORITMEN f(x)=1.093*x Udfoerelsestid som funktion af modelstoerrelse, sekvenslaengde: Hastighed / [sek] Modelstoerrelse / [Antal tilstande] tc1 tc2 genefinder1 Bedste rette linie Figur 5.6.: Tidsforbruget for de tre modeller vi har lavet. Dataene ligger temmligt spredte, men der er tydeligvis en voksende tendens. Funktionen øverst til venstre er resultatet af at fitte dataene til en ret linie på et dobbeltlogaritmisk plot.

66 58 KAPITEL 5. IMPLEMENTATION Pladsforbrug som funktion af modelstoerrelse, sekvenslaengde: Plads / [kb] Modelstoerrelse / [Antal tilstande] tc1 tc2 genefinder1 f(x)=2056x Figur 5.7.: Pladsforbruget for de tre forskellige modeller vi har lavet. Det er meget svært at få et nøjagtigt plot, idet de forskellige modeller har forskellige opstartspladsforbrug. På dette plot er opstartspladsen fratrukket de plottede data.

67 5.2. EKSPERIMENTER UDFØRT PÅ ALGORITMEN 59 vi har lavet, hvor vi kun opretter Middle-elementer, når der er brug for dem, træder i kraft her. Denne optimering får større betydning, jo mere kompliceret en model er, idet der så vil være flere veje igennem modellen, som ikke er mulige, og derved bliver der ikke oprettet så mange nye elementer Afrunding af eksperimenterne Det er i dette afsnit blevet bekræftet, at de teoretiske krav til vores implementation er opfyldt. Desværre har vi ikke lavet en implementation af vores algoritmer, som ikke anvender Hirschbergs pladsbesparelse, så det har ikke været muligt, at lave eksperimenter, der demonstrerer fordoblingen af udførelsestiden, hvilket kunne have været interessant. Hvis vi antager, at vi har en computer med 1 Gb RAM foruden de Kb, der skal bruges i opstarten af algoritmen, og det der skal bruges til operativsystemet mm., giver det følgende udregning for pladsforbruget (med genfinder1.xml modellen og tre sekvenser): plads(x) = 10 (2.046 log 10(x) 0.176) Kb log 10 (plads(x)) = log 10 (x) log 10 (10 6 ) = log 10 (x) = log 10 (x) x = 10 (6.176/2.046) x 1044 (5.1) Således at vi kan aligne tre sekvenser af længde ca bp. Så kan man så overveje tidsforbruget, hvilket følgende udregning giver svaret på: tid(x) = 10 (3.082 log10(x) 4.509) sek tid(1044) = 10 (3.082 log10(1044) 4.509) sek tid(1044) sek tid(1044) 1038 min 41 sek tid(1044) 17 timer 19 min (5.2)

68 60 KAPITEL 5. IMPLEMENTATION En udførelsestid på lidt over 17 timer er ikke skræmmende. Og selvom vi uden den lineære pladsbesparelse ville kunne have reduceret tiden til 17/2 = 8.5 timer og reducere pladsen der bruges per celle til ca 1/3 (vi kan spare pladsen til Middle-structen i afsnit 5.1.7), ville det kræve 1/ Gb 1/3 Tb RAM, som i øjeblikket ikke er et alternativ.

69 6. Genidentifikation Det framework, vi har implementeret og gennemgået i de tre foregående kapitler, er beregnet til at identificere genstrukturer i DNA-sekvenser. I dette kapitel gennemgår vi to SMMer, vi har lavet, som kan bruges til at finde gener i tre sekvenser på samme tid. Disse genfindere har vi anvendt på både simulerede og ægte sekvenser. De ægte sekvenser er fire forskellige gærgenomer fra [K + 03]. Resultaterne præsenteres i slutningen af kapitlet Genfinder I Den første genfinder vi har lavet, Genfinder I, kan finde gener uden introns (beskrevet i afsnit 2.1.3). Det betyder, at den genstruktur, som Genfinder I genkender, starter med et startcodon (AT G), hvorefter der kommer et antal codons og til sidst et stopcodon (T AA, T GA eller T AG) (definition 2.2.9). I afsnit 3.2 så vi et eksempel på en par-smm, der kan aligne to sekvenser. I dette afsnit laver vi en udvidelse til en tripel-smm, der kan aligne tre sekvenser, og som vi senere vil bruge til genidentifikation. Lad S 1, S 2 og S 3 være inputsekvenserne. En tripel-smm har syv tilstande for tre sekvenser med alle kombinationer af mellemrum og nukleotider pånær tre gange mellemrum. ccc = # # # ccg = gcg = - # - # # - gcc = cgg = # # # ggc = cgc = Der er en transition fra alle tilstande til alle tilstande. Det giver 49 transitioner med tilhørende transitionssandsynligheder. Tilstanden ccc indeholder fx tre symboler, som hver især kan være en af fire mulige nukleotider, dvs. tilstanden kan generere 4 3 = 64 søjler. Vi tildeler en emissionssandsynlighed for hver søjle efter Jukes-Cantor substitutionsmodellen. En sådan model for to sekvenser kan ses i afsnit 3.2. Substitutionsmodellen har vi lavet således, at det er mest sandsynligt at generere en søjle med tre ens nukleotider, lidt mindre sandsynligt at genere to ens osv. Emissionssandsynligheden for en søjle med AAA er fx større end for en søjle med AAC: - - # # - # 61

70 62 KAPITEL 6. GENIDENTIFIKATION e ccc A A A > e ccc Derved prøver vores model at lave søjler med ens nukleotider, som er vigtigt for et godt alignment i vores model. Denne SMM vil vi bruge til at aligne de dele af sekvenserne, der er ikke er exons (se afsnit 2.1.3). Derfor vil vi kalde den for den ikke-kodende SMM. Den næste del af genfinderen skal aligne de dele af sekvenserne, som er exons (se afsnit 2.2.4), den vil vi derfor kalde for den kodende SMM. Når der står AT G i alle tre sekvenser, skal vi starte med at fortolke sekvenserne som aminosyrer, hvilket vi gør ved at dele dem op i codons (definition 2.2.6). Nedenfor kan ses alle tilstande i den kodende SMM, hvor der skal være transitioner fra alle tilstande til alle tilstande. Der er 4 3 = 64 forskellige kombinationer af nukleotiderne A, C, G og T og dermed 64 forskellige codons. Til gengæld er der kun 20 forskellige aminosyrer (som codons koder for), hvilket betyder, at der kan være flere codons der koder for den samme aminosyre. To sådanne codons kaldes synonyme og ellers nonsynonyme. I modellen skal vi sørge for, at der er en stor sandsynlighed for at aligne synonyme codons og mindre sandsynlighed for at aligne nonsynonyme codons. Den kodende SMM har igen syv tilstande : eccc = ecgc = ### ### ### ### ### eccg = ecgg = eggc = ### ### ### A A C egcc = egcg = Antallet af søjler, de forskellige tilstande kan generere, er noget større for tilstandene i den kodende SMM end i den ikke-kodende SMM. Fx kan tilstanden eccc generere (4 3 3) 3 = mulige søjler, hvor vi ikke har talt de tre stopcodons med. Emissionssandsynlighederne for de syv tilstande er igen lavet som en Jukes-Cantor substitutionsmodel (se tabel 3.2) hvor: e eccc CCT CCC CCA > e eccc ### AAT AAC GAA ### ### ### > e eccc I søjlen med den største emissionssandsynlighed koder alle codons for den samme aminosyre proline (se den genetiske kode i tabel 2.1.4), dvs. de tre codons er synonyme. I AAT AGC GAA

71 6.2. GENFINDER II 63 Start Start codon Ikke kodende SMM Kodende SMM Stop codon Stop Figur 6.1.: Gen identifikation SMM med exon søjlen med den mellemste emissionssandsynlighed er der kun to codons, der koder for den samme aminosyre. I den sidste søjle koder alle tre codons for forskellige aminosyrer, så her sættes emissionssandsynligheden lavt. Transitions- og emissionssandsynlighederne burde sættes ved hjælp af parameterestimering (se afsnit 3.4), som vi dog ikke har anvendt, da vores fokus som tidligere nævnt har ligget på selve frameworket. Den ikke-kodende og den kodende SMM kan kombineres til én SMM, som er vores første genfinder, Genfinder I, i overenstemmelse med definition På figur 6.1 kan man se de to SMMer kombineret til én, og i bilag A kan man se XML versionen af denne SMM. De enkelte tilstande i den kodende og den ikke-kodende SMM er ikke afbildet eksplicit på figuren. Når der går en transition fra en tilstand s til den ikke-kodende SMM, betyder det, at der går en transition fra s til alle tilstande i den ikke-kodende SMM. Det samme gælder for den kodende SMM. Transitionen til startcodon er mulig, hvis der står AT G i alle tre inputsekvenser. Derefter er der en transition til den kodende SMM, hvorefter der er mulighed for en transition til stopcodon, som kræver en af T AA, T GA eller T AG i hver af de tre sekvenser Genfinder II Genfinder I kan ikke aligne genstrukturer, som indeholder introns. Til dette formål udvider vi Genfinder I, så den kan genkende donor site og acceptor site (se definition 2.2) og kalder den Genfinder II. Udvidelsen laves på følgende måde: Den ikke-kodende SMM kopieres og kaldes den ikkekodende-intron SMM (se figur 6.2). Fra den kodende SMM kan man følge en transition til den ikke-kodende-intron SMM, hvis der står GT (donor site) i alle tre input sekvenser.

72 64 KAPITEL 6. GENIDENTIFIKATION Start Kodende SMM Start codon Ikke kodende SMM Acceptor site Donor site Stop codon Ikke kodende intron SMM Stop Figur 6.2.: Gen identifikation SMM med exon og intron Der er en transition tilbage igen, hvis der står AG (acceptor site) i alle tre input sekvenser. Genfinder II har stadig nogle begrænsningner. Fx skal der være et exon merem end der er introns i generne, og alle gener skal have lige mange exons og introns. Det er dog relativt let at tilføje de ekstra tilstande, der skal til, så vores genfinder ikke længere har de førnævnte begrænsninger. Men man skal være klar over, at der skal to-tre gange så mange nye tilstande i modellen i forhold til de 27, der er i forvejen Simulerede sekvenser Vi har brugt simulerede sekvenser til at teste vores genfinder. Vi er jo i den heldige situation, at man kan simulere (se definition 3.1.2) en SMM og derved få genereret nogle alignments, som svarer til modellen. Givet et alignment kan man beregne sandsynligheden for, at modellen har genereret netop dette alignment. Hvis man simulerer mange alignments kan man vælge dem ud med størst sandsynlighed og anvende dem som testsekvenser ved at fjerne mellemrumstegn fra disse simulerede alignments og derefter bruge testsekvenserne som input for at identificere gener i dem. Hvis det simulerede alignment har en tilstrækkelig stor sandsynlighed burde vores genfinder kunne finde genstrukturen, da det er samme model og parametre, der anvendes. Grunden til at vi kun forventer at få ens alignments, når sandsynligheden for alignmentet er tilstrækkeligt stort er, at når man simulerer fx en tripel-smm, risikerer man at få et alignment, som har en lille sandsynlighed for at blive genereret. Da vores genfinder altid finder det mest sandsynlige alignment med de parametre der er givet, er det langt fra sikkert, at de to alignments er ens.

73 6.4. GÆRSEKVENSER 65 Simulerede output: A: - ATG GTC TCA CTC CTA GT A - - T A AG TTA B: - ATG GTA TCG CTT CCG CTC GT A A AG TTA C: G ATG GGT GAC AGA TTA GT A C T T A AG CTA A: GT A - AG CTT CCA AAA TTA AGC TGA G T - A B: GT A G AG TTG AAG AGG TCG TGA - - G A C: GT A G AG TTG AAT CTG CCT --- TTA --- TGA - T G A Input: A: ATGGTCTCACTCCTAGTATAAGTTAGTAAGCTTCCAAAATTAAGCTGAGTA B: ATGGTATCGCTTCCGCTCGTAAAGTTAGTAGAGTTGAAGAGGTCGTGAGA C: GATGGGTGACAGATTAGTACTTAAGCTAGTAGAGTTGAATCTGCCTTTATGATGA Genfinder II Output: A: - ATG GTC TCA CTC CTA GT A - - T A AG TTA B: - ATG GTA TCG CTT CCG CTC GT A A AG TTA C: G ATG GGT GAC AGA TTA GT A C T T A AG CTA A: GT A - AG CTT CCA AAA TTA AGC TGA G T - A B: GT A G AG TTG AAG AGG TCG TGA - - G A C: GT A G AG TTG AAT CTG CCT --- TTA --- TGA - T G A For dette alignment er det tilfældet, at det simulerede faktisk er det samme som det mest sandsynlige. Disse sekvenser er fra SMMen på figur 6.2 med donor site og acceptor site. Genidentifikation på simulerede sekvenser er en smule kunstigt, idet det ikke siger noget om kvaliteten af genfinderen på rigtige sekvenser. Det kan derimod bruges som en simpel test af om genfinderen (og frameworket) virker korrekt: Hvis den ikke kan aligne sekvenser genereret af sin egen model, er der noget galt Gærsekvenser Vi har kørt Genfinder I på sekvenser fra fire forskellige gærgenomer. Genomerne er hentet fra [K + 03]. Grunden til vi anvender Genfinder I i stedet for Genfinder II er, at de korte sekvenser, vi har alignet, ikke indeholder introns. Nedenstående er resultatet af at aligne S. cerevisiae, S. mikatae og S. bayanus.

74 66 KAPITEL 6. GENIDENTIFIKATION 1 MSQESSV..LSESQEQL..ANN.PKIE..DT...SPPSANS.RDN A 1 MSQES..TALSESQEQLDS..NS.KIENG..EAAS...NSPRDN B 1 MSQESSV..LSESQEQLG...NDPKIEEADT..A...SAN.PRDN C!!!!!**!!!!!!!!! *!!! ** ** **!**!!! consensus 35 SKPVLPWD...YKNKAI.EIKSFSGYKVN.FTGWIRRDV.RE.ER A 35 SKPVLPWDHES...KA.VEIKSFSGYKV.EFTGWIRRD.IR.QER B 35 SKPVLPWDFED...KAI.EIKSFSGYKVN.FTGWIRRDVS..QER C!!!!!!!! *!!*!!!!!!!!!!*!!!!!!!!* * *!! consensus 73 Q...RGSE.FT.ASDV..K.GSD.DKAT...RKKEP..ADE A 73 QKQPVSD..SES..NASD..IKE.S.EDK..SMGQ..KEPGK.DE B 73 QKQV...EL.TE.S..HMKE.SDS.KAT...G.KKEPG..DE C!** *! * *!*!*!* *!** *!!!*!! consensus 100 DP. E. VK...QLEKEGEDGLDS.. A 105..REQ...ERTQ...E... B 100 D. TEG. KDFEE..EK..EDG..SES C *! * * *** *** * consensus Alignmentet vises på aminosyreniveau, hvor hvert bogstav er én aminosyre. Inputsekvenserne er taget fra Center for Genome Research 1 websiden, hvor vi har hentet en ORF 2 ved navn YOR189W. For at måle kvaliteten af vores genfindere, skulle vi have sekvenser med gener fra tre forskellige genomer, hvor vi kendte den sande genstruktur, men det er desværre ikke lykkedes os at finde et sådant datasæt. Havde vi fundet et passende datasæt, kunne vi have afprøvet vores genfindere systematisk med disse sekvenser som input. Man kunne desuden have delt datasættet op i et træningssæt og et testsæt for derefter at lave parameterestimering på træningssættet. Når parametrene lå fast kunne vi anvende genfinderen til at forudsige genstrukturen på testsættet og sammenligne resultatet med den sande genstruktur. Derved ville vi få et mål for kvaliteten af genfinderen ORF er forkortelse for Open Reading Frame, som er en DNA-sekvens der potentielt indeholder et gen.

75 7. Konklusion I denne rapport har vi opbygget et framework (jvf. afsnit 5.1.1) til at identificere gener i op til tre sekvenser på én gang. Vi har gennemgået de biologiske begreber, der knytter sig til problemet, og vi har gennemgået teorien om Skjulte Markov Modeller, som vi bruger. Med disse ting som basis har vi formuleret, det vi kalder Push-algoritmen. Pushalgoritmen er en måde at implementere Viterbi-algoritmen, således at det bliver nemt at anvende Hirschbergs Pladsbesparelse, samtidig med at modellen (en Skjult Markov Model) er nem at udskifte. Vi har udført et antal eksperimenter på algoritmen, som alle viser, at de teoretiske udførelsestider og pladsforbrug opfyldes af vores implementation. Det primære mål har været implementation af ovennævnte framework. Som et sekundært mål, har vi haft anvendelsen af implementationen på nogle ægte DNA-sekvenser. Dette er gennemgået i det sidste kapitel. I afsnit 7.1 gennemgår vi de områder af frameworket, som vi mener, er oplagte forbedringer Perspektiv I dette afsnit gennemgår vi de forbedringer og udvidelser, som vi mener er relevante i forbindelse med vores framework. Ændringerne forbedrer det sekundære mål, nemlig selve genidentifikationen og anvendelsen af algoritmen Parameterestimering Parameterestimering er den vigtigste faktor, som vi mangler for at kunne opnå en god genfinder. Med parameterestimering mener vi, at estimere de transitions- og emissionssandsynligheder, som en Skjult Markov Model anvender. Det er dog et omfattende statistisk område, med adskillige estimeringsalgoritmer, fx Viterbi-træning (beskrevet i afsnit 3.4) og EM-algoritmen (Expectation Maximisation) [D + 98][s ], som vi har valgt lå uden for denne rapports omfang Blast-søgning En blast-søgning er en måde at finde delsekvenser, som er meget lig hinanden i sekvenser. Sammenholder man dette med, at vores implementation kun er velegnet til at aligne tre forholdsvis korte sekvenser (mindre end ca bp, pga. tids- og pladsforbruget på henholdsvis O(n 3 ) og O(n 2 ), med n sekvenslængderne), er det oplagt at lave en blast-søgning på de sekvenser, der gives som input, og så kun udføre Push-algoritmen på 67

76 68 KAPITEL 7. KONKLUSION S 1 S 2 Figur 7.1.: Blast søgning de delsekvenser, der er forskellige. Figur 7.1 viser to sekvenser S 1 og S 2 hvor man har fundet to delsekvenser, som er meget ens. Man kan nu nøjes med at udfylde de skraverede dele af matricen, men man skal dog stadig beregne vejen med størst sandsynlighed langs diagonalen Grafisk interface/smm-designer Da målgruppen for frameworks som det vi har udarbejdet, er folk som primært beskæftiger sig med modellering af SMMer og fortolkning af resultaterne, kunne det være givtigt at kombinere vores framework med et grafisk interface til at designe SMMer.

77 A. XML <?xml version="1.0"?> <hmmml seq="3"> <freevariable startcodonprob = "0.2" exon_length_prob = " " endprob = "0.2" cccprob = "0.9"/> <!-- The alphabet tag contains the description of the alphabet for this HMM. --> <!-- The alphabet must be before the state tags --> <alphabet> <!-- Atoms describes what possible character the wildcard can be. --> <atoms wildcard="#" gap="-"> <atom>a</atom> <atom>c</atom> <atom>t</atom> <atom>g</atom> </atoms> <!-- Letters are super patterns for an actual letter in the HMM sense. --> <!-- The advance attribute in the atom tag tells how many characters is read from the sequence --> <!-- The seq attribute tells which sequence its read from. --> <!-- Later when you specify an emission you can say that it is of type letter name. --> <!-- Then you don t have to specify seq, advance and the structure of the letter --> <letters> <letter name="ccc"> <atom seq="0" advance="1"><wildcard/></atom> <atom seq="1" advance="1"><wildcard/></atom> <atom seq="2" advance="1"><wildcard/></atom></letter> <letter name="ccg"> <atom seq="0" advance="1"><wildcard/></atom> <atom seq="1" advance="1"><wildcard/></atom> <atom seq="2" advance="0"><gap/></atom></letter> <letter name="cgc"> <atom seq="0" advance="1"><wildcard/></atom> <atom seq="1" advance="0"><gap/></atom> <atom seq="2" advance="1"><wildcard/></atom></letter> <letter name="gcc"> <atom seq="0" advance="0"><gap/></atom> <atom seq="1" advance="1"><wildcard/></atom> <atom seq="2" advance="1"><wildcard/></atom></letter> <letter name="cgg"> <atom seq="0" advance="1"><wildcard/></atom> <atom seq="1" advance="0"><gap/></atom> <atom seq="2" advance="0"><gap/></atom></letter> <letter name="ggc"> <atom seq="0" advance="0"><gap/></atom> <atom seq="1" advance="0"><gap/></atom> <atom seq="2" advance="1"><wildcard/></atom></letter> 69

78 70 BILAG A. XML <letter name="gcg"> <atom seq="0" advance="0"><wildcard/></atom> <atom seq="1" advance="1"><gap/></atom> <atom seq="2" advance="0"><wildcard/></atom></letter> <letter name="codon"> <atom seq="0" advance="3"><wildcard/><wildcard/><wildcard/></atom> <atom seq="1" advance="3"><wildcard/><wildcard/><wildcard/></atom> <atom seq="2" advance="3"><wildcard/><wildcard/><wildcard/></atom></letter> <letter name="eccc"> <atom seq="0" advance="3"><wildcard/><wildcard/><wildcard/></atom> <atom seq="1" advance="3"><wildcard/><wildcard/><wildcard/></atom> <atom seq="2" advance="3"><wildcard/><wildcard/><wildcard/></atom></letter> <letter name="egcc"> <atom seq="0" advance="0"><gap/><gap/><gap/></atom> <atom seq="1" advance="3"><wildcard/><wildcard/><wildcard/></atom> <atom seq="2" advance="3"><wildcard/><wildcard/><wildcard/></atom></letter> <letter name="ecgc"> <atom seq="0" advance="3"><wildcard/><wildcard/><wildcard/></atom> <atom seq="1" advance="0"><gap/><gap/><gap/></atom> <atom seq="2" advance="3"><wildcard/><wildcard/><wildcard/></atom></letter> <letter name="eccg"> <atom seq="0" advance="3"><wildcard/><wildcard/><wildcard/></atom> <atom seq="1" advance="3"><wildcard/><wildcard/><wildcard/></atom> <atom seq="2" advance="0"><gap/><gap/><gap/></atom></letter> <letter name="egcg"> <atom seq="0" advance="0"><gap/><gap/><gap/></atom> <atom seq="1" advance="3"><wildcard/><wildcard/><wildcard/></atom> <atom seq="2" advance="0"><gap/><gap/><gap/></atom></letter> <letter name="eggc"> <atom seq="0" advance="0"><gap/><gap/><gap/></atom> <atom seq="1" advance="0"><gap/><gap/><gap/></atom> <atom seq="2" advance="3"><wildcard/><wildcard/><wildcard/></atom></letter> <letter name="ecgg"> <atom seq="0" advance="3"><wildcard/><wildcard/><wildcard/></atom> <atom seq="1" advance="0"><gap/><gap/><gap/></atom> <atom seq="2" advance="0"><gap/><gap/><gap/></atom></letter> </letters> </alphabet> <states> <!-- There must be a state called start --> <state name="start"> <transitions> <transition to="startcodon" p="startcodonprob"/> <transition to="ccc" p=" *(1-startcodonprob)"/> <transition to="ccg" p=" *(1-startcodonprob)"/> <transition to="cgc" p=" *(1-startcodonprob)"/> <transition to="gcc" p=" *(1-startcodonprob)"/> <transition to="cgg" p=" *(1-startcodonprob)"/> <transition to="ggc" p=" *(1-startcodonprob)"/> <transition to="gcg" p=" *(1-startcodonprob)"/> </transitions> </state> <!-- There must be a state called end --> <state name="end"></state>

79 71 <state name="ccc"> <transitions> <transition to="startcodon" p="startcodonprob*(1-endprob)"/> <transition to="gcc" p="0.15*(1-startcodonprob)*(1-endprob)"/> <transition to="end" p="endprob*(1-startcodonprob)"/> <transition to="gcg" p="0.08*(1-startcodonprob)*(1-endprob)"/> <transition to="cgc" p="0.15*(1-startcodonprob)*(1-endprob)"/> <transition to="cgg" p="0.08*(1-startcodonprob)*(1-endprob)"/> <transition to="ggc" p="0.08*(1-startcodonprob)*(1-endprob)"/> <transition to="ccg" p="0.15*(1-startcodonprob)*(1-endprob)"/> <transition to="ccc" p="0.31*(1-startcodonprob)*(1-endprob)"/> </transitions> <emissions name="ccc"> <pythonfunction path="emissionprob"/> </emissions> </state> <state name="gcc"> <transitions> <transition to="startcodon" p="startcodonprob*(1-endprob)"/> <transition to="gcc" p="0.31*(1-startcodonprob)*(1-endprob)"/> <transition to="end" p="endprob*(1-startcodonprob)"/> <transition to="gcg" p="0.15*(1-startcodonprob)*(1-endprob)"/> <transition to="cgc" p="0.08*(1-startcodonprob)*(1-endprob)"/> <transition to="cgg" p="0.08*(1-startcodonprob)*(1-endprob)"/> <transition to="ggc" p="0.15*(1-startcodonprob)*(1-endprob)"/> <transition to="ccg" p="0.08*(1-startcodonprob)*(1-endprob)"/> <transition to="ccc" p="0.15*(1-startcodonprob)*(1-endprob)"/> </transitions> <emissions name="gcc"> <pythonfunction path="emissionprob"/> </emissions> </state> <state name="gcg"> <transitions> <transition to="startcodon" p="startcodonprob*(1-endprob)"/> <transition to="gcc" p="0.225*(1-startcodonprob)*(1-endprob)"/> <transition to="end" p="endprob*(1-startcodonprob)"/> <transition to="gcg" p="0.31*(1-startcodonprob)*(1-endprob)"/> <transition to="cgc" p="0.06*(1-startcodonprob)*(1-endprob)"/> <transition to="cgg" p="0.06*(1-startcodonprob)*(1-endprob)"/> <transition to="ggc" p="0.06*(1-startcodonprob)*(1-endprob)"/> <transition to="ccg" p="0.225*(1-startcodonprob)*(1-endprob)"/> <transition to="ccc" p="0.06*(1-startcodonprob)*(1-endprob)"/> </transitions> <emissions name="gcg"> <pythonfunction path="emissionprob"/> </emissions> </state> <state name="cgc"> <transitions> <transition to="startcodon" p="startcodonprob*(1-endprob)"/> <transition to="gcc" p="0.09*(1-startcodonprob)*(1-endprob)"/> <transition to="end" p="endprob*(1-startcodonprob)"/> <transition to="gcg" p="0.06*(1-startcodonprob)*(1-endprob)"/>

80 72 BILAG A. XML <transition to="cgc" p="0.31*(1-startcodonprob)*(1-endprob)"/> <transition to="cgg" p="0.15*(1-startcodonprob)*(1-endprob)"/> <transition to="ggc" p="0.15*(1-startcodonprob)*(1-endprob)"/> <transition to="ccg" p="0.09*(1-startcodonprob)*(1-endprob)"/> <transition to="ccc" p="0.15*(1-startcodonprob)*(1-endprob)"/> </transitions> <emissions name="cgc"> <pythonfunction path="emissionprob"/> </emissions> </state> <state name="cgg"> <transitions> <transition to="startcodon" p="startcodonprob*(1-endprob)"/> <transition to="gcc" p="0.03*(1-startcodonprob)*(1-endprob)"/> <transition to="end" p="endprob*(1-startcodonprob)"/> <transition to="gcg" p="0.07*(1-startcodonprob)*(1-endprob)"/> <transition to="cgc" p="0.225*(1-startcodonprob)*(1-endprob)"/> <transition to="cgg" p="0.31*(1-startcodonprob)*(1-endprob)"/> <transition to="ggc" p="0.07*(1-startcodonprob)*(1-endprob)"/> <transition to="ccg" p="0.225*(1-startcodonprob)*(1-endprob)"/> <transition to="ccc" p="0.07*(1-startcodonprob)*(1-endprob)"/> </transitions> <emissions name="cgg"> <pythonfunction path="emissionprob"/> </emissions> </state> <state name="ggc"> <transitions> <transition to="startcodon" p="startcodonprob*(1-endprob)"/> <transition to="gcc" p="0.225*(1-startcodonprob)*(1-endprob)"/> <transition to="end" p="endprob*(1-startcodonprob)"/> <transition to="gcg" p="0.07*(1-startcodonprob)*(1-endprob)"/> <transition to="cgc" p="0.225*(1-startcodonprob)*(1-endprob)"/> <transition to="cgg" p="0.07*(1-startcodonprob)*(1-endprob)"/> <transition to="ggc" p="0.31*(1-startcodonprob)*(1-endprob)"/> <transition to="ccg" p="0.03*(1-startcodonprob)*(1-endprob)"/> <transition to="ccc" p="0.07*(1-startcodonprob)*(1-endprob)"/> </transitions> <emissions name="ggc"> <pythonfunction path="emissionprob"/> </emissions> </state> <state name="ccg"> <transitions> <transition to="startcodon" p="startcodonprob*(1-endprob)"/> <transition to="gcc" p="0.08*(1-startcodonprob)*(1-endprob)"/> <transition to="end" p="endprob*(1-startcodonprob)"/> <transition to="gcg" p="0.15*(1-startcodonprob)*(1-endprob)"/> <transition to="cgc" p="0.08*(1-startcodonprob)*(1-endprob)"/> <transition to="cgg" p="0.15*(1-startcodonprob)*(1-endprob)"/> <transition to="ggc" p="0.08*(1-startcodonprob)*(1-endprob)"/> <transition to="ccg" p="0.31*(1-startcodonprob)*(1-endprob)"/> <transition to="ccc" p="0.15*(1-startcodonprob)*(1-endprob)"/> </transitions>

81 <emissions name="ccg"> <pythonfunction path="emissionprob"/> </emissions> </state> <state name="startcodon"> <transitions> <transition to="egcc" p=" "/> <transition to="egcg" p=" "/> <transition to="ecgc" p=" "/> <transition to="ecgg" p=" "/> <transition to="eggc" p=" "/> <transition to="eccg" p=" "/> <transition to="eccc" p=" "/> </transitions> <emissions name="codon"> <emission p="1.0">atg,atg,atg</emission> </emissions> </state> <state name="stopcodon"> <transitions> <transition to="gcc" p=" "/> <transition to="gcg" p=" "/> <transition to="cgc" p=" "/> <transition to="cgg" p=" "/> <transition to="ggc" p=" "/> <transition to="ccg" p=" "/> <transition to="ccc" p=" "/> </transitions> <emissions name="codon"> <pythonfunction path="stop_codon"/> </emissions> </state> <state name="eccc"> <transitions> <transition to="egcc" p="(4*(1-cccprob)/18)*(1 - exon_length_prob)"/> <transition to="egcg" p="((1-cccprob)/18)*(1 - exon_length_prob)"/> <transition to="ecgc" p="(4*(1-cccprob)/18)*(1 - exon_length_prob)"/> <transition to="ecgg" p="((1-cccprob)/18)*(1 - exon_length_prob)"/> <transition to="eggc" p="((1-cccprob)/18)*(1 - exon_length_prob)"/> <transition to="eccg" p="(4*(1-cccprob)/18)*(1 - exon_length_prob)"/> <transition to="eccc" p="cccprob*(1 - exon_length_prob)"/> <transition to="stopcodon" p="exon_length_prob"/> </transitions> <emissions name="codon"> <pythonfunction path="eccc_codon"/> </emissions> </state> <state name="egcc"> <transitions> <transition to="egcc" p="0.31*(1 - exon_length_prob)"/> <transition to="egcg" p="0.15*(1 - exon_length_prob)"/> <transition to="ecgc" p="0.08*(1 - exon_length_prob)"/> <transition to="ecgg" p="0.08*(1 - exon_length_prob)"/> <transition to="eggc" p="0.15*(1 - exon_length_prob)"/> 73

82 74 BILAG A. XML <transition to="eccg" p="0.08*(1 - exon_length_prob)"/> <transition to="eccc" p="0.15*(1 - exon_length_prob)"/> <transition to="stopcodon" p="exon_length_prob"/> </transitions> <emissions name="egcc"> <pythonfunction path="egcc_codon"/> </emissions> </state> <state name="egcg"> <transitions> <transition to="egcc" p="0.225*(1 - exon_length_prob)"/> <transition to="stopcodon" p="exon_length_prob"/> <transition to="egcg" p="0.31*(1 - exon_length_prob)"/> <transition to="ecgc" p="0.06*(1 - exon_length_prob)"/> <transition to="ecgg" p="0.06*(1 - exon_length_prob)"/> <transition to="eggc" p="0.06*(1 - exon_length_prob)"/> <transition to="eccg" p="0.225*(1 - exon_length_prob)"/> <transition to="eccc" p="0.06*(1 - exon_length_prob)"/> </transitions> <emissions name="egcg"> <pythonfunction path="egcg_codon"/> </emissions> </state> <state name="ecgc"> <transitions> <transition to="egcc" p="0.09*(1 - exon_length_prob)"/> <transition to="stopcodon" p="exon_length_prob"/> <transition to="egcg" p="0.06*(1 - exon_length_prob)"/> <transition to="ecgc" p="0.31*(1 - exon_length_prob)"/> <transition to="ecgg" p="0.15*(1 - exon_length_prob)"/> <transition to="eggc" p="0.15*(1 - exon_length_prob)"/> <transition to="eccg" p="0.09*(1 - exon_length_prob)"/> <transition to="eccc" p="0.15*(1 - exon_length_prob)"/> </transitions> <emissions name="ecgc"> <pythonfunction path="ecgc_codon"/> </emissions> </state> <state name="ecgg"> <transitions> <transition to="egcc" p="0.03*(1 - exon_length_prob)"/> <transition to="stopcodon" p="exon_length_prob"/> <transition to="egcg" p="0.07*(1 - exon_length_prob)"/> <transition to="ecgc" p="0.225*(1 - exon_length_prob)"/> <transition to="ecgg" p="0.31*(1 - exon_length_prob)"/> <transition to="eggc" p="0.07*(1 - exon_length_prob)"/> <transition to="eccg" p="0.225*(1 - exon_length_prob)"/> <transition to="eccc" p="0.07*(1 - exon_length_prob)"/> </transitions> <emissions name="ecgg"> <pythonfunction path="ecgg_codon"/> </emissions> </state> <state name="eggc">

83 <transitions> <transition to="egcc" p="0.225*(1 - exon_length_prob)"/> <transition to="stopcodon" p="exon_length_prob"/> <transition to="egcg" p="0.07*(1 - exon_length_prob)"/> <transition to="ecgc" p="0.225*(1 - exon_length_prob)"/> <transition to="ecgg" p="0.07*(1 - exon_length_prob)"/> <transition to="eggc" p="0.31*(1 - exon_length_prob)"/> <transition to="eccg" p="0.03*(1 - exon_length_prob)"/> <transition to="eccc" p="0.07*(1 - exon_length_prob)"/> </transitions> <emissions name="eggc"> <pythonfunction path="eggc_codon"/> </emissions> </state> <state name="eccg"> <transitions> <transition to="egcc" p="0.08*(1 - exon_length_prob)"/> <transition to="stopcodon" p="exon_length_prob"/> <transition to="egcg" p="0.15*(1 - exon_length_prob)"/> <transition to="ecgc" p="0.08*(1 - exon_length_prob)"/> <transition to="ecgg" p="0.15*(1 - exon_length_prob)"/> <transition to="eggc" p="0.08*(1 - exon_length_prob)"/> <transition to="eccg" p="0.31*(1 - exon_length_prob)"/> <transition to="eccc" p="0.15*(1 - exon_length_prob)"/> </transitions> <emissions name="eccg"> <pythonfunction path="eccg_codon"/> </emissions> </state> </states> </hmmml> 75

84 B. Emissionssandsynligheder alpha = diag = 1-3*alpha probsub2 = { A : { A : diag, C : alpha, G : alpha, T : alpha}, C : { A : alpha, C : diag, G : alpha, T : alpha}, G : { A : alpha, C : alpha, G : diag, T : alpha}, T : { A : alpha, C : alpha, G : alpha, T : diag}} dd = diag*diag da = diag*alpha ad = alpha*diag aa = alpha*alpha probsub3 = { A : { A : { A : dd, C : da, G : da, T : da}, C : { A : da, C : ad, G : aa, T : aa}, G : { A : da, C : aa, G : ad, T : aa}, T : { A : da, C : aa, G : aa, T : ad}}, C : { A : { A : ad, C : da, G : aa, T : aa}, C : { A : da, C : dd, G : da, T : da}, G : { A : aa, C : da, G : ad, T : aa}, T : { A : aa, C : da, G : aa, T : ad}}, G : { A : { A : ad, C : aa, G : da, T : aa}, C : { A : aa, C : ad, G : da, T : aa}, G : { A : da, C : da, G : dd, T : da}, T : { A : aa, C : aa, G : da, T : ad}}, T : { A : { A : ad, C : aa, G : aa, T : da}, C : { A : aa, C : ad, G : aa, T : da}, 76

85 77 G : { A : aa, C : aa, G : ad, T : da}, T : { A : da, C : da, G : da, T : dd}}} probuniform = { A : 1.0/4, C : 1.0/4, G : 1.0/4, T : 1.0/4} def generate_emission(state,path,hmm): if path == "emissionprob": charlist = [[ - ],hmm.atoms] c1list = charlist[hmm.lookup_advance(state.id,0)] c2list = charlist[hmm.lookup_advance(state.id,1)] c3list = charlist[hmm.lookup_advance(state.id,2)] for c1 in c1list: for c2 in c2list: for c3 in c3list: state.addemission(c1,c2,c3,emission(path,c1,c2,c3)) elif path == "eccc_codon": for (nuc, amino) in toaminoacid.items(): for (nuc1, amino1) in toaminoacid.items(): for (nuc2, amino2) in toaminoacid.items(): state.addemission(nuc, nuc1, nuc2, codonprob(nuc, nuc1, nuc2)) elif path == "egcc_codon": for (nuc1, amino1) in toaminoacid.items(): for (nuc2, amino2) in toaminoacid.items(): state.addemission("---", nuc1, nuc2, codonprob("---", nuc1, nuc2)) elif path == "ecgc_codon": for (nuc, amino) in toaminoacid.items(): for (nuc2, amino2) in toaminoacid.items(): state.addemission(nuc, "---", nuc2, codonprob(nuc, "---", nuc2)) elif path == "eccg_codon": for (nuc, amino) in toaminoacid.items(): for (nuc1, amino1) in toaminoacid.items(): state.addemission(nuc, nuc1, "---", codonprob(nuc, nuc1, "---")) elif path == "ecgg_codon": for (nuc, amino) in toaminoacid.items(): state.addemission(nuc, "---", "---", codonprob(nuc, "---", "---")) elif path == "eggc_codon": for (nuc, amino) in toaminoacid.items(): state.addemission("---", "---", nuc, codonprob("---", "---", nuc)) elif path == "egcg_codon": for (nuc, amino) in toaminoacid.items(): state.addemission("---", nuc, "---", codonprob("---", nuc, "---")) elif path == "stop_codon":

86 78 BILAG B. EMISSIONSSANDSYNLIGHEDER codonlist = [ TAA, TGA, TAG ] for codon1 in codonlist: for codon2 in codonlist: for codon3 in codonlist: state.addemission(codon1, codon2, codon3, 1.0/27) elif path == "ag": state.addemission("ag", "AG", "AG", 1) elif path == "gt": state.addemission("gt", "GT", "GT", 1) def emission(path, x1, x2, x3): if path == "emissionprob": return emissionprob(x1, x2, x3) elif path == "codonprob": return codonprob(x1, x2, x3) def emissionprob(x1,x2,x3): if x1 == - and x2 == - and x3 == - : return 0 elif x1 == - and x2 == - : return probuniform[x3] elif x1 == - and x3 == - : return probuniform[x2] elif x2 == - and x3 == - : return probuniform[x1] elif x1 == - : return probsub2[x2][x3] elif x2 == - : return probsub2[x1][x3] elif x3 == - : return probsub2[x1][x2] else: return probsub3[x1][x2][x3] c = 1/20.0 def codonprob(s1, s2, s3): if s1 == "---" and s2 == "---": return c elif s1 == "---" and s3 == "---": return c elif s2 == "---" and s3 == "---": return c elif s1 == "---": return c*c elif s2 == "---": return c*aminojukes(toaminoacid[s1],toaminoacid[s3]) elif s3 == "---": return c*aminojukes(toaminoacid[s1],toaminoacid[s2]) else: return c*aminojukes(toaminoacid[s1],toaminoacid[s2])

87 79 *AminoJukes(toAminoAcid[s1],toAminoAcid[s3]) t = 0.1 def AminoJukes(c1, c2): if c1 == c2: return 1-t else: return t/19 toaminoacid = { "TTT" : "Phe", "TTC" : "Phe", "TTA" : "Leu", "TTG" : "Leu", "CTT" : "Leu", "CTC" : "Leu", "CTA" : "Leu", "CTG" : "Leu", "ATT" : "Ile", "ATC" : "Ile", "ATA" : "Ile", "ATG" : "Met", "GTT" : "Val", "GTC" : "Val", "GTA" : "Val", "GTG" : "Val", "TCT" : "Ser", "TCC" : "Ser", "TCA" : "Ser", "TCG" : "Ser", "CCT" : "Pro", "CCC" : "Pro", "CCA" : "Pro", "CCG" : "Pro", "ACT" : "Thr", "ACC" : "Thr", "ACA" : "Thr", "ACG" : "Thr", "GCT" : "Ala", "GCC" : "Ala", "GCA" : "Ala", "GCG" : "Ala", "TAT" : "Tyr", "TAC" : "Tyr", "CAT" : "His", "CAC" : "His", "CAA" : "Gln", "CAG" : "Gln", "AAT" : "Asn", "AAC" : "Asn", "AAA" : "Lys",

88 80 BILAG B. EMISSIONSSANDSYNLIGHEDER "AAG" : "Lys", "GAT" : "Asp", "GAC" : "Asp", "GAA" : "Glu", "GAG" : "Glu", "TGT" : "Cys", "TGC" : "Cys", "TGG" : "Trp", "CGT" : "Arg", "CGC" : "Arg", "CGA" : "Arg", "CGG" : "Arg", "AGT" : "Ser", "AGC" : "Ser", "AGA" : "Arg", "AGG" : "Arg", "GGT" : "Gly", "GGC" : "Gly", "GGA" : "Gly", "GGG" : "Gly" }

89 C. Kode C.1. Getmaxprob StateData *swig_getmaxprob(elementdata *e, State *currentstate, int *c1, int *c2, int *c3, int trans2end) { int i; float maxvalue = -INF; State *maxstate = NULL; State *state; Transition *trans; StateData *sd; float currentvalue; float emissionprob; } emissionprob = State_emission_getEmission(currentState,c1,c2,c3); for(i = 0; i < currentstate->incominglist_length; i++) { state = currentstate->incominglist[i]; trans = &state->transitions[currentstate->key]; currentvalue = e->sdlist_prob[state->key] + trans->prob + emissionprob; if (currentvalue < -INF) currentvalue = -INF; if (currentvalue >= maxvalue) { maxvalue = currentvalue; maxstate = state; }; }; if (maxstate == NULL) { printf("no state has a transition to state %s. This is a mistake in the HMM.\n",currentState->id); exit(-1); }; sd = NEW(StateData); sd->prob = maxvalue; sd->middle = e->sdlist_middle[maxstate->key]; return sd; 81

90 82 BILAG C. KODE C.2. Notify void swig_donotify(elementdata *self, ElementData **notifylist, int *s1, int *s2, int *s3, int a, int b, int c, int d, int e, int f) { StateData *sd; int midpoint; int j,k,i; int state0, state1, state2; for(i = 0; i < hmm->statelist_length; i++) { Middle *m; State *state = &hmm->statelist[i]; ElementData *notify = notifylist[state->key]; if (notify!= NULL) { state0 = state->advance[0]; state1 = state->advance[1]; state2 = state->advance[2]; if ((self->i + state0 < b-a) && (self->j + state1 < d-c) && (self->k + state2 < f-e)) { sd = swig_getmaxprob(self,state,&ints1[self->i + a + 1], &ints2[self->j + c + 1], &ints3[self->k + e + 1],1); if (sd->prob!= -INF) { if (sd->middle == NULL) { m = new_middle(-1,-1,-1,null); } else { m = new_middle(sd->middle->i,sd->middle->j, sd->middle->k,sd->middle->state); }; midpoint = (b-a)/2; if ((self->i < midpoint) && ((self->i + state->advance[0]) >= midpoint)) { m->i = a + self->i + state->advance[0]; m->j = c + self->j + state->advance[1]; m->k = e + self->k + state->advance[2]; m->state = state; }; notify->notifycount++; notify->sdlist_prob[state->key] = sd->prob; notify->sdlist_middle[state->key] = m; } else { notify->notifycount++; }; free(sd);

91 C.3. BESTPROB 83 } }; }; }; C.3. Bestprob ElementData **swig_bestprob(int a, int b, int c, int d, int e, int f, State *startstate, State *endstate, int store, Middle *middle) { ElementData **ready; ElementData **stored; ElementData **readied; ElementData *next; ElementData *element; StateData *sd; int i; ready = Ready_init(150); pending = Pending_init(a,b,c,d,e,f,intS1_length, ints2_length, ints3_length); if (store) { stored = Stored_init(2*intS2_length*intS3_length); } else { stored = NULL; }; Ready_push(ready, swig_elementdata_init(0,0,0,0,ints1_length, ints2_length, ints3_length)); next = Ready_pop(ready); if (store) { Stored_push(stored,next); }; readied = swig_send(next, pending, startstate, a, b, c, d, e, f); Ready_update(ready,readied); Pending_update(pending,readied); if (store) { for(i = 0; i < hmm->states_length; i++) { element = readied[i]; if (element!= NULL) { if (swig_isready(element)) { Stored_push(stored,element); } } } }; while (Ready_hasMore()) { next = Ready_pop(ready); readied = swig_send(next, pending, startstate, a, b, c, d, e, f);

92 84 BILAG C. KODE if (Ready_hasMore()) { for(i = 0; i < hmm->states_length; i++) { if (next->sdlist_middle[i]!= NULL) { free(next->sdlist_middle[i]); }; }; free(next->sdlist_middle); free(next->sdlist_prob); free(next); }; Ready_update(ready,readied); if (store) { for(i = 0; i < hmm->states_length; i++) { element = readied[i]; if (element!= NULL) { if (swig_isready(element)) { Stored_push(stored,element); } } } }; Pending_update(pending,readied); free(readied); }; if (strcmp(endstate->id, "end")!= 0) { int j, k, state0, state1, state2; int *c1 = NEW_LIST(int, endstate->gapmax_length); int *c2 = NEW_LIST(int, endstate->gapmax_length); int *c3 = NEW_LIST(int, endstate->gapmax_length); state0 = endstate->advance[0]; state1 = endstate->advance[1]; state2 = endstate->advance[2]; // init c1, c2, c3 j = 0; for(k = 0; k < endstate->gapmax_length; k++) { c1[j] = 0; j++; }; j = 0; for(k = 0; k < endstate->gapmax_length; k++) { c2[j] = 0; j++; }; j = 0; for(k = 0; k < endstate->gapmax_length; k++) {

93 C.3. BESTPROB 85 c3[j] = 0; j++; }; // copy input strings if (state0!= 0) { j = 0; for(k = b; k < b + state0; k++) { c1[j] = ints1[k]; j++; }; }; if (state1!= 0) { j = 0; for(k = d; k < d + state1; k++) { c2[j] = ints2[k]; j++; }; }; if (state2!= 0) { j = 0; for(k = f; k < f + state2; k++) { c3[j] = ints3[k]; j++; }; }; sd = swig_getmaxprob(next, endstate, c1, c2, c3,1); if (sd->middle == NULL) { sd->middle = new_middle(-1,-1,-1,null); }; assign_middle(middle, sd->middle); } else { State *state = NULL; state = swig_getmaxstate(next); if (next->sdlist_middle[state->key]!= NULL) { assign_middle(middle, next->sdlist_middle[state->key]); } else { assign_middle(middle, new_middle(-1,-1,-1,null)); }; }; free(pending); free(ready); return stored; }

94 86 BILAG C. KODE C.4. getnotifylist ElementData **swig_initnotifylist(elementdata *self, int a, int b, int c, int d, int e, int f, ElementData **elementdatalist, int L1, int L2, int L3) { ElementData **notifylist; notifylist = NEW_LIST(ElementData *,hmm->states_length); int i; for(i = 0; i < hmm->states_length; i++) { notifylist[i] = NULL; }; for(i = 0; i < hmm->statelist_length; i++) { if ((self->i + hmm->statelist[i].advance[0] < b-a) && (self->j + hmm->statelist[i].advance[1] < d-c) && (self->k + hmm->statelist[i].advance[2] < f-e)) { notifylist[hmm->statelist[i].key] = Pending_get(elementdatalist, self->i + hmm->statelist[i].advance[0], self->j + hmm->statelist[i].advance[1], self->k + hmm->statelist[i].advance[2],l1,l2,l3); } } return notifylist; }

95 D. Summary in English Finding gene structures in DNA-sequences is a complex task. The exact structure can vary from one gene to another, and furthermore there can be a lot of noisy signals, that can make detection difficult. To get a better result we can try to find the same gene structure in two or more related species at a time, thereby reducing the influence of noise and improving the possibility of recognizing the true gene structure. One possibility of finding gene structures is to use a probabilistic model called a Hidden Markov Model (HMM). We adopt this model, but use a variant called a pair-hmm, which can align two sequences to each other while finding gene structures in both sequences. But instead of using it for only two sequences we extend it to handle three sequences, and thus call it a triple-hmm. When aligning three sequences, the usual time and space usage is O(n 3 ), if the sequences have approximately the same length, n. Especially the space usage imposes a very low upper bound on the lengths of the sequences, that are practically alignable. We have therefore implemented an alignment-algorithm (the Push-algorithm), where the space usage is reduced by one dimension to O(n 2 ) at a cost of doubling the time usage. This makes it practically possible to align three sequences of with a length of up to 1000bp each. At the same time it is possible to change the triple-hmm, that the algorithm uses, without having to change anything in the implementation of the algorithm. Both the space reduction and the separation of model and algorithm has a fairly simple implementation. This simplicity has been achieved by using a kind of forward-algorithm, where we push values forward (whence the name: Push-alignment), instead of asking for the value recursively, as is normally done in dynamic programming. We have tested our implementation, and seen that the theoretical space reduction has also been achieved in practice. Finally we have used our Push-algorithm on both simulated and real data. This task has been of minor interest in our work, since it would require estimation of the probabilities/parameters used in the model, to get the best results. Parameter estimation is a rather complex field in itself, and is not in the scope of this report. At the webaddress we have made a homepage, 87

96 88 BILAG D. SUMMARY IN ENGLISH where this report can be found in both postscript and pdf-versions. Furthermore the sourcecode for the framework can be found at this site.

97 Litteratur [A + 02] Alberts et al. Molecular Biology Of The Cell [D + 98] Durbin et al. Biological sequence analysis [Gus97] Dan Gusfield. Algorithms on Strings, Trees and Sequences [H + 93] Haussler et al. Protein modeling using hidden markov models: Analysis of globins in mudge, t. n., milutinovic, v., and hunter, l. (eds.), proceedings of the twenty-sixth annual hawaii international conference on system sciences volume 1 pp los alamitos, california. ieee computer society press [Hir75] D. S. Hirschberg. A linear space algorithm for computing maximal common subsequences. comm. a.c.m. 18(6) s [K + 94] A. Krogh et al. Journal of molecular biology 235, [K + 03] Manolis Kellis et al. Sequencing and comparison of yeast species to identify genes and regulatory elements. NATURE, 423: , [Lab03] Oak Ridge National Laboratory. Gene therapy. sci/techresources/human_genome/medicine/genetherapy%.shtml, November 19, [Mus99] National Health Museum. Access excellence, about biotech, graphics gallery [SEA92] SEARLS. American scientist 80, [SM97] Setubal and Meidanis. Introduction to Computational Molecular Biology [SW81] T. F. Smith and M. S. Waterman. Identification of common molecular subsequences. Journal of Molecular Biology, 147: ,

Modul 3: Sandsynlighedsregning

Modul 3: Sandsynlighedsregning Forskningsenheden for Statistik ST01: Elementær Statistik Bent Jørgensen Modul 3: Sandsynlighedsregning 3.1 Sandsynligheder................................... 1 3.2 Tilfældig udtrækning fra en mængde........................

Læs mere

Side 1 af 14. Eksamen: Bioinformatik It og Sundhed 27 Jan 2011 kl 9-13

Side 1 af 14. Eksamen: Bioinformatik It og Sundhed 27 Jan 2011 kl 9-13 Side 1 af 14 Eksamen: Bioinformatik It og Sundhed 27 Jan 2011 kl 9-13 Navn: Studie nummer: Dette eksamenssæt vil også kunne ses som en pdf fil nederst på kursus-hjemmesiden udfor den sidste dag d. 27 Jan

Læs mere

Danmarks Tekniske Universitet

Danmarks Tekniske Universitet Side 1 of 14 Danmarks Tekniske Universitet Skriftlig prøve, den 21/1-2013 Kursus navn: Kursus nr. 27633 Introduktion til Bioinformatik Tilladte hjælpemidler: Alle "Vægtning" Angivet ved de individuelle

Læs mere

Genetiske afstande og afstandsmatricer

Genetiske afstande og afstandsmatricer Genetiske afstande og afstandsmatricer Denne vejledning indeholder en række små øvelser og opgaver der illustrerer, hvordan man ud fra genetiske sekvenser kan udregne en gennemsnitlig evolutionær afstand

Læs mere

En forsker har lavet et cdna insert vha PCR og har anvendt det følgende primer sæt, som producerer hele den åbne læseramme af cdna et:

En forsker har lavet et cdna insert vha PCR og har anvendt det følgende primer sæt, som producerer hele den åbne læseramme af cdna et: F2011-Opgave 1. En forsker har lavet et cdna insert vha PCR og har anvendt det følgende primer sæt, som producerer hele den åbne læseramme af cdna et: Forward primer: 5 CC ATG GGT ATG AAG CTT TGC AGC CTT

Læs mere

Biologi opgave Opsamling: Cellebiologi (Bioanalytiker modul3)

Biologi opgave Opsamling: Cellebiologi (Bioanalytiker modul3) 1 Delphine Bonneau Biologi opgave Opsamling: Cellebiologi 1-6 Pelle har spist en kæmpe stor kage, og efterfølgende stiger hans blodsukker. Derfor sender kroppen besked til de endokrine kirtler i bugspytkirtlen

Læs mere

Fra DNA til protein - lærerens tekst

Fra DNA til protein - lærerens tekst Fra DNA til protein - lærerens tekst Af sidsel sangild Denne øvelse handler om proteinsyntese og proteiners foldning. Den giver mulighed for at danne nogle andre billeder af fænomenet, end man får ved

Læs mere

Struktur og funktion af gener

Struktur og funktion af gener Molekylærbiologi og genetik S4, F2008 f Malene Munk Jørgensen Emne: Struktur og funktion af gener Link: undervisningsplanen for S4-molekylærbiologi og genetik MMJ, VI niversity ollege Bioanalytikeruddannelsen

Læs mere

Biologiske signaler i graviditeten - Genetisk information

Biologiske signaler i graviditeten - Genetisk information Biologiske signaler i graviditeten - Genetisk information 2 I forbindelse med vores studie af graviditeten ønsker vi at foretage undersøgelser af arvematerialet (DNA og RNA). Disse genetiske undersøgelser

Læs mere

Side 1 af 13. Eksamen: Bioinformatik It og Sundhed 27 Jan 2011 kl 9-13

Side 1 af 13. Eksamen: Bioinformatik It og Sundhed 27 Jan 2011 kl 9-13 Side1af13 Eksamen: Bioinformatik It og Sundhed 27 Jan 2011 kl 9-13 Navn: Studie nummer: Dette eksamenssæt vil også kunne ses som en pdf fil nederst på kursus-hjemmesiden udfor den sidste dag d. 27 Jan

Læs mere

Danmarks Tekniske Universitet

Danmarks Tekniske Universitet Side 1 of 17 Danmarks Tekniske Universitet Skriftlig prøve, den 21/1-2013 Kursus navn: Kursus nr. 27633 Introduktion til Bioinformatik Tilladte hjælpemidler: Alle "Vægtning" Angivet ved de individuelle

Læs mere

Menneskets væskefaser

Menneskets væskefaser Menneskets væskefaser Mennesket består af ca. 60% væske (vand) Overordnet opdelt i to: Ekstracellulærvæske og intracellulærvæske Ekstracellulærvæske udgør ca. 1/3 Interstitielvæske: Væske der ligger mellem

Læs mere

Velkommen. Test dit eget DNA med PCR. Undervisningsdag på DTU Systembiologi. Undervisere: Sebastian, Louise og Ana

Velkommen. Test dit eget DNA med PCR. Undervisningsdag på DTU Systembiologi. Undervisere: Sebastian, Louise og Ana Velkommen Test dit eget DNA med PCR Undervisningsdag på DTU Systembiologi Undervisere: Sebastian, Louise og Ana Hvem er I? 2 DTU Systembiologi, Danmarks Tekniske Universitet Dagens program 9:00 10:00 Introduktion

Læs mere

Hvorfor er genfinding et vanskeligt problem?

Hvorfor er genfinding et vanskeligt problem? 19th January 2005 Genfinding og skjulte Markov-modeller Af Asger Hobolth og Leif Schauser Indledning I disse år kortlægges en række organismers arvelige materiale. Det humane om blev kortlagt i 2001, og

Læs mere

Gen-identifikation ved sekvens-sammenligning. Tejs Scharling. Specialerapport. Datalogisk Institut Aarhus Universitet Danmark

Gen-identifikation ved sekvens-sammenligning. Tejs Scharling. Specialerapport. Datalogisk Institut Aarhus Universitet Danmark Gen-identifikation ved sekvens-sammenligning Tejs Scharling Specialerapport Datalogisk Institut Aarhus Universitet Danmark Gen-identifikation ved sekvens-sammenligning En specialerapport afleveret til

Læs mere

Genetiske Aspekter af HCM hos Kat. - en introduktion til forskningsprojektet

Genetiske Aspekter af HCM hos Kat. - en introduktion til forskningsprojektet Genetiske Aspekter af HCM hos Kat - en introduktion til forskningsprojektet Cand. scient. Mia Nyberg, ph.d. stud. [email protected] IMHS, Det Biovidenskabelige Fakultet, Københavns Universitet, Klinisk Biokemisk

Læs mere

3u BI, terminsprøve (Bio A)

3u BI, terminsprøve (Bio A) 3.u BI, terminsprøve, 2018 MV 3u BI, terminsprøve (Bio A) Torsdag den 12/4, 2018, kl. 9-14. Af opgaverne 1, 2, 3, og 4 skal tre, og kun tre, afleveres Tilladte hjælpemidler: Bøger, kompendier, noter, lommeregner.

Læs mere

1. Hvad er kræft, og hvorfor opstår sygdommen?

1. Hvad er kræft, og hvorfor opstår sygdommen? 1. Hvad er kræft, og hvorfor opstår sygdommen? Dette kapitel fortæller om, cellen, kroppens byggesten hvad der sker i cellen, når kræft opstår? årsager til kræft Alle levende organismer består af celler.

Læs mere

Velkommen. Test dit eget DNA med PCR. Undervisningsdag på DTU Systembiologi. Undervisere:

Velkommen. Test dit eget DNA med PCR. Undervisningsdag på DTU Systembiologi. Undervisere: Velkommen Test dit eget DNA med PCR Undervisningsdag på DTU Systembiologi Undervisere: Hvem er I? 2 DTU Systembiologi, Danmarks Tekniske Universitet Hvilke baser indgår i DNA? A. Adenin, Guanin, Cytosin,

Læs mere

Cellekernen (Nucleus) Sebastian Frische Anatomisk Institut

Cellekernen (Nucleus) Sebastian Frische Anatomisk Institut Cellekernen (Nucleus) Sebastian Frische Anatomisk Institut Cellekernen Cellekernens overordnede struktur kernemembranen/nucleolemma kromatin nucleolus Cellecyklus faser i cellecyklus faser i mitosen Størrelse:

Læs mere

Kromosomer med genet: Genotype (= arveformel): RR Rr rr Fænotype (= fremtoning): Rød Rød Hvid

Kromosomer med genet: Genotype (= arveformel): RR Rr rr Fænotype (= fremtoning): Rød Rød Hvid Kromosomer med genet: R R R r r r Genotype (= arveformel): RR Rr rr Fænotype (= fremtoning): Rød Rød Hvid P-generation: Kønsceller: RR rr Meiose R R r r Befrugtning F 1-generation: Meiose Rr Rr Kønsceller:

Læs mere

Kvægavlens teoretiske grundlag

Kvægavlens teoretiske grundlag Kvægavlens teoretiske grundlag Lige siden de første husdyrarter blev tæmmet for flere tusinde år siden, har mange interesseret sig for nedarvningens mysterier. Indtil begyndelsen af forrige århundrede

Læs mere

Bioinformatik Open Source Software i biologiens tjeneste

Bioinformatik Open Source Software i biologiens tjeneste Bioinformatik Open Source Software i biologiens tjeneste Kenneth Geisshirt [email protected] Silex Science ApS Bioinformatik p.1/19 Om Silex Science ApS Grundlagt maj 2002 Ejeren er Cortex Holding Fokusområderne

Læs mere

Eukaryote celler arbejder

Eukaryote celler arbejder Eukaryote celler arbejder Niveau: 9. klasse Varighed: 5 lektioner Præsentation: I dette forløb skal eleverne arbejde med den eukaryote celle. I forløbet kommer vi omkring funktioner og kemiske processer

Læs mere

Skriftlig Eksamen Algoritmer og Datastrukturer (DM507)

Skriftlig Eksamen Algoritmer og Datastrukturer (DM507) Skriftlig Eksamen Algoritmer og Datastrukturer (DM507) Institut for Matematik og Datalogi Syddansk Universitet, Odense Mandag den 7. juni 00, kl. 9 Alle sædvanlige hjælpemidler (lærebøger, notater, osv.)

Læs mere

BIOTEKNOLOGI HØJT NIVEAU

BIOTEKNOLOGI HØJT NIVEAU STUDENTEREKSAMEN 2007 2007-BT-1 BITEKNLGI HØJT NIVEAU Torsdag den 31. maj 2007 kl. 9.00 14.00 Sættet består af 1 stor og 2 små opgaver samt 1 bilag i 2 eksemplarer. Det ene eksemplar af bilaget afleveres

Læs mere

CELLE OG VÆVSLÆRE 1 LEKTION 1. Nima Kalbasi, DDS Anatomi og fysiologi

CELLE OG VÆVSLÆRE 1 LEKTION 1. Nima Kalbasi, DDS Anatomi og fysiologi CELLE OG VÆVSLÆRE 1 LEKTION 1 Nima Kalbasi, DDS Anatomi og fysiologi Dagens emner Introduktion Cellemembranen Cytoplasmaet og dets struktur Cellekernen (nukleus) Celledelingen Genetik (arvelighedslære)

Læs mere

Banan DNA 1/6. Formål: Formålet med øvelsen er at give eleverne mulighed for at se DNA strenge med det blotte øje.

Banan DNA 1/6. Formål: Formålet med øvelsen er at give eleverne mulighed for at se DNA strenge med det blotte øje. Banan DNA Formål: Formålet med øvelsen er at give eleverne mulighed for at se DNA strenge med det blotte øje. Baggrundsviden: Om vi er mennesker, dyr eller planter, så har alle organismer DNA i deres celler.

Læs mere

Klip-og-kopier DNA: reparér mutationer med 'genom-redigering' DNA, RNA og protein

Klip-og-kopier DNA: reparér mutationer med 'genom-redigering' DNA, RNA og protein Forskningsnyheder om Huntingtons Sygdom På hverdagssprog Skrevet af forskere. Til det globale HS-fællesskab Klip-og-kopier DNA: reparér mutationer med 'genom-redigering' Forskere kan lave præcise ændringer

Læs mere

Skriftlig Eksamen Algoritmer og Datastrukturer (dads)

Skriftlig Eksamen Algoritmer og Datastrukturer (dads) Skriftlig Eksamen Algoritmer og Datastrukturer (dads) Datalogisk Institut Aarhus Universitet Tirsdag den 27. maj 2003, kl. 9.00 3.00 Opgave (25%) For konstanten π = 3.4592... gælder identiteten π 2 6 =

Læs mere

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer DM507 Algoritmer og datastrukturer Forår 2017 Projekt, del III Institut for matematik og datalogi Syddansk Universitet 6. april, 2017 Dette projekt udleveres i tre dele. Hver del har sin deadline, således

Læs mere

Cellen og dens funktioner

Cellen og dens funktioner Eksamensopgaver Biologi C, 17bic80 6. og 7. juni 2018 1 Cellen og dens funktioner 1. Redegør for hvordan eukaryote og prokaryote celler i hovedtræk er opbygget, herunder skal du gøre rede for forskelle

Læs mere

Cellens livscyklus GAP2. Celledeling

Cellens livscyklus GAP2. Celledeling Cellens livscyklus Cellens livscyklus inddeles i to faser, interfase og mitose. GAP1 (G1). Tiden lige efter mitosen hvor der syntetiseres RNA og protein. Syntese fasen. Tidsrummet hvor DNAet duplikeres

Læs mere

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer DM507 Algoritmer og datastrukturer Forår 2016 Projekt, del III Institut for matematik og datalogi Syddansk Universitet 20. april, 2016 Dette projekt udleveres i tre dele. Hver del har sin deadline, således

Læs mere

Dynamisk programmering

Dynamisk programmering Dynamisk programmering Dynamisk programmering Et algoritme-konstruktionsprincip ( paradigme ) for optimeringsproblemer. Har en hvis lighed med divide-and-conquer: Begge opbygger løsninger til større problemer

Læs mere

Plan. Markovkæder Matematisk modelling af kølængde, yatzy, smittespredning og partikelbevægelser. Materiale mm.

Plan. Markovkæder Matematisk modelling af kølængde, yatzy, smittespredning og partikelbevægelser. Materiale mm. Institut for Matematiske Fag Plan Markovkæder Matematisk modelling af kølængde, yatzy, smittespredning og partikelbevægelser Helle Sørensen Eftermiddagen vil være bygget om 3 4 eksempler: A. B. Random

Læs mere

# Problemet med genetisk ustabilitet

# Problemet med genetisk ustabilitet Forskningsnyheder om Huntingtons Sygdom På hverdagssprog Skrevet af forskere. Til det globale HS-fællesskab Et DNA-reparerende protein ændrer stabiliteten af lange CAG-områder i det muterede gen for Huntingtons

Læs mere

(19) DANMARK (11) DK B1 (12) PATENTSKRIFT. Ci2. Patent- og Varemærkestyrelsen

(19) DANMARK (11) DK B1 (12) PATENTSKRIFT. Ci2. Patent- og Varemærkestyrelsen (19) DANMARK (11) DK 176903 B1 Ci2 (12) PATENTSKRIFT Patent- og Varemærkestyrelsen (51) Int.CI. 8 : C 12 N 15/31 (2006.01) A 61 K 39/02 (2006.01) A 61 K 48/00 (2006.01) A 61 P 31/04 (2006.01) C 07 K 14/29

Læs mere

Dynamisk programmering. Flere eksempler

Dynamisk programmering. Flere eksempler Dynamisk programmering Flere eksempler Eksempel 1: Længste fælles delstreng Alfabet = mængde af tegn: {a,b,c,...,z}, {A,C,G,T}, {,1} Eksempel 1: Længste fælles delstreng Alfabet = mængde af tegn: {a,b,c,...,z},

Læs mere

Kromosomforandringer. Information til patienter og familier

Kromosomforandringer. Information til patienter og familier Kromosomforandringer Information til patienter og familier 2 Kromosomforandringer Den følgende information er en beskrivelse af kromosomforandringer, hvorledes de nedarves og hvornår dette kan medføre

Læs mere

Forskningsnyheder om Huntingtons Sygdom På hverdagssprog Skrevet af forskere. Til det globale HS-fællesskab Ofte stillede spørgsmål, januar 2011

Forskningsnyheder om Huntingtons Sygdom På hverdagssprog Skrevet af forskere. Til det globale HS-fællesskab Ofte stillede spørgsmål, januar 2011 Forskningsnyheder om Huntingtons Sygdom På hverdagssprog Skrevet af forskere. Til det globale HS-fællesskab Ofte stillede spørgsmål, januar 2011 Svar på ofte stillede spørgsmål om HD - den første i en

Læs mere

Kromosomforandringer. Information til patienter og familier

Kromosomforandringer. Information til patienter og familier 12 Odense: Odense Universitetshospital Sdr.Boulevard 29 5000 Odense C Tlf: 65 41 17 25 Kromosomforandringer Vejle: Sygehus Lillebælt, Vejle Klinisk Genetik Kabbeltoft 25 7100 Vejle Tlf: 79 40 65 55 Århus:

Læs mere

(19) DANMARK (11) DK 175533 B1 ( 1 2) PATENTSKRIFT. Patent- og Varemærkestyrelsen

(19) DANMARK (11) DK 175533 B1 ( 1 2) PATENTSKRIFT. Patent- og Varemærkestyrelsen (19) DANMARK (11) DK 175533 B1 ( 1 2) PATENTSKRIFT Patent- og Varemærkestyrelsen (51) Int.C1 7.: A 61 K 39/295 A 61 K 39/205 A 61 K 39/285 A 61 K 39/42 C 12 N 15/00 (21) Patentansøgning nr: PA 1985 06062

Læs mere

Dynamisk programmering

Dynamisk programmering Dynamisk programmering Dynamisk programmering Optimeringsproblem: man ønsker at finde bedste den kombinatoriske struktur blandt mange mulige. Dynamisk programmering Optimeringsproblem: man ønsker at finde

Læs mere

27611 Eksamen Sommer 2007

27611 Eksamen Sommer 2007 - Side 1 af 10-27611 Eksamen Sommer 2007 Dette sæt indeholder 4 opgaver. En online version af opgavesættet vil være tilgængeligt fra kursets lektionsplan, under selve eksamen (25. Maj 2007 klokken 9:00

Læs mere

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer DM507 Algoritmer og datastrukturer Forår 2019 Projekt, del III Institut for matematik og datalogi Syddansk Universitet 10. april, 2019 Dette projekt udleveres i tre dele. Hver del har sin deadline, således

Læs mere

Dynamisk programmering. Flere eksempler

Dynamisk programmering. Flere eksempler Dynamisk programmering Flere eksempler Eksempel 1: Længste fælles delstreng Alfabet = mængde af tegn: {a,b,c,...,z}, {A,C,G,T}, {,1} Streng = sekvens x 1 x 2 x 3... x n af tegn fra et alfabet: helloworld

Læs mere

På grund af reglerne for copyright er det ikke muligt at lægge figurer fra lærebøger på nettet. Derfor har jeg fjernet figurerne fra slides ne, men

På grund af reglerne for copyright er det ikke muligt at lægge figurer fra lærebøger på nettet. Derfor har jeg fjernet figurerne fra slides ne, men På grund af reglerne for copyright er det ikke muligt at lægge figurer fra lærebøger på nettet. Derfor har jeg fjernet figurerne fra slides ne, men skrevet hvorfra de er taget. De tre bøger, hvorfra illustrationerne

Læs mere

Deoxyribonukleinsyre

Deoxyribonukleinsyre DNAs Forunderlige struktur Ved Rebecca E.-Sørensen stud.scient i medicinalkemi ved Aarhus Universitet Deoxyribonukleinsyre Strukturen af DNA findes af James D. Watson og Francis H. Crick i 1953 1 Nuklein

Læs mere

Danmarks Tekniske Universitet

Danmarks Tekniske Universitet Side 1 of 16 Danmarks Tekniske Universitet Skriftlig prøve, den 26/1-2012 Kursus navn: Kursus nr. 27633 Introduktion til Bioinformatik Tilladte hjælpemidler: Alle "Vægtning" Angivet ved de individuelle

Læs mere

Generne bestemmer. Baggrundsviden og progression: Niveau: 8. klasse. Varighed: 12 lektioner

Generne bestemmer. Baggrundsviden og progression: Niveau: 8. klasse. Varighed: 12 lektioner Generne bestemmer Niveau: 8. klasse Varighed: 12 lektioner Præsentation: Generne bestemmer er et forløb om genernes indflydelse på individet. I forløbet kommer vi omkring den eukaryote celle, celledeling,

Læs mere

Det lyder enkelt, men for at forstå hvilket ærinde forskerne er ude i, er det nødvendigt med et indblik i, hvordan celler udvikles og specialiseres.

Det lyder enkelt, men for at forstå hvilket ærinde forskerne er ude i, er det nødvendigt med et indblik i, hvordan celler udvikles og specialiseres. Epigenetik Men hvad er så epigenetik? Ordet epi er af græsk oprindelse og betyder egentlig ved siden af. Genetik handler om arvelighed, og hvordan vores gener videreføres fra generation til generation.

Læs mere

Dansk resumé for begyndere

Dansk resumé for begyndere Dansk resumé for begyndere Dansk resumé for begyndere Dette afsnit introducerer bakteriel genregulation for enhver uden forudgående kendskab til dette emne. Alle nødvendige, videnskabelige betegnelser

Læs mere

Proteiners byggesten er aminosyrer

Proteiners byggesten er aminosyrer PTEIE G EZYME Proteiners byggesten er aminosyrer Lad os se på den kemiske opbygning af et protein. Proteiner er store molekyler der er opbygget af mindre molekyler, som man kalder aminosyrer. Der findes

Læs mere

Danmarks Tekniske Universitet

Danmarks Tekniske Universitet side af sider Danmarks Tekniske Universitet Skriftlig prøve, den 6. maj 0. Kursusnavn: Algoritmer og datastrukturer I Kursus nr. 005. Tilladte hjælpemidler: Skriftlige hjælpemidler. Varighed: timer Vægtning

Læs mere

Lærervejledning Til internet-spillet Kræftkampen og undervisningshæftet Hvorfor opstår kræft? Biologi 8.-9. klasse

Lærervejledning Til internet-spillet Kræftkampen og undervisningshæftet Hvorfor opstår kræft? Biologi 8.-9. klasse kraeftkampen.dk Kræftens Bekæmpelse Lærervejledning Til internet-spillet Kræftkampen og undervisningshæftet Hvorfor opstår kræft? Biologi 8.-9. klasse Hvorfor arbejde med Kræft? Erhvervsskolernes Forlag

Læs mere

BIOLOGI A-NIVEAU NY ORDNING. Tirsdag den 19. august 2008. Kl. 09.00 14.00 STX082-BIA STUDENTEREKSAMEN AUGUST 2008

BIOLOGI A-NIVEAU NY ORDNING. Tirsdag den 19. august 2008. Kl. 09.00 14.00 STX082-BIA STUDENTEREKSAMEN AUGUST 2008 STUDENTEREKSAMEN AUGUST 2008 BIOLOGI A-NIVEAU Tirsdag den 19. august 2008 NY ORDNING Kl. 09.00 14.00 Af opgaverne 1, 2, 3 og 4 skal tre og kun tre af opgaverne besvares STX082-BIA Undervisningsministeriet

Læs mere

Algoritmeanalyse. Øvre grænse for algoritme. Øvre grænse for problem. Nedre grænse for problem. Identificer essentiel(le) operation(er)

Algoritmeanalyse. Øvre grænse for algoritme. Øvre grænse for problem. Nedre grænse for problem. Identificer essentiel(le) operation(er) Algoritmeanalyse Identificer essentiel(le) operation(er) Øvre grænse for algoritme Find øvre grænse for antallet af gange de(n) essentielle operation(er) udføres. Øvre grænse for problem Brug øvre grænse

Læs mere

Ting man gør med Vektorfunktioner

Ting man gør med Vektorfunktioner Ting man gør med Vektorfunktioner Frank Nasser. april 11 c 8-11. Dette dokument må kun anvendes til undervisning i klasser som abonnerer på MatBog.dk. Se yderligere betingelser for brug her. Bemærk: Dette

Læs mere

Er der flere farver i sort?

Er der flere farver i sort? Er der flere farver i sort? Hvad er kromatografi? Kromatografi benyttes inden for mange forskellige felter og forskningsområder og er en anvendelig og meget benyttet analytisk teknik. Kromatografi bruges

Læs mere

Proteiner: en introduktion. Modul 1; F13 Rolf Andersen, 18/2-2013

Proteiner: en introduktion. Modul 1; F13 Rolf Andersen, 18/2-2013 Proteiner: en introduktion Modul 1; F13 Rolf Andersen, 18/2-2013 4 facts om proteiner Proteiner udgør én af de vigtigste stofgrupper i vores organisme; de varetager en lang række forskellige funktioner.

Læs mere

Epigenetik Arv er andet end gener

Epigenetik Arv er andet end gener Epigenetik Arv er andet end gener Indhold Indledning Afsnit1: Epigenetik og DNA Afsnit 2: DNA, nukleosomer og kromatin Afsnit 3: Epigenetik og celledifferentiering Afsnit 4: Genetisk ens individer kan

Læs mere

Pointen med Funktioner

Pointen med Funktioner Pointen med Funktioner Frank Nasser 0. april 0 c 0080. Dette dokument må kun anvendes til undervisning i klasser som abonnerer på MatBog.dk. Se yderligere betingelser for brug her. Bemærk: Dette er en

Læs mere

EKSAMENSOPGAVER. Eksamensopgaver uden bilag

EKSAMENSOPGAVER. Eksamensopgaver uden bilag EKSAMENSOPGAVER Eksamensopgaver uden bilag Eksaminator: Morten Sigby-Clausen (MSC) 1. Celler og celledeling 2. Kost, fordøjelse og ernæring 3. Blodkredsløbet og åndedrætssystemet 4. Nedarvning af udvalgte

Læs mere

Skriftlig Eksamen Algoritmer og Datastrukturer (dads)

Skriftlig Eksamen Algoritmer og Datastrukturer (dads) Skriftlig Eksamen Algoritmer og Datastrukturer (dads) Datalogisk Institut Aarhus Universitet Mandag den 27. maj 2002, kl. 9.00 13.00 Opgave 1 (25%) Denne opgave handler om multiplikation af positive heltal.

Læs mere

Abstrakte datatyper C#-version

Abstrakte datatyper C#-version Note til Programmeringsteknologi Akademiuddannelsen i Informationsteknologi Abstrakte datatyper C#-version Finn Nordbjerg 1/9 Abstrakte Datatyper Denne note introducerer kort begrebet abstrakt datatype

Læs mere

Simulering af stokastiske fænomener med Excel

Simulering af stokastiske fænomener med Excel Simulering af stokastiske fænomener med Excel John Andersen, Læreruddannelsen i Aarhus, VIA Det kan være en ret krævende læreproces at udvikle fornemmelse for mange begreber fra sandsynlighedsregningen

Læs mere

(19) DANMARK. 2six,l (12) PATENTSKRIFT. Patent- og Varemærkestyrelsen (11) DK 175072 B1

(19) DANMARK. 2six,l (12) PATENTSKRIFT. Patent- og Varemærkestyrelsen (11) DK 175072 B1 (19) DANMARK (11) DK 175072 B1 2six,l (12) PATENTSKRIFT Patent- og Varemærkestyrelsen (51) Int.C1 7.: C 12 N 15/38 A 61 K 39/245 C 12 N 15/63 G 01 N 33/569 (21) Patentansøgning nr: PA 1987 02888 (22).

Læs mere

Ting man gør med Vektorfunktioner

Ting man gør med Vektorfunktioner Ting man gør med Vektorfunktioner Frank Villa 3. august 13 Dette dokument er en del af MatBog.dk 8-1. IT Teaching Tools. ISBN-13: 978-87-9775--9. Se yderligere betingelser for brug her. Indhold 1 Introduktion

Læs mere

Asger Hobolth (AU, Matematisk Institut): Kaffe, computere og konveks analyse kan kvantificere kendskabet til kræft

Asger Hobolth (AU, Matematisk Institut): Kaffe, computere og konveks analyse kan kvantificere kendskabet til kræft Asger Hobolth (AU, Matematisk Institut): Kaffe, computere og konveks analyse kan kvantificere kendskabet til kræft I tæt samarbejde med Astrid Kousholt (Novo Nordisk), Jens Ledet Jensen (AU, Math) and

Læs mere

Regneark II Calc Open Office

Regneark II Calc Open Office Side 1 af 10 Gangetabel... 2 Udfyldning... 2 Opbygning af gangetabellen... 3 Cellestørrelser... 4 Øveark... 4 Facitliste... 6 Sideopsætning... 7 Flytte celler... 7 Højrejustering... 7 Kalender... 8 Dage

Læs mere

Celle- og vævslære. Maria Jensen 1

Celle- og vævslære. Maria Jensen 1 Celle- og vævslære. 1 Hvad er celler? Robert Hooke beskrev første gang en celle i 1665. Han undersøgte i mikroskop en skive fra en korkprop. Her opdagede han at korken var opbygget af små hulrum, små celler

Læs mere

Præsentation: Genetikeren Theo Dobzhansky har sagt: Nothing in biology makes sense except in the light of evolution.

Præsentation: Genetikeren Theo Dobzhansky har sagt: Nothing in biology makes sense except in the light of evolution. Evolution Niveau: 9. klasse Varighed: 7. lektioner Præsentation: Genetikeren Theo Dobzhansky har sagt: Nothing in biology makes sense except in the light of evolution. Molekylærbiologen Sydney Brenner

Læs mere

Gennemsnit og normalfordeling illustreret med terningkast, simulering og SLUMP()

Gennemsnit og normalfordeling illustreret med terningkast, simulering og SLUMP() Gennemsnit og normalfordeling illustreret med terningkast, simulering og SLUMP() John Andersen, Læreruddannelsen i Aarhus, VIA Et kast med 10 terninger gav følgende udfald Fig. 1 Result of rolling 10 dices

Læs mere

Hvad er en funktion? Funktioner og graftegning. Funktioners egenskaber. Funktioners egenskaber. f(b) y = f(x) f(a) f(a)

Hvad er en funktion? Funktioner og graftegning. Funktioners egenskaber. Funktioners egenskaber. f(b) y = f(x) f(a) f(a) Funktioner og graftegning Jeppe Revall Frisvad September 29 Hvad er en funktion? En funktion f er en regel som til hvert element i en mængde A ( A) knytter præcis ét element y i en mængde B Udtrykket f

Læs mere

27611 Eksamen Sommer 2008

27611 Eksamen Sommer 2008 27611 Eksamen Sommer 2008 Dette sæt indeholder 10 opgaver. En online version af opgavesættet vil være tilgængeligt fra kursets lektionsplan under selve eksamen ( juni 2008 klokken 15:00-19:00). DNA/Protein

Læs mere

1. Afrikansk plante med mulig gavnlig virkning på diabetes type II. 2. Bestemmelse af genomer hos forskellige arter organismer

1. Afrikansk plante med mulig gavnlig virkning på diabetes type II. 2. Bestemmelse af genomer hos forskellige arter organismer Eksamensspørgsmål til biobu maj 2013 1. Afrikansk plante med mulig gavnlig virkning på diabetes type II Forklar hvordan insulin er opbygget, dets dannelse og virkemåde. Hvad er årsagen til diabetes type

Læs mere

BIOTEKNOLOGI HØJT NIVEAU

BIOTEKNOLOGI HØJT NIVEAU STUDETEREKSAME 2006 2006-BT-2 BIOTEKOLOGI HØJT IVEAU Onsdag den 16. august 2006 kl. 9.00 14.00 Sættet består af 1 stor og 2 små opgaver. Alle hjælpemidler tilladt. STOR OPGAVE 1. Myoglobin A. Den røde

Læs mere