Ανάπτυξη προσομοιωτή πολυταινιακής μηχανής Turing



Σχετικά έγγραφα
Υπολογίσιμες Συναρτήσεις

Άδειες Χρήσης Το παρόν εκπαιδευτικό υλικό υπόκειται σε άδειες χρήσης Creative Commons. Για εκπαιδευτικό υλικό, όπως εικόνες, που υπόκειται σε άλλου τύ

ΕΠΛ 211: Θεωρία Υπολογισμού και Πολυπλοκότητας. Διάλεξη 13: Παραλλαγές Μηχανών Turing και Περιγραφή Αλγορίθμων

Περιεχόμενα Ορισμός και λειτουργία των μηχανών Turing Θεωρία Υπολογισμού Ενότητα 20: Μηχανές Turing: Σύνθεση και Υπολογισμοί Επ. Καθ. Π. Κατσαρός Τμήμ

Θεωρία Υπολογισμού Άρτιοι ΑΜ. Διδάσκων: Σταύρος Κολλιόπουλος. eclass.di.uoa.gr. Περιγραφή μαθήματος

Θεωρία Υπολογισμού Αρτιοι ΑΜ Διδάσκων: Σταύρος Κολλιόπουλος eclass.di.uoa.gr

Άδειες Χρήσης Το παρόν εκπαιδευτικό υλικό υπόκειται σε άδειες χρήσης Creative Commons. Για εκπαιδευτικό υλικό, όπως εικόνες, που υπόκειται σε άλλου τύ

Θεωρία Υπολογισμού και Πολυπλοκότητα

num(m(w 1 ;... ; w k )) = f(num(w 1 ),..., num(w k ))

Προγραμματισμός ΙI (Θ)

ΑΝΑΠΤΥΞΗ ΕΦΑΡΜΟΓΩΝ ΣΕ ΠΡΟΓΡΑΜΜΑΤΙΣΤΙΚΟ ΠΕΡΙΒΑΛΛΟΝ

Ειδικά θέματα Αλγορίθμων και Δομών Δεδομένων (ΠΛΕ073) Απαντήσεις 1 ου Σετ Ασκήσεων

Μηχανές Turing (T.M) I

ΘΕΩΡΙΑ ΥΠΟΛΟΓΙΣΜΩΝ ΚΑΙ ΑΥΤΟΜΑΤΩΝ

ΔΙΑΓΩΝΙΣΜΑ ΠΡΟΣΟΜΟΙΩΣΗΣ ΑΝΑΠΤΥΞΗ ΕΦΑΡΜΟΓΩΝ ΣΕ ΠΡΟΓΡΑΜΜΑΤΙΣΤΙΚΟ ΠΕΡΙΒΑΛΛΟΝ

Πληροφορική & Τηλεπικοινωνίες K18 - Υλοποίηση Συστηµάτων Βάσεων εδοµένων Εαρινό Εξάµηνο

Σειρά Προβλημάτων 4 Λύσεις

ΤΡΙΩΡΗ ΓΡΑΠΤΗ ΔΟΚΙΜΑΣΙΑ

Πληροφορική & Τηλεπικοινωνίες. K18 - Υλοποίηση Συστημάτων Βάσεων Δεδομένων Εαρινό Εξάμηνο

#include <stdlib.h> Α. [-128,127] Β. [-127,128] Γ. [-128,128]

'Ασκηση 1: Στατικός Κατακερματισμός. Εισαγωγή. Ρουτίνες υλοποίησης κατακερματισμού. (Ημερομηνία Παράδοσης: Παρασκευή, 16/5/2008, 5μμ) HT_Init()

CSC 314: Switching Theory

Η δυαδική σχέση M ( «παράγει σε ένα βήμα» ) ορίζεται ως εξής: (q, w) M (q, w ), αν και μόνο αν w = σw, για κάποιο σ Σ

Άσκηση 1 (ανακοινώθηκε στις 20 Μαρτίου 2017, προθεσμία παράδοσης: 24 Απριλίου 2017, 12 τα μεσάνυχτα).

2ο ΓΕΛ ΑΓ.ΔΗΜΗΤΡΙΟΥ ΑΕΠΠ ΘΕΟΔΟΣΙΟΥ ΔΙΟΝ ΠΡΟΣΟΧΗ ΣΤΑ ΠΑΡΑΚΑΤΩ

Άδειες Χρήσης Το παρόν εκπαιδευτικό υλικό υπόκειται σε άδειες χρήσης Creative Commons. Για εκπαιδευτικό υλικό, όπως εικόνες, που υπόκειται σε άλλου τύ

Πληροφορική 2. Αλγόριθμοι

2 ΟΥ και 7 ΟΥ ΚΕΦΑΛΑΙΟΥ

ΑΝΑΠΤΥΞΗ ΕΦΑΡΜΟΓΩΝ ΣΕ ΠΡΟΓΡΑΜΜΑΤΙΣΤΙΚΟ ΠΕΡΙΒΑΛΛΟΝ ΕΠΑΝΑΛΗΠΤΙΚΟ ΔΙΑΓΩΝΙΣΜΑ ΣΧΟΛΙΚΟΥ ΕΤΟΥΣ

Πανεπιστήμιο Πειραιώς Σχολή Τεχνολογιών Πληροφορικής και Επικοινωνιών Τμήμα Ψηφιακών Συστημάτων ομές εδομένων

ΚΕΦΑΛΑΙΟ 5. Κύκλος Ζωής Εφαρμογών ΕΝΟΤΗΤΑ 2. Εφαρμογές Πληροφορικής. Διδακτικές ενότητες 5.1 Πρόβλημα και υπολογιστής 5.2 Ανάπτυξη εφαρμογών

Σειρά Προβλημάτων 4 Λύσεις

ΟΜΟΣΠΟΝΔΙΑ ΕΚΠΑΙΔΕΥΤΙΚΩΝ ΦΡΟΝΤΙΣΤΩΝ ΕΛΛΑΔΟΣ (Ο.Ε.Φ.Ε.) ΕΠΑΝΑΛΗΠΤΙΚΑ ΘΕΜΑΤΑ ΕΠΑΝΑΛΗΠΤΙΚΑ ΘΕΜΑΤΑ 2019 Β ΦΑΣΗ Γ ΓΕΝΙΚΟΥ ΛΥΚΕΙΟΥ

Μεταγλωττιστές. Γιώργος Δημητρίου. Μάθημα 1 ο. Πανεπιστήμιο Θεσσαλίας - Τμήμα Ηλεκτρολόγων Μηχανικών & Μηχανικών Υπολογιστών

ΠΑΝΕΠΙΣΤΗΜΙΟ ΠΑΤΡΩΝ ΠΟΛΥΤΕΧΝΙΚΗ ΣΧΟΛΗ ΤΜΗΜΑ ΜΗΧΑΝΙΚΩΝ ΗΛΕΚΤΡΟΝΙΚΩΝ ΥΠΟΛΟΓΙΣΤΩΝ ΚΑΙ ΠΛΗΡΟΦΟΡΙΚΗΣ

Θεωρία Υπολογισμού και Πολυπλοκότητα To Δόγμα Church-Turing

Α. unsigned int Β. double. Γ. int. unsigned char x = 1; x = x + x ; x = x * x ; x = x ^ x ; printf("%u\n", x); Β. unsigned char

Επικοινωνία:

Κεφάλαιο 10 ο Υποπρογράµµατα

Ακρότατα πίνακα, χωρίς min, max, μόνο με pos

Προγραμματισμός Ι (ΗΥ120)

21. ΦΥΛΛΟ ΕΡΓΑΣΙΑΣ 4 - ΔΗΜΙΟΥΡΓΩΝΤΑΣ ΜΕ ΤΟ BYOB BYOB. Αλγόριθμος Διαδικασία Παράμετροι

Προγραμματισμός Ι. Εγγραφές. Δημήτρης Μιχαήλ. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Περιεχόμενα ΜΤ Τυχαίας Προσπέλασης Θεωρία Υπολογισμού Ενότητα 23: Μηχανές Turing Τυχαίας Προσπέλασης Επ. Καθ. Π. Κατσαρός Τμήμα Πληροφορικής Επ. Καθ.

Δομημένος Προγραμματισμός

Σειρά Προβλημάτων 4 Λύσεις

Φροντιστήριο 8 Λύσεις

Κεφ. 1: Εισαγωγή στην έννοια του Αλγορίθμου και στον Προγραμματισμό. Η έννοια του προβλήματος

Προγραμματισμός Ι. Δυναμική Διαχείριση Μνήμης. Δημήτρης Μιχαήλ. Ακ. Έτος Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

ΑΕΠΠ Ερωτήσεις θεωρίας

HEAD INPUT. q0 q1 CONTROL UNIT

Σε αυτό το µάθηµα. Εισαγωγή στις Μηχανές Turing. Μηχανή Turing (Turing Machine - TM) Μηχανές Turing. Παραδείγµατα Μηχανών Turing

ΕΡΓΑΣΤΗΡΙΟ 9: Συμβολοσειρές και Ορίσματα Γραμμής Εντολής

Πληροφορική & Τηλεπικοινωνίες. K18 - Υλοποίηση Συστημάτων Βάσεων Δεδομένων Εαρινό Εξάμηνο

Ανάπτυξη Εφαρμογών σε Προγραμματιστικό Περιβάλλον. Διάρκεια 3 ώρες. Όνομα... Επώνυμο... Βαθμός...

Άδειες Χρήσης Το παρόν εκπαιδευτικό υλικό υπόκειται σε άδειες χρήσης Creative Commons. Για εκπαιδευτικό υλικό, όπως εικόνες, που υπόκειται σε άλλου τύ

Πανεπιστήμιο Πειραιώς Σχολή Τεχνολογιών Πληροφορικής και Επικοινωνιών Τμήμα Ψηφιακών Συστημάτων ομές εδομένων

ΑΝΑΠΤΥΞΗ ΕΦΑΡΜΟΓΩΝ ΣΕ ΠΡΟΓΡΑΜΜΑΤΙΣΤΙΚΟ ΠΕΡΙΒΑΛΛΟΝ ΕΠΑΝΑΛΗΠΤΙΚΟ ΔΙΑΓΩΝΙΣΜΑ ΣΧΟΛΙΚΟΥ ΕΤΟΥΣ

Εργαστήριο Λειτουργικών Συστημάτων 8o εξάμηνο, Ροή Υ, ΗΜΜΥ

2 ΟΥ και 8 ΟΥ ΚΕΦΑΛΑΙΟΥ

Βιβλιοθήκες Αφηρημένοι τύποι δεδομένων. Προγραμματισμός II 1

Κεφάλαιο 3: Εισαγωγή στους αλγορίθμους - διαγράμματα ροής

Λύσεις για τις ασκήσεις του lab5

1. Πότε χρησιμοποιούμε την δομή επανάληψης; Ποιες είναι οι διάφορες εντολές (μορφές) της;

8. Η δημιουργία του εκτελέσιμου προγράμματος γίνεται μόνο όταν το πηγαίο πρόγραμμα δεν περιέχει συντακτικά λάθη.

Η-Υ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ. Εργαστήριο 1 Εισαγωγή στη C. Σοφία Μπαλτζή s.mpaltzi@di.uoa.gr

Λύβας Χρήστος Αρχική επιµέλεια Πιτροπάκης Νικόλαος και Υφαντόπουλος Νικόλαος

ΗΥ252 - Οντοκεντρικός Προγραµµατισµός Προγραµµατιστική Εργασία Εαρινού Εξαµήνου 2004 Περιγραφή Παραδοτέων

Αυτόματα. Παράδειγμα: πωλητής καφέ (iii) Παράδειγμα: πωλητής καφέ (iv) Εισαγωγή στην Επιστήμη των Υπολογιστών 6

ΑΝΑΠΤΥΞΗ ΕΦΑΡΜΟΓΩΝ ΣΕ ΠΡΟΓΡΑΜΜΑΤΙΣΤΙΚΟ ΠΕΡΙΒΑΛΛΟΝ ΕΠΑΝΑΛΗΠΤΙΚΟ ΔΙΑΓΩΝΙΣΜΑ ΠΡΟΣΟΜΟΙΩΣΗΣ ΠΑΝΕΛΛΑΔΙΚΩΝ ΣΧΟΛΙΚΟΥ ΕΤΟΥΣ

Ασκήσεις Φροντιστηρίου «Υπολογιστική Νοημοσύνη Ι» 5 o Φροντιστήριο

Μπορείτε να δηλώσετε πίνακα οποιουδήποτε τύπου είτε βασικού είτε κλάσης:

Σειρά Προβλημάτων 4 Λύσεις

Α2. Να γράψετε στο τετράδιο σας τον αριθμό 1-4 κάθε πρότασης και δίπλα το γράμμα που δίνει τη σωστή επιλογή.

Μεταγλωττιστές. Ενότητα 6: Λεκτική ανάλυση (Μέρος 2 ο ) Αγγελική Σγώρα Τμήμα Μηχανικών Πληροφορικής ΤΕ

Ενότητα 5: ΜΕΤΑΒΛΗΤΕΣ

ΕΠΛ 211: Θεωρία Υπολογισμού και Πολυπλοκότητας. Διάλεξη 12: Μηχανές Turing

Προβλήματα, αλγόριθμοι, ψευδοκώδικας

Ερωτήσεις πολλαπλής επιλογής - Κεφάλαιο 2. Α1. Ο αλγόριθμος είναι απαραίτητος μόνο για την επίλυση προβλημάτων πληροφορικής

Πρόβλημα 29 / σελίδα 28

Ψευδοκώδικας. November 7, 2011

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ Ακαδημαϊκό έτος ΤΕΤΡΑΔΙΟ ΕΡΓΑΣΤΗΡΙΟΥ #4

Δομημένος Προγραμματισμός (ΤΛ1006)

Κωστόπουλος ηµήτριος Μ.Π.Λ.Α. TAPE COMPRESSION (θεώρηµα 2.3 Παπαδηµητρίου)

Επανάληψη για τις Τελικές εξετάσεις. (Διάλεξη 24) ΕΠΛ 032: ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΜΕΘΟΔΩΝ ΕΠΙΛΥΣΗΣ ΠΡΟΒΛΗΜΑΤΩΝ

Ανάπτυξη και Σχεδίαση Λογισμικού

Προγραμματισμός Η/Υ 1 (Εργαστήριο)

ΘΕΜΑΤΑ ΤΕΛΙΚΗΣ ΦΑΣΗΣ

4 ο Εργαστήριο Τυχαίοι Αριθμοί, Μεταβλητές Συστήματος

Φροντιστήριο 8 Λύσεις

ΚΕΦΑΛΑΙΟ 8 Η ΓΛΩΣΣΑ PASCAL

2 Ορισμός Κλάσεων. Παράδειγμα: Μηχανή για Εισιτήρια. Δομή μιας Κλάσης. Ο Σκελετός της Κλάσης για τη Μηχανή. Ορισμός Πεδίων 4/3/2008

ΦΡΟΝΤΙΣΤΗΡΙΑ ΠΡΟΟΔΟΣ

Πίνακες: μια σύντομη εισαγωγή. Πίνακες χαρακτήρων: τα "Αλφαριθμητικά"

Στη C++ υπάρχουν τρεις τύποι βρόχων: (a) while, (b) do while, και (c) for. Ακολουθεί η σύνταξη για κάθε μια:

Σου προτείνω να τυπώσεις τις επόμενες τέσσερις σελίδες σε ένα φύλο διπλής όψης και να τις έχεις μαζί σου για εύκολη αναφορά.

CSC 314: Switching Theory. Chapter 3: Turing Machines

Δομημένος Προγραμματισμός. Τμήμα Επιχειρηματικού Σχεδιασμού και Πληροφοριακών Συστημάτων

Θεωρητικές Ασκήσεις. ΑΝΑΠΤΥΞΗ ΕΦΑΡΜΟΓΩΝ ΣΕ ΠΡΟΓΡΑΜΜΑΤΙΣΤΙΚΟ ΠΕΡΙΒΑΛΛΟΝ. 1 ο Μέρος

Transcript:

ΕΘΝΙΚΟ ΚΑΙ ΚΑΠΟΔΙΣΤΡΙΑΚΟ ΠΑΝΕΠΙΣΤΗΜΙΟ ΑΘΗΝΩΝ ΣΧΟΛΗ ΘΕΤΙΚΩΝ ΕΠΙΣΤΗΜΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ ΚΑΙ ΤΗΛΕΠΙΚΟΙΝΩΝΙΩΝ ΠΤΥΧΙΑΚΗ ΕΡΓΑΣΙΑ Ανάπτυξη προσομοιωτή πολυταινιακής μηχανής Turing Αντώνιος Κ. Τρουμπούκης Γεώργιος Σ. Παπαδημητρίου Επιβλέπων: Παναγιώτης Ροντογιάννης, Αναπληρωτής Καθηγητής ΕΚΠΑ ΑΘΗΝΑ ΣΕΠΤΕΜΒΡΙΟΣ 2009

ΠΤΥΧΙΑΚΗ ΕΡΓΑΣΙΑ Ανάπτυξη προσομοιωτή πολυταινιακής μηχανής Turing Αντώνιος Κ. Τρουμπούκης Α.Μ.: 1115200300150 Γεώργιος Σ. Παπαδημητρίου Α.Μ.: 1115200300218 ΕΠΙΒΛΕΠΩΝ: Παναγιώτης Ροντογιάννης, Αναπληρωτής Καθηγητής ΕΚΠΑ

ΠΕΡΙΛΗΨΗ Η μηχανή Turing είναι ένα από τα βασικότερα και πιο σημαντικά θεωρητικά μοντέλα στην επιστήμη των υπολογιστών. Αποτελεί αντικείμενο που συναντάται σε αρκετά πεδία της Πληροφορικής, έχει δε κεντρικό ρόλο στην θεωρία αλγορίθμων, την θεωρία υπολογισμού και την θεωρία πολυπλοκότητας. Στην εργασία αυτή, υλοποιούμε έναν προσομοιωτή πολυταινιακών μηχανών Turing. Η διεπαφή της εφαρμογής είναι τύπου γραμμής εντολών (κέλυφος) ενώ η περιγραφή των μηχανών Turing γίνεται με τη χρήση μιας απλής γλώσσας που δεν διαφέρει και πολύ από την περιγραφή των μηχανών Turing στο χαρτί. Ιδιαίτερη προσοχή δόθηκε στον σχεδιασμό της εφαρμογής. Προτιμήσαμε μια οργάνωση σε όσο το δυνατό περισσότερα επίπεδα ανεξάρτητα μεταξύ τους, ώστε να είναι οργανωμένη, ευέλικτη και εύκολα επεκτάσιμη. Πιστεύουμε ότι η χρήση του προσομοιωτή σε εκπαιδευτικό επίπεδο θα βοηθούσε αρκετά στη διδασκαλία των μηχανών Turing. ΘΕΜΑΤΙΚΗ ΠΕΡΙΟΧΗ: ΛΕΞΕΙΣ ΚΛΕΙΔΙΑ: Θεωρία Υπολογισμού προσομοίωση, μηχανή Turing, εκπαιδευτικό λογισμικό, εφαρμογή γραμμής εντολών, θεωρία υπολογισμού

Στις οικογένειές μας

ΠΕΡΙΕΧΟΜΕΝΑ ΠΕΡΙΛΗΨΗ 5 ΠΡΟΛΟΓΟΣ 15 1 ΕΙΣΑΓΩΓΗ 19 1.1 Η μηχανή Turing................................. 19 1.2 Ορισμοί...................................... 21 1.3 Λίγα λόγια για την υλοποίηση.......................... 23 2 Ο ΠΡΟΣΟΜΟΙΩΤΗΣ 27 2.1 Επίπεδο NAMES................................. 28 2.2 Επίπεδο TAPE.................................. 30 2.3 Επίπεδο CONTROL............................... 33 2.4 Επίπεδο MACHINE............................... 37 2.5 Παράδειγμα χρήσης βιβλιοθήκης........................ 42 3 Η ΔΙΕΠΑΦΗ 45 3.1 Επίπεδο PARSE................................. 45 3.2 Επίπεδο SHELL................................. 49 4 ΒΟΗΘΗΤΙΚΑ ΕΠΙΠΕΔΑ 55 4.1 Επίπεδο ARRAY................................. 55 Α. Τρουμπούκης, Γ. Παπαδημητρίου 9

4.2 Eπεξεργασία εντολών ανά γραμμή....................... 60 5 ΟΔΗΓΙΕΣ ΧΡΗΣΗΣ 63 5.1 Εγκατάσταση................................... 63 5.2 Εντολές...................................... 63 5.3 Περιγραφή μηχανών............................... 66 5.4 Αρχεία της εφαρμογής.............................. 68 ΠΑΡΑΡΤΗΜΑΤΑ 69 A ΠΑΡΑΔΕΙΓΜΑΤΑ ΠΕΡΙΓΡΑΦΩΝ ΜΗΧΑΝΩΝ TURING 71 B ΚΩΔΙΚΑΣ ΕΦΑΡΜΟΓΗΣ 81 B.1 Επίπεδο υλοποίησης πίνακα.......................... 81 B.2 Επίπεδο προσομοίωσης............................. 88 B.3 Επίπεδο διεπαφής................................ 112 ΒΙΒΛΙΟΓΡΑΦΙΑ 131 Α. Τρουμπούκης, Γ. Παπαδημητρίου 10

ΚΑΤΑΛΟΓΟΣ ΣΧΗΜΑΤΩΝ 1.1 Σχηματική παράσταση μιας μηχανής Turing.................. 22 1.2 Σχηματική παράσταση μιας πολυταινιακής μηχανής Turing.......... 23 1.3 Αρχιτεκτονική της εφαρμογής.......................... 25 2.1 Σχέση υποεπιπέδων του επιπέδου προσομοίωσης.............. 27 3.1 Σχέση υποεπιπέδων διεπαφής με το επίπεδο προσομοίωσης........ 45 4.1 Σχηματική παράσταση της δομής ARRAY................... 57 Α. Τρουμπούκης, Γ. Παπαδημητρίου 11

ΚΑΤΑΛΟΓΟΣ ΠΙΝΑΚΩΝ 2.1 Λάθη του επιπέδου NAMES........................... 30 2.2 Λάθη του επιπέδου TAPE............................ 33 2.3 Λάθη του επιπέδου CONTROL......................... 38 2.4 Λάθη του επιπέδου MACHINE......................... 41 2.5 Συνάρτηση μετάβασης μηχανής Turing..................... 42 3.1 Συνοπτική παρουσίαση των εντολών του κελύφους.............. 50 3.2 Παρουσίαση των συναρτήσεων που καλούν οι εντολές............ 54 4.1 Λάθη του επιπέδου ARRAY........................... 60 5.1 Συνοπτική παρουσίαση των εντολών του κελύφους.............. 64 5.2 Αρχεία της εφαρμογής.............................. 68 Α. Τρουμπούκης, Γ. Παπαδημητρίου 13

ΠΡΟΛΟΓΟΣ Η μηχανή Turing, ένα από τα βασικότερα θεωρητικά μοντέλα στην επιστήμη των υπολογιστών, ονομάστηκε έτσι από τον μεγάλο Άγγλο μαθηματικό και επιστήμονα Πληροφορικής Alan Turing, ο οποίος την εισήγαγε το 1936. Είναι μια βασική αφηρημένη μηχανή που μεταχειρίζεται σύμβολα, η οποία, παρ όλη την απλότητά της, θεωρείται συνώνυμη της έννοιας του αλγορίθμου και έχει άμεση χρησιμότητα στην θεωρία υπολογισμού, την θεωρία αλγορίθμων και τη θεωρία πολυπλοκότητας. Η μηχανή Turing μπορεί να προσαρμοστεί έτσι ώστε να προσομοιώσει τη λογική οποιουδήποτε υπολογιστή που μπορεί να κατασκευασθεί ποτέ, και επιπλέον, σύμφωνα με την θέση Church-Turing, ένα πρόβλημα είναι επιλύσιμο αν μπορεί να κατασκευαστεί μια μηχανή Turing που να το επιλύει. Από τα παραπάνω φαίνεται ότι οι μηχανές Turing έχουν κεντρικό ρόλο στην επιστήμη των υπολογιστών, τέτοιο ώστε να περιλαμβάνονται στην ύλη πολλών μαθημάτων Πληροφορικής (και συνήθως σε αυτά με θεωρητικό ή αλγοριθμικό περιεχόμενο). Αρκετές φορές, η πρώτη επαφή με τις μηχανές Turing, οι οποίες μπορούν να εκτελέσουν μόνο στοιχειώδη βήματα, προβληματίζει το φοιτητή. Η κατανόηση της λειτουργίας τους είναι στην αρχή αρκετά δύσκολη και η κατασκευή προγραμμάτων (έστω και για κάτι τόσο απλό όσο η αντιγραφή μιας συμβολοσειράς) αρκετά επίπονη. Η χρήση ενός προσομοιωτή για την διδασκαλία των μηχανών Turing, αποτελεί κατά τη γνώμη μας ένα πολύ σημαντικό βοήθημα, αφού θα δίνεται η δυνατότητα στο φοιτητή να παρατηρήσει λεπτομερώς την συμπεριφορά και τον τρόπο εκτέλεσης, σε πρώτη φάση των μηχανών που υπάρχουν στα βιβλία, και στη συνέχεια των μηχανών που θα κατασκευάσει ο ίδιος. Στην εργασία μας αυτή, υλοποιούμε έναν προσομοιωτή πολυταινιακών μηχανών Turing. Η γλώσσα υλοποίησης είναι η C, και τα επιπλέον εργαλεία που χρησιμοποιήθηκαν είναι ο λεκτικός αναλυτής Flex και ο συντακτικός αναλυτής Bison. Η εφαρμογή σχεδιάστηκε για το λειτουργικό σύστημα Linux, και εκτελείται στα μηχανήματα Linux της σχολής. Ιδιαίτερη προσοχή δόθηκε στον σχεδιασμό της εφαρμογής. Μια οργάνωση σε όσο το δυνατό περισσότερα επίπεδα ανεξάρτητα μεταξύ τους, προτιμήθηκε έναντι μιας δύσκαμπτης, μονολιθικής αρχιτεκτονικής δύσκολα επεκτάσιμης. Ένας αρχικός και προφανής διαχωρισμός, θα ήταν σε δύο επίπεδα, προσομοίωσης και διεπαφής. Τα επίπεδα αυτά είναι ανεξάρτητα, έτσι ώστε να είναι δυνατή, για παράδειγμά, η υλοποίηση του επιπέδου διεπαφής με διαφορετικό τρόπο. Τα επίπεδα διεπαφής και προσομοίωσης χωρίζονται με τη Α. Τρουμπούκης, Γ. Παπαδημητρίου 15

σειρά τους και αυτά σε μικρότερα επίπεδα. Προσπαθήσαμε να δώσουμε όσο το δυνατόν περισσότερες δυνατότητες στον προσομοιωτή. Για παράδειγμα, η μηχανή μπορεί να είναι οσωνδήποτε ταινιών ενώ, επιτρέπεται η χρήση συμβόλων και ονομάτων καταστάσεων για τη μηχανή παραπάνω του ενός χαρακτήρων. Η διεπαφή της εφαρμογής είναι τύπου γραμμής εντολών (κέλυφος) και επιτρέπει στον χρήστη να επικοινωνεί μέσω μιας σειράς εντολών με τον προσομοιωτή. Η περιγραφή της μηχανής Turing εισάγεται από τον προγραμματιστή σε ένα αρχείο κειμένου, με χρήση μιας απλής γλώσσας που δεν διαφέρει και πολύ από την περιγραφή των μηχανών Turing στο χαρτί. Το κείμενο που κρατάτε στα χέρια σας είναι οργανωμένο ως εξής: Στο πρώτο κεφάλαιο παρουσιάζεται μια ιστορική αναδρομή στην ιστορία, τις αρχές σχεδιασμού, την επίδραση και την σημασία των μηχανών Turing. Στην συνέχεια, δίνονται κάποιοι ορισμοί και αναφέρονται λίγα πράγματα για την υλοποίηση. Στο δεύτερο κεφάλαιο παρουσιάζεται η τεκμηρίωση του κώδικα του επιπέδου προσομοίωσης. Για κάθε επίπεδο της προσομοίωσης παρουσιάζονται πληροφορίες για την σχεδίαση του επιπέδου, τη σχέση του με τα άλλα επίπεδα, αναλυτική περιγραφή των συναρτήσεων του επιπέδου και τέλος παράθεση των λαθών του επιπέδου. Στο τρίτο κεφάλαιο παρουσιάζεται η τεκμηρίωση του κώδικα του επιπέδου διεπαφής. Για κάθε επίπεδο της διεπαφής παρουσιάζονται πληροφορίες για την σχεδίαση του επιπέδου, για την γλώσσα του επιπέδου (λεκτικές μονάδες και συντακτικό) και για τον τρόπο αλληλεπίδρασης με το επίπεδο προσομοίωσης. Στο τέταρτο κεφάλαιο παρουσιάζεται η τεκμηρίωση του βοηθητικού κώδικα των βοηθητικών επιπέδων και εφαρμογών που χρησιμοποιήθηκαν για την εκπόνηση της εργασίας. Το πέμπτο και τελευταίο κεφάλαιο είναι ο οδηγός χρήσης της εφαρμογής. Στο παράρτημα Α παρουσιάζονται παραδείγματα μηχανών Turing εκφρασμένων στην γλώσσα περιγραφής των μηχανών της εφαρμογής. Τέλος, στο παράρτημα Β συμπεριλαμβάνεται ο κώδικας της εφαρμογής. Η παρούσα πτυχιακή εργασία πραγματοποιήθηκε στο πλαίσιο του Προπτυχιακού Προγράμματος Σπουδών του Τμήματος Πληροφορικής και Τηλεπικοινωνιών του Εθνικού και Καποδιστριακού Πανεπιστημίου Αθηνών. Α. Τρουμπούκης, Γ. Παπαδημητρίου 16

Κλείνοντας, θα θέλαμε να ευχαριστήσουμε τον αναπληρωτή καθηγητή του Τμήματος Πληροφορικής και Τηλεπικοινωνιών του Εθνικού και Καποδιστριακού Πανεπιστημίου Αθηνών κ. Παναγιώτη Ροντογιάννη, αφενός μεν για την εμπιστοσύνη που μας έδειξε και την ευκαιρία που μας έδωσε για την ανάπτυξη της σημαντικής αυτής εφαρμογής, αφετέρου δε για το ότι η μεστή διδασκαλία του, οι συναρπαστικές παραδόσεις του και το αμείωτο ενδιαφέρον του για την μετάδοση της γνώσης αποτέλεσαν για εμάς το εφαλτήριο για την ενασχόλησή μας με τον πολύ όμορφο κόσμο της θεωρητικής πληροφορικής. Αντώνης Τρουμπούκης Γιώργος Παπαδημητρίου 10 Ιουλίου 2009 Α. Τρουμπούκης, Γ. Παπαδημητρίου 17

ΚΕΦΑΛΑΙΟ 1 ΕΙΣΑΓΩΓΗ 1.1 Η μηχανή Turing Η μηχανή Turing σαν φορμαλισμός εισήχθη το 1936 από τον Alan Turing στην εργασία του «Περί των Υπολογίσιμων Αριθμών, με μια εφαρμογή στο Entscheidungsproblem». Μέσω της εργασίας αυτής έδωσε αρνητική απάντηση στο πρόβλημα της αποφασισιμότητας (Entscheidungsproblem) του Hilbert, απέδειξε δηλαδή ότι δοθέντος ενός μαθηματικού συστήματος, δεν είναι δυνατό να διαπιστωθεί εάν μια δοσμένη μαθηματική πρόταση αποτελεί θεώρημα του συστήματος η όχι. Αξιοθαύμαστος είναι ο τρόπος με τον οποίο εργάστηκε πάνω σε αυτό το πρόβλημα ο Turing, σχεδιάζοντας μια «μηχανή» για να αντιμετωπίσει τα όρια των μαθηματικών, χαρακτηριστικός όμως της πολύπλευρης προσωπικότητάς του. Ενός ερευνητή «εκ πεποιθήσεως μοναχικό» (όπως χαρακτηρίστηκε από ένα καθηγητή του), που η σχέση του με την επιστήμη εκφραζόταν με δύο διαφορετικά πρόσωπα. Από την μία ο «θεωρητικός» Turing, που προσπαθούσε να απαντήσει σε προβλήματα της επιστήμης που πολλές φορές άγγιζαν τα όρια της φιλοσοφίας (όπως το test Turing), και από την άλλη ο «πρακτικός» Turing, που καταπιανόταν επιτυχώς με πρακτικές εφαρμογές (όπως την σχεδίαση της «αυτόματης μηχανής υπολογισμού» το 1946). Παρ όλη την ενασχόληση του με αρκετά επιστημονικά πεδία, αλλά και τη μεγάλη συνεισφορά για την έκβαση Β παγκοσμίου πολέμου με το σπάσιμο του γερμανικού κώδικα «Αίνιγμα», ο Alan Turing πήρε τη θέση του τελικά στο πάνθεον της επιστήμης με τις μηχανές του. Η βασική ιδέα για τις μηχανές του Turing, είχε προέλθει σε σημαντικό βαθμό από τις απλές γραφομηχανές. Πράγματι, η γραφομηχανή διαχειρίζεται μια σειρά καθορισμένων συμβόλων και η συμπεριφορά της θα μπορούσε εκ των προτέρων να προβλεφθεί με ακρίβεια (γι αυτό και ονομάζεται μηχανή). Επιπλέον, κάθε γραφομηχανή έχει δύο καταστάσεις (γραφή μικρών ή κεφαλαίων γραμμάτων), καθώς και τη δυνατότητα να μετακινεί την κεφαλή της κατά μήκος του χαρτιού. Τι επιπλέον θα έπρεπε να έχει μια γραφομηχανή ώστε να μπορέσει να εκτελέσει τη διαδικασία του υπολογισμού; Α. Τρουμπούκης, Γ. Παπαδημητρίου 19

Ας αναλύσουμε την διαδικασία που εκτελεί ένας άνθρωπος όταν πρόκειται να εκτελέσει έναν πολύπλοκο υπολογισμό. Ο άνθρωπος διαθέτει μια ποσότητα χαρτιού, ένα μολύβι, μια γόμα και μια σειρά από οδηγίες για την εκτέλεση του υπολογισμού. Σε κάθε βήμα της εργασίας του παρατηρεί κάποιο τμήμα του χαρτιού του και εκτελεί την οδηγία που τον αφορά εκείνη τη στιγμή, γράφοντας ή σβήνοντας κάποια πράγματα από το χαρτί του. Το πως θα καταλάβει βέβαια ποια οδηγία τον αφορά μια συγκεκριμένη στιγμή, μπορεί να φανεί από την εισαγωγή της έννοιας της διανοητικής κατάστασης. Ο άνθρωπος μπορεί για κάποιο λόγο να διακόψει την εργασία του. Για να μπορέσει αργότερα να θυμηθεί που είχε μείνει, μπορεί να αφήσει ένα σημείωμα με κάποιες πληροφορίες που αφορούν την χρονική στιγμή που σταμάτησε την εργασία του, έτσι ώστε να μπορέσει να συνεχίσει. Αυτές οι σημειώσεις μπορούν να σκιαγραφήσουν την έννοια την διανοητικής κατάστασής. Γυρνώντας πάλι στην γραφομηχανή, και λαμβάνοντας υπόψη τα γενικά χαρακτηριστικά του υπολογισμού, μπορούμε να επεκτείνουμε την γραφομηχανή ώστε να προκύψει ένα πλήρες υπολογιστικό μοντέλο. Η κεφαλή επιπλέον θα μπορεί να σβήνει και να διαβάζει (εκτός από το να γράφει) και οι καταστάσεις της μηχανής δεν θα είναι μόνο οι δύο καταστάσεις γραφής κεφαλαίων ή μικρών γραμμάτων, αλλά περισσότερες, και θα εκφράζουν τις διανοητικές καταστάσεις όπως περιγράφτηκαν παραπάνω. Τέλος, αν στη μηχανή προστεθεί και η δυνατότητα αυτόματης εκτέλεσης των στοιχειωδών λειτουργιών του υπολογισμού με τη μορφή δεδομένων εντολών, θα έχουμε προχωρήσει στο σχεδιασμό μιας μηχανής που δεν θα είναι και πολύ διαφορετική από αυτή που χρησιμοποίησε ο Turing στην περίφημη εργασία του για το Entscheidungsproblem. Όμως, η συνεισφορά του Turing και η σημασία των μηχανών του στην επιστήμη των υ- πολογιστών δεν σταμάτησε εκεί. Παρόλο που τελικά ο Alonso Church πρόλαβε να δώσει την δική του απόδειξη για το Entscheidungsproblem πριν τον Turing, οι μηχανές Turing ήταν, τελικά, το μαθηματικό σύστημα που ταίριαζε περισσότερο στην περιγραφή της έννοιας του υπολογισμού από τους φορμαλισμούς των Church (λ-λογισμός) και Gödel (αναδρομικές συναρτήσεις). Έτσι, η μηχανή του Turing δεν άργησε τελικά να καθιερωθεί ως βασικό μοντέλο στην θεωρία του υπολογισμού και τελικά να γίνει ισοδύναμη με την έννοια του αλγορίθμου (θέση Church-Turing). Η καθιέρωση μοντέλου αυτού, οδήγησε πιο εύκολα στην συνειδητοποίηση μιας πολύ σημαντικής αρχής: ότι πέρα από τη διαπίστωση ότι ένα πρόβλημα είναι επιλύσιμο, μας ενδιαφέρει η επίλυση να γίνεται όσο το δυνατόν γρηγορότερα. Ακόμη, ο Turing στην εργασία του για το Entscheidungsproblem, αναφέρεται σε μια ειδική μηχανή, η οποία παίρνει ως είσοδο την περιγραφή μιας άλλης μηχανής Turing και στη συνέχεια την προσομοιώνει (η οποία ονομάστηκε καθολική μηχανή Turing). Η ιδέα αυτή εφαρμόστηκε από τον John von Neumann τη δεκαετία του 1940 κατά την ανάπτυξη της αρχιτεκτονικής αποθηκευμένου προγράμματος. Οι von Neumann και Turing γνωρίζονταν προσωπικά, όμως δεν είναι γνωστό όμως αν ο Neumann ήξερε για τις ιδέες του Turing. Α. Τρουμπούκης, Γ. Παπαδημητρίου 20

Πάνω στην αρχιτεκτονική αρχιτεκτονική του von Neumann, βασίζονται και οι σημερινοί υπολογιστές. 1.2 Ορισμοί Μια μηχανή Turing αποτελείται από μια μονάδα ελέγχου πεπερασμένων καταστάσεων και μια ταινία. Η επικοινωνία μεταξύ τους επιτυγχάνεται με μια κεφαλή, η οποία έχει την δυνατότητα να διαβάζει σύμβολα από την ταινία και μεταβάλλει τα σύμβολα της ταινίας. Σε κάθε βήμα του υπολογισμού, ανάλογα με την κατάσταση της μηχανής και το σύμβολο που δείχνει η κεφαλή της ταινίας, τοποθετεί την μονάδα ελέγχου σε μια νέα κατάσταση και είτε γράφει ένα νέο σύμβολο στο τετράγωνο που δείχνει η κεφαλή αυτή τη στιγμή, ή μετακινεί την κεφαλή της ταινίας μια θέση αριστερά η δεξιά. Η ταινία αρχίζει από το αριστερό άκρο και εκτείνεται απεριόριστα προς τα δεξιά. Η τροφοδότηση της μηχανής γίνεται με την τοποθέτηση της συμβολοσειράς εισόδου στα τετράγωνα στο αριστερό άκρο της ταινίας, ενώ το υπόλοιπο της ταινίας περιέχει αρχικά κενά σύμβολα. Τέλος, η μηχανή επιτρέπεται να τροποποιεί την ταινία της ελεύθερα με όποιο τρόπο θεωρεί κατάλληλο. Μια μηχανή Turing είναι μια 5-άδα (Q, Σ, δ, s, H), όπου: Q είναι το σύνολο καταστάσεων Σ είναι το αλφάβητο της μηχανής, και περιέχει το σύμβολο (που ορίζεται κενό σύμβολο) και δεν περιέχει τα σύμβολα, (που είναι οι συμβολοσειρές αναπαράστασης της κίνησης της κεφαλής). δ είναι η συνάρτηση μετάβασης: Q Σ Q Σ (, ) s Q και είναι η αρχική κατάσταση H Q και είναι το σύνολο τελικών καταστάσεων Αν q K H, a Σ και δ(q, a) = (p, b), τότε η μηχανή όταν βρίσκεται στην κατάσταση q και διαβάζει από την ταινία το σύμβολο a, θα εισέλθει στην κατάσταση p και αν b (, ) κινεί την κεφαλή στην αντίστοιχη κατεύθυνση, διαφορετικά γράφει στην ταινία το σύμβολο b. Εφόσον η δ είναι συνάρτηση, η λειτουργία της μηχανής είναι ντετερμινιστική. Υπάρχουν αρκετές παραλλαγές του βασικού μοντέλου της μηχανής Turing που ορίστηκε παραπάνω, τα οποία αν και είναι έχουν την ίδια υπολογιστική ισχύ (μπορούν να λύσουν τα ίδια προβλήματα), προσφέρουν όμως οφέλη είτε σε περιπτώσεις υπολογιστικής πολυπλοκότητας ή ευκολίες στον προγραμματισμό. Στις παραλλαγές αυτές συγκαταλέγονται οι πολυταινιακές μηχανές Turing. Α. Τρουμπούκης, Γ. Παπαδημητρίου 21

Σχήμα 1.1: Σχηματική παράσταση μιας μηχανής Turing Μια πολυταινιακή μηχανή Turing δεν είναι παρά μια συνήθης μηχανή Turing με περισσότερες από μια ταινίες. Η μόνη αλλαγή στον τυπικό ορισμό αφορά τη συνάρτηση μετάβασης, που τώρα επιτρέπει την εγγραφή, ανάγνωση και την μετακίνηση της κεφαλής ταυτόχρονα σε όλες τις ταινίες ή σε μερικές από αυτές. Πιο συγκεκριμένα: Μια πολυταινιακή μηχανή Turing k ταινιών είναι μια 5-άδα (Q, Σ, δ, s, H), όπου: Q είναι το σύνολο καταστάσεων Σ είναι το αλφάβητο της μηχανής, και περιέχει το σύμβολο (που ορίζεται κενό σύμβολο) και δεν περιέχει τα σύμβολα, (που είναι οι συμβολοσειρές αναπαράστασης της κίνησης της κεφαλής). δ είναι η συνάρτηση μετάβασης Q Σ k > Q (Σ (, )) k s Q και είναι η αρχική κατάσταση H Q και είναι το σύνολο τελικών καταστάσεων Αν q K H, a1, a2,..., ak Σ και δ(q, (a1, a2,..., ak)) = (p, (b1, b2,..., bk)), τότε η μηχανή όταν βρίσκεται στην κατάσταση q και διαβάζει από την ταινία το σύμβολα a1, a2,..., ak, θα εισέλθει στην κατάσταση p και (αν για 1 i k) b i (, )) κινεί την i-οστή κεφαλή στην αντίστοιχη κατεύθυνση, διαφορετικά γράφει στην i-οστή ταινία το σύμβολο b i. Αποδεικνύεται εύκολα ότι για κάθε πολυταινιακή μηχανή Turing υπάρχει ισοδύναμη μονοταινιακή μηχανή Turing. Α. Τρουμπούκης, Γ. Παπαδημητρίου 22

Σχήμα 1.2: Σχηματική παράσταση μιας πολυταινιακής μηχανής Turing 1.3 Λίγα λόγια για την υλοποίηση Οι μηχανές Turing δεν προορίζονται για πρακτική υπολογιστική τεχνολογία, αλλά είναι στην πραγματικότητα ένα νοητό πείραμα για τα όρια των μηχανικών υπολογισμών. Έτσι, δεν κατασκευάστηκαν στην πραγματικότητα. Η σημασία τους όμως στον τομέα της θεωρίας υπολογισμού αλλά και γενικότερα στην επιστήμη των υπολογιστών, τις κατέστησαν βασικό κεφάλαιο στη διδασκαλία των μαθημάτων πληροφορικής. Έτσι, η υλοποίηση ενός προσομοιωτή μηχανής Turing, προσφέρει εκτός από το συναρπαστικό παιχνίδι του προγραμματισμού μιας μηχανής Turing, ένα σημαντικό βοήθημα στον σπουδαστή της θεωρίας υπολογισμού, που θα ήθελε να παρατηρήσει τον τρόπο εκτέλεσης και την συμπεριφορά των μηχανών που υπάρχουν στα βιβλία ή αυτών που ο ίδιος θα σχεδιάσει. Ανάμεσα στις πολλές επεκτάσεις που έχουν προταθεί κατά καιρούς για τις μηχανές Turing, επιλέξαμε να ενσωματώσουμε στον προσομοιωτή μας αυτή της πολυταινιακής μηχανής. Υπολογιστικά είναι ισοδύναμη με την απλή μηχανή Turing και προσφέρει ευκολίες στον προγραμματισμό. Η μηχανή μπορεί να είναι οσωνδήποτε ταινιών, καθώς δεν υπάρχει περιορισμός από την εφαρμογή για το πλήθος των ταινιών. Επίσης, επιτρέπεται η χρήση συμβόλων και ονομάτων καταστάσεων για τη μηχανή παραπάνω του ενός χαρακτήρων. Α. Τρουμπούκης, Γ. Παπαδημητρίου 23

Η γλώσσα υλοποίησης της εφαρμογής είναι η C, και τα επιπλέον εργαλεία που χρησιμοποιήθηκαν είναι ο λεκτικός αναλυτής Flex και ο συντακτικός αναλυτής Bison. Η εφαρμογή σχεδιάστηκε για το λειτουργικό σύστημα Linux, και εκτελείται στα μηχανήματα Linux της σχολής (Ubuntu Linux, με πυρήνα 2.6.24-21-generic, έκδοση libc 2.7.10, έκδοση μεταγλωττιστή gcc 4.2.3-1 και επιπλέον flex 2.5.34-2.1 και bison 2.3.dfsg-5). Ιδιαίτερη προσοχή δόθηκε στον σχεδιασμό της εφαρμογής. Μια οργάνωση σε όσο το δυνατό περισσότερα επίπεδα ανεξάρτητα μεταξύ τους, προτιμήθηκε έναντι μιας δύσκαμπτης, μονολιθικής αρχιτεκτονικής δύσκολα επεκτάσιμης. Ένας αρχικός και προφανής διαχωρισμός, θα ήταν σε δύο επίπεδα, προσομοίωσης και διεπαφής. Τα επίπεδα αυτά είναι ανεξάρτητα, έτσι ώστε να είναι δυνατή, για παράδειγμά, η υλοποίηση του επιπέδου διεπαφής με διαφορετικό τρόπο. Το επίπεδο προσομοίωσης (επίπεδο MACHINE), υλοποιεί την προσομοίωση της μηχανής Turing, και αποτελείται από ένα σχετικά μικρό αριθμό συναρτήσεων, ώστε να συνοψίζει περιεκτικά τις λειτουργίες μιας μηχανής Turing. Οι λειτουργίες αυτές είναι η αρχικοποίηση και η καταστροφή της μηχανής, η εισαγωγή στοιχείου της μηχανής (κατάσταση, σύμβολο, μετάβαση κ.τ.λ.), η αρχικοποίηση της ταινίας, η εκτέλεση μιας μετάβασης και η επανεκκίνηση της μηχανής. Εκτός από τις λειτουργίες, χρειάζονται και κάποιες συναρτήσεις για την εκτύπωση της μηχανής, όπως η εκτύπωση της κατάστασης, της ταινίας και του τελευταίου κανόνα μετάβασης που εκτελέστηκε. Το επίπεδο προσομοίωσης, με τη σειρά του διαθέτει 3 υποεπίπεδα, το επίπεδο διαχείρισης ονομάτων (NAMES), το επίπεδο διαχείρισης των ταινιών (TAPE) και το επίπεδο διαχείρισης του τμήματος ελέγχου της μηχανής (CONTROL). Τα επίπεδα είναι και αυτά ανεξάρτητα (π.χ. το CONTROL δεν γράφει απευθείας στην ταινία της μηχανής, αλλά επικοινωνεί με το TAPE μέσω ενός πίνακα συμβόλων). Η διεπαφή της εφαρμογής είναι τύπου γραμμής εντολών (κέλυφος) και επιτρέπει στον χρήστη να επικοινωνεί μέσω μιας σειράς εντολών με τον προσομοιωτή. Η περιγραφή της μηχανής Turing εισάγεται από τον προγραμματιστή σε ένα αρχείο κειμένου, με χρήση μιας απλής γλώσσας που δεν διαφέρει και πολύ από την περιγραφή των μηχανών Turing όπως ορίστηκαν παραπάνω. Οι δύο αυτές λειτουργίες αποτελούν και τα δύο ανεξάρτητα υποεπίπεδα (SHELL και PARSE αντίστοιχα) οργάνωσης του επιπέδου διεπαφής. Στην επόμενη σελίδα αναπαρίσταται σχηματικά η αρχιτεκτονική της εφαρμογής, μέσω των σχέσεων μεταξύ των επιμέρους επιπέδων. Α. Τρουμπούκης, Γ. Παπαδημητρίου 24

Σχήμα 1.3: Αρχιτεκτονική της εφαρμογής Α. Τρουμπούκης, Γ. Παπαδημητρίου 25

ΚΕΦΑΛΑΙΟ 2 Ο ΠΡΟΣΟΜΟΙΩΤΗΣ Το επίπεδο προσομοίωσης (επίπεδο MACHINE), υλοποιεί την προσομοίωση της μηχανής Turing, και αποτελείται από ένα σχετικά μικρό αριθμό συναρτήσεων, ώστε να συνοψίζει περιεκτικά τις λειτουργίες μιας μηχανής Turing. Οι λειτουργίες αυτές είναι η αρχικοποίηση και η καταστροφή της μηχανής, η εισαγωγή στοιχείου της μηχανής (κατάσταση, σύμβολο, μετάβαση κ.τ.λ.), η αρχικοποίηση της ταινίας, η εκτέλεση μιας μετάβασης και η επανεκκίνηση της μηχανής. Εκτός από τις λειτουργίες, χρειάζονται και κάποιες συναρτήσεις για την εκτύπωση της μηχανής, όπως η εκτύπωση της κατάστασης, της ταινίας και του τελευταίου κανόνα μετάβασης που εκτελέστηκε. Σχήμα 2.1: Σχέση υποεπιπέδων του επιπέδου προσομοίωσης Το επίπεδο προσομοίωσης, με τη σειρά του διαθέτει 3 υποεπίπεδα, το επίπεδο διαχείρισης ονομάτων (NAMES), το επίπεδο διαχείρισης των ταινιών (TAPE) και το επίπεδο διαχείρισης του τμήματος ελέγχου της μηχανής (CONTROL). Τα επίπεδα είναι και αυτά ανεξάρτητα (π.χ. το CONTROL δεν γράφει απευθείας στην ταινία της μηχανής, αλλά επικοινωνεί με το TAPE μέσω ενός πίνακα συμβόλων). Α. Τρουμπούκης, Γ. Παπαδημητρίου 27

2.1 Επίπεδο NAMES Το επίπεδο NAMES υλοποιεί μια αντιστοίχηση ενός ονόματος (το οποίο μπορεί να είναι ένα σύμβολο του αλφαβήτου ή μια κατάσταση της μηχανής) με ένα ακέραιο αριθμό. Καθώς τα ονόματα των καταστάσεων και τα ονόματα των συμβόλων του αλφαβήτου είναι συμβολοσειρές, είναι πιο κομψό να χρησιμοποιούμε έναν κωδικό αριθμό (κωδικό ονόματος) για να αναφερόμαστε στις καταστάσεις ή τα σύμβολα σε όλα τα υπόλοιπα επίπεδα του προσομοιωτή. Για παράδειγμα, η ταινία δεν θα περιέχει τα ίδια τα σύμβολα, αλλά θα περιέχει ακεραίους (τους κωδικούς ονομάτων των συμβόλων), και όταν παραστεί η ανάγκη για την πρόσβαση στο ίδιο το όνομα του συμβόλου (όπως στην εκτύπωση για παράδειγμα) θα καλείται η αντίστοιχη συνάρτηση του επιπέδου. Το τρέχον επίπεδο προϋποθέτει την ύπαρξη του βοηθητικού επιπέδου ARRAY, που περιέχει την υλοποίηση των πινάκων. Επίσης, τα άλλα επίπεδα πολλές φορές θεωρούν δεδομένο ότι ο κωδικός συμβόλου 0 αντιστοιχεί στο κενό σύμβολο, και επιπλέον, αν και δεν αποτελούν σύμβολα του αλφαβήτου, οι κωδικοί 1, 2 αντιστοιχούν στη συμβολοσειρά αναπαράστασης της κίνησης αριστερά και δεξιά αντίστοιχα της κεφαλής της μηχανής. Το struct του επιπέδου αποτελείται από δυο πίνακες (ένας για τις καταστάσεις και ένας για τα σύμβολα) που περιέχουν τα αντίστοιχα ονόματα. struct _names { a r r _ t s t a t e s ; / * Synolo katastasewn * / a r r _ t symbols ; / * Synolo symvolwn * / ; typedef struct _names *tm_names ; tm_names nms ; Ακολουθεί μια γενική περιγραφή των βασικών συναρτήσεων του επιπέδου NAMES. int tm_names_init(tm_names *nms); Αρχικοποίηση του επιπέδου nms. Επιστρέφει 0 σε επιτυχία και μικρότερο του μηδενός σε αποτυχία. Μετά την κλήση της συνάρτησης το nms θα είναι ένα αρχικοποιημένο επίπεδο NAMES. Η διαδικασία αρχικοποίησης περιλαμβάνει την δημιουργία των πινάκων states και symbols μέσω της κλήσης της συνάρτησης arr_create(). int tm_names_destroy(tm_names *nms); Α. Τρουμπούκης, Γ. Παπαδημητρίου 28

Καταστροφή του επιπέδου nms. Επιστρέφει 0 σε επιτυχία και μικρότερο του μηδενός σε αποτυχία. Μετά την κλήση της συνάρτησης το nms δεν θα είναι πια ένα επίπεδο NAMES. Η διαδικασία καταστροφής περιλαμβάνει την καταστροφή των πινάκων states και symbols μέσω της κλήσης της συνάρτησης arr_destroy(). int tm_names_size(tm_names nms, int *sym_n, int *st_n); Επιστρέφει μέσω παραμέτρων το πλήθος των συμβόλων και των καταστάσεων του επιπέδου nms. Επιστρέφει πάντα 0. Μετά την κλήση της συνάρτησης τα sym_n και τα st_n θα περιέχουν τα μεγέθη των πινάκων των συμβόλων και των καταστάσεων αντίστοιχα. int tm_names_insert(tm_names nms, int elem_type, char *name); Εισαγωγή του ονόματος name (που είναι τύπου elem_type, το οποίο είναι SYMBL για σύμβολο και STATE για κατάσταση) στο επίπεδο nms. Επιστρέφει 0 σε επιτυχία και μικρότερο του μηδενός σε αποτυχία. Αρχικά ελέγχει το elem_type για να αναγνωρίσει σε ποιο πίνακα πρέπει να εισάγει (συμβόλων ή καταστάσεων), αναζητά αν υπάρχει ήδη το όνομα στον αντίστοιχο πίνακα, και αν δεν υπάρχει το εισάγει στο τέλος του καλώντας την συνάρτηση arr_append(). int tm_names_get(tm_names nms, int elem_type, int id, char **name); Αναζήτηση για το όνομα name ενός δεδομένου κωδικού ονόματος id (που είναι τύπου elem_type, το οποίο είναι SYMBL για σύμβολο και STATE για κατάσταση) στο επίπεδο nms. Επιστρέφει 0 σε επιτυχία και μικρότερο του μηδενός σε αποτυχία. Αρχικά ελέγχει το elem_type για να αναγνωρίσει σε ποιο πίνακα πρέπει να α- ναζητήσει (συμβόλων ή καταστάσεων), και επιστρέφει στην παράμετρο *name το όνομα που αντιστοιχεί στον κωδικό id καλώντας την συνάρτηση arr_get(). int tm_names_find(tm_names nms, int elem_type, int *id, char *name); Αναζήτηση για τον κωδικό ονόματος id που αντιστοιχεί στο όνομα name (που είναι τύπου elem_type, το οποίο είναι SYMBL για σύμβολο και STATE για κατάσταση) στο επίπεδο nms. Επιστρέφει 1 αν το όνομα βρέθηκε, 0 αν το όνομα δεν βρέθηκε και μικρότερο του μηδενός σε αποτυχία. Α. Τρουμπούκης, Γ. Παπαδημητρίου 29

Αρχικά ελέγχει το elem_type για να αναγνωρίσει σε ποιο πίνακα πρέπει να α- ναζητήσει (συμβόλων ή καταστάσεων), και επιστρέφει στην παράμετρο id τον κωδικό ονόματος που αντιστοιχεί στο όνομα *name καλώντας την συνάρτηση arr_find(). Στον παρακάτω πίνακα φαίνονται τα λάθη του επιπέδου NAMES. Όλες οι συναρτήσεις θέτουν στην μεταβλητή TMT_errno και στη συνέχεια επιστρέφουν τα παρακάτω λάθη. Πίνακας 2.1: Λάθη του επιπέδου NAMES TMNE_OK 0 Επιτυχία TMNE_ARR -1 Λάθος του επιπέδου ARRAY TMNE_ELEM -2 Άκυρος τύπος στοιχείου (παράμετρος elem_type) TMNE_EXIST -3 Το όνομα υπάρχει ήδη (κατά την εισαγωγή ονόματος) TMNE_SYSE -4 Λάθος συστήματος 2.2 Επίπεδο TAPE Το επίπεδο TAPE αποτελεί την υλοποίηση της Ν-διάστατης ταινίας της μηχανής. Κάθε ταινία αποτελείται από μια ακολουθία από κωδικούς συμβόλων, ενώ η αντιστοίχηση με τα πραγματικά σύμβολα θα γίνεται εξωτερικά μέσω του επιπέδου NAMES. Η ταινία θεωρητικά έχει άπειρο μήκος προς τα δεξιά, κάθε φορά όμως περιέχει στο αρχικό της τμήμα έναν πεπερασμένο αριθμό συμβόλων που η μηχανή έχει προσπελάσει μέχρι στιγμής. Τα τετράγωνα από τα οποία αποτελείται το αρχικό αυτό τμήμα της ταινίας, τα ονομάζουμε δεσμευμένα τετράγωνα. Κάθε χρονική στιγμή, το επίπεδο TAPE αποθηκεύει τα δεσμευμένα τετράγωνα της ταινίας, ενώ στη συνέχεια υπονοείται ότι υπάρχει ένας άπειρος αριθμός κενών τετραγώνων. Οι δυναμικοί πίνακες που αναπαριστούν το πεπερασμένο τμήμα κάθε ταινίας (και έχουν υλοποιηθεί στο επίπεδο ARRAY) μπορούν να μεγαλώνουν συνέχεια (μέχρι εκεί βέβαια που θα επιτρέπει το λειτουργικό σύστημα και η μνήμη του υπολογιστή). Συνεπώς, η κάθε ταινία είναι ένας πίνακας από κωδικούς συμβόλων, που αναπαριστά κάθε φορά το δεσμευμένο τμήμα της. Εφόσον η μηχανή αποτελείται από Ν ταινίες, θα έχουμε ένα πίνακα από ταινίες, δηλαδή ένα πίνακα από πίνακες κωδικών συμβόλων. Ο ρόλος αυτού του επιπέδου είναι να προσφέρει συναρτήσεις για την διαχείριση του πολύπλοκου αυτού συστήματος που χρησιμοποιείται για την αναπαράσταση και την λειτουργία της Ν-διάστατης ταινίας της μηχανής. Για παράδειγμα, ενδεικτικές συναρτήσεις του επιπέδου είναι η επιστροφή του κωδικού του συμβόλου που δείχνει αυτή τη στιγμή η ι-οστή ταινία. Για την κίνηση δεξιά-αριστερά, απλά γράφουμε στην ταινία τον κωδικό συμβόλου αναπαράστασης της αντίστοιχης κίνησης (όπως αυτά ορίστηκαν στο επίπεδο NAMES). Α. Τρουμπούκης, Γ. Παπαδημητρίου 30

Το τρέχον επίπεδο προϋποθέτει την ύπαρξη του βοηθητικού επιπέδου ARRAY, που περιέχει την υλοποίηση των πινάκων. Επίσης, το επίπεδο TAPE επιστρέφει κωδικούς συμβόλων και όχι τα ίδια τα σύμβολα, συνεπώς είναι απαραίτητο το επίπεδο που καλεί τις συναρτήσεις της ταινίας να χρησιμοποιεί (αν χρειάζεται) το επίπεδο NAMES για να ανακαλύπτει τα πραγματικά σύμβολα. Επίσης, θεωρούμε ότι ο κωδικός συμβόλου 0 αντιστοιχεί στο κενό σύμβολο, και επιπλέον, αν και δεν αποτελούν σύμβολα του αλφαβήτου, οι κωδικοί 1, 2 (που τίθενται LEFT και RIGHT αντίστοιχα) αντιστοιχούν στη συμβολοσειρά αναπαράστασης της κίνησης αριστερά και δεξιά αντίστοιχα της κεφαλής της ταινίας. Για κάθε ταινία αποθηκεύουμε έναν πίνακα από κωδικούς συμβόλων (που είναι η ακολουθία των συμβόλων που περιέχονται στα δεσμευμένα τετράγωνα της ταινίας), και έναν ακέραιο αριθμό που αντιστοιχεί στην θέση που δείχνει η κεφαλή της ταινίας. Στην πραγματικότητα όμως έχουμε Ν ταινίες, άρα το επίπεδο αποτελείται από ένα πίνακα ταινιών. typedef struct _tape_t { a r r _ t tape ; / * Tainia * / i n t head ; / * Thesi pou d e i x n e i h k e f a l i * / tape_t ; a r r _ t tapes ; Ακολουθεί μια γενική περιγραφή των βασικών συναρτήσεων του επιπέδου TAPE. int tm_tape_init( arr_t *tapes, int n); Αρχικοποίηση ενός πίνακα n ταινιών. Επιστρέφει 0 σε επιτυχία και μικρότερο του μηδενός σε αποτυχία. Δημιουργούμε τον πίνακα ταινιών ως ένα πίνακα arr_t διάστασης n, του οποίου κάθε στοιχείο θα είναι ένας δείκτης σε struct τύπου tape_t. Για κάθε ταινία (δηλαδή για κάθε struct τύπου tape_t) αρχικοποιούμε τον πίνακα συμβόλων και θέτουμε την κεφαλή να δείχνει στην αρχή της ταινίας. int tm_tape_destroy(arr_t *tapes); Καταστροφή ενός πίνακα n ταινιών. Επιστρέφει 0 σε επιτυχία και μικρότερο του μηδενός σε αποτυχία. Για κάθε ταινία (δηλαδή για κάθε στοιχείο του πίνακα tapes) καταστρέφουμε τον πίνακα συμβόλων της, και στη συνέχεια καταστρέφουμε και τον πίνακα ταινιών. int tm_tape_flush(arr_t tapes, int n); Σβήνει τα περιεχόμενα της n-οστής ταινίας. Α. Τρουμπούκης, Γ. Παπαδημητρίου 31

Επιστρέφει 0 σε επιτυχία και μικρότερο του μηδενός σε αποτυχία. Φέρνουμε την n-οστή ταινία από τον πίνακα tapes, καταστρέφουμε τον πίνακα συμβόλων, στη συνέχεια τον δημιουργούμε ξανά και θέτουμε την κεφαλή να δείχνει στην αρχή της ταινίας. int tm_tape_get_symbol(arr_t tapes, int n, int i, int ** id ); Επιστρέφει στην παράμετρο id τον κωδικό του συμβόλου που βρίσκεται στο i-οστό τετράγωνο της n-οστής ταινίας. Χρησιμοποιείται κυρίως για εμφάνιση ή εκτύπωση της ταινίας. Για την αναγνώριση του είδους του i-οστού τετραγώνου η συνάρτηση έχει την παρακάτω συμπεριφορά: Αν η κεφαλή αυτή τη στιγμή δείχνει στο i-οστό τετράγωνο επιστρέφει 1. Διαφορετικά, οι τιμές επιστροφής είναι 0 (για δεσμευμένο τετράγωνο) και 2 (για μη δεσμευμένο τετράγωνο). Σε περίπτωση αποτυχίας ε- πιστρέφει μικρότερο του μηδενός. Φέρνουμε την n-οστή ταινία από τον πίνακα tapes. Αν το i βρίσκεται στα μη δεσμευμένα τετράγωνα (δηλαδή αν το i είναι μεγαλύτερο από το μέγεθος του πίνακα συμβόλων της ταινίας), γράφουμε στο id τον αριθμό 0 (αφού τα μη δεσμευμένα τετράγωνα είναι πάντα κενά) και επιστρέφουμε 2. Διαφορετικά, γράφουμε στο id τον κωδικό σύμβολου που βρίσκεται στη θέση i. Αν η κεφαλή βρίσκεται και αυτή στην θέση i επιστρέφουμε 1, διαφορετικά επιστρέφουμε 0. int tm_tape_get_curr_symbols(arr_t tapes, arr_t symbols); Επιστρέφει στην παράμετρο symbols τους κωδικούς συμβόλων που δείχνουν αυτή τη στιγμή οι κεφαλές των n ταινιών. Επιστρέφει 0 σε επιτυχία και μικρότερο του μηδενός σε αποτυχία. Για κάθε ταινία i από τον πίνακα tapes, κάνουμε τα εξής: φέρνουμε την i-οστή ταινία, φέρνουμε τον κωδικό του συμβόλου που δείχνει η κεφαλή, και το προσθέτουμε στην i-οστή θέση του πίνακα symbols. int tm_tape_put_symbol(arr_t tapes, int n, int symb); Γράφει το σύμβολο με κωδικό συμβόλου symb στην n-οστή ταινία (στη θέση που δείχνει τώρα η κεφαλή), ή κινεί την κεφαλή της ταινίας. Επιστρέφει 0 σε επιτυχία και μικρότερο του μηδενός σε αποτυχία. Φέρνουμε την n-οστή ταινία. Διακρίνουμε διάφορες περιπτώσεις για τον κωδικό συμβόλου symb. Αν είναι ίσο με LEFT ή RIGHT, που όπως ορίστηκαν στο NAMES είναι οι συμβολοσειρές κίνησης της κεφαλής, μειώνει ή αυξάνει αντίστοιχα την θέση της κεφαλής. Σε διαφορετική περίπτωση, γράφει τον κωδικό συμβόλου symb στην θέση της ταινίας που υποδεικνύει η κεφαλή. Α. Τρουμπούκης, Γ. Παπαδημητρίου 32

Στον παρακάτω πίνακα φαίνονται τα λάθη του επιπέδου TAPE. Όλες οι συναρτήσεις θέτουν στην μεταβλητή TMT_errno και στη συνέχεια επιστρέφουν τα παρακάτω λάθη. Πίνακας 2.2: Λάθη του επιπέδου TAPE TMΤE_OK 0 Επιτυχία TMΤE_ARR -1 Λάθος του επιπέδου ARRAY TMTE_TPNO -2 Άκυρος αριθμός ταινίας TMTE_LEFT -3 Η κεφαλή δεν μπορεί να πάει άλλο αριστερά (έχει φτάσει στο αριστερό άκρο) 2.3 Επίπεδο CONTROL Το επίπεδο CONTROL αποτελεί την υλοποίηση του τμήματος ελέγχου της μηχανής, που περιλαμβάνει την κατάσταση της μηχανής και την συνάρτηση μετάβασης, δεν έχει όμως άμεση αλληλεπίδραση με την ταινία. Οι καταστάσεις και τα σύμβολα αναπαρίστανται από κωδικούς καταστάσεων και συμβόλων αντίστοιχα, ενώ η αντιστοίχηση με τα πραγματικά ονόματα ονομάτων και καταστάσεων θα γίνεται εξωτερικά μέσω του επιπέδου NAMES. Η βασική λειτουργία του επιπέδου αυτού (αν εξαιρέσουμε τον ορισμό αρχικής και τελικών καταστάσεων και την αναγνώριση του αν βρισκόμαστε σε τελική κατάσταση) είναι η υλοποίηση της συνάρτησης μετάβασης της μηχανής (συνάρτηση δ). Η μορφή της συνάρτησης δ είναι η παρακάτω: δ(q, (s 1, s 2, s 3,..., s n )) = (q, (s 1, s 2, s 3,..., s n)) όπου q η τρέχουσα κατάσταση, s 1, s 2,..., s n τα σύμβολα στα οποία δείχνουν οι κεφαλές της ταινίας, ενώ q η επόμενη κατάσταση και καθένα από τα s 1, s 2,..., s n θα είναι είτε ένα σύμβολο (που σημαίνει ότι στην αντίστοιχη ταινία της μηχανής θα γραφτεί αυτό το σύμβολο) ή κάποιο από τα, (που σημαίνει ότι η κεφαλή της αντίστοιχης ταινίας θα πάει αριστερά ή δεξιά). Σημειώνουμε ότι οι μεταβλητές s 1, s 1, s 2, s 2,..., s n, s n θεωρούνται του ίδιου τύπου, για το λόγο ότι τα σύμβολα κίνησης κεφαλής συμπεριλαμβάνονται στον πίνακα συμβόλων του επιπέδου NAMES (βέβαια, στην ταινία ποτέ δεν θα γραφεί κάποιο από αυτά τα σύμβολα, όπως εξηγήθηκε στο προηγούμενο κεφάλαιο). Συνεπώς, αν για παράδειγμα η τιμή επιστροφής της συνάρτησης δ κάποια στιγμή είναι (q 1, (s 1, s 2, s 3 )), το επίπεδο CONTROL θα αλλάξει την κατάσταση σε q 1 και το επίπεδο TAPE θα γράψει στην ταινία τα (s 1, s 2, s 3 ). Η συνάρτηση δ, λοιπόν, θα δέχεται την τρέχουσα κατάσταση και ένα πίνακα με τα τρέχοντα σύμβολα, ενώ θα επιστρέφει μια δυάδα που θα περιλαμβάνει την επόμενη κατάσταση και τα σύμβολα που θα γραφτούν στην ταινία. Έστω ένας (n + 1)-διάστατος πίνακας (όπου n Α. Τρουμπούκης, Γ. Παπαδημητρίου 33

ο αριθμός των ταινιών), με καθένα από τα στοιχεία του να είναι οι τιμές επιστροφής της συνάρτησης δ, με τέτοιο τρόπο, έτσι ώστε πηγαίνοντας στην θέση [q, s1, s2, s3,..., sn] του πίνακα να βρίσκεται η τιμή επιστροφής της συνάρτησης δ με ορίσματα τα (q, (s 1, s 2, s 3,..., s n )). Σύμφωνα με τα παραπάνω, ο τρόπος που μπορούμε να ανακαλύψουμε την τιμή επιστροφής της συνάρτησης δ είναι να πάμε στην αντίστοιχη θέση του (n + 1)-διάστατου πίνακα. Καθώς από τις διαδικαστικές γλώσσες προγραμματισμού δεν προσφέρεται η δυνατότητα χρήσης πολυδιάστατων πινάκων με μη καθορισμένη διάσταση, αρκεί να παραστήσουμε τον (n + 1)-διάστατο πίνακα σε έναν μονοδιάστατο πίνακα. Γνωρίζουμε ότι αν θέλουμε να παραστήσουμε έναν πίνακα A διάστασης d 1 d 2 d 3... d m σε έναν πίνακα B μίας διάστασης, η θέση οποιουδήποτε στοιχείου A[i 1, i 2, i 3,..., i m ] στον πίνακα B βρίσκεται ως εξής: j = i 1 (d 2 d 3... d m ) + i 2 (d 3 d 4... d m ) +... + i n 1 d m + i n Αν εφαρμόσουμε το παραπάνω (με μερικές τροποποιήσεις) στον πίνακα της συνάρτησης δ, η τιμή της συνάρτησης δ(q, (s1, s2, s3,..., sn)) βρίσκεται στην θέση j του πίνακα αναπαράστασης της συνάρτησης σύμφωνα με τον παρακάτω υπολογισμό (όπου S το πλήθος των συμβόλων): j = s 1 + s 2 S 1 + s 3 S 2 +... + s n S n 1 + q S n Έστω Δ ο πίνακας υλοποίησης της συνάρτησης δ. Η πρόσβαση στις τιμές γίνεται κατά τη διάρκεια της λειτουργίας της μηχανής (επιστροφή της τιμής της θέσης του πίνακα Δ που δίνει ο πιο πάνω τύπος), ενώ η εκχώρηση των τιμών της συνάρτησης δ (εισαγωγή μεταβάσεων) γίνεται κατά την δημιουργία της μηχανής (γίνεται εισαγωγή της αντίστοιχης δυάδας επιστροφής στην θέση του πίνακα Δ που δίνει ο πιο πάνω τύπος). Η θέση που βρίσκεται μια τιμή επιστροφής της συνάρτησης δ, όπως φαίνεται παραπάνω, εξαρτάται (εκτός από τα q, s 1, s 2,..., s n ) από το πλήθος των ταινιών (που είναι εξ ορισμού σταθερό σε μια δεδομένη μηχανή Turing) και το πλήθος των συμβόλων. Το τελευταίο είναι πολύ σημαντικό, καθώς αν το S δεν είναι σταθερό, δεν θα επιστρέφονται οι σωστές τιμές. Συνεπώς, πριν την εισαγωγή των μεταβάσεων είναι απαραίτητο να έχει τελειώσει η εισαγωγή των καταστάσεων και των συμβόλων, και γι αυτό το λόγο χρησιμοποιείται η συνάρτηση tm_control_update(). Το τρέχον επίπεδο προϋποθέτει την ύπαρξη του βοηθητικού επιπέδου ARRAY, που περιέχει την υλοποίηση των πινάκων. Επίσης, το επίπεδο CONTROL επιστρέφει και επεξεργάζεται κωδικούς ονομάτων καταστάσεων και συμβόλων και όχι τα ίδια τα ονόματα, είναι απαραίτητο το επίπεδο που καλεί τις συναρτήσεις της ταινίας να χρησιμοποιεί (αν χρειάζεται) το επίπεδο NAMES για να ανακαλύπτει τα πραγματικά ονόματα. Για να λειτουργήσει σωστά το επίπεδο, θα πρέπει να έχει τελειώσει η εισαγωγή των ο- Α. Τρουμπούκης, Γ. Παπαδημητρίου 34

νομάτων (καταστάσεων και συμβόλων). Όταν η εισαγωγή των ονομάτων στο επίπεδο NAMES τελειώσει, καλείται η συνάρτηση tm_control_update(), ώστε να ξεκινήσει η δημιουργία της συνάρτησης δ. Τέλος, το επίπεδο CONTROL δεν έχει πρόσβαση στην ταινία, δηλαδή δεν διαβάζει από την ταινία ούτε γράφει σε αυτήν, αλλά επικοινωνεί με την ταινία μέσω ενός πίνακα κωδικών συμβόλων (για να είναι όσο το δυνατό πιο ανεξάρτητα τα επίπεδα CONTROL και TAPE). Ένα άλλο, πιο πάνω επίπεδο θα αναλαμβάνει τον γενικότερο συντονισμό μεταξύ των επιπέδων που έχουμε δει ως τώρα. Το struct του επιπέδου αποτελείται από τον κωδικό της τρέχουσας και της αρχικής κατάστασης, ένα πίνακα από κωδικούς τελικών καταστάσεων, τον πίνακα υλοποίησης της συνάρτησης μετάβασης, το πλήθος των συμβόλων και των καταστάσεων. struct _ c o n t r o l { i n t s t a t e ; / * trexousa k a t a s t a s i * / i n t i n i s t ; / * a r x i k i k a t a s t a s i * / a r r _ t f i n a l _ s t a t e s ; / * Synolo t e l i k w n katastasewn * / a r r _ t d e l t a _ f ; / * s y n a r t i s i metavasis * / i n t st_n ; / * P l i t h o s katastasewn * / i n t sym_n ; / * P l i h t o s symvolwn * / ; typedef struct _ c o n t r o l * tm_control ; tm_control c t r l ; Οι τιμές επιστροφής της συνάρτησης μετάβασης αποτελούνται από την επόμενη κατάσταση και ένα πίνακα από σύμβολα που θα γραφτούν σε κάθε ταινία. Στα σύμβολα αυτά περιλαμβάνονται και τα σύμβολα κίνησης της κεφαλής της ταινίας. typedef struct _step_t { i n t next_state ; / * epomeni k a t a s t a s i * / a r r _ t next_symbols ; / * epomena symvola gia kathe t a i n i a * / s t e p _ t ; Ακολουθεί μια γενική περιγραφή των βασικών συναρτήσεων του επιπέδου CONTROL. int tm_control_init (tm_control * ctrl ); Αρχικοποίηση του επιπέδου ctrl. Επιστρέφει 0 σε επιτυχία και μικρότερο του μηδενός σε αποτυχία. Α. Τρουμπούκης, Γ. Παπαδημητρίου 35

Αρχικοποιούμε τον πίνακα υλοποίησης της συνάρτησης δ, τον πίνακα τελικών καταστάσεων και θέτουμε στις υπόλοιπες μεταβλητές (που είναι ακέραιοι αριθμοί) την τιμή -1. int tm_control_update(tm_control ctrl, int st_n, int sym_n); Ενημερώνει το επίπεδο ctrl ότι μπορεί να ξεκινήσει η διαδικασία εισαγωγής μεταβάσεων, δίνοντας του το πλήθος των καταστάσεων και των συμβόλων. Επιστρέφει πάντα 0. Τίθεται ο αριθμός των καταστάσεων st_n και των συμβόλων sym_n στα αντίστοιχα πεδία του struct του επιπέδου. Πριν την κλήση της συνάρτησης οι αντίστοιχες τιμές είναι ίσες με -1. int tm_control_destroy(tm_control * ctrl ); Καταστροφή του επιπέδου ctrl. Επιστρέφει 0 σε επιτυχία και μικρότερο του μηδενός σε αποτυχία. Καταστρέφεται ο πίνακας υλοποίησης της συνάρτησης δ και ο πίνακας τελικών καταστάσεων. int tm_control_get_state(tm_control ctrl ); Επιστροφή κατάστασης της μηχανής. Επιστρέφει τον κωδικό ονόματος της τρέχουσας κατάστασης της μηχανής. int tm_control_insert_state(tm_control ctrl, int elem_type, int state ); Εισαγωγή αρχικής ή τελικής κατάστασης. Επιστρέφει 0 σε επιτυχία και μικρότερο του μηδενός σε αποτυχία. Αν η τιμή του elem_type είναι INIST, το state θα είναι ένας κωδικός ονόματος που θα αντιστοιχεί στην αρχική κατάσταση της μηχανής, οπότε θέτουμε την αρχική και την τρέχουσα κατάσταση της μηχανής την τιμή state. Αν η τιμή του elem_type είναι FINST, το state θα είναι ένας κωδικός ονόματος που θα αντιστοιχεί σε τελική κατάσταση της μηχανής, οπότε εισάγουμε στον πίνακα τελικών καταστάσεων την τιμή state (αφού ελέγξουμε αν υπάρχει ήδη). int tm_control_insert_delta(tm_control ctl, int s1, int s2, arr_t sm1, arr_t sm2); Εισαγωγή μετάβασης δ(s1, sm1) = (s2, sm2) στον πίνακα υλοποίησης της συνάρτησης δ. Τα s1, s2 είναι κωδικοί καταστάσεων και τα sm1,sm2 είναι πίνακες κωδικών συμβόλων. Επιστρέφει 0 σε επιτυχία και μικρότερο του μηδενός σε αποτυχία. Α. Τρουμπούκης, Γ. Παπαδημητρίου 36

Ελέγχει αν έχει κληθεί η tm_control_update(). Αν έχει κληθεί, δημιουργούμε μία τιμή επιστροφής (s2,sm2), και βρίσκουμε την θέση του πίνακα που αντιστοιχεί στην τιμή δ(s1,sm1). Αν η θέση αυτή είναι κενή γίνεται εισαγωγή της τιμής επιστροφής που δημιουργήθηκε πριν (αν έχει ήδη εισαχθεί κάποια άλλη τιμή (s3,sm3) στη θέση αυτή, το sm3 θα είναι ένας αρχικοποιημένος πίνακας του επιπέδου ARRAY). int tm_control_step(tm_control ctrl, arr_t cur_symb, arr_t *next_symb); Κάνει ένα βήμα. Ανάλογα με τους κωδικούς συμβόλων cur_symb και την τρέχουσα κατάσταση, αλλάζει την κατάσταση και δίνει στο next_symb τους κωδικούς συμβόλων που θα γραφτούν στην ταινία (συμπεριλαμβάνονται και οι κωδικοί κίνησης των κεφαλών). Επιστρέφει 0 σε επιτυχία και μικρότερο του μηδενός σε αποτυχία. Βρίσκουμε την θέση του πίνακα που αντιστοιχεί στην τιμή δ(τρέχουσα κατάσταση, cur_symb). Η θέση που επιστρέφει (ο έλεγχος για το αν είναι η όχι κενή γίνεται όπως στην παραπάνω συνάρτηση) είναι η τιμή επιστροφής (st, sym) της συνάρτησης δ. Η τρέχουσα κατάσταση γίνεται ίση με st και στην παράμετρο next_symb επιστρέφεται ο πίνακας κωδικών συμβόλων sym. int tm_control_isfinal (tm_control ctrl, int st ); Έλεγχος αν η μηχανή έχει φτάσει σε τελική κατάσταση. Επιστρέφει 0 αν η τρέχουσα κατάσταση δεν είναι τελική, 1 αν είναι τελική και μικρότερο του μηδενός σε αποτυχία. Αναζητούμε στον πίνακα τελικών καταστάσεων αν υπάρχει ο κωδικός της τρέχουσας κατάστασης. int tm_control_restart(tm_control ctrl ); Επανεκκίνηση της μηχανής. Θέτει την τρέχουσα κατάσταση ίση με την αρχική κατάσταση. Επιστρέφει πάντα 0. Στον παρακάτω πίνακα φαίνονται τα λάθη του επιπέδου CONTROL. Όλες οι συναρτήσεις θέτουν στην μεταβλητή TMC_errno και στη συνέχεια επιστρέφουν τα παρακάτω λάθη. 2.4 Επίπεδο MACHINE Το επίπεδο MACHINE αποτελεί το επίπεδο προσομοίωσης της μηχανής. Αναλαμβάνει τον συντονισμό των επιμέρους επιπέδων NAMES, TAPE και CONTROL, ώστε να προκύψει η εύρυθμη λειτουργία της μηχανής. Α. Τρουμπούκης, Γ. Παπαδημητρίου 37

Πίνακας 2.3: Λάθη του επιπέδου CONTROL TMCE_OK 0 Επιτυχία TMCE_ARR -1 Λάθος του επιπέδου ARRAY TMCE_STEP -2 Η μηχανή δεν μπορεί να κάνει βήμα καθώς δεν υπάρχει διαθέσιμη μετάβαση στην συνάρτηση delta TMCE_ELEM -3 Άκυρος τύπος στοιχείου (παράμετρος elem_type) TMCE_EXIST -4 Η κατάσταση ή η μετάβαση υπάρχει ήδη TMCE_UPDT -5 Δεν μπορεί να γίνει εισαγωγή μεταβάσεων (δεν έχει κληθεί η tm_control_update()) TMCE_SYSE -6 Λάθος συστήματος Η διεπαφή του επιπέδου MACHINE, που είναι και γενικά η διεπαφή του προσομοιωτή, αποτελείται από ένα σχετικά μικρό αριθμό συναρτήσεων, ώστε να συνοψίζει περιεκτικά τις λειτουργίες μιας μηχανής Turing. Οι λειτουργίες αυτές είναι η αρχικοποίηση και η καταστροφή της μηχανής, η εισαγωγή στοιχείου της μηχανής (κατάσταση, σύμβολο, μετάβαση κ.τ.λ.), η αρχικοποίηση της ταινίας, η εκτέλεση μιας μετάβασης και η επανεκκίνηση της μηχανής. Εκτός από τις λειτουργίες, χρειάζονται και κάποιες συναρτήσεις για την εκτύπωση της μηχανής, όπως η εκτύπωση της κατάστασης, της ταινίας και του τελευταίου κανόνα μετάβασης που εκτελέστηκε. Ακολουθεί μια γενική περιγραφή των βασικών συναρτήσεων του επιπέδου MACHINE. int _tm_update(int n); Εσωτερική συνάρτηση του επιπέδου MACHINE, για αρχικοποίηση του επιπέδου TAPE και ενημέρωση του επιπέδου CONTROL. Επιστρέφει 0 σε επιτυχία και μικρότερο του μηδενός σε αποτυχία. H συνάρτηση αυτή καλείται μόνο εσωτερικά στο επίπεδο MACHINE, αλλά αναφέρεται εδώ γιατί η λειτουργία της είναι αρκετά σημαντική. Με το που θα εισαχθεί η πρώτη μετάβαση, πρέπει να γίνουν 2 πράγματα: αφενός να κληθεί η συνάρτηση tm_control_update() ώστε να είναι δυνατή η εισαγωγή μεταβάσεων, και αφετέρου να αρχικοποιηθεί το επίπεδο TAPES, γιατί το πόσες ταινίες θα έχει η μηχανή φαίνεται μόνο από τη μορφή των μεταβάσεων της συνάρτησης δ. Επιπλέον, αρχικοποιούνται και διάφορες καθολικές μεταβλητές που θα χρειαστούν για την διαδικασία εκτύπωσης. int tm_init (void); Αρχικοποιεί το επίπεδο MACHINE. Επιστρέφει 0 σε επιτυχία και μικρότερο του μηδενός σε αποτυχία. Αρχικοποιεί τις καθολικές μεταβλητές και τα επίπεδα NAMES και CONTROL. Η αρχικοποίηση του επιπέδου TAPE γίνεται μετά τον καθορισμό του πλήθους των ταινιών, δηλαδή στην εσωτερική συνάρτηση _tm_update(). Α. Τρουμπούκης, Γ. Παπαδημητρίου 38

int tm_destroy(void); Καταστρέφει το επίπεδο MACHINE. Επιστρέφει 0 σε επιτυχία και μικρότερο του μηδενός σε αποτυχία. Καταστρέφει τα επίπεδα NAMES, CONTROL και TAPE. int tm_insert_element(int elem_type, int argc, char *argv []); Εισάγει ένα στοιχείο της μηχανής τύπου elem_type (STATE για κατάσταση, SYMBL για σύμβολο, INIST για αρχική κατάσταση, FINST για τελική κατάσταση και DELTA για μετάβαση). Το στοιχείο αυτό θα βρίσκεται στο πίνακα συμβολοσειρών argv που έχει μήκος argc. Πρέπει αρχικά να εισαχθούν το κενό σύμβολο και οι συμβολοσειρές κίνησης αριστερά και δεξιά. Επίσης, μετά την εισαγωγή των μεταβάσεων δεν γίνεται εισαγωγή συμβόλων και καταστάσεων. Επιστρέφει 0 σε επιτυχία και μικρότερο του μηδενός σε αποτυχία. Διακρίνουμε διάφορες περιπτώσεις για το elem_type: Αν είναι STATE ή SYMBL εισάγουμε το argv[0] στο επίπεδο NAMES (tm_names_insert()). Αν είναι INIST ή FINST βρίσκουμε τον κωδικό ονόματος της κατάστασης με όνομα argv[0] και εισάγουμε την κατάσταση στο επίπεδο CONTROL (tm_control_insert_state()). Αν είναι ίσο με DELTA, αυτό σημαίνει ότι θα πρέπει να εισάγουμε την μετάβαση δ(st1,sym1) = (st2, sym2), όπου st1, st2 καταστάσεις και sym1, sym2 πίνακες συμβόλων. Αν n ο αριθμός των ταινιών τότε θα ισχύει: st1 = argv[0], sym1 = (argv[1],argv[2],...,argv[n+1]), st2 = argv[n+2] και sym2 = (argv[n+3], argv[n+4],..., argv[2n+2]). Συνεπώς πρέπει να ελεγξουμε αν το argc είναι άρτιο και ίσο με (n 2)/2. Επίσης, αν είναι η πρώτη φορά που θα εισάγουμε μια μετάβαση, καλούμε την βοηθητική συνάρτηση _tm_update(). Στη συνέχεια, βρίσκουμε τους κωδικούς ονομάτων για καθένα από τα στοιχεία του πίνακα argv και φτιάχνουμε τα δεδομένα στη σωστή μορφή ώστε να γίνει η κλήση της tm_control_insert_delta(). int tm_set_tape(int i, int argc, char *argv []); Θέτει στην i-οστή ταινία τα σύμβολα που βρίσκονται στον πίνακα συμβολοσειρών argv που έχει μέγεθος argc. Επιστρέφει 0 σε επιτυχία και μικρότερο του μηδενός σε αποτυχία. Αρχικά σβήνουμε τα περιεχόμενα της i-οστης ταινίας καλώντας την συνάρτηση tm_tape_flush(), και στη συνέχεια, για κάθε σύμβολο που βρίσκεται στον πίνακα argv, αναζητούμε τον κωδικό ονόματός του και το γράφουμε στην ταινία. Στη συνέχεια γράφουμε και το σύμβολο, ώστε να πάει η κεφαλή μια θέση πιο δεξιά για να γράψουμε στο επόμενο βήμα το επόμενο σύμβολο. Όταν τελειώσουμε, γράφουμε argc φορές το σύμβολο, για να πάμε ξανά στην αρχή της ταινίας. Το γράψιμο των συμβόλων γίνεται με τη συνάρτηση tm_tape_put_symbol(). Α. Τρουμπούκης, Γ. Παπαδημητρίου 39

int tm_step(void); Κάνει ένα βήμα. Επιστρέφει 0 αν έχουμε τελική κατάσταση, 1 αν έγινε το βήμα και μικρότερο του μηδενός σε αποτυχία. Καλούμε την tm_control_get_state(), για να βρούμε την τρέχουσα κατάσταση, και στη συνέχεια καλούμε την tm_control_is_final(), για να αναγνωρίσουμε αν βρίσκεται σε τελική κατάσταση. Αν ναι, επιστρέφουμε 0, διαφορετικά η μηχανή θα πρέπει να κάνει ένα βήμα. Φέρνουμε τα σύμβολα που δείχνουν οι κεφαλές των ταινιών (tm_tape_get_curr_symbols()), στη συνέχεια καλούμε την tm_control_step() με τα σύμβολα αυτά. Η tm_control_step() θα εκτελέσει το βήμα στο επίπεδο CONTROL, και θα επιστρέψει τα σύμβολα που πρέπει να γραφτούν στην ταινία. Τέλος, γράφουμε σε καθεμία από τις ταινίες το αντίστοιχο σύμβολο με την συνάρτηση tm_tape_put_symbol(). int tm_restart(void); Επανεκκινεί την μηχανή. Επιστρέφει 0 σε επιτυχία και μικρότερο του μηδενός σε αποτυχία. Καλεί την tm_control_restart() για να πάμε πάλι στην αρχική κατάσταση, και σβήνει τα δεδομένα κάθε ταινίας με την tm_tape_flush(). int tm_num_tapes(void); Επιστρέφει το πλήθος των ταινιών της μηχανής. int tm_show_state(char **state); Επιστρέφει μέσω της παραμέτρου state το όνομα της τρέχουσας κατάστασης. Επιστρέφει 0 αν η τρέχουσα κατάσταση δεν είναι τελική, 1 αν είναι τελική και μικρότερο του μηδενός σε αποτυχία (οι τιμές επιστροφής είναι οι τιμές επιστροφής της tm_control_is_final()). Στην καθολική μεταβλητή s_cur έχουμε τον κωδικό της τρέχουσας κατάστασης (βλέπε συνάρτηση tm_step() αφου έχει εκτελεστεί το tm_control_step()). Φέρνουμε το όνομα στο οποίο αντστοιχεί ο κωδικός s_cur και καλούμε την tm_control_is_final() για να δούμε αν είναι τελική κατάσταση η όχι. int tm_show_tape(int n, int i, char **symb); Επιστρέφει μέσω της παραμέτρου symb το όνομα της τρέχουσας κατάστασης το όνομα του συμβόλου που βρίσκεται στο i-οστό τετράγωνο της n-οστής ταινίας. Α. Τρουμπούκης, Γ. Παπαδημητρίου 40