[ΠΛΗ 417] Τεχνητή Νοημοσύνη Project Εξαμήνου Γεωργαρά Αθηνά (A.M. 2011030065) ΠΟΛΥΤΕΧΝΕΙΟ ΚΡΗΤΗΣ ΤΜΗΜΑ ΗΛΕΚΤΡΟΛΟΓΩΝ ΜΗΧΑΝΙΚΩΝ & ΜΗΧΑΝΙΚΩΝ ΥΠΟΛΟΓΙΣΤΩΝ ΕΑΡΙΝΟ ΕΞΑΜΗΝΟ 2015-2016
Στη εργασία εξαμήνου αυτή έπρεπε να υλοποιήσουμε ένα πράκτορα ο οποίος θα παίζει το παιχνίδι Line of Actions. Συγκεκριμένα, ο πράκτοράς μας θα πρέπει να το αλγόριθμο αναζήτησης minimax. Μετά την υλοποίηση του κλασικού minimax, υλοποιήθηκε η βελτίωση α-β pruning. Ο πράκτορας γράφηκε στη γλώσσα προγραμματισμού C, χρησιμοποιώντας τους κώδικες βάσης που μας δόθηκαν. Αλγόριθμος minimax Ο ψευδοκώδικας του αλγορίθμου είναι ο εξής 1 : function minimax ( node, depth, maximizingplayer ) i f depth = 0 or node i s a terminal node return the h e u r i s t i c value of node i f maximizingplayer bestvalue := i n f v := minimax ( child, depth 1, FALSE) bestvalue := max( bestvalue, v ) return bestvalue e l s e ( * minimizing player * ) bestvalue := i n f v := minimax ( child, depth 1, TRUE) bestvalue := min( bestvalue, v ) return bestvalue Δημιουργία απόγονων καταστάσεων Κάθε φορά που καλείται η συνάρτηση minimax και δεν έχει φτάσει το μέγιστο βάθος πρέπει να βρεθούν όλες οι πιθανές κινήσεις. Στην παρούσα εργασία, χρησιμοποιούμε μια απλά συνδεδεμένη λίστα από structures. Κάθε κόμβος της λίστας αναπαριστά μια πιθανή ενέργεια, χρησιμοποιώντας μια μεταβλητή τύπου Move και ένα δείκτη στην επόμενη πιθανή ενέργεια. Ελέγχουμε λοιπόν όλα τα κελιά της σκακιέρας, και για κάθε κελί που περιέχει πιόνι δικό μας, προστίθενται οι πιθανές ενέργειες για αυτό το πιόνι στη λίστα. Ωστόσο, δεν είναι όλες οι ενέργειες επιτρεπτές. Για το λόγο αυτό ελέγχουμε κάθε ενέργεια αν είναι επιτρεπτή (χρησιμοποιώντας την έτοιμη συνάρτηση islegal) πριν την εισάγουμε στη λίστα. Εισάγουμε τις ενέργειες στη λίστα με μεθοδολογία push, και τις αφαιρούμε με μεθοδολογία pop. 1 (https://en.wikipedia.org/wiki/minimax) 1
Μετά τον έλεγχο ολόκληρης της σκακιέρας έχει δημιουργηθεί μια λίστα μόνο με τις νόμιμες σύμφωνα με τους κανονισμούς δυνατές ενέργιες. Αναδρομική κλήση του minimax Έχοντας τη λίστα με τις διάδοχες ενέργιες εκτελούμε μία μία της ενέργειες, χρησιμοποιώντας την έτοιμη συνάρτηση domove, και καλούμε αναδρομικά την συνάρτηση minimax. Συγκρίνουμε την επιστρεφόμενη αξιολόγηση για την ενέργεια αυτή, με τη μέχρι στιγμής καλύτερη ενέργεια. Αν η ενέργεια αυτή αποδίδει καλύτερα (είναι υψηλότερη σε περίπτωση maximizer, και χαμηλότερη σε περίπτωση minimizer), τότε κρατάμε αυτήν την αξιολόγηση και αυτήν την ενέργεια. Στο τέλος επαναφέρουμε τη σκακιέρα στη προηγούμενη κατάσταση εκτελόντας την αντίστροφη συνάρτηση undomove, ώστε να προχωρήσει η αναζήτηση στην επόμενη ενέργειαπαιδί. Η συνάρτηση minimax επιστρέφει ένα ζευγάρι {evaluation, move} (δομημένα σε ένα structure). Στην αρχή της συνάρτηση οι επιστρεφόμενες μεταβλητές αρχικοποιούνται ως εξής: e v a l = maximizingplayer move [ 0 ] = 1;? DBL_MIN : DBL_MAX; Το move[0] = 1 υποδηλώνει την κίνηση null. Οι σταθερές DBL_MIN, DBL_MAX είναι η ελάχιστη και η μέγιστη τιμή τύπου double. Και η μεταβλητή maximizingplayer δείχνει αν η κίνηση ανήκει στο πράκτορα ή στον αντίπαλό του. Στο τέλος, ο minimax θα επιστρέψει το ζευγάρι {evaluation, move} που αντιστοιχεί στην αποδοτικότερη κίνηση που βρήκε. Βελτίωση α-β pruning Αντίστοιχα, ο ψευδοκώδικας του αλγορίθμου είναι ο εξής 2 : function alphabeta ( node, depth, a, b, maximizingplayer ) i f depth = 0 or node i s a terminal node return the h e u r i s t i c value of node i f maximizingplayer v := i n f v := max( v, alphabeta ( child, depth 1, a, b, FALSE) ) a := max( a, v ) i f b a break ( * b cut o f f * ) 2 (https://en.wikipedia.org/wiki/alpha-beta_pruning) 2
return v e l s e v := + i n f v := min( v, alphabeta ( child, depth 1, a, b, TRUE) ) b := min(b, v ) i f b a break ( * a cut o f f * ) return v Οι ουσιαστικές διαφορές στον αλγόριθμο είναι ότι πρέπει να γίνουν συγκρίσεις με τις μεταβλητές α και β, οι οποίες παίρνουν την αποδοτικότερη τιμή μεταξύ της μέχρι στιγμής καλύτερης τιμής, της επιστρεφόμενης τιμής από την αναδρομική κλήση του minimax και του εαυτού τους. Καθώς και η τελική σύγκριση των δύο μεταβλητών α και β, για να κλαδέψουμε όσο το δυνατόν περισσότερο το δέντρο. Συνάρτηση Αξιολόγησης Ως συνάρτηση αξιολόγησης χρησιμοποιήθηκαν ιδέες από το paper An Evaluation Function For Lines Of Actions των M.H.M. Winands, H.J. van de Herik, J.W.H.M Uiterwijk 3. Concentration Αρχικά υπολογίζουμε για μια δεδομένη κατάσταση το κέντρο μάζας των πιονιών του παίκτη που μας ενδιαφέρει. Το κέντρο μάζας υπολογίζεται ως : mass_center = ( x y round( ), round( ) pieces pieces Όπου x είναι η γραμμή που βρίσκεται το κάθε πιόνι, y η στήλη και pieces το πλήθος των πιονιών. (Αυτά αναφέρονται μόνο σε πιόνια για τον παίκτη που μας ενδιαφέρει.) Έχοντας υπολογίσει το κέντρο μάζας, υπολογίζουμε την μέση απόσταση των πιονιών του παίκτη από το κέντρο τους. max { center x i, center y j } i,j Το άθροισμα αυτό ονομάζεται sum-of-distances. Επίσης, υπολογίζει και το ελάχιστο δυνατό μέσο όρο αποστάσεων. Στο κέντρο μάζας μπορεί να βρίσκεται μόνο ένα πιόνι. Το πιόνι αυτό συνεισφέρει απόσταση 0. Τα πιόνια στα γειτονικά κελιά συνεισφέρουν απόσταση 1, τα πιόνια στο αμέσως επόμενο πλαίσιο συνεισφέρουν απόσταση 2 κ.ο.κ. 2 2 2 2 2 2 1 1 1 2 2 1 0 1 2 2 1 1 1 2 2 2 2 2 2 2 1 0 1 2 2 1 1 1 2 2 2 2 2 2 3 2 1 0 3 2 1 1 3 2 2 2 3 3 3 3 3 (http://link.springer.com/chapter/10.1007%2f978-0-387-35706-5_16) 3
Σημειώνουμε ότι ο μέγιστος αριθμός πιονιών μπορεί να έχει κάθε παίκτης είναι 12. Επομένως οι παραπάνω 3 περιπτώσεις καλύπτουν όλες τις πιθανές διτάξεις (κάνοντας χρήση και της συμμετρίας). Όπως και προηγουμένως υπολογίζουμε την ιδανική μέση ελάχιστη απόσταση σύμφωνα με το πλήθος των πιονιών και το κέντρο μάζας τους. Αυτή η απόσταση λέγεται sum-ofminimal-distances. Υπολογίζουμε την ποσότητα : surplus of distances = Και βρίσκουμε την συγκέντρωση(concentration) ως: Centralization concentration = sum of distances sum of minimal distances 1 surplus of distances Τα κομμάτια που βρίσκονται στα άκρα της σκακιέρας είναι πολύ εύκολο να μπλοκαριστούν από κομμάτια του αντιπάλου. Για το λόγο αυτό, ευνοούμε τα κομμάτια που βρίσκονται το κέντρο της σκακιέρας και τιμωρούμε αυτά που βρίσκονται στα άκρα. Συγκεκριμένα ακολουθούμε το παρακάτω βαθμολόγησης: Κάθε κομμάτι που βρίσκεται σε κάποια από τις τέσσερις γωνίες τις σκακιέρας τότε συνεισφέρει μια αρνητική βαθμολογία 2.0. Κάθε κομμάτι που βρίσκεται στα όρια της σκακιέρας, αλλά όχι σε γωνία συνεισφέρει μια αρνητική βαθμολογία 0.5. Κάθε κομμάτι που απέχει απόσταση μεγαλύτερη του τέσσερα από το κέντρο της σκακιέρας, συνεισφέρει μια θετική βαθμολογία 0.5. Κάθε κομμάτι σε απόσταση τρία από το κέντρο της σκακιέρας, συνεισφέρει με μια θετική βαθμολογία 1.5. Κάθε κομμάτι σε απόσταση μικρότερη του τρία, συνεισφέρει με μια θετική βαθμολογία 3.5. Επομένως η κεντρικοποίηση (centralization): centralization = 3.5+ Quads pieces Dist<2 pieces 2<Dist<4 1.5+ pieces Dist 4 0.5 pieces corner 2.0 pieces edge Ένα quad (τετράδα) ορίζεται ως ένας 2 2 πίνακας. Συνολικά για κάθε παίκτη υπάρχουν 81 πιθανά quads (συμπεριλαμβανομένου και των quads που δεν καλύπτουν πλήρως την σκακιέρα). Υπάρχουν 6 διαφορετικά quad όπως φαίνεται στην εικόνα (1) Στην εικόνα(1), οι μαύρες τελείες, οι παχιές γραμμές και τα κατειλημμένα τετράγωνα σημειώνουν κορυφές (vertices), ευθύγραμμα τμήματα (line segments) και γεμμάτες περιοχές (filled regions), αντίστοιχα. Ο αριθμός Euler για το πλέγμα (την σκακιέρα 8 8) αντιπροσωπεύει 0.5 4
Q 0 Q 1 Q 2 Q 3 Q 4 Q d Figure 1: Different type of quads τον αριθμό από συνδεδεμένες ομάδες πλην τον αριθμό από τρύπες (holes). Σύμφωνα με το Gray, τα quads μπορούν να χρησιμοποιηθούν για να υπολογίσουμε τον αριθμό Euler με τον εξής τρόπο: Έστω n 0 ο συνολικός αριθμός από vertices n 1 ο συνολικός αριθμός από line segments n 2 ο συνολικός αριθμός από filled regions Τότε ο αριθμός Euler δίνεται από : E = n 0 n 1 + n 2 Παρατηρώντας τα quads, ισχύουν τα παρακάτω: Κάθε κορυφή (vertix) μπορεί να ανήκει μόνο σε ένα quad Κάθε ευθύγραμμο τμήμα (line segment) μπορεί να ανήκει σε δύο quads Κάθε γεμάτη περιοχή (filled region) μπορεί να ανήκει σε τέσσερα quads Σε κάθε κορυφή δίνεται ένα βάρος αξίας 1, για κάθε ευθύγραμμο τμήμα ένα βάρος 1/2 και για κάθε γεμάτη περιοχή ένα βάρος 1/4. Επειδή είναι αδύνατον να σπάσουμε σχηματισμούς quad με 3 και 4 κομμάτια, ευνοούμε αυτούς τους σχηματισμούς. Ωστόσο, υπάρχει κίνδυνος να σχηματιστούν τέτοιου είδους quads μακριά από το κέντρο μάζας. Για το λόγο αυτό, υπολογίζουμε τα quads στα οποία συμμετέχει το κέντρο μάζας και ευνοούμε τα Q 3 και Q 4. Εν τέλει υπολογίζουμε τον αριθμό Euler για τα τέσσερα quad στα οποία συμμετέχει το κέντρο μάζας. E = n 0 n 1 2 + n 2 4 όπου τα n 0, n 1 και n 2 είναι τα προαναφερμένα, αλλά υπολογισμένα μόνο για τέσσερα συγκεκριμένα quads. Τελική αξιολόγηση Εν τέλει, η ποσότητα που επιστρέφει η συνάρτηση αξιόλόγησης είναι : return value = concentration + centralization + quads 5
Συνάρτηση αξιολόγησης στο minimax/alpha-beta Τόσο στη συνάρτηση minimax όσο και στη συνάρτηση alpha-beta υπολογίζουμε το evaluation για το παίκτη, το evaluation για τον αντίπαλο και ως χρησιμότητα παίρνουμε τη διαφορά utility = evaluation(gamep osition, player) 0.2 evaluation(gamep osition, opponent) Δεν χρησιμοποιούμε λοιπόν μόνο την αξιολόγηση για τον δικό μας παίκτη, αλλά προσμετράμε (με ένα μικρό ποσοστό) και την αξιολόγηση του αντιπάλου. Συνάρτηση Αποκοπής Για την συνάρτηση αποκοπή λαμβάνουμε υπ όψιν το πλήθος των κομματιών που βρίσκονται πάνω στη σκακιέρα. Αν κάποιος από τους δύο παίκτες έχει τουλάχιστον 6 κομμάτια στη σκακιέρα, τότε το βάθος αποκοπής είναι 4 για τον minimax και 6 για τον alpha-beta. Αλλιώς αν το συνολικό πλήθος των κομματιών είναι τουλάχιστον 6, τότε το βάθος είναι 5 και 7 για τον minimax και τον alpha-beta. αντίστοιχα. Τέλος αν το σύνολο των κομματιών είναι το πολύ 6, τότε το βάθος είναι 6 και 8 για τον minimax και τον alpha-beta, αντίστοιχα. Compile / Execute Όπως ανέφερα στην αρχή το πρόγραμμα είναι γραμμένο στη γλώσσα C. Έχει τροποποιηθεί το make file ώστε να μπορεί να χρησιμοποιηθεί. Επίσης έχει προστεθεί η επιλογή στα input argumets ώστε να αλλάζει κατά την εκτέλεση η συνάρτηση minimax και alphabeta. Με εντολή:. / c l i e n t f on ο πράκτορας εκτελεί την συνάρτηση alpha-beta, ενώ η default είναι η συνάρτηση minimax. 6