Sunteți pe pagina 1din 58

UNIVESITATEA HYPERION din BUCUREŞTI

FACULTATEA de ŞTIINŢE EXACTE ŞI INGINEREŞTI


Specializarea: Informatică

PROIECT DE LICENTA

COORDONATOR STIINŢIFIC:
Conf. Dr.

Absolvent:

2019
UNIVESITATEA HYPERION din BUCUREŞTI
FACULTATEA de ŞTIINŢE EXACTE ŞI INGINEREŞTI
Specializarea: Informatică

……………….

COORDONATOR STIINŢIFIC:
Conf. Dr. Beteringhe Adrian

Absolvent:

București 2019
TEMA PROIECTULUI

Să se realizeze o aplicație în Microsoft Visual Studio, cu


ajutorul căreia putem realiza și vizualiza aliniamente
globale, aliniamente locale.
Sopul acestei aplicații este unul instructiv-educativ fiind
gratis și ușor de înțeles de către toate persoanele interesate
de acest domeniu al bioinformaticii.
Cuprins

I. Introducere .......................................................................................................................................... 5
2. Alinierea secventelor ........................................................................................................................ 11
2.1 Alinierea în perechi și programarea dinamică ........................................................................ 12
2.2 Alinieri globale vs. alinieri locale .............................................................................................. 19
2.3 Aliniere locală vs. Căutarea in baza de date ............................................................................ 21
2.4 Importanța tabelului de scor ..................................................................................................... 22
3. Alinieri multiple................................................................................................................................ 23
4. Algoritmi utilizați în alinierea secvențială ..................................................................................... 25
4.1 Aliniere Globala (Algoritmul Needleman-Wunsch) ................................................................ 25
4.2 Alinierea locala (Algoritmul Smith & Waterman) .................................................................. 30
4.2.1 Matricile AND ..................................................................................................................... 31
4.2.2 Matricea de proteine ........................................................................................................... 32
5. Limbajul de programare folosit pentru proiectarea aplicației practice ...................................... 38
5.1 Funcționalitatea aplicației ......................................................................................................... 40
6. Concluzii............................................................................................................................................ 44
Bibliografie............................................................................................................................................ 45
Anexe ..................................................................................................................................................... 46
I. Introducere

Bioinformatica este o stiință exactă in care biologia si tehnologia informației se unesc si


creează un nou domeniu. Aceasta implică folosirea calculatorelor, programelor software şi
bazelor de date pentru a raspunde unor întrebari biologice şi este imparțită in 3 domenii de
cercetare:

 Dezvoltarea de algoritmi si statistici de extragere de informații


 Interpretarea datelor legate de nucleotide si aminoacizi si analiza lor
 Dezvoltarea unor software-uri care să permită manipularea datelor rezultate în urma
algoritmilor

Există două ramuri ale biologiei ce utilizează bioinformatica, şi anume genomica si


proteomica. Genomica analizează genomul. Genomul este un set complet de secvențe de ADN
care codifică materialul ereditar transmis din generație in generație. Aceste secvențe includ
toate genele, adică unitatea fizică si funcțională a ereditații, si copiile ARN care reprezintă
pasul inițial în traducerea informației genetice incluse in genom. Astfel, genomica se referă la
secvențierea și analiza tuturor acestor entități genomice, inclusiv a genelor și a transcriptelor,
într-un organism. Proteomica, pe de altă parte, se referă la analiza setului complet de proteine.
În plus față de aceste două domenii, există şi altele ce folosesc bioinformatica, precum
metabolomica si transcriptomica. Fiecare dintre aceste domenii importante din bioinformatică
vizează înțelegerea sistemelor biologice complexe.

Mulți oameni de ştiință de astăzi, se referă la bioinformatică, ca biologia sistemelor, o nouă


metodă de a aborda intrebări de biologie complexe. Biologia sistemelor înseamnă complilarea
cunostințelor despre genomică, proteomică si bioinformatică pentru a creea o noua imagine
completă a unei entități biologice. De exemplu, modul în care o cale de semnalizare
funcționează într-o celulă poate fi observată si analizată prin intermediul biologiei sistemelor.
Pot fi observate genele implicate, modul in care acestea interacționează si cum modificările
schimbă rezultatele şi pot fi făcute modele după acestea. Orice sistem în care informațiile pot
fi reprezentate digital oferă o potențială aplicație pentru bioinformatică. Astfel, bioinformatica
poate fi aplicată de la celule singulare la ecosisteme întregi. Prin intelegerea completa a
"listelor de parti" intr-un genom, oamenii de stiință dobândesc o mai bună ințelegere a
sistemelor biologice complexe. Înțelegerea interacțiunilor care apar între toate aceste părți
într-un genom sau proteom reprezintă următorul nivel de complexitate în sistem. Prin
intermediul acestor abordări, bioinformatica are potențialul de a oferi perspective
fundamentale în înțelegerea și modelarea modului în care se manifestă bolile umane specifice
sau stările sănătoase.
Începutul bioinformaticii este dat de Margaret Dayhoff în 1968 cu colecția ei de secvențe de
proteine cunoscute sub denumirea de “Atlas of Protein Sequence and Structure”. Unul dintre
primele experimente semnificative în bioinformatică a fost aplicarea unui program de căutare
a similitudinii secvenței la identificarea originilor unei gene virale. În acest experiment,
oamenii de ştiintă au folosit unul dinte primele programe de cautare a similarității dintre gene,
numit FASTP (Fast Protein), pentru a determina că, conținutul genei v-sis, o secvență
cauzatoare de cancer, este similară cu gena celulară PDGF.

Acest rezultat surprinzător a oferit cunoștințe mecanice importante pentru biologii care
lucrează asupra modului în care această secvență virală duce la provocarea cancerului. De la
această primă aplicare inițială a computerelor la biologie, domeniul bioinformatic a explodat.
Creșterea bioinformaticii este paralelă cu dezvoltarea tehnologiei de secvențiere a ADN-ului.
În același mod în care dezvoltarea microscopului la sfârșitul anilor 1600 a revoluționat
științele biologice, permițând Anton Van Leeuwenhoek să privească celulele pentru prima
dată, tehnologia de secvențiere a ADN-ului a revoluționat domeniul bioinformatic. Creșterea
rapidă a bioinformaticii poate fi ilustrată prin creșterea secvențelor ADN conținute în
depozitul public al secvențelor de nucleotide numite GenBank.

Proiectele de secvențiere a genomului au devenit principalele obiective ale numeroaselor


inițiative de bioinformatică. “The human genome project” (HGP) este un exemplu de succes al
unui proiect de secvențiere a genomului, dar multe alte genomuri au fost secventiate si sunt
secventiate. De fapt, primele genomuri care au fost secvențiate au fost de virusuri (de
exemplu, MS2) și de bacterii, genomul lui Haemophilus influenzae Rd fiind primul genom al
unui organism viu liber depozitat în bazele de date publice de secvență. Această realizare a
fost primită cu mai puțin fanfară decât finalizarea genomului uman, dar devine clar că
secvențializarea altor genomi este un pas important pentru bioinformatica de azi. Cu toate
acestea, secvența genomului are de la sine informații limitate. Pentru a interpreta informațiile
genomice, trebuie făcută o analiză comparativă a secvențelor și un lucru important pentru
aceste analize sunt bazele de date secvențiale accesibile publicului. Fără bazele de date ale
secvențelor (cum ar fi GenBank), în care biologii au capturat informații despre secvența lor de
interes, o mare parte din informațiile bogate obținute din proiectele de secvențiere a genomului
nu ar fi disponibile. In acelasi mod in care evolutiile in microscopie prefigureaza descoperiri
in biologia celulara, noi descoperiri in tehnologia informatiei si biologia moleculara
prefigureaza descoperiri in bioinformatica. De fapt, o parte importantă a domeniului
bioinformatic este dezvoltarea de noi tehnologii care permit bioinformaticii să se desfășoare
într-un ritm foarte rapid. Din punct de vedere al calculatorului, internetului, noilor dezvoltări
de software şi noii algoritmi au permis bioinformaticilor să facă salturi mari în ceea ce privește
cantitatea de date care poate fi analizată eficient. Din punct de vedere al laboratoarelor,
tehnologiilor şi metodelor noi cum ar fi analiza secventiala si SAGE (serial analysis of gene
expression), s-au dezvoltat la un nivel foarte ridicat, permițându-le oamenilor de ştiință sa
producă date la un nivel foarte mare pentru analize. Bioinformatica oferă atât tehnologii care
permit oamenilor de știință să se ocupe de cantitățile mari de date produse prin inițiative de
genomică și proteomică, cât și de abordarea interpretării acestor date. În multe privințe,
bioinformatica oferă instrumentele de aplicare a metodei științifice pe date la scară largă și ar
trebui văzută ca o abordare științifică pentru a pune la îndoială multe noi și diferite tipuri de
întrebări biologice.

Cuvântul bioinformatică a devenit un cuvânt foarte popular în știință. Mulți oameni de


știință găsesc bioinformatica interesantă, deoarece deține potențialul de a se arunca cu capul
înainte într-un teritoriu neexplorat. Bioinformatica este o știință nouă și o nouă modalitate de
gândire care ar putea duce la multe descoperiri biologice relevante. Problemele biologice
importante pot fi abordate prin bioinformatică și includ înțelegerea legăturii genotip-fenotip
pentru boala umană, întelegerea structurii relațiilor funcționale la proteine și înțelegerea
rețelelor biologice. Bioinformaticienii îşi dau seama adesea că reactivii necesari pentru a
răspunde la aceste întrebări biologice interesante nu există. Astfel, o mare parte a slujbei
bioinformaticienilor constă în construirea de instrumente și tehnologii noi ca parte a procesului
de a pune întrebarea. Pentru multi, bioinformatica este foarte populara deoarece oamenii de
stiinta pot aplica atat biologia, cat si abilitatile lor la programare pentru a dezvolta reactivi
pentru cercetare. Mulți oameni de știință descoperă că acest domeniu este un nou teritoriu
interesant al chestionării științifice, cu un mare potențial de a beneficia de sănătatea umană și
de societate.

Viitorul bioinformaticii este integrarea. De exemplu, integrarea unei mari varietăți de surse
de date, cum ar fi datele clinice și genomice, ne va permite să folosim simptomele bolii pentru
a prezice mutațiile genetice și invers. Integrarea datelor GIS, cum ar fi hărțile, sistemele
meteorologice, datele privind sănătatea culturilor și genotipul, ne va permite să anticipăm
rezultatele reușite ale experimentelor în agricultură. O altă arie viitoare de cercetare în
bioinformatică este genomica comparativă pe scară largă. De exemplu, dezvoltarea de
instrumente care pot face comparații pe 10 direcții ale genomului va împinge înainte rata de
descoperire în acest domeniu de bioinformatică. În acest sens, modelarea și vizualizarea
rețelelor complete de sisteme complexe ar putea fi utilizate în viitor pentru a prezice modul în
care sistemul (sau celula) reacționează, de exemplu, la un medicament. Un set tehnic de
provocări se confruntă cu bioinformatica și se adresează prin computere mai rapide, progresele
tehnologice în spațiul de stocare pe disc și creșterea lărgimii de bandă, dar de departe una
dintre cele mai mari obstacole cu care se confruntă bioinformatica astăzi, este numărul mic de
cercetători din domeniu. Acest lucru se schimbă pe măsură ce bioinformatica se îndreaptă spre
prim-planul cercetării, dar acest decalaj în expertiză a dus la lacune reale în cunoașterea
bioinformaticii în comunitatea de cercetare. În cele din urmă, o întrebare cheie de cercetare
pentru viitorul bioinformaticilor va fi cum să comparăm computațional observații biologice
complexe, cum ar fi modele de expresie genetică și rețele de proteine. Bioinformatica este
despre convertirea observațiilor biologice într-un model pe care un calculator îl va înțelege.
Aceasta este o sarcină foarte dificilă, deoarece biologia poate fi foarte complexă. Această
problemă a modului de a digitiza datele fenotipice, cum ar fi comportamentul,
electrocardiogramele și sănătatea culturilor într-o formă citită de calculator, oferă provocări
interesante pentru viitorii bioinformaticieni.

Ce este un algoritm?

Un algoritm este o secvență de instrucțiuni care trebuie urmarită pentru a rezolva o


problemă bine formulată. Vom specifica problemele în ceea ce privește intrările și ieșirile , iar
algoritmul va fi metoda de transformare a intrărilor în ieșiri. O problemă bine formulată este
precisă şi lipsită de ambiguitate, fără a lăsa loc de interpretare greșită. Pentru a rezolva o
problemă, o entitate trebuie să efectueze pașii specificați de algoritm. Un om cu un pix și
hârtie ar fi capabil să facă acest lucru, dar oamenii sunt în general lenți, fac greșeli și preferă să
nu facă muncă repetitivă. Un computer este mai puțin inteligent, dar poate urmări paşi simplii
fără a face greşeli. Un computer nu poate înțelege limba engleză, deci algoritmii trebuie să fie
reformulați într-un limbaj de programare, cum ar fi C sau Java pentru a oferi instrucțiuni
specifice procesorului. Fiecare detaliu trebuie să fie dat computerului în formatul exact şi
corect, ceea ce face dificil descrierea algoritmilor; detalii minuțioase pe care o persoană le-ar
înțelege în mod natural trebuie să fie specificate. Dacă ar fi trebuit să punem un computer sa se
incalțe, ar fi nevoie să-i spunem să găsească o pereche care se potrivește, să-şi puna pantoful
stâng in piciorul stâng, pantoful drept in piciorul drept şi apoi sa se lege la fiecare.

Natura folosește proceduri asemănătoare algoritmilor pentru rezolvarea problemelor


biologice, ca de exemplu, în procesul de replicare ADN. Înainte ca o celulă să se poată diviza,
trebuie mai întâi să facă o copie completă a întregului material genetic. Refacerea ADN-ului se
desfășoară în etape, fiecare necesitând o cooperare elaborata între diferitele tipuri de molecule.
De dragul simplitatii, descriem procesul de replicare așa cum se întâmplă în bacterii, mai
degrabă decât procesul de replicare la om sau la alte mamifere, care este destul de complicat.
Mecanismul de bază a fost propus de James Watson și Francis Crick la începutul anilor 1950,
dar a putut fi verificat doar prin ingeniosul experiment Meselson-Stahl din 1957. Procesul de
replicare începe de la o pereche de lanțuri complementare de ADN și se termină cu două
perechi. Procesul de duplicare are 7 paşi şi începe cu AND-ul dublu helix reprezentat in figura
urmatoare:

Figura 1. Procesul de duplicare al ADN


Primul pas - O mașină moleculară (cu alte cuvinte, un complex proteic) numită Helicază
ADN, se leagă de ADN la anumite poziții numite origini de replicare.

Figura 2. Helicaza

Al doilea pas - Helicaza desparte cele două lanțuri organice ale ADN-ului, creând o așa-zisă
furculiță de replicare. Cele două lanțuri sunt complementare și se execută în direcții opuse
(una este denumită 3’ → 5’, cealaltă 5’ → 3’). Două alte mașini moleculare, topoizomeraza și
proteina de legare monocatenară (nereprezentată) se leagă la catene pentru a ajuta la
ameliorarea instabilității ADN-ului.

Figura 3. Topoizomeraza

Al treilea pas - Primerii, care sunt secvențe scurte de ARN, sunt sintetizate de un complex
proteic numit primază și se blochează pe poziții specifice în lanțurile nou deschise, furnizând o
ancoră pentru următoarea etapă. Fără primeri, următorul pas nu poate începe.

Figura 4. Categorie de primeri

Al patrulea pas - O polimerază ADN (încă o altă mașină moleculară) se leagă la fiecare catenă
de ADN șablon proaspăt separat. Polimeraza ADN traversează firele părinte numai în direcția
3 → 5. Prin urmare, polimerazele ADN atașate la cele două fire ADN se mișcă în direcții
opuse.
Figura 5. Polimeraza ADN

Al cincilea pas - La fiecare nucleotidă, polimeraza ADN potrivește nucleotida lanțului șablon
cu baza complementară și o adaugă la lanțul sintetizat. Înainte de a trece la următoarea
nucleotidă, polimeraza ADN verifică pentru a se asigura că baza corectă a fost asociată la
poziția curentă. Dacă nu, elimină baza incorectă și reîncercă. Deoarece polimeraza ADN poate
traversa ADN-ul doar in directia 3 → 5 si din moment ce cele doua fire de ADN ruleaza in
directii opuse, numai o catena a ADN-ului template poate fi folosită de polimeraza pentru a
sintetiza continuu complementul; Cealaltă componentă necesită oprire și repornire ocazională.
Acest lucru are ca rezultat segmente scurte numite fragmente Okazaki.

Figura 6. Fragmente Okazaki

Pasul al şaselea - O altă mașină moleculară, ligaza ADN, repara gap-urile din noul ADN
sintetizat, care leagă efectiv toate fragmentele Okazaki într-o singură moleculă și curăță orice
rupturi ale firului primar.

Figura 7. Alte categorii de fragmente Okazaki

Pasul al şaptelea - Când tot ADN-ul a fost copiat într-o astfel de manieră, firele originale se
separă, astfel încât se formează două perechi de fire ADN, fiecare pereche constând dintr-o
catenă veche și una nouă sintetizată.

Figura 8. Separarea firelor orignale


Evident, este necesară o cantitate uluitoare de logistică moleculară pentru a asigura replicarea
completă a ADN-ului: helicaza ADN-ului separă catenele, polimeraza ADN asigură
complementaritatea corespunzătoare și așa mai departe. Cu toate acestea, din punctul de
vedere al logicii procesului, niciuna din aceste mecanisme moleculare complicate nu contează
în realitate - pentru a imita acest proces într-un algoritm, pur și simplu trebuie să luăm un șir
care reprezintă ADN-ul și sa returnăm o copie a acestuia.

2. Alinierea secventelor

Alinierea secvențelor este o procedură fundamentală (implicită sau explicită) efectuată


în orice studiu biologic care compară două sau mai multe secvențe biologice (ADN, ARN sau
proteine). Este procedura prin care se încearcă să se deducă pozițiile (secțiunile) din secvențe
care sunt omoloage, adică secvențele care au o istorie comună evoluționistă. Pentru
majoritatea oamenilor de știință, alinierea este o sarcină a cărei soluție automată a fost
rezolvată cu ani în urmă. Alinierea nu are un interes direct, ci este mai degrabă o etapă
necesară care permite studierea unor probleme mai profunde, cum ar fi identificarea și
cuantificarea regiunilor conservate sau a motivelor funcționale, analiza filogenetică, profilarea
secvenței ancestrale şi predicție. Pentru alți oameni de știință, alinierea este o zonă activă de
cercetare, în care întrebările de bază privind modul în care ar trebui să se construiască și să se
evalueze o aliniere sunt supuse unor analize și dezbateri grele. Deoarece alinierea este primul
pas în multe studii complexe, este important de reținut că algoritmii de aliniere produc o
ipoteză de omologie (la fel cum arborele filogenetic este o ipoteză a istoriei evolutive). Ca și
alte ipoteze, aceste alinieri pot conține mai mult sau mai puțin erori, în funcție de natura
datelor, dintre care unele pot avea efecte uriașe în aval asupra altor analize. Într-un studiu,
majoritatea cercetătorilor susțin că au fost publicate douăzeci sau treizeci de programe și
algoritmi de aliniere. Numărul real este de fapt în sute, numărul crescând în fiecare an. Doar
numărarea programelor numite și nu a unor lucrări care descriu avansuri algoritmice sau
coduri sau programe anonime, a înregistrat o medie de peste cinci programe lansate pe an, cu o
tendință generală de creștere în timp. Următoarea figură arată un rezumat al numărului de
programe de aliniere numite lansate în perioada de 20 de ani din 1986 până în 2005 (algoritmii
de aliniere merg înapoi în 1970, dar înainte de mijlocul anilor 1980 și apariția calculatorului
personal, majoritatea au fost pur și simplu publicate ca logice descrieri sau ca sursă, mai
degrabă decât ca executabile compilate).
Figura 8. Algoritmi dezvoltați pentru alinierea secvențială odată cu trecerea timpului

2.1 Alinierea în perechi și programarea dinamică

Pentru a putea compara alinierile posibile ale secvențelor, trebuie să determinăm o


valoare (sau scor) care estimează calitatea fiecărei alinieri. Formulele din spatele unui scor de
aliniere sunt cunoscute în general ca funcții obiective. Ele variază de la sume simple cost-
beneficiu până la valori complexe de probabilitate maximă.

Atunci când se folosește o abordare cost-beneficiu pentru evaluarea unei aliniere în


perechi, trebuie să se precizeze scorurile pentru diferitele moduri în care se poate compara o
pereche de secvențe. În cel mai simplu caz, se specifică trei scoruri: (1) beneficiul alinierii
unei perechi care conține același caracter în ambele secvențe (potrivire); (2) costul de aliniere
a unei perechi care conține caractere diferite în secvențe (nepotrivire); (3) costul alinierii unui
caracter într-o singură secvență, cu un decalaj în cealaltă secvență (gap). În funcție de modul
în care se definesc scorurile, obiectivul final ar putea fi acela de a găsi alinierea care
maximizează beneficiul sau pentru a găsi alinierea care minimizează costul. Aceasta este, în
esență, o alegere arbitrară, bazată pe modul în care alegem să definim costurile și beneficiile.
Multe dintre programele de aliniere populare utilizate astăzi (de exemplu, ClustalW) găsesc
scorul maxim, o convenție care va fi păstrată pe parcursul acestei descrieri. În domeniul
informaticii, o funcție simplă de notare bazată pe cost este distanța de editare, adică numărul
minim de modificări necesare pentru a converti o secvență în alta. În acest caz, obiectivul
alinierii este de a minimiza distanța de editare.

Având un tabel de scor, se poate compara orice set de aliniamente pentru același set de
secvențe inițiale. Cel care are cel mai bun scor va fi considerat cea mai bună aliniere. De
exemplu, stabilim costul pentru o potrivire +1, costul unei nepotriviri la -3 și costul unui gap
de -4. Figura următoare prezintă două alinieri posibile ale secvențelor ACCTGATCCG și
ACTGATCAG. În prima aliniere posibilă există 8 potriviri (8*(+1) = 8), o nepotrivire
(1*(-3) = -3) și un gap (1*(-4) = -4), ceea ce inseamna un scor total de +1. În cea de-a doua
aliniere posibilă, există 5 potriviri (+5), 4 nepotriviri (-12) și un gap (-4), cu un scor total de
-11. Prima aliniere are un scor mai mare decât cel de-al doilea și ar fi considerat o aliniere mai
bună. Dar cum știm că este cea mai bună posibilă aliniere?

Figura 9. Exemplu de scor în urma alinierii secvențiale

Este imposibil să se evalueze toate alinierile posibile. Luați cazul simplu în care o
secvență de 100 de caractere este aliniată cu o secvență de 95 de caractere. Dacă tot ceea ce
facem este să adăugăm 5 gap-uri la cea de-a doua secvență (pentru a o aduce la 100 de
caractere totale), există aproximativ 55 de milioane de alinieri posibile. Deoarece este posibil
să fie nevoie să adăugăm gap-uri la ambele secvențe, numărul efectiv de aliniamente posibile
este semnificativ mai mare.

Numărul de alinieri potențiale a făcut proceduri automatizate pentru alinierea


secvențelor, un aspect critic al comparării secvențelor moleculare. Primele încercări de a
dezvolta o metodă computațională de aliniere a secvențelor au fost întreprinse la mijlocul
anilor '60 cu studii precum cele ale lui Fitch (1966) și Needleman și Blair (1969), dar în 1970,
prima soluție elegantă fost produsă la problema alinierii (Needleman și Wunsch 1970).
Această soluție, utilizând programarea dinamică, a făcut ca procedura să fie părintele tuturor
algoritmilor de aliniere.

Programarea dinamică este o abordare computațională a rezolvării problemelor care, în


esență, rezolvă problema invers. Programarea dinamică este ilustrată cel mai bine cu un
exemplu matematic simplu, de exemplu calcularea valorii n a unei secvențe Fibonacci.
Secvența Fibonacci este o serie de numere în care fiecare valoare este egală cu suma celor
două valori ce o preced, 𝐹𝑛 = 𝐹𝑛−1 + 𝐹𝑛−2 (prin definiție trebuie să fie specificate primele
două valori ale secvenței). Astfel, pentru a calcula a 10-a valoare a secvenței Fibonacci,
trebuie să cunoaștem valorile 8 și 9; Pentru a calcula a 9-a valoare, trebuie să cunoaștem
valorile 7 și 8; Pentru a calcula a opta valoare trebuie să cunoaștem valorile 6 și 7; si asa mai
departe. Deși nu este deosebit de dificil să se rezolve această problemă cu un algoritm recursiv
simplu, găsirea celei de-a cincea valori printr-o abordare recursivă este foarte ineficientă.
Rețineți că, dacă fiecare valoare este determinată independent, este necesar să se calculeze
aceeași valoare mai mult decât o singură dată (de exemplu, calcularea valorilor 9 și 8 necesită
calcularea celei de-a șaptea valori). Folosind un algoritm recursiv standard, determinarea celei
de-a zecea valori a secvenței Fibonacci ar necesita 109 pași. Complexitatea formală a abordării
recursive a secvenței Fibonacci este exponențială. O abordare dinamică de programare, pe de
altă parte, este mai simplă și mai eficientă. Problema funcționează în direcția opusă abordării
recursive pornind de la prima valoare din secvență, mai degrabă decât în a șaptea valoare. În
secvența Fibonacci, primele două valori trebuie să fie predefinite. Pentru acest exemplu vom
seta prima valoare 0 și a doua valoare 1. Având în vedere primele două valori, putem
determina cu ușurință valoarea 3 (0 + 1 = 1). Valoarea a 4-a este suma celor deja determinate,
a doua valoare și a treia valoare și, prin urmare, este 1 + 1 = 2. În acest moment este banal să
continuăm să mergem înainte până când ajungem la a 10-a valoare (a 5-a valoare = 1 + 2 = 3,
a 6-a valoare = 2 + 3 = 5; = 3 + 5 = 8; valoarea a 8-a = 5 + 8 = 13; valoarea 9 = 8 + 13 = 21; a
10-a valoare = 13 + 21 = 34). Prin evitarea determinării redundante a valorilor inferioare,
abordarea dinamică de programare are doar 10 pași. Adică, complexitatea este liniară,
necesitând numai n pași.

Alinierea secvenței în perechi este mai complicată decât calculul secvenței Fibonacci,
însă este implicat același principiu. Scorul de aliniere pentru o pereche de secvențe poate fi
determinat recursiv prin ruperea problemei în combinația de caractere unice la sfârșitul
secvențelor și subsecvențele lor aliniate optim. Dacă secvențele x și y au m și n caractere,
ultima poziție a alinierii lor poate avea trei posibilități: xm și yn sunt aliniate, xm este aliniat
cu un gap cu yn undeva în urmă sau yn este aliniat cu un gap cu xm undeva în urmă. Scorul de
aliniere pentru fiecare caz este scorul pentru poziția finală plus scorul alinierii optime a
secvenței din urmă (fiecare loc este marcat independent, astfel încât scorul segmentelor de
aliniere poate fi adăugat pentru un scor total). Scorul general optim este maximul scorului
pentru cele trei cazuri. Critic, scorul optim pentru fiecare dintre subsecvențele aliniate poate fi
determinat în același mod: trei cazuri posibile pentru poziția finală plus alinierea optimă a
subsecvenței în amonte pentru fiecare caz. Astfel, o formulă pentru scorul de aliniere optimă
poate fi scrisă într-un format simplu recursiv:

𝑆(𝑖 − 1, 𝑗 − 1) + 𝜎(𝑥𝑖 , 𝑦𝑗 )
𝑆(𝑖, 𝑗) = 𝑚𝑎𝑥 { 𝑆(𝑖 − 1, 𝑗) + 𝛾
𝑆(𝑖, 𝑗 − 1) + 𝛾

Figura 10. Exemplu de formula de scoring

unde S (i, j) este scorul pentru alinierea optimă de la poziția 1 la i în secvența x și de la 1 până
la j în secvența y, g este costul gap-ului și s (𝑥𝑖 ,𝑦𝑗 ) este scorul de potrivire/nepotrivire pentru
perechi la pozițiile 𝑥𝑖 şi 𝑦𝑗 .

Deși este ușor de scris, această formulă este foarte ineficientă pentru rezolvare și, ca și în cazul
secvenței Fibonacci, duce la o determinare redundantă a punctajului optim pentru alinierile
subsecvențelor care vor apărea din nou și din nou. Soluția de programare dinamică
funcționează pornind de la alinierea optimă a celor mai mici subsecvențe posibile (nimic în
secvență x aliniat la nimic în secvența y) și determinarea progresivă a scorului optim pentru
secvențe mai lungi și mai lungi prin adăugarea de caractere una câte una. Urmărind scorul
optim pentru fiecare subsecvență posibilă aliniată într-o matrice, scorul optim și alinierea
secvențelor complete pot fi ușor și eficient determinate.

Această metodă este ilustrată în următoarele figuri cu alinierea unei perechi de


secvențe scurte: ATG și GGAATGG, utilizând un scor de potrivire de +1, un scor de
nepotrivire de -1 și un scor de gap de -2. Primul pas este de a construi o matrice care conține
fiecare secvență de-a lungul unei axe, cu un rând și o coloană liberă la partea superioară și la
stânga a matricei. Fiecare celulă din matrice va fi completată cu maximul a trei valori posibile:
(1) suma scorului dintre celula de pe diagonală în stânga sus și scorul de potrivire sau de
nepotrivire (în funcție de faptul dacă caracterele din rând-coloană se potrivesc sau nu); (2)
suma punctajului celulei de deasupra și scorul gap-ului; Sau (3) suma punctajului celulei din
stânga și scorul gap-ului. (Există în esență o regulă ascunsă care permite să sări peste orice
regulă care nu se aplică, de exemplu, celulele din rândul de sus nu au celule deasupra lor, deci
regula 2 nu se poate aplica). Rezultatul practic al acestor reguli este că primul pas este să
plasați un zero în colțul din stânga sus al matricei și apoi să umpleți primul rând și coloana cu
creșteri multiple ale costului gap-ului. Restul celulelor din matrice sunt completate una câte
una. Un punct important este acela că trebuie urmărit ce regulă a fost aplicată, adică, ce celulă
vecină (diagonală, deasupra sau stânga) a condus la valoarea care a fost introdusă. În mod
computațional aceasta este stocată într-o a doua matrice numită matrice de urmărire; În figurile
următoare acest lucru este ilustrat cu săgeți pentru simplitate. Un al doilea punct important
este faptul că este posibil ca mai multe reguli să producă valoarea maximă identică; Într-un
astfel de caz, matricea de urmărire ar trebui să includă în mod corespunzător toate căile
posibile la valoarea maximă.
Creerea matricei Primul rând și prima coloană sunt completate
cu multiplicări crescătoare ale costului
gap-ului. Primei celule i se va da
maximul dintre cele trei valori posibile.

Se introduce valoarea primei celule Se introduce valoarea pentru a doua celulă;


împreună cu calea care a condus la valoare. Mai multe căi sunt înregistrate, deoarece mai
Valorile posibile pentru a doua multe căi au condus la scorul maxim.
celulă sunt ilustrate.
Matricea completă Matricea finalizată cu toate căile suboptimale
eliminate. Urmărirea săgeților din colțul din
dreapta jos în stânga sus duce la patru căi
posibile și (prin urmare) patru aliniamente la
fel de optime.

Figura 11. Modul de completare al matricii în alinierea globală

În exemplul nostru, prima celulă (A vs G) poate avea trei valori: (1) scorul celulei din
stânga-sus 0, plus costul de nepotrivire (A / G este o nepotrivire), 0 + (-1) = -1; (2) scorul
celulei de deasupra lui, -2, plus scorul decalajului, -2 + (-2) = -4; Sau (3) scorul celulei din
stânga, -2, plus scorul decalajului, -2 + (-2) = -4. Maximul acestora este primul scor, -1, care
este introdus în celulă, împreună cu o săgeată spre stânga sus pentru a ne reaminti că este acea
cale din care a rezultat scorul. Repetăm pentru celula următoare (la dreapta). Valorile posibile
pentru această celulă sunt -2 + -1 = -3, -4 + -2 = -6 sau -1 + -2 = -3. Valoarea maximă este de
-3, dar acest lucru poate fi obținut din două căi separate, așa că înregistrăm ambele căi folosind
săgețile de urmărire.

Această procedură se repetă până când întreaga matrice este completată cu valori.
Valoarea din ultima celulă, din dreapta jos (-5 în exemplul nostru), reprezintă scorul celei mai
bune alinieri (având în vedere funcția de scor). Pentru a găsi această aliniere, începe cu această
celulă și urmează săgețile înapoi în colțul din stânga sus al matricei. În urma unei săgeți
diagonale se indică faptul ca acele caractere reprezentate de acel rând și coloana matricei ar
trebui aliniate. În urma unei săgeți verticale se indică faptul că acel caracterul din secvența
de-a lungul axei verticale (caracterul reprezentat de rândul matricei) trebuie aliniat cu un gap
în secvența reprezentată de axa orizontală. În urma unei săgeți orizontale se indică faptul că
acel caracter din secvența de-a lungul axei orizontale (caracterul reprezentat de coloana
matricei) trebuie aliniat cu un gap în secvența reprezentată de axa verticală.
Dacă există mai multe căi posibile înapoi spre partea superioară a matricei, acest lucru
indică faptul că mai multe aliniere în perechi duc la scorul identic și sunt la fel de optime. În
exemplul nostru, există patru căi posibile, care conduc la patru alinieri posibile ale acestor
secvențe, prezentate în figura următoare:

Figura 12. Exemplu de aliniere prin metoda Trace-Back

În acest caz specific, s-ar putea argumenta că primul dintre acestea pare să fie o
aliniere mai bună decât celelalte, însă, bazându-se exclusiv pe tabelul de cost specificat, toate
cele patru aliniamente sunt la fel de bune (fiecare dintre aceste alinieri conține trei potriviri și
patru gap-uri). Schimbarea punctajelor poate schimba rezultatul (vezi mai jos). Foarte puține
programe de aliniere produc mai mult de o aliniere, chiar dacă există mai multe aliniamente la
fel de optime; Algoritmii “sim” ai lui Huang (1990) și Huang și Miller (1991) sunt o excepție
notabilă. Modul în care singura aliniere rezultantă produsă de majoritatea programelor este
aleasă din universul posibil alinierilor optime nu este, de obicei, clar.

Aceasta este cea mai simplă abordare a alinierii succesive a perechilor. Îmbunătățirile
vizibile includ utilizarea unor funcții de notare mai complicate. Nu toate neconcordanțele sunt
în mod necesar egale, iar diferite tipuri de neconcordanțe ar putea da scoruri diferite, în funcție
de proprietățile caracterelor. Pentru secvențele ADN, aceste scoruri diferențiale s-ar putea baza
pe modele standard de evoluție a secvenței. De exemplu, este bine cunoscut faptul că
substituțiile tranzitorii apar mai des decât substituțiile transversale, prin urmare, o nepotrivire
transversală ar putea avea un cost mai mare decât o nepotrivire tranzitorie. Pentru secvențele
de proteine, matricele de substituție derivate empiric sunt de obicei folosite pentru a determina
costurile relative ale diferitelor neconcordanțe. Aceste matrici includ matricile PAM (Dayhoff,
1978), JTT (Jones, 1992) și BLOSUM (Henikoff și Henikoff 1992). Aceste matrici includ, de
obicei, factori biologici estimați, cum ar fi conservarea, frecvența și modelele evolutive ale
aminoacizilor individuali. În principiu, s-ar putea să ne imaginăm că oferim beneficii diferite
diferitelor potriviri (de exemplu, poate că un avantaj mai mare ar trebui să fie aducerea unei
alinieri a unei perechi de resturi de cisteină din cauza constrângerilor extreme și a
constrângerilor structurale ale acestui aminoacid).

O altă îmbunătățire a funcției de notare are de a face cu costurile gap-ului. După cum
este descris mai sus, toate gap-urile sunt tratate ca evenimente identice de poziție. Din punct
de vedere biologic, recunoaștem că evenimentele singulare de inserție-ștergere pot (și de multe
ori fac) să acopere mai multe caractere. Prin urmare, este posibil să nu ne dorim ca acel cost al
gap-ului care acoperă trei spatii să tripleze costul unui gap care acoperă doar un singur spatiu
(un cost liniar). Soluția generală constă în folosirea unui scor de cost pentru deschiderea unui
gap și a unui al doilea punctaj pentru extinderea (prelungirea) unui gol (un cost de afinitate)
(Altschul și Erickson 1986; Gotoh 1982, 1986; Taylor 1984). În acest caz, costul total al gap-
ului este O + nE unde O este costul de deschidere a gap-ului, E este costul prelungirii
diferenței și n este lungimea intervalului (sau lungimea extensiei, în funcție de modul în care
algoritmul este definit). Sunt posibile scheme mult mai complicate de marcare a decalajelor de
lungimi diferite, deși majoritatea programelor moderne de aliniere par să utilizeze o formă de
structură a costurilor afine. Unii algoritmi vor varia, de asemenea, în modul în care tratează
lacunele terminale (adică lacunele care apar la începutul sau la sfârșitul unei secvențe); Unii
algoritmi vor da acest cost redus (chiar zero), deoarece nu se poate deduce că apar între
caracterele observate (acest lucru este uneori cunoscut sub numele de aliniere semi-globală).

În exemplul anterior, utilizarea unui cost de gap afin ar elimina alinierea a treia și a
patra din figura anterioară din setul optim, deoarece acestea au fiecare câte trei goluri
independente (cu lungimea 2, 1 și 1), în timp ce primele două alinieri au doar două goluri (de
lungime 3 și 1). Scăderea costului golurilor terminale ar elimina apoi a doua aliniere, deoarece
unul dintre decalaje este intern pentru caracterele observate, în timp ce alinierea inițială
conține numai goluri terminale. Dincolo de schimbările în modul de aliniere, s-au înregistrat
numeroase îmbunătățiri în eficiența abordării de bază dinamice de programare descrise mai
sus, inclusiv, de exemplu, scăderea cerințelor de memorie (Myers și Miller 1988) și numărul
de etape de calcul (Gotoh 1982).

2.2 Alinieri globale vs. alinieri locale

Procedura descrisă până acum este un algoritm de aliniere globală; Adică presupune că
toate secvențele sunt omoloage și încearcă să alinieze toate caracterele în mod optim în cadrul
secvențelor. Această presupunere poate fi incorectă ca rezultat al rearanjării secvențelor pe
scară largă și al schimbării genomului. Într-un astfel de caz, numai subsecțiunile secvențelor
pot fi omoloage, sau secțiunile omoloage pot fi într-o ordine diferită. De exemplu, o secvență
lungă poate fi comandată ABCDEF (unde fiecare literă reprezintă o secțiune de secvență și nu
un caracter individual). O inversiune de secvență a secțiunii CDE poate schimba secvența
dintr-o altă specie la ABEDCF. Deși fiecare secțiune din prima secvență este omologă cu o
secțiune din secvența a doua, ele nu pot fi aliniate global, din cauza rearanjării. Figura
următoare prezintă aliniamente globale posibile dacă secțiunea C, D sau E este aliniată. În
fiecare caz, celelalte două secțiuni nu pot fi aliniate corect.

Figura 13. Tipuri de alinieri globale


O abordare alternativă a alinierii globale este alinierea locală. Într-o aliniere locală,
subsecțiunile secvențelor sunt aliniate fără referire la modelele globale. Aceasta permite
algoritmului să alinieze regiuni separat, indiferent de ordinea generală din cadrul secvenței, și
să alinieze regiuni similare, permițând regiunilor foarte divergente să rămână nealiniate.

Abordările timpurii pentru alinierea locală au fost dezvoltate de Sankoff (1972) și


Sellers (1979, 1980), dar procedura de aliniere locală de bază cea mai răspândită a fost
propusă de Smith și Waterman (1981). Este o simplă adaptare la algoritmul standard
Needleman-Wunsch. Prima diferență constă în determinarea valorilor pentru o celulă. Pe lângă
cele trei valori posibile descrise de algoritmul Needleman-Wunsch, algoritmul de aliniere
locală permite o a patra valoare posibilă: zero. Acest lucru împiedică scorul de aliniere să
devină negativ; Dacă această regulă este invocată, nu este salvată nici o săgeată de urmărire
pentru celulă. Figura următoare prezintă matricea scorului pentru o aliniere locală pentru
aceleași secvențe care au fost aliniate global în figura de mai sus. Adăugarea celei de a patra
reguli modifică în mod substanțial structura scorurilor și săgețile de urmărire.

Figura 14. Matricea alinierii locale

Odată ce matricea a fost finalizată, cea de-a doua modificare a algoritmului de aliniere locală
este că, mai degrabă decât pornirea în colțul din dreapta jos al matricei, se folosește celula cu
cea mai mare valoare ca poziție de pornire pentru trace-back. În exemplul nostru, aceasta este
celula direct deasupra coltului jos-dreapta, cu un scor de 3. Diferența finală în această metodă
este aceea că trace-back-ul nu continuă în colțul din stânga sus, ci mai degrabă se termină când
săgețile se termină. Rezultatul acestei proceduri este că numai o porțiune din secvențe poate fi
aliniată; Restul secvențelor sunt lăsate nealiniate. Pentru acest exemplu, alinierea locală este
pur și simplu cea prezentată în figura următoare.

Figura 15. Tip de alinere locală

Sunt raportate numai părțile aliniate ale secvențelor. Desigur, ar putea fi găsite
aliniamente locale suplimentare ale secvențelor dacă există mai multe celule cu același punctaj
maxim sau prin alegerea punctelor de plecare submaximale. Ca și în cazul alinierii globale, s-
au înregistrat progrese majore în abordările de aliniere locală; Programele majore de aliniere
locală și algoritmii utilizați astăzi includ DIALIGN (Morgenstern 1999; Morgenstern, Frech et
al. 1998) și CHAOS (Brudno, Chapman și colab., 2003; Brudno și Morgenstern 2002).

Cu o revoluție recentă de secvențiere, o provocare a bioinformaticii a fost compararea


secvențelor genomului complet. Deoarece genomul este atât de ușor de rearanjat, alinierea
genomilor întregi este un caz specializat de aliniere locală aplicată la scară foarte largă. Multe
programe specializate de producere a alinierii locale a genomului intreg au fost produse recent,
incluzând BlastZ (Schwartz et al., 2003), MUMMER (Delcher et al., 1999; Delcher et al.
2002), GLASS (Batzoglou et al. 2000) (Kent și Zahler 2000), MAUVE (Darling et al., 2004),
GRAT (Kindlund et al., 2007), MAP2 (Ye și Huang 2005) și AuberGene (Szklarczyk și
Heringa 2006).

2.3 Aliniere locală vs. Căutarea in baza de date

O mare parte din lucrul la alinierea locală s-a concentrat pe căutarea în baza de date,
mai degrabă decât pe compararea simplă a secvențelor. S-a recunoscut foarte devreme că
algoritmii ar fi necesari pentru a prelua secvențe dintr-o bază de date cu un model similar cu
cel al unei secvențe de interogare (de exemplu, Korn și colab., 1977). Compararea secvențelor
pentru modele similare necesită, într-o anumită formă, alinierea locală, iar metodele locale de
aliniere formează baza tuturor algoritmilor de căutare în baza de date. Cel mai cunoscut
algoritm de căutare a secvențelor, BLAST (Altschul et al., 1990), conține această expresie în
numele său: Instrumentul de căutare pentru alinierea locală (Basic Local Alignment Search
Tool). Necesitatea muncii majore privind alinierea locală derivă din interesul în căutarea în
baza de date, în special în dezvoltarea familiei de algoritmi BLAST și FASTx (Lipman și
Pearson 1985; Pearson și Lipman 1988).
2.4 Importanța tabelului de scor

Algoritmii descriși mai sus permit căutarea unei populații de alinieri posibile în mod
eficient pentru cele mai optime alinieri, dar este cea mai importantă funcție de cost pentru a
determina cea mai bună aliniere reală. Așa cum s-ar aștepta, schimbarea costului poate
schimba care aliniere este considerată a fi cea mai optimă. Luați, de exemplu, perechea de
secvențe CAGCCTCGCTTAG și AATGCCATTGACGG. Dacă efectuăm alinierea globală și
locală a acestor secvențe folosind parametrii ca înainte (+1 potrivire, -1 nepotrivire, -2 gap),
găsim patru aliniamente globale la fel de optime, prezentate în figura A (singura diferență este
poziția gap-ului din a doua secvență) și o aliniere locală (figura B).

Figura 16. Exemple de aliniere locală

Dacă vom schimba parametrii tabelului nostru de cost, astfel încât beneficiul potrivirii
să fie încă +1, dar costul de nepotrivire este acum -0.3 și costul gap-ului este -1.3, s-ar găsi
aceleași patru aliniamente globale, dar alinierea noastră locală se va schimba la cea indicată în
figura următoare. Seturi diferite de valori de punctaj pot duce la alinierea optimă diferită; Cea
mai bună aliniere nu depinde doar de algoritm (global vs. local), ci de parametrii.

Figura 17. Exemple de aliniere locală, alte variante

Cum determinăm ce valori trebuie utilizate pentru tabelul de cost? Majoritatea


utilizatorilor tind să utilizeze setările implicite ale programului, caz în care problema stabilirii
valorilor corecte este lăsată doar autorilor programului și nu utilizatorului. Trebuie notat că
magnitudinea absolută a valorilor nu este importantă; Este valoarea relativă care contează
(adică înmulțirea tuturor scorurilor cu o constantă nu va afecta cea mai bună aliniere
rezultantă). Așa cum am menționat anterior, valorile relative de potrivire și nepotrivire sunt de
obicei determinate din matricele de substituție empirice (pentru proteine) sau modelele de
evoluție a secvenței pentru ADN.
Cu toate acestea, valoarea cea mai importantă în clasarea alinierilor este adesea
considerată a fi raportul dintre costul de nepotrivire și costul gap-ului (o funcție mai complexă
poate include costuri diferite de nepotrivire și costuri de gap, dar principiul general rămâne în
continuare). Valorile din exemplul de mai sus indică faptul că un gap este de două ori mai
costisitor decât o nepotrivire. Ar putea însemna că mutațiile punctuale apar de două ori la fel
de des ca și evenimentele de inserție / ștergere; Cu toate acestea, din punct de vedere biologic
știm că indelii (inserțiile/ştergerile) tind să fie mult mai rari decât mutațiile punctuale. Există
date remarcabil de mici privind raportul observat între evenimentele indel și mutațiile
punctuale. Pentru ADN, indelii par să fie de aproximativ 12 până la 70 de ori mai puțin
întâlniți decât mutațiile punctuale, în funcție de divergențele evolutive examinate (Mills,
Luttig și colab., 2006, Ophir și Graur 1997, Sundström et al 2003). S-ar aștepta ca secvențele
de proteine să aibă un raport diferit. Este ușor de imaginat modul în care se poate forța o
aliniere optimă să fie mai mult sau mai puțin "gappy" prin manipularea costului de gap: un
cost foarte ridicat al decalajului va crește numărul de nepotriviri și va reduce numărul de
decalaje în alinierea optimă, în timp ce costul redus al golurilor va reduce numărul de
nepotriviri și va spori numărul de goluri.

În plus, se pare că există un pic de discrepanță între raportul biologic al mutațiilor


punctuale și indelii și structura costului real utilizat în aliniere. Evaluarea subiectivă a
alinierilor produse cu rapoarte de cost diferite, precum și examinarea obiectivă a reperelor
empirice și simulate (nepublicate) tind să afirme că aceste costuri de decalaj care produc cele
mai bune alinieri (cele care se aseamănă cel mai mult cu alinierea reală) sunt de obicei mai
mici decât cele care ar putea fi prognozate dintr-o evaluare directă a ratelor reale de mutație.
Metodele de optimizare a costurilor de decalaj (precum și alte aspecte ale funcției de cost) și
efectele acestora reprezintă un aspect subestimat al alinierii secvențelor.

3. Alinieri multiple

Până în acest moment, algoritmii descriși au fost pentru compararea perechilor de


secvențe. În general, suntem adesea interesați să aliniem mai mult de două secvențe (numite
alinieri multiple). În principiu, se poate folosi o abordare Needleman-Wunsch pentru mai mult
de două secvențe (de exemplu, construirea unei matrice cubice tridimensionale pentru trei
secvențe) (Jue et al., 1980, Murata și colab., 1985), dar acest lucru devine rapid computațional
imposibil de rezolvat și neefectuat ca urmare a constrângerilor în puterea și memoria
computațională.

Abordările alternative pentru alinierea multiplă au necesitat un arbore filogenetic


cunoscut. Sankoff et al. (Sankoff și colab., 1973, Sankoff 1975, Sankoff și colab., 1976) au
dezvoltat abordări bazate pe parsimonie. Waterman și Perlwitz (1984) au sugerat o abordare
alternativă care folosea medierea ponderată. În locul folosirii unui arbore cunoscut, Hogeweg
și Hesper (1984) au sugerat o metodă iterativă care începe cu un arbore presupus, aliniază
datele, utilizează alinierea pentru a estima un arbore nou și apoi utilizează noul arbore pentru a
realinia datele și așa mai departe.

Abordarea pentru alinierea mai multor secvențe care în cele din urmă a prins este
cunoscută sub denumirea de aliniere progresivă (Feng and Doolittle 1987, 1990). În alinierea
progresivă, se pornește în general prin construirea tuturor aliniamentelor posibile (pentru n
secvențe, există perechi n*(n-1)/2 ). Aceste alinieri în perechi sunt folosite pentru a estima un
arbore filogenetic utilizând un algoritm bazat pe distanțe, cum ar fi metoda unweighted pair
group method with arithmetic mean (UPGMA) sau îmbinarea vecinilor. Folosind arborele ca
ghid, cele mai asemănătoare secvențe sunt aliniate una cu alta folosind un algoritm de perechi.
Unul adaugă apoi succesiv secvențe la aliniere, câte o secvență, pe baza structurii arborelui
filogenetic. Numeroase programe de aliniere multiple s-au bazat pe o adaptare progresivă de
aliniere a algoritmului Needleman-Wunsch, inclusiv ClustalW (Thompson et al., 1994),
probabil cel mai utilizat program de aliniere multiplă globală.

Spre deosebire de algoritmul pereche, algoritmii de aliniere multiplă sunt mai degrabă
euristice decât soluții exacte; Prin căutarea numai a unui subset al populației de aliniamente,
ele găsesc eficient o aliniere care este aproximativ optimă, dar nu este garantată ca fiind cea
mai optimă aliniere posibilă pentru funcția de cost dată. De exemplu, un dezavantaj general al
abordării de aliniere progresivă este cunoscut ca un algoritm greedy; Orice greșeli care se fac
în etapele timpurii ale procedurii nu pot fi corectate prin pași ulteriori. De exemplu, luați cazul
cu trei secvențe scurte a căror aliniere optimă este prezentată în figura A. Presupunând că
arborele de ghidare indică faptul că ar trebui să începem prin alinierea secvențelor 1 și 2,
există trei alinieri posibile cu același scor (o nepotrivire transversală și un gap), prezentate în
figura B. La adăugarea secvenței 3, poziția gap-ului nu poate fi modificată. Astfel, adăugarea
secvenței 3 ar putea conduce la trei alinieri multiple posibile, prezentate în figura C, dintre
care numai prima este optimă. În prima etapă, numai una dintre cele trei aliniamente poate fi
utilizată pentru următoarea etapă, iar dacă este aleasă greșit, rezultatele finale nu vor fi soluția
cea mai optimă.

Alinierea multipla optima a celor 3 secvente


Cele trei posibile alinieri optime care ar fi construite în prima etapă a alinierii, în funcție de ce
perechi au fost alese să fie aliniate în primul rând

Aliniamentele multiple rezultate din fiecare dintre cele trei puncte de pornire din figura B.
Numai una dintre ele este egală cu alinierea optimă reală ilustrată în A.

Figura 18. Exemple de alinieri multiple

Un număr de algoritmi mai puțin lacomi au fost proiectați pentru a încerca să


depășească această problemă. De exemplu, T-Coffee (Notredame et al., 2000) începe prin
utilizarea alinierilor locale în perechi pentru a găsi regiuni cu grad mare de similaritate. Deși o
aliniere progresivă de bază este folosită pentru a produce alinierea multiplă globală, aceste
alinieri locale au un efect asupra scorului relativ la etapele progresive timpurii și pot ajuta la
evitarea erorilor care altfel ar fi introduse în alinierea multiplă. O altă abordare este utilizarea
metodelor iterative în care alinierea generată de o singură trecere a unui algoritm este folosită
pentru a construi un nou arbore de ghidare, care poate fi apoi utilizat pentru a forma o nouă
aliniere. Unele dintre cele mai cunoscute programe de aliniere iterativă includ MultAlin
(Corpet 1988), PRRP (Gotoh 1996) și DIALIGN (Morgenstern 1999; Morgenstern, Frech și
colab., 1998).

4. Algoritmi utilizați în alinierea secvențială


4.1 Aliniere Globala (Algoritmul Needleman-Wunsch)

Să presupunem că vrem să aliniem două secvențe S și T cu S = ACGT și T =


ACGGCT. Se folosește o schemă de punctare simplă, cu o pedeapsă de gap constantă (G) de -
2, un scor de potrivire (M) de 2 și un scor de nepotrivire (MM = -1). Alinierea globală cu
abordarea dinamică de programare este ilustrată numeric în figura următoare. O secvență
dintre cele două ocupă rândul de sus și va fi denumită secvența de linie (secvența S din
exemplul nostru). Cealaltă secvență ocupă prima coloană și va fi numită secvența de coloană
(secvența T din exemplul nostru). Pe baza acestor două secvențe, se creează două matrice.
Prima este matricea de punctaj pentru a obține scorul de aliniere, cu dimensiunile (n + 1, m +
1). A doua este matricea backtrack necesară pentru obținerea alinierii efective, cu dimensiunile
(n, m). În figura următoare, cele două matrice sunt suprapuse, matricea de punctare fiind
numerele și matricea backtrack fiind realizată din săgeți. Matricea backtrack este uneori
numită matricea traceback.

O valoare în linia i și coloana j în matricea de punctare este scorul de aliniere dintre un prefix
al lui S și un prefix T, adică 𝑆𝑗 și 𝑇𝑖 . Acest lucru va deveni clar mai târziu.

Primul rând și prima coloană a matricei de notare sunt umplute cu i × G (unde i = 0, 1, ..., n),
respectiv j × G (unde j = 0, 1, ..., m). Acestea reprezintă inserarea consecutivă a gap-urilor. De
exemplu, numărul -8 din ultima celulă a primului rând al matricei de notare implică
următoarea aliniere cu patru decalări consecutive în secvența de coloană și un scor de aliniere
de -8:

În mod similar, numărul de -12 din ultima celulă din prima coloană a matricei de notare
implică următoarea aliniere cu șase gap-uri consecutive pe secvența de linie și un scor de
aliniere de -12:
Figura 19. Matricea algoritmului Needleman-Wunsch

Prima celulă în care trebuie să calculăm scorul este cea care corespunde primului
caracter S și T, adică celula cu valoarea 2. Pentru a calcula valoarea pentru celulă, avem
nevoie de valori în alte trei celule, una la stânga, una deasupra ei și una la diagonală stânga-
sus, cu valorile lor de celule desemnate ca L (left), U (up) și, respectiv, UL (up-left). Rețineți
că celula are o valoare de UL egala cu 0, o valoare de U egală cu -2 și o valoare de (L) egală
cu -2. Se calculează următoarele trei valori:

𝐷𝐼𝐴𝐺 + 𝐼𝐹(𝑀 𝑜𝑟 𝑀𝑀) = 0 + 2 = 2 (𝑀 = 𝑚𝑎𝑡𝑐ℎ; 𝑀𝑀 = 𝑚𝑖𝑠𝑚𝑎𝑡𝑐ℎ)


𝑀𝐴𝑋 { 𝑆𝑡â𝑛𝑔𝑎 = 𝐿 + 𝐺 = −2 + (−2) = −4
𝑆𝑢𝑠 = 𝑈 + 𝐺 = −2 + (−2) = −4

Figura 20. Aparatul matematic al algoritmului Needleman-Wunsch

Funcția IF de mai sus ia valoarea lui M dacă cele două nucleotide corespondente se
potrivesc sau MM dacă nu. Maximul acestor trei valori este DIAG, adică 2, care a fost
introdus ca primul element calculat în matricea de punctare. Celula este, de asemenea, umplută
cu o săgeată pe diagonala stânga-sus deoarece DIAG este maximul celor trei valori. Dacă
LEFT (sau UP) ar fi maximul celor trei, am fi pus o săgeată stânga (sau sus) în celula
corespunzătoare din matricea backtrack.

Calculul este de la stânga la dreapta și de sus în jos. Pentru cea de-a doua celulă,
maximul celor trei valori este LEFT (= 0), iar celula corespunzătoare din matricea backtrack
este umplută cu o săgeată îndreptată spre stânga. Continuăm calculul până la celula din
dreapta jos, unde valoarea finală este egală cu 4. Acesta este scorul de aliniere. Puteți observa
că celula corespunzătoare nucleotidului G în secvența liniei și celui de-al doilea G din
secvența coloanei este specială cu două săgeți. Veți găsi că valorile DIAG și UP sunt ambele
egale cu 4 în această celulă. Prin urmare, această celulă va conține si sageata spre UL cat si
spre U. O astfel de celulă presupune existența unor alinieri la fel de optime.

Secvențele aliniate sunt obținute direct din matricea backtrack. Începem din celula din
dreapta jos și urmăm direcția săgeții din celulă. Săgeata UL din celula din dreapta-jos
înseamnă că trebuie să aliniem cele două nucleotide corespunzătoare (T și T) în secvențele
liniei și coloanei. Rețineți că ați fi suprapus cele două nucleotide corespunzătoare, indiferent
dacă acestea sunt aceleași sau diferite, atâta timp cât o săgeată UL este în celulă. O săgeată
orientată spre stânga sau spre sus în celulă înseamnă un gap în secvența coloanelor sau
respectiv în secvența liniei.

Săgeata UL din celula din dreapta-jos ne conduce către celula care conține o săgeată în
sus, adică adăugam un gap "-" peste nucleotidul corespunzător (C) în secvența de coloană.
Această săgeată orientată spre sus ne aduce în celula specială cu două săgeți, una UL și alta în
sus. Aceasta duce la construirea alternativă a alinierii secvenței. Dacă alegem săgeata de sus,
vom plasa un caracter gap peste nucleotida corespunzătoare (G) în secvența coloanei și vom
trece la celula cu o valoare de 6 și o săgeată U. Acest lucru duce în cele din urmă la alinierea
secvențelor din figura următoare A. Alternativ, putem alege să urmărim săgeata UL și să
suprapunem cele două nucleotide (G în ambele secvențe) așa cum se arată în figura următoare
B. Acest lucru duce în cele din urmă la alinierea secvenței alternative în figura B.

Figura 21. Alinierea rezultată în urma aplicării algoritmului Needleman-Wunsch

Ambele aliniamente din figura anterioară au patru potriviri, două gap-uri și zero
nepotriviri. Deci, scorul de aliniere este 4 ∗ 𝑀 + 2 ∗ 𝐺 + 0 ∗ (𝑀𝑀) = 4, pe care îl cunoaștem
deja după terminarea matricei de punctare, a cărei celulă din dreapta-jos conține scorul de
aliniere.

Amintiți-vă că fiecare celulă cu un scor și o săgeată specifică o aliniere optimă între un


prefix al lui S și un prefix T, adică 𝑆𝑗 și 𝑇𝑖 . De exemplu, prima celulă cu o valoare calculată de
2 și o săgeată UL specifică alinierea optimă a S1 (= 'A') și T1 (= 'A') cu un scor de aliniere de
2 (care este scorul de potrivire). Următoarea celulă din dreapta, cu un scor de 0 și o săgeată
stângă, specifică alinierea optimă a S2 și T1 (scorul 0 rezultă dintr-o potrivire și o penalizare a
gap-ului):
Celula cu un scor de 4 și două săgeți arată două aliniamente la fel de optime cu un scor de
aliniere de 4:

Când secvențele sunt lungi, ar putea exista multe alinieri la fel de optime și puține
programe de calculator ar încerca să le găsească și să le scoată pe toate. În schimb, este urmată
numai o singură cale, care duce la ieșirea doar a uneia dintre potențialele aliniamente la fel de
optime.

Programarea dinamică garantează că alinierea rezultată este optimă având în vedere


schema de punctare. Cu alte cuvinte, nu există nici o aliniere care să aibă un scor de aliniere
mai mare de 4 având în vedere cele două secvențe și schema de notare a lui M = 2, MM = -1 și
G = -2. Cu toate acestea, o aliniere optimă se poate schimba atunci când schema de notare este
schimbată. Acest lucru este ilustrat în figurile următoare, unde utilizarea schemei de notare 1
ar avea ca rezultat alinierea 1 (cu scorul de aliniere = 14) mai bună decât alinierea 2 (cu scorul
de aliniere = 12), dar utilizarea schemei de notare 2 ar conduce la Opus, cu alinierea 2 (scorul
de aliniere = 20) mult mai bună decât alinierea 1 (scorul de aliniere = 9).

Alinierea 1

Alinierea 2

Tabel de scor 1
Tabelul 1. Tabel de scor 2

Aliniere Potrivire Nepotrivire Gap Scor 1 Scor 2


1 7 5 0 14 9
2 11 0 2 12 20

Deoarece nu există o metodă obiectivă de a alege schema potrivită de punctare, este important
să rețineți că alinierea secvențelor este o metodă de explorare a datelor în locul unei metode
analitice care va conduce la o singură soluție optimă. Din acest motiv, aproape toate
programele software pentru alinierea secvențelor permit utilizatorului să încerce diferite
scheme de notare și editarea manuală post-aliniere.

4.2 Alinierea locala (Algoritmul Smith & Waterman)

Alinierea locală a secvențelor (Smith și Waterman, 1981) este similară cu alinierea


globală prezentată mai sus, cu doar trei diferențe majore. În primul rând, prima linie și prima
coloană a matricei de notare sunt umplute cu zero în loc de i × G. În al doilea rând, ori de câte
ori valoarea celulei devine negativă (adică, maximul celor trei valori este mai mic decât 0),
valoarea celulei este setată la 0. Astfel, atunci când două secvențe au o potrivire locală scurtă
dar perfectă și o similitudine mică în altă parte, scorul de aliniere a potrivirii scurte dar
perfecte nu este afectat de similitudinea scăzută în altă parte. În al treilea rând, deoarece o
aliniere locală se poate încheia oriunde în matrice, nu vom urmări din celula din colțul din
dreapta jos al matricei de scoruri. În schimb, găsim scorul maxim în matrice și urmărim din
acel punct până când ajungem la o celulă cu o valoare de 0, ceea ce indică începutul alinierii
locale.

Schema de punctare simplă pe care am utilizat-o are trei probleme majore. Mai întâi,
tranzițiile (adică substituțiile între nucleotidele A și G și între C și T) apar în general mai
frecvent decât transversiile (când A sau G sunt înlocuite cu C sau T). Acest lucru sugerează că
nu ar trebui să tratăm diferențele tranzitorii și diferențele transversale cu același scor de
nepotrivire. În schimb, tranzițiile ar trebui penalizate mai puțin decât transversiile. În al doilea
rând, există adesea baze ambigue în introducerea secvențelor, de exemplu, R pentru A sau G și
Y pentru C sau T. O pereche A-R nu este nici o potrivire strictă, nici o nepotrivire strictă, dar
are o probabilitate de 0,5 ca fiind o potrivire și o probabilitate de 0,5 ca fiind o tranziție.
Schema de punctare simplă pe care am utilizat-o nu poate rezolva aceste probleme, ceea ce
necesită utilizarea unei matrici de similitudine.

Schema simplă de notare are, de asemenea, o altă problemă, chiar mai gravă, cauzată de o
pedeapsă constantă. Un biolog se va plânge tare că o metodă de aliniere este greșită dacă
consideră că cele două aliniamente alternative din figurile de mai sus sunt la fel de bune și ar fi
ales alinierea din figura a ca o aliniere mai bună. Cea mai simplă soluție la această problemă
este de a folosi ceea ce se numește o funcție afină pentru lacune.

4.2.1 Matricile AND

Un exemplu de matrice de similitudine este " transition bias matrix " (tabelul următor)
utilizat în DAMBE (Xia, 2001; Xia și Xie, 2001) pentru alinierea multiplă cu un arbore stelar.
Un arbore stelar conține un singur nod intern cu toate frunzele conectate la același nod intern.
Semnificația matricei 4 × 4 din partea de sus (valorile boldate din tabelul următor) este ușor de
înțeles. Primele patru valori diagonale de 30 sunt echivalente cu scorul de potrivire, un scor de
nepotrivire care implică o transversie sau o tranziție este -30 sau 0, respectiv, deoarece
tranzițiile apar în general mult mai frecvent decât transversiile și, prin urmare, sunt penalizate
mai puțin. Restul matricei implică coduri ambigue specificate în al doilea tabel, conform
Comitetului pentru Nomenclatură al Uniunii Internaționale de Biochimie (1985).

Figura 22. Transition bias matrix


Figura 23.Tipuri de aminoacizi

(tabelele au fost preluate din cursurile Springer “Bioinformatics and the Cell Modern
Computational Approaches in Genomics, Proteomics and Transcriptomics” Chapter 2)

Schema de codare este adesea considerată drept codul IUB sau notația IUB. De exemplu,
R reprezintă fie A, fie G, deci o pereche A-R are o probabilitate de 0,5 să fie o potrivire A-A și
o probabilitate de 0,5 să fie o tranziție A-G. Scorul corespunzător (= 15) este, prin urmare,
undeva între o potrivire perfectă și o tranziție. În contrast, Y reprezintă fie C, fie T / U, iar o
pereche A-Y este întotdeauna o transversie, cu un scor de -30.

4.2.2 Matricea de proteine

Aminoacizii diferă unul de celălalt în volum, încărcare, polaritate și multe alte


proprietăți, iar reziduurile de aminoacizi dintr-o proteină conferă proteinei proprietăți diferite.
Proteinele cu o durată de viata lungă (> 1 zi) au în mod obișnuit glicină, valină sau metionină
la capătul N-terminal, în timp ce cele cu o durată de viață scurtă (câteva minute) au de obicei
reziduuri încărcate pozitiv (arginină, lizină) terminal. Un reziduu mic de aminoacid, cum ar fi
glicina și alanina, în penultimul loc (cel de-al doilea loc de aminoacizi din peptida născută)
permite ca metionina inițiatorului să fie clivată eficient (Moerschell și colab., 1990).
Înlocuirea aminoacidului care implică aminoacizi foarte diferiți este în general selectată
împotriva (Xia și Li, 1998). Din acest motiv, o schemă de notare cu potrivire și nepotrivire
este rar utilizată pentru alinierea secvențelor de proteine.
Figura 24. Formula structurala a 20 de aminoacizi (a fost preluata din cursurile Springer
“Bioinformatics and the Cell Modern Computational Approaches in Genomics, Proteomics and
Transcriptomics” Chapter 5)

Un exemplu frecvent utilizat pentru a ilustra efectul unui aminoacid care este înlocuit
cu un aminoacid diferit este anemia celulelor seceră. Anemia celulară este cauzată de o
înlocuire a unui singur aminoacid în lanțul β al hemoglobinei umane la șase poziții, cu un
reziduu de glutamat înlocuit cu un reziduu de valină. Glutamatul este încărcat negativ și
hidrofil și tinde să rămână pe suprafața proteinei în mediul apos din sânge. În schimb, valina
este un reziduu nepolar și hidrofob și tinde să se micsoreze în mijlocul proteinei. Moleculele
de proteine deformate formează apoi fascicule și distorsionează celula roșie din sânge,
rezultând în forma caracteristică a unei seceră. În general, este adevărat că aminoacizii de
polaritate diferită rar se substituie reciproc (Xia și Li, 1998), în timp ce aminoacizii cu
polaritate similară se pot înlocui destul de des (Xia și Kumar, 2006).

Matricele de substituție utilizate frecvent pentru secvențele de proteine sunt de două


tipuri, matricea PAM (Dayhoff și colab., 1978) și matricea BLOSUM (Henikoff, 1992).
Codurile literelor pentru aminoacizi propuse de Comitetul pentru Nomenclatură al Uniunii
Internaționale de Biochimie (1985) sunt prezentate în tabelul următor. Aceste coduri sunt
acum adoptate universal de către comunitatea științifică. Pe scurt, matricele PAM și BLOSUM
sunt derivate de alinierile secvențelor legate de proteine, prima fiind bazată pe alinierea
globală, iar cea de-a doua bazată pe alinierea locală. Matricea PAM1 se bazează pe comparații
ale secvențelor care nu au mai mult de 1% divergență și toate celelalte matrici PAM sunt
derivate din această matrice PAM1. Cerința privind proteinele care nu au mai mult de 1%
divergență este necesară pentru o aliniere globală fiabilă. Matricea cea mai frecvent utilizată
BLOSUM este BLOSUM 62 care este calculată din comparații ale secvențelor cu divergențe
de cel puțin 62%. Matricea BLOSUM xx se bazează pe blocuri de secvențe cu divergență nu
mai mică de xx%, adică toate matricile BLOSUM se bazează pe alinieri observate în contrast
cu matricele PAM derivate din matricea PAM1. BLOSUM 62 este matricea implicită în
BLAST 2.0.

Figura 25. Tipuri de aminoacizi utilizați în matricipe de tip BLOSUM

(a fost preluata din cursurile Springer “Bioinformatics and the Cell Modern Computational
Approaches in Genomics, Proteomics and Transcriptomics” Chapter 4)

A doua extensie a schemei simple de punctare este înlocuirea penalizării constante a


gap-ului cu ceea ce se numește o funcție affină. Problema cu pedeapsa constantă a decalajului
este exemplificată în cele două aliniamente optime din figura următoare (folosită si mai
devreme). Din punct de vedere biologic, alinierea cu două goluri independente (b) este mai
puțin probabilă decât cea cu un singur gap de lungime 2 (a). Așadar, ar trebui să găsim o
schemă de penalizare a decalajului care favorizează alinierea din figura a față de cea din figura
b. Funcția afină, care este utilizată în BLAST (Altschul et al., 1990; Altschul et al., 1997), este
cea mai simplă dintre schemele de penalizare a decalajelor care vor face treaba. Un avantaj
particular al funcției afină este că permite ca alinierea să fie finalizată în timpul proporțional
cu MN, unde M și N sunt lungimea celor două secvențe care trebuie aliniate.

Figura 26. Aliniamente rezultate ăn alinierile locale și utilizănd diverse categorii de matrici

Funcția afină pentru penalizarea gap-ului este:

𝐺(𝑥) = −(𝑎 + 𝑏𝑥) (1)

unde x este lungimea decalajului, iar a și b sunt penalizările deschise și, respectiv, extensiile
de decalaj. Pedeapsa de decalaj crește liniar cu lungimea decalajului. BLAST are setările
implicite cu a = 5 și b = 2, împreună cu scorul de potrivire (M) = 1 și scorul de nepotrivire
(MM) = -3.

Tabelul următor ilustrează calculul implicat în alinierea a două secvențe cu M = 1, MM


= -3 și penalizarea de decalare specificată cu a = 5 și b = 2, adică schema implicită de scorare
BLAST. Rețineți că, în timp ce prima valoare din matrice este încă 0, ca mai înainte,
următoarea valoare a primei linii sau a primei coloane este -7 care are ca rezultat
−(𝑎 + 1𝑏) = −(5 + 1 ∗ 2) = −7 (Rețineți că o mișcare spre stânga sau spre în jos înseamnă
introducerea unui spațiu fie în linie, fie în secvența de coloană, iar primul spațiu este asociat
atât cu gap-urile deschise, cât și cu gap-urile de extensie a spațiului. Valorile de după -7 pe
prima linie sau pe prima coloană sunt scăzute numai prin extensia gap-ului, adică dacă un
spațiu este deja deschis, diferențele suplimentare vor suferi doar penalizări de extensie a
spațiului. Este din nou necesar să calculam trei valori în fiecare celulă rămasă. Vom calcula
valorile DIAG, LEFT și UP așa cum se specifică mai jos și vom umple celula cu maximul
celor trei.

Pentru prima celulă, DIAG = 1 din cauza potrivirii celor două nucleotide corespunzătoare,
adică perechile A-A. Valorile UP și LEFT sunt ambele -9. Deci, avem 1 în celulă cu o săgeată
UL. Pentru celula următoare, avem
𝐷𝐼𝐴𝐺 = −7 − 3 = −10

𝑈𝑃 = −9 − 2 = −11

𝐿𝐸𝐹𝑇 = 1 − 5 − 2 = −6

Figura 27. Alte exemple de aliniamente

Rețineți că valoarea LEFT pentru această celulă este punctată atât cu gap-ul deschis,
cât și cu penalizarea extinderii spațiului, deoarece celula precedentă (cu valoare = 1) are o
săgeată UL, adică nu există nici un gap. Dacă celula precedentă are o săgeată spre stânga, ceea
ce înseamnă că spațiul a fost deja deschis, s-ar aplica numai pedeapsa de extindere a spațiului.
Cea mai mare valoare a celor trei este LEFT (=-6), iar celula este deci completată cu -6 şi o
sageată stânga. Acest proces continuă până ajungem la ultima celulă, cu o valoare de -5.
Acesta este scorul de aliniere bazat pe schema de notare cu penalizări de decalaj specificate cu
funcția afină.

Există câteva celule care necesită explicații. Prima este celula cu o valoare de -4
corespunzătoare nucleotidei G din secvența de linie și a celei de-a doua nucleotide G din
secvența coloană. Celula are două săgeți, una îndreptată spre U și una orientată în UL. Acest
lucru se datorează faptului că valorile DIAG și UP sunt egale cu -4:

𝐷𝐼𝐴𝐺 = −5 + 1 = −4 (2)

𝑈𝑃 = 3 – (5 + 2) = −4 (3)

Dacă această celulă ar fi ultima celulă, adică, dacă ar fi aliniat secvența parțială a liniei "ACG"
împotriva secvenței coloană parțiale "ACGG", am obține două aliniere optimă alternativă
ambele cu scorul de aliniere de -4:
Cealaltă celulă cu două săgeți este în ultima coloană, al doilea rând de jos în sus. Dacă această
celulă ar fi ultima celulă, adică, dacă ar fi aliniat secvența de linie "ACGT" împotriva
secvenței coloană parțiale "ACGGC", am obține două alinieri optime alternative, ambele cu
scorul de aliniere de - 7 (adică, trei potriviri, o nepotrivire și un gap și o penalizare de
extindere a gap-ului):

Figura 28. Aliniamentele rezultate din matricea prezentate în figura 27

Cea mai dificilă celulă se află în penultima coloană și penultima linie, adică cea cu o valoare
UP de -6. Valorile DIAG și LEFT pentru această celulă sunt simple:

𝐷𝐼𝐴𝐺 = −7 – 3 = −10

𝐿𝐸𝐹𝑇 = −9 – 2 = −11

Cu toate acestea, valoarea UP depinde de ce săgeți din celula de mai sus (de exemplu,
celula cu o valoare de -4 și două săgeți) ar trebui să luăm. Dacă luăm săgeata UP (adică, un
gol a fost deja deschis), apoi 𝑈𝑃 = −4 − 2 = −6. Cu toate acestea, dacă luăm săgeata UL
(adică, nici un gol nu a fost deschis încă), atunci 𝑈𝑃 = −4 − (5 + 2) = −11. Ar trebui să
alegem valoarea maximă, adică -6, iar acest lucru constrânge celula anterioară (adică celula cu
o valoare de -4 și două săgeți) pentru a avea o săgeată în sus. Cu alte cuvinte, după ce am
introdus o valoare -6 în celulă, celula de deasupra nu va mai avea două săgeți, ci va avea doar
o săgeată în sus. Din acest motiv, am setat săgeata UL din acea celulă la gri, dar am lăsat
săgeata UP neagră.

Acum, urmând săgețile backtrack, obținem alinierea din figura următoare. Alinierea
are patru potriviri și un gap de lungime 2. Deci scorul de aliniere este 4 ∗ 1 − (5 + 2 ∗ 2) =
−5, ceea ce confirmă faptul că matricea noastră de punctare a fost obținută corect deoarece
valoarea din colț dreapta jos din matricea de punctare este scorul de aliniere).

5. Limbajul de programare folosit pentru proiectarea aplicației


practice

Microsoft Visual Studio este un mediu de dezvoltare integrat (IDE) de la Microsoft.


Acesta este folosit pentru a dezvolta programe de calculator pentru Microsoft Windows,
precum și site-uri Web, aplicații web, servicii web și aplicații mobile. Visual Studio utilizează
platforme de dezvoltare software Microsoft cum ar fi Windows API, Windows Forms,
Windows Presentation Foundation, Windows Store și Microsoft Silverlight. Poate produce atât
cod nativ, cât și cod gestionat.
Visual Studio include un editor de cod care suportă IntelliSense (componenta de completare a
codului), precum și refactorizarea codului. Debuggerul integrat funcționează atât ca un
depanator la nivel de sursă, cât și ca un depanator la nivel de mașină. Alte instrumente
încorporate includ un profil de cod, designer de formulare pentru construirea de aplicații GUI,
web designer, designer de clasă și designer de schemă de baze de date. Acesta acceptă
pluginuri care îmbunătățesc funcționalitatea la aproape toate nivelurile, inclusiv adăugarea de
suport pentru sistemele de control sursă (precum Subversion) și adăugarea unor noi seturi de
instrumente, cum ar fi editorii și designerii vizuale, pentru limbile sau seturile de instrumente
specifice domeniului pentru alte aspecte ale ciclului de viață al dezvoltării software Cum ar fi
clientul Team Foundation Server: Team Explorer).
Visual Studio suportă 36 de limbi de programare diferite și permite editorului de cod și
depanatorului să suporte (în grade diferite) aproape orice limbaj de programare, cu condiția să
existe un serviciu specific limbajului. Limbile încorporate includ C, C ++ și C ++ / CLI (prin
Visual C ++), VB.NET (prin Visual Basic .NET), C # (prin Visual C #), F # (din Visual Studio
2010) Și TypeScript (din Visual Studio 2013 Update 2). Suportul pentru alte limbi, cum ar fi
Python, Ruby, Node.js și M, printre altele, este disponibil prin intermediul serviciilor de limbă
instalate separat. Acesta acceptă, de asemenea, XML / XSLT, HTML / XHTML, JavaScript și
CSS. Java (și J #) au fost suportate în trecut.
Microsoft oferă o versiune gratuită a Visual Studio numită ediție comunitară care acceptă
pluginuri și este disponibilă gratuit.
Jocul este în proporție de 100% dezvoltat în limbajul C# (Windows forms) și are la bază
conceptul de POO (programare orientate obiect). C # este un limbaj de programare multi-
paradigmă care cuprinde discipline puternice de tiparire, imperativ, declarativ, funcțional,
generic, orientat pe obiecte (bazat pe clase) și orientate pe componente. Acesta a fost dezvoltat
de Microsoft în cadrul inițiativei .NET și ulterior a fost aprobat ca standard de Ecma (ECMA-
334) și ISO (ISO / IEC 23270: 2006). C # este unul dintre limbile de programare concepute
pentru infrastructura lingvistică comună. Cea mai recentă versiune este C # 7.0 care a fost
lansată în 2017 împreună cu Visual Studio 2017. Numele "C sharp" a fost inspirat de notația
muzicală în care un ascuțit indică faptul că nota scrisă ar trebui să fie făcută cu o jumătate mai
mare în pitch. Acesta este similar cu numele limbajului C ++, unde "++" indică faptul că o
variabilă trebuie să fie incrementată cu 1. Simbolul ascuțit seamănă de asemenea cu o ligatură
a patru simboluri "+" (într-o grilă două-două) Ceea ce înseamnă că limba este o creștere a C
++. Sintaxa de bază a limbajului C # este similară cu cea a altor limbi în stil C, cum ar fi C, C
++ și Java. În special:
“;” sunt folosite pentru a indica sfârșitul unei declarații. “{}” sunt folosite pentru a grupa
declarațiile. Declarațiile sunt în mod obișnuit grupate în metode (funcții), metode în clase și
clase în spații de nume. Variabilele sunt atribuite folosind egal, dar se compară folosind două
semne consecutive de egalitate. Parantezele pătrate sunt folosite cu matrice, atât pentru a le
declara, cât și pentru a obține o valoare la un indice dat în unul dintre ele. Prin proiectare, C #
este limbajul de programare care reflectă cel mai direct infrastructura lingvistică comună
(CLI). Cele mai multe dintre tipurile sale intrinseci corespund tipurilor de valori implementate
de cadrul CLI. Cu toate acestea, specificația de limbă nu precizează cerințele de generare a
codului compilatorului: adică nu prevede că un compilator C # trebuie să vizeze un Runtime
de limbă comună sau să genereze o limbă comună intermediară (CIL) sau să genereze orice alt
format specific. Teoretic, un compilator C # ar putea genera codul mașinii ca și compilatorii
tradiționali de C ++ sau Fortran.
5.1 Funcționalitatea aplicației

După rularea executabilului se va deschide o fereastră în care sunt prezentate cele două
aliniamente – alinierea globală și cea locală.

Figura 29. Fereastra princilă a aplicației

Dacă se dorește o analiza secvențială globală, vom obține următoarea figură:


Figura 30. Fereastra pentru alinierea globală

Prin introducerea secvențelor și a schemei scoring se poate obține matricea specifică


algoritmului.

Figura 30. Matricea rezultată din algorimul Needleman-Wunsch (aliniertea globală)

Următorul pas este a utiliza procedura Back-Trace pentru obșinerea scorului optim de aliniere.

Pentru exemplul nostrum scorup optim este: -3


Figura 31. Aliniamentul optim si scorul obținut pentru exemplul de secvențe prezentate

Aceeași procedura este urmată și în cazul alinierii locale.

Figura 32. Fereastra pentru inițierea algoritmului Smith-Waterman (aliniere locală)


Următorul pas al procedurii este de a introduce secvențele pentru care se dorește alinierea locală
precum și schema de scoring dorită.

Figura 33. Introducea secvențele pentru care se dorește alinierea locală precum și schema de scoring
dorită

Urmează generarea matricii specificiă algoritmului Smith-Waterman.

Figura 34. Generarea matricii specificiă algoritmului Smith-Waterman

Următorul pas este a utiliza procedura Back-Trace pentru obșinerea scorului optim de aliniere.

Pentru exemplul nostrum scorup optim este: 2


Figura 35. Procedura Back-Trace, aliniamentul local și scorul opținut

6. Concluzii
Având în vedere că ştiinţa aveansează foarte repede, iar noile informaţii trebuie
depozitate în baze de date voluminoase, este nevoie ca accesul la aceste date să fie rapid şi
eficient. Aplicaţiile deja existente sunt costisitoare atât din punct de vedere al timpului de
prelucrare, cât şi din punct de vedere finaciar. Pentru a dezvolta aplicaţii cât mai utile şi
eficiente sunt necesare cunoştinţe de programare, dar şi de bioinformatică.

Scopul aplicaţiei este acela de a facilita studiul alinierii secvenţiale fără a fi nevoie de
achiziţionarea de soluţii software scumpe, greu de intuit şi utilizat.

Aplicația poate fi folosită mai ales în cadrul cursurilor de bioinformatică, simplificând


foarte mult procesul de învaţare. Astfel, studenţii pasionaţi de acest domeniu nu vor mai trebui
să construiască şi să calculeze matrici de scor de dimensiuni mari, câştigând astfel timp, ce
poate fi petrecut învăţând noi metode de aliniere sau chiar dezvoltând noi aplicaţii în acest
domeniu.

Pentru a putea contribui cu inovaţii în acest domeniu, este absolut necesar ca viitorii
bioinformaticieni să stăpânească bine aceste cunoştiinţe, să poată vizualiza aliniamentele şi să
pună în practică teoria, lucru mult mai uşor de realizat datorită acestei aplicații.
Desigur, pe viitor, această aplicaţie va putea fi îmbunătăţită prin adăugarea de noi
algoritmi de aliniere secvenţială, noi metode de aliniere multiplă şi poate chiar şi elemente de
inteligenţă artificială, cu scopul de a o transforma într-o aplicaţie de instruire a studenţilor.

Cu timpul, aplicația se va extinde la o platformă de educare a tinerilor învăţăcei,


oferindu-le acestora definiţii ale termenilor utilizaţi în bioinformatică şi metode de analiză
secvenţială, analiză filogenetică, algoritmi de alinire locală sau globală, utilizând scheme de
scor sau matrici de substituţie.

Bibliografie

1. Needleman SB, Wunsch CD (1970). “A general method applicable to the search for
similarities in the amino acid sequence of two proteins". J Mol Biol 48 (3): 443–453.
2. Lesk AM, Introduction to Bioinformatics (edition 3), Oxford Univ Press, Oxford UK, 2008.
3. Smith TF, Waterman MS (1981). “Identification of Common Molecular Subsequences". J
Mol Biol 147: 195-197.
4. Waterman MS, Smith TF, Beyer WA (1976). “Some biological sequences metrics". Adv
Math 20: 367-387.
5. Wong KC, Computational Biology and Bioinformatics: Gene Regulation, CRC Press, 2016.
6. Mihalaș GI, Tudor A, Paralescu S, Bioinformatică, Ed. Victor Babeș, Timișoara, 2011.
7. Isea R (2015), “The Present-Day Meaning of the Word Bioinformatics“, Global J. Adv.
Res., 2, 70-73.
8. Lee C (2003), “Generating consensus sequences from partial order multiple sequence
alignment graphs”. Bioinformatics 19, 999–1008.
9. Luscombe NM, Greenbaum D, Gerstein M (2001), “What is bioinformatics? An
introduction and overview”. YearBook Med. Inf., 83-100.
10. Hsu PC, Evaritus Nwulia MS, Akira Sawa MHS (2009), “Images in Neuroscience: Using
Bioinformatic Tools”. The American Journal of Psychiatry, 166-168.
11. Warren J. Ewens, Gregory R. Grant, “Statistical Methods in Bioinformatics: An
Introduction”. Penn Center for Bioinformatics Computational Biology and Informatics
Laboratory, University of Pennylvania Philadelphia, PA 19104 USA.
12. Grasso, C. and Lee, C. (2004), “Combining partial order alignment and progressive
multiple sequence alignment increases alignment speed and scalability to very large alignment
problems”. Bioinformatics 20, 1546–1556.

Anexe
Codul sursă
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
public int dimPrSecv, dimSecSecv, nrRow = 1, nrCol = 1, pozTextBoxA = 15,
pozTextBoxB = 200, f = 1, poz1 =0;
public TextBox[] publicTextBox;
public int contor = 3, counter = 0;
public int contorNou = 0;
public int localI = 0, localj = 0;
public void calculMatrice(TextBox[] _arrayPrincipal)
{
TextBox[] MyTextBoxDimA = new TextBox[10000];
MyTextBoxDimA = _arrayPrincipal;
int[] rezultat = new int[4];
int CmpSecv2;
int nrPozCalc = (3 * dimPrSecv + 3);
int discrepanta = 3;
for (CmpSecv2 = (3 * dimPrSecv + 2); CmpSecv2 <= (dimPrSecv * dimSecSecv);
CmpSecv2 = CmpSecv2 + dimPrSecv) // ia toate val secv2
{
discrepanta++;
for (int CmpSecv1 = (dimPrSecv + 4); CmpSecv1 <= (dimPrSecv * dimSecSecv);
CmpSecv1++) // ia toate val secv 1
{
nrPozCalc++;
if (nrPozCalc != discrepanta * dimPrSecv + 1) // conditie pt poz care trb calc
{
if (MyTextBoxDimA[CmpSecv1].Text ==
MyTextBoxDimA[CmpSecv2].Text) // oblic
{
rezultat[0] = Convert.ToInt32(MyTextBoxDimA[(nrPozCalc - dimPrSecv -
1)].Text) + Convert.ToInt32(textBox3.Text); // daca e "="
}
else
{
rezultat[0] = Convert.ToInt32(MyTextBoxDimA[(nrPozCalc - dimPrSecv -
1)].Text) + Convert.ToInt32(textBox4.Text); // daca e "!="
}
rezultat[1] = Convert.ToInt32(MyTextBoxDimA[(nrPozCalc -
dimPrSecv)].Text) + Convert.ToInt32(textBox5.Text); // sus
rezultat[2] = Convert.ToInt32(MyTextBoxDimA[(nrPozCalc - 1)].Text) +
Convert.ToInt32(textBox5.Text); // stanga
rezultat[3] = 0;
MyTextBoxDimA[nrPozCalc].Text = rezultat.Max().ToString();
}
if (CmpSecv1 == 2 * dimPrSecv)
{
nrPozCalc = nrPozCalc + 3;
break;
}
}
}
}
public void splitSecv1si2(TextBox[] _arrayPrincipal, int _nrCol, int _nrRow)
{
TextBox[] MyTextBoxDimA = new TextBox[10000];
int nrCol, nrRow;
nrCol = _nrCol;
nrRow = _nrRow;
MyTextBoxDimA = _arrayPrincipal;
if (nrCol > 3 && nrRow == 2)
{
string localText1 = textBox1.Text;
localText1.ToCharArray();
MyTextBoxDimA[f].Text = localText1[localI].ToString();
localI++;
}
if (nrCol == 2 && nrRow > 3)
{
string localText2 = textBox2.Text;
localText2.ToCharArray();
MyTextBoxDimA[f].Text = localText2[localj].ToString();
localj++;
}
}
public void colorareMatrice()
{
int[] compararNumere = new int[3];
int casutaBlue = 0;
int[] VectNRJos = new int[dimPrSecv - 2];
int[] VectNRsus = new int[dimSecSecv - 3];
int i = 0,cmpvct =0;
for (int M = dimPrSecv * dimSecSecv; M >= (dimPrSecv * dimSecSecv - (dimPrSecv
- 3)); M--)
{
VectNRJos[i] = Convert.ToInt32(publicTextBox[M].Text);
i++;
}
i = 0;
for (int M = dimPrSecv * dimSecSecv - dimPrSecv; M >= (dimPrSecv * 4); M = M -
dimPrSecv)
{
VectNRsus[i] = Convert.ToInt32(publicTextBox[M].Text);
i++;
}
cmpvct = VectNRJos.Max() > VectNRsus.Max() ? VectNRJos.Max() :
VectNRsus.Max();
i = 0;
while(i <= dimPrSecv - 2)
{
if (VectNRJos[i] == cmpvct)
{
poz1 = dimPrSecv * dimSecSecv - i;
break;
}
i++;
}
i = 1;
while(i <= dimSecSecv - 4)
{
if (VectNRsus[i] == cmpvct)
{
poz1 = (dimPrSecv * dimSecSecv) - (dimPrSecv * i);
break;
}
i++;
}
casutaBlue = poz1;
publicTextBox[casutaBlue].BackColor = Color.Aqua;
while (casutaBlue != (dimPrSecv * 2) + 3)
{
try
{
compararNumere[0] = Convert.ToInt32(publicTextBox[casutaBlue -
dimPrSecv].Text);
compararNumere[1] = Convert.ToInt32(publicTextBox[casutaBlue - dimPrSecv -
1].Text);
compararNumere[2] = Convert.ToInt32(publicTextBox[casutaBlue - 1].Text);
int numarMaxim = compararNumere.Max();
if (Convert.ToInt32(publicTextBox[casutaBlue - dimPrSecv - 1].Text) ==
numarMaxim)
{
publicTextBox[casutaBlue - dimPrSecv - 1].BackColor = Color.Aqua;
casutaBlue = casutaBlue - dimPrSecv - 1;
}
else if (Convert.ToInt32(publicTextBox[casutaBlue - dimPrSecv].Text) ==
numarMaxim)
{
publicTextBox[casutaBlue - dimPrSecv].BackColor = Color.Aqua;
casutaBlue = casutaBlue - dimPrSecv;
}
else if (Convert.ToInt32(publicTextBox[casutaBlue - 1].Text) == numarMaxim)
{
publicTextBox[casutaBlue - 1].BackColor = Color.Aqua;
casutaBlue = casutaBlue - 1;
}
}
catch
{
if (casutaBlue > (dimPrSecv * 2) + 3)
{
casutaBlue = casutaBlue - dimPrSecv;
}
}
}
}
private void button1_Click_1(object sender, EventArgs e)
{
TextBox[] MyTextBoxDimA = new TextBox[100000];
dimPrSecv = textBox1.TextLength + 3;
dimSecSecv = textBox2.TextLength + 3;
AutoScroll = true;
WindowState = System.Windows.Forms.FormWindowState.Maximized;
while (dimSecSecv >= nrRow)
{
while (dimPrSecv >= nrCol)
{
MyTextBoxDimA[f] = new TextBox();
MyTextBoxDimA[f].Location = new Point(pozTextBoxA, pozTextBoxB);
// sa scrie coloane
if (nrCol == 2 && nrRow == 1)
{
MyTextBoxDimA[f].Text = "Coloane";
}
// pe linia coloane, numara cate coloane sunt
if (nrCol > 2 && nrRow == 1)
{
int i = 3;
while (i <= dimPrSecv)
{
MyTextBoxDimA[i] = new TextBox();
MyTextBoxDimA[i].Location = new Point(pozTextBoxA, pozTextBoxB);
MyTextBoxDimA[i].Text = (i - 3).ToString();
i++;
}
}
// sa scrie linii
if (nrCol == 1 && nrRow == 2)
{
MyTextBoxDimA[f].Text = "Linii";
}
// sub textul de linii , numara cate linii avem
if (nrCol == 1 && nrRow > 2)
{
int i = dimPrSecv * 2 + 1;
int k = 3;
while (k <= dimSecSecv)
{
MyTextBoxDimA[i] = new TextBox();
MyTextBoxDimA[i].Location = new Point(pozTextBoxA, pozTextBoxB);
MyTextBoxDimA[i].Text = (nrRow - 3).ToString();
k++;
i = i + dimPrSecv;
}
}
// 0 pe coloana
if (nrCol > 2 && nrRow == 3)
{
if (contor <= dimPrSecv)
{
MyTextBoxDimA[f].Text = counter.ToString();
counter = 0;
contor++;
}
}
// 0 pe linie
if (nrCol == 3 && nrRow > 3)
{
MyTextBoxDimA[f].Text = contorNou.ToString();
contorNou = 0;
}
this.splitSecv1si2(MyTextBoxDimA, nrCol, nrRow);
MyTextBoxDimA[f].Size = new Size(50, 10);
MyTextBoxDimA[f].TabIndex = 2;
Controls.Add(MyTextBoxDimA[1]);
Controls.Add(MyTextBoxDimA[f]);
pozTextBoxA = pozTextBoxA + 50;
f++;
nrCol++;
}
pozTextBoxB = pozTextBoxB + 30;
nrCol = 1;
nrRow++;
pozTextBoxA = 15;
}
this.calculMatrice(MyTextBoxDimA);
publicTextBox = MyTextBoxDimA;
}
private void button2_Click_1(object sender, EventArgs e)
{
this.colorareMatrice();
}
private void button3_Click_1(object sender, EventArgs e)
{
int[] compararNumere = new int[3];
int localcount = poz1-(dimPrSecv * (dimSecSecv-2)) -1;
int countsecv2 = 0;
int casutaBlue = poz1;
if (publicTextBox[dimPrSecv * dimSecSecv] != null)
{
textBox6.Text = publicTextBox[dimPrSecv * 2].Text.ToString();
textBox7.Text = publicTextBox[(dimPrSecv * dimSecSecv) - (dimPrSecv -
2)].Text.ToString();
}
while (casutaBlue != (dimPrSecv * 2) + 3)
{
try
{
compararNumere[0] = Convert.ToInt32(publicTextBox[casutaBlue -
dimPrSecv].Text);
compararNumere[1] = Convert.ToInt32(publicTextBox[casutaBlue - dimPrSecv -
1].Text);
compararNumere[2] = Convert.ToInt32(publicTextBox[casutaBlue - 1].Text);
int numarMaxim = compararNumere.Max();
if (Convert.ToInt32(publicTextBox[casutaBlue - dimPrSecv].Text) ==
numarMaxim)
{
countsecv2 = ((dimPrSecv * dimSecSecv) - (casutaBlue - dimPrSecv)) %
dimPrSecv + (casutaBlue - dimPrSecv) - (dimPrSecv - 2);
textBox6.Text = textBox6.Text + "_";
textBox7.Text = textBox7.Text + publicTextBox[countsecv2].Text.ToString();
casutaBlue = casutaBlue - dimPrSecv;
}
else if (Convert.ToInt32(publicTextBox[casutaBlue - dimPrSecv - 1].Text) ==
numarMaxim)
{
countsecv2 = ((dimPrSecv * dimSecSecv) - (casutaBlue - dimPrSecv - 1)) %
dimPrSecv + (casutaBlue - dimPrSecv - 1) - (dimPrSecv - 2);
textBox6.Text = textBox6.Text + publicTextBox[localcount].Text.ToString();
textBox7.Text = textBox7.Text + publicTextBox[countsecv2].Text.ToString();
localcount--;
casutaBlue = casutaBlue - dimPrSecv - 1;
}
else if (Convert.ToInt32(publicTextBox[casutaBlue - 1].Text) == numarMaxim)
{
textBox6.Text = textBox6.Text + publicTextBox[localcount].Text.ToString();
textBox7.Text = textBox7.Text + "_";
localcount--;
casutaBlue = casutaBlue - 1;
}
}
catch
{
if (casutaBlue > (dimPrSecv * 2) + 3)
{
break;
}
}
}
string localText6 = textBox6.Text;
localText6.ToCharArray();
textBox6.Clear();
for (int h = localText6.Length - 2; h >= 0; h--)
{
textBox6.Text = textBox6.Text + localText6[h];
}
string localText7 = textBox7.Text;
localText7.ToCharArray();
textBox7.Clear();
for (int h = localText7.Length - 1; h >= 0; h--)
{
textBox7.Text = textBox7.Text + localText7[h];
}
}
private void button4_Click(object sender, EventArgs e)
{
string charArryTextBox6 = textBox6.Text;
string charArryTextBox7 = textBox7.Text;
int counterG = 0, counterP = 0, counterN = 0;
charArryTextBox6.ToCharArray();
charArryTextBox7.ToCharArray();
for (int i = 0; i <= (charArryTextBox6.Length - 1); i++ )
{
try
{
if (charArryTextBox6[i] == charArryTextBox7[i])
counterP++;
else if (charArryTextBox6[i] != charArryTextBox7[i])
{
if (charArryTextBox6[i] == Convert.ToChar("_") || charArryTextBox7[i] ==
Convert.ToChar("_"))
counterG++;
else
counterN++;
}
}
catch
{
counterG++;
}
}
int scor = (counterP * Convert.ToInt32(textBox3.Text)) + (counterN *
Convert.ToInt32(textBox4.Text)) + (counterG * Convert.ToInt32(textBox5.Text));
textBox8.Text = scor.ToString();
}
}
}

S-ar putea să vă placă și