Αναδροµή. Προγραµµατισµός Ι 1

Σχετικά έγγραφα
Προγραμματισμός Ι (ΗΥ120)

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

Οι πύργοι του Hanoi ίνεται ένα χώρος µε τρείς θέσεις αποθήκευσης. ίνεται µια στοίβα από Ν πλάκες σε φθίνων µέγεθος, σε µια από τις τρείς θέσεις. Ζητού

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

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

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

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

Διασυνδεδεμένες Δομές. Δυαδικά Δέντρα. Προγραμματισμός II 1

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

διεύθυνση πρώτου στοιχείου διεύθυνση i-οστού στοιχείου T t[n]; &t[0] είναι t &t[i] είναι t + i*sizeof(t)

Αναδρομικοί Αλγόριθμοι

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

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

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

Εισαγωγή στον Προγραµµατισµό. Πανεπιστήµιο Θεσσαλίας Τµήµα Ηλεκτρολόγων Μηχανικών και Μηχανικών Η/Υ

int a[5]; a[0] a[1] a[2] a[3] a[4] 15/10/2009

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

Προγραµµατισµός. Αναδροµή (1/2)

Δείκτες (Pointers) Ένας δείκτης είναι μια μεταβλητή με τιμή μια διεύθυνση μνήμης. 9.8

Ν!=1*2*3* *(N-1) * N => N! = (Ν-1)! * N έτσι 55! = 54! * 55

Διδάσκων: Κωνσταντίνος Κώστα Διαφάνειες: Δημήτρης Ζεϊναλιπούρ

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

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

Διασυνδεδεμένες Δομές. Λίστες. Προγραμματισμός II 1

που θα δώσει αποτέλεσµα 48, λόγω της αριστερής προσεταιριστικότητας των τελεστών / και *, ενώ η επιθυµητή αντικατάσταση θα ήταν η

ΕΙΣΑΓΩΓΗ ΣΤΟΝ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟ Ενδεικτικές Απαντήσεις Εξετάσεων Α' Περιόδου Θέµα 1. (α') 2 - ii 3 - iii 4 - iv

ΠΛΗ111. Ανοιξη Μάθηµα 7 ο. έντρο. Τµήµα Ηλεκτρονικών Μηχανικών και Μηχανικών Υπολογιστών Πολυτεχνείο Κρήτης

Αναδροµή. Σε αυτήν την (βοηθητική) ενότητα θα µελετηθούν τα εξής : Η έννοια της αναδροµής Υλοποίηση και αποδοτικότητα Αφαίρεση της αναδροµής

Εισαγωγή στον Προγραμματισμό

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

Επίλυση Προβλημάτων 1

Π. Σταθοπούλου ή Οµάδα Α (Φοιτητές µε µονό αριθµό Μητρώου ) ιδασκαλία : Παρασκευή 11πµ-13µµ ΗΛ7

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

Branch and Bound. Branch and Bound

Ενδεικτικές λύσεις και στατιστικά

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

Προεπεξεργαστής C. Προγραμματισμός Ι 1

Ενώσεις δεδομένων Απαριθμητές Ψηφιακοί τελεστές Αναδρομικές συναρτήσεις

Μεταγλώττιση και σύνδεση πολλαπλών αρχείων κώδικα. Προγραμματισμός II 1

Προγραμματιστικές Ασκήσεις, Φυλλάδιο 1

Α Β Γ static; printf("%c\n", putchar( A +1)+2); B DB BD. int i = 0; while (++i); printf("*");

Εισαγωγή στην C. Μορφή Προγράµµατος σε γλώσσα C

είκτες και Πίνακες (2)

Αλγόριθμοι Ταξινόμησης Μέρος 1

Δομές Δεδομένων (Data Structures)

Διάλεξη 6: Δείκτες και Πίνακες

Επεξεργασία Αρχείων Κειµένου

Διδάσκων: Παναγιώτης Ανδρέου

Π. Σταθοπούλου ή Οµάδα Α (Φοιτητές µε µονό αριθµό Μητρώου ) ιδασκαλία : Παρασκευή 11πµ-13µµ ΗΛ7

Διάλεξη 20: Αναδρομή (Recursion) Διδάσκων: Παναγιώτης Ανδρέου

Προγραμματισμό για ΗΜΥ

Προγραμματισμός Η/Υ (ΤΛ2007 )

Αναδροµή (Recursion) ύο παρεξηγήσεις. Σκέψου Αναδροµικά. Τρίγωνο Sierpinski Μη αναδροµικός ορισµός;

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

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

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

Κεφάλαιο 6 Υλοποίηση Γλωσσών Προγραμματισμού

Αλγόριθµοι Οπισθοδρόµησης

Χαρακτηριστικά αναδροµής

Αναδρομή Ανάλυση Αλγορίθμων

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

int array[10]; double arr[5]; char pin[20]; Προγραµµατισµός Ι

Π. Σταθοπούλου ή Οµάδα Α (Φοιτητές µε µονό αριθµό Μητρώου ) ιδασκαλία : Παρασκευή 11πµ-13µµ ΗΛ7

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

Διάλεξη 15: Αναδρομή (Recursion) Διδάσκων: Παναγιώτης Ανδρέου

Δυναμική δέσμευση και αποδέσμευση μνήμης. Προγραμματισμός II 1

Τεχνητή Νοημοσύνη (ΥΠ23) 6 ο εξάμηνο Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο Ουρανία Χατζή

ΣΧΕΔΙΑΣΗ ΚΑΙ ΥΛΟΠΟΙΗΣΗ ΛΟΓΙΣΜΙΚΟΥ

Δομές Δεδομένων & Αλγόριθμοι

Τεχνητή Νοημοσύνη (ΥΠ23) 6 ο εξάμηνο Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο Ουρανία Χατζή

Διάλεξη 15η: Αναδρομή, μέρος 1ο

Ανάπτυξη Μεγάλων Εφαρµογών στη Γλώσσα C (2)

ΠΑΡΑΡΤΗΜΑ: QUIZ ΔΟΜΕΣ ΔΕΔΟΜΕΝΩΝ

Εισαγωγή στους Η/Υ. Γιώργος Δημητρίου. Μάθημα 3-4: Προγραμματισμός MIPS. Πανεπιστήμιο Θεσσαλίας - Τμήμα Πληροφορικής

Εργαστήριο 8: Αναδρομική διεργασία εισαγωγής καινούριου κόμβου σε ΔΔΑ

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

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

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

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

ΕΙΣΑΓΩΓΗ ΣΤΟΝ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟ Ενδεικτικές Απαντήσεις Εξετάσεων Β' Περιόδου Θέµα 1. (α')

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

Σχεδίαση Αλγορίθμων - Τμήμα Πληροφορικής ΑΠΘ -4ο εξάμηνο 1

ΕΠΛ 231 οµές εδοµένων και Αλγόριθµοι Άννα Φιλίππου,

Μια TM µπορεί ένα από τα δύο: να αποφασίζει µια γλώσσα L. να αναγνωρίζει (ηµιαποφασίζει) µια γλώσσα L. 1. Η TM «εκτελεί» τον απαριθµητή, E.

Επανάληψη για τις Τελικές εξετάσεις

ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΥΠΡΟΥ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ. ΕΠΛ 035: οµές εδοµένων και Αλγόριθµοι για Ηλεκτρολόγους Μηχανικούς και Μηχανικούς Υπολογιστών

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

4.3. Γραµµικοί ταξινοµητές

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

Αλγόριθμοι και Δομές Δεδομένων (IΙ) (γράφοι και δένδρα)

Δημιουργία & Τερματισμός Διεργασιών. Προγραμματισμός II 1

Διδάσκων: Παναγιώτης Ανδρέου

Προγραμματισμός Η/Υ (ΤΛ2007 )

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

οριακό PASS 402 PASS Πολύ σωστά, µπράβο οριακό PASS

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

ΠΛΕ075: Προηγμένη Σχεδίαση Αλγορίθμων και Δομών Δεδομένων. Λουκάς Γεωργιάδης

scanf() scanf() stdin scanf() printf() int float double %lf float

ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ

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

Transcript:

Αναδροµή Προγραµµατισµός Ι lalis@inf.uth.gr 1

Συναρτήσεις που καλούν τον εαυτό τους Μια συνάρτηση ονοµάζεται αναδροµική όταν καλεί τον εαυτό της άµεσα ή έµµεσα (µέσα από άλλες συναρτήσεις). Μια αναδροµική συνάρτηση πρέπει να τερµατίζει. Ηατέρµονη αναδροµή είναι προγραµµατιστικό λάθος (αντίστοιχο µε αυτό της ατέρµονης επανάληψης) και οδηγεί σε τερµατισµό του προγράµµατος, λόγω υπερχείλισης της στοίβας (stack overflow). Ηαναδροµή µπορεί να θεωρηθεί σαν ένα ξεχωριστό παράδειγµα προγραµµατισµού καθώς διάφορα (πολύπλοκα) προβλήµατα µπορεί να λυθούν µε φυσικό τρόπο χρησιµοποιώντας αναδροµή. Προγραµµατισµός Ι lalis@inf.uth.gr 2

/* εκτύπωση τιµών από 0 µέχρι n */ #include <stdio.h> void printints(int from, int to) { int i; for(i=from; i <= to; i++) { printf("%d ",i); int main(int argc, char *argv[]) { int n; printf("enter int: "); scanf("%d",&n); printints(0,n); Προγραµµατισµός Ι lalis@inf.uth.gr 3

0 1 2 3 4 5 τύπωσε 0 τύπωσε 1-5 τύπωσε 1 τύπωσε 2-5 τύπωσε 2 τύπωσε 3-5 τύπωσε 3 τύπωσε 4-5 τύπωσε 4 τύπωσε 5-5 τύπωσε 5 τύπωσε 6-5 Προγραµµατισµός Ι lalis@inf.uth.gr 4

/* εκτύπωση τιµών από 0 µέχρι n */ #include <stdio.h> void printints(int from, int to) { if (from <= to) { printf("%d ",from); printints(from+1,to); int main(int argc, char *argv[]) { int n; printf("enter int: "); scanf("%d",&n); printints(0,n); Προγραµµατισµός Ι lalis@inf.uth.gr 5

printints(0,3) printints(1,3) printints(2,3) printints(3,3) printints(4,3) 0 1 2 3 Προγραµµατισµός Ι lalis@inf.uth.gr 6

/* εκτύπωση τιµών από n µέχρι 0 */ #include <stdio.h> void printintsrev(int from, int to) { if (from<=to) { printintsrev(from+1,to); printf("%d ",from); int main(int argc, char *argv[]) { int n; printf("enter int: "); scanf("%d",&n); printintsrev(0,n); Προγραµµατισµός Ι lalis@inf.uth.gr 7

printintsrev(0,3) printintsrev(1,3) printintsrev(2,3) printintsrev(3,3) printintsrev(4,3) 3 2 1 0 Προγραµµατισµός Ι lalis@inf.uth.gr 8

Αναδροµική σκέψη και λύση προβληµάτων Για να λυθεί ένα πρόβληµα µε αναδροµή, πρέπει πρώτα να εκφραστεί µε αναδροµικό τρόπο. Κλασική προσέγγιση: 1. Προσπαθούµε ναβρούµε την λύση του προβλήµατος για την πιο απλή περίπτωση του. 2. Στην συνέχεια, ανάγουµε/κατασκευάζουµε τηνλύση της (αµέσως) πιο πολύπλοκης περίπτωσης, µε βάση την λύση της πιο απλής περίπτωσης (αναδροµή). 3. Αν τα (1) και (2) γίνουν «σωστά», έχουµε ήδη κατασκευάσει την λύση στο πρόβληµα µας! Ησυνθήκητερµατισµού είναι πολλές φορές το κλειδί στην ανεύρεση της πιο απλής περίπτωσης. Προγραµµατισµός Ι lalis@inf.uth.gr 9

Υπολογισµός x! Επιθυµούµε να υπολογίζουµε την έκφραση x! == 1*2*3* *(x-1)*x Περίπτωση τερµατισµού x==0 ή x==1: επιστρέφεται 1 Γενική περίπτωση x > 1: επιστρέφεται x*(x-1)! Η «λύση» της γενικής περίπτωσης µπορεί να κατασκευαστεί µε βάσητηνλύσητουίδιου προβλήµατος, σε µικρότερη «κλίµακα». Προγραµµατισµός Ι lalis@inf.uth.gr 10

/* υπολογισµός n! */ int factorial(int n) { if (n<=1) { return(1); else { return(n*factorial(n-1)); Προγραµµατισµός Ι lalis@inf.uth.gr 11

24 factorial(4) 4 * 6 factorial(3) 3 * 2 factorial(2) 2 * 1 factorial(1) 1 Προγραµµατισµός Ι lalis@inf.uth.gr 12

Οι πύργοι του Hanoi ίνεται ένα χώρος µε τρείς θέσεις αποθήκευσης. ίνεται µια στοίβα από Ν πλάκες σε φθίνων µέγεθος, σε µια από τις τρείς θέσεις. Ζητούµενο: µετακίνησε την στοίβα σε µια άλλη θέση χωρίς ποτέ να βάλεις µια µεγαλύτερη πλάκα πάνω από µια µικρότερη πλάκα. Α Β Γ Προγραµµατισµός Ι lalis@inf.uth.gr 13

Λύση µε 1 πλάκα Α Β Γ Προγραµµατισµός Ι lalis@inf.uth.gr 14

Λύση µε 2 πλάκες Α Β Γ Προγραµµατισµός Ι lalis@inf.uth.gr 15

Λύση µε 2 πλάκες Α Β Γ Προγραµµατισµός Ι lalis@inf.uth.gr 16

Λύση µε 2 πλάκες Α Β Γ Προγραµµατισµός Ι lalis@inf.uth.gr 17

Λύση µε 2 πλάκες Α Β Γ Προγραµµατισµός Ι lalis@inf.uth.gr 18

Λύση µε 2 πλάκες Α Β Γ Προγραµµατισµός Ι lalis@inf.uth.gr 19

Λύση για Ν πλάκες Θεωρούµε ότιοιµικρότερες Ν-1 πλάκες είναι µια πλάκα, η µετακίνηση της οποίας µπορεί να γίνει πλέον αναδροµικά (Ν-1 πλάκες πρέπει να µετακινηθούν από µια θέση σε µια άλλη µέσω µιας τρίτης). Α Β Γ Προγραµµατισµός Ι lalis@inf.uth.gr 20

Μοντελοποίηση της λύσης Μετακίνησε Ν πλάκες από την θέση Α µέσω της θέσης Β στην θέση Γ: Απλή περίπτωση: αν Ν==1 τότε µεταφέρουµε την πλάκα από την θέση Α απ ευθείας στην θέση Γ. Πολύπλοκη περίπτωση: αν Ν>1, τότε (α) µεταφέρουµε τιςπάνων-1 πλάκες από την θέση Α µέσω της θέσης Γ στην θέση Β, (β) µεταφέρουµε την(µια) πλάκα που απέµεινε από την θέση Α απ ευθείαςστηνθέσηγ, και (γ) µεταφέρουµε τιςν-1 πλάκες από την θέση Β µέσω της θέσης Α στην θέση Γ. Προγραµµατισµός Ι lalis@inf.uth.gr 21

void movetower(int a, int b, int c, int n) { if (n==1) { movepiece(a,c); else { movetower(a,c,b,n-1); movepiece(a,c); movetower(b,a,c,n-1); Προγραµµατισµός Ι lalis@inf.uth.gr 22

Σχεδίαση αναδροµικών σχηµάτων Η draw_cross(int x, int y, int len) ζωγραφίζει ένα σταυρό, µε κέντρο το σηµείο (x,y) και µήκος 2*len. len x y Προγραµµατισµός Ι lalis@inf.uth.gr 23

Σχεδίαση αναδροµικών σχηµάτων Ζητούµενο: υλοποιήστε µια συνάρτηση που σχεδιάζει τα εξής σχήµατα µε βάση τις ακέραιες παραµέτρους x, y, len και level. level=1 level=2 level=3 len len len len x,y len x,y len x,y Προγραµµατισµός Ι lalis@inf.uth.gr 24

Σχεδίαση αναδροµικών σχηµάτων Παρατήρηση: το ίδιο σχέδιο επαναλαµβάνεται σε µικρότερη κλίµακα σε όλα τα τεταρτηµόρια του σχεδίου της αµέσως µεγαλύτερης κλίµακας. level=1 level=2 level=3 Προγραµµατισµός Ι lalis@inf.uth.gr 25

void draw_grid(int x, int y, int len, int level) { if (level==1) { draw_cross(x,y,len); else { draw_cross(x,y,len); draw_drid(x-len/2,y+len/2,len/2,level-1); draw_grid(x-len/2,y-len/2,len/2,level-1); draw_grid(x+len/2,y-len/2,len/2,level-1); draw_grid(x+len/2,y+len/2,len/2,level-1); Προγραµµατισµός Ι lalis@inf.uth.gr 26

Έλεγχος και αποτίµηση εκφράσεων ίνεται το συντακτικό των επιτρεπτών αριθµητικών εκφράσεων (προτάσεων) µε βάσηebnf. ενυπάρχουνσυγκεκριµένες προτεραιότητες, και ηαποτίµηση γίνεται από δεξιά προς τα αριστερά. Ζητούµενο: να υλοποιηθεί µια συνάρτηση που ελέγχει κατά πόσο η έκφραση που δίνεται από τον χρήστη σαν είσοδος αντιστοιχεί σε µια επιτρεπτή πρόταση, και αν ναι να υπολογίζει και να επιστρέφει το αποτέλεσµα. Επιτρέπονται κενά εκτός ανάµεσασταψηφίαενός αριθµού, και το τέλος της έκφρασης σηµατοδοτείται από τον χαρακτήρα '\n'. Προγραµµατισµός Ι lalis@inf.uth.gr 27

ΕBNF ακέραια-έκφραση=ακέραιος[πράξη ακέραια-έκφραση] ακέραιος=νούµερο{νούµερο νούµερο= 0 1 2 3 4 5 6 7 8 9 πράξη== + - * / Syntax diagram ακέραια-έκφραση ακέραιος πράξη ακέραια-έκφραση ψηφίο ακέραιος ψηφίο + 0 πράξη - * ψηφίο 1 / Προγραµµατισµός Ι lalis@inf.uth.gr 28 9

11 parse_expr() 15-4 11 parse_expr() 8 / 2 4 parse_expr() 2 \n 2 15-8 / 2 <return> Προγραµµατισµός Ι lalis@inf.uth.gr 29

Αναδροµή και επανάληψη Οι περισσότερες µορφές επανάληψης µπορεί να εκφραστούν µε αναδροµή, αρκεί η συνάρτηση να περνά στον εαυτό της τις κατάλληλες παραµέτρους. Αντίθετα, υπάρχουν αρκετές µορφές αναδροµής που είναι δύσκολο να εκφραστούν µε επανάληψη. Το κύριο πλεονέκτηµα της αναδροµής είναι ότι η συνάρτηση κρατά δυναµική ενδιάµεση κατάσταση µέσα από τις τοπικές µεταβλητές (πλαίσιο εκτέλεσης) κάθε (αλυσιδωτής) αναδροµικής κλήσης. Παρόµοιο αποτέλεσµα µπορεί να επιτευχθεί και µε συµβατικό τρόπο, αλλά η διαχείριση της κατάστασης πρέπει να γίνει από τον ίδιο τον προγραµµάτιστή (συνήθως χρησιµοποιώντας δυναµική µνήµη). Προγραµµατισµός Ι lalis@inf.uth.gr 30

Συνδυαστικά προβλήµατα Προγραµµατισµός Ι lalis@inf.uth.gr 31

Επίλυση συνδυαστικών προβληµάτων Συχνά ένα πρόβληµα µπορεί να εκφραστεί ως µια «αναζήτηση» ενός επιτρεπτού συνδυασµού κάποιων µεταβλητών µέσα από όλους τους δυνατούς συνδυασµούς που µπορεί να γίνουν. Κάποιες φορές, το ζητούµενο είναι να βρεθεί ο βέλτιστος συνδυασµός, που ελαχιστοποιεί ή µεγιστοποιεί κάποια συνάρτηση των µεταβλητών. Λύση µε αναδροµή: 1. Κατασκευάζουµε τοσύνολοτωνσυνδυασµών αναδροµικά (µε διεξοδική «αναζήτηση» σε βάθος). 2. Ελέγχουµε κάθεσυνδυασµό για το κατά πόσο είναι επιτρεπτός ή/και καλύτερος σε σχέση µε τους συνδυασµούς που έχουν κατασκευαστεί / εξεταστεί. Προγραµµατισµός Ι lalis@inf.uth.gr 32

έντρα συνδυασµών και αποφάσεων Όλοι οι δυνατοί συνδυασµοί (µεταβλητών) µπορεί να µοντελοποιηθούν (αναπαρασταθούν) ως ένα δέντρο. Κάθε κόµβος του δέντρου σε επίπεδο L αντιστοιχεί σε ένα συγκεκριµένο συνδυασµό επιλογών (τιµών) για L διαφορετικές µεταβλητές. Ξεκινώντας από ένα κόµβο σε επίπεδο L, επιλέγουµε την επόµενη µεταβλητή, και για κάθε τιµή πουαυτή µπορεί να λάβει κατασκευάσουµε ένα κόµβο παιδί σε επίπεδο L+1, κλπ. Ένας κόµβος αποτελεί «φύλλο» όταν δεν υπάρχουν άλλες «ελεύθερες» µεταβλητές όλες έχουν λάβει συγκεκριµένες τιµές. Προγραµµατισµός Ι lalis@inf.uth.gr 33

(αναδροµική) παραγωγή όλων των δυνατών συνδυασµών έλεγχος για επιθυµητούς ή βέλτιστους συνδυασµούς δυνατοί συνδυασµοί επιθυµητοί συνδυασµοί Προγραµµατισµός Ι lalis@inf.uth.gr 34

Αποφυγή της συνδυαστικής έκρηξης Οαριθµός των µεταβλητών µπορεί να είναι µεγάλος και οι πιθανές τιµές για κάθε µεταβλητή πολλές. Η παραγωγή όλων των δυνατών συνδυασµών απαιτεί πόρους (µνήµη, χρόνος) µπορεί να είναι πρακτικά ανέφικτη (ακόµα καιµε τησηµερινή τεχνολογία). Επιπλέον, οι περισσότεροι από τους συνδυασµούς που παράγονται «στα τυφλά» είναι καταδικασµένοι εκ των προτέρων (πολύ πριν δηµιουργηθούν οι τερµατικοί κόµβοι «φύλλα» του δέντρου) να µην επιλεγούν ποτέ ως επιθυµητοί (ή βέλτιστοι). Βελτιστοποίηση: πρόωρος αποκλεισµός ολόκληρων υποδέντρων από την ρίζα τους χωρίς υπολογισµό των αντίστοιχων συνδυασµών (branch and bound). Προγραµµατισµός Ι lalis@inf.uth.gr 35

παραγωγή των συνδυασµών µε αποκλεισµό όλων των «αδιάφορων» υποδέντρων δεν παράγεται επιπλέον έλεγχος για επιθυµητούς ή/και βέλτιστους συνδυασµούς επιθυµητοί συνδυασµοί Προγραµµατισµός Ι lalis@inf.uth.gr 36

Απλό παράδειγµα -8 Queens Ζητούµενο: να βρεθεί λύση στο εξής πρόβληµα: να τοποθετηθούν 8 ντάµες σε µια σκακιέρα έτσι ώστε να µην απειλούνται µεταξύ τους Προγραµµατισµός Ι lalis@inf.uth.gr 37

Εντοπισµός σύγκρουσης (col,row) ίδια κολώνα: col==col διαγώνιος 1: col+row==col +row ίδια γραµµή: row==row (0,0) διαγώνιος 2: col-row==col -row int check(int col1,int row1,int col2,int row2) { return((col1!=col2) && (row1!=row2) && (col1+row1!=col2+row2) && (col1-row1!=col2-row2)); Προγραµµατισµός Ι lalis@inf.uth.gr 38

ύο προσεγγίσεις Προσέγγιση 1 (brute force): 1. ηµιουργούµε όλους τους συνδυασµούς θέσεων. 2. ιαγράφουµε τους συνδυασµούς όπου δύο ή περισσότερες ντάµες απειλούν η µια την άλλη. 3. Οι συνδυασµοί που αποµένουν είναι αποδεκτοί. Προσέγγιση 2 (b&b): 1. Για κάθε νέα ντάµα που τοποθετούµε, ελέγχουµε προκαταβολικά κατά πόσο απειλεί µια από τις ντάµες που έχουν ήδη τοποθετηθεί στη σκακιέρα. 2. Σε αυτή τη περίπτωση, τερµατίζουµε τηναναδροµή (όλοι οι περαιτέρω συνδυασµοί είναι µη αποδεκτοί). 3. Οι συνδυασµοί που µένουν είναι οι επιθυµητοί. Προγραµµατισµός Ι lalis@inf.uth.gr 39

αριθµός στήλης για τις ντάµες 0<=i<n που έχουν τοποθετηθεί µέχρι στιγµής αριθµός γραµµής για τις ντάµες 0<=i<n που έχουν τοποθετηθεί µέχρι στιγµής void putnxtqueen(int cols[], int rows[], int n, int M) { αριθµός επόµενης ντάµας προς τοποθέτηση τελικός αριθµός από ντάµες προς τοποθέτηση /* κλήση */ #define Μ 8 int cols[μ],rows[μ]; putnxtqueen(cols,rows,0,μ); Προγραµµατισµός Ι lalis@inf.uth.gr 40

Προσέγγιση 1 (έλεγχος στο τέλος) void putnxtqueen(int cols[], int rows[], int n, int M) { int i,j; (βλακώδης) δηµιουργία όλων των συνδυασµών (φύλλων του δέντρου) if (n<m) { for (i=0; i<m; i++) { for (j=0; j<m; j++) { cols[n]=j; rows[n]=i; putnxtqueen(cols,rows,n+1,m); απόρριψη συνδυασµού (φύλλου) αν υπάρχει κάποια σύγκρουση else { for (i=0; i<m; i++) { for (j=i; j<m; j++) { if (!check(cols[i],rows[i],cols[j],rows[j])) {return; for (i=0; i<m; i++) {printf("(%d,%d)\n",cols[i],rows[i]); εκτύπωση αποδεκτού συνδυασµού Προγραµµατισµός Ι lalis@inf.uth.gr 41

Προσέγγιση 2(έλεγχος στην τοποθέτηση) void putnxtqueen(int cols[], int rows[], int n, int M) { int i,j,k,ok; if (n<m) { for (i=0; i<m; i++) { for (j=0; j<m; j++) { ok = 1; for (k=0; (k<n) && (ok); k++) { ok = check(j,i,cols[k],rows[k]); if (ok) { col[n]=j; row[n]=i; putnxtqueen(cols,rows,n+1,m); έλεγχος σύγκρουσης για την νέα τοποθέτηση j,i εκτύπωση αποδεκτού συνδυασµού else { for (i=0; i<m; i++) {printf("(%d,%d)\n",cols[i],rows[i]); Προγραµµατισµός Ι lalis@inf.uth.gr 42

Βελτιστοποίηση Ακόµα και ένας πρωτάρης σκακιστής, µπορεί να συµπεράνει ότι κάθε ντάµα πρέπει υποχρεωτικά να τοποθετηθεί σε ξεχωριστή γραµµή. Ιδέα: παράγουµε τους συνδυασµούς υπό τον περιορισµό ότι η i-οστή ντάµα τοποθετείται (κάπου) στην i-οστή γραµµή. Η λύση ακολουθεί τη φιλοσοφία της προσέγγισης 2, αλλά αποφεύγει µε ιδιαίτερα αποδοτικό τρόπο πάρα πολλούς µη αποδεκτούς συνδυασµούς. Σηµείωση: η συνάρτηση δεν χρειάζεται να δέχεται πλέον ως παράµετρο τους αριθµούς γραµµής από τις ντάµες που έχουν τοποθετηθεί, αφού row[i]==i. Προγραµµατισµός Ι lalis@inf.uth.gr 43

αριθµός στήλης για τις ντάµες 0<=i<n που έχουν τοποθετηθεί µέχρι στιγµής οαριθµός γραµµής για τις ντάµες 0<=i<n που έχουν τοποθετηθεί µέχρι στιγµής είναι row[i]==i void putnxtqueen(int cols[], int n, int M) { αριθµός επόµενης ντάµας προς τοποθέτηση τελικός αριθµός από ντάµες προς τοποθέτηση /* κλήση */ #define Μ 8 int cols[μ]; putnxtqueen(cols,0,μ); Προγραµµατισµός Ι lalis@inf.uth.gr 44

Προσέγγιση 3 void putnxtqueen(int cols[], int n, int M) { int i,k,ok; if (n<m) { for (i=0; i<m; i++) { ok = 1; for (k=0; (k<n) && (ok); k++) { ok=check(i,n,cols[k],k); if (ok) { col[n]=i; putnxtqueen(col,n+1,m); έλεγχος σύγκρουσης για τη νέα τοποθέτηση i,n εκτύπωση αποδεκτού συνδυασµού else { for (i=0; i<m; i++) {printf("(%d,%d)\n",cols[i],i); Προγραµµατισµός Ι lalis@inf.uth.gr 45

Σχόλιο Οι παραπάνω προσεγγίσεις βρίσκουν όλους τους επιτρεπτούς συνδυασµούς (συµπεριλαµβανοµένων και ισοδύναµων «συµµετρικών» λύσεων). Όταν απορρίπτεται ένας συνδυασµός (φύλλο ή/και υποδέντρο) είναι εγγυηµένα µη αποδεκτός. Προγραµµατισµός Ι lalis@inf.uth.gr 46

Μονοπάτι σε γράφο Ένας γράφος κωδικοποιείται µέσω ενός 2-διάστατου πίνακα c, όπου c[i][j]==1 αν υπάρχει ακµή από τον κόµβο i στον j, διαφορετικά c[i][j]==0. Επιθυµούµε ναβρούµε έναµονοπάτι από τον κόµβο n1 προς ένα άλλο κόµβο n2: path(n1,n2): Περίπτωση εύκολου τερµατισµού: c[n1][n2]==1 Γενική περίπτωση: αν n:[n1][n]==1 και path(n,n2) τότε το ζητούµενο µονοπάτι είναι n+path(n,n2), διαφορετικά, δεν υπάρχει κανένα µονοπάτι που να οδηγεί από n1 προς n2. Προγραµµατισµός Ι lalis@inf.uth.gr 47

0 2 1 3 c[0][0]=0; c[0][1]=0; c[0][2]=1; c[0][3]=0; c[1][0]=1; c[1][1]=0; c[1][2]=0; c[1][3]=0; c[2][0]=0; c[2][1]=1; c[2][2]=0; c[2][3]=0; c[3][0]=0; c[3][0]=0; c[3][2]=1; c[3][3]=0; Προγραµµατισµός Ι lalis@inf.uth.gr 48

int path(int n1, int n2) { int n; if (c[n1][n2]) { return(1); else { for (n=0; n<n; n++) { if ((c[n1][n]) && path(n,n2)) { return(1); return(0); Προγραµµατισµός Ι lalis@inf.uth.gr 49

Σχόλια για την προηγούµενη λύση Η αναζήτηση του µονοπατιού γίνεται «σε βάθος» (depth first) υπάρχει και αναζήτηση «σε πλάτος». Επιστρέφεται το πρώτο µονοπάτι που θα βρεθεί, χωρίς να εξερευνούνται οι υπόλοιπες πιθανές λύσεις. εν επιστρέφεται εγγυηµένα η πιο σύντοµη διαδροµή (µόνο κατά τύχη, αν αυτή τυχαίνει να είναι η πρώτη διαδροµή που βρέθηκε µέσω της αναδροµής). εν λαµβάνονται υπ όψη πιθανοί κύκλοι στον γράφο, οπότε υπάρχει πιθανότητα ατέρµονης αναδροµής. Ηυλοποίησηµπορεί να επεκταθεί «σχετικά» εύκολα έτσι ώστε να αντιµετωπιστούν όλες οι παραπάνω αδυναµίες / ατέλειες. Προγραµµατισµός Ι lalis@inf.uth.gr 50

Κατασκευή «δέντρου» συνδυασµών Προσέγγιση «σε βάθος» (depth first): αρχίζουµε από τη ρίζα και κατασκευάζουµε / διερευνούµε τους κόµβους ανά υποδέντρο (από πάνω προς τα κάτω). Προσέγγιγη «κατά πλάτος» (breadth first): αρχίζουµε από τη ρίζα και κατασκευάζουµε / διερευνούµε τους κόµβους ανά επίπεδο (από αριστερά προς τα δεξιά). Η προσέγγιση σε βάθος µπορεί εύκολα να υλοποιηθεί αναδροµικά σε αυτή την περίπτωση ονοµάζεται και «αναδροµική κάθοδος» (recursive descent). Η προσέγγιση κατά πλάτος απαιτεί επιπλέον διαχείριση κατάστασης από το πρόγραµµα γιατην αποθήκευση των κόµβων έτσι ώστε να γίνεται έλεγχος µε τη σωστή σειρά(ουρά FIFO). Προγραµµατισµός Ι lalis@inf.uth.gr 51

1 4 7 2 3 5 6 8 9 Προγραµµατισµός Ι lalis@inf.uth.gr 52

1 2 3 4 5 6 7 8 9 Προγραµµατισµός Ι lalis@inf.uth.gr 53

1 6 11 βέλτιστος συνδυασµός 2 3 7 10 12 13 4 5 8 9 συνδυασµοί που δεν ελέγχονται 14 15 Προγραµµατισµός Ι lalis@inf.uth.gr 54

1 2 3 βέλτιστος συνδυασµός 4 5 6 7 8 9 συνδυασµοί που δεν ελέγχονται 10 11 12 13 14 15 Προγραµµατισµός Ι lalis@inf.uth.gr 55

Μη βέλτιστες (ευρεστικές) λύσεις Μερικά προβλήµατα είναι δύσκολο να λυθούν διεξοδικά, µε έλεγχο όλων των επιτρεπτών συνδυασµών (µε b&b). Ακόµα καιγια«σχετικά µικρά» Ν, π.χ. 10000, ένας σύγχρονος Η/Υ µπορεί να χρειαστεί µέρες ή και βδοµάδες να ολοκληρώσει τον υπολογισµό (αν στο µεταξύ δεν του έχει ήδη σωθεί η διαθέσιµη µνήµη). Ευρεστικές µέθοδοι: εκτός από τα υποδέντρα που σίγουρα δεν οδηγούν σε λύση, αποκλείουµε καιτα υποδέντρα που πιστεύουµε, σύµφωνα µε µια «κοινή» λογική, ότι δεν θα οδηγήσουν σε κάποια (καλή) λύση. Οι ευρεστικές µέθοδοι µειώνουν σηµαντικά τον αριθµό των συνδυασµών προς έλεγχο, αλλά στην γενική περίπτωση δεν οδηγούν εγγυηµένα σε βέλτιστη λύση. Προγραµµατισµός Ι lalis@inf.uth.gr 56

αποκλεισµός υποδέντρων που σίγουρα δεν οδηγούν σε λύση αποκλεισµός υποδέντρων που µάλλον δεν οδηγούν σε λύση βέλτιστος συνδυασµός Προγραµµατισµός Ι lalis@inf.uth.gr 57

Παράδειγµα Knapsack / Rucksack ίνεται: αντικείµενα Ο[i] µε βάροςw[i] και αξία V[i]. Ζητούµενο: να επιλεγούν τα αντικείµενα τα οποία µεγιστοποιούν την αξία ενός φορτίου µε µέγιστο συνολικό βάρος ένα γνωστό άνω όριο maxweight. Προσέγγιση 1 (brute force): κατασκευή όλων των συνδυασµών, και επιλογή του συνδυασµού µε την µεγαλύτερη αξία στα πλαίσια του επιτρεπτού βάρους. Προσέγγιση 2 (branch & bound): όπως 1, αλλά σε κάθε βήµα ελέγχεται το βάρος του συνδυασµού και αυτός απορρίπτεται (πρόωρα) αν υπερβαίνει το όριο. Προσέγγιση 3 (heuristic b&b): όπως 2, αλλά σε κάθε βήµα επιλέγεται (αµετάκλητα) το αντικείµενο µετο µεγαλύτερο ειδικό βάρος που χωρά στο φορτίο. Προγραµµατισµός Ι lalis@inf.uth.gr 58

Σχόλιο Η προσέγγιση σε βάθος είναι κατάλληλη όταν όλες οι λύσεις (φύλλα του δέντρου) βρίσκονται στο ίδιο επίπεδο, π.χ. 8 ντάµες. Η προσέγγιση κατά πλάτος είναι κατάλληλη όταν κάποιες λύσεις (φύλλα του δέντρου) βρίσκονται πιθανώς σε διαφορετικό επίπεδο και γνωρίζουµε ότι ο επιθυµητός συνδυασµός βρίσκεται στο πιο ψηλό επίπεδο, π.χ. πιο σύντοµο µονοπάτι εξόδου σε ένα λαβύρινθο. Σε αυτή τη περίπτωση ο αριθµός των συνδυασµών που ελέγχονται µπορεί να είναι κατά πολύ µικρότερος (το δέντρο των συνδυασµών κόβεται οριζόντια, κάτω από το επίπεδο της λύσης). Προγραµµατισµός Ι lalis@inf.uth.gr 59