Version 1.5.1 (24/03/2017) Σχολή Τεχνολογικών Εφαρμογών (ΣΤΕΦ) Τμήμα Μηχανικών Πληροφορικής Τ.Ε. Διδάσκων: Γκόγκος Χρήστος Μάθημα: Τεχνητή Νοημοσύνη (εργαστήριο Δ εξαμήνου) Ακαδημαϊκό έτος 2016-2017 εαρινό εξάμηνο ΑΣΚΗΣΕΙΣ ΓΙΑ ΤΟ ΕΡΓΑΣΤΗΡΙΟ 1 Άσκηση 1 Σχεδιάστε ένα μη κατευθυνόμενο γράφημα με 5 κόμβους και 7 ακμές στο χαρτί. Δημιουργήστε ένα αρχείο κειμένου που να περιέχει τη πληροφορία του γραφήματος που σχεδιάσατε όπως περιγράφεται στο εργαστήριο. Χρησιμοποιώντας τον κώδικα lab01_01.cpp του εργαστηρίου εμφανίστε τα περιεχόμενα του γραφήματος. Άσκηση 2 Γράψτε πρόγραμμα που να δέχεται ως όρισμα γραμμής εντολών ένα όνομα αρχείου γραφήματος και να υπολογίζει τις ακόλουθες πληροφορίες: 1. Μέσος όρος βάρους ακμών για όλο το γράφημα 2. Το βαθμό κάθε κορυφής και το μέσο όρο βαθμού κορυφών για όλο το γράφημα 3. Ονόματα κορυφών με το μεγαλύτερο βαθμό 4. Όνομα κορυφής που βρίσκεται στη μεγαλύτερη απόσταση από όλες τις γειτονικές της Άσκηση 3 Τροποποιώντας τις υλοποιήσεις των BFS, DFS και UCS του εργαστηρίου έτσι ώστε να επιστρέφουν το μήκος της διαδρομής να υπολογιστούν τα ακόλουθα για κάθε πιθανό συνδυασμό δύο πόλεων στο πρόβλημα tour_romania: 1. Πόσες φορές ο αλγόριθμος BFS δίνει συντομότερη διαδρομή από τον DFS; 2. Πόσες φορές ο αλγόριθμος DFS δίνει συντομότερη διαδρομή από τον BFS; 3. Πόσες φορές οι αλγόριθμοι DFS και BFS εντοπίζουν διαδρομή με το ίδιο μήκος; 4. Πόσες φορές o καθένας από τους αλγορίθμους DFS και BFS δίνει τη βέλτιστη σε σχέση με το μήκος της διαδρομής λύση; Ας σημειωθεί ότι καθώς οι πόλεις είναι 20 οι συνδυασμοί των πόλεων ανά 2 είναι choose(20,2)=190. Αριθμός ζευγών πόλεων που ο DFS εντοπίζει συντομότερη διαδρομή από τον BFS Αριθμός ζευγών πόλεων που ο BFS εντοπίζει συντομότερη διαδρομή από τον DFS Αριθμός ζευγών πόλεων που ο DFS και ο BFS εντοπίζει διαδρομή με το ίδιο μήκος Αριθμός ζευγών πόλεων που ο BFS εντοπίζει τη βέλτιστη διαδρομή όπως υπολογίζεται από τον UCS Αριθμός ζευγών πόλεων που ο DFS εντοπίζει τη βέλτιστη διαδρομή όπως υπολογίζεται από τον UCS Άσκηση 4 Τροποποιήστε τους αλγορίθμους depth_first_search_base και breadth_first_search_base του εργαστηρίου έτσι ώστε να επιστρέφουν το πλήθος των περιπτώσεων που ο αλγόριθμος οδηγήθηκε σε βρόχο. Γράψτε πρόγραμμα που να καλεί τους αλγορίθμους για το πρόβλημα tour_romania και να εμφανίζει το πλήθος των περιπτώσεων που «πέφτουν» σε βρόχους για τη μετάβαση από όλους τους άλλους κόμβους προς τον κόμβο B. 1
Άσκηση 5 Για το γράφημα toy1.txt με τα ακόλουθα δεδομένα να εφαρμοστούν οι αλγόριθμοι DFS, BFS και UCS για την μετάβαση από την κορυφή Α στην κορυφή G και να συμπληρωθούν οι ακόλουθοι πίνακες [VERTICES:7] A B C D E F G [EDGES:8] A,B,25 A,D,15 B,C,15 B,E,20 D,C,35 D,F,20 E,F,15 F,G,14 toy1.txt Για τον αλγόριθμο ΒFS (Αφετηρία: Α, Στόχος: G) Μέτωπο αναζήτησης Κλειστό σύνολο Τρέχουσα Κατάσταση Παιδιά Διαδρομή και κόστος: Για τον αλγόριθμο DFS (Αφετηρία: Α, Στόχος: G) Μέτωπο αναζήτησης Κλειστό σύνολο Τρέχουσα Κατάσταση Παιδιά Διαδρομή και κόστος: 2
Για τον αλγόριθμο UCS (Αφετηρία: Α, Στόχος: G) Μέτωπο αναζήτησης Κλειστό σύνολο Τρέχουσα Κατάσταση Παιδιά Διαδρομή και κόστος: Άσκηση 6 Μια εναλλακτική υλοποίηση του αλγορίθμου αναζήτησης κατά πλάτος είναι η ακόλουθη: /** * εναλλακτική υλοποίηση του bfs * */ void breadth_first_search_alt(struct di_graph graph, string start_vertex, string goal_vertex) cout << "BREADTH FIRST SEARCH" << endl; set<string> closed ; queue<search_node> frontier ; // FIFO frontier.push(to_search_node(start_vertex)); bool found false ; while (true) if (frontier.empty()) search_node current_state = frontier.front(); string current_state_back = current_state.path.back(); print_status(closed, queue_to_list(frontier), current_state_back, get_successors(graph, current_state_back)); frontier.pop(); if (goal_vertex.compare(current_state_back) == 0) cout << "Path to goal node found: " << search_node_as_string(current_state) << endl; found = true; bool is_in closed.find(current_state_back)!= closed.end() ; if (!is_in) closed.insert(current_state_back); for (string v : get_successors(graph, current_state_back)) frontier.push(to_search_node(graph, current_state, v)); if (!found) cout << "Goal not found!" << endl; Κατασκευάστε ανάλογες υλοποιήσεις για τον αλγόριθμο αναζήτησης κατά βάθος (DFS) και για τον αλγόριθμο ομοιόμορφης αναζήτησης (UCS). Ελέγξτε την ορθότητα των υλοποιήσεων συγκρίνοντας τα αποτελέσματα από τις δικές σας υλοποιήσεις με τα αποτελέσματα των ήδη διατυπωμένων αλγορίθμων. Θα πρέπει να σημειωθεί ότι κατά την εισαγωγή νέων καταστάσεων στο μέτωπο αναζήτησης χρησιμοποιείται η σύμβαση ότι ανάμεσα στις καταστάσεις που προστίθενται προτεραιότητα θα πρέπει να αποκτούν εκείνες που προηγούνται στην αλφαβητική σειρά (δηλαδή ο κόμβος Α εφόσον εισήλθε μαζί με τον κόμβο Β στο μέτωπο αναζήτησης θα πρέπει να εξέλθει πριν τον κόμβο Β). Άρα στην περίπτωση του DFS η συνάρτηση get_successors θα πρέπει να κληθεί ως εξής: get_successors(graph, current_state_back, false). Ορίζοντας την τελευταία παράμετρο της συνάρτησης ως false οι κόμβοι επιστρέφονται σε φθίνουσα σειρά και ωθούνται στη στοίβα. Κατά την απώθηση τους στη συνέχεια εξέρχονται σε αύξουσα αλφαβητική σειρά. 3
Άσκηση 7 Για το ακόλουθο γράφημα να υπολογιστούν οι διαδρομές που υπολογίζουν οι αλγόριθμοι BFS, DFS και UCS για τη μετάβαση από την κορυφή Α στην κορυφή Ι χωρίς να κατασκευαστούν οι πίνακες μετώπου αναζήτησης, κλειστού συνόλου κλπ. Άσκηση 8 (προαιρετική) Υλοποιήστε αναδρομικούς αλγορίθμους για τον αλγόριθμο αναζήτησης πρώτα κατά πλάτος και τον αλγόριθμο αναζήτησης πρώτα κατά βάθος. Ελέγξτε την ορθότητα των αλγορίθμων συγκρίνοντας τα αποτελέσματα που επιστρέφουν με τα αποτελέσματα που επιστρέφουν οι μη αναδρομικοί αλγόριθμοι του εργαστηρίου. 4
ΛΥΣΕΙΣ ΑΣΚΗΣΕΩΝ ΓΙΑ ΤΟ ΕΡΓΑΣΤΗΡΙΟ 1 Άσκηση 1 [VERTICES:5] A B C D E [EDGES:7] A,B,5 A,C,10 A,D,15 B,D,3 B,E,20 C,D,7 D,E,6 Γράφημα askisi1.txt./lab01_01 askisi1.txt Vertices=5 Vertex A(A) Vertex B(B) Vertex C(C) Vertex D(D) Vertex E(E) Edges=7 A(A)--5-->B(B) A(A)--10-->C(C) A(A)--15-->D(D) B(B)--3-->D(D) B(B)--20-->E(E) C(C)--7-->D(D) D(D)--6-->E(E) Άσκηση 2 #include "lab01_graph.hpp" using namespace std; int main(int argc, char **argv) if (argc!= 2) cout << "Wrong number of arguments" << endl; exit(-1); string fn = argv[1]; struct di_graph graph = read_data(fn); 5
// Q1. μέσος όρος βάρους ακμών για όλο το γράφημα double sum = 0.0; int c = 0; for (int v1 = 0; v1 < graph.v; v1++) for (int v2 = 0; v2 < graph.v; v2++) if (v1!= v2) int weight = graph.adjacency_matrix[v1][v2]; if (weight!= 0) c++; sum += weight; cout << "Q1. Average weight of all edges " << sum / c << endl; // Q2. Βαθμοί κορυφών και μέσος όρος βαθμού κορυφών για όλο το γράφημα int max = 0; sum = 0.0; for (int i = 0; i < graph.v; i++) string vertex = get_vertex_label(graph, i); list<string> edges = get_successors(graph, vertex); int degree = edges.size(); cout << "Q2. Degree of vertex " << vertex << " is " << degree << endl; sum += degree; if (degree > max) max = degree; cout << "Q2. Average degree of all vertices " << sum / graph.v << endl; // Q3. Ονόματα κορυφών με το μεγαλύτερο βαθμό for (int i = 0; i < graph.v; i++) string vertex = get_vertex_label(graph, i); list<string> edges = get_successors(graph, vertex); int degree = edges.size(); if (degree == max) cout << "Q3. Vertex " << vertex << " has maximum degree " << max << endl; ης // Q4. Όνομα κορυφής που βρίσκεται στη μεγαλύτερη απόσταση από όλες τις γειτονικές τ max = 0; int pmax = -1; for (int i = 0; i < graph.v; i++) string vertex1 = get_vertex_label(graph, i); int min = INT_MAX; for (string vertex2 : get_successors(graph, vertex1)) 6
int distance = get_weight(graph, vertex1, vertex2); if (distance < min) min = distance; if (min > max) max = min; pmax = i; cout << "Q4. Vertex " << get_vertex_label(graph, pmax) << " is furthest away from al l other vertices having distance to closest vertex=" << max << endl; free_memory(graph); return 0; lab01_exercise02.cpp g++ lab01_graph.cpp lab01_exercise02.cpp -o lab01_exercise02 -Wall -std=c++11./lab01_exercise02 data/tour_romania.txt Q1. Average weight of all edges 107.957 Q2. Degree of vertex A is 3 Q2. Degree of vertex B is 4 Q2. Degree of vertex C is 3 Q2. Degree of vertex D is 2 Q2. Degree of vertex E is 1 Q2. Degree of vertex F is 2 Q2. Degree of vertex G is 1 Q2. Degree of vertex H is 2 Q2. Degree of vertex I is 2 Q2. Degree of vertex L is 2 Q2. Degree of vertex M is 2 Q2. Degree of vertex N is 1 Q2. Degree of vertex O is 2 Q2. Degree of vertex P is 3 Q2. Degree of vertex R is 3 Q2. Degree of vertex S is 4 Q2. Degree of vertex T is 2 Q2. Degree of vertex U is 3 Q2. Degree of vertex V is 2 Q2. Degree of vertex Z is 2 Q2. Average degree of all vertices 2.3 Q3. Vertex B has maximum degree 4 Q3. Vertex S has maximum degree 4 Q4. Vertex C is furthest away from all other vertices having distance to closest vertex=120 Άσκηση 3 #include "lab01_graph.hpp" #include <set> #include <stack> #include <queue> 7
using namespace std; struct search_node list<string> path; int cost = 0; bool is_goal = false; bool operator<(search_node other) const return cost > other.cost; ; // αναζήτηση πρώτα κατά βάθος int depth_first_search(struct di_graph graph, string start_vertex, string goal_vertex); // αναζήτηση πρώτα κατά πλάτος int breadth_first_search(struct di_graph graph, string start_vertex, string goal_vertex); // αναζήτηση ομοιόμορφου κόστους int uniform_cost_search(struct di_graph graph, string start_vertex, string goal_vertex); // convenience function για μεταφορά περιεχομένων στοίβας σε λίστα list<search_node> stack_to_list(stack<search_node> frontier); // convenience function για μεταφορά περιεχομένων ουράς σε λίστα list<search_node> queue_to_list(queue<search_node> frontier); // convenience function για μεταφορά περιεχομένων ουράς προτεραιότητας σε λίστα list<search_node> priority_queue_to_list(priority_queue<search_node> frontier); // convenience function για pretty print ενός search_node string search_node_as_string(search_node sn, bool show_path_cost = true); // επιστρέφει τη λύση μαζί με το κόστος της χρησιμοποιώντας τα πλήρη ονόματα // των κόμβων του γράφου string solution_path_cost(di_graph graph, search_node sn); // convenience function για pretty print λίστας με λεκτικά string list_as_string(list<string> alist); // convenience function για pretty print συνόλου με λεκτικά string set_as_string(set<string> aset); /** * χρησιμοποιείται για να εμφανίζει κατά τη διάρκεια της αναζήτησης * το μέτωπο αναζήτησης, το κλειστό σύνολο, τον τρέχοντα κόμβο και τους * γειτονικούς κόμβους του τρέχοντα κόμβου */ void print_status(set<string> closed, list<search_node> frontier, string current_state, list<string> successors, bool show_path_cost = false); // χρησιμοποιείται μόνο για τον κόμβο αφετηρία (start_node) έτσι ώστε να 8
// αρχικοποιήσει τη διαδρομή search_node to_search_node(string node); // προσθήκη ενός επιπλέον κόμβου στη διαδρομή που έχει ήδη δημιουργηθεί, // ενημέρωση κόστους search_node to_search_node(di_graph graph, search_node parent_sn, string node); lab01_search_exercise03.hpp #include "lab01_search_exercise03.hpp" using namespace std; int depth_first_search(struct di_graph graph, string start_vertex, string goal_vertex) cout << "DEPTH FIRST SEARCH" << endl; set<string> closed; stack<search_node> frontier; // LIFO frontier.push(to_search_node(start_vertex)); search_node current_state = frontier.top(); string current_state_back = current_state.path.back(); bool foundtrue; while (goal_vertex.compare(current_state_back)!= 0) // print_status(closed, stack_to_list(frontier), current_state_back, // get_successors(graph, current_state_back)); frontier.pop(); bool is_inclosed.find(current_state_back)!= closed.end(); if (!is_in) // Οι γειτονικοί κόμβοι λαμβάνονται σε φθίνουσα αλφαβητική σειρά έτσι ώστε // όταν // τοποθετηθούν στη στοίβα η τιμή που βρίσκεται στη κορυφή να είναι η // μικρότερη // αλφαβητικά από αυτές που εισήχθησαν τελευταίες for (string v : get_successors(graph, current_state_back, false)) frontier.push(to_search_node(graph, current_state, v)); closed.insert(current_state_back); if (frontier.empty()) found = false; current_state = frontier.top(); current_state_back = current_state.path.back(); if (found) // print_status(closed, stack_to_list(frontier), current_state_back, // get_successors(graph, current_state_back)); cout << "Path to goal node found: " 9
<< solution_path_cost(graph, current_state) << endl; return current_state.cost; else cout << "Goal not found!" << endl; return -1; int breadth_first_search(struct di_graph graph, string start_vertex, string goal_vertex) cout << "BREADTH FIRST SEARCH" << endl; set<string> closed; queue<search_node> frontier; // FIFO frontier.push(to_search_node(start_vertex)); search_node current_state = frontier.front(); string current_state_back = current_state.path.back(); bool foundtrue; while (goal_vertex.compare(current_state_back)!= 0) // print_status(closed, queue_to_list(frontier), current_state_back, // get_successors(graph, current_state_back)); frontier.pop(); bool is_inclosed.find(current_state_back)!= closed.end(); if (!is_in) for (string v : get_successors(graph, current_state_back)) frontier.push(to_search_node(graph, current_state, v)); closed.insert(current_state_back); if (frontier.empty()) found = false; current_state = frontier.front(); current_state_back = current_state.path.back(); if (found) // print_status(closed, queue_to_list(frontier), current_state_back, // get_successors(graph, current_state_back)); cout << "Path to goal node found: " << solution_path_cost(graph, current_state) << endl; return current_state.cost; else cout << "Goal not found!" << endl; return -1; 10
int uniform_cost_search(struct di_graph graph, string start_vertex, string goal_vertex) cout << "UNIFORM COST SEARCH" << endl; set<string> closed; priority_queue<search_node> frontier; // MIN HEAP frontier.push(to_search_node(start_vertex)); search_node current_state = frontier.top(); string current_state_back = current_state.path.back(); bool foundtrue; while (goal_vertex.compare(current_state_back)!= 0) // print_status(closed, priority_queue_to_list(frontier), current_state_back, // get_successors(graph, current_state_back), true); frontier.pop(); bool is_inclosed.find(current_state_back)!= closed.end(); if (!is_in) for (string v : get_successors(graph, current_state_back)) frontier.push(to_search_node(graph, current_state, v)); closed.insert(current_state_back); if (frontier.empty()) found = false; current_state = frontier.top(); current_state_back = current_state.path.back(); if (found) // print_status(closed, priority_queue_to_list(frontier), current_state_back, // get_successors(graph, current_state_back), true); cout << "Path to goal node found: " << solution_path_cost(graph, current_state) << endl; return current_state.cost; else cout << "Goal not found!" << endl; return -1; list<search_node> stack_to_list(stack<search_node> frontier) list<search_node> alist; while (!frontier.empty()) alist.push_back(frontier.top()); 11
frontier.pop(); return alist; list<search_node> queue_to_list(queue<search_node> frontier) list<search_node> alist; while (!frontier.empty()) alist.push_back(frontier.front()); frontier.pop(); return alist; list<search_node> priority_queue_to_list(priority_queue<search_node> frontier) list<search_node> alist; while (!frontier.empty()) alist.push_back(frontier.top()); frontier.pop(); return alist; string search_node_as_string(search_node sn, bool show_path_cost) string s; s.append("("); for (string v : sn.path) s.append(v); s.append("-"); if (s.length() > 1) s.pop_back(); if (show_path_cost) s.append(" "); s.append(to_string(sn.cost)); s.append(")"); return s; string solution_path_cost(di_graph graph, search_node sn) string s; s.append("("); for (string v : sn.path) 12
s.append(graph.vertices_full_names[get_vertex_index(graph, v)]); s.append("-"); if (s.length() > 1) s.pop_back(); s.append(" "); s.append(to_string(sn.cost)); s.append(")"); return s; string list_as_string(list<string> alist) string s; s.append("["); for (string v : alist) s.append(v); s.append(" "); if (s.length() > 1) s.pop_back(); s.append("]"); return s; string set_as_string(set<string> aset) string s; s.append("["); for (string v : aset) s.append(v); s.append(" "); if (s.length() > 1) s.pop_back(); s.append("]"); return s; void print_status(set<string> closed, list<search_node> frontier, string current_state, list<string> successors, bool show_path_cost) cout << "frontier:["; for (search_node sn : frontier) cout << search_node_as_string(sn, show_path_cost); cout << "]"; cout << " closed set:" << set_as_string(closed); cout << " current node:" << current_state; bool is_inclosed.find(current_state)!= closed.end(); if (is_in) 13
cout << " successors:[loop]" << endl; else cout << " successors:" << list_as_string(successors) << endl; search_node to_search_node(string node) search_node sn; sn.path.push_back(node); sn.cost = 0; return sn; search_node to_search_node(di_graph graph, search_node parent_sn, string node) search_node sn; for (string v : parent_sn.path) sn.path.push_back(v); sn.path.push_back(node); sn.cost = parent_sn.cost + get_weight(graph, parent_sn.path.back(), node); return sn; lab01_search_exercise03.cpp #include "lab01_search_exercise03.hpp" using namespace std; int main(int argc, char **argv) if (argc!= 2) cout << "Wrong number of arguments" << endl; exit(-1); string fn = argv[1]; struct di_graph graph = read_data(fn); int c1, c2, c3, c4, c5; c1 = c2 = c3 = c4 = c5 = 0; for (int v1 = 0; v1 < graph.v; v1++) for (int v2 = v1 + 1; v2 < graph.v; v2++) int dfs_cost, bfs_cost, ucs_cost; string vertex1 = get_vertex_label(graph, v1); string vertex2 = get_vertex_label(graph, v2); bfs_cost = breadth_first_search(graph, vertex1, vertex2); dfs_cost = depth_first_search(graph, vertex1, vertex2); 14
ucs_cost = uniform_cost_search(graph, vertex1, vertex2); if (bfs_cost < dfs_cost) c1++; else if (bfs_cost > dfs_cost) c2++; else c3++; if (bfs_cost == ucs_cost) c4++; if (dfs_cost == ucs_cost) c5++; cout << "Q1. " << c1 << endl; cout << "Q2. " << c2 << endl; cout << "Q3. " << c3 << endl; cout << "Q4. " << c4 << endl; cout << "Q5. " << c5 << endl; lab01_exercise03.cpp g++ lab01_graph.cpp lab01_search_exercise03.cpp lab01_exercise03.cpp - o lab01_exercise03 -Wall -std=c++11./lab01_exercise03 data/tour_romania.txt Q1. 86 Q2. 0 Q3. 104 Q4. 135 Q5. 64 Άσκηση 4 #include "lab01_graph.hpp" // Ο αλγόριθμος αναζήτησης κατά πλάτος χωρίς αποθήκευση της διαδρομής int breadth_first_search_base(struct di_graph graph, string start_vertex, string goal_vertex); // Ο αλγόριθμος αναζήτησης κατά βάθος χωρίς αποθήκευση της διαδρομής int depth_first_search_base(struct di_graph graph, string start_vertex, string goal_vertex); lab01_search_simple_exercise04.hpp #include "lab01_search_simple_exercise04.hpp" #include <set> #include <queue> #include <stack> #include <unordered_map> using namespace std; 15
int breadth_first_search_base(struct di_graph graph, string start_vertex, string goal_vertex) cout << "BREADTH FIRST SEARCH" << endl; unordered_map<string, int> hm; set<string> closed; queue<string> frontier; // FIFO frontier.push(start_vertex); string current_state = frontier.front(); hm[current_state] = 0; bool foundtrue; cout << "Starting from node " << start_vertex << endl; int c = 0; while (goal_vertex.compare(current_state)!= 0) frontier.pop(); bool is_inclosed.find(current_state)!= closed.end(); if (!is_in) for (string v : get_successors(graph, current_state)) frontier.push(v); hm[v] = hm[current_state] + get_weight(graph, current_state, v); closed.insert(current_state); else c++; if (frontier.empty()) found = false; current_state = frontier.front(); cout << "current state: " << current_state << endl; if (found) cout << "Path from " << start_vertex << " to " << goal_vertex << " found having length " << hm[goal_vertex] << endl; else cout << "Path from " << start_vertex << " to " << goal_vertex << " was not found!" << endl; return c; int depth_first_search_base(struct di_graph graph, string start_vertex, string goal_vertex) cout << "DEPTH FIRST SEARCH" << endl; unordered_map<string, int> hm; set<string> closed; stack<string> frontier; // LIFO frontier.push(start_vertex); 16
string current_state = frontier.top(); hm[current_state] = 0; bool foundtrue; cout << "Starting from node " << start_vertex << endl; int c = 0; while (goal_vertex.compare(current_state)!= 0) frontier.pop(); bool is_inclosed.find(current_state)!= closed.end(); if (!is_in) for (string v : get_successors(graph, current_state, false)) frontier.push(v); hm[v] = hm[current_state] + get_weight(graph, current_state, v); closed.insert(current_state); else c++; if (frontier.empty()) found = false; current_state = frontier.top(); cout << "current state: " << current_state << endl; if (found) cout << "Path from " << start_vertex << " to " << goal_vertex << " found having length " << hm[goal_vertex] << endl; else cout << "Path from " << start_vertex << " to " << goal_vertex << " was not found!" << endl; return c; lab01_search_simple_exercise04.cpp #include "lab01_search_simple_exercise04.hpp" int main() string fn"data/tour_romania.txt"; struct di_graph graph = read_data(fn); int loops_bfs = 0; int loops_dfs = 0; string destination = "B"; for (int v = 0; v < graph.v; v++) string vertex = get_vertex_label(graph, v); if (vertex!= destination) 17
loops_bfs += breadth_first_search_base(graph, vertex, destination); loops_dfs += depth_first_search_base(graph, vertex, destination); cout << "Loops for BFS " << loops_bfs << endl; cout << "Loops for DFS " << loops_dfs << endl; free_memory(graph); return 0; lab01_exercise04.cpp g++ lab01_graph.cpp lab01_search_simple_exercise04.cpp lab01_exercise04.cpp - o lab01_exercise04 -Wall -std=c++11./lab01_exercise04 Loops for BFS 47 Loops for DFS 28 Άσκηση 5 [VERTICES:7] A B C D E F G [EDGES:8] A,B,25 A,D,15 B,C,15 B,E,20 D,C,35 D,F,20 E,F,15 F,G,14 toy1.txt Για τον αλγόριθμο ΒFS (Αφετηρία: Α, Στόχος: G) Μέτωπο αναζήτησης Κλειστό σύνολο Τρέχουσα Κατάσταση Παιδιά [(A)] A B,D [(A-B),(A-D)] [A] B C,E [(A-D),(A-B-C),(A-B-E)] [A,B] D C,F [(A-B-C),(A-B-E), (A-D-C),(A-D-F)] [A,B,D] C [(A-B-E), (A-D-C),(A-D-F)] [A,B,C,D] E F [(A-D-C),(A-D-F),(A-B-E-F)] [A,B,C,D,E] C βρόχος [(A-D-F),(A-B-E-F)] [A,B,C,D,E] F G [(A-B-E-F),(A-D-F-G)] [A,B,C,D,E,F] F βρόχος [(A-D-F-G)] [A,B,C,D,E,F] G Διαδρομή και κόστος: A-D-F-G, 49 18
Για τον αλγόριθμο DFS (Αφετηρία: Α, Στόχος: G) Μέτωπο αναζήτησης Κλειστό σύνολο Τρέχουσα Κατάσταση Παιδιά [(A)] A B,D [(A-B),(A-D)] [A] B C,E [(A-B-C),(A-B-E),(A-D)] [A,B] C [(A-B-E),(A-D)] [A,B,C] E F [(A-B-E-F),(A-D)] [A,B,C,E] F G [(A-B-E-F-G),(A-D)] [A,B,C,E,F] G Διαδρομή και κόστος: A-B-E-F-G, 74 Για τον αλγόριθμο UCS (Αφετηρία: Α, Στόχος: G) Μέτωπο αναζήτησης Κλειστό σύνολο Τρέχουσα Κατάσταση Παιδιά [(A,0)] A B,D [(A-D,15),(A-B,25)] [A] D C,F [(A-B,25),(A-D-F,35),(A-D-C,50)] [A,D] B C,E [(A-D-F,35),(A-B-C,40),(A-B-E,45),(A-D-C,50)] [A,B,D] F G [(A-B-C,40),(A-B-E,45),(A-D-F-G,49),(A-D-C,50)] [A,B,D,F] C [(A-B-E,45),(A-D-F-G,49),(A-D-C,50)] [A,B,C,D,F] E F [(A-D-F-G 49),(A-D-C 50),(A-B-E-F 60)] [A,B,C,D,E,F] G Διαδρομή και κόστος: A-D-F-G,49 Άσκηση 6 #include "lab01_search.hpp" using namespace std; void breadth_first_search_alt(struct di_graph graph, string start_vertex, string goal_vertex); void breadth_first_search_recursive(struct di_graph graph, string start_vertex, string goal_vertex); search_node bfs_r(struct di_graph graph, set<string> closed, list<search_node> node_list, string goal_vertex); void depth_first_search_alt(struct di_graph graph, string start_vertex, string goal_vertex); void depth_first_search_recursive(struct di_graph graph, string start_vertex, string goal_vertex); search_node dfs_r(struct di_graph graph, set<string> closed, search_node current_state, string goal_vertex); 19
void uniform_cost_search_alt(struct di_graph graph, string start_vertex, string goal_vertex); lab01_search_ext.hpp #include "lab01_search_ext.hpp" using namespace std; void breadth_first_search_alt(struct di_graph graph, string start_vertex, string goal_vertex) cout << "BREADTH FIRST SEARCH ALTERNATIVE IMPLEMENTATION" << endl; set<string> closed; queue<search_node> frontier; // FIFO frontier.push(to_search_node(start_vertex)); bool foundfalse; while (true) if (frontier.empty()) search_node current_state = frontier.front(); string current_state_back = current_state.path.back(); print_status(closed, queue_to_list(frontier), current_state_back, get_successors(graph, current_state_back)); frontier.pop(); if (goal_vertex.compare(current_state_back) == 0) cout << "Path to goal node found: " << solution_path_cost(graph, current_state) << endl; found = true; bool is_inclosed.find(current_state_back)!= closed.end(); if (!is_in) closed.insert(current_state_back); for (string v : get_successors(graph, current_state_back)) frontier.push(to_search_node(graph, current_state, v)); if (!found) cout << "Goal not found!" << endl; void breadth_first_search_recursive(struct di_graph graph, string start_vertex, string goal_vertex) cout << "BREADTH FIRST SEARCH ALTERNATIVE IMPLEMENTATION (RECURSIVE)" << endl; list<search_node> new_nodesto_search_node(start_vertex); set<string> closed; search_node sn = bfs_r(graph, closed, new_nodes, goal_vertex); if (!sn.is_goal) cout << "Goal not found!" << endl; else cout << "Path to goal node found: " << solution_path_cost(graph, sn) << endl; 20
search_node bfs_r(struct di_graph graph, set<string> closed, list<search_node> node_list, string goal_vertex) list<search_node> new_nodes; for (search_node current_state : node_list) string current_state_back = current_state.path.back(); if (goal_vertex.compare(current_state_back) == 0) current_state.is_goal = true; return current_state; else if (closed.find(current_state_back) == closed.end()) for (string v : get_successors(graph, current_state_back)) new_nodes.push_back(to_search_node(graph, current_state, v)); closed.insert(current_state_back); if (new_nodes.size()!= 0) return bfs_r(graph, closed, new_nodes, goal_vertex); else return to_search_node("goal not found"); void depth_first_search_alt(struct di_graph graph, string start_vertex, string goal_vertex) cout << "DEPTH FIRST SEARCH ALTERNATIVE IMPLEMENTATION" << endl; set<string> closed; stack<search_node> frontier; frontier.push(to_search_node(start_vertex)); bool foundfalse; while (true) if (frontier.empty()) search_node current_state = frontier.top(); string current_state_back = current_state.path.back(); print_status(closed, stack_to_list(frontier), current_state_back, get_successors(graph, current_state_back)); frontier.pop(); if (goal_vertex.compare(current_state_back) == 0) cout << "Path to goal node found: " << solution_path_cost(graph, current_state) << endl; found = true; bool is_inclosed.find(current_state_back)!= closed.end(); if (!is_in) closed.insert(current_state_back); for (string v : get_successors(graph, current_state_back, false)) frontier.push(to_search_node(graph, current_state, v)); if (!found) cout << "Goal not found!" << endl; 21
void depth_first_search_recursive(struct di_graph graph, string start_vertex, string goal_vertex) cout << "DEPTH FIRST SEARCH ALTERNATIVE IMPLEMENTATION (RECURSIVE)" << endl; set<string> closed; search_node sn = dfs_r(graph, closed, to_search_node(start_vertex), goal_vertex); if (!sn.is_goal) cout << "Goal not found!" << endl; else cout << "Path to goal node found: " << solution_path_cost(graph, sn) << endl; search_node dfs_r(struct di_graph graph, set<string> closed, search_node current_state, string goal_vertex) string current_state_back = current_state.path.back(); if (goal_vertex.compare(current_state_back) == 0) current_state.is_goal = true; return current_state; if (closed.find(current_state_back)!= closed.end()) return to_search_node("state in closed set"); list<search_node> new_nodes; for (string v : get_successors(graph, current_state_back)) new_nodes.push_back(to_search_node(graph, current_state, v)); closed.insert(current_state_back); while (!new_nodes.empty()) search_node result = dfs_r(graph, closed, new_nodes.front(), goal_vertex); if (result.is_goal) return result; new_nodes.pop_front(); return to_search_node("goal not found"); void uniform_cost_search_alt(struct di_graph graph, string start_vertex, string goal_vertex) cout << "UNIFORM COST SEARCH ALTERNATIVE IMPLEMENTATION" << endl; set<string> closed; priority_queue<search_node> frontier; frontier.push(to_search_node(start_vertex)); bool foundfalse; while (true) if (frontier.empty()) search_node current_state = frontier.top(); string current_state_back = current_state.path.back(); print_status(closed, priority_queue_to_list(frontier), current_state_back, get_successors(graph, current_state_back), true); frontier.pop(); if (goal_vertex.compare(current_state_back) == 0) cout << "Path to goal node found: " 22
<< solution_path_cost(graph, current_state) << endl; found = true; bool is_inclosed.find(current_state_back)!= closed.end(); if (!is_in) closed.insert(current_state_back); for (string v : get_successors(graph, current_state_back)) frontier.push(to_search_node(graph, current_state, v)); if (!found) cout << "Goal not found!" << endl; lab01_search_ext.cpp g++ lab01_graph.cpp lab01_search.cpp lab01_search_ext.cpp lab01_exercise06.cpp -o lab01_exercise06 -Wall -std=c++11./lab01_exercise06 data/tour_romamia.txt A B bfs BREADTH FIRST SEARCH ALTERNATIVE IMPLEMENTATION frontier:[(a)] closed set:[] current node:a successors:[s T Z] frontier:[(a-s)(a-t)(a-z)] closed set:[a] current node:s successors:[a F O R] frontier:[(a-t)(a-z)(a-s-a)(a-s-f)(a-s-o)(a-s-r)] closed set:[a S] current node:t successors:[a L] frontier:[(a-z)(a-s-a)(a-s-f)(a-s-o)(a-s-r)(a-t-a)(a-t-l)] closed set:[a S T] current node:z successors:[a O] frontier:[(a-s-a)(a-s-f)(a-s-o)(a-s-r)(a-t-a)(a-t-l)(a-z-a)(a-z-o)] closed set:[a S T Z] current node:a successors:[loop] frontier:[(a-s-f)(a-s-o)(a-s-r)(a-t-a)(a-t-l)(a-z-a)(a-z-o)] closed set:[a S T Z] current node:f successors:[b S] frontier:[(a-s-o)(a-s-r)(a-t-a)(a-t-l)(a-z-a)(a-z-o)(a-s-f-b)(a-s-f-s)] closed set:[a F S T Z] current node:o successors:[s Z] frontier:[(a-s-r)(a-t-a)(a-t-l)(a-z-a)(a-z-o)(a-s-f-b)(a-s-f-s)(a-s-o-s)(a-s-o-z)] closed set:[a F O S T Z] current node:r successors:[c P S] frontier:[(a-t-a)(a-t-l)(a-z-a)(a-z-o)(a-s-f-b)(a-s-f-s)(a-s-o-s)(a-s-o-z)(a-s-r-c)(a-s-r-p)(a-s-r-s)] closed set:[a F O R S T Z] current node:a successors:[loop] frontier:[(a-t-l)(a-z-a)(a-z-o)(a-s-f-b)(a-s-f-s)(a-s-o-s)(a-s-o-z)(a-s-r-c)(a-s-r-p)(a-s-r-s)] closed set:[a F O R S T Z] current node:l successors:[m T] frontier:[(a-z-a)(a-z-o)(a-s-f-b)(a-s-f-s)(a-s-o-s)(a-s-o-z)(a-s-r-c)(a-s-r-p)(a-s-r-s)(a-t-l-m)(a-t-l- T)] closed set:[a F L O R S T Z] current node:a successors:[loop] frontier:[(a-z-o)(a-s-f-b)(a-s-f-s)(a-s-o-s)(a-s-o-z)(a-s-r-c)(a-s-r-p)(a-s-r-s)(a-t-l-m)(a-t-l-t)] closed set:[a F L O R S T Z] current node:o successors:[loop] frontier:[(a-s-f-b)(a-s-f-s)(a-s-o-s)(a-s-o-z)(a-s-r-c)(a-s-r-p)(a-s-r-s)(a-t-l-m)(a-t-l-t)] closed set:[a F L O R S T Z] current node:b successors:[f G P U] Path to goal node found: (Arad-Sibiu-Fagaras-Bucharest 450) Άσκηση 7 Για την αναζήτηση πρώτα κατά πλάτος (BFS) αναζητούμε τη διαδρομή με το μικρότερο πλήθος βημάτων (hops) για τη μετάβαση από την αρχική κατάσταση στην τελική κατάσταση. Συνεπώς για το συγκεκριμένο παράδειγμα η διαδρομή είναι η A-C-F-I με μήκος 34. Για την αναζήτηση πρώτα κατά βάθος (DFS) επιλέγουμε ένα από τα παιδιά του τρέχοντα κόμβου (π.χ. εκείνο που προηγείται αλφαβητικά) και ο κόμβος αυτός γίνεται ο τρέχοντας. Η διαδικασία συνεχίζεται μέχρι να βρεθούμε στον κόμβο προορισμό. Συνεπώς για το συγκεκριμένο παράδειγμα η διαδρομή είναι η A-B-D-G-H-I με μήκος 24. Η αναζήτηση ομοιόμορφου κόστους εντοπίζει τη διαδρομή με το συντομότερο μήκος διαδρομής από την αφετηρία στον προορισμό. Συνεπώς για το συγκεκριμένο παράδειγμα η διαδρομή είναι η A-B-E-F-G-I με μήκος 6. Άσκηση 8 Οι αναδρομικοί αλγόριθμοι των BFS, DFS βρίσκονται υλοποιημένοι στο lab01_search_ext.cpp της άσκησης 6. 23
#include "lab01_search_ext.hpp" int main(int argc, char **argv) struct di_graph graph ; string fn; string start_vertex, goal_vertex, search_method; if (argc == 5) fn = argv[1]; start_vertex = argv[2]; goal_vertex = argv[3]; search_method = argv[4]; graph = read_data(fn); if (search_method.compare("bfs") == 0) breadth_first_search(graph, start_vertex, goal_vertex); breadth_first_search_recursive(graph, start_vertex, goal_vertex); else if (search_method.compare("dfs") == 0) depth_first_search_alt(graph, start_vertex, goal_vertex); depth_first_search_recursive(graph, start_vertex, goal_vertex); else cerr << "Invalid choice" << endl; free_memory(graph); lab01_exercise08.cpp g++ lab01_graph.cpp lab01_search.cpp lab01_search_ext.cpp lab01_exercise08.cpp -o lab01_exercise08 -Wall -std=c++11 lab01_exercise08 data/tour_romania.txt A B bfs BREADTH FIRST SEARCH frontier:[(a)] closed set:[] current node:a successors:[s T Z] frontier:[(a-s)(a-t)(a-z)] closed set:[a] current node:s successors:[a F O R] frontier:[(a-t)(a-z)(a-s-a)(a-s-f)(a-s-o)(a-s-r)] closed set:[a S] current node:t successors:[a L] frontier:[(a-z)(a-s-a)(a-s-f)(a-s-o)(a-s-r)(a-t-a)(a-t-l)] closed set:[a S T] current node:z successors:[a O] frontier:[(a-s-a)(a-s-f)(a-s-o)(a-s-r)(a-t-a)(a-t-l)(a-z-a)(a-z-o)] closed set:[a S T Z] current node:a successors:[loop] frontier:[(a-s-f)(a-s-o)(a-s-r)(a-t-a)(a-t-l)(a-z-a)(a-z-o)] closed set:[a S T Z] current node:f successors:[b S] frontier:[(a-s-o)(a-s-r)(a-t-a)(a-t-l)(a-z-a)(a-z-o)(a-s-f-b)(a-s-f-s)] closed set:[a F S T Z] current node:o successors:[s Z] frontier:[(a-s-r)(a-t-a)(a-t-l)(a-z-a)(a-z-o)(a-s-f-b)(a-s-f-s)(a-s-o-s)(a-s-o-z)] closed set:[a F O S T Z] current node:r successors:[c P S] frontier:[(a-t-a)(a-t-l)(a-z-a)(a-z-o)(a-s-f-b)(a-s-f-s)(a-s-o-s)(a-s-o-z)(a-s-r-c)(a-s-r-p)(a-s-r-s)] closed set:[a F O R S T Z] current node:a successors:[loop] frontier:[(a-t-l)(a-z-a)(a-z-o)(a-s-f-b)(a-s-f-s)(a-s-o-s)(a-s-o-z)(a-s-r-c)(a-s-r-p)(a-s-r-s)] closed set:[a F O R S T Z] current node:l successors:[m T] frontier:[(a-z-a)(a-z-o)(a-s-f-b)(a-s-f-s)(a-s-o-s)(a-s-o-z)(a-s-r-c)(a-s-r-p)(a-s-r-s)(a-t-l-m)(a-t-l- T)] closed set:[a F L O R S T Z] current node:a successors:[loop] frontier:[(a-z-o)(a-s-f-b)(a-s-f-s)(a-s-o-s)(a-s-o-z)(a-s-r-c)(a-s-r-p)(a-s-r-s)(a-t-l-m)(a-t-l-t)] closed set:[a F L O R S T Z] current node:o successors:[loop] frontier:[(a-s-f-b)(a-s-f-s)(a-s-o-s)(a-s-o-z)(a-s-r-c)(a-s-r-p)(a-s-r-s)(a-t-l-m)(a-t-l-t)] closed set:[a F L O R S T Z] current node:b successors:[f G P U] Path to goal node found: (Arad-Sibiu-Fagaras-Bucharest 450) BREADTH FIRST SEARCH ALTERNATIVE IMPLEMENTATION (RECURSIVE) Path to goal node found: (Arad-Sibiu-Fagaras-Bucharest 450) 24