VISOKA ŠKOLA ZA MENADŢMENT U TURIZMU I INFORMATICI U VIROVITICI MAJA PASARIĆ SIMULATOR TURINGOVOG STROJA ZAVRŠNI RAD VIROVITICA, GODINA 2014 VISOKA ŠKOLA ZA MENADŢMENT U TURIZMU I INFORMATICI U VIROVITICI SIMULATOR TURINGOVOG STROJA ZAVRŠNI RAD Predmet: Osnove programiranja Mentor: Student: dr.sc. Oliver Jukić, prof.v.š. VIROVITICA, GODINA 2014. Maja Pasarić SADRŽAJ 1. UVOD ................................................................................................................................... 1 2. TEORIJSKE POSTAVKE .................................................................................................... 2 3. IZVEDBA SIMULATORA TURINGOVOG STROJA ....................................................... 3 3.1. Metodologija ...................................................................................................................... 3 3.2. Klase .................................................................................................................................. 4 3.3. Izvedba funkcionalne sheme .............................................................................................. 4 3.3.1. Unos i aţuriranje funkcionalne sheme ............................................................................ 6 3.3.2. Pohrana i naknadno uĉitavanje ..................................................................................... 10 3.4. Izvedba vanjske memorije ............................................................................................... 12 3.4.1. Unos i aţuriranje ........................................................................................................... 13 3.4.2. Pohrana i naknadno uĉitavanje ..................................................................................... 14 3.5. Izvedba simuliranja .......................................................................................................... 15 3.4. Prikaz k-te konfiguracije .................................................................................................. 21 4. RASPRAVA ....................................................................................................................... 22 5. ZAKLJUĈAK ..................................................................................................................... 24 6. POPIS LITERATURE ........................................................................................................ 25 7. POPIS ILUSTRACIJA ....................................................................................................... 26 1. UVOD Turingov stroj je koncept univerzalnog izvršitelja algoritama. Njegova definicija je jednostavna, ali se dotiĉe kompleksnih pitanja matematiĉke apstrakcije razmišljanja, granica automatiziranog rješavanja problema, naĉina stvaranja, pojednostavljenja i izvoĊenja algoritama kojima se jednostavnim operacijama pokušavaju riješiti sloţeniji problemi. Stvaranje algoritama kojima Turingov stroj moţe poĉetnu informaciju preobraziti u zadovoljavajuću konaĉnu je ĉesto izazovan problem, no sam rad stroja je jednostavan. Iako je neke probleme kojih se koncept Turingovog stroja dotiĉe teško objasniti, sam rad Turingovog stroja je jednostavan i lagan za simulirati. Sve što je potrebno jest oblik unosa i ispisa simbola u vanjsku memoriju, mogućnost pomicanja ureĊaja za uĉitavanje i ispisivanje simbola te nekakav spremnik za izraze logiĉke funkcije stroja. To se sve moţe izvesti programski, i to na nekoliko naĉina, a ovaj rad prezentira jedno moguće rješenje. Ovaj rad će se prvo osvrnuti na sam koncept Turingovog stroja i objasniti osnovne pojmove koji se nastoje izvesti predstavljenim programskim rješenjem. Zatim će biti rijeĉi o samoj metodologiji izvedbe rješenja problematike simuliranja Turingovog stroja. Ostatak rada predstavlja samo rješenje problema; prezentirajući implementaciju osnovnih funkcionalnosti simulatora Turingovog stroja. Prvo će se predstaviti funkcionalnosti vezane uz funkcionalnu shemu: unošenje i aţuriranje funkcionalne sheme, te pohranu i naknadno uĉitavanje funkcijske sheme. Zatim će se predstaviti izvedbe unošenja i aţuriranja vanjske memorije, te njezine pohrane i naknadnog uĉitavanja. Nakon toga slijedi opis izvedbe simulacije Turingovog stroja te prikaza k-te konfiguracije. Rad će zaokruţiti rasprava prikladnosti rješenja problemu, nakon ĉega slijedi par zakljuĉnih rijeĉi. 1 2. TEORIJSKE POSTAVKE Turingov stroj je model osmišljen da oponaša proces ljudskog razmišljanja. Prvi ga je opisao Alan Turing u svrhu promišljanja i istraţivanja granica raĉunanja. Koncept je usredotoĉen na razlaganje sloţenih algoritama na jednostavne korake koji se mogu matematiĉki izraziti i uspješno izvršiti jednostavnim automatom. Raĉunanje Turingovim strojem se svodi na uĉitavanje ulaznog znaka, mijenjanje internog stanja svijesti s obzirom na trenutno stanje i ulazni znak, te produciranje i ispisivanje izlaznog znaka na traku1. Turingov stroj se sastoji od glave za ĉitanje i pisanje, logiĉkog polja, polja za pohranu untarnjeg stanja i polja za pomak. Vanjska memorija je predstavljena beskonaĉnom trakom s poljima s koje stroj glavom za ĉitanje uĉitava ulazni znak. Ulazni znak pripada konaĉnoj abecedi, a svako polje moţe sadrţavati najviše jedan znak. Abeceda stroja uvijek sadrţi prazni znak (b). Ĉitanje tog znaka znaĉi da je polje trake prazno, a ispisivanje tog znaka prazni polje. Logiĉka funkcija svakom paru ulaznog simbola i trenutnog stanja pridruţuje trojku idućeg stanja, izlaznog simbola i pomakom glave za ĉitanje i pisanje. Internih stanja ima konaĉno mnogo, i to najmanje dva: poĉetno stanje (q0) i konaĉno stanje (qf). Glava je pomiĉna i za svaki Turingov stroj su definirana toĉno tri pomaka: pomak za jedno polje ulijevo (L), pomak za jedno polje udesno (D), i ostanak glave na mjestu (N) (Jukić, Špoljarić, 2010). Svaki Turingov stroj je definiran svojom abecedom, skupom mogućih stanja, skupom mogućih pomaka i logiĉkom funkcijom koja opisuje njegov algoritam. Logiĉka funkcija stroja je sadrţana u njegovom logiĉkom bloku, a moţe ju se prikazati funkcionalnom shemom. Funkcionalna shema je tabliĉni zapis svih trojki izlaznog simbola, idućeg stanja i pomaka pridruţenih svakom paru ulaznog simbola i trenutnog stanja (Turing, 1936). Obrada informacije zapisane u vanjskoj memoriji se odraĊuje u taktovima. Zapis na traci na poĉetku svakog takta predstavlja meĊuinformaciju ĉijom obradom stroj mora doći do konaĉne informacije tj. doći u konaĉno stanje u kojem emitira stop signal i prestaje sa daljnjim ĉitanjem vanjske memorije. Svaku meĊuinformaciju nazivamo konfiguracijom Turingovog stroja. K-ta konfiguracija Turingovog stroja je zapis na traci na poĉetku k-tog takta. Ako stroj moţe kroz konaĉni broj konfiguracija doći do konaĉnog rezultata, stroj je primjenjiv za poĉetnu informaciju (Jukić, Špoljarić, 2010). 1 http://plato.stanford.edu/entries/turing-machine/ (18.11.2014.) 2 3. IZVEDBA SIMULATORA TURINGOVOG STROJA 3.1. Metodologija Programsko rješenje problema simulacije beskonaĉnog broja razliĉitih Turingovih strojeva napisano je jezikom C++ i izvedeno uz pomoć razvojne okoline2 Qt Creator 3.2.0. Qt Creator je IDE osmišljen za programiranje multiplatformskih rješenja uz olakšani dizajn korisniĉkog suĉelja3. Osim standardnih konstrukata C++ jezika, Qt nudi i vlastite klase stvorene da budu ne samo kompatibilne sa C++ standardima, već i optimizirane izvedbe te podrške odreĊenim konceptima programiranja. Jedan od koncepata svojstvenih Qt Creatoru je sustav povezivanja signala i slotova (signals and slots). Sustav omogućuje komunikaciju izmeĊu objekata kojom funkcija jednog objekta signalom poziva funkciju drugog objekta – slot. To se razlikuje od uobiĉajene izvedbe takve komunikacije koja je pohrana pokazivaĉa na funkcije. Objektu koji poziva funkciju proslijeĊuje se pokazivaĉ na funkciju drugog objekta kojeg on pohranjuje i koristi za poziv funkcije drugog objekta kad zatreba. Mane takve izvedbe su te da nije uvijek zajamĉeno da će objekt pozvati funkciju sa ispravnim argumentima i da je izvedba ovisna o pozivajućoj funkciji. Ako funkcija ne zna koju funkciju mora zvati, osmišljena veza izmeĊu dvaju objekata se neće ostvariti kako je zamišljeno. Qt-ov sustav signala i slotova osigurava pozivanje ispravnih funkcija sa ispravnim argumentima neovisno o samom objektu. Objekt ne pohranjuje dodatne podatke niti sam poziva funkciju; za uspostavljene konekcije brine se Qtov meta-objektni prevoditelj. Konekcije su jedino ograniĉene popisom argumenata koji se signalom šalju. Pozivajuća funkcija ne moţe pozvanoj funkciji poslati manje argumenata nego što pozvanoj funkciji treba za izvedbu4. Stvaranje aplikacije u Qt-u olakšano je raznim posebnim klasama i widgetima ukljuĉenima u Qt-ove biblioteke. Qt za mnoge elemente grafiĉkih korisniĉkih suĉelja poput gumba, prozora, dijaloga i alatnih traka nudi i po nekoliko klasa iz kojih se izvoĊenjem novih klasa postiţe olakšana izvedba aplikacija sa grafiĉkim suĉeljima. Jedna od tih klasa je i QWidgetTable koja je u programskom rješenju predstavljenom ovim radom korištena kao izvedba funkcionalne sheme i vanjske memorije Turingovog stroja. Qt podrţava i tzv. MVC (model/view/controller) oblikovni uzorak koji manipuliranje podacima i njihovo prezentiranje korisniku odvaja u tri komponente: model, koji sluţi kao spona izmeĊu podataka i 2 U daljnjem nastavku: IDE (Integrated development environment) https://qt-project.org/doc/qtcreator-2.5/creator-overview.html (18.11.2014.) 4 http://qt-project.org/doc/qt-4.8/signalsandslots.html (18.11.2014.) 3 3 prezentacije, pregled (view) koji je zaduţen samo za prezentaciju podataka, i kontroler (controller) koji upravlja naĉinom interakcije suĉelja i podataka. Pojam kontrolera u Qt-u je izveden delegatima (delegates). MVC obrasci dizajniranja softverskih rješenja su vrlo korisni. Programsko rješenje koje je temelj ovog rada izvodi vanjsku memoriju posebno definiranim delegatom za zadavanje poĉetne konfiguracije Turingovog stroja kojim se osigurava da korisnik na traku zapisuje samo one simbole koji se nalaze u vanjskoj abecedi stroja. 3.2. Klase Programsko rješenje je izvedeno uz pomoć šest klasa: AddDialog, Dialog, RemoveDialog, TapeDelegate, TableEditor i MainWindow. Klase AddDialog, Dialog i RemoveDialog su dijaloške klase ĉijim objektima se aplikacija sluţi pri odreĊivanju vanjske abecede i skupa unutarnjih stanja Turingovog stroja te izvoĊenju k-te konfiguracije stroja. Objekti klase AddDialog koriste se za dodavanje stanja i simbola u pripadajuće skupove, a objekti klase RemoveDialog se koristi za njihovo uklanjanje. Objekt klase Dialog od korisnika traţi unos broja k kojim se aplikacija sluţi za odreĊivanje k-te konfiguracije Turingovog stroja. Klasa TapeDelegate je klasa već spomenutog delegata korištenog pri unošenju i preinakama vanjske memorije, a klasa TableEditor je klasa objekta korištenog za unos i aţuriranje funkcionalne sheme. Klasa MainWindow predstavlja centralni widget aplikacije. Velika većina funkcionalnosti aplikacije proizlazi upravo iz MainWindow klase koja nasljeĊuje QMainWindow, Qt-ovu klasu specijaliziranu za aplikacije sa grafiĉkim suĉeljem. Najviše ĉlanova ove klase su funkcije od kojih su skoro sve definirane kao slotovi, funkcije koje druga funkcija moţe pozvati. Budući da su za internu upotrebu, tj. pozivaju ih funkcije koje su ĉlanovi istog objekta, nema potrebe da ih se deklarira javnima. 3.3. Izvedba funkcionalne sheme Kao što je već reĉeno, funkcionalna shema izvedena je objektom klase QTableWidget. QTableWidget je widget za tabliĉni prikaz kojem je pridruţen standardni podatkovni model. Budući da su zahtjevi izvedbe funkcionalne sheme jednostavni i svode se na unos i aţuriranje tablice, nema potrebe za izvoĊenjem klasa ili MVC programiranjem. 4 Osnovica funkcionalne sheme su vanjska abeceda i skup unutarnjih stanja. Svaka ćelija sadrţi trojku odreĊenu ulaznim simbolom (redak tablice) i trenutnim stanjem (stupac tablice). Skup pomaka je strogo definiran. Skup unutarnjih stanja predstavlja states ĉlan klase MainWindow koji je tipa QStringList, što ga oznaĉava kao listu u koju se spremaju podaci tipa QString. Vanjsku abecedu predstavlja symbols, isto deklariran kao varijabla tipa QStringList, a shifts je QStringList koji pohranjuje skup pomaka. Sva tri ĉlana se inicijaliziraju u konstruktoru klase MainWindow, kao što je prikazano u idućem odsjeĉku koda. MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { states.append("q0"); symbols.append("b"); shifts.append("L"); shifts.append("N"); shifts.append("D"); ... } Funkcija append() listi dodaje ĉlanove tako da svaki novi ĉlan pozicionira u poloţaju odmah nakon zadnjeg elementa liste5. Dodavanjem novih stanja i simbola na kraj liste osiguravamo poredane podatke. To je posebno vaţno ostvariti za listu u kojoj ĉuvamo stanja budući da indeksi stanja direktno koreliraju sa indeksima stringova njihovih oznaka u listi u kojoj ih ĉuvamo. Simboli ne moraju biti poredani (npr., prema abecedi), ali zato pomaci moraju uvijek biti inicijalizirani ovako budući da se prevoĊenje oznake pomaka u stvarni pomak glave za ĉitanje i pisanje prevodi uprav na temelju indeksa oznake u listi. Liste koje pohranjuju simbole i stanja moraju na poĉetku dobiti nekoliko zadanih podataka. Ti podaci predstavljaju dva bitna elementa koja su spomenuta u izlaganju teorijske osnove ovog rada, a to su prazni simbol b i poĉetno stanje q0. Prazni simbol i poĉetno stanje su obvezni ĉlanovi svojih skupova, stoga u ovom dijelu koda abecedi dodajemo prazni simbol, a skupu stanja dodajemo poĉetno stanje. Konaĉno stanje qf je isto obvezni element skupa stanja, no zbog odreĊenih 5 http://www.cplusplus.com/reference/string/string/append/ (18.11.2014.) 5 aspekata izvedbe dodavanja novih stanja, uklanjanja stanja te korištenja stanja za potrebe simulacije, izravno ukljuĉivanje konaĉnog stanja u skup nije prikladno. Zbog toga konaĉno stanje nije ukljuĉeno u listu, ali se koristi pri simulaciji rada stroja i ureĊivanju funkcionalne sheme. QTableWidget je u aplikaciju dodan preko Qt Designera, Qt-ovog alata za dizajn grafiĉkih korisniĉkih suĉelja, stoga u kodu klase MainWindow nije zapisana deklaracija tog objekta. Ona se nalazi u skrivenoj zaglavnoj datoteci koju generira Qt u svrhu odvajanja koda generiranog Qt Designerom od koda napisanog od strane programera. Generirani kod postaje dijelom ui klase koju generira Qt Designer prilikom ureĊivanja grafiĉkog suĉelja, stoga funkcionalnoj shemi pristupamo preko pokazivaĉa na objekt klase ui. Qt tijekom dodavanja grafiĉkih elemenata kroz Qt Designer generira i imena objekata. Tako je QTableWidget koji se koristi kao prikaz funkcionalne sheme od strane Qt Designera nazvan tableWidget. Naredni odsjeĉak koda inicijalizira tableWidget i tako ga priprema za daljnju korisnikovu upotrebu. Postavljaju se dimenzije tablice te poĉetna trojka. void MainWindow::initShema() { ui->tableWidget->setRowCount(1); ui->tableWidget->setColumnCount(1); QTableWidgetItem *item = new QTableWidgetItem(QString("q0, b, N")); ui->tableWidget->setItem(0,0,item); ui->tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("q0")); ui->tableWidget->setVerticalHeaderItem(0, new QTableWidgetItem("b")); } Inicijalno, dimenzije funkcionalne sheme su postavljene na 1x1, što odgovara trojci odreĊenoj parom poĉetnog stanja i praznog simbola, a tekst zaglavnih ćelija se postavlja shodno tome. Zadana trojka na koju se postavlja prva ćelija oznaĉava da je rezultantno stanje uĉitavanja praznog simbola tijekom bivanja u poĉetnom stanju ponovno poĉetno stanje, i da pomaka glave za ĉitanje i pisanje nema. 6 3.3.1. Unos i ažuriranje funkcionalne sheme UreĊivanje funkcionalne sheme ima dvije komponente: dodavanje i brisanje elemenata skupa unutarnjih stanja i vanjske abecede, i unošenje trojki u shemu. Objekti klasa AddDialog i RemoveDialog se stvaraju klikom na odreĊene gumbe na suĉelju, a TableEditor se instancira dvostrukim klikom na ćeliju sheme. To instanciranje je izvedeno niţe navedenom konekcijom. connect(ui->tableWidget, SIGNAL(cellClicked(int,int)), this, SLOT(editDialog(int,int))); Signal cellClicked(int,int) šalje oznaku retka i stupca kojima ćelija pripada. Slot prima te argumente i koristi ih za ureĊivanje sheme. void MainWindow::editDialog(int r, int c) { int a = r; int b = c; QTableWidget *table = dynamic_cast<QTableWidget*>(sender()); TableEditor *t = new TableEditor(this); //... } Osim indeksa ćelije, pribavlja i pokazivaĉ na QTableWidget posebnom naredbom koja vraća pokazivaĉ na objekt koji je poslao signal slotu. Dijalog direktno ureĊuje tablicu, a za to mu trebaju upravo indeks ćelije i pokazivaĉ na objekt. 7 Korisnik tableWidget TableEditor "Uredi ovu ćeliju" <indeks ćelije> "Unesite postavke ćelije" <sadržaj ćelije> "Napravi string" <nova vrijednost ćelije> Slika 1.: MSC dijagram procesa uređivanja ćelije funkcionalne sheme Na Slici 1. prikazana je razmjena poruka izmeĊu korisnika, funkcionalne sheme i ureĊivaĉa ćelije. TableEditor je instanca klase ureĊivaĉa funkcionalne sheme. Nakon što korisnik unese sadrţaj ćelije koji ţeli postaviti, ureĊivaĉ sam sebi pošalje signal da unesene vrijednosti pretvori u string koji onda pošalje funkcionalnoj shemi, postavljajući tekstualnu vrijednost ćelije na formirani string. Općenito, pri unosu ili novih stanja, ili novih simbola, stvaraju se novi stupci, odnosno redci i postavljaju se njihove zaglavne ćelije. Ovo je demonstrirano narednim odsjeĉkom koda koji pripada funkciji addState, funkciji odgovornoj za dodavanje stanja. void MainWindow::addState(){ int cCount = states.size(); states.append(QString("q%1").arg(cCount)); populateCombo(); cCount++; ui->tableWidget->setColumnCount(cCount); cCount--; ui->tableWidget->setHorizontalHeaderItem(cCount, new QTableWidgetItem(QString("q%1").arg(cCount))); for(int i=0; i<ui->tableWidget->columnCount(); i++) { 8 QTableWidgetItem *item = new QTableWidgetItem(); item->setText(" "); ui->tableWidget->setItem(i, cCount, item); } } Prvo se funkcijom size() pribavlja broj elemenata u listi da bi se mogao izvesti indeks novog stanja. Budući da indeksiranje liste poĉinje od nule, što znaĉi da k-ti element ima indeks k-1, broj elemenata u nekoj listi odgovara indeksu elementa koji bi se dodao na kraj liste. Kad aplikacija pribavi broj elemenata u listi, stvori QString spajanjem znaka q i indeksa tog novog stanja u listi. Indeksi stanja se isto poĉinju brojati od nule, što znaĉi da je indeks svakog stanja u listi jednak njegovom indeksu kao ĉlana skupa internih stanja. Funkcija updateCombo nakon pohrane novog stanja u listu aţurira popise opcija padajućih izbornika koji se koriste u ureĊivaĉu ćelija. Poslije unosa novog stanja u listu, aţuriraju se dimenzije i sadrţaj tablice. Dodaje se novi stupac uz desni rub tablice. Tekst zaglavne ćelije se postavlja tako da odraţava novo dodano stanje i oznaĉi taj stupac kao zonu presjeka tog stanja i pojedinih znakova vanjske abecede. Iteriranjem kroz for petlju aplikacija prolazi kroz svaku ćeliju novododanog stupca i postavlja nihove tekstualne vrijednosti na " ". Uklanjanje stanja i simbola se odvija preko instance klase RemoveDialog putem koje korisnik odabire stanje ili simbol koji ţeli ukloniti. Nakon što korisnik unese svoj odabir, aplikacija traţi stupac ili redak koji odgovara uklonjenom elementu, uklanja ga iz tablice te iterira kroz cijelu tablicu aţurirajući pohranjene trojke. Trojke ne smiju pokazivati na nepostojeća stanja ili nepostojeće simbole, stoga je nuţno svaku trojku provjeriti i izmijeniti prema potrebi. To je pokazano idućim kodnim odsjeĉkom koji je dio funkcije removeState kojom aplikacija uklanja stanja iz skupa te shodno tome aţurira tablicu. for(int i=0; i<=states.size(); i++) { for(int j=0; j<symbols.size(); j++) { if(ui->tableWidget->item(j,i)!=0) { item= ui->tableWidget->item(j, i)->text(); triplet= item.split(", "); 9 if(triplet.size()==3) { QString number = triplet.at(0); if(number!="qF") { number.remove(0,1); int newIndex = number.toInt(); if(newIndex>0) newIndex--; triplet.replace(0,QString("q%1").arg(newIndex)); QString set= QString(); set=triplet.join(", "); ui->tableWidget->item(j, i)->setText(set); } } else { QTableWidgetItem *it = new QTableWidgetItem(); ui->tableWidget->setItem(j, i, it); } Aplikacija uĉitava trojku pohranjenu u ćeliji te tako dobivenim QStringom manipulira tako da moţe razluĉiti koje stanje je u trojci zabiljeţeno kao iduće. Oznaci uĉitanog stanja oduzima znak q i konverzijom tako dobivenog stringa u broj dobiva indeks tog stanja u QString listi. Ako taj indeks odgovara indeksu onog stanja kojeg aplikacija uklanja, aplikacija postavlja indekse stanja tako da pokazuju na neko postojeće stanje. 3.3.2. Pohrana i naknadno učitavanje Spremanje funkcionalne sheme u datoteku se odvija kroz objekt klase QFileDialog, dijaloški okvir definiran za upravljanje datototekama. Korisnik unosi ime datoteke koje se zatim koristi za instanciranje objekta klase QFile. QFile pruţa suĉelje za ĉitanje i pisanje datoteka6. Tom objektu se pridruţuje instanca klase QDataStream koja predstavlja tok podataka. Da bi se funkcionalna shema uspješno pohranila, treba spremiti vanjsku abecedu i skup unutarnjih stanja, izvući podatke iz QTableWidget objekta i pretvoriti ih u oblik koji se 6 http://qt-project.org/doc/qt-5/qfile.html (18.11.2014.) 10 moţe proslijediti otvorenom toku podataka. QTableWidget se ne moţe pohraniti stavljanjem u QDataStream tok podataka budući da objekti navedene klase sluţe za serijalizaciju binarnih tipova podataka. U suštini, svi podaci su binarni, ali samo neki tipovi podataka se mogu tako spremati i ĉitati neovisno o platformi7. Takvi podaci ukljuĉuju jednostavne standardne podatkovne tipove poput integer, double, i float, te objekte pojedinih Qt-ovih klasa. QTableWidget nije tip podatka, već sloţeni objekt, widget, stoga jednostavno stavljanje njegovih podataka u podatkovni tok nije moguće. Podaci se izvlaĉe iz funkcionalne sheme iteriranjem ugnijeţĊenim for petljama. U svakoj iteraciji, tekst spremljen u ćeliji widgeta se pohranjuje u za tu svrhu deklariran QStringList saveData. QStringList saveData; for(int row=0; row<symbols.size(); row++) { for(int column=0; column<states.size(); column++) { if(!ui->tableWidget->item(row, column)||ui->tableWidget->item(row, column)>text().isEmpty()) { saveData.append(" "); } else { saveData.append(ui->tableWidget->item(row, column)->text()); } } } Nakon uspješnog izvlaĉenja teksta svih ćelija sheme, podaci se pohranjuju. out<<states<<symbols<<saveData; file.close(); Otvaranje datoteke se odvija vrlo sliĉno. Otvara se dijaloški okvir putem kojeg korisnik odabire datoteku koju ţeli otvoriti. Otvara se novi tok podataka iz kojeg uĉitavamo podatke u 7 http://qt-project.org/doc/qt-4.8/datastreamformat.html (18.11.2014.) 11 datoteci. Prilikom otvaranja, vrlo je bitno uĉitavati podatke onim redoslijedom kojim smo ih zapisali8. Uĉitavamo podatke iz podatkovnog toka i spremamo ih u states, symbols i QStringList loadData. for(int row = 0; row<symbols.size();row++) { ui->tableWidget->setVerticalHeaderItem(row, new QTableWidgetItem(symbols.at(row))); for (int column=0; column<states.size(); column++) { ui->tableWidget->setHorizontalHeaderItem(column, new QTableWidgetItem(states.at(column))); QTableWidgetItem *item=new QTableWidgetItem; ui->tableWidget->setItem(row, column, item); ui->tableWidget->item(row, column)->setText("###"); }} Aplikacija pripremi QTableWidget objekt za postavljanje podataka tako da mu broj stupaca i redaka postavi na broj podataka spremljenih u odgovarajućim QStringList spremnicima. Broj stupaca mora biti jednak broju unutarnjih stanja, a broj redaka mora biti jednak broju simbola vanjske abecede. Naslovi stupaca i redaka se isto postavljaju prema skupu unutarnjih stanja i vanjske abecede. Zatim aplikacija doda ćelije QTableWidget objektu i pstavlja njihovu tekstualnu vrijednost na " ###". Podaci koje je aplikacija preuzela iz podatkovnog toka i pohranila u loadData se iteracijom kroz listu postavljaju u svaku ćeliju. for(int i=0; i<loadData.size();i++) { int row=i/symbols.size(); int column= i%symbols.size(); ui->tableWidget->item(row, column)->setText(loadData.at(i)); } Aplikacija zatim zatvara podatkovni tok i datoteku iz koje je uĉitala podatke. 8 http://qt-project.org/doc/qt-4.8/qdatastream.html (18.11.2014.) 12 3.4. Izvedba vanjske memorije Vanjska memorija je takoĊer izvedena korištenjem QTableWidgeta. QTableWidget kojim ju aplikacija izvodi ima skrivene zaglavne ćelije, stupce i retke fiksnih dimenzija i posebno postavljen font. Na widget je postavljen i poseban delegat. QTableWidget nije dio Qt-ove izvedbe MVC programiranja budući da ne odvaja podatke od modela, ali moguće je postavljati delegate na objekte te klase9. Vanjska memorija je inicijalizirana kao tablica sa jednim retkom i 10 stupaca, dakle 10 ćelija, i bez okvira. Budući da je i ovaj objekt dodan aplikaciji u Qt Designeru, i njemu se pristupa preko ui pokazivaĉa. ui->tableWidget_2->setRowCount(1); ui->tableWidget_2->setColumnCount(10); ui->tableWidget_2->setFrameStyle(QFrame::NoFrame); QFont *font = new QFont(); font->setPointSize(30); 3.4.1. Unos i ažuriranje Već spomenuta klasa TapeDelegate je klasa izvedena iz QStyledItemDelegate klase. Implementacija izvedenog delegata mora reiplementirati barem tri funkcije: createEditor(), setEditorData() i setModelData(). Funkcija createEditor() stvara ureĊivaĉ modela, widget putem kojeg će korisnik modificirati podatke. TapeDelegate kao ureĊivaĉ koristi padajući izbornik koji je objekt clase QComboBox. QWidget* TapeDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const { if(index.row() != 0) return QStyledItemDelegate::createEditor(parent, option, index); QComboBox *cb = new QComboBox(parent); //stvara ureĊivaĉ ćelije vanjske memorije cb->addItems(MainWindow::getSymbols()); return cb; } 9 http://qt-project.org/doc/qt-4.8/qtablewidget.html (18.11.2014.) 13 Funkcija setEditorData() predaje ureĊivaĉu podatke koji se trenutno nalaze u ćeliji, a funkcija setModelData preuzima unesene podatke iz ureĊivaĉa te ih proslijeĊuje tabliĉnom podatkovnom modelu. Ako korisnik unese prazni simbol, tekstualna vrijednost odabrane ćelije se postavlja na " ". Od nekoliko podvrsti Turingovog stroja10, aplikacija implementira onu ĉija traka se proteţe u beskonaĉnost na oba kraja. Upravljanje duljinom trake se izvan simulacije obavlja dvama funkcijama: lengthenTape() koja traku produljuje za jednu ćeliju, tj. umetne prazni stupac u QTableWidget na samom rubu tablice, i shortenTape() koja traku skrati za jednu ćeliju uklanjanjem krajnjeg stupca. Tijekom simulacije, produljivanje trake se vrši prema potrebi unutar funkcije goForth() o kojoj će kasnije biti rijeĉi. 3.4.2. Pohrana i naknadno učitavanje Vanjska memorija se pohranjuje u datoteke sa ekstenzijom .tst. Funkcija spremanja vanjske memorije saveTape() se od funkcije spremanja funkcionalne sheme saveShema() razlikuje samo po ekstenziji datoteke i naĉinu izvlaĉenja podataka iz widgeta. Za razliku od funkcionalne sheme za ĉiju definiciju je nuţno imati definiranu vanjsku abecedu i skup unutarnjih stanja, vanjsku memoriju ne odreĊuje ništa drugo osim nje same. Njezina struktura je jednostavnija od strukture funkcionalne sheme te je naĉin izvlaĉenja podataka iz nje jednostavniji. Iteriranjem kroz jedini redak pripadajućeg QTableWidgeta i pohranjivanjem tekstualne vrijednosti svake ćelije u QStringList saveData dobiva se lista QStringova koju se jednostavno proslijedi u podatkovni tok. Ako je tekstualna vrijednost neke ćelije prazna, kao simbol se pohranjuje string " ". for(int column =0; column < ui->tableWidget_2->columnCount(); column++) { if(!ui->tableWidget_2->item(0, column)||ui->tableWidget_2->item(0, column)>text().isEmpty()) { saveData.append(" "); }else { saveData.append(ui->tableWidget_2->item(0, column)->text()); 10 http://plato.stanford.edu/entries/turing-machine/ (18.11.2014.) 14 } Uĉitavanje vanjske memorije iz datoteke se odvija po istom procesu kao i otvaranje funkcionalne sheme. Prvo se dijaloškim okvirom od korisnika zatraţi odabir datoteke. Instancira se datoteĉni objekt klase QFile kojem se pridruţi objekt podatkovnog toka klase QDataStream. QString fileName = QFileDialog::getOpenFileName(this, QString("Otvaranje..."), QString(""),QString("Vanjska memorija (*.tst);;Sve datoteke (*.*)")); if (fileName.isEmpty()) { return; //izlazi iz funkcije ako korisnik ne zada ime datoteke } else { QFile file(fileName); if (!file.open(QIODevice::ReadOnly)) { QMessageBox::information(this, QString("Greška!"), QString("Datoteka se ne moţe otvoriti"), QMessageBox::Ok); return; } QDataStream in(&file); in.setVersion(QDataStream::Qt_4_5); Svaka verzija Qt-a izaĊe sa malo drukĉijom specifikacijom odreĊenih klasa i koncepata. Binarni formati Qt-a su se isto mijenjali kroz razvoj okruţenja i vrlo je vaţno datoteku spremiti prema onoj verziji binarnog formata koja će se koristiti prilikom uĉitavanja datoteke. Naredba setVersion() izriĉito biljeţi prema kojoj verziji Qt-a se definira binarni format datoteke11. 3.5. Izvedba simuliranja Već spomenuta funkcija goForth() je ta koja vrši simuliranje rada stroja po taktovima. Na Slici 7. je prikazana aplikacija usred simuliranja rada Turingovog stroja. Aplikacija vrši pomake na traci, uĉitavanje simbola, mijenjanje stanja te ispis simbola, i ispisuje zapise 11 http://qt-project.org/doc/qt-4.8/qdatastream.html (18.11.2014.) 15 taktova u obliku (trenutno stanje, ulazni simbol) --> (iduće stanje, izlazni simbol, pomak). Kontrole koje su korisniku na raspolaganju su kontrole potrebne za simulaciju koje su aktivne kad je naĉin davanja takta ruĉan. U bilokojem trenutku, korisnik moţe promijeniti naĉin davanja takta. Osim funkcije goForth(), u simulaciji sudjeluju i neki podatkovni ĉlanovi klase MainWindow. StepCount je podatkovni ĉlan tipa integer koji pohranjuje broj odraĊenih taktova, napoĉetku postavljen na vrijednost 0. CurrentConfiguration je isto cjelobrojni podatkovni ĉlan koji pohranjuje broj konfiguracija koje je stroj prošao. Na poĉetku programa je jednak 1 jer je prva konfiguracija ona na poĉetku prvog takta. AutoStep je logiĉkog tipa i mijenja se s obzirom na to da li je davanje takta ruĉno ili automatski. Ako je njegova vrijednost false, davanje takta je postavljeno kao ruĉno. Budući da neki elementi suĉelja poput gumbova za davanje takta i traţenje k-te konfiguracije ne smiju biti aktivni dok je davanje takta automatsko, bitno je negdje u aplikaciji nekako pratiti postavke naĉina davanja takta. Gumbom takt:auto u alatnoj traci korisnik moţe prebacivati s jednog naĉina davanja takta na drugi. Da bi gumb ispravno mijenjao naĉine davanja takta na korisnikov klik, mora nekako znati koji naĉin davanja takta je trenutno postavljen. Sliĉnu funkciju ima i podatkovni ĉlan simActive koji je isto logiĉkog tipa. SimActive prati da li je korisnik poĉeo simulaciju ili ne. void MainWindow::goForth() { int row, column, move, tapeCell; QString cSymbol, cState, next; QStringList triplet; QModelIndex index; QString quintuplet; U funkciji deklariramo pomoćne varijable. Row i column sluţe za odreĊivanje ćelije funkcionalne sheme iz koje aplikacija uzima trojku. Move sluţi za matematiĉko odreĊivanje pomaka, a tapeCell pohranjuje oznaku stupca u kojem se nalazi glava za ĉitanje i pisanje. CSymbol, i cState pohranjuju trenutni par, a next pohranjuje QString dobavljen iz odreĊene ćelije koji predstavlja trojku. Next nakon dobavljanja iz funkcionalne sheme razlamamo u triplet radi razluĉivanja pomaka od idućeg stanja i izlaznog simbola. Index se koristi pri odreĊivanju indeksa iduće ćelije, a quintuplet predstavlja zapis takta. 16 Korisnik prije poĉetka simulacije bira poĉetnu ćeliju trake. Ima i mogućnost biranja trenutnog stanja putem padajućeg izbornika. Ako je uĉitan QString " ", ulazni simbol se pohranjuje kao "b". Tijekom traţenja trojke, aplikacija traţi ulazni simbol u QStringListu symbols u kojem je prazni znak zabiljeţen kao "b". cSymbol=ui->tableWidget_2->currentItem()->text(); if(cSymbol==" ") { cSymbol="b"; } cState=ui->comboBox->currentText(); column=states.indexOf(cState); row=symbols.indexOf(cSymbol); next=ui->tableWidget->item(row, column)->text(); ui->tableWidget->setCurrentCell(row, column); Nakon uĉitavanja para, aplikacija izvlaĉi trojku iz odreĊene ćelije funkcionalne sheme i postavlja ju kao trenutno odabranu ćeliju. To omogućava korisniku da tijekom simulacije prati koja trojka se toĉno izvršava što moţe pomoći pri osmišljavanju logiĉke funkcije Turingovog stroja. Ako je uĉitana trojka prazna, aplikacija javlja korisniku da odreĊenom paru nije pridruţena trojka. Ako trojka nije prazna, next se funkcijom triplet = next.split(", ") razdvaja na tri QStringa koja se spreme u triplet. Aplikacija zatim ĉitanjem svakog QStringa odreĊuje odvijanje trenutnog takta. Budući da je trojka spremljena u uniformiranom formatu "qn, s, m", gdje je qn trenutno stanje, s ulazni simbol, a m pomak, aplikacija moţe bez problema odrediti koji QString znaĉi što. Tako je prvi QString u tripletu (triplet.at(0)) uvijek iduće stanje, drugi je izlazni simbol, a treći je pomak. if(triplet.at(0)=="qF") { QMessageBox message; message.setText("Stroj je došao u konaĉno stanje!"); message.setWindowTitle("SiTuS"); message.exec(); simActive=false; 17 autoStep=false; timer->stop(); }else { ui->comboBox->setCurrentText(triplet.at(0)); Aplikacija svaki put provjeri da li je ušla u konaĉno stanje usporeĊivanjem prvog QStringa tripleta sa QStringom "qF". Ako je iduće stanje zaista konaĉno, aplikacija obustavlja simulaciju i obavještava korisnika o ulasku u konaĉno stanje. Inaĉe, aplikacija kao trenutnu vrijednost padajućeg izbornika postavlja iduće stanje. Padajući izbornik ne sluţisamo koa mogućnost ruĉnog postavljanja trenutnog stanja, već i kao indikator tog istog. Pomak se raĉuna izrazom move=shifts.indexOf(triplet.at(2)) - 1; kojim se dobiva cjelobrojna vrijednost iskoristiva za odreĊivanje indeksa iduće ćelije trake. Oznake pomaka su u QStringListi poredane ovako: "L", "N", "D". Njihovi indeksi su, redom: 0, 1, 2. Ako od svakog oduzmemo 1, dobivamo -1, 0, 1, što odgovara pomaku ulijevo, izostanku pomaka i pomaku udesno kretanjem po indeksima stupaca QTableWidgeta koji predstavlja traku. index=ui->tableWidget_2->currentIndex(); tapeCell=index.column(); if(tapeCell==ui->tableWidget_2->columnCount()-2) //ako je blizu desnog ruba { ui->tableWidget_2->insertColumn(ui->tableWidget_2->columnCount()); ui->tableWidget_2->setItem(0, ui->tableWidget_2->columnCount()-1, item); ui->tableWidget_2->setCurrentCell(0, tapeCell+move); //dodaj ćeliju desno }else if((tapeCell+move)<0) //ako je u prvoj ćeliji i miĉe se ulijevo { ui->tableWidget_2->insertColumn(0); QTableWidgetItem *item = new QTableWidgetItem(); item->setTextAlignment(Qt::AlignCenter); QFont *font = new QFont(); font->setPointSize(30); //dodaj ćeliju slijeva item->setFont(*font); 18 item->setText(" "); ui->tableWidget_2->setItem(0, 0, item); ui->tableWidget_2->setCurrentCell(0,0); }else { ui->tableWidget_2->setCurrentCell(0, tapeCell+move); } Budući da aplikacija simulira Turingove strojeve sa trakama koje su beskonaĉne duljine s obje strane, nuţno je da aplikacija provjerava bliţi li se rubu trake te da ju produlji ako je to potrebno. stepCount++; currentConfiguration++; quintuplet= QString("%1.takt:(%2,%3)-->(%4)"). arg(stepCount).arg(cState).arg(cSymbol).arg(triplet.join(", ")); Budući da je takt završen u ovom trenutku, aplikacija povećava vrijednosti stepCount i currentConfiguration te formira zapis takta koji zatim sprema u QListWidget koji sluţi kao zapisnik taktova. 19 tableWidget_2 Korisnik tableWidget MainWindow listWidget "Ovo je početna pozicija" "Simuliraj!" "Koji je ulazni simbol?" <ulazni simbol> "Koje je trenutno stanje?" "Koja trojka odgovara ovom paru?" <qn, s, m> <iduće stanje> <pomak> <izlazni simbol> <zapis takta> Slika 2.: MSC dijagram razmjene poruka tijekom ručno danog takta Na Slici 2. je opisana cijela razmjena poruka tijekom jednog ruĉno danog takta. TableWidget_2 je ime objekta koji predstavlja vanjsku memoriju, a listWidget je ime objekta koji predstavlja zapisnik taktova. if(ui->radioButton_2->isChecked()) { timer=new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(goForth())); timer->start(1500); ui->comboBox->setEnabled(false); //<--onemogućuje padajući izbornik this->autoStep=true; //koji sluţi kao indikator i biraĉ trenutnog stanja RadioButton_2 je gumb kojim korisnik na poĉetku odabire automatsko davanje takta. Ako je gumb stisnut, stvara se objekt klase QTimer koji u zadanim intervalima emitira signal timeout(). Jedan takt ovdje zadanog tajmera traje 1500 milisekundi i njegov timeout() signal povezan je sa funkcijom goForth() koja je definirana kao slot. 20 3.4. Prikaz k-te konfiguracije Za prikaz k-te konfiguracije Turingovog stroja, stroj mora odraditi k-1 taktova. Korisnik u bilokojem trenutku dok je davanje takta ruĉno moţe zatraţiti od aplikacije prikaz k-te konfiguracije. Moţe zatraţiti prikaz konfiguracije nakon trenutne, a moţe i zatraţiti konfiguraciju prije trenutne. Za sluĉaj kada aplikacija mora ići unazad, osmišljena je funkcija goBack() koja je ujedno i slot. QString step= ui->listWidget->item(stepCount)->text(); int remove=step.indexOf("("); step.remove(0, remove+1); remove=step.indexOf(")"); step.replace(remove,7,", "); step.remove(")"); Funkcija iz zapisnika taktova izvuĉe zapis takta koji mora obrnuti. Zatim ga sa nekoliko operacija oblikuje u format "qn, s, m, qm, z" gdje je qn trenutno stanje, s ulazni simbol, m pomak, qm iduće stanje, a z je izlazni simbol. Nakon oblikovanja, aplikacija naredbom quintuplet = step.split(", "); razlomi zapis takta u QStringListu quintuplet iz koje zatim izvlaĉi informacije potrebne za preokretanje takta. Ulazni simbol uĉitan u ovom taktu postaje izlazni simbol, trenutno stanje postaje iduće, a pomak se mnoţi sa -1. Aplikacija takav takt izvrši kao i inaĉe, s time da smanji umjesto da poveća stepCount i currentConfiguration tako da aplikacija moţe toĉno pratiti u kojem je taktu. Prikaz k-te konfiguracije Turingovog stroja generira funkcija getConfiguration(); koja dijaloškim okvirom zatraţi korisnika da unese broj konfiguracije koju ţeli vidjeti. Odabrani broj se sprema u varijablu a. Ovisno o odnosu varijable a i vrijednosti currentConfgurationa, funkcija odabire da li će pozvati funkciju goBack() ili goForth(). Ako korisnik ţeli ići naprijed kroz simulaciju, tj. ţeli vidjeti konfiguraciju koja dolazi nakon trenutne, aplikacija mora ići naprijed, stoga u tom sluĉaju poziva funkciju goForth(). U suprotnom sluĉaju, aplikacija zove funkciju goBack. Ako korisnik zatraţi pregled konfiguracije koja u tom trenu već jest prikazana, aplikacija izlazi iz tog bloka naredbi. if(a>currentConfiguration) { for(int i = currentConfiguration; i<a; i++ ) { 21 goForth(); } }else if(a<currentConfiguration) { for(int i =currentConfiguration; i>a;i--) { goBack(); } currentConfiguration=a; Kada završi sa iteriranjem, aplikacija broj traţene konfiguracije postavi kao broj trenutne konfiguracije. Simulator u svakom trenutku mora znati u kojem je taktu i koju konfiguraciju trenutno prikazuje. 4. RASPRAVA Programsko rješenje problema simuliranja rada Turingovog stroja predstavljeno ovim radom nije jedino moguće rješenje. Jednom problemu se moţe pristupiti na nekoliko naĉina, a ovaj problem nije izlika. Pristup korišten pri osmišljavanju ovog rješenja vodi se proceduralnom paradigmom programiranja. Proceduralno programiranje odvaja podatke od operacija nad njima i svodi se na slanje podataka odreĊenim funkcijama12. Iako ovo rješenje koristi klase i objekte, u suštini je proceduralno programirano. Od šest izvedenih klasa korištenih u ovom rješenju, samo MainWindow se moţe iole gledati kao objedinjenje podataka i procedura nad njima budući da su ostale klase pomoćne i sluţe samo kao produţeci procedura definiranih u klasi MainWindow. Rješenje se svodi na procedure kojima se pristupa i manipulira podacima bez pokušaja dizanja koncepta na višu razinu. Objektno orijentirano programiranje se ĉesto spominje kao bolji pristup od proceduralnog zbog svoje fleksibilnosti, nelinearnosti i općeg pogleda na probleme. Dok proceduralno programiranje za svaki tip podataka nalazi drukĉije rješenje, objektno orijentirano programiranje pokušava objediniti podatke i metode nad njima u klase koje se onda proširuju nasljeĊivanjem i polimorfizmom13. Ovo rješenje kombinira dinamiĉno 12 13 http://ocw.utm.my/file.php/42/01PPvsOOP-edit15Feb13.pdf (18.11.2014.) http://www.virtuosimedia.com/dev/php/procedural-vs-object-oriented-programming-oop 22 korištenje objekata sa proceduralnim pristupom problemu i ne moţe se nazvati niti ĉisto proceduralnim, niti ĉisto objektno orijentiranim rješenjem, ali oĉito je koji pristup je dominantan. Objektno orijentirano rješenje bi se moglo izvesti tako da se trojke i parovi implementiraju kao objekti koji nadograĊuju jedan drugog, ili da se ĉak spoje u jedan objekt koji bi predstavljao cijelu petorku. U tom sluĉaju, funkcionalna shema bi se mogla izvesti MVC programiranjem. Osmislio bi se podatkovni model prilagoĊen spremanju objekata i slanju relevantnih atributa drugim pogledima koji bi se izveo kao podklasa QAbstractTableModel. Ako bismo kao osnovni objekt uzeli petorku, mogli bismo funkcionalnu shemu i zapisnik taktova izvoditi iz istih podataka razliĉitim pogledima. Bilo bi nuţno implementirati i specifiĉne delegate, barem za funkcionalnu shemu. Iako se objektno orijentirani pristup ĉesto promovira kao najbolji pristup programiranju, on nije uvijek primjeren pristup problemu. Objektno orijentirano programiranje je korisno kada se problem sastoji od koncepata koji su apstrakcija stvarnih objekata. Osobe, vozila, poduzeća i sliĉno se ne mogu svesti na jedan string kojim se jednostavnim manipulacijama moţe doći do rješenja problema. Iako bi se rješenje problema simuliranja Turingovog stroja itekako elegantno moglo riješiti objektno orijentiranim programiranjem, pristup predstavljen u ovom radu je jednostavniji. Problematika simuliranja Turingovog stroja nije toliko kompleksna da bi bila znatno bolje riješena objektno orijentiranim programiranjem, stoga ovo rješenje nije pristupalo problemu na taj naĉin. 23 5. ZAKLJUČAK Problematka simuliranja Turingovog stroja je zanimljiva budući da je Turingov stroj jedan od bitnih koncepata raĉunalnih znanosti. Kao koncept izvršitelja algoritama, predstavlja matematiĉku apstrakciju ljudskog razmišljanja te je kao takva neizostavan dio svakog iole informatiĉko usmjerenog obrazovanja. Turing je svojim definiranjem takvih strojeva dotaknuo vrlo bitno pitanje: pitanje izraĉunljivosti. Postoji beskonaĉno mnogo problema koji bi se mogli riješiti prikladnim Turingovim strojem, kao što postoji i beskonaĉno mnogo problema na koje sam koncept Turingovog stroja nije uopće primijenjiv. Iako je koncept Turingovog stroja vaţan za shvaćanje stvaranja algoritama i razlaganja tog istog na jednostavne operacije, sam rad stroja je u suštini jednostavan i lagan za programsku izvedbu, što se i pokazalo rješenjem prezentiranim u ovom radu. Rješenje se svodi na skup operacija nad jednostavnim podacima ĉiji rezultati su vizualizirani objektnoorijentirano stvaranim grafiĉkim elementima. Iako se moglo izvesti ĉisto objektnoorijentiranim pristupom, za time nije bilo potrebe. Rad Turingovog stroja se svodi na automatizirano ĉitanje i pisanje što je programski vrlo jednostavno izvesti. Rješenje predstavljeno ovim radom nije jedino rješenje problematike simuliranja rada Turingovog stroja uz programibilnost logiĉkog polja i mogućnost unošenja razliĉitih informacija za obradu razliĉitim Turingovim strojevima, ali je dovoljno jednostavno i stabilno da bi se moglo smatrati prikladnim. Rješenje sadrţi sve osnovne funkcionalnosti definirane zahtjevima problematike, što ga ĉini dobro izvedenim simulatorom Turingovog stroja. 24 6. POPIS LITERATURE Knjige: Jukić, O., Špoljarić, M. (2010): Uvod u graĊu raĉunala. Virovitica, VŠMTI Članci: Turing, A. M. (1936): On Computable Numbers, With An Application To The Entscheidungsproblem. Proceedings of the London Mathematical Society, Series 2, vol.42:230-265 Online izvori: 1. http://www.cplusplus.com/reference/string/string/append/ (18.11.2014.) 1. http://ocw.utm.my/file.php/42/01PPvsOOP-edit15Feb13.pdf (18.11.2014.) 2. http://plato.stanford.edu/entries/turing-machine (18.11.2014.) 3. http://qt-project.org/doc/qt-4.8/qdatastream.html (18.11.2014.) 4. http://qt-project.org/doc/qt-4.8/datastreamformat.html (18.11.2014.) 5. http://qt-project.org/doc/qt-4.8/signalsandslots.html (18.11.2014.) 6. http://qt-project.org/doc/qt-5/qfile.html (18.11.2014.) 7. https://qt-project.org/doc/qtcreator-2.5/creator-overview.html (18.11.2014.) 8. http://www.virtuosimedia.com/dev/php/procedural-vs-object-oriented-programming-oop (18.11.2014.) 25 7. POPIS ILUSTRACIJA Slika 1.: MSC dijagram procesa ureĊivanja ćelije funkcionalne sheme Slika 2.: MSC dijagram razmjene poruka tijekom ruĉno danog takta 26
© Copyright 2024 Paperzz