From ace08a5cd671a2b8b3e9b49bdac441e865d788f4 Mon Sep 17 00:00:00 2001 From: Apurv-Bajaj Date: Wed, 13 Dec 2017 00:26:35 +0530 Subject: [PATCH 1/8] tic-tac-toe gui added --- gui/tic-tac-toe.py | 236 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 gui/tic-tac-toe.py diff --git a/gui/tic-tac-toe.py b/gui/tic-tac-toe.py new file mode 100644 index 000000000..c2781255f --- /dev/null +++ b/gui/tic-tac-toe.py @@ -0,0 +1,236 @@ +from tkinter import * +import sys +import os.path +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) +from games import minimax_decision, alphabeta_player, random_player, TicTacToe +# "gen_state" can be used to generate a game state to apply the algorithm +from tests.test_games import gen_state + +ttt = TicTacToe() +root = None +buttons = [] +frames = [] +x_pos = [] +o_pos = [] +count = 0 +sym = "" +result = None +choices = None + + +def create_frames(root): + """ + This function creates the necessary structure of the game. + """ + frame1 = Frame(root) + frame2 = Frame(root) + frame3 = Frame(root) + frame4 = Frame(root) + create_buttons(frame1) + create_buttons(frame2) + create_buttons(frame3) + buttonExit = Button( + frame4, height=1, width=2, + text="Exit", + command=lambda: exit_game(root)) + buttonExit.pack(side=LEFT) + frame4.pack(side=BOTTOM) + frame3.pack(side=BOTTOM) + frame2.pack(side=BOTTOM) + frame1.pack(side=BOTTOM) + frames.append(frame1) + frames.append(frame2) + frames.append(frame3) + for x in frames: + buttons_in_frame = [] + for y in x.winfo_children(): + buttons_in_frame.append(y) + buttons.append(buttons_in_frame) + buttonReset = Button(frame4, height=1, width=2, + text="Reset", command=lambda: reset_game()) + buttonReset.pack(side=LEFT) + + +def create_buttons(frame): + """ + This function creates the buttons to be pressed/clicked during the game. + """ + button0 = Button(frame, height=2, width=2, text=" ", + command=lambda: on_click(button0)) + button0.pack(side=LEFT) + button1 = Button(frame, height=2, width=2, text=" ", + command=lambda: on_click(button1)) + button1.pack(side=LEFT) + button2 = Button(frame, height=2, width=2, text=" ", + command=lambda: on_click(button2)) + button2.pack(side=LEFT) + + +# TODO: Add a choice option for the user. +def on_click(button): + """ + This function determines the action of any button. + """ + global ttt, choices, count, sym, result, x_pos, o_pos + + if count % 2 == 0: + sym = "X" + else: + sym = "O" + count += 1 + + button.config( + text=sym, + state='disabled', + disabledforeground="red") # For cross + + x, y = get_coordinates(button) + x += 1 + y += 1 + x_pos.append((x, y)) + state = gen_state(to_move='O', x_positions=x_pos, + o_positions=o_pos) + try: + choice = choices.get() + if "Random" in choice: + a, b = random_player(ttt, state) + elif "Pro" in choice: + a, b = minimax_decision(state, ttt) + else: + a, b = alphabeta_player(ttt, state) + except (ValueError, IndexError, TypeError) as e: + disable_game() + result.set("It's a draw :|") + return + if 1 <= a <= 3 and 1 <= b <= 3: + o_pos.append((a, b)) + button_to_change = get_button(a - 1, b - 1) + if count % 2 == 0: # Used again, will become handy when user is given the choice of turn. + sym = "X" + else: + sym = "O" + count += 1 + + if check_victory(button): + result.set("You win :)") + disable_game() + else: + button_to_change.config(text=sym, state='disabled', + disabledforeground="black") + if check_victory(button_to_change): + result.set("You lose :(") + disable_game() + + +# TODO: Replace "check_victory" by "k_in_row" function. +def check_victory(button): + """ + This function checks various winning conditions of the game. + """ + # check if previous move caused a win on vertical line + global buttons + x, y = get_coordinates(button) + tt = button['text'] + if buttons[0][y]['text'] == buttons[1][y]['text'] == buttons[2][y]['text'] != " ": + buttons[0][y].config(text="|" + tt + "|") + buttons[1][y].config(text="|" + tt + "|") + buttons[2][y].config(text="|" + tt + "|") + return True + + # check if previous move caused a win on horizontal line + if buttons[x][0]['text'] == buttons[x][1]['text'] == buttons[x][2]['text'] != " ": + buttons[x][0].config(text="--" + tt + "--") + buttons[x][1].config(text="--" + tt + "--") + buttons[x][2].config(text="--" + tt + "--") + return True + + # check if previous move was on the main diagonal and caused a win + if x == y and buttons[0][0]['text'] == buttons[1][1]['text'] == buttons[2][2]['text'] != " ": + buttons[0][0].config(text="\\" + tt + "\\") + buttons[1][1].config(text="\\" + tt + "\\") + buttons[2][2].config(text="\\" + tt + "\\") + return True + + # check if previous move was on the secondary diagonal and caused a win + if x + \ + y == 2 and buttons[0][2]['text'] == buttons[1][1]['text'] == buttons[2][0]['text'] != " ": + buttons[0][2].config(text="/" + tt + "/") + buttons[1][1].config(text="/" + tt + "/") + buttons[2][0].config(text="/" + tt + "/") + return True + + return False + + +def get_coordinates(button): + """ + This function returns the coordinates of the button clicked. + """ + global buttons + for x in range(len(buttons)): + for y in range(len(buttons[x])): + if buttons[x][y] == button: + return x, y + + +def get_button(x, y): + """ + This function returns the button memory location corresponding to a coordinate. + """ + global buttons + return buttons[x][y] + + +def reset_game(): + """ + This function will reset all the tiles to the initial null value. + """ + global x_pos, o_pos, frames, count + + count = 0 + x_pos = [] + o_pos = [] + result.set("Your Turn!") + for x in frames: + for y in x.winfo_children(): + y.config(text=" ", state='normal') + + +def disable_game(): + """ + This function deactivates the game after a win, loss or draw. + """ + global frames + for x in frames: + for y in x.winfo_children(): + y.config(state='disabled') + + +def exit_game(root): + """ + This function will exit the game by killing the root. + """ + root.destroy() + + +def main(): + global result, choices + + root = Tk() + root.title("TicTacToe") + root.resizable(0, 0) # To remove the maximize window option + result = StringVar() + result.set("Your Turn!") + w = Label(root, textvariable=result) + w.pack(side=BOTTOM) + create_frames(root) + choices = StringVar(root) + choices.set("Vs Pro") + menu = OptionMenu(root, choices, "Vs Random", "Vs Pro", "Vs Legend") + menu.pack() + root.mainloop() + + +if __name__ == "__main__": + main() + From 01344921029fb4aefe7a609aa893b6ca280b87e0 Mon Sep 17 00:00:00 2001 From: Apurv-Bajaj Date: Sat, 16 Dec 2017 16:50:45 +0530 Subject: [PATCH 2/8] Added GUI for Searching --- gui/romania_problem.py | 271 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 gui/romania_problem.py diff --git a/gui/romania_problem.py b/gui/romania_problem.py new file mode 100644 index 000000000..0e377d9a7 --- /dev/null +++ b/gui/romania_problem.py @@ -0,0 +1,271 @@ +from tkinter import * +import sys +import os.path +import math +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) +from search import * + +root = None +city_coord = {} +height = 0 + + +def create_map(root): + ''' + This function draws out the required map. + ''' + romania_problem = GraphProblem('Arad', 'Bucharest', romania_map) + romania_locations = romania_map.locations + global height + width = 700 + height = 800 + margin = 5 + city_map = Canvas(root, width=width, height=height) + city_map.pack() + + for city in romania_locations.keys(): + create_rectangle( + city_map, + romania_locations[city][0], + height - + romania_locations[city][1], + margin, + city) + + # Since lines have to be drawn between particular points, we need to list + # them separately + create_line( + city_map, + romania_locations['Arad'][0], + height - + romania_locations['Arad'][1], + romania_locations['Sibiu'][0], + height - + romania_locations['Sibiu'][1], + 140) + create_line( + city_map, + romania_locations['Arad'][0], + height - + romania_locations['Arad'][1], + romania_locations['Zerind'][0], + height - + romania_locations['Zerind'][1], + 75) + create_line( + city_map, + romania_locations['Arad'][0], + height - + romania_locations['Arad'][1], + romania_locations['Timisoara'][0], + height - + romania_locations['Timisoara'][1], + 118) + create_line( + city_map, + romania_locations['Oradea'][0], + height - + romania_locations['Oradea'][1], + romania_locations['Zerind'][0], + height - + romania_locations['Zerind'][1], + 71) + create_line( + city_map, + romania_locations['Oradea'][0], + height - + romania_locations['Oradea'][1], + romania_locations['Sibiu'][0], + height - + romania_locations['Sibiu'][1], + 151) + create_line( + city_map, + romania_locations['Lugoj'][0], + height - + romania_locations['Lugoj'][1], + romania_locations['Timisoara'][0], + height - + romania_locations['Timisoara'][1], + 111) + create_line( + city_map, + romania_locations['Lugoj'][0], + height - + romania_locations['Lugoj'][1], + romania_locations['Mehadia'][0], + height - + romania_locations['Mehadia'][1], + 70) + create_line( + city_map, + romania_locations['Drobeta'][0], + height - + romania_locations['Drobeta'][1], + romania_locations['Mehadia'][0], + height - + romania_locations['Mehadia'][1], + 75) + create_line( + city_map, + romania_locations['Drobeta'][0], + height - + romania_locations['Drobeta'][1], + romania_locations['Craiova'][0], + height - + romania_locations['Craiova'][1], + 120) + create_line( + city_map, + romania_locations['Pitesti'][0], + height - + romania_locations['Pitesti'][1], + romania_locations['Craiova'][0], + height - + romania_locations['Craiova'][1], + 138) + create_line( + city_map, + romania_locations['Rimnicu'][0], + height - + romania_locations['Rimnicu'][1], + romania_locations['Craiova'][0], + height - + romania_locations['Craiova'][1], + 146) + create_line( + city_map, + romania_locations['Rimnicu'][0], + height - + romania_locations['Rimnicu'][1], + romania_locations['Sibiu'][0], + height - + romania_locations['Sibiu'][1], + 80) + create_line( + city_map, + romania_locations['Rimnicu'][0], + height - + romania_locations['Rimnicu'][1], + romania_locations['Pitesti'][0], + height - + romania_locations['Pitesti'][1], + 97) + create_line( + city_map, + romania_locations['Fagaras'][0], + height - + romania_locations['Fagaras'][1], + romania_locations['Sibiu'][0], + height - + romania_locations['Sibiu'][1], + 99) + create_line( + city_map, + romania_locations['Fagaras'][0], + height - + romania_locations['Fagaras'][1], + romania_locations['Bucharest'][0], + height - + romania_locations['Bucharest'][1], + 211) + create_line( + city_map, + romania_locations['Giurgiu'][0], + height - + romania_locations['Giurgiu'][1], + romania_locations['Bucharest'][0], + height - + romania_locations['Bucharest'][1], + 90) + create_line( + city_map, + romania_locations['Urziceni'][0], + height - + romania_locations['Urziceni'][1], + romania_locations['Bucharest'][0], + height - + romania_locations['Bucharest'][1], + 85) + create_line( + city_map, + romania_locations['Urziceni'][0], + height - + romania_locations['Urziceni'][1], + romania_locations['Hirsova'][0], + height - + romania_locations['Hirsova'][1], + 98) + create_line( + city_map, + romania_locations['Eforie'][0], + height - + romania_locations['Eforie'][1], + romania_locations['Hirsova'][0], + height - + romania_locations['Hirsova'][1], + 86) + create_line( + city_map, + romania_locations['Urziceni'][0], + height - + romania_locations['Urziceni'][1], + romania_locations['Vaslui'][0], + height - + romania_locations['Vaslui'][1], + 142) + create_line( + city_map, + romania_locations['Iasi'][0], + height - + romania_locations['Iasi'][1], + romania_locations['Vaslui'][0], + height - + romania_locations['Vaslui'][1], + 92) + create_line( + city_map, + romania_locations['Iasi'][0], + height - + romania_locations['Iasi'][1], + romania_locations['Neamt'][0], + height - + romania_locations['Neamt'][1], + 87) + + +def create_line(map, x0, y0, x1, y1, distance): + ''' + This function draws out the lines joining various points. + ''' + map.create_line(x0, y0, x1, y1) + map.create_text((x0 + x1) / 2, (y0 + y1) / 2, text=distance) + + +def create_rectangle(map, x0, y0, margin, city_name): + ''' + This function draws out rectangles for various points. + ''' + global city_coord + rect = map.create_rectangle( + x0 - margin, + y0 - margin, + x0 + margin, + y0 + margin) + map.create_text( + x0 - 2 * margin, + y0 - 2 * margin, + text=city_name, + anchor=SE) + city_coord.update({city_name: rect}) + + +def main(): + root = Tk() + root.title("Road Map of Romania") + create_map(root) + root.mainloop() + + +if __name__ == "__main__": + main() From ac7fa0f4ca30e91ddd018851d14dbe83f46e739b Mon Sep 17 00:00:00 2001 From: Apurv-Bajaj Date: Sat, 16 Dec 2017 17:43:26 +0530 Subject: [PATCH 3/8] Added Legend and Minor Fix --- gui/romania_problem.py | 85 +++++++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 34 deletions(-) diff --git a/gui/romania_problem.py b/gui/romania_problem.py index 0e377d9a7..cdb1d33e7 100644 --- a/gui/romania_problem.py +++ b/gui/romania_problem.py @@ -23,18 +23,9 @@ def create_map(root): city_map = Canvas(root, width=width, height=height) city_map.pack() - for city in romania_locations.keys(): - create_rectangle( - city_map, - romania_locations[city][0], - height - - romania_locations[city][1], - margin, - city) - # Since lines have to be drawn between particular points, we need to list # them separately - create_line( + make_line( city_map, romania_locations['Arad'][0], height - @@ -43,7 +34,7 @@ def create_map(root): height - romania_locations['Sibiu'][1], 140) - create_line( + make_line( city_map, romania_locations['Arad'][0], height - @@ -52,7 +43,7 @@ def create_map(root): height - romania_locations['Zerind'][1], 75) - create_line( + make_line( city_map, romania_locations['Arad'][0], height - @@ -61,7 +52,7 @@ def create_map(root): height - romania_locations['Timisoara'][1], 118) - create_line( + make_line( city_map, romania_locations['Oradea'][0], height - @@ -70,7 +61,7 @@ def create_map(root): height - romania_locations['Zerind'][1], 71) - create_line( + make_line( city_map, romania_locations['Oradea'][0], height - @@ -79,7 +70,7 @@ def create_map(root): height - romania_locations['Sibiu'][1], 151) - create_line( + make_line( city_map, romania_locations['Lugoj'][0], height - @@ -88,7 +79,7 @@ def create_map(root): height - romania_locations['Timisoara'][1], 111) - create_line( + make_line( city_map, romania_locations['Lugoj'][0], height - @@ -97,7 +88,7 @@ def create_map(root): height - romania_locations['Mehadia'][1], 70) - create_line( + make_line( city_map, romania_locations['Drobeta'][0], height - @@ -106,7 +97,7 @@ def create_map(root): height - romania_locations['Mehadia'][1], 75) - create_line( + make_line( city_map, romania_locations['Drobeta'][0], height - @@ -115,7 +106,7 @@ def create_map(root): height - romania_locations['Craiova'][1], 120) - create_line( + make_line( city_map, romania_locations['Pitesti'][0], height - @@ -124,7 +115,7 @@ def create_map(root): height - romania_locations['Craiova'][1], 138) - create_line( + make_line( city_map, romania_locations['Rimnicu'][0], height - @@ -133,7 +124,7 @@ def create_map(root): height - romania_locations['Craiova'][1], 146) - create_line( + make_line( city_map, romania_locations['Rimnicu'][0], height - @@ -142,7 +133,7 @@ def create_map(root): height - romania_locations['Sibiu'][1], 80) - create_line( + make_line( city_map, romania_locations['Rimnicu'][0], height - @@ -151,7 +142,7 @@ def create_map(root): height - romania_locations['Pitesti'][1], 97) - create_line( + make_line( city_map, romania_locations['Fagaras'][0], height - @@ -160,7 +151,7 @@ def create_map(root): height - romania_locations['Sibiu'][1], 99) - create_line( + make_line( city_map, romania_locations['Fagaras'][0], height - @@ -169,7 +160,7 @@ def create_map(root): height - romania_locations['Bucharest'][1], 211) - create_line( + make_line( city_map, romania_locations['Giurgiu'][0], height - @@ -178,7 +169,7 @@ def create_map(root): height - romania_locations['Bucharest'][1], 90) - create_line( + make_line( city_map, romania_locations['Urziceni'][0], height - @@ -187,7 +178,7 @@ def create_map(root): height - romania_locations['Bucharest'][1], 85) - create_line( + make_line( city_map, romania_locations['Urziceni'][0], height - @@ -196,7 +187,7 @@ def create_map(root): height - romania_locations['Hirsova'][1], 98) - create_line( + make_line( city_map, romania_locations['Eforie'][0], height - @@ -205,7 +196,7 @@ def create_map(root): height - romania_locations['Hirsova'][1], 86) - create_line( + make_line( city_map, romania_locations['Urziceni'][0], height - @@ -214,7 +205,7 @@ def create_map(root): height - romania_locations['Vaslui'][1], 142) - create_line( + make_line( city_map, romania_locations['Iasi'][0], height - @@ -223,7 +214,7 @@ def create_map(root): height - romania_locations['Vaslui'][1], 92) - create_line( + make_line( city_map, romania_locations['Iasi'][0], height - @@ -233,8 +224,18 @@ def create_map(root): romania_locations['Neamt'][1], 87) + for city in romania_locations.keys(): + make_rectangle( + city_map, + romania_locations[city][0], + height - + romania_locations[city][1], + margin, + city) + + make_legend(city_map) -def create_line(map, x0, y0, x1, y1, distance): +def make_line(map, x0, y0, x1, y1, distance): ''' This function draws out the lines joining various points. ''' @@ -242,7 +243,7 @@ def create_line(map, x0, y0, x1, y1, distance): map.create_text((x0 + x1) / 2, (y0 + y1) / 2, text=distance) -def create_rectangle(map, x0, y0, margin, city_name): +def make_rectangle(map, x0, y0, margin, city_name): ''' This function draws out rectangles for various points. ''' @@ -251,7 +252,8 @@ def create_rectangle(map, x0, y0, margin, city_name): x0 - margin, y0 - margin, x0 + margin, - y0 + margin) + y0 + margin, + fill="white") map.create_text( x0 - 2 * margin, y0 - 2 * margin, @@ -259,6 +261,21 @@ def create_rectangle(map, x0, y0, margin, city_name): anchor=SE) city_coord.update({city_name: rect}) +def make_legend(map): + rect1=map.create_rectangle(600,100,610,110,fill="white") + text1 = map.create_text(615, 105,anchor=W,text="Un-explored") + + rect2=map.create_rectangle(600,115,610,125,fill="orange") + text2 = map.create_text(615, 120,anchor=W,text="Frontier") + + rect3=map.create_rectangle(600,130,610,140,fill="red") + text3 = map.create_text(615, 135,anchor=W,text="Currently Exploring") + + rect4=map.create_rectangle(600,145,610,155,fill="grey") + text4 = map.create_text(615, 150,anchor=W,text="Explored") + + rect5=map.create_rectangle(600,160,610,170,fill="dark green") + text5 = map.create_text(615, 165, anchor=W, text="Final Solution") def main(): root = Tk() From 442765b2a47779b5ee6823ee24ab10873e41afde Mon Sep 17 00:00:00 2001 From: Apurv-Bajaj Date: Sun, 17 Dec 2017 01:38:46 +0530 Subject: [PATCH 4/8] Minor Fix and Options added --- gui/romania_problem.py | 80 +++++++++++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 28 deletions(-) diff --git a/gui/romania_problem.py b/gui/romania_problem.py index cdb1d33e7..211a9a605 100644 --- a/gui/romania_problem.py +++ b/gui/romania_problem.py @@ -7,18 +7,20 @@ root = None city_coord = {} -height = 0 +romania_problem = GraphProblem('Arad', 'Bucharest', romania_map) +algo=None +start=None +goal=None def create_map(root): ''' This function draws out the required map. ''' - romania_problem = GraphProblem('Arad', 'Bucharest', romania_map) + global romania_problem romania_locations = romania_map.locations - global height - width = 700 - height = 800 + width = 750 + height = 670 margin = 5 city_map = Canvas(root, width=width, height=height) city_map.pack() @@ -33,7 +35,7 @@ def create_map(root): romania_locations['Sibiu'][0], height - romania_locations['Sibiu'][1], - 140) + romania_map.get('Arad', 'Sibiu')) make_line( city_map, romania_locations['Arad'][0], @@ -42,7 +44,7 @@ def create_map(root): romania_locations['Zerind'][0], height - romania_locations['Zerind'][1], - 75) + romania_map.get('Arad', 'Zerind')) make_line( city_map, romania_locations['Arad'][0], @@ -51,7 +53,7 @@ def create_map(root): romania_locations['Timisoara'][0], height - romania_locations['Timisoara'][1], - 118) + romania_map.get('Arad', 'Timisoara')) make_line( city_map, romania_locations['Oradea'][0], @@ -60,7 +62,7 @@ def create_map(root): romania_locations['Zerind'][0], height - romania_locations['Zerind'][1], - 71) + romania_map.get('Oradea', 'Zerind')) make_line( city_map, romania_locations['Oradea'][0], @@ -69,7 +71,7 @@ def create_map(root): romania_locations['Sibiu'][0], height - romania_locations['Sibiu'][1], - 151) + romania_map.get('Oradea', 'Sibiu')) make_line( city_map, romania_locations['Lugoj'][0], @@ -78,7 +80,7 @@ def create_map(root): romania_locations['Timisoara'][0], height - romania_locations['Timisoara'][1], - 111) + romania_map.get('Lugoj', 'Timisoara')) make_line( city_map, romania_locations['Lugoj'][0], @@ -87,7 +89,7 @@ def create_map(root): romania_locations['Mehadia'][0], height - romania_locations['Mehadia'][1], - 70) + romania_map.get('Lugoj', 'Mehandia')) make_line( city_map, romania_locations['Drobeta'][0], @@ -96,7 +98,7 @@ def create_map(root): romania_locations['Mehadia'][0], height - romania_locations['Mehadia'][1], - 75) + romania_map.get('Drobeta', 'Mehandia')) make_line( city_map, romania_locations['Drobeta'][0], @@ -105,7 +107,7 @@ def create_map(root): romania_locations['Craiova'][0], height - romania_locations['Craiova'][1], - 120) + romania_map.get('Drobeta', 'Craiova')) make_line( city_map, romania_locations['Pitesti'][0], @@ -114,7 +116,7 @@ def create_map(root): romania_locations['Craiova'][0], height - romania_locations['Craiova'][1], - 138) + romania_map.get('Pitesti', 'Craiova')) make_line( city_map, romania_locations['Rimnicu'][0], @@ -123,7 +125,7 @@ def create_map(root): romania_locations['Craiova'][0], height - romania_locations['Craiova'][1], - 146) + romania_map.get('Rimnicu', 'Craiova')) make_line( city_map, romania_locations['Rimnicu'][0], @@ -132,7 +134,7 @@ def create_map(root): romania_locations['Sibiu'][0], height - romania_locations['Sibiu'][1], - 80) + romania_map.get('Rimnicu', 'Sibiu')) make_line( city_map, romania_locations['Rimnicu'][0], @@ -141,7 +143,7 @@ def create_map(root): romania_locations['Pitesti'][0], height - romania_locations['Pitesti'][1], - 97) + romania_map.get('Rimnicu', 'Pitesti')) make_line( city_map, romania_locations['Fagaras'][0], @@ -150,7 +152,7 @@ def create_map(root): romania_locations['Sibiu'][0], height - romania_locations['Sibiu'][1], - 99) + romania_map.get('Fagaras', 'Sibiu')) make_line( city_map, romania_locations['Fagaras'][0], @@ -159,7 +161,7 @@ def create_map(root): romania_locations['Bucharest'][0], height - romania_locations['Bucharest'][1], - 211) + romania_map.get('Fagaras', 'Bucharest')) make_line( city_map, romania_locations['Giurgiu'][0], @@ -168,7 +170,7 @@ def create_map(root): romania_locations['Bucharest'][0], height - romania_locations['Bucharest'][1], - 90) + romania_map.get('Giurgiu', 'Bucharest')) make_line( city_map, romania_locations['Urziceni'][0], @@ -177,7 +179,7 @@ def create_map(root): romania_locations['Bucharest'][0], height - romania_locations['Bucharest'][1], - 85) + romania_map.get('Urziceni', 'Bucharest')) make_line( city_map, romania_locations['Urziceni'][0], @@ -186,7 +188,7 @@ def create_map(root): romania_locations['Hirsova'][0], height - romania_locations['Hirsova'][1], - 98) + romania_map.get('Urziceni', 'Hirsova')) make_line( city_map, romania_locations['Eforie'][0], @@ -195,7 +197,7 @@ def create_map(root): romania_locations['Hirsova'][0], height - romania_locations['Hirsova'][1], - 86) + romania_map.get('Eforie', 'Hirsova')) make_line( city_map, romania_locations['Urziceni'][0], @@ -204,7 +206,7 @@ def create_map(root): romania_locations['Vaslui'][0], height - romania_locations['Vaslui'][1], - 142) + romania_map.get('Urziceni', 'Vaslui')) make_line( city_map, romania_locations['Iasi'][0], @@ -213,7 +215,7 @@ def create_map(root): romania_locations['Vaslui'][0], height - romania_locations['Vaslui'][1], - 92) + romania_map.get('Iasi', 'Vaslui')) make_line( city_map, romania_locations['Iasi'][0], @@ -222,7 +224,7 @@ def create_map(root): romania_locations['Neamt'][0], height - romania_locations['Neamt'][1], - 87) + romania_map.get('Iasi', 'Neamt')) for city in romania_locations.keys(): make_rectangle( @@ -262,6 +264,7 @@ def make_rectangle(map, x0, y0, margin, city_name): city_coord.update({city_name: rect}) def make_legend(map): + rect1=map.create_rectangle(600,100,610,110,fill="white") text1 = map.create_text(615, 105,anchor=W,text="Un-explored") @@ -276,10 +279,31 @@ def make_legend(map): rect5=map.create_rectangle(600,160,610,170,fill="dark green") text5 = map.create_text(615, 165, anchor=W, text="Final Solution") - + def main(): + global algo,start,goal root = Tk() root.title("Road Map of Romania") + root.geometry("950x1150") + algo=StringVar(root) + start = StringVar(root) + goal = StringVar(root) + algo.set("Breadth First Tree Search") + start.set('Arad') + goal.set('Bucharest') + cities=list(romania_map.locations.keys()) + cities.sort() + algorithm_menu=OptionMenu(root,algo,"Breadth-First Tree Search","Depth-First Tree Search") + Label(root,text="\n Search Algorithm").pack() + algorithm_menu.pack() + Label(root,text="\n Start City").pack() + start_menu = OptionMenu(root,start,*cities) + start_menu.pack() + Label(root, text="\n Goal City").pack() + goal_menu = OptionMenu(root,goal,*cities) + goal_menu.pack() + next_button = Button(root, width=6, height=2, text="Next", command=None,padx=2,pady=2,relief=GROOVE) + next_button.pack(side=BOTTOM) create_map(root) root.mainloop() From cd027d5498174b8b9ac251b5f6cdd057c0247514 Mon Sep 17 00:00:00 2001 From: Apurv-Bajaj Date: Mon, 18 Dec 2017 10:43:10 +0530 Subject: [PATCH 5/8] Added Breadth-First Tree Search --- gui/romania_problem.py | 201 ++++++++++++++++++++++++++++++++++------- 1 file changed, 168 insertions(+), 33 deletions(-) diff --git a/gui/romania_problem.py b/gui/romania_problem.py index 211a9a605..b930c80dd 100644 --- a/gui/romania_problem.py +++ b/gui/romania_problem.py @@ -4,20 +4,28 @@ import math sys.path.append(os.path.join(os.path.dirname(__file__), '..')) from search import * - +from search import breadth_first_tree_search as bfts +from utils import Stack, FIFOQueue, PriorityQueue +from copy import deepcopy root = None city_coord = {} -romania_problem = GraphProblem('Arad', 'Bucharest', romania_map) -algo=None -start=None -goal=None +romania_problem = None +algo = None +start = None +goal = None +counter = -1 +city_map = None +frontier = None +front = None +node = None +next_button = None def create_map(root): ''' This function draws out the required map. ''' - global romania_problem + global city_map, start, goal romania_locations = romania_map.locations width = 750 height = 670 @@ -237,6 +245,7 @@ def create_map(root): make_legend(city_map) + def make_line(map, x0, y0, x1, y1, distance): ''' This function draws out the lines joining various points. @@ -263,47 +272,173 @@ def make_rectangle(map, x0, y0, margin, city_name): anchor=SE) city_coord.update({city_name: rect}) + def make_legend(map): - - rect1=map.create_rectangle(600,100,610,110,fill="white") - text1 = map.create_text(615, 105,anchor=W,text="Un-explored") - - rect2=map.create_rectangle(600,115,610,125,fill="orange") - text2 = map.create_text(615, 120,anchor=W,text="Frontier") - - rect3=map.create_rectangle(600,130,610,140,fill="red") - text3 = map.create_text(615, 135,anchor=W,text="Currently Exploring") - - rect4=map.create_rectangle(600,145,610,155,fill="grey") - text4 = map.create_text(615, 150,anchor=W,text="Explored") - - rect5=map.create_rectangle(600,160,610,170,fill="dark green") + + rect1 = map.create_rectangle(600, 100, 610, 110, fill="white") + text1 = map.create_text(615, 105, anchor=W, text="Un-explored") + + rect2 = map.create_rectangle(600, 115, 610, 125, fill="orange") + text2 = map.create_text(615, 120, anchor=W, text="Frontier") + + rect3 = map.create_rectangle(600, 130, 610, 140, fill="red") + text3 = map.create_text(615, 135, anchor=W, text="Currently Exploring") + + rect4 = map.create_rectangle(600, 145, 610, 155, fill="grey") + text4 = map.create_text(615, 150, anchor=W, text="Explored") + + rect5 = map.create_rectangle(600, 160, 610, 170, fill="dark green") text5 = map.create_text(615, 165, anchor=W, text="Final Solution") - + + +def tree_search(problem): + ''' + This function has been changed to make it suitable for the Tkinter GUI. + ''' + global counter, frontier, node + # print(counter) + if counter == -1: + frontier.append(Node(problem.initial)) + # print(frontier) + display_frontier(frontier) + if counter % 3 == 0 and counter >= 0: + node = frontier.pop() + # print(node) + display_current(node) + if counter % 3 == 1 and counter >= 0: + if problem.goal_test(node.state): + # print(node) + return node + frontier.extend(node.expand(problem)) + # print(frontier) + display_frontier(frontier) + if counter % 3 == 2 and counter >= 0: + # print(node) + display_explored(node) + return None + + +def display_frontier(queue): + ''' + This function marks the frontier nodes (orange) on the map. + ''' + global city_map, city_coord + qu = deepcopy(queue) + while qu: + node = qu.pop() + for city in city_coord.keys(): + if node.state == city: + city_map.itemconfig(city_coord[city], fill="orange") + return + + +def display_current(node): + ''' + This function marks the currently exploring node (red) on the map. + ''' + global city_map, city_coord + city = node.state + city_map.itemconfig(city_coord[city], fill="red") + return + + +def display_explored(node): + ''' + This function marks the already explored node (gray) on the map. + ''' + global city_map, city_coord + city = node.state + city_map.itemconfig(city_coord[city], fill="gray") + return + + +def display_final(cities): + ''' + This function marks the final solution nodes (green) on the map. + ''' + global city_map, city_coord + for city in cities: + city_map.itemconfig(city_coord[city], fill="green") + return + + +def breadth_first_tree_search(problem): + """Search the shallowest nodes in the search tree first.""" + global frontier, counter + if counter == -1: + frontier = FIFOQueue() + return tree_search(problem) + + +def on_click(): + ''' + This function defines the action of the 'Next' button. + ''' + global algo, counter, next_button, romania_problem, start, goal + romania_problem = GraphProblem(start.get(), goal.get(), romania_map) + if "Breadth-First Tree Search" == algo.get(): + node = breadth_first_tree_search(romania_problem) + if node is not None: + final_path = bfts(romania_problem).solution() + final_path.append(start.get()) + display_final(final_path) + next_button.config(state="disabled") + counter += 1 + + +def reset_map(): + global counter, city_coord, city_map, next_button + counter = -1 + for city in city_coord.keys(): + city_map.itemconfig(city_coord[city], fill="white") + next_button.config(state="normal") + +# TODO: Add more search algorithms in the OptionMenu + + def main(): - global algo,start,goal + global algo, start, goal, next_button root = Tk() root.title("Road Map of Romania") root.geometry("950x1150") - algo=StringVar(root) + algo = StringVar(root) start = StringVar(root) goal = StringVar(root) - algo.set("Breadth First Tree Search") + algo.set("Breadth-First Tree Search") start.set('Arad') goal.set('Bucharest') - cities=list(romania_map.locations.keys()) - cities.sort() - algorithm_menu=OptionMenu(root,algo,"Breadth-First Tree Search","Depth-First Tree Search") - Label(root,text="\n Search Algorithm").pack() + cities = sorted(romania_map.locations.keys()) + algorithm_menu = OptionMenu(root, algo, "Breadth-First Tree Search") + Label(root, text="\n Search Algorithm").pack() algorithm_menu.pack() - Label(root,text="\n Start City").pack() - start_menu = OptionMenu(root,start,*cities) + Label(root, text="\n Start City").pack() + start_menu = OptionMenu(root, start, *cities) start_menu.pack() Label(root, text="\n Goal City").pack() - goal_menu = OptionMenu(root,goal,*cities) + goal_menu = OptionMenu(root, goal, *cities) goal_menu.pack() - next_button = Button(root, width=6, height=2, text="Next", command=None,padx=2,pady=2,relief=GROOVE) - next_button.pack(side=BOTTOM) + frame1 = Frame(root) + next_button = Button( + frame1, + width=6, + height=2, + text="Next", + command=on_click, + padx=2, + pady=2, + relief=GROOVE) + next_button.pack(side=RIGHT) + reset_button = Button( + frame1, + width=6, + height=2, + text="Reset", + command=reset_map, + padx=2, + pady=2, + relief=GROOVE) + reset_button.pack(side=RIGHT) + frame1.pack(side=BOTTOM) create_map(root) root.mainloop() From f2e1a12208c3276b5fb3163e3f381359418664ff Mon Sep 17 00:00:00 2001 From: Apurv-Bajaj Date: Mon, 18 Dec 2017 17:56:44 +0530 Subject: [PATCH 6/8] Added Depth-First Tree Search --- gui/romania_problem.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/gui/romania_problem.py b/gui/romania_problem.py index b930c80dd..e80608e14 100644 --- a/gui/romania_problem.py +++ b/gui/romania_problem.py @@ -4,7 +4,7 @@ import math sys.path.append(os.path.join(os.path.dirname(__file__), '..')) from search import * -from search import breadth_first_tree_search as bfts +from search import breadth_first_tree_search as bfts, depth_first_tree_search as dfts from utils import Stack, FIFOQueue, PriorityQueue from copy import deepcopy root = None @@ -370,6 +370,14 @@ def breadth_first_tree_search(problem): return tree_search(problem) +def depth_first_tree_search(problem): + """Search the deepest nodes in the search tree first.""" + global frontier,counter + if counter == -1: + frontier=Stack() + return tree_search(problem) + +# TODO: Remove redundant code. def on_click(): ''' This function defines the action of the 'Next' button. @@ -384,7 +392,14 @@ def on_click(): display_final(final_path) next_button.config(state="disabled") counter += 1 - + elif "Depth-First Tree Search" == algo.get(): + node = depth_first_tree_search(romania_problem) + if node is not None: + final_path = dfts(romania_problem).solution() + final_path.append(start.get()) + display_final(final_path) + next_button.config(state="disabled") + counter += 1 def reset_map(): global counter, city_coord, city_map, next_button @@ -408,7 +423,8 @@ def main(): start.set('Arad') goal.set('Bucharest') cities = sorted(romania_map.locations.keys()) - algorithm_menu = OptionMenu(root, algo, "Breadth-First Tree Search") + algorithm_menu = OptionMenu( + root, algo, "Breadth-First Tree Search", "Depth-First Tree Search") Label(root, text="\n Search Algorithm").pack() algorithm_menu.pack() Label(root, text="\n Start City").pack() From 7233ed3d9d2d060cddaa06c88b91832794c1b5cb Mon Sep 17 00:00:00 2001 From: Apurv-Bajaj Date: Mon, 18 Dec 2017 22:47:23 +0530 Subject: [PATCH 7/8] Minor Fix --- gui/romania_problem.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gui/romania_problem.py b/gui/romania_problem.py index e80608e14..c8e551245 100644 --- a/gui/romania_problem.py +++ b/gui/romania_problem.py @@ -372,12 +372,15 @@ def breadth_first_tree_search(problem): def depth_first_tree_search(problem): """Search the deepest nodes in the search tree first.""" + # This search algorithm might not work in case of repeated paths. global frontier,counter if counter == -1: frontier=Stack() return tree_search(problem) -# TODO: Remove redundant code. +# TODO: +# Remove redundant code. +# Make the interchangbility work between various algorithms at each step. def on_click(): ''' This function defines the action of the 'Next' button. From 7e3dc209d587b59003b48ebceabbe1e8c0a5662f Mon Sep 17 00:00:00 2001 From: Apurv-Bajaj Date: Wed, 20 Dec 2017 02:21:08 +0530 Subject: [PATCH 8/8] Added Depth-First Graph Search --- gui/romania_problem.py | 74 +++++++++++++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/gui/romania_problem.py b/gui/romania_problem.py index c8e551245..31a3d04c7 100644 --- a/gui/romania_problem.py +++ b/gui/romania_problem.py @@ -4,7 +4,7 @@ import math sys.path.append(os.path.join(os.path.dirname(__file__), '..')) from search import * -from search import breadth_first_tree_search as bfts, depth_first_tree_search as dfts +from search import breadth_first_tree_search as bfts, depth_first_tree_search as dfts,depth_first_graph_search as dfgs from utils import Stack, FIFOQueue, PriorityQueue from copy import deepcopy root = None @@ -19,7 +19,7 @@ front = None node = None next_button = None - +explored=None def create_map(root): ''' @@ -152,6 +152,15 @@ def create_map(root): height - romania_locations['Pitesti'][1], romania_map.get('Rimnicu', 'Pitesti')) + make_line( + city_map, + romania_locations['Bucharest'][0], + height - + romania_locations['Bucharest'][1], + romania_locations['Pitesti'][0], + height - + romania_locations['Pitesti'][1], + romania_map.get('Bucharest', 'Pitesti')) make_line( city_map, romania_locations['Fagaras'][0], @@ -293,6 +302,9 @@ def make_legend(map): def tree_search(problem): ''' + earch through the successors of a problem to find a goal. + The argument frontier should be an empty queue. + Don't worry about repeated paths to a state. [Figure 3.7] This function has been changed to make it suitable for the Tkinter GUI. ''' global counter, frontier, node @@ -317,6 +329,34 @@ def tree_search(problem): display_explored(node) return None +def graph_search(problem): + ''' + Search through the successors of a problem to find a goal. + The argument frontier should be an empty queue. + If two paths reach a state, only use the first one. [Figure 3.7] + This function has been changed to make it suitable for the Tkinter GUI. + ''' + global counter,frontier,node,explored + if counter == -1: + frontier.append(Node(problem.initial)) + explored=set() + display_frontier(frontier) + if counter % 3 ==0 and counter >=0: + node = frontier.pop() + display_current(node) + if counter % 3 == 1 and counter >= 0: + if problem.goal_test(node.state): + return node + explored.add(node.state) + frontier.extend(child for child in node.expand(problem) + if child.state not in explored and + child not in frontier) + display_frontier(frontier) + if counter % 3 == 2 and counter >= 0: + display_explored(node) + return None + + def display_frontier(queue): ''' @@ -329,8 +369,6 @@ def display_frontier(queue): for city in city_coord.keys(): if node.state == city: city_map.itemconfig(city_coord[city], fill="orange") - return - def display_current(node): ''' @@ -339,8 +377,6 @@ def display_current(node): global city_map, city_coord city = node.state city_map.itemconfig(city_coord[city], fill="red") - return - def display_explored(node): ''' @@ -349,8 +385,6 @@ def display_explored(node): global city_map, city_coord city = node.state city_map.itemconfig(city_coord[city], fill="gray") - return - def display_final(cities): ''' @@ -359,8 +393,6 @@ def display_final(cities): global city_map, city_coord for city in cities: city_map.itemconfig(city_coord[city], fill="green") - return - def breadth_first_tree_search(problem): """Search the shallowest nodes in the search tree first.""" @@ -378,6 +410,14 @@ def depth_first_tree_search(problem): frontier=Stack() return tree_search(problem) +# TODO: Check if the solution given by this function is consistent with the original function. +def depth_first_graph_search(problem): + """Search the deepest nodes in the search tree first.""" + global frontier, counter + if counter == -1: + frontier = Stack() + return graph_search(problem) + # TODO: # Remove redundant code. # Make the interchangbility work between various algorithms at each step. @@ -403,6 +443,18 @@ def on_click(): display_final(final_path) next_button.config(state="disabled") counter += 1 + elif "Depth-First Graph Search" == algo.get(): + node = depth_first_graph_search(romania_problem) + if node is not None: + print(node) + final_path = dfgs(romania_problem).solution() + print(final_path) + final_path.append(start.get()) + display_final(final_path) + next_button.config(state="disabled") + counter += 1 + + def reset_map(): global counter, city_coord, city_map, next_button @@ -427,7 +479,7 @@ def main(): goal.set('Bucharest') cities = sorted(romania_map.locations.keys()) algorithm_menu = OptionMenu( - root, algo, "Breadth-First Tree Search", "Depth-First Tree Search") + root, algo, "Breadth-First Tree Search", "Depth-First Tree Search","Depth-First Graph Search") Label(root, text="\n Search Algorithm").pack() algorithm_menu.pack() Label(root, text="\n Start City").pack() pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy