Τα προγράμματα ως αριθμοί, και το αντίστροφο Για τη συζήτηση από δω και πέρα θα χρειαστούμε να βλέπουμε το τυχόν python πρόγραμμα ως ένα φυσικό αριθμό, και τον τυχόντα φυσικό αριθμό ως ένα python πρόγραμμα. Πώς γίνεται αυτό; Πολύ απλά, ένα python πρόγραμμα δεν είναι παρά ένα κομμάτι κειμένου, μια λέξη δηλ. πάνω από ένα συγκεκριμένο αλφάβητο. Το αλφάβητο που χρησιμοποιείται στους υπολογιστές σήμερα είναι το
Η απεικόνιση είναι εύκολο να δεί κανείς ότι είναι ένα προς ένα (αλλά όχι επί, αφού δεν είναι όλοι οι αριθμοί κωδικοποιήσεις συντακτικά σωστών προγραμμάτων), και ότι η απεικόνιση δεν είναι ένα προς ένα, αφού μπορεί δύο προγράμματα να μοιάζουν διαφορετικά αλλά να κάνουν την ίδια δουλειά, να υπολογίζουν δηλαδή την ίδια συνάρτηση. Είναι επίσης σημαντικό το ότι και οι δύο απεικονίσεις είναι υπολογίσιμες. Το ότι η είναι υπολογίσιμη είναι φανερό, ενώ το μόνο λεπτό σημείο όσον αφορά την υπολογισιμότητα της είναι στο κομμάτι όπου πρέπει να ελέγξουμε αν η λέξη του που προκύπτει είναι συντακτικά σωστό python πρόγραμμα ή όχι. Το να αποδείξουμε ότι κάτι τέτοιο είναι υπολογστικά εφικτό σημαίνει ουσιαστικά να γράψουμε ένα πρόγραμμα που να αναγνωρίζει αν ένα κομμάτι κειμένου (μια λέξη του ) είναι ένα σωστό συντακτικά python πρόγραμμα ή όχι. Τέτοια προγράμματα όμως υπάρχουν και χρησιμοποιούνται ευρέως αφού αποτελούν το πρώτο τμήμα των compilers ή interpreters (μεταφραστών) που παίρνουν ένα πρόγραμμα σε python και παράγουν από αυτό ένα ισοδύναμο πρόγραμμα σε «γλώσσα μηχανής».
Προσομοίωση. Θα χρειαστούμε επίσης το εξής: Υπάρχει ένα πρόγραμμα το οποίο (α) βρίσκει το πρόγραμμα και (β) «Τρέχει» το πρόγραμμα για τόσα βήματα όσα λέει ο αριθμός ή επ άπειρον αν ο αριθμός είναι αρνητικός. Αν και όταν το πρόγραμμα τελειώσει το επιστρέφει ότι επέστρεψε το . Δε θα δείξουμε την ύπαρξη αυτού του προγράμματος που προσμομοιώνει άλλα προγράμματα, μια και τέτοια προγράμματα υπάρχουν και χρησιμοποιούνται ευρέως στον προγραμματισμό (π.χ. interpreters, debuggers, κλπ).
Είμαστε έτοιμοι τώρα να αναφερθούμε στο Halting problem (πρόβλημα τερματισμού). Αυτό ρωτάει απλά αν υπάρχει ένα πρόγραμμα που να μπορεί να αποφασίζει αν ένα τυχόν άλλο πρόγραμμα που εμείς του προσδιορίζουμε θα τερματίσει ή όχι.
Είναι φανερό ότι υπάρχουν προγράμματα που δεν τερματίζουν ποτέ, π.χ. το παρακάτω.
def P(x): while True: x = 1 return 1
Ένα τέτοιο πρόγραμμα θα ήταν εξαιρετικά χρήσιμο αν υπήρχε. Φανταστείτε να έχετε ένα python interpreter ο οποίος όχι μόνο θα μετάφραζε το πρόγραμμά σας σε γλώσσα μηχανής αλλά θα μπορούσε και να σας πει εκ των προτέρων αν το πρόγραμμά σας θα έπεφτε σε άπειρο βρόχο (loop) ή όχι. Δυστυχώς όμως τέτοιο πρόγραμμα δεν υπάρχει.
Στο εξής, για τυχόν πρόγραμμα , θα γράφουμε αν το πρόγραμμα τερματίζει και αν το τρέχει επ' άπειρον.
def Q(x): if P(x, x)==0: return 1 else: while True: x = 1 # This does nothing and runs forever
Το πρόγραμμα που ορίσαμε έχει την ιδιότητα ότι τερματίζει αν και μόνο αν το δεν τερματίζει.
Ποια είναι η συμπεριφορά του προγράμματος ; Τερματίζει ή όχι; Σύμφωνα με τη προηγούμενη παρατήρηση τερματίζει αν και μόνο αν το πρόγραμμα δεν τερματίζει. Αλλά , οπότε δείξαμε ότι το πρόγραμμα τερματίζει αν και μόνο αν δεν τερματίζει, πράγμα προφανώς αδύνατο. Το συμπέρασμα είναι ότι η συνάρτηση δεν είναι υπολογίσιμη.
Έχουμε λοιπόν δείξει ότι η, πολύ φυσιολογική, συνάρτηση που διακρίνει πότε το πρόγραμμα τερματίζει με input ή όχι δεν είναι υπολογίσιμη. Έχουμε λοιπόν τώρα μια απόδειξη του ότι υπάρχουν μη υπολογίσιμες συναρτήσεις που είναι αρκετά πιο συγκεκριμένη από την προηγούμενη υπαρξιακή απόδειξη του Θεωρήματος 10.1. Μπορεί βέβαια και πάλι να πει κανείς ότι η δεν έχει ίσως και τόσο ενδιαφέρον από μαθηματική άποψη μια και είναι μια συνάρτηση «κομμένη και ραμμένη» στα μέτρα της Θεωρίας Υπολογισμών, και άρα όχι, ίσως, τόσο φυσιολογική.
Υπάρχουν όμως πολλά παραδείγματα αρκετά φυσιολογικών μαθηματικών προβλημάτων που δεν επιδέχονται λύση αλγοριθμική, προβλήματα που προυπήρχαν της Θεωρίας Υπολογισμών.
Ένα πολύ ενδιαφέρον ερώτημα είναι αν ένα δεδομένο πεπερασμένο σύνολο από πολυόμινα μπορεί να χρησιμοποιηθεί για να «πλακοστρώσει» ολόκληρο το επίπεδο. Αυτό σημαίνει ότι καλύπτουμε το επίπεδο, χωρίς αλληλοεπικαλύψεις, από κομμάτια καθ' ένα από τα οποία είναι μια παράλληλη μεταφορά κάποιου από τα δεδομένα πολυόμινα. Για παράδειγμα, είναι σχετικά εύκολο να δει κανείς πως τα δύο πολυόμινα του Σχήματος 10.1 μπορούν να πλακοστρώσουν (αγγλικά: tiling) το επίπεδο, και είναι επίσης εύκολο να φτιάξει κανείς παραδείγματα απο σύνολο πολυομίνων που δε μπορούν, όπως και να μεταφερθούν, να πλακοστρώσουν το επίπεδο. Αποδεικνύεται λοιπόν ότι το να αποφασίσει κανείς αν ένα δεδομένο σύνολο από πολυόμινα μπορεί να πλακοστρώσει το επίπεδο είναι αλγοριθμικά ανεπίλυτο πρόβλημα. Δεν υπάρχει δηλ. πρόγραμμα που να του δίνουμε ένα τυχόν πεπερασμένο σύνολο από πολυόμινα και να μας απαντά αν επιδέχεται πλακόστρωση ή όχι.
Mihalis Kolountzakis 2015-11-28